2009-03-27 07:55:32 -06:00
|
|
|
/************************************************************
|
|
|
|
Copyright (c) 1994 by Silicon Graphics Computer Systems, Inc.
|
|
|
|
|
|
|
|
Permission to use, copy, modify, and distribute this
|
|
|
|
software and its documentation for any purpose and without
|
|
|
|
fee is hereby granted, provided that the above copyright
|
|
|
|
notice appear in all copies and that both that copyright
|
|
|
|
notice and this permission notice appear in supporting
|
2009-04-04 10:19:51 -06:00
|
|
|
documentation, and that the name of Silicon Graphics not be
|
|
|
|
used in advertising or publicity pertaining to distribution
|
2009-03-27 07:55:32 -06:00
|
|
|
of the software without specific prior written permission.
|
2009-04-04 10:19:51 -06:00
|
|
|
Silicon Graphics makes no representation about the suitability
|
2009-03-27 07:55:32 -06:00
|
|
|
of this software for any purpose. It is provided "as is"
|
|
|
|
without any express or implied warranty.
|
2009-04-04 10:19:51 -06:00
|
|
|
|
|
|
|
SILICON GRAPHICS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS
|
|
|
|
SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
|
2009-03-27 07:55:32 -06:00
|
|
|
AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL SILICON
|
2009-04-04 10:19:51 -06:00
|
|
|
GRAPHICS BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL
|
|
|
|
DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
|
|
|
|
DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
|
2009-03-27 07:55:32 -06:00
|
|
|
OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH
|
|
|
|
THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
|
|
|
|
|
|
|
********************************************************/
|
|
|
|
|
|
|
|
#include "xkbcomp.h"
|
2009-04-08 08:46:25 -06:00
|
|
|
#include "xkballoc.h"
|
|
|
|
#include "xkbmisc.h"
|
2009-03-27 07:55:32 -06:00
|
|
|
#include "xkbpath.h"
|
|
|
|
#include "keycodes.h"
|
|
|
|
#include "misc.h"
|
|
|
|
#include <X11/keysym.h>
|
|
|
|
#include "parseutils.h"
|
|
|
|
|
|
|
|
/***====================================================================***/
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Open the file given in the include statement and parse it's content.
|
|
|
|
* If the statement defines a specific map to use, this map is returned in
|
|
|
|
* file_rtrn. Otherwise, the default map is returned.
|
|
|
|
*
|
|
|
|
* @param stmt The include statement, specifying the file name to look for.
|
|
|
|
* @param file_type Type of file (XkmKeyNamesIdx, etc.)
|
|
|
|
* @param file_rtrn Returns the key map to be used.
|
|
|
|
* @param merge_rtrn Always returns stmt->merge.
|
|
|
|
*
|
|
|
|
* @return True on success or False otherwise.
|
|
|
|
*/
|
|
|
|
Bool
|
|
|
|
ProcessIncludeFile(IncludeStmt * stmt,
|
|
|
|
unsigned file_type,
|
|
|
|
XkbFile ** file_rtrn, unsigned *merge_rtrn)
|
|
|
|
{
|
|
|
|
FILE *file;
|
|
|
|
XkbFile *rtrn, *mapToUse;
|
|
|
|
char oldFile[1024] = {0};
|
|
|
|
int oldLine = lineNum;
|
|
|
|
|
|
|
|
rtrn = XkbFindFileInCache(stmt->file, file_type, &stmt->path);
|
|
|
|
if (rtrn == NULL)
|
|
|
|
{
|
|
|
|
/* file not in cache, open it, parse it and store it in cache for next
|
|
|
|
time. */
|
|
|
|
file = XkbFindFileInPath(stmt->file, file_type, &stmt->path);
|
|
|
|
if (file == NULL)
|
|
|
|
{
|
2009-03-31 08:21:20 -06:00
|
|
|
ERROR("Can't find file \"%s\" for %s include\n", stmt->file,
|
2009-03-27 07:55:32 -06:00
|
|
|
XkbDirectoryForInclude(file_type));
|
|
|
|
return False;
|
|
|
|
}
|
2012-02-15 05:54:11 -07:00
|
|
|
if (scanFile)
|
|
|
|
strcpy(oldFile, scanFile);
|
|
|
|
else
|
|
|
|
memset(oldFile, 0, sizeof(oldFile));
|
2009-03-27 07:55:32 -06:00
|
|
|
oldLine = lineNum;
|
|
|
|
setScanState(stmt->file, 1);
|
|
|
|
if (debugFlags & 2)
|
2009-03-31 08:21:20 -06:00
|
|
|
INFO("About to parse include file %s\n", stmt->file);
|
2009-03-27 07:55:32 -06:00
|
|
|
/* parse the file */
|
|
|
|
if ((XKBParseFile(file, &rtrn) == 0) || (rtrn == NULL))
|
|
|
|
{
|
|
|
|
setScanState(oldFile, oldLine);
|
2009-03-31 08:21:20 -06:00
|
|
|
ERROR("Error interpreting include file \"%s\"\n", stmt->file);
|
2009-03-27 07:55:32 -06:00
|
|
|
fclose(file);
|
|
|
|
return False;
|
|
|
|
}
|
|
|
|
fclose(file);
|
|
|
|
XkbAddFileToCache(stmt->file, file_type, stmt->path, rtrn);
|
|
|
|
}
|
|
|
|
mapToUse = rtrn;
|
|
|
|
if (stmt->map != NULL)
|
|
|
|
{
|
|
|
|
while ((mapToUse) && ((!uStringEqual(mapToUse->name, stmt->map)) ||
|
|
|
|
(mapToUse->type != file_type)))
|
|
|
|
{
|
|
|
|
mapToUse = (XkbFile *) mapToUse->common.next;
|
|
|
|
}
|
|
|
|
if (!mapToUse)
|
|
|
|
{
|
2009-03-31 08:21:20 -06:00
|
|
|
ERROR("No %s named \"%s\" in the include file \"%s\"\n",
|
2009-03-28 15:06:26 -06:00
|
|
|
XkbcConfigText(file_type), stmt->map, stmt->file);
|
2009-03-27 07:55:32 -06:00
|
|
|
return False;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else if ((rtrn->common.next != NULL) && (warningLevel > 5))
|
|
|
|
{
|
2009-03-31 08:21:20 -06:00
|
|
|
WARN("No map in include statement, but \"%s\" contains several\n",
|
2009-03-27 07:55:32 -06:00
|
|
|
stmt->file);
|
2009-03-31 08:21:20 -06:00
|
|
|
ACTION("Using first defined map, \"%s\"\n", rtrn->name);
|
2009-03-27 07:55:32 -06:00
|
|
|
}
|
|
|
|
setScanState(oldFile, oldLine);
|
|
|
|
if (mapToUse->type != file_type)
|
|
|
|
{
|
2009-03-31 08:21:20 -06:00
|
|
|
ERROR("Include file wrong type (expected %s, got %s)\n",
|
2009-03-28 15:06:26 -06:00
|
|
|
XkbcConfigText(file_type), XkbcConfigText(mapToUse->type));
|
2009-03-31 08:21:20 -06:00
|
|
|
ACTION("Include file \"%s\" ignored\n", stmt->file);
|
2009-03-27 07:55:32 -06:00
|
|
|
return False;
|
|
|
|
}
|
|
|
|
/* FIXME: we have to check recursive includes here (or somewhere) */
|
|
|
|
|
|
|
|
mapToUse->compiled = True;
|
|
|
|
*file_rtrn = mapToUse;
|
|
|
|
*merge_rtrn = stmt->merge;
|
|
|
|
return True;
|
|
|
|
}
|
|
|
|
|
|
|
|
/***====================================================================***/
|
|
|
|
|
|
|
|
int
|
|
|
|
ReportNotArray(const char *type, const char *field, const char *name)
|
|
|
|
{
|
2009-03-31 08:21:20 -06:00
|
|
|
ERROR("The %s %s field is not an array\n", type, field);
|
|
|
|
ACTION("Ignoring illegal assignment in %s\n", name);
|
2009-03-27 07:55:32 -06:00
|
|
|
return False;
|
|
|
|
}
|
|
|
|
|
|
|
|
int
|
2010-06-30 15:20:56 -06:00
|
|
|
ReportShouldBeArray(const char *type, const char *field, const char *name)
|
2009-03-27 07:55:32 -06:00
|
|
|
{
|
2009-03-31 08:21:20 -06:00
|
|
|
ERROR("Missing subscript for %s %s\n", type, field);
|
|
|
|
ACTION("Ignoring illegal assignment in %s\n", name);
|
2009-03-27 07:55:32 -06:00
|
|
|
return False;
|
|
|
|
}
|
|
|
|
|
|
|
|
int
|
|
|
|
ReportBadType(const char *type, const char *field,
|
|
|
|
const char *name, const char *wanted)
|
|
|
|
{
|
2009-03-31 08:21:20 -06:00
|
|
|
ERROR("The %s %s field must be a %s\n", type, field, wanted);
|
|
|
|
ACTION("Ignoring illegal assignment in %s\n", name);
|
2009-03-27 07:55:32 -06:00
|
|
|
return False;
|
|
|
|
}
|
|
|
|
|
|
|
|
int
|
|
|
|
ReportBadField(const char *type, const char *field, const char *name)
|
|
|
|
{
|
2009-03-31 08:21:20 -06:00
|
|
|
ERROR("Unknown %s field %s in %s\n", type, field, name);
|
|
|
|
ACTION("Ignoring assignment to unknown field in %s\n", name);
|
2009-03-27 07:55:32 -06:00
|
|
|
return False;
|
|
|
|
}
|
|
|
|
|
|
|
|
/***====================================================================***/
|
|
|
|
|
|
|
|
Bool
|
|
|
|
UseNewField(unsigned field,
|
|
|
|
CommonInfo * oldDefs, CommonInfo * newDefs, unsigned *pCollide)
|
|
|
|
{
|
|
|
|
Bool useNew;
|
|
|
|
|
|
|
|
useNew = False;
|
|
|
|
if (oldDefs->defined & field)
|
|
|
|
{
|
|
|
|
if (newDefs->defined & field)
|
|
|
|
{
|
|
|
|
if (((oldDefs->fileID == newDefs->fileID)
|
|
|
|
&& (warningLevel > 0)) || (warningLevel > 9))
|
|
|
|
{
|
|
|
|
*pCollide |= field;
|
|
|
|
}
|
|
|
|
if (newDefs->merge != MergeAugment)
|
|
|
|
useNew = True;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else if (newDefs->defined & field)
|
|
|
|
useNew = True;
|
|
|
|
return useNew;
|
|
|
|
}
|
|
|
|
|
2009-03-27 21:13:22 -06:00
|
|
|
char *
|
2009-03-27 07:55:32 -06:00
|
|
|
ClearCommonInfo(CommonInfo * cmn)
|
|
|
|
{
|
|
|
|
if (cmn != NULL)
|
|
|
|
{
|
|
|
|
CommonInfo *this, *next;
|
|
|
|
for (this = cmn; this != NULL; this = next)
|
|
|
|
{
|
|
|
|
next = this->next;
|
2010-06-28 04:58:01 -06:00
|
|
|
free(this);
|
2009-03-27 07:55:32 -06:00
|
|
|
}
|
|
|
|
}
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
2009-03-27 21:13:22 -06:00
|
|
|
char *
|
2009-03-27 07:55:32 -06:00
|
|
|
AddCommonInfo(CommonInfo * old, CommonInfo * new)
|
|
|
|
{
|
|
|
|
CommonInfo *first;
|
|
|
|
|
|
|
|
first = old;
|
|
|
|
while (old && old->next)
|
|
|
|
{
|
|
|
|
old = old->next;
|
|
|
|
}
|
|
|
|
new->next = NULL;
|
|
|
|
if (old)
|
|
|
|
{
|
|
|
|
old->next = new;
|
2009-03-27 21:13:22 -06:00
|
|
|
return (char *) first;
|
2009-03-27 07:55:32 -06:00
|
|
|
}
|
2009-03-27 21:13:22 -06:00
|
|
|
return (char *) new;
|
2009-03-27 07:55:32 -06:00
|
|
|
}
|
|
|
|
|
|
|
|
/***====================================================================***/
|
|
|
|
|
|
|
|
typedef struct _KeyNameDesc
|
|
|
|
{
|
2010-06-28 04:50:12 -06:00
|
|
|
uint32_t level1;
|
|
|
|
uint32_t level2;
|
2009-03-27 07:55:32 -06:00
|
|
|
char name[5];
|
|
|
|
Bool used;
|
|
|
|
} KeyNameDesc;
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Find the key with the given name and return its keycode in kc_rtrn.
|
|
|
|
*
|
|
|
|
* @param name The 4-letter name of the key as a long.
|
|
|
|
* @param kc_rtrn Set to the keycode if the key was found, otherwise 0.
|
|
|
|
* @param use_aliases True if the key aliases should be searched too.
|
|
|
|
* @param create If True and the key is not found, it is added to the
|
|
|
|
* xkb->names at the first free keycode.
|
|
|
|
* @param start_from Keycode to start searching from.
|
|
|
|
*
|
|
|
|
* @return True if found, False otherwise.
|
|
|
|
*/
|
|
|
|
Bool
|
2010-07-01 12:35:24 -06:00
|
|
|
FindNamedKey(struct xkb_desc * xkb,
|
2009-03-27 07:55:32 -06:00
|
|
|
unsigned long name,
|
2012-02-15 07:34:08 -07:00
|
|
|
xkb_keycode_t *kc_rtrn,
|
2009-03-27 07:55:32 -06:00
|
|
|
Bool use_aliases, Bool create, int start_from)
|
|
|
|
{
|
|
|
|
register unsigned n;
|
|
|
|
|
|
|
|
if (start_from < xkb->min_key_code)
|
|
|
|
{
|
|
|
|
start_from = xkb->min_key_code;
|
|
|
|
}
|
|
|
|
else if (start_from > xkb->max_key_code)
|
|
|
|
{
|
|
|
|
return False;
|
|
|
|
}
|
|
|
|
|
|
|
|
*kc_rtrn = 0; /* some callers rely on this */
|
|
|
|
if (xkb && xkb->names && xkb->names->keys)
|
|
|
|
{
|
|
|
|
for (n = start_from; n <= xkb->max_key_code; n++)
|
|
|
|
{
|
|
|
|
unsigned long tmp;
|
|
|
|
tmp = KeyNameToLong(xkb->names->keys[n].name);
|
|
|
|
if (tmp == name)
|
|
|
|
{
|
|
|
|
*kc_rtrn = n;
|
|
|
|
return True;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (use_aliases)
|
|
|
|
{
|
|
|
|
unsigned long new_name;
|
|
|
|
if (FindKeyNameForAlias(xkb, name, &new_name))
|
|
|
|
return FindNamedKey(xkb, new_name, kc_rtrn, False, create, 0);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (create)
|
|
|
|
{
|
|
|
|
if ((!xkb->names) || (!xkb->names->keys))
|
|
|
|
{
|
2009-03-28 12:45:05 -06:00
|
|
|
if (XkbcAllocNames(xkb, XkbKeyNamesMask, 0, 0) != Success)
|
2009-03-27 07:55:32 -06:00
|
|
|
{
|
|
|
|
if (warningLevel > 0)
|
|
|
|
{
|
|
|
|
WARN("Couldn't allocate key names in FindNamedKey\n");
|
2009-03-31 08:21:20 -06:00
|
|
|
ACTION("Key \"%s\" not automatically created\n",
|
2009-03-28 16:24:06 -06:00
|
|
|
longText(name));
|
2009-03-27 07:55:32 -06:00
|
|
|
}
|
|
|
|
return False;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
/* Find first unused keycode and store our key here */
|
|
|
|
for (n = xkb->min_key_code; n <= xkb->max_key_code; n++)
|
|
|
|
{
|
|
|
|
if (xkb->names->keys[n].name[0] == '\0')
|
|
|
|
{
|
|
|
|
char buf[XkbKeyNameLength + 1];
|
|
|
|
LongToKeyName(name, buf);
|
|
|
|
memcpy(xkb->names->keys[n].name, buf, XkbKeyNameLength);
|
|
|
|
*kc_rtrn = n;
|
|
|
|
return True;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return False;
|
|
|
|
}
|
|
|
|
|
|
|
|
Bool
|
2010-07-01 12:35:24 -06:00
|
|
|
FindKeyNameForAlias(struct xkb_desc * xkb, unsigned long lname,
|
2009-03-27 07:55:32 -06:00
|
|
|
unsigned long *real_name)
|
|
|
|
{
|
|
|
|
register int i;
|
|
|
|
char name[XkbKeyNameLength + 1];
|
|
|
|
|
|
|
|
if (xkb && xkb->geom && xkb->geom->key_aliases)
|
|
|
|
{
|
2010-07-01 12:35:24 -06:00
|
|
|
struct xkb_key_alias * a;
|
2009-03-27 07:55:32 -06:00
|
|
|
a = xkb->geom->key_aliases;
|
|
|
|
LongToKeyName(lname, name);
|
|
|
|
name[XkbKeyNameLength] = '\0';
|
|
|
|
for (i = 0; i < xkb->geom->num_key_aliases; i++, a++)
|
|
|
|
{
|
|
|
|
if (strncmp(name, a->alias, XkbKeyNameLength) == 0)
|
|
|
|
{
|
|
|
|
*real_name = KeyNameToLong(a->real);
|
|
|
|
return True;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (xkb && xkb->names && xkb->names->key_aliases)
|
|
|
|
{
|
2010-07-01 12:35:24 -06:00
|
|
|
struct xkb_key_alias * a;
|
2009-03-27 07:55:32 -06:00
|
|
|
a = xkb->names->key_aliases;
|
|
|
|
LongToKeyName(lname, name);
|
|
|
|
name[XkbKeyNameLength] = '\0';
|
|
|
|
for (i = 0; i < xkb->names->num_key_aliases; i++, a++)
|
|
|
|
{
|
|
|
|
if (strncmp(name, a->alias, XkbKeyNameLength) == 0)
|
|
|
|
{
|
|
|
|
*real_name = KeyNameToLong(a->real);
|
|
|
|
return True;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return False;
|
|
|
|
}
|