summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKaleb Keithley <kaleb@freedesktop.org>2003-11-14 15:54:54 +0000
committerKaleb Keithley <kaleb@freedesktop.org>2003-11-14 15:54:54 +0000
commit2af3aabf0e7eb1514d39b29a6b58fcd0d4de41d1 (patch)
tree93f90d2a90d9163a9b8930ae643dcabae310350f
downloadxorg-app-xkbcomp-2af3aabf0e7eb1514d39b29a6b58fcd0d4de41d1.tar.gz
R6.6 is the Xorg base-lineXORG-MAIN
-rw-r--r--action.c1467
-rw-r--r--action.h94
-rw-r--r--alias.c302
-rw-r--r--alias.h68
-rw-r--r--compat.c913
-rw-r--r--expr.c1106
-rw-r--r--expr.h234
-rw-r--r--geometry.c3782
-rw-r--r--indicators.c535
-rw-r--r--indicators.h106
-rw-r--r--keycodes.c877
-rw-r--r--keycodes.h47
-rw-r--r--keymap.c174
-rw-r--r--keytypes.c1353
-rw-r--r--listing.c500
-rw-r--r--misc.c605
-rw-r--r--misc.h157
-rw-r--r--parseutils.c966
-rw-r--r--parseutils.h319
-rw-r--r--symbols.c1920
-rw-r--r--tokens.h100
-rw-r--r--utils.c530
-rw-r--r--utils.h453
-rw-r--r--vmod.c271
-rw-r--r--vmod.h101
-rw-r--r--xkbcomp.c932
-rw-r--r--xkbcomp.h408
-rw-r--r--xkbcomp.man97
-rw-r--r--xkbparse.y806
-rw-r--r--xkbpath.c359
-rw-r--r--xkbpath.h89
-rw-r--r--xkbscan.c496
32 files changed, 20167 insertions, 0 deletions
diff --git a/action.c b/action.c
new file mode 100644
index 0000000..bc2b281
--- /dev/null
+++ b/action.c
@@ -0,0 +1,1467 @@
+/* $Xorg: action.c,v 1.3 2000/08/17 19:54:30 cpqbld Exp $ */
+/************************************************************
+ 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
+ documentation, and that the name of Silicon Graphics not be
+ used in advertising or publicity pertaining to distribution
+ of the software without specific prior written permission.
+ Silicon Graphics makes no representation about the suitability
+ of this software for any purpose. It is provided "as is"
+ without any express or implied warranty.
+
+ SILICON GRAPHICS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS
+ SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+ AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL SILICON
+ 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
+ OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH
+ THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+ ********************************************************/
+
+#include "xkbcomp.h"
+#include "tokens.h"
+#include "expr.h"
+
+#include "keycodes.h"
+#include "vmod.h"
+#include "action.h"
+#include "misc.h"
+
+static Bool actionsInitialized;
+static ExprDef constTrue;
+static ExprDef constFalse;
+
+/***====================================================================***/
+
+static Bool
+#if NeedFunctionPrototypes
+stringToAction(char *str,unsigned *type_rtrn)
+#else
+stringToAction(str,type_rtrn)
+ char * str;
+ unsigned * type_rtrn;
+#endif
+{
+ if (str==NULL)
+ return False;
+
+ if (uStrCaseCmp(str,"noaction")==0) *type_rtrn= XkbSA_NoAction;
+ else if (uStrCaseCmp(str,"setmods")==0) *type_rtrn= XkbSA_SetMods;
+ else if (uStrCaseCmp(str,"latchmods")==0) *type_rtrn= XkbSA_LatchMods;
+ else if (uStrCaseCmp(str,"lockmods")==0) *type_rtrn= XkbSA_LockMods;
+ else if (uStrCaseCmp(str,"setgroup")==0) *type_rtrn= XkbSA_SetGroup;
+ else if (uStrCaseCmp(str,"latchgroup")==0) *type_rtrn= XkbSA_LatchGroup;
+ else if (uStrCaseCmp(str,"lockgroup")==0) *type_rtrn= XkbSA_LockGroup;
+ else if (uStrCaseCmp(str,"moveptr")==0) *type_rtrn= XkbSA_MovePtr;
+ else if (uStrCaseCmp(str,"movepointer")==0) *type_rtrn= XkbSA_MovePtr;
+ else if (uStrCaseCmp(str,"ptrbtn")==0) *type_rtrn= XkbSA_PtrBtn;
+ else if (uStrCaseCmp(str,"pointerbutton")==0)
+ *type_rtrn= XkbSA_PtrBtn;
+ else if (uStrCaseCmp(str,"lockptrbtn")==0) *type_rtrn= XkbSA_LockPtrBtn;
+ else if (uStrCaseCmp(str,"lockpointerbutton")==0)
+ *type_rtrn= XkbSA_LockPtrBtn;
+ else if (uStrCaseCmp(str,"lockptrbutton")==0)
+ *type_rtrn= XkbSA_LockPtrBtn;
+ else if (uStrCaseCmp(str,"lockpointerbtn")==0)
+ *type_rtrn= XkbSA_LockPtrBtn;
+ else if (uStrCaseCmp(str,"setptrdflt")==0) *type_rtrn= XkbSA_SetPtrDflt;
+ else if (uStrCaseCmp(str,"setpointerdefault")==0)
+ *type_rtrn= XkbSA_SetPtrDflt;
+ else if (uStrCaseCmp(str,"isolock")==0) *type_rtrn= XkbSA_ISOLock;
+ else if (uStrCaseCmp(str,"terminate")==0) *type_rtrn= XkbSA_Terminate;
+ else if (uStrCaseCmp(str,"terminateserver")==0)
+ *type_rtrn= XkbSA_Terminate;
+ else if (uStrCaseCmp(str,"switchscreen")==0)*type_rtrn= XkbSA_SwitchScreen;
+ else if (uStrCaseCmp(str,"setcontrols")==0) *type_rtrn= XkbSA_SetControls;
+ else if (uStrCaseCmp(str,"lockcontrols")==0)*type_rtrn= XkbSA_LockControls;
+ else if (uStrCaseCmp(str,"actionmessage")==0)*type_rtrn= XkbSA_ActionMessage;
+ else if (uStrCaseCmp(str,"messageaction")==0)*type_rtrn= XkbSA_ActionMessage;
+ else if (uStrCaseCmp(str,"message")==0) *type_rtrn= XkbSA_ActionMessage;
+ else if (uStrCaseCmp(str,"redirect")==0) *type_rtrn= XkbSA_RedirectKey;
+ else if (uStrCaseCmp(str,"redirectkey")==0) *type_rtrn= XkbSA_RedirectKey;
+ else if (uStrCaseCmp(str,"devbtn")==0) *type_rtrn= XkbSA_DeviceBtn;
+ else if (uStrCaseCmp(str,"devicebtn")==0) *type_rtrn= XkbSA_DeviceBtn;
+ else if (uStrCaseCmp(str,"devbutton")==0) *type_rtrn= XkbSA_DeviceBtn;
+ else if (uStrCaseCmp(str,"devicebutton")==0)*type_rtrn= XkbSA_DeviceBtn;
+ else if (uStrCaseCmp(str,"lockdevbtn")==0) *type_rtrn= XkbSA_DeviceBtn;
+ else if (uStrCaseCmp(str,"lockdevicebtn")==0)
+ *type_rtrn= XkbSA_LockDeviceBtn;
+ else if (uStrCaseCmp(str,"lockdevbutton")==0)
+ *type_rtrn= XkbSA_LockDeviceBtn;
+ else if (uStrCaseCmp(str,"lockdevicebutton")==0)
+ *type_rtrn= XkbSA_LockDeviceBtn;
+ else if (uStrCaseCmp(str,"devval")==0) *type_rtrn=XkbSA_DeviceValuator;
+ else if (uStrCaseCmp(str,"deviceval")==0) *type_rtrn=XkbSA_DeviceValuator;
+ else if (uStrCaseCmp(str,"devvaluator")==0) *type_rtrn=XkbSA_DeviceValuator;
+ else if (uStrCaseCmp(str,"devicevaluator")==0)
+ *type_rtrn=XkbSA_DeviceValuator;
+ else if (uStrCaseCmp(str,"private")==0) *type_rtrn= PrivateAction;
+ else return False;
+ return True;
+}
+
+static Bool
+#if NeedFunctionPrototypes
+stringToField(char *str,unsigned *field_rtrn)
+#else
+stringToField(str,field_rtrn)
+ char * str;
+ unsigned * field_rtrn;
+#endif
+{
+
+ if (str==NULL)
+ return False;
+
+ if (uStrCaseCmp(str,"clearlocks")==0) *field_rtrn= F_ClearLocks;
+ else if (uStrCaseCmp(str,"latchtolock")==0) *field_rtrn= F_LatchToLock;
+ else if (uStrCaseCmp(str,"genkeyevent")==0) *field_rtrn= F_GenKeyEvent;
+ else if (uStrCaseCmp(str,"generatekeyevent")==0)
+ *field_rtrn= F_GenKeyEvent;
+ else if (uStrCaseCmp(str,"report")==0) *field_rtrn= F_Report;
+ else if (uStrCaseCmp(str,"default")==0) *field_rtrn= F_Default;
+ else if (uStrCaseCmp(str,"affect")==0) *field_rtrn= F_Affect;
+ else if (uStrCaseCmp(str,"increment")==0) *field_rtrn= F_Increment;
+ else if (uStrCaseCmp(str,"mods")==0) *field_rtrn= F_Modifiers;
+ else if (uStrCaseCmp(str,"modifiers")==0) *field_rtrn= F_Modifiers;
+ else if (uStrCaseCmp(str,"group")==0) *field_rtrn= F_Group;
+ else if (uStrCaseCmp(str,"x")==0) *field_rtrn= F_X;
+ else if (uStrCaseCmp(str,"y")==0) *field_rtrn= F_Y;
+ else if (uStrCaseCmp(str,"accel")==0) *field_rtrn= F_Accel;
+ else if (uStrCaseCmp(str,"accelerate")==0) *field_rtrn= F_Accel;
+ else if (uStrCaseCmp(str,"repeat")==0) *field_rtrn= F_Accel;
+ else if (uStrCaseCmp(str,"button")==0) *field_rtrn= F_Button;
+ else if (uStrCaseCmp(str,"value")==0) *field_rtrn= F_Value;
+ else if (uStrCaseCmp(str,"controls")==0) *field_rtrn= F_Controls;
+ else if (uStrCaseCmp(str,"ctrls")==0) *field_rtrn= F_Controls;
+ else if (uStrCaseCmp(str,"type")==0) *field_rtrn= F_Type;
+ else if (uStrCaseCmp(str,"count")==0) *field_rtrn= F_Count;
+ else if (uStrCaseCmp(str,"screen")==0) *field_rtrn= F_Screen;
+ else if (uStrCaseCmp(str,"same")==0) *field_rtrn= F_Same;
+ else if (uStrCaseCmp(str,"sameserver")==0) *field_rtrn= F_Same;
+ else if (uStrCaseCmp(str,"data")==0) *field_rtrn= F_Data;
+ else if (uStrCaseCmp(str,"device")==0) *field_rtrn= F_Device;
+ else if (uStrCaseCmp(str,"dev")==0) *field_rtrn= F_Device;
+ else if (uStrCaseCmp(str,"key")==0) *field_rtrn= F_Keycode;
+ else if (uStrCaseCmp(str,"keycode")==0) *field_rtrn= F_Keycode;
+ else if (uStrCaseCmp(str,"kc")==0) *field_rtrn= F_Keycode;
+ else if (uStrCaseCmp(str,"clearmods")==0) *field_rtrn= F_ModsToClear;
+ else if (uStrCaseCmp(str,"clearmodifiers")==0) *field_rtrn= F_ModsToClear;
+ else return False;
+ return True;
+}
+
+static char *
+#if NeedFunctionPrototypes
+fieldText(unsigned field)
+#else
+fieldText(field)
+ unsigned field;
+#endif
+{
+static char buf[32];
+
+ switch (field) {
+ case F_ClearLocks: strcpy(buf,"clearLocks"); break;
+ case F_LatchToLock: strcpy(buf,"latchToLock"); break;
+ case F_GenKeyEvent: strcpy(buf,"genKeyEvent"); break;
+ case F_Report: strcpy(buf,"report"); break;
+ case F_Default: strcpy(buf,"default"); break;
+ case F_Affect: strcpy(buf,"affect"); break;
+ case F_Increment: strcpy(buf,"increment"); break;
+ case F_Modifiers: strcpy(buf,"modifiers"); break;
+ case F_Group: strcpy(buf,"group"); break;
+ case F_X: strcpy(buf,"x"); break;
+ case F_Y: strcpy(buf,"y"); break;
+ case F_Accel: strcpy(buf,"accel"); break;
+ case F_Button: strcpy(buf,"button"); break;
+ case F_Value: strcpy(buf,"value"); break;
+ case F_Controls: strcpy(buf,"controls"); break;
+ case F_Type: strcpy(buf,"type"); break;
+ case F_Count: strcpy(buf,"count"); break;
+ case F_Screen: strcpy(buf,"screen"); break;
+ case F_Same: strcpy(buf,"sameServer"); break;
+ case F_Data: strcpy(buf,"data"); break;
+ case F_Device: strcpy(buf,"device"); break;
+ case F_Keycode: strcpy(buf,"keycode"); break;
+ case F_ModsToClear: strcpy(buf,"clearmods"); break;
+ default: strcpy(buf,"unknown"); break;
+ }
+ return buf;
+}
+
+/***====================================================================***/
+
+static Bool
+#if NeedFunctionPrototypes
+ReportMismatch(unsigned action,unsigned field,char *type)
+#else
+ReportMismatch(action,field,type)
+ unsigned action;
+ unsigned field;
+ char * type;
+#endif
+{
+ ERROR2("Value of %s field must be of type %s\n",fieldText(field),type);
+ ACTION1("Action %s definition ignored\n",
+ XkbActionTypeText(action,XkbMessage));
+ return False;
+}
+
+static Bool
+#if NeedFunctionPrototypes
+ReportIllegal(unsigned action,unsigned field)
+#else
+ReportIllegal(action,field)
+ unsigned action;
+ unsigned field;
+#endif
+{
+ ERROR2("Field %s is not defined for an action of type %s\n",
+ fieldText(field),
+ XkbActionTypeText(action,XkbMessage));
+ ACTION("Action definition ignored\n");
+ return False;
+}
+
+static Bool
+#if NeedFunctionPrototypes
+ReportActionNotArray(unsigned action,unsigned field)
+#else
+ReportActionNotArray(action,field)
+ unsigned action;
+ unsigned field;
+#endif
+{
+ ERROR2("The %s field in the %s action is not an array\n",
+ fieldText(field),
+ XkbActionTypeText(action,XkbMessage));
+ ACTION("Action definition ignored\n");
+ return False;
+}
+
+static Bool
+#if NeedFunctionPrototypes
+ReportNotFound(unsigned action,unsigned field,char *what,char *bad)
+#else
+ReportNotFound(action,field,what,bad)
+ unsigned action;
+ unsigned field;
+ char * what;
+ char * bad;
+#endif
+{
+ ERROR2("%s named %s not found\n",what,bad);
+ ACTION2("Ignoring the %s field of an %s action\n",fieldText(field),
+ XkbActionTypeText(action,XkbMessage));
+ return False;
+}
+
+static Bool
+#if NeedFunctionPrototypes
+HandleNoAction( XkbDescPtr xkb,
+ XkbAnyAction * action,
+ unsigned field,
+ ExprDef * array_ndx,
+ ExprDef * value)
+#else
+HandleNoAction(xkb,action,field,array_ndx,value)
+ XkbDescPtr xkb;
+ XkbAnyAction * action;
+ unsigned field;
+ ExprDef * array_ndx;
+ ExprDef * value;
+#endif
+{
+ return ReportIllegal(action->type,field);
+}
+
+static Bool
+#if NeedFunctionPrototypes
+CheckLatchLockFlags( unsigned action,
+ unsigned field,
+ ExprDef * value,
+ unsigned * flags_inout)
+#else
+CheckLatchLockFlags(action,field,value,flags_inout)
+ unsigned action;
+ unsigned field;
+ ExprDef * value;
+ unsigned * flags_inout;
+#endif
+{
+unsigned tmp;
+ExprResult result;
+
+ if (field==F_ClearLocks) tmp= XkbSA_ClearLocks;
+ else if (field==F_LatchToLock) tmp= XkbSA_LatchToLock;
+ else return False; /* WSGO! */
+ if (!ExprResolveBoolean(value,&result,NULL,NULL))
+ return ReportMismatch(action,field,"boolean");
+ if (result.uval) *flags_inout|= tmp;
+ else *flags_inout&= ~tmp;
+ return True;
+}
+
+static Bool
+#if NeedFunctionPrototypes
+CheckModifierField( XkbDescPtr xkb,
+ unsigned action,
+ ExprDef * value,
+ unsigned * flags_inout,
+ unsigned * mods_rtrn)
+#else
+CheckModifierField(xkb,action,value,flags_inout,mods_rtrn)
+ XkbDescPtr xkb;
+ unsigned action;
+ ExprDef * value;
+ unsigned * flags_inout;
+ unsigned * mods_rtrn;
+#endif
+{
+ExprResult rtrn;
+
+ if (value->op==ExprIdent) {
+ register char *valStr;
+ valStr= XkbAtomGetString(NULL,value->value.str);
+ if (valStr&&((uStrCaseCmp(valStr,"usemodmapmods")==0)||
+ (uStrCaseCmp(valStr,"modmapmods")==0))) {
+
+ *mods_rtrn= 0;
+ *flags_inout|= XkbSA_UseModMapMods;
+ return True;
+ }
+ }
+ if (!ExprResolveModMask(value,&rtrn,LookupVModMask,(XPointer)xkb))
+ return ReportMismatch(action,F_Modifiers,"modifier mask");
+ *mods_rtrn= rtrn.uval;
+ *flags_inout&= ~XkbSA_UseModMapMods;
+ return True;
+}
+
+static Bool
+#if NeedFunctionPrototypes
+HandleSetLatchMods( XkbDescPtr xkb,
+ XkbAnyAction * action,
+ unsigned field,
+ ExprDef * array_ndx,
+ ExprDef * value)
+#else
+HandleSetLatchMods(xkb,action,field,array_ndx,value)
+ XkbDescPtr xkb;
+ XkbAnyAction * action;
+ unsigned field;
+ ExprDef * array_ndx;
+ ExprDef * value;
+#endif
+{
+XkbModAction * act;
+unsigned rtrn;
+unsigned t1,t2;
+
+ act= (XkbModAction *)action;
+ if (array_ndx!=NULL) {
+ switch (field) {
+ case F_ClearLocks: case F_LatchToLock:
+ case F_Modifiers:
+ return ReportActionNotArray(action->type,field);
+ }
+ }
+ switch (field) {
+ case F_ClearLocks:
+ case F_LatchToLock:
+ rtrn= act->flags;
+ if (CheckLatchLockFlags(action->type,field,value,&rtrn)) {
+ act->flags= rtrn;
+ return True;
+ }
+ return False;
+ case F_Modifiers:
+ t1= act->flags;
+ if (CheckModifierField(xkb,action->type,value,&t1,&t2)) {
+ act->flags= t1;
+ act->real_mods= act->mask= (t2&0xff);
+ t2= (t2>>8)&0xffff;
+ XkbSetModActionVMods(act,t2);
+ return True;
+ }
+ return False;
+ }
+ return ReportIllegal(action->type,field);
+}
+
+static Bool
+#if NeedFunctionPrototypes
+HandleLockMods( XkbDescPtr xkb,
+ XkbAnyAction * action,
+ unsigned field,
+ ExprDef * array_ndx,
+ ExprDef * value)
+#else
+HandleLockMods(xkb,action,field,array_ndx,value)
+ XkbDescPtr xkb;
+ XkbAnyAction * action;
+ unsigned field;
+ ExprDef * array_ndx;
+ ExprDef * value;
+#endif
+{
+XkbModAction * act;
+unsigned t1,t2;
+
+ act= (XkbModAction *)action;
+ if ((array_ndx!=NULL)&&(field==F_Modifiers))
+ return ReportActionNotArray(action->type,field);
+ switch (field) {
+ case F_Modifiers:
+ t1= act->flags;
+ if (CheckModifierField(xkb,action->type,value,&t1,&t2)) {
+ act->flags= t1;
+ act->real_mods= act->mask= (t2&0xff);
+ t2= (t2>>8)&0xffff;
+ XkbSetModActionVMods(act,t2);
+ return True;
+ }
+ return False;
+ }
+ return ReportIllegal(action->type,field);
+}
+
+static LookupEntry groupNames[] = {
+ { "group1", 1 },
+ { "group2", 2 },
+ { "group3", 3 },
+ { "group4", 4 },
+ { "group5", 5 },
+ { "group6", 6 },
+ { "group7", 7 },
+ { "group8", 8 },
+ { NULL, 0 },
+};
+
+static Bool
+#if NeedFunctionPrototypes
+CheckGroupField( unsigned action,
+ ExprDef * value,
+ unsigned * flags_inout,
+ int * grp_rtrn)
+#else
+CheckGroupField(action,value,flags_inout,grp_rtrn)
+ unsigned action;
+ ExprDef * value;
+ unsigned * flags_inout;
+ int * grp_rtrn;
+#endif
+{
+ExprDef * spec;
+ExprResult rtrn;
+
+ if ((value->op==OpNegate)||(value->op==OpUnaryPlus)) {
+ *flags_inout&= ~XkbSA_GroupAbsolute;
+ spec= value->value.child;
+ }
+ else {
+ *flags_inout|= XkbSA_GroupAbsolute;
+ spec= value;
+ }
+
+ if (!ExprResolveInteger(spec,&rtrn,SimpleLookup,(XPointer)groupNames))
+ return ReportMismatch(action,F_Group,"integer (range 1..8)");
+ if ((rtrn.ival<1)||(rtrn.ival>XkbNumKbdGroups)) {
+ ERROR2("Illegal group %d (must be in the range 1..%d)\n",rtrn.ival,
+ XkbNumKbdGroups);
+ ACTION1("Action %s definition ignored\n",
+ XkbActionTypeText(action,XkbMessage));
+ return False;
+ }
+ if (value->op==OpNegate) *grp_rtrn= -rtrn.ival;
+ else if (value->op==OpUnaryPlus) *grp_rtrn= rtrn.ival;
+ else *grp_rtrn= rtrn.ival-1;
+ return True;
+}
+
+static Bool
+#if NeedFunctionPrototypes
+HandleSetLatchGroup( XkbDescPtr xkb,
+ XkbAnyAction * action,
+ unsigned field,
+ ExprDef * array_ndx,
+ ExprDef * value)
+#else
+HandleSetLatchGroup(xkb,action,field,array_ndx,value)
+ XkbDescPtr xkb;
+ XkbAnyAction * action;
+ unsigned field;
+ ExprDef * array_ndx;
+ ExprDef * value;
+#endif
+{
+XkbGroupAction * act;
+unsigned rtrn;
+unsigned t1;
+int t2;
+
+ act= (XkbGroupAction *)action;
+ if (array_ndx!=NULL) {
+ switch (field) {
+ case F_ClearLocks: case F_LatchToLock:
+ case F_Group:
+ return ReportActionNotArray(action->type,field);
+ }
+ }
+ switch (field) {
+ case F_ClearLocks:
+ case F_LatchToLock:
+ rtrn= act->flags;
+ if (CheckLatchLockFlags(action->type,field,value,&rtrn)) {
+ act->flags= rtrn;
+ return True;
+ }
+ return False;
+ case F_Group:
+ t1= act->flags;
+ if (CheckGroupField(action->type,value,&t1,&t2)) {
+ act->flags= t1;
+ XkbSASetGroup(act,t2);
+ return True;
+ }
+ return False;
+ }
+ return ReportIllegal(action->type,field);
+}
+
+static Bool
+#if NeedFunctionPrototypes
+HandleLockGroup( XkbDescPtr xkb,
+ XkbAnyAction * action,
+ unsigned field,
+ ExprDef * array_ndx,
+ ExprDef * value)
+#else
+HandleLockGroup(xkb,action,field,array_ndx,value)
+ XkbDescPtr xkb;
+ XkbAnyAction * action;
+ unsigned field;
+ ExprDef * array_ndx;
+ ExprDef * value;
+#endif
+{
+XkbGroupAction * act;
+unsigned t1;
+int t2;
+
+ act= (XkbGroupAction *)action;
+ if ((array_ndx!=NULL) && (field==F_Group))
+ return ReportActionNotArray(action->type,field);
+ if (field==F_Group) {
+ t1= act->flags;
+ if (CheckGroupField(action->type,value,&t1,&t2)) {
+ act->flags= t1;
+ XkbSASetGroup(act,t2);
+ return True;
+ }
+ return False;
+ }
+ return ReportIllegal(action->type,field);
+}
+
+static Bool
+#if NeedFunctionPrototypes
+HandleMovePtr( XkbDescPtr xkb,
+ XkbAnyAction * action,
+ unsigned field,
+ ExprDef * array_ndx,
+ ExprDef * value)
+#else
+HandleMovePtr(xkb,action,field,array_ndx,value)
+ XkbDescPtr xkb;
+ XkbAnyAction * action;
+ unsigned field;
+ ExprDef * array_ndx;
+ ExprDef * value;
+#endif
+{
+ExprResult rtrn;
+XkbPtrAction * act;
+Bool absolute;
+
+ act= (XkbPtrAction *)action;
+ if ((array_ndx!=NULL)&&((field==F_X)||(field==F_Y)))
+ return ReportActionNotArray(action->type,field);
+
+ if ((field==F_X)||(field==F_Y)) {
+ if ((value->op==OpNegate)||(value->op==OpUnaryPlus))
+ absolute= False;
+ else absolute= True;
+ if (!ExprResolveInteger(value,&rtrn,NULL,NULL))
+ return ReportMismatch(action->type,field,"integer");
+ if (field==F_X) {
+ if (absolute)
+ act->flags|= XkbSA_MoveAbsoluteX;
+ XkbSetPtrActionX(act,rtrn.ival);
+ }
+ else {
+ if (absolute)
+ act->flags|= XkbSA_MoveAbsoluteY;
+ XkbSetPtrActionY(act,rtrn.ival);
+ }
+ return True;
+ }
+ else if (field==F_Accel) {
+ if (!ExprResolveBoolean(value,&rtrn,NULL,NULL))
+ return ReportMismatch(action->type,field,"boolean");
+ if (rtrn.uval) act->flags&= ~XkbSA_NoAcceleration;
+ else act->flags|= XkbSA_NoAcceleration;
+ }
+ return ReportIllegal(action->type,field);
+}
+
+static LookupEntry btnNames[] = {
+ { "button1", 1 },
+ { "button2", 2 },
+ { "button3", 3 },
+ { "button4", 4 },
+ { "button5", 5 },
+ { "default", 0 },
+ { NULL, 0 }
+};
+
+static LookupEntry lockWhich[] = {
+ { "both", 0 },
+ { "lock", XkbSA_LockNoUnlock },
+ { "neither", (XkbSA_LockNoLock|XkbSA_LockNoUnlock) },
+ { "unlock", XkbSA_LockNoLock },
+ { NULL, 0 }
+};
+
+static Bool
+#if NeedFunctionPrototypes
+HandlePtrBtn( XkbDescPtr xkb,
+ XkbAnyAction * action,
+ unsigned field,
+ ExprDef * array_ndx,
+ ExprDef * value)
+#else
+HandlePtrBtn(xkb,action,field,array_ndx,value)
+ XkbDescPtr xkb;
+ XkbAnyAction * action;
+ unsigned field;
+ ExprDef * array_ndx;
+ ExprDef * value;
+#endif
+{
+ExprResult rtrn;
+XkbPtrBtnAction * act;
+
+ act= (XkbPtrBtnAction *)action;
+ if (field==F_Button) {
+ if (array_ndx!=NULL)
+ return ReportActionNotArray(action->type,field);
+ if (!ExprResolveInteger(value,&rtrn,SimpleLookup,(XPointer)btnNames))
+ return ReportMismatch(action->type,field,"integer (range 1..5)");
+ if ((rtrn.ival<0)||(rtrn.ival>5)) {
+ ERROR("Button must specify default or be in the range 1..5\n");
+ ACTION1("Illegal button value %d ignored\n",rtrn.ival);
+ return False;
+ }
+ act->button= rtrn.ival;
+ return True;
+ }
+ else if ((action->type==XkbSA_LockPtrBtn)&&(field==F_Affect)) {
+ if (array_ndx!=NULL)
+ return ReportActionNotArray(action->type,field);
+ if (!ExprResolveEnum(value,&rtrn,lockWhich))
+ return ReportMismatch(action->type,field,"lock or unlock");
+ act->flags&= ~(XkbSA_LockNoLock|XkbSA_LockNoUnlock);
+ act->flags|= rtrn.ival;
+ return True;
+ }
+ else if (field==F_Count) {
+ if (array_ndx!=NULL)
+ return ReportActionNotArray(action->type,field);
+ if (!ExprResolveInteger(value,&rtrn,SimpleLookup,(XPointer)btnNames))
+ return ReportMismatch(action->type,field,"integer");
+ if ((rtrn.ival<0)||(rtrn.ival>255)) {
+ ERROR("The count field must have a value in the range 0..255\n");
+ ACTION1("Illegal count %d ignored\n",rtrn.ival);
+ return False;
+ }
+ act->count= rtrn.ival;
+ return True;
+ }
+ return ReportIllegal(action->type,field);
+}
+
+static LookupEntry ptrDflts[] = {
+ { "dfltbtn", XkbSA_AffectDfltBtn },
+ { "defaultbutton", XkbSA_AffectDfltBtn },
+ { "button", XkbSA_AffectDfltBtn },
+ { NULL, 0 }
+};
+
+static Bool
+#if NeedFunctionPrototypes
+HandleSetPtrDflt( XkbDescPtr xkb,
+ XkbAnyAction * action,
+ unsigned field,
+ ExprDef * array_ndx,
+ ExprDef * value)
+#else
+HandleSetPtrDflt(xkb,action,field,array_ndx,value)
+ XkbDescPtr xkb;
+ XkbAnyAction * action;
+ unsigned field;
+ ExprDef * array_ndx;
+ ExprDef * value;
+#endif
+{
+ExprResult rtrn;
+XkbPtrDfltAction * act;
+
+ act= (XkbPtrDfltAction *)action;
+ if (field==F_Affect) {
+ if (array_ndx!=NULL)
+ return ReportActionNotArray(action->type,field);
+ if (!ExprResolveEnum(value,&rtrn,ptrDflts))
+ return ReportMismatch(action->type,field,"pointer component");
+ act->affect= rtrn.uval;
+ return True;
+ }
+ else if ((field==F_Button)||(field==F_Value)) {
+ ExprDef *btn;
+ if (array_ndx!=NULL)
+ return ReportActionNotArray(action->type,field);
+ if ((value->op==OpNegate)||(value->op==OpUnaryPlus)) {
+ act->flags&= ~XkbSA_DfltBtnAbsolute;
+ btn= value->value.child;
+ }
+ else {
+ act->flags|= XkbSA_DfltBtnAbsolute;
+ btn= value;
+ }
+
+ if (!ExprResolveInteger(btn,&rtrn,SimpleLookup,(XPointer)btnNames))
+ return ReportMismatch(action->type,field,"integer (range 1..5)");
+ if ((rtrn.ival<0)||(rtrn.ival>5)) {
+ ERROR("New default button value must be in the range 1..5\n");
+ ACTION1("Illegal default button value %d ignored\n",rtrn.ival);
+ return False;
+ }
+ if (rtrn.ival==0) {
+ ERROR("Cannot set default pointer button to \"default\"\n");
+ ACTION("Illegal default button setting ignored\n");
+ return False;
+ }
+ if (value->op==OpNegate)
+ XkbSASetPtrDfltValue(act,-rtrn.ival);
+ else XkbSASetPtrDfltValue(act,rtrn.ival);
+ return True;
+ }
+ return ReportIllegal(action->type,field);
+}
+
+static LookupEntry isoNames[] = {
+ { "mods", XkbSA_ISONoAffectMods },
+ { "modifiers", XkbSA_ISONoAffectMods },
+ { "group", XkbSA_ISONoAffectGroup },
+ { "groups", XkbSA_ISONoAffectGroup },
+ { "ptr", XkbSA_ISONoAffectPtr },
+ { "pointer", XkbSA_ISONoAffectPtr },
+ { "ctrls", XkbSA_ISONoAffectCtrls },
+ { "controls", XkbSA_ISONoAffectCtrls },
+ { "all", ~((unsigned)0) },
+ { "none", 0 },
+ { NULL, 0 },
+};
+
+static Bool
+#if NeedFunctionPrototypes
+HandleISOLock( XkbDescPtr xkb,
+ XkbAnyAction * action,
+ unsigned field,
+ ExprDef * array_ndx,
+ ExprDef * value)
+#else
+HandleISOLock(xkb,action,field,array_ndx,value)
+ XkbDescPtr xkb;
+ XkbAnyAction * action;
+ unsigned field;
+ ExprDef * array_ndx;
+ ExprDef * value;
+#endif
+{
+ExprResult rtrn;
+XkbISOAction * act;
+unsigned flags,mods;
+int group;
+
+ act= (XkbISOAction *)action;
+ switch (field) {
+ case F_Modifiers:
+ if (array_ndx!=NULL)
+ return ReportActionNotArray(action->type,field);
+ flags= act->flags;
+ if (CheckModifierField(xkb,action->type,value,&flags,&mods)) {
+ act->flags= flags&(~XkbSA_ISODfltIsGroup);
+ act->real_mods= mods&0xff;
+ mods= (mods>>8)&0xff;
+ XkbSetModActionVMods(act,mods);
+ return True;
+ }
+ return False;
+ case F_Group:
+ if (array_ndx!=NULL)
+ return ReportActionNotArray(action->type,field);
+ flags= act->flags;
+ if (CheckGroupField(action->type,value,&flags,&group)) {
+ act->flags= flags|XkbSA_ISODfltIsGroup;
+ XkbSASetGroup(act,group);
+ return True;
+ }
+ return False;
+ case F_Affect:
+ if (array_ndx!=NULL)
+ return ReportActionNotArray(action->type,field);
+ if (!ExprResolveMask(value,&rtrn,SimpleLookup,(XPointer)isoNames))
+ return ReportMismatch(action->type,field,"keyboard component");
+ act->affect= (~rtrn.uval)&XkbSA_ISOAffectMask;
+ return True;
+ }
+ return ReportIllegal(action->type,field);
+}
+
+static Bool
+#if NeedFunctionPrototypes
+HandleSwitchScreen( XkbDescPtr xkb,
+ XkbAnyAction * action,
+ unsigned field,
+ ExprDef * array_ndx,
+ ExprDef * value)
+#else
+HandleSwitchScreen(xkb,action,field,array_ndx,value)
+ XkbDescPtr xkb;
+ XkbAnyAction * action;
+ unsigned field;
+ ExprDef * array_ndx;
+ ExprDef * value;
+#endif
+{
+ExprResult rtrn;
+XkbSwitchScreenAction * act;
+
+ act= (XkbSwitchScreenAction *)action;
+ if (field==F_Screen) {
+ ExprDef *scrn;
+ if (array_ndx!=NULL)
+ return ReportActionNotArray(action->type,field);
+ if ((value->op==OpNegate)||(value->op==OpUnaryPlus)) {
+ act->flags&= ~XkbSA_SwitchAbsolute;
+ scrn= value->value.child;
+ }
+ else {
+ act->flags|= XkbSA_SwitchAbsolute;
+ scrn= value;
+ }
+
+ if (!ExprResolveInteger(scrn,&rtrn,NULL,NULL))
+ return ReportMismatch(action->type,field,"integer (0..255)");
+ if ((rtrn.ival<0)||(rtrn.ival>255)) {
+ ERROR("Screen index must be in the range 1..255\n");
+ ACTION1("Illegal screen value %d ignored\n",rtrn.ival);
+ return False;
+ }
+ if (value->op==OpNegate)
+ XkbSASetScreen(act,-rtrn.ival);
+ else XkbSASetScreen(act,rtrn.ival);
+ return True;
+ }
+ else if (field==F_Same) {
+ if (array_ndx!=NULL)
+ return ReportActionNotArray(action->type,field);
+ if (!ExprResolveBoolean(value,&rtrn,NULL,NULL))
+ return ReportMismatch(action->type,field,"boolean");
+ if (rtrn.uval) act->flags&= ~XkbSA_SwitchApplication;
+ else act->flags|= XkbSA_SwitchApplication;
+ return True;
+ }
+ return ReportIllegal(action->type,field);
+}
+
+LookupEntry ctrlNames[]= {
+ { "repeatkeys", XkbRepeatKeysMask },
+ { "repeat", XkbRepeatKeysMask },
+ { "autorepeat", XkbRepeatKeysMask },
+ { "slowkeys", XkbSlowKeysMask },
+ { "bouncekeys", XkbBounceKeysMask },
+ { "stickykeys", XkbStickyKeysMask },
+ { "mousekeys", XkbMouseKeysMask },
+ { "mousekeysaccel", XkbMouseKeysAccelMask },
+ { "accessxkeys", XkbAccessXKeysMask },
+ { "accessxtimeout", XkbAccessXTimeoutMask },
+ { "accessxfeedback", XkbAccessXFeedbackMask },
+ { "groupswrap", XkbGroupsWrapMask },
+ { "audiblebell", XkbAudibleBellMask },
+ { "overlay1", XkbOverlay1Mask },
+ { "overlay2", XkbOverlay2Mask },
+ { "ignoregrouplock", XkbIgnoreGroupLockMask },
+ { "all", XkbAllBooleanCtrlsMask },
+ { "none", 0 },
+ { NULL, 0 }
+};
+
+static Bool
+#if NeedFunctionPrototypes
+HandleSetLockControls( XkbDescPtr xkb,
+ XkbAnyAction * action,
+ unsigned field,
+ ExprDef * array_ndx,
+ ExprDef * value)
+#else
+HandleSetLockControls(xkb,action,field,array_ndx,value)
+ XkbDescPtr xkb;
+ XkbAnyAction * action;
+ unsigned field;
+ ExprDef * array_ndx;
+ ExprDef * value;
+#endif
+{
+ExprResult rtrn;
+XkbCtrlsAction * act;
+
+ act= (XkbCtrlsAction *)action;
+ if (field==F_Controls) {
+ if (array_ndx!=NULL)
+ return ReportActionNotArray(action->type,field);
+ if (!ExprResolveMask(value,&rtrn,SimpleLookup,(XPointer)ctrlNames))
+ return ReportMismatch(action->type,field,"controls mask");
+ XkbActionSetCtrls(act,rtrn.uval);
+ return True;
+ }
+ return ReportIllegal(action->type,field);
+}
+
+static LookupEntry evNames[]= {
+ { "press", XkbSA_MessageOnPress },
+ { "keypress", XkbSA_MessageOnPress },
+ { "release", XkbSA_MessageOnRelease },
+ { "keyrelease", XkbSA_MessageOnRelease },
+ { "all", XkbSA_MessageOnPress|XkbSA_MessageOnRelease },
+ { "none", 0 },
+ { NULL, 0 }
+};
+
+static Bool
+#if NeedFunctionPrototypes
+HandleActionMessage( XkbDescPtr xkb,
+ XkbAnyAction * action,
+ unsigned field,
+ ExprDef * array_ndx,
+ ExprDef * value)
+#else
+HandleActionMessage(xkb,action,field,array_ndx,value)
+ XkbDescPtr xkb;
+ XkbAnyAction * action;
+ unsigned field;
+ ExprDef * array_ndx;
+ ExprDef * value;
+#endif
+{
+ExprResult rtrn;
+XkbMessageAction * act;
+
+ act= (XkbMessageAction *)action;
+ switch (field) {
+ case F_Report:
+ if (array_ndx!=NULL)
+ return ReportActionNotArray(action->type,field);
+ if (!ExprResolveMask(value,&rtrn,SimpleLookup,(XPointer)evNames))
+ return ReportMismatch(action->type,field,"key event mask");
+ act->flags&= ~(XkbSA_MessageOnPress|XkbSA_MessageOnRelease);
+ act->flags= rtrn.uval&(XkbSA_MessageOnPress|XkbSA_MessageOnRelease);
+ return True;
+ case F_GenKeyEvent:
+ if (array_ndx!=NULL)
+ return ReportActionNotArray(action->type,field);
+ if (!ExprResolveBoolean(value,&rtrn,NULL,NULL))
+ return ReportMismatch(action->type,field,"boolean");
+ if (rtrn.uval) act->flags|= XkbSA_MessageGenKeyEvent;
+ else act->flags&= ~XkbSA_MessageGenKeyEvent;
+ return True;
+ case F_Data:
+ if (array_ndx==NULL) {
+ if (!ExprResolveString(value,&rtrn,NULL,NULL))
+ return ReportMismatch(action->type,field,"string");
+ else {
+ int len= strlen(rtrn.str);
+ if ((len<1)||(len>6)) {
+ WARN("An action message can hold only 6 bytes\n");
+ ACTION1("Extra %d bytes ignored\n",len-6);
+ }
+ strncpy((char *)act->message,rtrn.str,6);
+ }
+ return True;
+ }
+ else {
+ unsigned ndx;
+ if (!ExprResolveInteger(array_ndx,&rtrn,NULL,NULL)) {
+ ERROR("Array subscript must be integer\n");
+ ACTION("Illegal subscript ignored\n");
+ return False;
+ }
+ ndx= rtrn.uval;
+ if (ndx>5) {
+ ERROR("An action message is at most 6 bytes long\n");
+ ACTION1("Attempt to use data[%d] ignored\n",ndx);
+ return False;
+ }
+ if (!ExprResolveInteger(value,&rtrn,NULL,NULL))
+ return ReportMismatch(action->type,field,"integer");
+ if ((rtrn.ival<0)||(rtrn.ival>255)) {
+ ERROR("Message data must be in the range 0..255\n");
+ ACTION1("Illegal datum %d ignored\n",rtrn.ival);
+ return False;
+ }
+ act->message[ndx]= rtrn.uval;
+ }
+ return True;
+ }
+ return ReportIllegal(action->type,field);
+}
+
+static Bool
+#if NeedFunctionPrototypes
+HandleRedirectKey( XkbDescPtr xkb,
+ XkbAnyAction * action,
+ unsigned field,
+ ExprDef * array_ndx,
+ ExprDef * value)
+#else
+HandleRedirectKey(xkb,action,field,array_ndx,value)
+ XkbDescPtr xkb;
+ XkbAnyAction * action;
+ unsigned field;
+ ExprDef * array_ndx;
+ ExprDef * value;
+#endif
+{
+ExprResult rtrn;
+XkbRedirectKeyAction * act;
+unsigned t1,t2,vmods,vmask;
+unsigned long tmp;
+
+ if (array_ndx!=NULL)
+ return ReportActionNotArray(action->type,field);
+
+ act= (XkbRedirectKeyAction *)action;
+ switch (field) {
+ case F_Keycode:
+ if (!ExprResolveKeyName(value,&rtrn,NULL,NULL))
+ return ReportMismatch(action->type,field,"key name");
+ tmp= KeyNameToLong(rtrn.keyName.name);
+ if (!FindNamedKey(xkb,tmp,&t1,True,CreateKeyNames(xkb),0)) {
+ return ReportNotFound(action->type,field,"Key",
+ XkbKeyNameText(rtrn.keyName.name,XkbMessage));
+ }
+ act->new_key= t1;
+ return True;
+ case F_ModsToClear:
+ case F_Modifiers:
+ t1= 0;
+ if (CheckModifierField(xkb,action->type,value,&t1,&t2)) {
+ act->mods_mask|= (t2&0xff);
+ if (field==F_Modifiers)
+ act->mods|= (t2&0xff);
+ else act->mods&= ~(t2&0xff);
+
+ t2= (t2>>8)&0xffff;
+ vmods= XkbSARedirectVMods(act);
+ vmask= XkbSARedirectVModsMask(act);
+ vmask|= t2;
+ if (field==F_Modifiers)
+ vmods|= t2;
+ else vmods&= ~t2;
+ XkbSARedirectSetVMods(act,vmods);
+ XkbSARedirectSetVModsMask(act,vmask);
+ return True;
+ }
+ return True;
+ }
+ return ReportIllegal(action->type,field);
+}
+
+static Bool
+#if NeedFunctionPrototypes
+HandleDeviceBtn( XkbDescPtr xkb,
+ XkbAnyAction * action,
+ unsigned field,
+ ExprDef * array_ndx,
+ ExprDef * value)
+#else
+HandleDeviceBtn(xkb,action,field,array_ndx,value)
+ XkbDescPtr xkb;
+ XkbAnyAction * action;
+ unsigned field;
+ ExprDef * array_ndx;
+ ExprDef * value;
+#endif
+{
+ExprResult rtrn;
+XkbDeviceBtnAction * act;
+
+ act= (XkbDeviceBtnAction *)action;
+ if (field==F_Button) {
+ if (array_ndx!=NULL)
+ return ReportActionNotArray(action->type,field);
+ if (!ExprResolveInteger(value,&rtrn,NULL,NULL))
+ return ReportMismatch(action->type,field,"integer (range 1..255)");
+ if ((rtrn.ival<0)||(rtrn.ival>255)) {
+ ERROR("Button must specify default or be in the range 1..255\n");
+ ACTION1("Illegal button value %d ignored\n",rtrn.ival);
+ return False;
+ }
+ act->button= rtrn.ival;
+ return True;
+ }
+ else if ((action->type==XkbSA_LockDeviceBtn)&&(field==F_Affect)) {
+ if (array_ndx!=NULL)
+ return ReportActionNotArray(action->type,field);
+ if (!ExprResolveEnum(value,&rtrn,lockWhich))
+ return ReportMismatch(action->type,field,"lock or unlock");
+ act->flags&= ~(XkbSA_LockNoLock|XkbSA_LockNoUnlock);
+ act->flags|= rtrn.ival;
+ return True;
+ }
+ else if (field==F_Count) {
+ if (array_ndx!=NULL)
+ return ReportActionNotArray(action->type,field);
+ if (!ExprResolveInteger(value,&rtrn,SimpleLookup,(XPointer)btnNames))
+ return ReportMismatch(action->type,field,"integer");
+ if ((rtrn.ival<0)||(rtrn.ival>255)) {
+ ERROR("The count field must have a value in the range 0..255\n");
+ ACTION1("Illegal count %d ignored\n",rtrn.ival);
+ return False;
+ }
+ act->count= rtrn.ival;
+ return True;
+ }
+ else if (field==F_Device) {
+ if (array_ndx!=NULL)
+ return ReportActionNotArray(action->type,field);
+ if (!ExprResolveInteger(value,&rtrn,NULL,NULL))
+ return ReportMismatch(action->type,field,"integer (range 1..255)");
+ if ((rtrn.ival<0)||(rtrn.ival>255)) {
+ ERROR("Device must specify default or be in the range 1..255\n");
+ ACTION1("Illegal device value %d ignored\n",rtrn.ival);
+ return False;
+ }
+ act->device= rtrn.ival;
+ return True;
+ }
+ return ReportIllegal(action->type,field);
+}
+
+static Bool
+#if NeedFunctionPrototypes
+HandlePrivate( XkbDescPtr xkb,
+ XkbAnyAction * action,
+ unsigned field,
+ ExprDef * array_ndx,
+ ExprDef * value)
+#else
+HandlePrivate(xkb,action,field,array_ndx,value)
+ XkbDescPtr xkb;
+ XkbAnyAction * action;
+ unsigned field;
+ ExprDef * array_ndx;
+ ExprDef * value;
+#endif
+{
+ExprResult rtrn;
+
+ switch (field) {
+ case F_Type:
+ if (!ExprResolveInteger(value,&rtrn,NULL,NULL))
+ return ReportMismatch(PrivateAction,field,"integer");
+ if ((rtrn.ival<0)||(rtrn.ival>255)) {
+ ERROR("Private action type must be in the range 0..255\n");
+ ACTION1("Illegal type %d ignored\n",rtrn.ival);
+ return False;
+ }
+ action->type= rtrn.uval;
+ return True;
+ case F_Data:
+ if (array_ndx==NULL) {
+ if (!ExprResolveString(value,&rtrn,NULL,NULL))
+ return ReportMismatch(action->type,field,"string");
+ else {
+ int len= strlen(rtrn.str);
+ if ((len<1)||(len>7)) {
+ WARN("A private action has 7 data bytes\n");
+ ACTION1("Extra %d bytes ignored\n",len-6);
+ return False;
+ }
+ strncpy((char *)action->data,rtrn.str,7);
+ }
+ return True;
+ }
+ else {
+ unsigned ndx;
+ if (!ExprResolveInteger(array_ndx,&rtrn,NULL,NULL)) {
+ ERROR("Array subscript must be integer\n");
+ ACTION("Illegal subscript ignored\n");
+ return False;
+ }
+ ndx= rtrn.uval;
+ if (ndx>6) {
+ ERROR("The data for a private action is 7 bytes long\n");
+ ACTION1("Attempt to use data[%d] ignored\n",ndx);
+ return False;
+ }
+ if (!ExprResolveInteger(value,&rtrn,NULL,NULL))
+ return ReportMismatch(action->type,field,"integer");
+ if ((rtrn.ival<0)||(rtrn.ival>255)) {
+ ERROR("All data for a private action must be 0..255\n");
+ ACTION1("Illegal datum %d ignored\n",rtrn.ival);
+ return False;
+ }
+ action->data[ndx]= rtrn.uval;
+ return True;
+ }
+ }
+ return ReportIllegal(PrivateAction,field);
+}
+
+typedef Bool (*actionHandler)(
+#if NeedFunctionPrototypes
+ XkbDescPtr /* xkb */,
+ XkbAnyAction * /* action */,
+ unsigned /* field */,
+ ExprDef * /* array_ndx */,
+ ExprDef * /* value */
+#endif
+);
+
+static actionHandler handleAction[XkbSA_NumActions+1] = {
+ HandleNoAction /* NoAction */,
+ HandleSetLatchMods /* SetMods */,
+ HandleSetLatchMods /* LatchMods */,
+ HandleLockMods /* LockMods */,
+ HandleSetLatchGroup /* SetGroup */,
+ HandleSetLatchGroup /* LatchGroup */,
+ HandleLockGroup /* LockGroup */,
+ HandleMovePtr /* MovePtr */,
+ HandlePtrBtn /* PtrBtn */,
+ HandlePtrBtn /* LockPtrBtn */,
+ HandleSetPtrDflt /* SetPtrDflt */,
+ HandleISOLock /* ISOLock */,
+ HandleNoAction /* Terminate */,
+ HandleSwitchScreen /* SwitchScreen */,
+ HandleSetLockControls /* SetControls */,
+ HandleSetLockControls /* LockControls */,
+ HandleActionMessage /* ActionMessage*/,
+ HandleRedirectKey /* RedirectKey */,
+ HandleDeviceBtn /* DeviceBtn */,
+ HandleDeviceBtn /* LockDeviceBtn*/,
+ HandlePrivate /* Private */
+};
+
+/***====================================================================***/
+
+static void
+#if NeedFunctionPrototypes
+ApplyActionFactoryDefaults(XkbAction *action)
+#else
+ApplyActionFactoryDefaults(action)
+ XkbAction * action;
+#endif
+{
+ if (action->type==XkbSA_SetPtrDflt) { /* increment default button */
+ action->dflt.affect= XkbSA_AffectDfltBtn;
+ action->dflt.flags= 0;
+ XkbSASetPtrDfltValue(&action->dflt,1);
+ }
+ else if (action->type==XkbSA_ISOLock) {
+ action->iso.real_mods= LockMask;
+ }
+ return;
+}
+
+
+int
+#if NeedFunctionPrototypes
+HandleActionDef( ExprDef * def,
+ XkbDescPtr xkb,
+ XkbAnyAction * action,
+ unsigned mergeMode,
+ ActionInfo * info)
+#else
+HandleActionDef(def,xkb,action,mergeMode,info)
+ ExprDef * def;
+ XkbDescPtr xkb;
+ XkbAnyAction * action;
+ unsigned mergeMode;
+ ActionInfo * info;
+#endif
+{
+ExprDef * arg;
+register char * str;
+unsigned tmp,hndlrType;
+
+ if (!actionsInitialized)
+ ActionsInit();
+
+ if (def->op!=ExprActionDecl) {
+ ERROR1("Expected an action definition, found %s\n",exprOpText(def->op));
+ return False;
+ }
+ str= XkbAtomGetString(NULL,def->value.action.name);
+ if (!str) {
+ WSGO("Missing name in action definition!!\n");
+ return False;
+ }
+ if (!stringToAction(str,&tmp)) {
+ ERROR1("Unknown action %s\n",str);
+ return False;
+ }
+ action->type= hndlrType= tmp;
+ if (action->type!=XkbSA_NoAction) {
+ ApplyActionFactoryDefaults((XkbAction *)action);
+ while (info) {
+ if ((info->action==XkbSA_NoAction)||(info->action==hndlrType)) {
+ if (!(*handleAction[hndlrType])(xkb,action,
+ info->field,info->array_ndx,
+ info->value)) {
+ return False;
+ }
+ }
+ info= info->next;
+ }
+ }
+ for (arg=def->value.action.args;arg!=NULL;arg=(ExprDef*)arg->common.next) {
+ ExprDef *field,*value,*arrayRtrn;
+ ExprResult elemRtrn,fieldRtrn;
+ unsigned fieldNdx;
+
+ if (arg->op==OpAssign) {
+ field= arg->value.binary.left;
+ value= arg->value.binary.right;
+ }
+ else {
+ if ((arg->op==OpNot)||(arg->op==OpInvert)) {
+ field= arg->value.child;
+ value= &constFalse;
+ }
+ else {
+ field= arg;
+ value= &constTrue;
+ }
+ }
+ if (!ExprResolveLhs(field,&elemRtrn,&fieldRtrn,&arrayRtrn))
+ return False; /* internal error -- already reported */
+
+ if (elemRtrn.str!=NULL) {
+ ERROR("Cannot change defaults in an action definition\n");
+ ACTION2("Ignoring attempt to change %s.%s\n",elemRtrn.str,
+ fieldRtrn.str);
+ return False;
+ }
+ if (!stringToField(fieldRtrn.str,&fieldNdx)) {
+ ERROR1("Unknown field name %s\n",uStringText(fieldRtrn.str));
+ return False;
+ }
+ if (!(*handleAction[hndlrType])(xkb,action,fieldNdx,arrayRtrn,value)) {
+ return False;
+ }
+ }
+ return True;
+}
+
+/***====================================================================***/
+
+int
+#if NeedFunctionPrototypes
+SetActionField( XkbDescPtr xkb,
+ char * elem,
+ char * field,
+ ExprDef * array_ndx,
+ ExprDef * value,
+ ActionInfo ** info_rtrn)
+#else
+SetActionField(xkb,elem,field,array_ndx,value,info_rtrn)
+ XkbDescPtr xkb;
+ char * elem;
+ char * field;
+ ExprDef * array_ndx;
+ ExprDef * value;
+ ActionInfo ** info_rtrn;
+#endif
+{
+ActionInfo *new,*old;
+
+ if (!actionsInitialized)
+ ActionsInit();
+
+ new= uTypedAlloc(ActionInfo);
+ if (new==NULL) {
+ WSGO("Couldn't allocate space for action default\n");
+ return False;
+ }
+ if (uStrCaseCmp(elem,"action")==0)
+ new->action= XkbSA_NoAction;
+ else {
+ if (!stringToAction(elem,&new->action))
+ return False;
+ if (new->action==XkbSA_NoAction) {
+ ERROR1("\"%s\" is not a valid field in a NoAction action\n",field);
+ return False;
+ }
+ }
+ if (!stringToField(field,&new->field)) {
+ ERROR1("\"%s\" is not a legal field name\n",field);
+ return False;
+ }
+ new->array_ndx= array_ndx;
+ new->value= value;
+ new->next= NULL;
+ old= *info_rtrn;
+ while ((old)&&(old->next))
+ old= old->next;
+ if (old==NULL) *info_rtrn= new;
+ else old->next= new;
+ return True;
+}
+
+/***====================================================================***/
+
+void
+#if NeedFunctionPrototypes
+ActionsInit(void)
+#else
+ActionsInit()
+#endif
+{
+ if (!actionsInitialized) {
+ bzero((char *)&constTrue,sizeof(constTrue));
+ bzero((char *)&constFalse,sizeof(constFalse));
+ constTrue.common.stmtType= StmtExpr;
+ constTrue.common.next= NULL;
+ constTrue.op= ExprIdent;
+ constTrue.type= TypeBoolean;
+ constTrue.value.str= XkbInternAtom(NULL,"true",False);
+ constFalse.common.stmtType= StmtExpr;
+ constFalse.common.next= NULL;
+ constFalse.op= ExprIdent;
+ constFalse.type= TypeBoolean;
+ constFalse.value.str= XkbInternAtom(NULL,"false",False);
+ actionsInitialized= 1;
+ }
+ return;
+}
+
diff --git a/action.h b/action.h
new file mode 100644
index 0000000..f588ff4
--- /dev/null
+++ b/action.h
@@ -0,0 +1,94 @@
+/* $Xorg: action.h,v 1.3 2000/08/17 19:54:30 cpqbld Exp $ */
+/************************************************************
+ 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
+ documentation, and that the name of Silicon Graphics not be
+ used in advertising or publicity pertaining to distribution
+ of the software without specific prior written permission.
+ Silicon Graphics makes no representation about the suitability
+ of this software for any purpose. It is provided "as is"
+ without any express or implied warranty.
+
+ SILICON GRAPHICS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS
+ SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+ AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL SILICON
+ 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
+ OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH
+ THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+ ********************************************************/
+
+#ifndef ACTION_H
+#define ACTION_H 1
+
+#define F_ClearLocks 0
+#define F_LatchToLock 1
+#define F_GenKeyEvent 2
+#define F_Report 3
+#define F_Default 4
+#define F_Affect 5
+#define F_Increment 6
+#define F_Modifiers 7
+#define F_Group 8
+#define F_X 9
+#define F_Y 10
+#define F_Accel 11
+#define F_Button 12
+#define F_Value 13
+#define F_Controls 14
+#define F_Type 15
+#define F_Count 16
+#define F_Screen 17
+#define F_Same 18
+#define F_Data 19
+#define F_Device 20
+#define F_Keycode 21
+#define F_ModsToClear 22
+#define F_LastField F_ModsToClear
+#define F_NumFields (F_LastField+1)
+
+#define PrivateAction (XkbSA_LastAction+1)
+
+typedef struct _ActionInfo {
+ unsigned action;
+ unsigned field;
+ ExprDef * array_ndx;
+ ExprDef * value;
+ struct _ActionInfo * next;
+} ActionInfo;
+
+extern int HandleActionDef(
+#if NeedFunctionPrototypes
+ ExprDef * /* def */,
+ XkbDescPtr /* xkb */,
+ XkbAnyAction * /* action */,
+ unsigned /* mergeMode */,
+ ActionInfo * /* info */
+#endif
+);
+
+extern int SetActionField(
+#if NeedFunctionPrototypes
+ XkbDescPtr /* xkb */,
+ char * /* elem */,
+ char * /* field */,
+ ExprDef * /* index */,
+ ExprDef * /* value */,
+ ActionInfo ** /* info_rtrn */
+#endif
+);
+
+extern void ActionsInit(
+#if NeedFunctionPrototypes
+ void
+#endif
+);
+
+#endif /* ACTION_H */
diff --git a/alias.c b/alias.c
new file mode 100644
index 0000000..dc51b82
--- /dev/null
+++ b/alias.c
@@ -0,0 +1,302 @@
+/* $Xorg: alias.c,v 1.3 2000/08/17 19:54:30 cpqbld Exp $ */
+/************************************************************
+ Copyright (c) 1995 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
+ documentation, and that the name of Silicon Graphics not be
+ used in advertising or publicity pertaining to distribution
+ of the software without specific prior written permission.
+ Silicon Graphics makes no representation about the suitability
+ of this software for any purpose. It is provided "as is"
+ without any express or implied warranty.
+
+ SILICON GRAPHICS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS
+ SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+ AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL SILICON
+ 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
+ OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH
+ THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+ ********************************************************/
+
+#include "xkbcomp.h"
+#include "misc.h"
+#include "alias.h"
+#include "keycodes.h"
+
+#include <X11/extensions/XKBgeom.h>
+
+static void
+#if NeedFunctionPrototypes
+HandleCollision(AliasInfo *old,AliasInfo *new)
+#else
+HandleCollision(old,new)
+ AliasInfo * old;
+ AliasInfo * new;
+#endif
+{
+ if (strncmp(new->real,old->real,XkbKeyNameLength)==0) {
+ if (((new->def.fileID==old->def.fileID)&&(warningLevel>0))||
+ (warningLevel>9)) {
+ WARN2("Alias of %s for %s declared more than once\n",
+ XkbKeyNameText(new->alias,XkbMessage),
+ XkbKeyNameText(new->real,XkbMessage));
+ ACTION("First definition ignored\n");
+ }
+ }
+ else {
+ char *use,*ignore;
+ if (new->def.merge==MergeAugment) {
+ use= old->real;
+ ignore= new->real;
+ }
+ else {
+ use= new->real;
+ ignore= old->real;
+ }
+ if (((old->def.fileID==new->def.fileID)&&(warningLevel>0))||
+ (warningLevel>9)){
+ WARN1("Multiple definitions for alias %s\n",
+ XkbKeyNameText(old->alias,XkbMessage));
+ ACTION2("Using %s, ignoring %s\n", XkbKeyNameText(use,XkbMessage),
+ XkbKeyNameText(ignore,XkbMessage));
+ }
+ if (use!=old->real)
+ memcpy(old->real,use,XkbKeyNameLength);
+ }
+ old->def.fileID= new->def.fileID;
+ old->def.merge= new->def.merge;
+ return;
+}
+
+static void
+#if NeedFunctionPrototypes
+InitAliasInfo( AliasInfo * info,
+ unsigned merge,
+ unsigned file_id,
+ char * alias,
+ char * real)
+#else
+InitAliasInfo(info,merge,file_id,alias,real)
+ AliasInfo * info;
+ unsigned merge;
+ unsigned file_id;
+ char * alias;
+ char * real;
+#endif
+{
+ bzero(info,sizeof(AliasInfo));
+ info->def.merge= merge;
+ info->def.fileID= file_id;
+ strncpy(info->alias,alias,XkbKeyNameLength);
+ strncpy(info->real,real,XkbKeyNameLength);
+ return;
+}
+
+int
+#if NeedFunctionPrototypes
+HandleAliasDef( KeyAliasDef * def,
+ unsigned merge,
+ unsigned file_id,
+ AliasInfo ** info_in)
+#else
+HandleAliasDef(def,merge,file_id,info_in)
+ KeyAliasDef * def;
+ unsigned merge;
+ unsigned file_id;
+ AliasInfo ** info_in;
+#endif
+{
+AliasInfo * info;
+
+ for (info= *info_in;info!=NULL;info= (AliasInfo *)info->def.next) {
+ if (strncmp(info->alias,def->alias,XkbKeyNameLength)==0) {
+ AliasInfo new;
+ InitAliasInfo(&new,merge,file_id,def->alias,def->real);
+ HandleCollision(info,&new);
+ return True;
+ }
+ }
+ info= uTypedCalloc(1,AliasInfo);
+ if (info==NULL) {
+ WSGO("Allocation failure in HandleAliasDef\n");
+ return False;
+ }
+ info->def.fileID= file_id;
+ info->def.merge= merge;
+ info->def.next= (CommonInfo *)*info_in;
+ memcpy(info->alias,def->alias,XkbKeyNameLength);
+ memcpy(info->real,def->real,XkbKeyNameLength);
+ *info_in= (AliasInfo *)AddCommonInfo(&(*info_in)->def,&info->def);
+ return True;
+}
+
+void
+#if NeedFunctionPrototypes
+ClearAliases(AliasInfo **info_in)
+#else
+ClearAliases(info_in)
+ AliasInfo ** info_in;
+#endif
+{
+ if ((info_in)&&(*info_in))
+ ClearCommonInfo(&(*info_in)->def);
+ return;
+}
+
+Bool
+#if NeedFunctionPrototypes
+MergeAliases(AliasInfo **into,AliasInfo **merge,unsigned how_merge)
+#else
+MergeAliases(into,merge,how_merge)
+ AliasInfo ** into;
+ AliasInfo ** merge;
+ unsigned how_merge;
+#endif
+{
+AliasInfo * tmp;
+KeyAliasDef def;
+
+ if ((*merge)==NULL)
+ return True;
+ if ((*into)==NULL) {
+ *into= *merge;
+ *merge= NULL;
+ return True;
+ }
+ bzero((char *)&def,sizeof(KeyAliasDef));
+ for (tmp= *merge;tmp!=NULL;tmp= (AliasInfo *)tmp->def.next) {
+ if (how_merge==MergeDefault)
+ def.merge= tmp->def.merge;
+ else def.merge= how_merge;
+ memcpy(def.alias,tmp->alias,XkbKeyNameLength);
+ memcpy(def.real,tmp->real,XkbKeyNameLength);
+ if (!HandleAliasDef(&def,def.merge,tmp->def.fileID,into))
+ return False;
+ }
+ return True;
+}
+
+int
+#if NeedFunctionPrototypes
+ApplyAliases(XkbDescPtr xkb,Bool toGeom,AliasInfo **info_in)
+#else
+ApplyAliases(xkb,toGeom,info_in)
+ XkbDescPtr xkb;
+ Bool toGeom;
+ AliasInfo ** info_in;
+#endif
+{
+register int i;
+XkbKeyAliasPtr old,a;
+AliasInfo * info;
+int nNew,nOld;
+Status status;
+
+ if (*info_in==NULL)
+ return True;
+ if (toGeom) {
+ nOld= (xkb->geom?xkb->geom->num_key_aliases:0);
+ old= (xkb->geom?xkb->geom->key_aliases:NULL);
+ }
+ else {
+ nOld= (xkb->names?xkb->names->num_key_aliases:0);
+ old= (xkb->names?xkb->names->key_aliases:NULL);
+ }
+ for (nNew=0,info= *info_in;info!=NULL;info= (AliasInfo *)info->def.next) {
+ unsigned long lname;
+ unsigned int kc;
+
+ lname= KeyNameToLong(info->real);
+ if (!FindNamedKey(xkb,lname,&kc,False,CreateKeyNames(xkb),0)) {
+ if (warningLevel>4) {
+ WARN2("Attempt to alias %s to non-existent key %s\n",
+ XkbKeyNameText(info->alias,XkbMessage),
+ XkbKeyNameText(info->real,XkbMessage));
+ ACTION("Ignored\n");
+ }
+ info->alias[0]= '\0';
+ continue;
+ }
+ lname= KeyNameToLong(info->alias);
+ if (FindNamedKey(xkb,lname,&kc,False,False,0)) {
+ if (warningLevel>4) {
+ WARN("Attempt to create alias with the name of a real key\n");
+ ACTION2("Alias \"%s = %s\" ignored\n",
+ XkbKeyNameText(info->alias,XkbMessage),
+ XkbKeyNameText(info->real,XkbMessage));
+ }
+ info->alias[0]= '\0';
+ continue;
+ }
+ nNew++;
+ if ( old ) {
+ for (i=0,a=old;i<nOld;i++,a++) {
+ if (strncmp(a->alias,info->alias,XkbKeyNameLength)==0) {
+ AliasInfo old;
+ InitAliasInfo(&old,MergeAugment,0,a->alias,a->real);
+ HandleCollision(&old,info);
+ memcpy(old.real,a->real,XkbKeyNameLength);
+ info->alias[0]= '\0';
+ nNew--;
+ break;
+ }
+ }
+ }
+ }
+ if (nNew==0) {
+ ClearCommonInfo(&(*info_in)->def);
+ *info_in= NULL;
+ return True;
+ }
+ status= Success;
+ if (toGeom) {
+ if (!xkb->geom) {
+ XkbGeometrySizesRec sizes;
+ bzero((char *)&sizes,sizeof(XkbGeometrySizesRec));
+ sizes.which= XkbGeomKeyAliasesMask;
+ sizes.num_key_aliases= nOld+nNew;
+ status= XkbAllocGeometry(xkb,&sizes);
+ }
+ else {
+ status= XkbAllocGeomKeyAliases(xkb->geom,nOld+nNew);
+ }
+ if (xkb->geom)
+ old= xkb->geom->key_aliases;
+ }
+ else {
+ status= XkbAllocNames(xkb,XkbKeyAliasesMask,0,nOld+nNew);
+ if (xkb->names)
+ old= xkb->names->key_aliases;
+ }
+ if (status!=Success) {
+ WSGO("Allocation failure in ApplyAliases\n");
+ return False;
+ }
+ if (toGeom)
+ a= &xkb->geom->key_aliases[nOld];
+ else a= &xkb->names->key_aliases[nOld];
+ for (info= *info_in;info!=NULL;info= (AliasInfo *)info->def.next) {
+ if (info->alias[0]!='\0') {
+ strncpy(a->alias,info->alias,XkbKeyNameLength);
+ strncpy(a->real,info->real,XkbKeyNameLength);
+ a++;
+ }
+ }
+#ifdef DEBUG
+ if ((a-old)!=(nOld+nNew)) {
+ WSGO2("Expected %d aliases total but created %d\n",nOld+nNew,a-old);
+ }
+#endif
+ if (toGeom)
+ xkb->geom->num_key_aliases+= nNew;
+ ClearCommonInfo(&(*info_in)->def);
+ *info_in= NULL;
+ return True;
+}
diff --git a/alias.h b/alias.h
new file mode 100644
index 0000000..7c76083
--- /dev/null
+++ b/alias.h
@@ -0,0 +1,68 @@
+/* $Xorg: alias.h,v 1.3 2000/08/17 19:54:30 cpqbld Exp $ */
+/************************************************************
+ Copyright (c) 1995 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
+ documentation, and that the name of Silicon Graphics not be
+ used in advertising or publicity pertaining to distribution
+ of the software without specific prior written permission.
+ Silicon Graphics makes no representation about the suitability
+ of this software for any purpose. It is provided "as is"
+ without any express or implied warranty.
+
+ SILICON GRAPHICS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS
+ SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+ AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL SILICON
+ 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
+ OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH
+ THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+ ********************************************************/
+
+#ifndef ALIAS_H
+#define ALIAS_H 1
+
+typedef struct _AliasInfo {
+ CommonInfo def;
+ char alias[XkbKeyNameLength+1];
+ char real[XkbKeyNameLength+1];
+} AliasInfo;
+
+extern int HandleAliasDef(
+#if NeedFunctionPrototypes
+ KeyAliasDef * /* def */,
+ unsigned /* merge */,
+ unsigned /* file_id */,
+ AliasInfo ** /* info */
+#endif
+);
+
+extern void ClearAliases(
+#if NeedFunctionPrototypes
+ AliasInfo ** /* info */
+#endif
+);
+
+extern Bool MergeAliases(
+#if NeedFunctionPrototypes
+ AliasInfo ** /* into */,
+ AliasInfo ** /* merge */,
+ unsigned /* how_merge */
+#endif
+);
+
+extern int ApplyAliases(
+#if NeedFunctionPrototypes
+ XkbDescPtr /* xkb */,
+ Bool /* toGeom */,
+ AliasInfo ** /* info */
+#endif
+);
+
+#endif /* ALIAS_H */
diff --git a/compat.c b/compat.c
new file mode 100644
index 0000000..2b44523
--- /dev/null
+++ b/compat.c
@@ -0,0 +1,913 @@
+/* $Xorg: compat.c,v 1.3 2000/08/17 19:54:30 cpqbld Exp $ */
+/************************************************************
+ 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
+ documentation, and that the name of Silicon Graphics not be
+ used in advertising or publicity pertaining to distribution
+ of the software without specific prior written permission.
+ Silicon Graphics makes no representation about the suitability
+ of this software for any purpose. It is provided "as is"
+ without any express or implied warranty.
+
+ SILICON GRAPHICS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS
+ SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+ AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL SILICON
+ 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
+ OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH
+ THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+ ********************************************************/
+
+#include <X11/Xos.h>
+#include "xkbcomp.h"
+#include "tokens.h"
+#include "expr.h"
+#include "vmod.h"
+#include "misc.h"
+#include "indicators.h"
+#include "action.h"
+
+typedef struct _SymInterpInfo {
+ CommonInfo defs;
+ XkbSymInterpretRec interp;
+} SymInterpInfo;
+
+#define _SI_VirtualMod (1<<0)
+#define _SI_Action (1<<1)
+#define _SI_AutoRepeat (1<<2)
+#define _SI_LockingKey (1<<3)
+#define _SI_LevelOneOnly (1<<4)
+
+typedef struct _GroupCompatInfo {
+ unsigned char fileID;
+ unsigned char merge;
+ unsigned char real_mods;
+ unsigned short vmods;
+} GroupCompatInfo;
+
+typedef struct _CompatInfo {
+ char * name;
+ unsigned fileID;
+ int errorCount;
+ int nInterps;
+ SymInterpInfo * interps;
+ SymInterpInfo dflt;
+ LEDInfo ledDflt;
+ GroupCompatInfo groupCompat[XkbNumKbdGroups];
+ LEDInfo * leds;
+ VModInfo vmods;
+ ActionInfo * act;
+ XkbDescPtr xkb;
+} CompatInfo;
+
+/***====================================================================***/
+
+#define ReportSINotArray(si,f,i) \
+ ReportNotArray("symbol interpretation",(f),siText((si),(i)))
+#define ReportSIBadType(si,f,w,i) \
+ ReportBadType("symbol interpretation",(f),siText((si),(i)),(w))
+
+/***====================================================================***/
+
+static char *
+#if NeedFunctionPrototypes
+siText(SymInterpInfo * si,CompatInfo * info)
+#else
+siText(si,info)
+ SymInterpInfo * si;
+ CompatInfo * info;
+#endif
+{
+static char buf[128];
+
+ if (si==&info->dflt) {
+ sprintf(buf,"default");
+ }
+ else {
+ sprintf(buf,"%s+%s(%s)",XkbKeysymText(si->interp.sym,XkbMessage),
+ XkbSIMatchText(si->interp.match,XkbMessage),
+ XkbModMaskText(si->interp.mods,XkbMessage));
+ }
+ return buf;
+}
+
+static void
+#if NeedFunctionPrototypes
+InitCompatInfo(CompatInfo *info,XkbDescPtr xkb)
+#else
+InitCompatInfo(info,xkb)
+ CompatInfo * info;
+ XkbDescPtr xkb;
+#endif
+{
+register int i;
+
+ info->xkb= xkb;
+ info->name= NULL;
+ info->fileID= 0;
+ info->errorCount= 0;
+ info->nInterps= 0;
+ info->interps= NULL;
+ info->act= NULL;
+ info->dflt.defs.fileID= info->fileID;
+ info->dflt.defs.defined= 0;
+ info->dflt.defs.merge= MergeOverride;
+ info->dflt.interp.flags= 0;
+ info->dflt.interp.virtual_mod= XkbNoModifier;
+ info->dflt.interp.act.type= XkbSA_NoAction;
+ for (i=0;i<XkbAnyActionDataSize;i++) {
+ info->dflt.interp.act.data[i]= 0;
+ }
+ ClearIndicatorMapInfo(xkb->dpy,&info->ledDflt);
+ info->ledDflt.defs.fileID= info->fileID;
+ info->ledDflt.defs.defined= 0;
+ info->ledDflt.defs.merge= MergeOverride;
+ bzero((char *)&info->groupCompat[0],XkbNumKbdGroups*sizeof(GroupCompatInfo));
+ info->leds= NULL;
+ InitVModInfo(&info->vmods,xkb);
+ return;
+}
+
+static void
+#if NeedFunctionPrototypes
+ClearCompatInfo(CompatInfo *info,XkbDescPtr xkb)
+#else
+ClearCompatInfo(info,xkb)
+ CompatInfo * info;
+ XkbDescPtr xkb;
+#endif
+{
+register int i;
+
+ if (info->name!=NULL)
+ uFree(info->name);
+ info->name= NULL;
+ info->dflt.defs.defined= 0;
+ info->dflt.defs.merge= MergeAugment;
+ info->dflt.interp.flags= 0;
+ info->dflt.interp.virtual_mod= XkbNoModifier;
+ info->dflt.interp.act.type= XkbSA_NoAction;
+ for (i=0;i<XkbAnyActionDataSize;i++) {
+ info->dflt.interp.act.data[i]= 0;
+ }
+ ClearIndicatorMapInfo(xkb->dpy,&info->ledDflt);
+ info->nInterps= 0;
+ info->interps= (SymInterpInfo *)ClearCommonInfo(&info->interps->defs);
+ bzero((char *)&info->groupCompat[0],XkbNumKbdGroups*sizeof(GroupCompatInfo));
+ info->leds= (LEDInfo *)ClearCommonInfo(&info->leds->defs);
+ /* 3/30/94 (ef) -- XXX! Should free action info here */
+ ClearVModInfo(&info->vmods,xkb);
+ return;
+}
+
+static SymInterpInfo *
+#if NeedFunctionPrototypes
+NextInterp(CompatInfo *info)
+#else
+NextInterp(info)
+ CompatInfo * info;
+#endif
+{
+SymInterpInfo * si;
+
+ si= uTypedAlloc(SymInterpInfo);
+ if (si) {
+ bzero((char *)si,sizeof(SymInterpInfo));
+ info->interps= (SymInterpInfo *)AddCommonInfo(&info->interps->defs,
+ (CommonInfo *)si);
+ info->nInterps++;
+ }
+ return si;
+}
+
+static SymInterpInfo *
+#if NeedFunctionPrototypes
+FindMatchingInterp(CompatInfo *info,SymInterpInfo *new)
+#else
+FindMatchingInterp(info,new)
+ CompatInfo * info;
+ SymInterpInfo * new;
+#endif
+{
+SymInterpInfo * old;
+
+ for (old= info->interps;old!=NULL;old=(SymInterpInfo *)old->defs.next) {
+ if ((old->interp.sym==new->interp.sym)&&
+ (old->interp.mods==new->interp.mods)&&
+ (old->interp.match==new->interp.match)) {
+ return old;
+ }
+ }
+ return NULL;
+}
+
+static Bool
+#if NeedFunctionPrototypes
+AddInterp(CompatInfo *info,SymInterpInfo *new)
+#else
+AddInterp(info,new)
+ CompatInfo * info;
+ SymInterpInfo * new;
+#endif
+{
+unsigned collide;
+SymInterpInfo * old;
+
+ collide= 0;
+ old= FindMatchingInterp(info,new);
+ if (old!=NULL) {
+ if (new->defs.merge==MergeReplace) {
+ SymInterpInfo *next= (SymInterpInfo *)old->defs.next;
+ if (((old->defs.fileID==new->defs.fileID)&&(warningLevel>0))||
+ (warningLevel>9)) {
+ WARN1("Multiple definitions for \"%s\"\n",siText(new,info));
+ ACTION("Earlier interpretation ignored\n");
+ }
+ *old= *new;
+ old->defs.next= &next->defs;
+ return True;
+ }
+ if (UseNewField(_SI_VirtualMod,&old->defs,&new->defs,&collide)) {
+ old->interp.virtual_mod= new->interp.virtual_mod;
+ old->defs.defined|= _SI_VirtualMod;
+ }
+ if (UseNewField(_SI_Action,&old->defs,&new->defs,&collide)) {
+ old->interp.act= new->interp.act;
+ old->defs.defined|= _SI_Action;
+ }
+ if (UseNewField(_SI_AutoRepeat,&old->defs,&new->defs,&collide)) {
+ old->interp.flags&= ~XkbSI_AutoRepeat;
+ old->interp.flags|= (new->interp.flags&XkbSI_AutoRepeat);
+ old->defs.defined|= _SI_AutoRepeat;
+ }
+ if (UseNewField(_SI_LockingKey,&old->defs,&new->defs,&collide)) {
+ old->interp.flags&= ~XkbSI_LockingKey;
+ old->interp.flags|= (new->interp.flags&XkbSI_LockingKey);
+ old->defs.defined|= _SI_LockingKey;
+ }
+ if (UseNewField(_SI_LevelOneOnly,&old->defs,&new->defs,&collide)) {
+ old->interp.match&= ~XkbSI_LevelOneOnly;
+ old->interp.match|= (new->interp.match&XkbSI_LevelOneOnly);
+ old->defs.defined|= _SI_LevelOneOnly;
+ }
+ if (collide) {
+ WARN1("Multiple interpretations of \"%s\"\n",siText(new,info));
+ ACTION1("Using %s definition for duplicate fields\n",
+ (new->defs.merge!=MergeAugment?"last":"first"));
+ }
+ return True;
+ }
+ old= new;
+ if ((new= NextInterp(info))==NULL)
+ return False;
+ *new= *old;
+ new->defs.next= NULL;
+ return True;
+}
+
+static Bool
+#if NeedFunctionPrototypes
+AddGroupCompat(CompatInfo *info,unsigned group,GroupCompatInfo *newGC)
+#else
+AddGroupCompat(info,group,newGC)
+ CompatInfo * info;
+ unsigned group;
+ GroupCompatInfo * newGC;
+#endif
+{
+GroupCompatInfo * gc;
+unsigned merge;
+
+ merge= newGC->merge;
+ gc= &info->groupCompat[group];
+ if ((gc->fileID<1)||
+ ((gc->real_mods==newGC->real_mods)&&(gc->vmods==newGC->vmods))) {
+ *gc= *newGC;
+ return True;
+ }
+ if (((gc->fileID==newGC->fileID)&&(warningLevel>0))||(warningLevel>9)) {
+ WARN1("Compat map for group %d redefined\n",group+1);
+ ACTION1("Using %s definition\n",(merge==MergeAugment?"old":"new"));
+ }
+ if (merge!=MergeAugment)
+ *gc= *newGC;
+ return True;
+}
+
+/***====================================================================***/
+
+static Bool
+#if NeedFunctionPrototypes
+ResolveStateAndPredicate( ExprDef * expr,
+ unsigned * pred_rtrn,
+ unsigned * mods_rtrn,
+ CompatInfo * info)
+#else
+ResolveStateAndPredicate(expr,pred_rtrn,mods_rtrn,info)
+ ExprDef * expr;
+ unsigned * pred_rtrn;
+ unsigned * mods_rtrn;
+ CompatInfo * info;
+#endif
+{
+ExprResult result;
+
+ if (expr==NULL) {
+ *pred_rtrn= XkbSI_AnyOfOrNone;
+ *mods_rtrn= ~0;
+ return True;
+ }
+
+ *pred_rtrn= XkbSI_Exactly;
+ if (expr->op==ExprActionDecl) {
+ char *pred_txt= XkbAtomText(NULL,expr->value.action.name,XkbMessage);
+ if (uStrCaseCmp(pred_txt,"noneof")==0)
+ *pred_rtrn= XkbSI_NoneOf;
+ else if (uStrCaseCmp(pred_txt,"anyofornone")==0)
+ *pred_rtrn= XkbSI_AnyOfOrNone;
+ else if (uStrCaseCmp(pred_txt,"anyof")==0)
+ *pred_rtrn= XkbSI_AnyOf;
+ else if (uStrCaseCmp(pred_txt,"allof")==0)
+ *pred_rtrn= XkbSI_AllOf;
+ else if (uStrCaseCmp(pred_txt,"exactly")==0)
+ *pred_rtrn= XkbSI_Exactly;
+ else {
+ ERROR1("Illegal modifier predicate \"%s\"\n",pred_txt);
+ ACTION("Ignored\n");
+ return False;
+ }
+ expr= expr->value.action.args;
+ }
+ else if (expr->op==ExprIdent) {
+ char *pred_txt= XkbAtomText(NULL,expr->value.str,XkbMessage);
+ if ((pred_txt)&&(uStrCaseCmp(pred_txt,"any")==0)) {
+ *pred_rtrn= XkbSI_AnyOf;
+ *mods_rtrn= 0xff;
+ return True;
+ }
+ }
+
+ if (ExprResolveModMask(expr,&result,NULL,NULL)) {
+ *mods_rtrn= result.uval;
+ return True;
+ }
+ return False;
+}
+
+/***====================================================================***/
+
+static void
+#if NeedFunctionPrototypes
+MergeIncludedCompatMaps( CompatInfo * into,
+ CompatInfo * from,
+ unsigned merge)
+#else
+MergeIncludedCompatMaps(into,from,merge)
+ CompatInfo * into;
+ CompatInfo * from;
+ unsigned merge;
+#endif
+{
+SymInterpInfo * si;
+LEDInfo * led,*rtrn,*next;
+GroupCompatInfo * gcm;
+register int i;
+
+ if (from->errorCount>0) {
+ into->errorCount+= from->errorCount;
+ return;
+ }
+ if (into->name==NULL) {
+ into->name= from->name;
+ from->name= NULL;
+ }
+ for (si=from->interps;si;si=(SymInterpInfo *)si->defs.next) {
+ if (merge!=MergeDefault)
+ si->defs.merge= merge;
+ if (!AddInterp(into,si))
+ into->errorCount++;
+ }
+ for (i=0,gcm=&from->groupCompat[0];i<XkbNumKbdGroups;i++,gcm++) {
+ if (merge!=MergeDefault)
+ gcm->merge= merge;
+ if (!AddGroupCompat(into,i,gcm))
+ into->errorCount++;
+ }
+ for (led=from->leds;led!=NULL;led=next) {
+ next= (LEDInfo *)led->defs.next;
+ if (merge!=MergeDefault)
+ led->defs.merge= merge;
+ rtrn= AddIndicatorMap(into->leds,led);
+ if (rtrn!=NULL)
+ into->leds= rtrn;
+ else into->errorCount++;
+ }
+ return;
+}
+
+typedef void (*FileHandler)(
+#if NeedFunctionPrototypes
+ XkbFile * /* rtrn */,
+ XkbDescPtr /* xkb */,
+ unsigned /* merge */,
+ CompatInfo * /* info */
+#endif
+);
+
+static Bool
+#if NeedFunctionPrototypes
+HandleIncludeCompatMap( IncludeStmt * stmt,
+ XkbDescPtr xkb,
+ CompatInfo * info,
+ FileHandler hndlr)
+#else
+HandleIncludeCompatMap(stmt,xkb,info,hndlr)
+ IncludeStmt * stmt;
+ XkbDescPtr xkb;
+ CompatInfo * info;
+ FileHandler hndlr;
+#endif
+{
+unsigned newMerge;
+XkbFile * rtrn;
+CompatInfo included;
+Bool haveSelf;
+
+ haveSelf= False;
+ if ((stmt->file==NULL)&&(stmt->map==NULL)) {
+ haveSelf= True;
+ included= *info;
+ bzero(info,sizeof(CompatInfo));
+ }
+ else if (ProcessIncludeFile(stmt,XkmCompatMapIndex,&rtrn,&newMerge)) {
+ InitCompatInfo(&included,xkb);
+ included.fileID= rtrn->id;
+ included.dflt= info->dflt;
+ included.dflt.defs.fileID= rtrn->id;
+ included.dflt.defs.merge= newMerge;
+ included.ledDflt.defs.fileID= rtrn->id;
+ included.ledDflt.defs.merge= newMerge;
+ included.act= info->act;
+ (*hndlr)(rtrn,xkb,MergeOverride,&included);
+ if (stmt->stmt!=NULL) {
+ if (included.name!=NULL)
+ uFree(included.name);
+ included.name= stmt->stmt;
+ stmt->stmt= NULL;
+ }
+ }
+ else {
+ info->errorCount+= 10;
+ return False;
+ }
+ if ((stmt->next!=NULL)&&(included.errorCount<1)) {
+ IncludeStmt * next;
+ unsigned op;
+ CompatInfo next_incl;
+
+ for (next=stmt->next;next!=NULL;next=next->next) {
+ if ((next->file==NULL)&&(next->map==NULL)) {
+ haveSelf= True;
+ MergeIncludedCompatMaps(&included,info,next->merge);
+ ClearCompatInfo(info,xkb);
+ }
+ else if (ProcessIncludeFile(next,XkmCompatMapIndex,&rtrn,&op)) {
+ InitCompatInfo(&next_incl,xkb);
+ next_incl.fileID= rtrn->id;
+ next_incl.dflt= info->dflt;
+ next_incl.dflt.defs.fileID= rtrn->id;
+ next_incl.dflt.defs.merge= op;
+ next_incl.ledDflt.defs.fileID= rtrn->id;
+ next_incl.ledDflt.defs.merge= op;
+ next_incl.act= info->act;
+ (*hndlr)(rtrn,xkb,MergeOverride,&next_incl);
+ MergeIncludedCompatMaps(&included,&next_incl,op);
+ ClearCompatInfo(&next_incl,xkb);
+ }
+ else {
+ info->errorCount+= 10;
+ return False;
+ }
+ }
+ }
+ if (haveSelf)
+ *info= included;
+ else {
+ MergeIncludedCompatMaps(info,&included,newMerge);
+ ClearCompatInfo(&included,xkb);
+ }
+ return (info->errorCount==0);
+}
+
+static LookupEntry useModMapValues[] = {
+ { "levelone", 1 },
+ { "level1", 1 },
+ { "anylevel", 0 },
+ { "any", 0 },
+ { NULL, 0 }
+};
+
+static int
+#if NeedFunctionPrototypes
+SetInterpField( SymInterpInfo * si,
+ XkbDescPtr xkb,
+ char * field,
+ ExprDef * arrayNdx,
+ ExprDef * value,
+ CompatInfo * info)
+#else
+SetInterpField(si,xkb,field,arrayNdx,value,info)
+ SymInterpInfo * si;
+ XkbDescPtr xkb;
+ char * field;
+ ExprDef * arrayNdx;
+ ExprDef * value;
+ CompatInfo * info;
+#endif
+{
+int ok= 1;
+ExprResult tmp;
+
+ if (uStrCaseCmp(field,"action")==0) {
+ if (arrayNdx!=NULL)
+ return ReportSINotArray(si,field,info);
+ ok= HandleActionDef(value,xkb,&si->interp.act,si->defs.merge,info->act);
+ if (ok)
+ si->defs.defined|= _SI_Action;
+ }
+ else if ((uStrCaseCmp(field,"virtualmodifier")==0)||
+ (uStrCaseCmp(field,"virtualmod")==0)) {
+ if (arrayNdx!=NULL)
+ return ReportSINotArray(si,field,info);
+ ok= ResolveVirtualModifier(value,&tmp,&info->vmods);
+ if (ok) {
+ si->interp.virtual_mod= tmp.uval;
+ si->defs.defined|= _SI_VirtualMod;
+ }
+ else return ReportSIBadType(si,field,"virtual modifier",info);
+ }
+ else if (uStrCaseCmp(field,"repeat")==0) {
+ if (arrayNdx!=NULL)
+ return ReportSINotArray(si,field,info);
+ ok= ExprResolveBoolean(value,&tmp,NULL,NULL);
+ if (ok) {
+ if (tmp.uval) si->interp.flags|= XkbSI_AutoRepeat;
+ else si->interp.flags&= ~XkbSI_AutoRepeat;
+ si->defs.defined|= _SI_AutoRepeat;
+ }
+ else return ReportSIBadType(si,field,"boolean",info);
+ }
+ else if (uStrCaseCmp(field,"locking")==0) {
+ if (arrayNdx!=NULL)
+ return ReportSINotArray(si,field,info);
+ ok= ExprResolveBoolean(value,&tmp,NULL,NULL);
+ if (ok) {
+ if (tmp.uval) si->interp.flags|= XkbSI_LockingKey;
+ else si->interp.flags&= ~XkbSI_LockingKey;
+ si->defs.defined|= _SI_LockingKey;
+ }
+ else return ReportSIBadType(si,field,"boolean",info);
+ }
+ else if ((uStrCaseCmp(field,"usemodmap")==0)||
+ (uStrCaseCmp(field,"usemodmapmods")==0)) {
+ if (arrayNdx!=NULL)
+ return ReportSINotArray(si,field,info);
+ ok= ExprResolveEnum(value,&tmp,useModMapValues);
+ if (ok) {
+ if (tmp.uval) si->interp.match|= XkbSI_LevelOneOnly;
+ else si->interp.match&= ~XkbSI_LevelOneOnly;
+ si->defs.defined|= _SI_LevelOneOnly;
+ }
+ else return ReportSIBadType(si,field,"level specification",info);
+ }
+ else {
+ ok= ReportBadField("symbol interpretation",field,siText(si,info));
+ }
+ return ok;
+}
+
+LookupEntry groupNames[]= {
+ { "group1", 0x01 },
+ { "group2", 0x02 },
+ { "group3", 0x04 },
+ { "group4", 0x08 },
+ { "group5", 0x10 },
+ { "group6", 0x20 },
+ { "group7", 0x40 },
+ { "group8", 0x80 },
+ { "none", 0x00 },
+ { "all", 0xff },
+ { NULL, 0 }
+};
+
+static int
+#if NeedFunctionPrototypes
+HandleInterpVar(VarDef *stmt,XkbDescPtr xkb,CompatInfo *info)
+#else
+HandleInterpVar(stmt,xkb,info)
+ VarDef * stmt;
+ XkbDescPtr xkb;
+ CompatInfo * info;
+#endif
+{
+ExprResult elem,field;
+ExprDef * ndx;
+
+ if (ExprResolveLhs(stmt->name,&elem,&field,&ndx)==0)
+ return 0; /* internal error, already reported */
+ if (elem.str&&(uStrCaseCmp(elem.str,"interpret")==0))
+ return SetInterpField(&info->dflt,xkb,field.str,ndx,stmt->value,info);
+ if (elem.str&&(uStrCaseCmp(elem.str,"indicator")==0)) {
+ return SetIndicatorMapField(&info->ledDflt,xkb,field.str,ndx,
+ stmt->value);
+ }
+ return SetActionField(xkb,elem.str,field.str,ndx,stmt->value,&info->act);
+}
+
+static int
+#if NeedFunctionPrototypes
+HandleInterpBody(VarDef *def,XkbDescPtr xkb,SymInterpInfo *si,CompatInfo *info)
+#else
+HandleInterpBody(def,xkb,si,info)
+ VarDef * def;
+ XkbDescPtr xkb;
+ SymInterpInfo * si;
+ CompatInfo * info;
+#endif
+{
+int ok= 1;
+ExprResult tmp,field;
+ExprDef * arrayNdx;
+
+ for (;def!=NULL;def= (VarDef *)def->common.next) {
+ if ((def->name)&&(def->name->type==ExprFieldRef)) {
+ ok= HandleInterpVar(def,xkb,info);
+ continue;
+ }
+ ok= ExprResolveLhs(def->name,&tmp,&field,&arrayNdx);
+ if (ok)
+ ok= SetInterpField(si,xkb,field.str,arrayNdx,def->value,info);
+ }
+ return ok;
+}
+
+static int
+#if NeedFunctionPrototypes
+HandleInterpDef(InterpDef *def,XkbDescPtr xkb,unsigned merge,CompatInfo *info)
+#else
+HandleInterpDef(def,xkb,merge,info)
+ InterpDef * def;
+ XkbDescPtr xkb;
+ unsigned merge;
+ CompatInfo * info;
+#endif
+{
+unsigned pred,mods;
+SymInterpInfo si;
+
+ if (!ResolveStateAndPredicate(def->match,&pred,&mods,info)) {
+ ERROR("Couldn't determine matching modifiers\n");
+ ACTION("Symbol interpretation ignored\n");
+ return False;
+ }
+ if (def->merge!=MergeDefault)
+ merge= def->merge;
+
+ si= info->dflt;
+ si.defs.merge= merge;
+ si.interp.sym= def->sym;
+ si.interp.match= (si.interp.match&(~XkbSI_OpMask))|(pred&XkbSI_OpMask);
+ si.interp.mods= mods;
+ if (!HandleInterpBody(def->def,xkb,&si,info)) {
+ info->errorCount++;
+ return False;
+ }
+
+ if (!AddInterp(info,&si)) {
+ info->errorCount++;
+ return False;
+ }
+ return True;
+}
+
+static int
+#if NeedFunctionPrototypes
+HandleGroupCompatDef( GroupCompatDef * def,
+ XkbDescPtr xkb,
+ unsigned merge,
+ CompatInfo * info)
+#else
+HandleGroupCompatDef(def,xkb,merge,info)
+ GroupCompatDef * def;
+ XkbDescPtr xkb;
+ unsigned merge;
+ CompatInfo * info;
+#endif
+{
+ExprResult val;
+GroupCompatInfo tmp;
+
+ if (def->merge!=MergeDefault)
+ merge= def->merge;
+ if (!XkbIsLegalGroup(def->group-1)) {
+ ERROR1("Keyboard group must be in the range 1..%d\n",XkbNumKbdGroups+1);
+ ACTION1("Compatibility map for illegal group %d ignored\n",def->group);
+ return False;
+ }
+ tmp.fileID= info->fileID;
+ tmp.merge= merge;
+ if (!ExprResolveModMask(def->def,&val,LookupVModMask,(XPointer)xkb)) {
+ ERROR("Expected a modifier mask in group compatibility definition\n");
+ ACTION1("Ignoring illegal compatibility map for group %d\n",def->group);
+ return False;
+ }
+ tmp.real_mods= val.uval&0xff;
+ tmp.vmods= (val.uval>>8)&0xffff;
+ return AddGroupCompat(info,def->group-1,&tmp);
+}
+
+static void
+#if NeedFunctionPrototypes
+HandleCompatMapFile( XkbFile * file,
+ XkbDescPtr xkb,
+ unsigned merge,
+ CompatInfo * info)
+#else
+HandleCompatMapFile(file,xkb,merge,info)
+ XkbFile *file;
+ XkbDescPtr xkb;
+ unsigned merge;
+ CompatInfo *info;
+#endif
+{
+ParseCommon *stmt;
+
+ if (merge==MergeDefault)
+ merge= MergeAugment;
+ info->name= uStringDup(file->name);
+ stmt= file->defs;
+ while (stmt) {
+ switch (stmt->stmtType) {
+ case StmtInclude:
+ if (!HandleIncludeCompatMap((IncludeStmt *)stmt,xkb,info,
+ HandleCompatMapFile))
+ info->errorCount++;
+ break;
+ case StmtInterpDef:
+ if (!HandleInterpDef((InterpDef *)stmt,xkb,merge,info))
+ info->errorCount++;
+ break;
+ case StmtGroupCompatDef:
+ if (!HandleGroupCompatDef((GroupCompatDef*)stmt,xkb,merge,info))
+ info->errorCount++;
+ break;
+ case StmtIndicatorMapDef:
+ {
+ LEDInfo *rtrn;
+ rtrn= HandleIndicatorMapDef((IndicatorMapDef *)stmt,xkb,
+ &info->ledDflt,info->leds,
+ merge);
+ if (rtrn!=NULL)
+ info->leds= rtrn;
+ else info->errorCount++;
+ }
+ break;
+ case StmtVarDef:
+ if (!HandleInterpVar((VarDef *)stmt,xkb,info))
+ info->errorCount++;
+ break;
+ case StmtVModDef:
+ if (!HandleVModDef((VModDef *)stmt,merge,&info->vmods))
+ info->errorCount++;
+ break;
+ case StmtKeycodeDef:
+ ERROR("Interpretation files may not include other types\n");
+ ACTION("Ignoring definition of key name\n");
+ info->errorCount++;
+ break;
+ default:
+ WSGO1("Unexpected statement type %d in HandleCompatMapFile\n",
+ stmt->stmtType);
+ break;
+ }
+ stmt= stmt->next;
+ if (info->errorCount>10) {
+#ifdef NOISY
+ ERROR("Too many errors\n");
+#endif
+ ACTION1("Abandoning compatibility map \"%s\"\n",file->topName);
+ break;
+ }
+ }
+ return;
+}
+
+static void
+#if NeedFunctionPrototypes
+CopyInterps( CompatInfo * info,
+ XkbCompatMapPtr compat,
+ Bool needSymbol,
+ unsigned pred)
+#else
+CopyInterps(info,compat,needSymbol,pred)
+ CompatInfo * info;
+ XkbCompatMapPtr compat;
+ Bool needSymbol;
+ unsigned pred;
+#endif
+{
+SymInterpInfo * si;
+
+ for (si=info->interps;si;si=(SymInterpInfo *)si->defs.next) {
+ if (((si->interp.match&XkbSI_OpMask)!=pred)||
+ (needSymbol&&(si->interp.sym==NoSymbol))||
+ ((!needSymbol)&&(si->interp.sym!=NoSymbol)))
+ continue;
+ if (compat->num_si>=compat->size_si) {
+ WSGO("No room to merge symbol interpretations\n");
+ ACTION("Symbol interpretations lost\n");
+ return;
+ }
+ compat->sym_interpret[compat->num_si++]= si->interp;
+ }
+ return;
+}
+
+Bool
+#if NeedFunctionPrototypes
+CompileCompatMap( XkbFile * file,
+ XkbFileInfo * result,
+ unsigned merge,
+ LEDInfo ** unboundLEDs)
+#else
+CompileCompatMap(file,result,merge,unboundLEDs)
+ XkbFile * file;
+ XkbFileInfo * result;
+ unsigned merge;
+ LEDInfo ** unboundLEDs;
+#endif
+{
+int i;
+CompatInfo info;
+XkbDescPtr xkb;
+GroupCompatInfo * gcm;
+
+ xkb= result->xkb;
+ InitCompatInfo(&info,xkb);
+ info.dflt.defs.merge= merge;
+ info.ledDflt.defs.merge= merge;
+ HandleCompatMapFile(file,xkb,merge,&info);
+
+ if (info.errorCount==0) {
+ int size;
+ if (XkbAllocCompatMap(xkb,XkbAllCompatMask,info.nInterps)!=Success) {
+ WSGO("Couldn't allocate compatibility map\n");
+ ACTION("Exiting\n");
+ return False;
+ }
+ if (info.name!=NULL) {
+ if (XkbAllocNames(xkb,XkbCompatNameMask,0,0)==Success)
+ xkb->names->compat= XkbInternAtom(xkb->dpy,info.name,False);
+ else {
+ WSGO("Couldn't allocate space for compat name\n");
+ ACTION2("Name \"%s\" (from %s) NOT assigned\n",scanFile,
+ info.name);
+ }
+ }
+ size= info.nInterps*sizeof(XkbSymInterpretRec);
+ if (size>0) {
+ CopyInterps(&info,xkb->compat,True,XkbSI_Exactly);
+ CopyInterps(&info,xkb->compat,True,XkbSI_AllOf|XkbSI_NoneOf);
+ CopyInterps(&info,xkb->compat,True,XkbSI_AnyOf);
+ CopyInterps(&info,xkb->compat,True,XkbSI_AnyOfOrNone);
+ CopyInterps(&info,xkb->compat,False,XkbSI_Exactly);
+ CopyInterps(&info,xkb->compat,False,XkbSI_AllOf|XkbSI_NoneOf);
+ CopyInterps(&info,xkb->compat,False,XkbSI_AnyOf);
+ CopyInterps(&info,xkb->compat,False,XkbSI_AnyOfOrNone);
+ }
+ for (i=0,gcm=&info.groupCompat[0];i<XkbNumKbdGroups;i++,gcm++) {
+ if ((gcm->fileID!=0)||(gcm->real_mods!=0)||(gcm->vmods!=0)) {
+ xkb->compat->groups[i].mask= gcm->real_mods;
+ xkb->compat->groups[i].real_mods= gcm->real_mods;
+ xkb->compat->groups[i].vmods= gcm->vmods;
+ }
+ }
+ if (info.leds!=NULL) {
+ if (!CopyIndicatorMapDefs(result,info.leds,unboundLEDs))
+ info.errorCount++;
+ info.leds= NULL;
+ }
+ ClearCompatInfo(&info,xkb);
+ return True;
+ }
+ if (info.interps!=NULL)
+ uFree(info.interps);
+ return False;
+}
diff --git a/expr.c b/expr.c
new file mode 100644
index 0000000..0e1bded
--- /dev/null
+++ b/expr.c
@@ -0,0 +1,1106 @@
+/* $Xorg: expr.c,v 1.5 2000/08/17 19:54:30 cpqbld Exp $ */
+/************************************************************
+ 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
+ documentation, and that the name of Silicon Graphics not be
+ used in advertising or publicity pertaining to distribution
+ of the software without specific prior written permission.
+ Silicon Graphics makes no representation about the suitability
+ of this software for any purpose. It is provided "as is"
+ without any express or implied warranty.
+
+ SILICON GRAPHICS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS
+ SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+ AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL SILICON
+ 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
+ OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH
+ THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+ ********************************************************/
+
+#include "xkbcomp.h"
+#include "tokens.h"
+#include "expr.h"
+
+#include <ctype.h>
+
+/***====================================================================***/
+
+char *
+#if NeedFunctionPrototypes
+exprOpText(unsigned type)
+#else
+exprOpText(type)
+ unsigned type;
+#endif
+{
+static char buf[32];
+
+ switch (type) {
+ case ExprValue:
+ strcpy(buf,"literal");
+ break;
+ case ExprIdent:
+ strcpy(buf,"identifier");
+ break;
+ case ExprActionDecl:
+ strcpy(buf,"action declaration");
+ break;
+ case ExprFieldRef:
+ strcpy(buf,"field reference");
+ break;
+ case ExprArrayRef:
+ strcpy(buf,"array reference");
+ break;
+ case ExprKeysymList:
+ strcpy(buf,"list of keysyms");
+ break;
+ case ExprActionList:
+ strcpy(buf,"list of actions");
+ break;
+ case OpAdd:
+ strcpy(buf,"addition");
+ break;
+ case OpSubtract:
+ strcpy(buf,"subtraction");
+ break;
+ case OpMultiply:
+ strcpy(buf,"multiplication");
+ break;
+ case OpDivide:
+ strcpy(buf,"division");
+ break;
+ case OpAssign:
+ strcpy(buf,"assignment");
+ break;
+ case OpNot:
+ strcpy(buf,"logical not");
+ break;
+ case OpNegate:
+ strcpy(buf,"arithmetic negation");
+ break;
+ case OpInvert:
+ strcpy(buf,"bitwise inversion");
+ break;
+ case OpUnaryPlus:
+ strcpy(buf,"plus sign");
+ break;
+ default:
+ sprintf(buf,"illegal(%d)",type);
+ break;
+ }
+ return buf;
+}
+
+char *
+#if NeedFunctionPrototypes
+exprTypeText(unsigned type)
+#else
+exprTypeText(type)
+ unsigned type;
+#endif
+{
+static char buf[20];
+
+ switch (type) {
+ case TypeUnknown:
+ strcpy(buf,"unknown");
+ break;
+ case TypeBoolean:
+ strcpy(buf,"boolean");
+ break;
+ case TypeInt:
+ strcpy(buf,"int");
+ break;
+ case TypeString:
+ strcpy(buf,"string");
+ break;
+ case TypeAction:
+ strcpy(buf,"action");
+ break;
+ case TypeKeyName:
+ strcpy(buf,"keyname");
+ break;
+ default:
+ sprintf(buf,"illegal(%d)",type);
+ break;
+ }
+ return buf;
+}
+
+int
+#if NeedFunctionPrototypes
+ExprResolveLhs( ExprDef * expr,
+ ExprResult * elem_rtrn,
+ ExprResult * field_rtrn,
+ ExprDef ** index_rtrn)
+#else
+ExprResolveLhs(expr,elem_rtrn,field_rtrn,index_rtrn)
+ ExprDef * expr;
+ ExprResult * elem_rtrn;
+ ExprResult * field_rtrn;
+ ExprDef ** index_rtrn;
+#endif
+{
+ switch (expr->op) {
+ case ExprIdent:
+ elem_rtrn->str= NULL;
+ field_rtrn->str= XkbAtomGetString(NULL,expr->value.str);
+ *index_rtrn= NULL;
+ return True;
+ case ExprFieldRef:
+ elem_rtrn->str= XkbAtomGetString(NULL,expr->value.field.element);
+ field_rtrn->str= XkbAtomGetString(NULL,expr->value.field.field);
+ *index_rtrn= NULL;
+ return True;
+ case ExprArrayRef:
+ elem_rtrn->str= XkbAtomGetString(NULL,expr->value.array.element);
+ field_rtrn->str= XkbAtomGetString(NULL,expr->value.array.field);
+ *index_rtrn= expr->value.array.entry;
+ return True;
+ }
+ WSGO1("Unexpected operator %d in ResolveLhs\n",expr->op);
+ return False;
+}
+
+Bool
+#if NeedFunctionPrototypes
+SimpleLookup( XPointer priv,
+ Atom elem,
+ Atom field,
+ unsigned type,
+ ExprResult * val_rtrn)
+#else
+SimpleLookup(priv,elem,field,type,val_rtrn)
+ XPointer priv;
+ Atom elem;
+ Atom field;
+ unsigned type;
+ ExprResult * val_rtrn;
+#endif
+{
+LookupEntry * entry;
+register char * str;
+
+ if ((priv==NULL)||
+ (field==None)||(elem!=None)||
+ ((type!=TypeInt)&&(type!=TypeFloat))) {
+ return False;
+ }
+ str= XkbAtomGetString(NULL,field);
+ for (entry=(LookupEntry *)priv;(entry!=NULL)&&(entry->name!=NULL);entry++) {
+ if (uStrCaseCmp(str,entry->name)==0) {
+ val_rtrn->uval= entry->result;
+ if (type==TypeFloat)
+ val_rtrn->uval*= XkbGeomPtsPerMM;
+ return True;
+ }
+ }
+ return False;
+}
+
+Bool
+#if NeedFunctionPrototypes
+RadioLookup( XPointer priv,
+ Atom elem,
+ Atom field,
+ unsigned type,
+ ExprResult * val_rtrn)
+#else
+RadioLookup(priv,elem,field,type,val_rtrn)
+ XPointer priv;
+ Atom elem;
+ Atom field;
+ unsigned type;
+ ExprResult * val_rtrn;
+#endif
+{
+register char * str;
+int rg;
+
+ if ((field==None)||(elem!=None)||(type!=TypeInt))
+ return False;
+ str= XkbAtomGetString(NULL,field);
+ if (str) {
+ if (uStrCasePrefix("group",str))
+ str+= strlen("group");
+ else if (uStrCasePrefix("radiogroup",str))
+ str+= strlen("radiogroup");
+ else if (uStrCasePrefix("rg",str))
+ str+= strlen("rg");
+ else if (!isdigit(str[0]))
+ str= NULL;
+ }
+ if ((!str)||(sscanf(str,"%i",&rg)<1)||(rg<1)||(rg>XkbMaxRadioGroups))
+ return False;
+ val_rtrn->uval= rg;
+ return True;
+}
+
+int
+#if NeedFunctionPrototypes
+TableLookup( XPointer priv,
+ Atom elem,
+ Atom field,
+ unsigned type,
+ ExprResult * val_rtrn)
+#else
+TableLookup(priv,elem,field,type,val_rtrn)
+ XPointer priv;
+ Atom elem;
+ Atom field;
+ unsigned type;
+ ExprResult * val_rtrn;
+#endif
+{
+LookupTable * tbl= (LookupTable *)priv;
+register char * str;
+
+ if ((priv==NULL)||(field==None)||(type!=TypeInt))
+ return False;
+ str= XkbAtomGetString(NULL,elem);
+ while (tbl) {
+ if (((str==NULL)&&(tbl->element==NULL))||
+ ((str!=NULL)&&(tbl->element!=NULL)&&
+ (uStrCaseCmp(str,tbl->element)==0))) {
+ break;
+ }
+ tbl= tbl->nextElement;
+ }
+ if (tbl==NULL) /* didn't find a matching element */
+ return False;
+ priv= (XPointer)tbl->entries;
+ return SimpleLookup(priv,(Atom)None,field,type,val_rtrn);
+}
+
+static LookupEntry modIndexNames[] = {
+ { "shift", ShiftMapIndex },
+ { "control", ControlMapIndex },
+ { "lock", LockMapIndex },
+ { "mod1", Mod1MapIndex },
+ { "mod2", Mod2MapIndex },
+ { "mod3", Mod3MapIndex },
+ { "mod4", Mod4MapIndex },
+ { "mod5", Mod5MapIndex },
+ { NULL, 0 }
+};
+
+int
+#if NeedFunctionPrototypes
+LookupModIndex( XPointer priv,
+ Atom elem,
+ Atom field,
+ unsigned type,
+ ExprResult * val_rtrn)
+#else
+LookupModIndex(priv,elem,field,type,val_rtrn)
+ XPointer priv;
+ Atom elem;
+ Atom field;
+ unsigned type;
+ ExprResult * val_rtrn;
+#endif
+{
+ return SimpleLookup((XPointer)modIndexNames,elem,field,type,val_rtrn);
+}
+
+int
+#if NeedFunctionPrototypes
+LookupModMask( XPointer priv,
+ Atom elem,
+ Atom field,
+ unsigned type,
+ ExprResult * val_rtrn)
+#else
+LookupModMask(priv,elem,field,type,val_rtrn)
+ XPointer priv;
+ Atom elem;
+ Atom field;
+ unsigned type;
+ ExprResult * val_rtrn;
+#endif
+{
+char *str;
+
+ if ((elem!=None)||(type!=TypeInt))
+ return False;
+ str= XkbAtomGetString(NULL,field);
+ if (str==NULL)
+ return False;
+ if (uStrCaseCmp(str,"all")==0)
+ val_rtrn->uval= 0xff;
+ else if (uStrCaseCmp(str,"none")==0)
+ val_rtrn->uval= 0;
+ else if (LookupModIndex(priv,elem,field,type,val_rtrn))
+ val_rtrn->uval= (1<<val_rtrn->uval);
+ else if (priv != NULL) {
+ LookupPriv *lpriv= (LookupPriv *)priv;
+ if ((lpriv->chain==NULL)||
+ (!(*lpriv->chain)(lpriv->chainPriv,elem,field,type,val_rtrn)))
+ return False;
+ }
+ else return False;
+ return True;
+}
+
+int
+#if NeedFunctionPrototypes
+ExprResolveModIndex( ExprDef * expr,
+ ExprResult * val_rtrn,
+ IdentLookupFunc lookup,
+ XPointer lookupPriv)
+#else
+ExprResolveModIndex(expr,val_rtrn,lookup,lookupPriv)
+ ExprDef * expr;
+ ExprResult * val_rtrn;
+ IdentLookupFunc lookup;
+ XPointer lookupPriv;
+#endif
+{
+int ok= 0;
+char *bogus= NULL;
+
+ switch (expr->op) {
+ case ExprValue:
+ if (expr->type!=TypeInt) {
+ ERROR1("Found constant of type %s where a modifier mask was expected\n",
+ exprTypeText(expr->type));
+ return False;
+ }
+ else if ((expr->value.ival>=XkbNumModifiers)||(expr->value.ival<0)){
+ ERROR2("Illegal modifier index (%d, must be 0..%d)\n",
+ expr->value.ival,XkbNumModifiers-1);
+ return False;
+ }
+ val_rtrn->ival= expr->value.ival;
+ return True;
+ case ExprIdent:
+ if (LookupModIndex(lookupPriv,(Atom)None,expr->value.str,
+ (unsigned)TypeInt,val_rtrn)) {
+ return True;
+ }
+ if (lookup) {
+ ok= (*lookup)(lookupPriv,
+ None,expr->value.str,
+ TypeInt,val_rtrn);
+ }
+ if (!ok)
+ ERROR1("Cannot determine modifier index for \"%s\"\n",
+ XkbAtomText(NULL,expr->value.str,XkbMessage));
+ break;
+ case ExprFieldRef:
+ bogus= "field reference";
+ break;
+ case ExprArrayRef:
+ bogus= "array reference";
+ break;
+ case ExprActionDecl:
+ bogus= "function";
+ break;
+ case OpAdd:
+ case OpSubtract:
+ case OpMultiply:
+ case OpDivide:
+ case OpInvert:
+ case OpNegate:
+ case OpNot:
+ case OpUnaryPlus:
+ bogus= "arithmetic operations";
+ break;
+ case OpAssign:
+ bogus= "assignment";
+ break;
+ default:
+ WSGO1("Unknown operator %d in ResolveModIndex\n",expr->op);
+ return False;
+ }
+ if (bogus) {
+ ERROR1("Modifier index must be a name or number, %s ignored\n",bogus);
+ return False;
+ }
+ return ok;
+}
+
+int
+#if NeedFunctionPrototypes
+ExprResolveModMask( ExprDef * expr,
+ ExprResult * val_rtrn,
+ IdentLookupFunc lookup,
+ XPointer lookupPriv)
+#else
+ExprResolveModMask(expr,val_rtrn,lookup,lookupPriv)
+ ExprDef * expr;
+ ExprResult * val_rtrn;
+ IdentLookupFunc lookup;
+ XPointer lookupPriv;
+#endif
+{
+LookupPriv priv;
+
+ priv.priv= NULL;
+ priv.chain= lookup;
+ priv.chainPriv= lookupPriv;
+ return ExprResolveMask(expr,val_rtrn,LookupModMask,(XPointer)&priv);
+}
+
+int
+#if NeedFunctionPrototypes
+ExprResolveBoolean( ExprDef * expr,
+ ExprResult * val_rtrn,
+ IdentLookupFunc lookup,
+ XPointer lookupPriv)
+#else
+ExprResolveBoolean(expr,val_rtrn,lookup,lookupPriv)
+ ExprDef * expr;
+ ExprResult * val_rtrn;
+ IdentLookupFunc lookup;
+ XPointer lookupPriv;
+#endif
+{
+int ok= 0;
+char * bogus= NULL;
+
+ switch (expr->op) {
+ case ExprValue:
+ if (expr->type!=TypeBoolean) {
+ ERROR1("Found constant of type %s where boolean was expected\n",
+ exprTypeText(expr->type));
+ return False;
+ }
+ val_rtrn->ival= expr->value.ival;
+ return True;
+ case ExprIdent:
+ bogus= XkbAtomGetString(NULL,expr->value.str);
+ if (bogus) {
+ if ((uStrCaseCmp(bogus,"true")==0)||
+ (uStrCaseCmp(bogus,"yes")==0)||
+ (uStrCaseCmp(bogus,"on")==0)) {
+ val_rtrn->uval= 1;
+ return True;
+ }
+ else if ((uStrCaseCmp(bogus,"false")==0)||
+ (uStrCaseCmp(bogus,"no")==0)||
+ (uStrCaseCmp(bogus,"off")==0)) {
+ val_rtrn->uval= 0;
+ return True;
+ }
+ }
+ if (lookup) {
+ ok= (*lookup)(lookupPriv,
+ None,expr->value.str,
+ TypeBoolean,val_rtrn);
+ }
+ if (!ok)
+ ERROR1("Identifier \"%s\" of type int is unknown\n",
+ XkbAtomText(NULL,expr->value.str,XkbMessage));
+ return ok;
+ case ExprFieldRef:
+ if (lookup) {
+ ok= (*lookup)(lookupPriv,
+ expr->value.field.element,expr->value.field.field,
+ TypeBoolean,val_rtrn);
+ }
+ if (!ok)
+ ERROR2("Default \"%s.%s\" of type boolean is unknown\n",
+ XkbAtomText(NULL,expr->value.field.element,XkbMessage),
+ XkbAtomText(NULL,expr->value.field.field,XkbMessage));
+ return ok;
+ case OpInvert:
+ case OpNot:
+ ok= ExprResolveBoolean(expr,val_rtrn,lookup,lookupPriv);
+ if (ok)
+ val_rtrn->uval= !val_rtrn->uval;
+ return ok;
+ case OpAdd: if (bogus==NULL) bogus= "Addition";
+ case OpSubtract: if (bogus==NULL) bogus= "Subtraction";
+ case OpMultiply: if (bogus==NULL) bogus= "Multiplication";
+ case OpDivide: if (bogus==NULL) bogus= "Division";
+ case OpAssign: if (bogus==NULL) bogus= "Assignment";
+ case OpNegate: if (bogus==NULL) bogus= "Negation";
+ ERROR1("%s of boolean values not permitted\n",bogus);
+ break;
+ case OpUnaryPlus:
+ ERROR("Unary \"+\" operator not permitted for boolean values\n");
+ break;
+ default:
+ WSGO1("Unknown operator %d in ResolveBoolean\n",expr->op);
+ break;
+ }
+ return False;
+}
+
+int
+#if NeedFunctionPrototypes
+ExprResolveFloat( ExprDef * expr,
+ ExprResult * val_rtrn,
+ IdentLookupFunc lookup,
+ XPointer lookupPriv)
+#else
+ExprResolveFloat(expr,val_rtrn,lookup,lookupPriv)
+ ExprDef * expr;
+ ExprResult * val_rtrn;
+ IdentLookupFunc lookup;
+ XPointer lookupPriv;
+#endif
+{
+int ok= 0;
+ExprResult leftRtrn,rightRtrn;
+ExprDef *left,*right;
+
+ switch (expr->op) {
+ case ExprValue:
+ if (expr->type==TypeString) {
+ register char *str;
+ str= XkbAtomGetString(NULL,expr->value.str);
+ if ((str!=None)&&(strlen(str)==1)) {
+ val_rtrn->uval= str[0]*XkbGeomPtsPerMM;
+ return True;
+ }
+ }
+ if ((expr->type!=TypeInt)&&(expr->type!=TypeFloat)) {
+ ERROR1("Found constant of type %s, expected a number\n",
+ exprTypeText(expr->type));
+ return False;
+ }
+ val_rtrn->ival= expr->value.ival;
+ if (expr->type==TypeInt)
+ val_rtrn->ival*= XkbGeomPtsPerMM;
+ return True;
+ case ExprIdent:
+ if (lookup) {
+ ok= (*lookup)(lookupPriv,
+ None,expr->value.str,
+ TypeFloat,val_rtrn);
+ }
+ if (!ok)
+ ERROR1("Numeric identifier \"%s\" unknown\n",
+ XkbAtomText(NULL,expr->value.str,XkbMessage));
+ return ok;
+ case ExprFieldRef:
+ if (lookup) {
+ ok= (*lookup)(lookupPriv,
+ expr->value.field.element,expr->value.field.field,
+ TypeFloat,val_rtrn);
+ }
+ if (!ok)
+ ERROR2("Numeric default \"%s.%s\" unknown\n",
+ XkbAtomText(NULL,expr->value.field.element,XkbMessage),
+ XkbAtomText(NULL,expr->value.field.field,XkbMessage));
+ return ok;
+ case OpAdd:
+ case OpSubtract:
+ case OpMultiply:
+ case OpDivide:
+ left= expr->value.binary.left;
+ right= expr->value.binary.right;
+ if (ExprResolveFloat(left,&leftRtrn,lookup,lookupPriv)&&
+ ExprResolveFloat(right,&rightRtrn,lookup,lookupPriv)) {
+ switch (expr->op) {
+ case OpAdd:
+ val_rtrn->ival= leftRtrn.ival+rightRtrn.ival;
+ break;
+ case OpSubtract:
+ val_rtrn->ival= leftRtrn.ival-rightRtrn.ival;
+ break;
+ case OpMultiply:
+ val_rtrn->ival= leftRtrn.ival*rightRtrn.ival;
+ break;
+ case OpDivide:
+ val_rtrn->ival= leftRtrn.ival/rightRtrn.ival;
+ break;
+ }
+ return True;
+ }
+ return False;
+ case OpAssign:
+ WSGO("Assignment operator not implemented yet\n");
+ break;
+ case OpNot:
+ left= expr->value.child;
+ if (ExprResolveFloat(left,&leftRtrn,lookup,lookupPriv)) {
+ ERROR("The ! operator cannot be applied to a number\n");
+ }
+ return False;
+ case OpInvert:
+ case OpNegate:
+ left= expr->value.child;
+ if (ExprResolveFloat(left,&leftRtrn,lookup,lookupPriv)) {
+ if (expr->op==OpNegate)
+ val_rtrn->ival= -leftRtrn.ival;
+ else val_rtrn->ival= ~leftRtrn.ival;
+ return True;
+ }
+ return False;
+ case OpUnaryPlus:
+ left= expr->value.child;
+ return ExprResolveFloat(left,val_rtrn,lookup,lookupPriv);
+ default:
+ WSGO1("Unknown operator %d in ResolveFloat\n",expr->op);
+ break;
+ }
+ return False;
+}
+
+int
+#if NeedFunctionPrototypes
+ExprResolveInteger( ExprDef * expr,
+ ExprResult * val_rtrn,
+ IdentLookupFunc lookup,
+ XPointer lookupPriv)
+#else
+ExprResolveInteger(expr,val_rtrn,lookup,lookupPriv)
+ ExprDef * expr;
+ ExprResult * val_rtrn;
+ IdentLookupFunc lookup;
+ XPointer lookupPriv;
+#endif
+{
+int ok= 0;
+ExprResult leftRtrn,rightRtrn;
+ExprDef *left,*right;
+
+ switch (expr->op) {
+ case ExprValue:
+ if (expr->type==TypeString) {
+ register char *str;
+ str= XkbAtomGetString(NULL,expr->value.str);
+ if ((str!=None)&&(strlen(str)==1)) {
+ val_rtrn->uval= str[0];
+ return True;
+ }
+ }
+ if ((expr->type!=TypeInt)&&(expr->type!=TypeFloat)) {
+ ERROR1("Found constant of type %s where an int was expected\n",
+ exprTypeText(expr->type));
+ return False;
+ }
+ val_rtrn->ival= expr->value.ival;
+ if (expr->type==TypeFloat)
+ val_rtrn->ival/= XkbGeomPtsPerMM;
+ return True;
+ case ExprIdent:
+ if (lookup) {
+ ok= (*lookup)(lookupPriv,
+ None,expr->value.str,
+ TypeInt,val_rtrn);
+ }
+ if (!ok)
+ ERROR1("Identifier \"%s\" of type int is unknown\n",
+ XkbAtomText(NULL,expr->value.str,XkbMessage));
+ return ok;
+ case ExprFieldRef:
+ if (lookup) {
+ ok= (*lookup)(lookupPriv,
+ expr->value.field.element,expr->value.field.field,
+ TypeInt,val_rtrn);
+ }
+ if (!ok)
+ ERROR2("Default \"%s.%s\" of type int is unknown\n",
+ XkbAtomText(NULL,expr->value.field.element,XkbMessage),
+ XkbAtomText(NULL,expr->value.field.field,XkbMessage));
+ return ok;
+ case OpAdd:
+ case OpSubtract:
+ case OpMultiply:
+ case OpDivide:
+ left= expr->value.binary.left;
+ right= expr->value.binary.right;
+ if (ExprResolveInteger(left,&leftRtrn,lookup,lookupPriv)&&
+ ExprResolveInteger(right,&rightRtrn,lookup,lookupPriv)) {
+ switch (expr->op) {
+ case OpAdd:
+ val_rtrn->ival= leftRtrn.ival+rightRtrn.ival;
+ break;
+ case OpSubtract:
+ val_rtrn->ival= leftRtrn.ival-rightRtrn.ival;
+ break;
+ case OpMultiply:
+ val_rtrn->ival= leftRtrn.ival*rightRtrn.ival;
+ break;
+ case OpDivide:
+ val_rtrn->ival= leftRtrn.ival/rightRtrn.ival;
+ break;
+ }
+ return True;
+ }
+ return False;
+ case OpAssign:
+ WSGO("Assignment operator not implemented yet\n");
+ break;
+ case OpNot:
+ left= expr->value.child;
+ if (ExprResolveInteger(left,&leftRtrn,lookup,lookupPriv)) {
+ ERROR("The ! operator cannot be applied to an integer\n");
+ }
+ return False;
+ case OpInvert:
+ case OpNegate:
+ left= expr->value.child;
+ if (ExprResolveInteger(left,&leftRtrn,lookup,lookupPriv)) {
+ if (expr->op==OpNegate)
+ val_rtrn->ival= -leftRtrn.ival;
+ else val_rtrn->ival= ~leftRtrn.ival;
+ return True;
+ }
+ return False;
+ case OpUnaryPlus:
+ left= expr->value.child;
+ return ExprResolveInteger(left,val_rtrn,lookup,lookupPriv);
+ default:
+ WSGO1("Unknown operator %d in ResolveInteger\n",expr->op);
+ break;
+ }
+ return False;
+}
+
+int
+#if NeedFunctionPrototypes
+ExprResolveString( ExprDef * expr,
+ ExprResult * val_rtrn,
+ IdentLookupFunc lookup,
+ XPointer lookupPriv)
+#else
+ExprResolveString(expr,val_rtrn,lookup,lookupPriv)
+ ExprDef * expr;
+ ExprResult * val_rtrn;
+ IdentLookupFunc lookup;
+ XPointer lookupPriv;
+#endif
+{
+int ok= 0;
+ExprResult leftRtrn,rightRtrn;
+ExprDef * left;
+ExprDef * right;
+char * bogus= NULL;
+
+ switch (expr->op) {
+ case ExprValue:
+ if (expr->type!=TypeString) {
+ ERROR1("Found constant of type %s, expected a string\n",
+ exprTypeText(expr->type));
+ return False;
+ }
+ val_rtrn->str= XkbAtomGetString(NULL,expr->value.str);
+ if (val_rtrn->str==NULL) {
+ static char *empty= "";
+ val_rtrn->str= empty;
+ }
+ return True;
+ case ExprIdent:
+ if (lookup) {
+ ok= (*lookup)(lookupPriv,
+ None,expr->value.str,
+ TypeString,val_rtrn);
+ }
+ if (!ok)
+ ERROR1("Identifier \"%s\" of type string not found\n",
+ XkbAtomText(NULL,expr->value.str,XkbMessage));
+ return ok;
+ case ExprFieldRef:
+ if (lookup) {
+ ok= (*lookup)(lookupPriv,
+ expr->value.field.element,expr->value.field.field,
+ TypeString,val_rtrn);
+ }
+ if (!ok)
+ ERROR2("Default \"%s.%s\" of type string not found\n",
+ XkbAtomText(NULL,expr->value.field.element,XkbMessage),
+ XkbAtomText(NULL,expr->value.field.field,XkbMessage));
+ return ok;
+ case OpAdd:
+ left= expr->value.binary.left;
+ right= expr->value.binary.right;
+ if (ExprResolveString(left,&leftRtrn,lookup,lookupPriv)&&
+ ExprResolveString(right,&rightRtrn,lookup,lookupPriv)) {
+ int len;
+ char *new;
+ len= strlen(leftRtrn.str)+strlen(rightRtrn.str)+1;
+ new= (char *)uAlloc(len);
+ if (new) {
+ sprintf(new,"%s%s",leftRtrn.str,rightRtrn.str);
+ val_rtrn->str= new;
+ return True;
+ }
+ }
+ return False;
+ case OpSubtract: if (bogus==NULL) bogus= "Subtraction";
+ case OpMultiply: if (bogus==NULL) bogus= "Multiplication";
+ case OpDivide: if (bogus==NULL) bogus= "Division";
+ case OpAssign: if (bogus==NULL) bogus= "Assignment";
+ case OpNegate: if (bogus==NULL) bogus= "Negation";
+ case OpInvert: if (bogus==NULL) bogus= "Bitwise complement";
+ ERROR1("%s of string values not permitted\n",bogus);
+ return False;
+ case OpNot:
+ left= expr->value.child;
+ if (ExprResolveString(left,&leftRtrn,lookup,lookupPriv)) {
+ ERROR("The ! operator cannot be applied to a string\n");
+ }
+ return False;
+ case OpUnaryPlus:
+ left= expr->value.child;
+ if (ExprResolveString(left,&leftRtrn,lookup,lookupPriv)) {
+ ERROR("The + operator cannot be applied to a string\n");
+ }
+ return False;
+ default:
+ WSGO1("Unknown operator %d in ResolveString\n",expr->op);
+ break;
+ }
+ return False;
+}
+
+int
+#if NeedFunctionPrototypes
+ExprResolveKeyName( ExprDef * expr,
+ ExprResult * val_rtrn,
+ IdentLookupFunc lookup,
+ XPointer lookupPriv)
+#else
+ExprResolveKeyName(expr,val_rtrn,lookup,lookupPriv)
+ ExprDef * expr;
+ ExprResult * val_rtrn;
+ IdentLookupFunc lookup;
+ XPointer lookupPriv;
+#endif
+{
+int ok= 0;
+ExprDef * left;
+ExprResult leftRtrn;
+char * bogus= NULL;
+
+ switch (expr->op) {
+ case ExprValue:
+ if (expr->type!=TypeKeyName) {
+ ERROR1("Found constant of type %s, expected a key name\n",
+ exprTypeText(expr->type));
+ return False;
+ }
+ memcpy(val_rtrn->keyName.name,expr->value.keyName,XkbKeyNameLength);
+ return True;
+ case ExprIdent:
+ if (lookup) {
+ ok= (*lookup)(lookupPriv,
+ None,expr->value.str,
+ TypeString,val_rtrn);
+ }
+ if (!ok)
+ ERROR1("Identifier \"%s\" of type string not found\n",
+ XkbAtomText(NULL,expr->value.str,XkbMessage));
+ return ok;
+ case ExprFieldRef:
+ if (lookup) {
+ ok= (*lookup)(lookupPriv,
+ expr->value.field.element,expr->value.field.field,
+ TypeString,val_rtrn);
+ }
+ if (!ok)
+ ERROR2("Default \"%s.%s\" of type key name not found\n",
+ XkbAtomText(NULL,expr->value.field.element,XkbMessage),
+ XkbAtomText(NULL,expr->value.field.field,XkbMessage));
+ return ok;
+ case OpAdd: if (bogus==NULL) bogus= "Addition";
+ case OpSubtract: if (bogus==NULL) bogus= "Subtraction";
+ case OpMultiply: if (bogus==NULL) bogus= "Multiplication";
+ case OpDivide: if (bogus==NULL) bogus= "Division";
+ case OpAssign: if (bogus==NULL) bogus= "Assignment";
+ case OpNegate: if (bogus==NULL) bogus= "Negation";
+ case OpInvert: if (bogus==NULL) bogus= "Bitwise complement";
+ ERROR1("%s of key name values not permitted\n",bogus);
+ return False;
+ case OpNot:
+ left= expr->value.binary.left;
+ if (ExprResolveString(left,&leftRtrn,lookup,lookupPriv)) {
+ ERROR("The ! operator cannot be applied to a key name\n");
+ }
+ return False;
+ case OpUnaryPlus:
+ left= expr->value.binary.left;
+ if (ExprResolveString(left,&leftRtrn,lookup,lookupPriv)) {
+ ERROR("The + operator cannot be applied to a key name\n");
+ }
+ return False;
+ default:
+ WSGO1("Unknown operator %d in ResolveKeyName\n",expr->op);
+ break;
+ }
+ return False;
+}
+
+/***====================================================================***/
+
+int
+#if NeedFunctionPrototypes
+ExprResolveEnum(ExprDef *expr,ExprResult *val_rtrn,LookupEntry *values)
+#else
+ExprResolveEnum(expr,val_rtrn,values)
+ ExprDef * expr;
+ ExprResult * val_rtrn;
+ LookupEntry * values;
+#endif
+{
+ if (expr->op!=ExprIdent) {
+ ERROR1("Found a %s where an enumerated value was expected\n",
+ exprOpText(expr->op));
+ return False;
+ }
+ if (!SimpleLookup((XPointer)values,(Atom)None,expr->value.str,
+ (unsigned)TypeInt,val_rtrn)) {
+ int nOut=0;
+ ERROR1("Illegal identifier %s (expected one of: ",
+ XkbAtomText(NULL,expr->value.str,XkbMessage));
+ while (values && values->name) {
+ if (nOut!=0) INFO1(", %s",values->name);
+ else INFO1("%s",values->name);
+ }
+ INFO(")\n");
+ return False;
+ }
+ return True;
+}
+
+int
+#if NeedFunctionPrototypes
+ExprResolveMask( ExprDef * expr,
+ ExprResult * val_rtrn,
+ IdentLookupFunc lookup,
+ XPointer lookupPriv)
+#else
+ExprResolveMask(expr,val_rtrn,lookup,lookupPriv)
+ ExprDef * expr;
+ ExprResult * val_rtrn;
+ IdentLookupFunc lookup;
+ XPointer lookupPriv;
+#endif
+{
+int ok= 0;
+ExprResult leftRtrn,rightRtrn;
+ExprDef *left,*right;
+char * bogus= NULL;
+
+ switch (expr->op) {
+ case ExprValue:
+ if (expr->type!=TypeInt) {
+ ERROR1("Found constant of type %s where a mask was expected\n",
+ exprTypeText(expr->type));
+ return False;
+ }
+ val_rtrn->ival= expr->value.ival;
+ return True;
+ case ExprIdent:
+ if (lookup) {
+ ok= (*lookup)(lookupPriv,
+ None,expr->value.str,
+ TypeInt,val_rtrn);
+ }
+ if (!ok)
+ ERROR1("Identifier \"%s\" of type int is unknown\n",
+ XkbAtomText(NULL,expr->value.str,XkbMessage));
+ return ok;
+ case ExprFieldRef:
+ if (lookup) {
+ ok= (*lookup)(lookupPriv,
+ expr->value.field.element,expr->value.field.field,
+ TypeInt,val_rtrn);
+ }
+ if (!ok)
+ ERROR2("Default \"%s.%s\" of type int is unknown\n",
+ XkbAtomText(NULL,expr->value.field.element,XkbMessage),
+ XkbAtomText(NULL,expr->value.field.field,XkbMessage));
+ return ok;
+ case ExprArrayRef:
+ bogus= "array reference";
+ case ExprActionDecl:
+ if (bogus==NULL)
+ bogus= "function use";
+ ERROR1("Unexpected %s in mask expression\n",bogus);
+ ACTION("Expression ignored\n");
+ return False;
+ case OpAdd:
+ case OpSubtract:
+ case OpMultiply:
+ case OpDivide:
+ left= expr->value.binary.left;
+ right= expr->value.binary.right;
+ if (ExprResolveMask(left,&leftRtrn,lookup,lookupPriv)&&
+ ExprResolveMask(right,&rightRtrn,lookup,lookupPriv)) {
+ switch (expr->op) {
+ case OpAdd:
+ val_rtrn->ival= leftRtrn.ival|rightRtrn.ival;
+ break;
+ case OpSubtract:
+ val_rtrn->ival= leftRtrn.ival&(~rightRtrn.ival);
+ break;
+ case OpMultiply:
+ case OpDivide:
+ ERROR1("Cannot %s masks\n",
+ expr->op==OpDivide?"divide":"multiply");
+ ACTION("Illegal operation ignored\n");
+ return False;
+ }
+ return True;
+ }
+ return False;
+ case OpAssign:
+ WSGO("Assignment operator not implemented yet\n");
+ break;
+ case OpInvert:
+ left= expr->value.child;
+ if (ExprResolveInteger(left,&leftRtrn,lookup,lookupPriv)) {
+ val_rtrn->ival= ~leftRtrn.ival;
+ return True;
+ }
+ return False;
+ case OpUnaryPlus:
+ case OpNegate:
+ case OpNot:
+ left= expr->value.child;
+ if (ExprResolveInteger(left,&leftRtrn,lookup,lookupPriv)) {
+ ERROR1("The %s operator cannot be used with a mask\n",
+ (expr->op==OpNegate?"-":"!"));
+ }
+ return False;
+ default:
+ WSGO1("Unknown operator %d in ResolveMask\n",expr->op);
+ break;
+ }
+ return False;
+}
+
+int
+#if NeedFunctionPrototypes
+ExprResolveKeySym( ExprDef * expr,
+ ExprResult * val_rtrn,
+ IdentLookupFunc lookup,
+ XPointer lookupPriv)
+#else
+ExprResolveKeySym(expr,val_rtrn,lookup,lookupPriv)
+ ExprDef * expr;
+ ExprResult * val_rtrn;
+ IdentLookupFunc lookup;
+ XPointer lookupPriv;
+#endif
+{
+int ok= 0;
+KeySym sym;
+
+ if (expr->op==ExprIdent) {
+ char *str;
+ str= XkbAtomGetString(NULL,expr->value.str);
+ if ((str!=NULL)&&((sym= XStringToKeysym(str))!=NoSymbol)) {
+ val_rtrn->uval= sym;
+ return True;
+ }
+ }
+ ok= ExprResolveInteger(expr,val_rtrn,lookup,lookupPriv);
+ if ((ok)&&(val_rtrn->uval<10))
+ val_rtrn->uval+= '0';
+ return ok;
+}
diff --git a/expr.h b/expr.h
new file mode 100644
index 0000000..53263b8
--- /dev/null
+++ b/expr.h
@@ -0,0 +1,234 @@
+/* $Xorg: expr.h,v 1.3 2000/08/17 19:54:30 cpqbld Exp $ */
+/************************************************************
+ 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
+ documentation, and that the name of Silicon Graphics not be
+ used in advertising or publicity pertaining to distribution
+ of the software without specific prior written permission.
+ Silicon Graphics makes no representation about the suitability
+ of this software for any purpose. It is provided "as is"
+ without any express or implied warranty.
+
+ SILICON GRAPHICS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS
+ SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+ AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL SILICON
+ 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
+ OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH
+ THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+ ********************************************************/
+
+#ifndef EXPR_H
+#define EXPR_H 1
+
+typedef union _ExprResult {
+ char * str;
+ int ival;
+ unsigned uval;
+ XkbKeyNameRec keyName;
+} ExprResult;
+
+_XFUNCPROTOBEGIN
+
+typedef Bool (*IdentLookupFunc)(
+#if NeedFunctionPrototypes
+ XPointer /* priv */,
+ Atom /* elem */,
+ Atom /* field */,
+ unsigned /* type */,
+ ExprResult * /* val_rtrn */
+#endif
+);
+
+extern char *exprTypeText(
+#if NeedFunctionPrototypes
+ unsigned /* type */
+#endif
+);
+
+_XFUNCPROTOEND
+
+extern int ExprResolveLhs(
+#if NeedFunctionPrototypes
+ ExprDef * /* expr */,
+ ExprResult * /* elem_rtrn */,
+ ExprResult * /* field_rtrn */,
+ ExprDef ** /* index_rtrn */
+#endif
+);
+
+typedef struct _LookupPriv {
+ XPointer priv;
+ IdentLookupFunc chain;
+ XPointer chainPriv;
+} LookupPriv;
+
+typedef struct _LookupEntry {
+ char * name;
+ unsigned result;
+} LookupEntry;
+
+typedef struct _LookupTable {
+ char * element;
+ LookupEntry * entries;
+ struct _LookupTable * nextElement;
+} LookupTable;
+
+_XFUNCPROTOBEGIN
+
+
+extern char *exprOpText(
+#if NeedFunctionPrototypes
+ unsigned /* type */
+#endif
+);
+
+extern int RadioLookup(
+#if NeedFunctionPrototypes
+ XPointer /* priv */,
+ Atom /* elem */,
+ Atom /* field */,
+ unsigned /* type */,
+ ExprResult * /* val_rtrn */
+#endif
+);
+
+extern int SimpleLookup(
+#if NeedFunctionPrototypes
+ XPointer /* priv */,
+ Atom /* elem */,
+ Atom /* field */,
+ unsigned /* type */,
+ ExprResult * /* val_rtrn */
+#endif
+);
+
+extern int TableLookup(
+#if NeedFunctionPrototypes
+ XPointer /* priv */,
+ Atom /* elem */,
+ Atom /* field */,
+ unsigned /* type */,
+ ExprResult * /* val_rtrn */
+#endif
+);
+
+extern int LookupModIndex(
+#if NeedFunctionPrototypes
+ XPointer /* priv */,
+ Atom /* elem */,
+ Atom /* field */,
+ unsigned /* type */,
+ ExprResult * /* val_rtrn */
+#endif
+);
+
+extern int LookupModMask(
+#if NeedFunctionPrototypes
+ XPointer /* priv */,
+ Atom /* elem */,
+ Atom /* field */,
+ unsigned /* type */,
+ ExprResult * /* val_rtrn */
+#endif
+);
+
+extern int ExprResolveModIndex(
+#if NeedFunctionPrototypes
+ ExprDef * /* expr */,
+ ExprResult * /* val_rtrn */,
+ IdentLookupFunc /* lookup */,
+ XPointer /* lookupPriv */
+#endif
+);
+
+extern int ExprResolveModMask(
+#if NeedFunctionPrototypes
+ ExprDef * /* expr */,
+ ExprResult * /* val_rtrn */,
+ IdentLookupFunc /* lookup */,
+ XPointer /* priv */
+#endif
+);
+
+extern int ExprResolveBoolean(
+#if NeedFunctionPrototypes
+ ExprDef * /* expr */,
+ ExprResult * /* val_rtrn */,
+ IdentLookupFunc /* lookup */,
+ XPointer /* lookupPriv */
+#endif
+);
+
+extern int ExprResolveInteger(
+#if NeedFunctionPrototypes
+ ExprDef * /* expr */,
+ ExprResult * /* val_rtrn */,
+ IdentLookupFunc /* lookup */,
+ XPointer /* lookupPriv */
+#endif
+);
+
+extern int ExprResolveFloat(
+#if NeedFunctionPrototypes
+ ExprDef * /* expr */,
+ ExprResult * /* val_rtrn */,
+ IdentLookupFunc /* lookup */,
+ XPointer /* lookupPriv */
+#endif
+);
+
+extern int ExprResolveString(
+#if NeedFunctionPrototypes
+ ExprDef * /* expr */,
+ ExprResult * /* val_rtrn */,
+ IdentLookupFunc /* lookup */,
+ XPointer /* lookupPriv */
+#endif
+);
+
+extern int ExprResolveKeyName(
+#if NeedFunctionPrototypes
+ ExprDef * /* expr */,
+ ExprResult * /* val_rtrn */,
+ IdentLookupFunc /* lookup */,
+ XPointer /* lookupPriv */
+#endif
+);
+
+extern int ExprResolveEnum(
+#if NeedFunctionPrototypes
+ ExprDef * /* expr */,
+ ExprResult * /* val_rtrn */,
+ LookupEntry * /* values */
+#endif
+);
+
+extern int ExprResolveMask(
+#if NeedFunctionPrototypes
+ ExprDef * /* expr */,
+ ExprResult * /* val_rtrn */,
+ IdentLookupFunc /* lookup */,
+ XPointer /* lookupPriv */
+#endif
+);
+
+extern int ExprResolveKeySym(
+#if NeedFunctionPrototypes
+ ExprDef * /* expr */,
+ ExprResult * /* val_rtrn */,
+ IdentLookupFunc /* lookup */,
+ XPointer /* lookupPriv */
+#endif
+);
+
+_XFUNCPROTOEND
+
+#endif /* EXPR_H */
diff --git a/geometry.c b/geometry.c
new file mode 100644
index 0000000..3e84a96
--- /dev/null
+++ b/geometry.c
@@ -0,0 +1,3782 @@
+/* $Xorg: geometry.c,v 1.3 2000/08/17 19:54:30 cpqbld Exp $ */
+/************************************************************
+ 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
+ documentation, and that the name of Silicon Graphics not be
+ used in advertising or publicity pertaining to distribution
+ of the software without specific prior written permission.
+ Silicon Graphics makes no representation about the suitability
+ of this software for any purpose. It is provided "as is"
+ without any express or implied warranty.
+
+ SILICON GRAPHICS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS
+ SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+ AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL SILICON
+ 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
+ OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH
+ THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+ ********************************************************/
+
+#include "xkbcomp.h"
+#include "tokens.h"
+#include "expr.h"
+#include "vmod.h"
+#include "misc.h"
+#include "indicators.h"
+#include "action.h"
+#include "keycodes.h"
+#include "alias.h"
+
+#include "X11/extensions/XKBgeom.h"
+
+#define DFLT_FONT "helvetica"
+#define DFLT_SLANT "r"
+#define DFLT_WEIGHT "medium"
+#define DFLT_SET_WIDTH "normal"
+#define DFLT_VARIANT ""
+#define DFLT_ENCODING "iso8859-1"
+#define DFLT_SIZE 120
+
+typedef struct _PropertyInfo {
+ CommonInfo defs;
+ char * name;
+ char * value;
+} PropertyInfo;
+
+#define _GSh_Outlines (1<<1)
+#define _GSh_Approx (1<<2)
+#define _GSh_Primary (1<<3)
+typedef struct _ShapeInfo {
+ CommonInfo defs;
+ Atom name;
+ short index;
+ unsigned short nOutlines;
+ unsigned short szOutlines;
+ XkbOutlinePtr outlines;
+ XkbOutlinePtr approx;
+ XkbOutlinePtr primary;
+ int dfltCornerRadius;
+} ShapeInfo;
+
+#define shText(d,s) \
+ ((s)?XkbAtomText((d),(s)->name,XkbMessage):"default shape")
+
+#define _GD_Priority (1<<0)
+#define _GD_Top (1<<1)
+#define _GD_Left (1<<2)
+#define _GD_Angle (1<<3)
+#define _GD_Shape (1<<4)
+#define _GD_FontVariant (1<<4) /* CHEATING */
+#define _GD_Corner (1<<5)
+#define _GD_Width (1<<5) /* CHEATING */
+#define _GD_Color (1<<6)
+#define _GD_OffColor (1<<7)
+#define _GD_Height (1<<7) /* CHEATING */
+#define _GD_Text (1<<8)
+#define _GD_Font (1<<9)
+#define _GD_FontSlant (1<<10)
+#define _GD_FontWeight (1<<11)
+#define _GD_FontSetWidth (1<<12)
+#define _GD_FontSize (1<<13)
+#define _GD_FontEncoding (1<<14)
+#define _GD_FontSpec (1<<15)
+
+
+#define _GD_FontParts (_GD_Font|_GD_FontSlant|_GD_FontWeight|_GD_FontSetWidth|_GD_FontSize|_GD_FontEncoding|_GD_FontVariant)
+
+typedef struct _DoodadInfo {
+ CommonInfo defs;
+ Atom name;
+ unsigned char type;
+ unsigned char priority;
+ short top;
+ short left;
+ short angle;
+ unsigned short corner;
+ unsigned short width;
+ unsigned short height;
+ Atom shape;
+ Atom color;
+ Atom offColor;
+ Atom text;
+ Atom font;
+ Atom fontSlant;
+ Atom fontWeight;
+ Atom fontSetWidth;
+ Atom fontVariant;
+ unsigned short fontSize;
+ Atom fontEncoding;
+ Atom fontSpec;
+ char * logoName;
+ struct _SectionInfo *section;
+} DoodadInfo;
+
+#define Yes 1
+#define No 0
+#define Undefined -1
+
+#define _GK_Default (1<<0)
+#define _GK_Name (1<<1)
+#define _GK_Gap (1<<2)
+#define _GK_Shape (1<<3)
+#define _GK_Color (1<<4)
+typedef struct _KeyInfo {
+ CommonInfo defs;
+ char name[8];
+ short gap;
+ short index;
+ Atom shape;
+ Atom color;
+ struct _RowInfo * row;
+} KeyInfo;
+#define keyText(k) ((k)&&(k)->name[0]?(k)->name:"default")
+
+#define _GR_Default (1<<0)
+#define _GR_Vertical (1<<1)
+#define _GR_Top (1<<2)
+#define _GR_Left (1<<3)
+typedef struct _RowInfo {
+ CommonInfo defs;
+ unsigned short top;
+ unsigned short left;
+ short index;
+ Bool vertical;
+ unsigned short nKeys;
+ KeyInfo * keys;
+ KeyInfo dfltKey;
+ struct _SectionInfo *section;
+} RowInfo;
+#define rowText(d,r) \
+ ((r)?XkbAtomText((d),(r)->section->name,XkbMessage):"default")
+
+#define _GOK_UnknownRow -1
+typedef struct _OverlayKeyInfo {
+ CommonInfo defs;
+ short sectionRow;
+ short overlayRow;
+ char over[XkbKeyNameLength+1];
+ char under[XkbKeyNameLength+1];
+} OverlayKeyInfo;
+
+typedef struct _OverlayInfo {
+ CommonInfo defs;
+ Atom name;
+ unsigned short nRows;
+ unsigned short nKeys;
+ OverlayKeyInfo *keys;
+} OverlayInfo;
+#define oiText(d,o) ((o)?XkbAtomText((d),(o)->name,XkbMessage):"default")
+
+
+#define _GS_Default (1<<0)
+#define _GS_Name (1<<1)
+#define _GS_Top (1<<2)
+#define _GS_Left (1<<3)
+#define _GS_Width (1<<4)
+#define _GS_Height (1<<5)
+#define _GS_Angle (1<<6)
+#define _GS_Priority (1<<7)
+typedef struct _SectionInfo {
+ CommonInfo defs;
+ Atom name;
+ unsigned short top;
+ unsigned short left;
+ unsigned short width;
+ unsigned short height;
+ unsigned short angle;
+ unsigned short nRows;
+ unsigned short nDoodads;
+ unsigned short nOverlays;
+ unsigned char priority;
+ unsigned char nextDoodadPriority;
+ RowInfo * rows;
+ DoodadInfo * doodads;
+ RowInfo dfltRow;
+ DoodadInfo * dfltDoodads;
+ OverlayInfo * overlays;
+ struct _GeometryInfo *geometry;
+} SectionInfo;
+#define scText(d,s) ((s)?XkbAtomText((d),(s)->name,XkbMessage):"default")
+
+typedef struct _GeometryInfo {
+ char * name;
+ Display * dpy;
+ unsigned fileID;
+ unsigned merge;
+ int errorCount;
+ unsigned nextPriority;
+ int nProps;
+ int nShapes;
+ int nSections;
+ int nDoodads;
+ PropertyInfo * props;
+ ShapeInfo * shapes;
+ SectionInfo * sections;
+ DoodadInfo * doodads;
+ int widthMM;
+ int heightMM;
+ Atom font;
+ Atom fontSlant;
+ Atom fontWeight;
+ Atom fontSetWidth;
+ Atom fontVariant;
+ unsigned fontSize;
+ Atom fontEncoding;
+ Atom fontSpec;
+ Atom baseColor;
+ Atom labelColor;
+ int dfltCornerRadius;
+ SectionInfo dfltSection;
+ DoodadInfo * dfltDoodads;
+ AliasInfo * aliases;
+} GeometryInfo;
+
+static char *
+#if NeedFunctionPrototypes
+ddText(Display *dpy,DoodadInfo *di)
+#else
+ddText(dpy,di)
+ Display * dpy;
+ DoodadInfo * di;
+#endif
+{
+static char buf[64];
+
+ if (di==NULL) {
+ strcpy(buf,"default");
+ return buf;
+ }
+ if (di->section) {
+ sprintf(buf,"%s in section %s",XkbAtomText(dpy,di->name,XkbMessage),
+ scText(dpy,di->section));
+ return buf;
+ }
+ return XkbAtomText(dpy,di->name,XkbMessage);
+}
+
+/***====================================================================***/
+
+static void
+#if NeedFunctionPrototypes
+InitPropertyInfo(PropertyInfo *pi,GeometryInfo *info)
+#else
+InitPropertyInfo(pi,info)
+ PropertyInfo * pi;
+ GeometryInfo * info;
+#endif
+{
+ pi->defs.defined= 0;
+ pi->defs.fileID= info->fileID;
+ pi->defs.merge= info->merge;
+ pi->name= pi->value= NULL;
+ return;
+}
+
+static void
+#if NeedFunctionPrototypes
+FreeProperties(PropertyInfo *pi,GeometryInfo *info)
+#else
+FreeProperties(pi,info)
+ PropertyInfo * pi;
+ GeometryInfo * info;
+#endif
+{
+PropertyInfo * tmp;
+PropertyInfo * next;
+
+ if (info->props==pi) {
+ info->props= NULL;
+ info->nProps= 0;
+ }
+ for (tmp=pi;tmp!=NULL;tmp=next) {
+ if (pi->name)
+ uFree(pi->name);
+ if (pi->value)
+ uFree(pi->value);
+ pi->name= pi->value=NULL;
+ next= (PropertyInfo *)tmp->defs.next;
+ uFree(tmp);
+ }
+ return;
+}
+
+static void
+#if NeedFunctionPrototypes
+InitKeyInfo(KeyInfo *key,RowInfo *row,GeometryInfo *info)
+#else
+InitKeyInfo(key,row,info)
+ KeyInfo * key;
+ RowInfo * row;
+ GeometryInfo * info;
+#endif
+{
+
+ if (key!=&row->dfltKey) {
+ *key= row->dfltKey;
+ strcpy(key->name,"unknown");
+ key->defs.defined&= ~_GK_Default;
+ }
+ else {
+ bzero(key,sizeof(KeyInfo));
+ strcpy(key->name,"default");
+ key->defs.defined= _GK_Default;
+ key->defs.fileID= info->fileID;
+ key->defs.merge= info->merge;
+ key->defs.next= NULL;
+ key->row= row;
+ }
+ return;
+}
+
+static void
+#if NeedFunctionPrototypes
+ClearKeyInfo(KeyInfo *key)
+#else
+ClearKeyInfo(key)
+ KeyInfo * key;
+#endif
+{
+ key->defs.defined&= ~_GK_Default;
+ strcpy(key->name,"default");
+ key->gap= 0;
+ key->shape= None;
+ key->color= None;
+ return;
+}
+
+static void
+#if NeedFunctionPrototypes
+FreeKeys(KeyInfo *key,RowInfo *row,GeometryInfo *info)
+#else
+FreeKeys(key,row,info)
+ KeyInfo * key;
+ RowInfo * row;
+ GeometryInfo * info;
+#endif
+{
+KeyInfo * tmp;
+KeyInfo * next;
+
+ if (row->keys==key) {
+ row->nKeys= 0;
+ row->keys= NULL;
+ }
+ for (tmp=key;tmp!=NULL;tmp=next) {
+ ClearKeyInfo(tmp);
+ next= (KeyInfo *)tmp->defs.next;
+ uFree(tmp);
+ }
+ return;
+}
+
+static void
+#if NeedFunctionPrototypes
+InitRowInfo(RowInfo *row,SectionInfo *section,GeometryInfo *info)
+#else
+InitRowInfo(row,section,info)
+ RowInfo * row;
+ SectionInfo * section;
+ GeometryInfo * info;
+#endif
+{
+ if (row!= &section->dfltRow) {
+ *row= section->dfltRow;
+ row->defs.defined&= ~_GR_Default;
+ }
+ else {
+ bzero(row,sizeof(RowInfo *));
+ row->defs.defined= _GR_Default;
+ row->defs.fileID= info->fileID;
+ row->defs.merge= info->merge;
+ row->defs.next= NULL;
+ row->section= section;
+ row->nKeys= 0;
+ row->keys= NULL;
+ InitKeyInfo(&row->dfltKey,row,info);
+ }
+ return;
+}
+
+static void
+#if NeedFunctionPrototypes
+ClearRowInfo(RowInfo *row,GeometryInfo *info)
+#else
+ClearRowInfo(row,info)
+ RowInfo * row;
+ GeometryInfo * info;
+#endif
+{
+ row->defs.defined&= ~_GR_Default;
+ row->top= row->left= 0;
+ row->vertical= False;
+ row->nKeys= 0;
+ if (row->keys)
+ FreeKeys(row->keys,row,info);
+ ClearKeyInfo(&row->dfltKey);
+ row->dfltKey.defs.defined|= _GK_Default;
+ return;
+}
+
+static void
+#if NeedFunctionPrototypes
+FreeRows(RowInfo *row,SectionInfo *section,GeometryInfo *info)
+#else
+FreeRows(row,section,info)
+ RowInfo * row;
+ SectionInfo * section;
+ GeometryInfo * info;
+#endif
+{
+RowInfo * next;
+RowInfo * tmp;
+
+ if (row==section->rows) {
+ section->nRows= 0;
+ section->rows= NULL;
+ }
+ for (tmp=row;tmp!=NULL;tmp=next) {
+ ClearRowInfo(tmp,info);
+ next= (RowInfo *)tmp->defs.next;
+ uFree(tmp);
+ }
+ return;
+}
+
+static DoodadInfo *
+#if NeedFunctionPrototypes
+FindDoodadByType(DoodadInfo *di,unsigned type)
+#else
+FindDoodadByType(di,type)
+ DoodadInfo * di;
+ unsigned type;
+#endif
+{
+ while (di) {
+ if (di->type==type)
+ return di;
+ di= (DoodadInfo *)di->defs.next;
+ }
+ return NULL;
+}
+
+static DoodadInfo *
+#if NeedFunctionPrototypes
+FindDoodadByName(DoodadInfo *di,Atom name)
+#else
+FindDoodadByName(di,name)
+ DoodadInfo * di;
+ Atom name;
+#endif
+{
+ while (di) {
+ if (di->name==name)
+ return di;
+ di= (DoodadInfo *)di->defs.next;
+ }
+ return NULL;
+}
+
+static void
+#if NeedFunctionPrototypes
+InitDoodadInfo(DoodadInfo *di,unsigned type,SectionInfo *si,GeometryInfo *info)
+#else
+InitDoodadInfo(di,type,si,info)
+ DoodadInfo * di;
+ unsigned type;
+ SectionInfo * si;
+ GeometryInfo * info;
+#endif
+{
+DoodadInfo * dflt;
+
+ dflt= NULL;
+ if (si && si->dfltDoodads)
+ dflt= FindDoodadByType(si->dfltDoodads,type);
+ if ((dflt==NULL)&&(info->dfltDoodads))
+ dflt= FindDoodadByType(info->dfltDoodads,type);
+ if (dflt!=NULL) {
+ *di= *dflt;
+ di->defs.next= NULL;
+ }
+ else {
+ bzero(di,sizeof(DoodadInfo));
+ di->defs.fileID= info->fileID;
+ di->type= type;
+ }
+ di->section= si;
+ if (si!=NULL) {
+ di->priority= si->nextDoodadPriority++;
+ if (si->nextDoodadPriority>XkbGeomMaxPriority)
+ si->nextDoodadPriority= XkbGeomMaxPriority;
+ }
+ else {
+ di->priority= info->nextPriority++;
+ if (info->nextPriority>XkbGeomMaxPriority)
+ info->nextPriority= XkbGeomMaxPriority;
+ }
+ return;
+}
+
+static void
+#if NeedFunctionPrototypes
+ClearDoodadInfo(DoodadInfo *di)
+#else
+ClearDoodadInfo(di)
+ DoodadInfo * di;
+#endif
+{
+CommonInfo defs;
+
+ defs= di->defs;
+ bzero(di,sizeof(DoodadInfo));
+ di->defs= defs;
+ di->defs.defined= 0;
+ return;
+}
+
+static void
+#if NeedFunctionPrototypes
+ClearOverlayInfo(OverlayInfo *ol)
+#else
+ClearOverlayInfo(ol)
+ OverlayInfo * ol;
+#endif
+{
+ if (ol && ol->keys) {
+ ol->keys= (OverlayKeyInfo *)ClearCommonInfo(&ol->keys->defs);
+ ol->nKeys= 0;
+ }
+ return;
+}
+
+static void
+#if NeedFunctionPrototypes
+FreeDoodads(DoodadInfo *di,SectionInfo *si,GeometryInfo *info)
+#else
+FreeDoodads(di,si,info)
+ DoodadInfo * di;
+ SectionInfo * si;
+ GeometryInfo * info;
+#endif
+{
+DoodadInfo * tmp;
+DoodadInfo * next;
+
+ if (si) {
+ if (si->doodads==di) {
+ si->doodads= NULL;
+ si->nDoodads= 0;
+ }
+ if (si->dfltDoodads==di)
+ si->dfltDoodads= NULL;
+ }
+ if (info->doodads==di) {
+ info->doodads= NULL;
+ info->nDoodads= 0;
+ }
+ if (info->dfltDoodads==di)
+ info->dfltDoodads= NULL;
+ for (tmp=di;tmp!=NULL;tmp=next) {
+ next= (DoodadInfo *)tmp->defs.next;
+ ClearDoodadInfo(tmp);
+ uFree(tmp);
+ }
+ return;
+}
+
+static void
+#if NeedFunctionPrototypes
+InitSectionInfo(SectionInfo *si,GeometryInfo *info)
+#else
+InitSectionInfo(si,info)
+ SectionInfo * si;
+ GeometryInfo * info;
+#endif
+{
+ if (si!=&info->dfltSection) {
+ *si= info->dfltSection;
+ si->defs.defined&= ~_GS_Default;
+ si->name= XkbInternAtom(info->dpy,"unknown",False);
+ si->priority= info->nextPriority++;
+ if (info->nextPriority>XkbGeomMaxPriority)
+ info->nextPriority= XkbGeomMaxPriority;
+ }
+ else {
+ bzero(si,sizeof(SectionInfo));
+ si->defs.fileID= info->fileID;
+ si->defs.merge= info->merge;
+ si->defs.next= NULL;
+ si->geometry= info;
+ si->name= XkbInternAtom(info->dpy,"default",False);
+ InitRowInfo(&si->dfltRow,si,info);
+ }
+ return;
+}
+
+static void
+#if NeedFunctionPrototypes
+DupSectionInfo(SectionInfo *into,SectionInfo *from,GeometryInfo *info)
+#else
+DupSectionInfo(into,from,info)
+ SectionInfo * into;
+ SectionInfo * from;
+ GeometryInfo * info;
+#endif
+{
+CommonInfo defs;
+
+ defs= into->defs;
+ *into= *from;
+ into->defs.fileID= defs.fileID;
+ into->defs.merge= defs.merge;
+ into->defs.next= NULL;
+ into->dfltRow.defs.fileID= defs.fileID;
+ into->dfltRow.defs.merge= defs.merge;
+ into->dfltRow.defs.next= NULL;
+ into->dfltRow.section= into;
+ into->dfltRow.dfltKey.defs.fileID= defs.fileID;
+ into->dfltRow.dfltKey.defs.merge= defs.merge;
+ into->dfltRow.dfltKey.defs.next= NULL;
+ into->dfltRow.dfltKey.row= &into->dfltRow;
+ return;
+}
+
+static void
+#if NeedFunctionPrototypes
+ClearSectionInfo(SectionInfo *si,GeometryInfo *info)
+#else
+ClearSectionInfo(si,info)
+ SectionInfo * si;
+ GeometryInfo * info;
+#endif
+{
+
+ si->defs.defined&= ~_GS_Default;
+ si->name= XkbInternAtom(info->dpy,"default",False);
+ si->top= si->left= 0;
+ si->width= si->height= 0;
+ si->angle= 0;
+ if (si->rows) {
+ FreeRows(si->rows,si,info);
+ si->rows= NULL;
+ }
+ ClearRowInfo(&si->dfltRow,info);
+ if (si->doodads) {
+ FreeDoodads(si->doodads,si,info);
+ si->doodads= NULL;
+ }
+ si->dfltRow.defs.defined= _GR_Default;
+ return;
+}
+
+static void
+#if NeedFunctionPrototypes
+FreeSections(SectionInfo *si,GeometryInfo *info)
+#else
+FreeSections(si,info)
+ SectionInfo * si;
+ GeometryInfo * info;
+#endif
+{
+SectionInfo * tmp;
+SectionInfo * next;
+
+ if (si==info->sections) {
+ info->nSections= 0;
+ info->sections= NULL;
+ }
+ for (tmp=si;tmp!=NULL;tmp=next) {
+ ClearSectionInfo(tmp,info);
+ next= (SectionInfo *)tmp->defs.next;
+ uFree(tmp);
+ }
+ return;
+}
+
+static void
+#if NeedFunctionPrototypes
+FreeShapes(ShapeInfo *si,GeometryInfo *info)
+#else
+FreeShapes(si,info)
+ ShapeInfo * si;
+ GeometryInfo * info;
+#endif
+{
+ShapeInfo * tmp;
+ShapeInfo * next;
+
+ if (si==info->shapes) {
+ info->nShapes= 0;
+ info->shapes= NULL;
+ }
+ for (tmp=si;tmp!=NULL;tmp=next) {
+ if (tmp->outlines) {
+ register int i;
+ for (i=0;i<tmp->nOutlines;i++) {
+ if (tmp->outlines[i].points!=NULL) {
+ uFree(tmp->outlines[i].points);
+ tmp->outlines[i].num_points= 0;
+ tmp->outlines[i].points= NULL;
+ }
+ }
+ uFree(tmp->outlines);
+ tmp->szOutlines= 0;
+ tmp->nOutlines= 0;
+ tmp->outlines= NULL;
+ tmp->primary= tmp->approx=NULL;
+ }
+ next= (ShapeInfo *)tmp->defs.next;
+ uFree(tmp);
+ }
+ return;
+}
+
+/***====================================================================***/
+
+static void
+#if NeedFunctionPrototypes
+InitGeometryInfo(GeometryInfo *info,unsigned fileID,unsigned merge)
+#else
+InitGeometryInfo(info,fileID,merge)
+ GeometryInfo * info;
+ unsigned fileID;
+ unsigned merge;
+#endif
+{
+ bzero(info,sizeof(GeometryInfo));
+ info->fileID= fileID;
+ info->merge= merge;
+ InitSectionInfo(&info->dfltSection,info);
+ info->dfltSection.defs.defined= _GS_Default;
+ return;
+}
+
+static void
+#if NeedFunctionPrototypes
+ClearGeometryInfo(GeometryInfo *info)
+#else
+ClearGeometryInfo(info)
+ GeometryInfo * info;
+#endif
+{
+ if (info->name)
+ uFree(info->name);
+ info->name= NULL;
+ if (info->props)
+ FreeProperties(info->props,info);
+ if (info->shapes)
+ FreeShapes(info->shapes,info);
+ if (info->sections)
+ FreeSections(info->sections,info);
+ info->widthMM= 0;
+ info->heightMM= 0;
+ info->dfltCornerRadius= 0;
+ ClearSectionInfo(&info->dfltSection,info);
+ info->dfltSection.defs.defined= _GS_Default;
+ if (info->aliases)
+ ClearAliases(&info->aliases);
+ return;
+}
+
+/***====================================================================***/
+
+static PropertyInfo *
+#if NeedFunctionPrototypes
+NextProperty(GeometryInfo *info)
+#else
+NextProperty(info)
+ GeometryInfo * info;
+#endif
+{
+PropertyInfo * pi;
+
+ pi= uTypedAlloc(PropertyInfo);
+ if (pi) {
+ bzero((char *)pi,sizeof(PropertyInfo));
+ info->props= (PropertyInfo *)AddCommonInfo(&info->props->defs,
+ (CommonInfo *)pi);
+ info->nProps++;
+ }
+ return pi;
+}
+
+static PropertyInfo *
+#if NeedFunctionPrototypes
+FindProperty(GeometryInfo *info,char *name)
+#else
+FindProperty(info,name)
+ GeometryInfo * info;
+ char * name;
+#endif
+{
+PropertyInfo * old;
+
+ if (!name)
+ return NULL;
+ for (old= info->props;old!=NULL;old=(PropertyInfo *)old->defs.next) {
+ if ((old->name)&&(uStringEqual(name,old->name)))
+ return old;
+ }
+ return NULL;
+}
+
+static Bool
+#if NeedFunctionPrototypes
+AddProperty(GeometryInfo *info,PropertyInfo *new)
+#else
+AddProperty(info,new)
+ GeometryInfo * info;
+ PropertyInfo * new;
+#endif
+{
+PropertyInfo * old;
+
+ if ((!new)||(!new->value)||(!new->name))
+ return False;
+ old= FindProperty(info,new->name);
+ if (old!=NULL) {
+ if ((new->defs.merge==MergeReplace)||(new->defs.merge==MergeOverride)) {
+ if (((old->defs.fileID==new->defs.fileID)&&(warningLevel>0))||
+ (warningLevel>9)) {
+ WARN1("Multiple definitions for the \"%s\" property\n",
+ new->name);
+ ACTION2("Ignoring \"%s\", using \"%s\"\n",old->value,
+ new->value);
+ }
+ if (old->value)
+ uFree(old->value);
+ old->value= uStringDup(new->value);
+ return True;
+ }
+ if (((old->defs.fileID==new->defs.fileID)&&(warningLevel>0))||
+ (warningLevel>9)) {
+ WARN1("Multiple definitions for \"%s\" property\n",new->name);
+ ACTION2("Using \"%s\", ignoring \"%s\" \n",old->value,new->value);
+ }
+ return True;
+ }
+ old= new;
+ if ((new= NextProperty(info))==NULL)
+ return False;
+ new->defs.next= NULL;
+ new->name= uStringDup(old->name);
+ new->value= uStringDup(old->value);
+ return True;
+}
+
+/***====================================================================***/
+
+static ShapeInfo *
+#if NeedFunctionPrototypes
+NextShape(GeometryInfo *info)
+#else
+NextShape(info)
+ GeometryInfo * info;
+#endif
+{
+ShapeInfo * si;
+
+ si= uTypedAlloc(ShapeInfo);
+ if (si) {
+ bzero((char *)si,sizeof(ShapeInfo));
+ info->shapes= (ShapeInfo *)AddCommonInfo(&info->shapes->defs,
+ (CommonInfo *)si);
+ info->nShapes++;
+ si->dfltCornerRadius= info->dfltCornerRadius;
+ }
+ return si;
+}
+
+static ShapeInfo *
+#if NeedFunctionPrototypes
+FindShape(GeometryInfo *info,Atom name,char *type,char *which)
+#else
+FindShape(info,name,type,which)
+ GeometryInfo * info;
+ Atom name;
+ char * type;
+ char * which;
+#endif
+{
+ShapeInfo * old;
+
+ for (old= info->shapes;old!=NULL;old=(ShapeInfo *)old->defs.next) {
+ if (name==old->name)
+ return old;
+ }
+ if (type!=NULL) {
+ old= info->shapes;
+ WARN3("Unknown shape \"%s\" for %s %s\n",
+ XkbAtomText(info->dpy,name,XkbMessage),type,which);
+ if (old) {
+ ACTION1("Using default shape %s instead\n",shText(info->dpy,old));
+ return old;
+ }
+ ACTION("No default shape; definition ignored\n");
+ return NULL;
+ }
+ return NULL;
+}
+
+static Bool
+#if NeedFunctionPrototypes
+AddShape(GeometryInfo *info,ShapeInfo *new)
+#else
+AddShape(info,new)
+ GeometryInfo * info;
+ ShapeInfo * new;
+#endif
+{
+ShapeInfo * old;
+
+ old= FindShape(info,new->name,NULL,NULL);
+ if (old!=NULL) {
+ if ((new->defs.merge==MergeReplace)||(new->defs.merge==MergeOverride)) {
+ ShapeInfo *next= (ShapeInfo *)old->defs.next;
+ if (((old->defs.fileID==new->defs.fileID)&&(warningLevel>0))||
+ (warningLevel>9)) {
+ WARN1("Duplicate shape name \"%s\"\n",shText(info->dpy,old));
+ ACTION("Using last definition\n");
+ }
+ *old= *new;
+ old->defs.next= &next->defs;
+ return True;
+ }
+ if (((old->defs.fileID==new->defs.fileID)&&(warningLevel>0))||
+ (warningLevel>9)) {
+ WARN1("Multiple shapes named \"%s\"\n",shText(info->dpy,old));
+ ACTION("Using first definition\n");
+ }
+ return True;
+ }
+ old= new;
+ if ((new= NextShape(info))==NULL)
+ return False;
+ *new= *old;
+ new->defs.next= NULL;
+ old->szOutlines= old->nOutlines= 0;
+ old->outlines= NULL;
+ old->approx= NULL;
+ old->primary= NULL;
+ return True;
+}
+
+/***====================================================================***/
+
+static void
+#if NeedFunctionPrototypes
+ReplaceDoodad(DoodadInfo *into,DoodadInfo *from)
+#else
+ReplaceDoodad(into,from)
+ DoodadInfo * into;
+ DoodadInfo * from;
+#endif
+{
+CommonInfo * next;
+
+ next= into->defs.next;
+ ClearDoodadInfo(into);
+ *into= *from;
+ into->defs.next= next;
+ next= from->defs.next;
+ ClearDoodadInfo(from);
+ from->defs.next= next;
+ return;
+}
+
+static DoodadInfo *
+#if NeedFunctionPrototypes
+NextDfltDoodad(SectionInfo *si,GeometryInfo *info)
+#else
+NextDfltDoodad(si,info)
+ SectionInfo * si;
+ GeometryInfo * info;
+#endif
+{
+DoodadInfo * di;
+
+ di= uTypedCalloc(1,DoodadInfo);
+ if (!di)
+ return NULL;
+ if (si) {
+ si->dfltDoodads= (DoodadInfo *)AddCommonInfo(&si->dfltDoodads->defs,
+ (CommonInfo *)di);
+ }
+ else {
+ info->dfltDoodads= (DoodadInfo *)AddCommonInfo(&info->dfltDoodads->defs,
+ (CommonInfo *)di);
+ }
+ return di;
+}
+
+static DoodadInfo *
+#if NeedFunctionPrototypes
+NextDoodad(SectionInfo *si,GeometryInfo *info)
+#else
+NextDoodad(si,info)
+ SectionInfo * si;
+ GeometryInfo * info;
+#endif
+{
+DoodadInfo * di;
+
+ di= uTypedCalloc(1,DoodadInfo);
+ if (di) {
+ if (si) {
+ si->doodads= (DoodadInfo *)AddCommonInfo(&si->doodads->defs,
+ (CommonInfo *)di);
+ si->nDoodads++;
+ }
+ else {
+ info->doodads= (DoodadInfo *)AddCommonInfo(&info->doodads->defs,
+ (CommonInfo *)di);
+ info->nDoodads++;
+ }
+ }
+ return di;
+}
+
+static Bool
+#if NeedFunctionPrototypes
+AddDoodad(SectionInfo *si,GeometryInfo *info,DoodadInfo *new)
+#else
+AddDoodad(si,info,new)
+ SectionInfo * si;
+ GeometryInfo * info;
+ DoodadInfo * new;
+#endif
+{
+DoodadInfo * old;
+
+ old= FindDoodadByName((si?si->doodads:info->doodads),new->name);
+ if (old!=NULL) {
+ if ((new->defs.merge==MergeReplace)||(new->defs.merge==MergeOverride)) {
+ if (((old->defs.fileID==new->defs.fileID)&&(warningLevel>0))||
+ (warningLevel>9)) {
+ WARN1("Multiple doodads named \"%s\"\n",
+ XkbAtomText(info->dpy,old->name,XkbMessage));
+ ACTION("Using last definition\n");
+ }
+ ReplaceDoodad(old,new);
+ old->section= si;
+ return True;
+ }
+ if (((old->defs.fileID==new->defs.fileID)&&(warningLevel>0))||
+ (warningLevel>9)) {
+ WARN1("Multiple doodads named \"%s\"\n",
+ XkbAtomText(info->dpy,old->name,XkbMessage));
+ ACTION("Using first definition\n");
+ }
+ return True;
+ }
+ old= new;
+ if ((new= NextDoodad(si,info))==NULL)
+ return False;
+ ReplaceDoodad(new,old);
+ new->section= si;
+ new->defs.next= NULL;
+ return True;
+}
+
+static DoodadInfo *
+#if NeedFunctionPrototypes
+FindDfltDoodadByTypeName(char *name,SectionInfo *si,GeometryInfo *info)
+#else
+FindDfltDoodadByTypeName(name,si,info)
+ char * name;
+ SectionInfo * si;
+ GeometryInfo * info;
+#endif
+{
+DoodadInfo * dflt;
+unsigned type;
+
+ if (uStrCaseCmp(name,"outline")==0) type= XkbOutlineDoodad;
+ else if (uStrCaseCmp(name,"solid")==0) type= XkbSolidDoodad;
+ else if (uStrCaseCmp(name,"text")==0) type= XkbTextDoodad;
+ else if (uStrCaseCmp(name,"indicator")==0) type= XkbIndicatorDoodad;
+ else if (uStrCaseCmp(name,"logo")==0) type= XkbLogoDoodad;
+ else return NULL;
+ if ((si)&&(si->dfltDoodads))
+ dflt= FindDoodadByType(si->dfltDoodads,type);
+ else dflt= NULL;
+ if ((!dflt)&&(info->dfltDoodads))
+ dflt= FindDoodadByType(info->dfltDoodads,type);
+ if (dflt==NULL) {
+ dflt= NextDfltDoodad(si,info);
+ if (dflt!=NULL) {
+ dflt->name= None;
+ dflt->type= type;
+ }
+ }
+ return dflt;
+}
+
+/***====================================================================***/
+
+static Bool
+#if NeedFunctionPrototypes
+AddOverlay(SectionInfo *si,GeometryInfo *info,OverlayInfo *new)
+#else
+AddOverlay(si,info,new)
+ SectionInfo *si;
+ GeometryInfo *info;
+ OverlayInfo *new;
+#endif
+{
+OverlayInfo * old;
+
+ for (old=si->overlays;old!=NULL;old=(OverlayInfo *)old->defs.next) {
+ if (old->name==new->name)
+ break;
+ }
+ if (old!=NULL) {
+ if ((new->defs.merge==MergeReplace)||(new->defs.merge==MergeOverride)) {
+ if (((old->defs.fileID==new->defs.fileID)&&(warningLevel>0))||
+ (warningLevel>9)) {
+ WARN2("Multiple overlays named \"%s\" for section \"%s\"\n",
+ XkbAtomText(info->dpy,old->name,XkbMessage),
+ XkbAtomText(info->dpy,si->name,XkbMessage));
+ ACTION("Using last definition\n");
+ }
+ ClearOverlayInfo(old);
+ old->nKeys= new->nKeys;
+ old->keys= new->keys;
+ new->nKeys= 0;
+ new->keys= NULL;
+ return True;
+ }
+ if (((old->defs.fileID==new->defs.fileID)&&(warningLevel>0))||
+ (warningLevel>9)) {
+ WARN2("Multiple doodads named \"%s\" in section \"%s\"\n",
+ XkbAtomText(info->dpy,old->name,XkbMessage),
+ XkbAtomText(info->dpy,si->name,XkbMessage));
+ ACTION("Using first definition\n");
+ }
+ return True;
+ }
+ old= new;
+ new= uTypedCalloc(1,OverlayInfo);
+ if (!new) {
+ if (warningLevel>0) {
+ WSGO("Couldn't allocate a new OverlayInfo\n");
+ ACTION2("Overlay \"%s\" in section \"%s\" will be incomplete\n",
+ XkbAtomText(info->dpy,old->name,XkbMessage),
+ XkbAtomText(info->dpy,si->name,XkbMessage));
+ }
+ return False;
+ }
+ *new= *old;
+ old->nKeys= 0;
+ old->keys= NULL;
+ si->overlays= (OverlayInfo *)AddCommonInfo(&si->overlays->defs,
+ (CommonInfo *)new);
+ si->nOverlays++;
+ return True;
+}
+
+/***====================================================================***/
+
+static SectionInfo *
+#if NeedFunctionPrototypes
+NextSection(GeometryInfo *info)
+#else
+NextSection(info)
+ GeometryInfo * info;
+#endif
+{
+SectionInfo * si;
+
+ si= uTypedAlloc(SectionInfo);
+ if (si) {
+ *si= info->dfltSection;
+ si->defs.defined&= ~_GS_Default;
+ si->defs.next= NULL;
+ si->nRows= 0;
+ si->rows= NULL;
+ info->sections= (SectionInfo *)AddCommonInfo(&info->sections->defs,
+ (CommonInfo *)si);
+ info->nSections++;
+ }
+ return si;
+}
+
+static SectionInfo *
+#if NeedFunctionPrototypes
+FindMatchingSection(GeometryInfo *info,SectionInfo *new)
+#else
+FindMatchingSection(info,new)
+ GeometryInfo * info;
+ SectionInfo * new;
+#endif
+{
+SectionInfo * old;
+
+ for (old=info->sections;old!=NULL;old=(SectionInfo *)old->defs.next) {
+ if (new->name==old->name)
+ return old;
+ }
+ return NULL;
+}
+
+static Bool
+#if NeedFunctionPrototypes
+AddSection(GeometryInfo *info,SectionInfo *new)
+#else
+AddSection(info,new)
+ GeometryInfo * info;
+ SectionInfo * new;
+#endif
+{
+SectionInfo * old;
+
+ old= FindMatchingSection(info,new);
+ if (old!=NULL) {
+#ifdef NOTDEF
+ if ((new->defs.merge==MergeReplace)||(new->defs.merge==MergeOverride)) {
+ SectionInfo *next= (SectionInfo *)old->defs.next;
+ if (((old->defs.fileID==new->defs.fileID)&&(warningLevel>0))||
+ (warningLevel>9)) {
+ WARN1("Duplicate shape name \"%s\"\n",shText(info->dpy,old));
+ ACTION("Using last definition\n");
+ }
+ *old= *new;
+ old->defs.next= &next->defs;
+ return True;
+ }
+ if (((old->defs.fileID==new->defs.fileID)&&(warningLevel>0))||
+ (warningLevel>9)) {
+ WARN1("Multiple shapes named \"%s\"\n",shText(info->dpy,old));
+ ACTION("Using first definition\n");
+ }
+ return True;
+#else
+ WARN("Don't know how to merge sections yet\n");
+#endif
+ }
+ old= new;
+ if ((new= NextSection(info))==NULL)
+ return False;
+ *new= *old;
+ new->defs.next= NULL;
+ old->nRows= old->nDoodads= old->nOverlays= 0;
+ old->rows= NULL;
+ old->doodads= NULL;
+ old->overlays= NULL;
+ if (new->doodads) {
+ DoodadInfo *di;
+ for (di=new->doodads;di;di=(DoodadInfo *)di->defs.next) {
+ di->section= new;
+ }
+ }
+ return True;
+}
+
+/***====================================================================***/
+
+static RowInfo *
+#if NeedFunctionPrototypes
+NextRow(SectionInfo *si)
+#else
+NextRow(si)
+ SectionInfo * si;
+#endif
+{
+RowInfo * row;
+
+ row= uTypedAlloc(RowInfo);
+ if (row) {
+ *row= si->dfltRow;
+ row->defs.defined&= ~_GR_Default;
+ row->defs.next= NULL;
+ row->nKeys= 0;
+ row->keys= NULL;
+ si->rows= (RowInfo *)AddCommonInfo(&si->rows->defs,(CommonInfo *)row);
+ row->index= si->nRows++;
+ }
+ return row;
+}
+
+static Bool
+#if NeedFunctionPrototypes
+AddRow(SectionInfo *si,RowInfo *new)
+#else
+AddRow(si,new)
+ SectionInfo * si;
+ RowInfo * new;
+#endif
+{
+RowInfo * old;
+
+ old= new;
+ if ((new= NextRow(si))==NULL)
+ return False;
+ *new= *old;
+ new->defs.next= NULL;
+ old->nKeys= 0;
+ old->keys= NULL;
+ return True;
+}
+
+/***====================================================================***/
+
+static KeyInfo *
+#if NeedFunctionPrototypes
+NextKey(RowInfo *row)
+#else
+NextKey(row)
+ RowInfo * row;
+#endif
+{
+KeyInfo * key;
+
+ key= uTypedAlloc(KeyInfo);
+ if (key) {
+ *key= row->dfltKey;
+ key->defs.defined&= ~_GK_Default;
+ key->defs.next= NULL;
+ key->index= row->nKeys++;
+ }
+ return key;
+}
+
+static Bool
+#if NeedFunctionPrototypes
+AddKey(RowInfo *row,KeyInfo *new)
+#else
+AddKey(row,new)
+ RowInfo * row;
+ KeyInfo * new;
+#endif
+{
+KeyInfo * old;
+
+ old= new;
+ if ((new= NextKey(row))==NULL)
+ return False;
+ *new= *old;
+ new->defs.next= NULL;
+ row->keys= (KeyInfo *)AddCommonInfo(&row->keys->defs,(CommonInfo *)new);
+ return True;
+}
+
+/***====================================================================***/
+
+static void
+#if NeedFunctionPrototypes
+MergeIncludedGeometry(GeometryInfo *into,GeometryInfo *from,unsigned merge)
+#else
+MergeIncludedGeometry(into,from,merge)
+ GeometryInfo * into;
+ GeometryInfo * from;
+ unsigned merge;
+#endif
+{
+Bool clobber;
+
+ if (from->errorCount>0) {
+ into->errorCount+= from->errorCount;
+ return;
+ }
+ clobber= (merge==MergeOverride)||(merge==MergeReplace);
+ if (into->name==NULL) {
+ into->name= from->name;
+ from->name= NULL;
+ }
+ if ((into->widthMM==0)||((from->widthMM!=0)&&clobber))
+ into->widthMM= from->widthMM;
+ if ((into->heightMM==0)||((from->heightMM!=0)&&clobber))
+ into->heightMM= from->heightMM;
+ if ((into->font==None)||((from->font!=None)&&clobber))
+ into->font= from->font;
+ if ((into->fontSlant==None)||((from->fontSlant!=None)&&clobber))
+ into->fontSlant= from->fontSlant;
+ if ((into->fontWeight==None)||((from->fontWeight!=None)&&clobber))
+ into->fontWeight= from->fontWeight;
+ if ((into->fontSetWidth==None)||((from->fontSetWidth!=None)&&clobber))
+ into->fontSetWidth= from->fontSetWidth;
+ if ((into->fontVariant==None)||((from->fontVariant!=None)&&clobber))
+ into->fontVariant= from->fontVariant;
+ if ((into->fontSize==0)||((from->fontSize!=0)&&clobber))
+ into->fontSize= from->fontSize;
+ if ((into->fontEncoding==None)||((from->fontEncoding!=None)&&clobber))
+ into->fontEncoding= from->fontEncoding;
+ if ((into->fontSpec==None)||((from->fontSpec!=None)&&clobber))
+ into->fontSpec= from->fontSpec;
+ if ((into->baseColor==None)||((from->baseColor!=None)&&clobber))
+ into->baseColor= from->baseColor;
+ if ((into->labelColor==None)||((from->labelColor!=None)&&clobber))
+ into->labelColor= from->labelColor;
+ into->nextPriority= from->nextPriority;
+ if (from->props!=NULL) {
+ PropertyInfo *pi;
+ for (pi=from->props;pi;pi=(PropertyInfo *)pi->defs.next) {
+ if (!AddProperty(into,pi))
+ into->errorCount++;
+ }
+ }
+ if (from->shapes!=NULL) {
+ ShapeInfo * si;
+
+ for (si=from->shapes;si;si=(ShapeInfo *)si->defs.next) {
+ if (!AddShape(into,si))
+ into->errorCount++;
+ }
+ }
+ if (from->sections!=NULL) {
+ SectionInfo * si;
+
+ for (si=from->sections;si;si=(SectionInfo *)si->defs.next) {
+ if (!AddSection(into,si))
+ into->errorCount++;
+ }
+ }
+ if (from->doodads!=NULL) {
+ DoodadInfo * di;
+
+ for (di=from->doodads;di;di=(DoodadInfo *)di->defs.next) {
+ if (!AddDoodad(NULL,into,di))
+ into->errorCount++;
+ }
+ }
+ if (!MergeAliases(&into->aliases,&from->aliases,merge))
+ into->errorCount++;
+ return;
+}
+
+typedef void (*FileHandler)(
+#if NeedFunctionPrototypes
+ XkbFile * /* file */,
+ XkbDescPtr /* xkb */,
+ unsigned /* merge */,
+ GeometryInfo * /* info */
+#endif
+);
+
+static Bool
+#if NeedFunctionPrototypes
+HandleIncludeGeometry(IncludeStmt *stmt,XkbDescPtr xkb,GeometryInfo *info,
+ FileHandler hndlr)
+#else
+HandleIncludeGeometry(stmt,xkb,info,hndlr)
+ IncludeStmt * stmt;
+ XkbDescPtr xkb;
+ GeometryInfo * info;
+ FileHandler hndlr;
+#endif
+{
+unsigned newMerge;
+XkbFile * rtrn;
+GeometryInfo included;
+Bool haveSelf;
+
+ haveSelf= False;
+ if ((stmt->file==NULL)&&(stmt->map==NULL)) {
+ haveSelf= True;
+ included= *info;
+ bzero(info,sizeof(GeometryInfo));
+ }
+ else if (ProcessIncludeFile(stmt,XkmGeometryIndex,&rtrn,&newMerge)) {
+ InitGeometryInfo(&included,rtrn->id,newMerge);
+ included.nextPriority= info->nextPriority;
+ included.dfltCornerRadius= info->dfltCornerRadius;
+ DupSectionInfo(&included.dfltSection,&info->dfltSection,info);
+ (*hndlr)(rtrn,xkb,MergeOverride,&included);
+ if (stmt->stmt!=NULL) {
+ if (included.name!=NULL)
+ uFree(included.name);
+ included.name= stmt->stmt;
+ stmt->stmt= NULL;
+ }
+ }
+ else {
+ info->errorCount+= 10;
+ return False;
+ }
+ if ((stmt->next!=NULL)&&(included.errorCount<1)) {
+ IncludeStmt * next;
+ unsigned op;
+ GeometryInfo next_incl;
+
+ for (next=stmt->next;next!=NULL;next=next->next) {
+ if ((next->file==NULL)&&(next->map==NULL)) {
+ haveSelf= True;
+ MergeIncludedGeometry(&included,info,next->merge);
+ ClearGeometryInfo(info);
+ }
+ else if (ProcessIncludeFile(next,XkmGeometryIndex,&rtrn,&op)) {
+ InitGeometryInfo(&next_incl,rtrn->id,op);
+ next_incl.nextPriority= included.nextPriority;
+ next_incl.dfltCornerRadius= included.dfltCornerRadius;
+ DupSectionInfo(&next_incl.dfltSection,&included.dfltSection,
+ &included);
+ (*hndlr)(rtrn,xkb,MergeOverride,&next_incl);
+ MergeIncludedGeometry(&included,&next_incl,op);
+ ClearGeometryInfo(&next_incl);
+ }
+ else {
+ info->errorCount+= 10;
+ return False;
+ }
+ }
+ }
+ if (haveSelf)
+ *info= included;
+ else {
+ MergeIncludedGeometry(info,&included,newMerge);
+ ClearGeometryInfo(&included);
+ }
+ return (info->errorCount==0);
+}
+
+static int
+#if NeedFunctionPrototypes
+SetShapeField( ShapeInfo * si,
+ char * field,
+ ExprDef * arrayNdx,
+ ExprDef * value,
+ GeometryInfo * info)
+#else
+SetShapeField(si,field,arrayNdx,value,info)
+ ShapeInfo * si;
+ char * field;
+ ExprDef * arrayNdx;
+ ExprDef * value;
+ GeometryInfo * info;
+#endif
+{
+ExprResult tmp;
+
+ if ((uStrCaseCmp(field,"radius")==0)||(uStrCaseCmp(field,"corner")==0)||
+ (uStrCaseCmp(field,"cornerradius")==0)) {
+ if (arrayNdx!=NULL) {
+ info->errorCount++;
+ return ReportNotArray("key shape",field,shText(info->dpy,si));
+ }
+ if (!ExprResolveFloat(value,&tmp,NULL,NULL)) {
+ info->errorCount++;
+ return ReportBadType("key shape",field,
+ shText(info->dpy,si),"number");
+ }
+ if (si)
+ si->dfltCornerRadius= tmp.ival;
+ else info->dfltCornerRadius= tmp.ival;
+ return True;
+ }
+ info->errorCount++;
+ return ReportBadField("key shape",field,shText(info->dpy,si));
+}
+
+static int
+#if NeedFunctionPrototypes
+SetShapeDoodadField( DoodadInfo * di,
+ char * field,
+ ExprDef * arrayNdx,
+ ExprDef * value,
+ SectionInfo * si,
+ GeometryInfo * info)
+#else
+SetShapeDoodadField(di,field,arrayNdx,value,si,info)
+ DoodadInfo * di;
+ char * field;
+ ExprDef * arrayNdx;
+ ExprDef * value;
+ SectionInfo * si;
+ GeometryInfo * info;
+#endif
+{
+ExprResult tmp;
+char * typeName;
+
+ typeName= (di->type==XkbSolidDoodad?"solid doodad":"outline doodad");
+ if ((!uStrCaseCmp(field,"corner"))||(!uStrCaseCmp(field,"cornerradius"))) {
+ if (arrayNdx!=NULL) {
+ info->errorCount++;
+ return ReportNotArray(typeName,field,ddText(info->dpy,di));
+ }
+ if (!ExprResolveFloat(value,&tmp,NULL,NULL)) {
+ info->errorCount++;
+ return ReportBadType(typeName,field,ddText(info->dpy,di),"number");
+ }
+ di->defs.defined|= _GD_Corner;
+ di->corner= tmp.ival;
+ return True;
+ }
+ else if (uStrCaseCmp(field,"angle")==0) {
+ if (arrayNdx!=NULL) {
+ info->errorCount++;
+ return ReportNotArray(typeName,field,ddText(info->dpy,di));
+ }
+ if (!ExprResolveFloat(value,&tmp,NULL,NULL)) {
+ info->errorCount++;
+ return ReportBadType(typeName,field,ddText(info->dpy,di),"number");
+ }
+ di->defs.defined|= _GD_Angle;
+ di->angle= tmp.ival;
+ return True;
+ }
+ else if (uStrCaseCmp(field,"shape")==0) {
+ if (arrayNdx!=NULL) {
+ info->errorCount++;
+ return ReportNotArray(typeName,field,ddText(info->dpy,di));
+ }
+ if (!ExprResolveString(value,&tmp,NULL,NULL)) {
+ info->errorCount++;
+ return ReportBadType(typeName,field,ddText(info->dpy,di),"string");
+ }
+ di->shape= XkbInternAtom(info->dpy,tmp.str,False);
+ di->defs.defined|= _GD_Shape;
+ return True;
+ }
+ return ReportBadField(typeName,field,ddText(info->dpy,di));
+}
+
+#define FIELD_STRING 0
+#define FIELD_SHORT 1
+#define FIELD_USHORT 2
+
+static int
+#if NeedFunctionPrototypes
+SetTextDoodadField( DoodadInfo * di,
+ char * field,
+ ExprDef * arrayNdx,
+ ExprDef * value,
+ SectionInfo * si,
+ GeometryInfo * info)
+#else
+SetTextDoodadField(di,field,arrayNdx,value,si,info)
+ DoodadInfo * di;
+ char * field;
+ ExprDef * arrayNdx;
+ ExprDef * value;
+ SectionInfo * si;
+ GeometryInfo * info;
+#endif
+{
+ExprResult tmp;
+unsigned def;
+unsigned type;
+char * typeName= "text doodad";
+union {
+ Atom * str;
+ short * ival;
+ unsigned short * uval;
+} pField;
+
+ if (uStrCaseCmp(field,"angle")==0) {
+ if (arrayNdx!=NULL) {
+ info->errorCount++;
+ return ReportNotArray(typeName,field,ddText(info->dpy,di));
+ }
+ if (!ExprResolveFloat(value,&tmp,NULL,NULL)) {
+ info->errorCount++;
+ return ReportBadType(typeName,field,ddText(info->dpy,di),"number");
+ }
+ di->defs.defined|= _GD_Angle;
+ di->angle= tmp.ival;
+ return True;
+ }
+ if (uStrCaseCmp(field,"width")==0) {
+ type= FIELD_USHORT;
+ pField.uval= &di->width;
+ def= _GD_Width;
+ }
+ else if (uStrCaseCmp(field,"height")==0) {
+ type= FIELD_USHORT;
+ pField.uval= &di->height;
+ def= _GD_Height;
+ }
+ else if (uStrCaseCmp(field,"text")==0) {
+ type= FIELD_STRING;
+ pField.str= &di->text;
+ def= _GD_Text;
+ }
+ else if (uStrCaseCmp(field,"font")==0) {
+ type= FIELD_STRING;
+ pField.str= &di->font;
+ def= _GD_Font;
+ }
+ else if ((uStrCaseCmp(field,"fontslant")==0)||
+ (uStrCaseCmp(field,"slant")==0)) {
+ type= FIELD_STRING;
+ pField.str= &di->fontSlant;
+ def= _GD_FontSlant;
+ }
+ else if ((uStrCaseCmp(field,"fontweight")==0)||
+ (uStrCaseCmp(field,"weight")==0)) {
+ type= FIELD_STRING;
+ pField.str= &di->fontWeight;
+ def= _GD_FontWeight;
+ }
+ else if ((uStrCaseCmp(field,"fontwidth")==0)||
+ (uStrCaseCmp(field,"setwidth")==0)) {
+ type= FIELD_STRING;
+ pField.str= &di->fontSetWidth;
+ def= _GD_FontSetWidth;
+ }
+ else if ((uStrCaseCmp(field,"fontvariant")==0)||
+ (uStrCaseCmp(field,"variant")==0)) {
+ type= FIELD_STRING;
+ pField.str= &di->fontVariant;
+ def= _GD_FontVariant;
+ }
+ else if ((uStrCaseCmp(field,"fontencoding")==0)||
+ (uStrCaseCmp(field,"encoding")==0)) {
+ type= FIELD_STRING;
+ pField.str= &di->fontEncoding;
+ def= _GD_FontEncoding;
+ }
+ else if ((uStrCaseCmp(field,"xfont")==0)||
+ (uStrCaseCmp(field,"xfontname")==0)) {
+ type= FIELD_STRING;
+ pField.str= &di->fontSpec;
+ def= _GD_FontSpec;
+ }
+ else if (uStrCaseCmp(field,"fontsize")==0) {
+ type= FIELD_USHORT;
+ pField.uval= &di->fontSize;
+ def= _GD_FontSize;
+ }
+ else {
+ return ReportBadField(typeName,field,ddText(info->dpy,di));
+ }
+ if (arrayNdx!=NULL) {
+ info->errorCount++;
+ return ReportNotArray(typeName,field,ddText(info->dpy,di));
+ }
+ if (type==FIELD_STRING) {
+ if (!ExprResolveString(value,&tmp,NULL,NULL)) {
+ info->errorCount++;
+ return ReportBadType(typeName,field,ddText(info->dpy,di),
+ "string");
+ }
+ di->defs.defined|= def;
+ *pField.str= XkbInternAtom(NULL,tmp.str,False);
+ }
+ else {
+ if (!ExprResolveFloat(value,&tmp,NULL,NULL)) {
+ info->errorCount++;
+ return ReportBadType(typeName,field,ddText(info->dpy,di),"number");
+ }
+ if ((type==FIELD_USHORT)&&(tmp.ival<0)) {
+ info->errorCount++;
+ return
+ ReportBadType(typeName,field,ddText(info->dpy,di),"unsigned");
+ }
+ di->defs.defined|= def;
+ if (type==FIELD_USHORT)
+ *pField.uval= tmp.uval;
+ else *pField.ival= tmp.ival;
+ }
+ return True;
+}
+
+static int
+#if NeedFunctionPrototypes
+SetIndicatorDoodadField( DoodadInfo * di,
+ char * field,
+ ExprDef * arrayNdx,
+ ExprDef * value,
+ SectionInfo * si,
+ GeometryInfo * info)
+#else
+SetIndicatorDoodadField(di,field,arrayNdx,value,si,info)
+ DoodadInfo * di;
+ char * field;
+ ExprDef * arrayNdx;
+ ExprDef * value;
+ SectionInfo * si;
+ GeometryInfo * info;
+#endif
+{
+ExprResult tmp;
+
+ if ((uStrCaseCmp(field,"oncolor")==0)||(uStrCaseCmp(field,"offcolor")==0)
+ ||(uStrCaseCmp(field,"shape")==0)) {
+ if (arrayNdx!=NULL) {
+ info->errorCount++;
+ return ReportNotArray("indicator doodad",field,
+ ddText(info->dpy,di));
+ }
+ if (!ExprResolveString(value,&tmp,NULL,NULL)) {
+ info->errorCount++;
+ return ReportBadType("indicator doodad",field,ddText(info->dpy,di),
+ "string");
+ }
+ if (uStrCaseCmp(field,"oncolor")==0) {
+ di->defs.defined|= _GD_Color;
+ di->color= XkbInternAtom(NULL,tmp.str,False);
+ }
+ else if (uStrCaseCmp(field,"offcolor")==0) {
+ di->defs.defined|= _GD_OffColor;
+ di->offColor= XkbInternAtom(NULL,tmp.str,False);
+ }
+ else if (uStrCaseCmp(field,"shape")==0) {
+ di->defs.defined|= _GD_Shape;
+ di->shape= XkbInternAtom(info->dpy,tmp.str,False);
+ }
+ return True;
+ }
+ return ReportBadField("indicator doodad",field,ddText(info->dpy,di));
+}
+
+static int
+#if NeedFunctionPrototypes
+SetLogoDoodadField( DoodadInfo * di,
+ char * field,
+ ExprDef * arrayNdx,
+ ExprDef * value,
+ SectionInfo * si,
+ GeometryInfo * info)
+#else
+SetLogoDoodadField(di,field,arrayNdx,value,si,info)
+ DoodadInfo * di;
+ char * field;
+ ExprDef * arrayNdx;
+ ExprDef * value;
+ SectionInfo * si;
+ GeometryInfo * info;
+#endif
+{
+ExprResult tmp;
+char * typeName= "logo doodad";
+
+ if ((!uStrCaseCmp(field,"corner"))||(!uStrCaseCmp(field,"cornerradius"))) {
+ if (arrayNdx!=NULL) {
+ info->errorCount++;
+ return ReportNotArray(typeName,field,ddText(info->dpy,di));
+ }
+ if (!ExprResolveFloat(value,&tmp,NULL,NULL)) {
+ info->errorCount++;
+ return ReportBadType(typeName,field,ddText(info->dpy,di),"number");
+ }
+ di->defs.defined|= _GD_Corner;
+ di->corner= tmp.ival;
+ return True;
+ }
+ else if (uStrCaseCmp(field,"angle")==0) {
+ if (arrayNdx!=NULL) {
+ info->errorCount++;
+ return ReportNotArray(typeName,field,ddText(info->dpy,di));
+ }
+ if (!ExprResolveFloat(value,&tmp,NULL,NULL)) {
+ info->errorCount++;
+ return ReportBadType(typeName,field,ddText(info->dpy,di),"number");
+ }
+ di->defs.defined|= _GD_Angle;
+ di->angle= tmp.ival;
+ return True;
+ }
+ else if (uStrCaseCmp(field,"shape")==0) {
+ if (arrayNdx!=NULL) {
+ info->errorCount++;
+ return ReportNotArray(typeName,field,ddText(info->dpy,di));
+ }
+ if (!ExprResolveString(value,&tmp,NULL,NULL)) {
+ info->errorCount++;
+ return ReportBadType(typeName,field,ddText(info->dpy,di),"string");
+ }
+ di->shape= XkbInternAtom(info->dpy,tmp.str,False);
+ di->defs.defined|= _GD_Shape;
+ return True;
+ }
+ else if ((!uStrCaseCmp(field,"logoname"))||(!uStrCaseCmp(field,"name"))) {
+ if (arrayNdx!=NULL) {
+ info->errorCount++;
+ return ReportNotArray(typeName,field,ddText(info->dpy,di));
+ }
+ if (!ExprResolveString(value,&tmp,NULL,NULL)) {
+ info->errorCount++;
+ return ReportBadType(typeName,field,ddText(info->dpy,di),"string");
+ }
+ di->logoName= uStringDup(tmp.str);
+ return True;
+ }
+ return ReportBadField(typeName,field,ddText(info->dpy,di));
+}
+
+static int
+#if NeedFunctionPrototypes
+SetDoodadField( DoodadInfo * di,
+ char * field,
+ ExprDef * arrayNdx,
+ ExprDef * value,
+ SectionInfo * si,
+ GeometryInfo * info)
+#else
+SetDoodadField(di,field,arrayNdx,value,si,info)
+ DoodadInfo * di;
+ char * field;
+ ExprDef * arrayNdx;
+ ExprDef * value;
+ SectionInfo * si;
+ GeometryInfo * info;
+#endif
+{
+ExprResult tmp;
+
+ if (uStrCaseCmp(field,"priority")==0) {
+ if (arrayNdx!=NULL) {
+ info->errorCount++;
+ return ReportNotArray("doodad",field,ddText(info->dpy,di));
+ }
+ if (!ExprResolveInteger(value,&tmp,NULL,NULL)) {
+ info->errorCount++;
+ return ReportBadType("doodad",field,ddText(info->dpy,di),"integer");
+ }
+ if ((tmp.ival<0)||(tmp.ival>XkbGeomMaxPriority)) {
+ info->errorCount++;
+ ERROR2("Doodad priority %d out of range (must be 0..%d)\n",
+ tmp.ival,XkbGeomMaxPriority);
+ ACTION1("Priority for doodad %s not changed",ddText(info->dpy,di));
+ return False;
+ }
+ di->defs.defined|= _GD_Priority;
+ di->priority= tmp.ival;
+ return True;
+ }
+ else if (uStrCaseCmp(field,"left")==0) {
+ if (arrayNdx!=NULL) {
+ info->errorCount++;
+ return ReportNotArray("doodad",field,ddText(info->dpy,di));
+ }
+ if (!ExprResolveFloat(value,&tmp,NULL,NULL)) {
+ info->errorCount++;
+ return ReportBadType("doodad",field,ddText(info->dpy,di),"number");
+ }
+ di->defs.defined|= _GD_Left;
+ di->left= tmp.ival;
+ return True;
+ }
+ else if (uStrCaseCmp(field,"top")==0) {
+ if (arrayNdx!=NULL) {
+ info->errorCount++;
+ return ReportNotArray("doodad",field,ddText(info->dpy,di));
+ }
+ if (!ExprResolveFloat(value,&tmp,NULL,NULL)) {
+ info->errorCount++;
+ return ReportBadType("doodad",field,ddText(info->dpy,di),"number");
+ }
+ di->defs.defined|= _GD_Top;
+ di->top= tmp.ival;
+ return True;
+ }
+ else if (uStrCaseCmp(field,"color")==0) {
+ if (arrayNdx!=NULL) {
+ info->errorCount++;
+ return ReportNotArray("doodad",field,ddText(info->dpy,di));
+ }
+ if (!ExprResolveString(value,&tmp,NULL,NULL)) {
+ info->errorCount++;
+ return ReportBadType("doodad",field,ddText(info->dpy,di),"string");
+ }
+ di->defs.defined|= _GD_Color;
+ di->color= XkbInternAtom(NULL,tmp.str,False);
+ return True;
+ }
+ switch (di->type) {
+ case XkbOutlineDoodad:
+ case XkbSolidDoodad:
+ return SetShapeDoodadField(di,field,arrayNdx,value,si,info);
+ case XkbTextDoodad:
+ return SetTextDoodadField(di,field,arrayNdx,value,si,info);
+ case XkbIndicatorDoodad:
+ return SetIndicatorDoodadField(di,field,arrayNdx,value,si,info);
+ case XkbLogoDoodad:
+ return SetLogoDoodadField(di,field,arrayNdx,value,si,info);
+ }
+ WSGO1("Unknown doodad type %d in SetDoodadField\n",(unsigned int)di->type);
+ ACTION2("Definition of %s in %s ignored\n",field,ddText(info->dpy,di));
+ return False;
+}
+
+static int
+#if NeedFunctionPrototypes
+SetSectionField( SectionInfo * si,
+ char * field,
+ ExprDef * arrayNdx,
+ ExprDef * value,
+ GeometryInfo * info)
+#else
+SetSectionField(si,field,arrayNdx,value,info)
+ SectionInfo * si;
+ char * field;
+ ExprDef * arrayNdx;
+ ExprDef * value;
+ GeometryInfo * info;
+#endif
+{
+unsigned short * pField;
+unsigned def;
+ExprResult tmp;
+
+ pField= NULL;
+ def= 0;
+ if (uStrCaseCmp(field,"priority")==0) {
+ if (arrayNdx!=NULL) {
+ info->errorCount++;
+ return ReportNotArray("keyboard section",field,scText(info->dpy,si));
+ }
+ if (!ExprResolveInteger(value,&tmp,NULL,NULL)) {
+ info->errorCount++;
+ ReportBadType("keyboard section",field,scText(info->dpy,si),
+ "integer");
+ return False;
+ }
+ if ((tmp.ival<0)||(tmp.ival>XkbGeomMaxPriority)) {
+ info->errorCount++;
+ ERROR2("Section priority %d out of range (must be 0..%d)\n",
+ tmp.ival,XkbGeomMaxPriority);
+ ACTION1("Priority for section %s not changed",scText(info->dpy,si));
+ return False;
+ }
+ si->priority= tmp.ival;
+ si->defs.defined|= _GS_Priority;
+ return True;
+ }
+ else if (uStrCaseCmp(field,"top")==0) {
+ pField= &si->top;
+ def= _GS_Top;
+ }
+ else if (uStrCaseCmp(field,"left")==0) {
+ pField= &si->left;
+ def= _GS_Left;
+ }
+ else if (uStrCaseCmp(field,"width")==0) {
+ pField= &si->width;
+ def= _GS_Width;
+ }
+ else if (uStrCaseCmp(field,"height")==0) {
+ pField= &si->height;
+ def= _GS_Height;
+ }
+ else if (uStrCaseCmp(field,"angle")==0) {
+ pField= &si->angle;
+ def= _GS_Angle;
+ }
+ else {
+ info->errorCount++;
+ return ReportBadField("keyboard section",field,scText(info->dpy,si));
+ }
+ if (arrayNdx!=NULL) {
+ info->errorCount++;
+ return ReportNotArray("keyboard section",field,scText(info->dpy,si));
+ }
+ if (!ExprResolveFloat(value,&tmp,NULL,NULL)) {
+ info->errorCount++;
+ ReportBadType("keyboard section",field,scText(info->dpy,si),"number");
+ return False;
+ }
+ si->defs.defined|= def;
+ *pField= tmp.uval;
+ return True;
+}
+
+static int
+#if NeedFunctionPrototypes
+SetRowField( RowInfo * row,
+ char * field,
+ ExprDef * arrayNdx,
+ ExprDef * value,
+ GeometryInfo * info)
+#else
+SetRowField(row,field,arrayNdx,value,info)
+ RowInfo * row;
+ char * field;
+ ExprDef * arrayNdx;
+ ExprDef * value;
+ GeometryInfo * info;
+#endif
+{
+ExprResult tmp;
+
+ if (uStrCaseCmp(field,"top")==0) {
+ if (arrayNdx!=NULL) {
+ info->errorCount++;
+ return ReportNotArray("keyboard row",field,rowText(info->dpy,row));
+ }
+ if (!ExprResolveFloat(value,&tmp,NULL,NULL)) {
+ info->errorCount++;
+ return ReportBadType("keyboard row",field,rowText(info->dpy,row),
+ "number");
+ }
+ row->defs.defined|= _GR_Top;
+ row->top= tmp.uval;
+ }
+ else if (uStrCaseCmp(field,"left")==0) {
+ if (arrayNdx!=NULL) {
+ info->errorCount++;
+ return ReportNotArray("keyboard row",field,rowText(info->dpy,row));
+ }
+ if (!ExprResolveFloat(value,&tmp,NULL,NULL)) {
+ info->errorCount++;
+ return ReportBadType("keyboard row",field,rowText(info->dpy,row),
+ "number");
+ }
+ row->defs.defined|= _GR_Left;
+ row->left= tmp.uval;
+ }
+ else if (uStrCaseCmp(field,"vertical")==0) {
+ if (arrayNdx!=NULL) {
+ info->errorCount++;
+ return ReportNotArray("keyboard row",field,rowText(info->dpy,row));
+ }
+ if (!ExprResolveBoolean(value,&tmp,NULL,NULL)) {
+ info->errorCount++;
+ return ReportBadType("keyboard row",field,rowText(info->dpy,row),
+ "boolean");
+ }
+ row->defs.defined|= _GR_Vertical;
+ row->vertical= tmp.uval;
+ }
+ else {
+ info->errorCount++;
+ return ReportBadField("keyboard row",field,rowText(info->dpy,row));
+ }
+ return True;
+}
+
+static int
+#if NeedFunctionPrototypes
+SetKeyField( KeyInfo *key,
+ char *field,
+ ExprDef *arrayNdx,
+ ExprDef *value,
+ GeometryInfo *info)
+#else
+SetKeyField(key,field,arrayNdx,value,info)
+ KeyInfo * key;
+ char * field;
+ ExprDef * arrayNdx;
+ ExprDef * value;
+ GeometryInfo * info;
+#endif
+{
+ExprResult tmp;
+
+ if (uStrCaseCmp(field,"gap")==0) {
+ if (arrayNdx!=NULL) {
+ info->errorCount++;
+ return ReportNotArray("key",field,keyText(key));
+ }
+ if (!ExprResolveFloat(value,&tmp,NULL,NULL)) {
+ info->errorCount++;
+ return ReportBadType("key",field,keyText(key),"number");
+ }
+ key->defs.defined|= _GK_Gap;
+ key->gap= tmp.ival;
+ }
+ else if (uStrCaseCmp(field,"shape")==0) {
+ if (arrayNdx!=NULL) {
+ info->errorCount++;
+ return ReportNotArray("key",field,keyText(key));
+ }
+ if (!ExprResolveString(value,&tmp,NULL,NULL)) {
+ info->errorCount++;
+ return ReportBadType("key",field,keyText(key),"string");
+ }
+ key->defs.defined|= _GK_Shape;
+ key->shape= XkbInternAtom(info->dpy,tmp.str,False);
+ }
+ else if ((uStrCaseCmp(field,"color")==0)||
+ (uStrCaseCmp(field,"keycolor")==0)) {
+ if (arrayNdx!=NULL) {
+ info->errorCount++;
+ return ReportNotArray("key",field,keyText(key));
+ }
+ if (!ExprResolveString(value,&tmp,NULL,NULL)) {
+ info->errorCount++;
+ return ReportBadType("key",field,keyText(key),"string");
+ }
+ key->defs.defined|= _GK_Color;
+ key->color= XkbInternAtom(NULL,tmp.str,False);
+ }
+ else if ((uStrCaseCmp(field,"name")==0)||(uStrCaseCmp(field,"keyname")==0)){
+ if (arrayNdx!=NULL) {
+ info->errorCount++;
+ return ReportNotArray("key",field,keyText(key));
+ }
+ if (!ExprResolveKeyName(value,&tmp,NULL,NULL)) {
+ info->errorCount++;
+ return ReportBadType("key",field,keyText(key),"key name");
+ }
+ key->defs.defined|= _GK_Name;
+ bzero(key->name,XkbKeyNameLength+1);
+ strncpy(key->name,tmp.keyName.name,XkbKeyNameLength);
+ }
+ else {
+ info->errorCount++;
+ return ReportBadField("key",field,keyText(key));
+ }
+ return True;
+}
+
+static int
+#if NeedFunctionPrototypes
+SetGeometryProperty(GeometryInfo *info,char *property,ExprDef *value)
+#else
+SetGeometryProperty(info,property,value)
+ GeometryInfo * info;
+ char * property;
+ ExprDef * value;
+#endif
+{
+PropertyInfo pi;
+ExprResult result;
+
+ InitPropertyInfo(&pi,info);
+ pi.name= property;
+ if (!ExprResolveString(value,&result,NULL,NULL)) {
+ info->errorCount++;
+ ERROR("Property values must be type string\n");
+ ACTION1("Ignoring illegal definition of \"%s\" property\n",property);
+ return False;
+ }
+ pi.value= result.str;
+ return AddProperty(info,&pi);
+}
+
+static int
+#if NeedFunctionPrototypes
+HandleGeometryVar(VarDef *stmt,XkbDescPtr xkb,GeometryInfo *info)
+#else
+HandleGeometryVar(stmt,xkb,info)
+ VarDef * stmt;
+ XkbDescPtr xkb;
+ GeometryInfo * info;
+#endif
+{
+ExprResult elem,field,tmp;
+ExprDef * ndx;
+DoodadInfo * di;
+Atom * pField;
+
+ if (ExprResolveLhs(stmt->name,&elem,&field,&ndx)==0)
+ return 0; /* internal error, already reported */
+ if (elem.str&&(uStrCaseCmp(elem.str,"shape")==0))
+ return SetShapeField(NULL,field.str,ndx,stmt->value,info);
+ if (elem.str&&(uStrCaseCmp(elem.str,"key")==0))
+ return SetKeyField(&info->dfltSection.dfltRow.dfltKey,
+ field.str,ndx,stmt->value,info);
+ if (elem.str&&(uStrCaseCmp(elem.str,"row")==0))
+ return SetRowField(&info->dfltSection.dfltRow,field.str,ndx,
+ stmt->value,info);
+ if (elem.str&&(uStrCaseCmp(elem.str,"section")==0)) {
+ return SetSectionField(&info->dfltSection,field.str,ndx,stmt->value,
+ info);
+ }
+ if (elem.str&&(uStrCaseCmp(elem.str,"property")==0)) {
+ if (ndx!=NULL) {
+ info->errorCount++;
+ ERROR1("The %s geometry property is not an array\n",field.str);
+ ACTION("Ignoring illegal property definition\n");
+ return False;
+ }
+ return SetGeometryProperty(info,field.str,stmt->value);
+ }
+ if (elem.str&&((di=FindDfltDoodadByTypeName(elem.str,NULL,info))!=NULL)) {
+ return SetDoodadField(di,field.str,ndx,stmt->value,NULL,info);
+ }
+ if (elem.str&&(uStrCaseCmp(elem.str,"solid")==0)) {
+ DoodadInfo *dflt;
+ dflt= FindDoodadByType(info->dfltDoodads,XkbSolidDoodad);
+ if (dflt==NULL)
+ dflt= NextDfltDoodad(NULL,info);
+ return SetDoodadField(dflt,field.str,ndx,stmt->value,NULL,info);
+ }
+ if (elem.str&&(uStrCaseCmp(elem.str,"outline")==0)) {
+ DoodadInfo *dflt;
+ dflt= FindDoodadByType(info->dfltDoodads,XkbOutlineDoodad);
+ if (dflt==NULL)
+ dflt= NextDfltDoodad(NULL,info);
+ return SetDoodadField(dflt,field.str,ndx,stmt->value,NULL,info);
+ }
+ if (elem.str&&(uStrCaseCmp(elem.str,"text")==0)) {
+ DoodadInfo *dflt;
+ dflt= FindDoodadByType(info->dfltDoodads,XkbTextDoodad);
+ if (dflt==NULL)
+ dflt= NextDfltDoodad(NULL,info);
+ return SetDoodadField(dflt,field.str,ndx,stmt->value,NULL,info);
+ }
+ if (elem.str&&(uStrCaseCmp(elem.str,"indicator")==0)) {
+ DoodadInfo *dflt;
+ dflt= FindDoodadByType(info->dfltDoodads,XkbIndicatorDoodad);
+ if (dflt==NULL)
+ dflt= NextDfltDoodad(NULL,info);
+ return SetDoodadField(dflt,field.str,ndx,stmt->value,NULL,info);
+ }
+ if (elem.str&&(uStrCaseCmp(elem.str,"logo")==0)) {
+ DoodadInfo *dflt;
+ dflt= FindDoodadByType(info->dfltDoodads,XkbLogoDoodad);
+ if (dflt==NULL)
+ dflt= NextDfltDoodad(NULL,info);
+ return SetDoodadField(dflt,field.str,ndx,stmt->value,NULL,info);
+ }
+ if (elem.str) {
+ WARN("Assignment to field of unknown element\n");
+ ACTION2("No value assigned to %s.%s\n",elem.str,field.str);
+ return False;
+ }
+
+ if ((uStrCaseCmp(field.str,"width")==0)||
+ (uStrCaseCmp(field.str,"widthmm")==0)) {
+ if (ndx!=NULL) {
+ info->errorCount++;
+ return ReportNotArray("keyboard",field.str,"geometry");
+ }
+ if (!ExprResolveFloat(stmt->value,&tmp,NULL,NULL)) {
+ info->errorCount++;
+ return ReportBadType("keyboard",field.str,"geometry","number");
+ }
+ if (tmp.ival<1) {
+ WARN("Keyboard width must be positive\n");
+ ACTION1("Ignoring illegal keyboard width %s\n",
+ XkbGeomFPText(tmp.ival,XkbMessage));
+ return True;
+ }
+ if (info->widthMM!=0) {
+ WARN("Keyboard width multiply defined\n");
+ ACTION1("Using last definition (%s),",
+ XkbGeomFPText(tmp.ival,XkbMessage));
+ INFO1(" ignoring first (%s)\n",
+ XkbGeomFPText(info->widthMM,XkbMessage));
+ }
+ info->widthMM= tmp.ival;
+ return True;
+ }
+ else if ((uStrCaseCmp(field.str,"height")==0)||
+ (uStrCaseCmp(field.str,"heightmm")==0)) {
+ if (ndx!=NULL) {
+ info->errorCount++;
+ return ReportNotArray("keyboard",field.str,"geometry");
+ }
+ if (!ExprResolveFloat(stmt->value,&tmp,NULL,NULL)) {
+ info->errorCount++;
+ return ReportBadType("keyboard",field.str,"geometry","number");
+ }
+ if (tmp.ival<1) {
+ WARN("Keyboard height must be positive\n");
+ ACTION1("Ignoring illegal keyboard height %s\n",
+ XkbGeomFPText(tmp.ival,XkbMessage));
+ return True;
+ }
+ if (info->heightMM!=0) {
+ WARN("Keyboard height multiply defined\n");
+ ACTION1("Using last definition (%s),",
+ XkbGeomFPText(tmp.ival,XkbMessage));
+ INFO1(" ignoring first (%s)\n",
+ XkbGeomFPText(info->heightMM,XkbMessage));
+ }
+ info->heightMM= tmp.ival;
+ return True;
+ }
+ else if (uStrCaseCmp(field.str,"font")==0) {
+ pField= &info->font;
+ }
+ else if ((uStrCaseCmp(field.str,"fontslant")==0)||
+ (uStrCaseCmp(field.str,"slant")==0)) {
+ pField= &info->fontSlant;
+ }
+ else if ((uStrCaseCmp(field.str,"fontweight")==0)||
+ (uStrCaseCmp(field.str,"weight")==0)) {
+ pField= &info->fontWeight;
+ }
+ else if ((uStrCaseCmp(field.str,"fontwidth")==0)||
+ (uStrCaseCmp(field.str,"setwidth")==0)) {
+ pField= &info->fontWeight;
+ }
+ else if ((uStrCaseCmp(field.str,"fontencoding")==0)||
+ (uStrCaseCmp(field.str,"encoding")==0)) {
+ pField= &info->fontEncoding;
+ }
+ else if ((uStrCaseCmp(field.str,"xfont")==0)||
+ (uStrCaseCmp(field.str,"xfontname")==0)) {
+ pField= &info->fontSpec;
+ }
+ else if (uStrCaseCmp(field.str,"fontsize")==0) {
+ if (ndx!=NULL) {
+ info->errorCount++;
+ return ReportNotArray("keyboard",field.str,"geometry");
+ }
+ if (!ExprResolveFloat(stmt->value,&tmp,NULL,NULL)) {
+ info->errorCount++;
+ return ReportBadType("keyboard",field.str,"geometry","number");
+ }
+ if ((tmp.ival<40)||(tmp.ival>2550)) {
+ info->errorCount++;
+ ERROR1("Illegal font size %d (must be 4..255)\n",tmp.ival);
+ ACTION("Ignoring font size in keyboard geometry\n");
+ return False;
+ }
+ info->fontSize= tmp.ival;
+ return True;
+ }
+ else if ((uStrCaseCmp(field.str,"color")==0)||
+ (uStrCaseCmp(field.str,"basecolor")==0)){
+ if (ndx!=NULL) {
+ info->errorCount++;
+ return ReportNotArray("keyboard",field.str,"geometry");
+ }
+ if (!ExprResolveString(stmt->value,&tmp,NULL,NULL)) {
+ info->errorCount++;
+ return ReportBadType("keyboard",field.str,"geometry","string");
+ }
+ info->baseColor= XkbInternAtom(NULL,tmp.str,False);
+ return True;
+ }
+ else if (uStrCaseCmp(field.str,"labelcolor")==0){
+ if (ndx!=NULL) {
+ info->errorCount++;
+ return ReportNotArray("keyboard",field.str,"geometry");
+ }
+ if (!ExprResolveString(stmt->value,&tmp,NULL,NULL)) {
+ info->errorCount++;
+ return ReportBadType("keyboard",field.str,"geometry","string");
+ }
+ info->labelColor= XkbInternAtom(NULL,tmp.str,False);
+ return True;
+ }
+ else {
+ return SetGeometryProperty(info,field.str,stmt->value);
+ }
+
+ if (ndx!=NULL) {
+ info->errorCount++;
+ return ReportNotArray("keyboard",field.str,"geometry");
+ }
+ if (!ExprResolveString(stmt->value,&tmp,NULL,NULL)) {
+ info->errorCount++;
+ return ReportBadType("keyboard",field.str,"geometry","string");
+ }
+ *pField= XkbInternAtom(NULL,tmp.str,False);
+ return True;
+}
+
+/***====================================================================***/
+
+static Bool
+#if NeedFunctionPrototypes
+HandleShapeBody(ShapeDef *def,ShapeInfo *si,unsigned merge,GeometryInfo *info)
+#else
+HandleShapeBody(def,si,merge,info)
+ ShapeDef * def;
+ ShapeInfo * si;
+ unsigned merge;
+ GeometryInfo * info;
+#endif
+{
+OutlineDef * ol;
+int nOut,nPt;
+XkbOutlinePtr outline;
+ExprDef * pt;
+
+ if (def->nOutlines<1) {
+ WARN1("Shape \"%s\" has no outlines\n",shText(info->dpy,si));
+ ACTION("Definition ignored\n");
+ return True;
+ }
+ si->nOutlines= def->nOutlines;
+ si->outlines= uTypedCalloc(def->nOutlines,XkbOutlineRec);
+ if (!si->outlines) {
+ ERROR1("Couldn't allocate outlines for \"%s\"\n",shText(info->dpy,si));
+ ACTION("Definition ignored\n");
+ info->errorCount++;
+ return False;
+ }
+ for (nOut=0,ol=def->outlines;ol!=NULL;ol=(OutlineDef *)ol->common.next) {
+ if (ol->nPoints<1) {
+ SetShapeField(si,XkbAtomGetString(NULL,ol->field),NULL,
+ ol->points,info);
+ continue;
+ }
+ outline= NULL;
+ outline= &si->outlines[nOut++];
+ outline->num_points= ol->nPoints;
+ outline->corner_radius= si->dfltCornerRadius;
+ outline->points= uTypedCalloc(ol->nPoints,XkbPointRec);
+ if (!outline->points) {
+ ERROR1("Can't allocate points for \"%s\"\n",shText(info->dpy,si));
+ ACTION("Definition ignored\n");
+ info->errorCount++;
+ return False;
+ }
+ for (nPt=0,pt=ol->points;pt!=NULL;pt=(ExprDef *)pt->common.next) {
+ outline->points[nPt].x= pt->value.coord.x;
+ outline->points[nPt].y= pt->value.coord.y;
+ nPt++;
+ }
+ if (ol->field!=None) {
+ char *str= XkbAtomText(NULL,ol->field,XkbMessage);
+ if ((uStrCaseCmp(str,"approximation")==0)||
+ (uStrCaseCmp(str,"approx")==0)) {
+ if (si->approx==NULL)
+ si->approx= outline;
+ else {
+ WARN1("Multiple approximations for \"%s\"\n",
+ shText(info->dpy,si));
+ ACTION("Treating all but the first as normal outlines\n");
+ }
+ }
+ else if (uStrCaseCmp(str,"primary")==0) {
+ if (si->primary==NULL)
+ si->primary= outline;
+ else {
+ WARN1("Multiple primary outlines for \"%s\"\n",
+ shText(info->dpy,si));
+ ACTION("Treating all but the first as normal outlines\n");
+ }
+ }
+ else {
+ WARN2("Unknown outline type %s for \"%s\"\n",str,
+ shText(info->dpy,si));
+ ACTION("Treated as a normal outline\n");
+ }
+ }
+ }
+ if (nOut!=si->nOutlines) {
+ WSGO2("Expected %d outlines, got %d\n",(unsigned int)si->nOutlines,
+ nOut);
+ si->nOutlines= nOut;
+ }
+ return True;
+}
+
+static int
+#if NeedFunctionPrototypes
+HandleShapeDef(ShapeDef *def,XkbDescPtr xkb,unsigned merge,GeometryInfo *info)
+#else
+HandleShapeDef(def,xkb,merge,info)
+ ShapeDef * def;
+ XkbDescPtr xkb;
+ unsigned merge;
+ GeometryInfo * info;
+#endif
+{
+ShapeInfo si;
+
+ if (def->merge!=MergeDefault)
+ merge= def->merge;
+
+ bzero(&si,sizeof(ShapeInfo));
+ si.defs.merge= merge;
+ si.name= XkbInternAtom(info->dpy,XkbAtomGetString(NULL,def->name),False);
+ si.dfltCornerRadius= info->dfltCornerRadius;
+ if (!HandleShapeBody(def,&si,merge,info))
+ return False;
+ if (!AddShape(info,&si))
+ return False;
+ return True;
+}
+
+/***====================================================================***/
+
+static int
+#if NeedFunctionPrototypes
+HandleDoodadDef( DoodadDef *def,
+ unsigned merge,
+ SectionInfo *si,
+ GeometryInfo *info)
+#else
+HandleDoodadDef(def,merge,si,info)
+ DoodadDef * def;
+ unsigned merge;
+ SectionInfo * si;
+ GeometryInfo * info;
+#endif
+{
+ExprResult elem,field;
+ExprDef * ndx;
+DoodadInfo new;
+VarDef * var;
+
+ if (def->common.stmtType==StmtIndicatorMapDef) {
+ IndicatorMapDef *imap= (IndicatorMapDef *)def;
+ Atom name= imap->name;
+ VarDef * body= imap->body;
+ def->common.stmtType= StmtDoodadDef;
+ def->type= XkbIndicatorDoodad;
+ def->name= name;
+ def->body= body;
+ }
+ InitDoodadInfo(&new,def->type,si,info);
+ new.name= XkbInternAtom(info->dpy,XkbAtomGetString(NULL,def->name),False);
+ for (var=def->body;var!=NULL;var= (VarDef *)var->common.next) {
+ if (ExprResolveLhs(var->name,&elem,&field,&ndx)==0)
+ return 0; /* internal error, already reported */
+ if (elem.str!=NULL) {
+ WARN1("Assignment to field of unknown element in doodad %s\n",
+ ddText(info->dpy,&new));
+ ACTION2("No value assigned to %s.%s\n",elem.str,field.str);
+ }
+ else if (!SetDoodadField(&new,field.str,ndx,var->value,si,info))
+ return False;
+ }
+ if (!AddDoodad(si,info,&new))
+ return False;
+ ClearDoodadInfo(&new);
+ return True;
+}
+
+/***====================================================================***/
+
+static int
+#if NeedFunctionPrototypes
+HandleOverlayDef( OverlayDef * def,
+ unsigned merge,
+ SectionInfo * si,
+ GeometryInfo * info)
+#else
+HandleOverlayDef(def,merge,si,info)
+ OverlayDef * def;
+ unsigned merge;
+ SectionInfo * si;
+ GeometryInfo * info;
+#endif
+{
+OverlayKeyDef * keyDef;
+OverlayKeyInfo *key;
+OverlayInfo ol;
+
+ if ((def->nKeys<1)&&(warningLevel>3)) {
+ WARN2("Overlay \"%s\" in section \"%s\" has no keys\n",
+ XkbAtomText(NULL,def->name,XkbMessage),
+ scText(info->dpy,si));
+ ACTION("Overlay ignored\n");
+ return True;
+ }
+ bzero(&ol,sizeof(OverlayInfo));
+ ol.name= XkbInternAtom(info->dpy,XkbAtomGetString(NULL,def->name),False);
+ for (keyDef= def->keys;keyDef;keyDef=(OverlayKeyDef *)keyDef->common.next) {
+ key= uTypedCalloc(1,OverlayKeyInfo);
+ if ((!key)&&warningLevel>0) {
+ WSGO("Couldn't allocate OverlayKeyInfo\n");
+ ACTION2("Overlay %s for section %s will be incomplete\n",
+ oiText(info->dpy,&ol),
+ scText(info->dpy,si));
+ return False;
+ }
+ strncpy(key->over,keyDef->over,XkbKeyNameLength);
+ strncpy(key->under,keyDef->under,XkbKeyNameLength);
+ key->sectionRow= _GOK_UnknownRow;
+ key->overlayRow= _GOK_UnknownRow;
+ ol.keys= (OverlayKeyInfo *)AddCommonInfo(&ol.keys->defs,
+ (CommonInfo *)key);
+ ol.nKeys++;
+ }
+ if (!AddOverlay(si,info,&ol))
+ return False;
+ ClearOverlayInfo(&ol);
+ return True;
+}
+
+/***====================================================================***/
+
+static Bool
+#if NeedFunctionPrototypes
+HandleComplexKey(KeyDef *def,KeyInfo *key,GeometryInfo *info)
+#else
+HandleComplexKey(def,key,info)
+ KeyDef * def;
+ KeyInfo * key;
+ GeometryInfo * info;
+#endif
+{
+RowInfo * row;
+ExprDef * expr;
+
+ row= key->row;
+ for (expr=def->expr;expr!=NULL;expr=(ExprDef *)expr->common.next) {
+ if (expr->op==OpAssign) {
+ ExprResult elem,f;
+ ExprDef *ndx;
+ if (ExprResolveLhs(expr->value.binary.left,&elem,&f,&ndx)==0)
+ return False; /* internal error, already reported */
+ if ((elem.str==NULL)||(uStrCaseCmp(elem.str,"key")==0)) {
+ if (!SetKeyField(key,f.str,ndx,expr->value.binary.right,info))
+ return False;
+ }
+ else {
+ ERROR("Illegal element used in a key definition\n");
+ ACTION2("Assignment to %s.%s ignored\n",elem.str,f.str);
+ return False;
+ }
+ }
+ else {
+ switch (expr->type) {
+ case TypeInt: case TypeFloat:
+ if (!SetKeyField(key,"gap",NULL,expr,info))
+ return False;
+ break;
+ case TypeString:
+ if (!SetKeyField(key,"shape",NULL,expr,info))
+ return False;
+ break;
+ case TypeKeyName:
+ if (!SetKeyField(key,"name",NULL,expr,info))
+ return False;
+ break;
+ default:
+ ERROR("Cannot determine field for unnamed expression\n");
+ ACTION3("Ignoring key %d in row %d of section %s\n",
+ row->nKeys+1,row->section->nRows+1,
+ rowText(info->dpy,row));
+ return False;
+ }
+ }
+ }
+ return True;
+}
+
+static Bool
+#if NeedFunctionPrototypes
+HandleRowBody(RowDef *def,RowInfo *row,unsigned merge,GeometryInfo *info)
+#else
+HandleRowBody(def,row,merge,info)
+ RowDef * def;
+ RowInfo * row;
+ unsigned merge;
+ GeometryInfo * info;
+#endif
+{
+KeyDef * keyDef;
+
+ if ((def->nKeys<1)&&(warningLevel>3)) {
+ ERROR1("Row in section %s has no keys\n",rowText(info->dpy,row));
+ ACTION("Section ignored\n");
+ return True;
+ }
+ for (keyDef= def->keys; keyDef!=NULL;keyDef=(KeyDef *)keyDef->common.next) {
+ if (keyDef->common.stmtType==StmtVarDef) {
+ VarDef *var= (VarDef *)keyDef;
+ ExprResult elem,field;
+ ExprDef *ndx;
+ if (ExprResolveLhs(var->name,&elem,&field,&ndx)==0)
+ return 0; /* internal error, already reported */
+ if ((elem.str==NULL)||(uStrCaseCmp(elem.str,"row")==0)) {
+ if (!SetRowField(row,field.str,ndx,var->value,info))
+ return False;
+ }
+ else if (uStrCaseCmp(elem.str,"key")==0) {
+ if (!SetKeyField(&row->dfltKey,field.str,ndx,var->value,info))
+ return False;
+ }
+ else {
+ WARN("Assignment to field of unknown element in row\n");
+ ACTION2("No value assigned to %s.%s\n",elem.str,field.str);
+ }
+ }
+ else if (keyDef->common.stmtType==StmtKeyDef) {
+ KeyInfo key;
+ InitKeyInfo(&key,row,info);
+ if (keyDef->name!=NULL) {
+ int len= strlen(keyDef->name);
+ if ((len<1)||(len>XkbKeyNameLength)) {
+ ERROR2("Illegal name %s for key in section %s\n",
+ keyDef->name,
+ rowText(info->dpy,row));
+ ACTION("Section not compiled\n");
+ return False;
+ }
+ bzero(key.name,XkbKeyNameLength+1);
+ strncpy(key.name,keyDef->name,XkbKeyNameLength);
+ key.defs.defined|= _GK_Name;
+ }
+ else if (!HandleComplexKey(keyDef,&key,info))
+ return False;
+ if (!AddKey(row,&key))
+ return False;
+ }
+ else {
+ WSGO1("Unexpected statement (type %d) in row body\n",
+ keyDef->common.stmtType);
+ return False;
+ }
+ }
+ return True;
+}
+
+static Bool
+#if NeedFunctionPrototypes
+HandleSectionBody( SectionDef * def,
+ SectionInfo * si,
+ unsigned merge,
+ GeometryInfo * info)
+#else
+HandleSectionBody(def,si,merge,info)
+ SectionDef * def;
+ SectionInfo * si;
+ unsigned merge;
+ GeometryInfo * info;
+#endif
+{
+RowDef * rowDef;
+DoodadInfo * di;
+
+ for (rowDef= def->rows;rowDef!=NULL;rowDef=(RowDef *)rowDef->common.next) {
+ if (rowDef->common.stmtType==StmtVarDef) {
+ VarDef *var= (VarDef *)rowDef;
+ ExprResult elem,field;
+ ExprDef *ndx;
+ if (ExprResolveLhs(var->name,&elem,&field,&ndx)==0)
+ return 0; /* internal error, already reported */
+ if ((elem.str==NULL)||(uStrCaseCmp(elem.str,"section")==0)) {
+ if (!SetSectionField(si,field.str,ndx,var->value,info))
+ return False;
+ }
+ else if (uStrCaseCmp(elem.str,"row")==0) {
+ if (!SetRowField(&si->dfltRow,field.str,ndx,var->value,info))
+ return False;
+ }
+ else if (uStrCaseCmp(elem.str,"key")==0) {
+ if(!SetKeyField(&si->dfltRow.dfltKey,field.str,ndx,
+ var->value,info))
+ return False;
+ }
+ else if ((di=FindDfltDoodadByTypeName(elem.str,si,info))!=NULL) {
+ if (!SetDoodadField(di,field.str,ndx,var->value,si,info))
+ return False;
+ }
+ else {
+ WARN("Assignment to field of unknown element in section\n");
+ ACTION2("No value assigned to %s.%s\n",elem.str,field.str);
+ }
+ }
+ else if (rowDef->common.stmtType==StmtRowDef) {
+ RowInfo row;
+ InitRowInfo(&row,si,info);
+ if (!HandleRowBody(rowDef,&row,merge,info))
+ return False;
+ if (!AddRow(si,&row))
+ return False;
+/* ClearRowInfo(&row,info);*/
+ }
+ else if ((rowDef->common.stmtType==StmtDoodadDef)||
+ (rowDef->common.stmtType==StmtIndicatorMapDef)) {
+ if (!HandleDoodadDef((DoodadDef *)rowDef,merge,si,info))
+ return False;
+ }
+ else if (rowDef->common.stmtType==StmtOverlayDef) {
+ if (!HandleOverlayDef((OverlayDef *)rowDef,merge,si,info))
+ return False;
+ }
+ else {
+ WSGO1("Unexpected statement (type %d) in section body\n",
+ rowDef->common.stmtType);
+ return False;
+ }
+ }
+ if (si->nRows!=def->nRows) {
+ WSGO2("Expected %d rows, found %d\n",(unsigned int)def->nRows,
+ (unsigned int)si->nRows);
+ ACTION1("Definition of section %s might be incorrect\n",
+ scText(info->dpy,si));
+ }
+ return True;
+}
+
+static int
+#if NeedFunctionPrototypes
+HandleSectionDef( SectionDef * def,
+ XkbDescPtr xkb,
+ unsigned merge,
+ GeometryInfo * info)
+#else
+HandleSectionDef(def,xkb,merge,info)
+ SectionDef * def;
+ XkbDescPtr xkb;
+ unsigned merge;
+ GeometryInfo * info;
+#endif
+{
+SectionInfo si;
+char * str;
+
+ if (def->merge!=MergeDefault)
+ merge= def->merge;
+ InitSectionInfo(&si,info);
+ si.defs.merge= merge;
+ str= XkbAtomGetString(NULL,def->name);
+ if ((str==NULL)||(strlen(str)<1)) {
+ ERROR("Section defined without a name\n");
+ ACTION("Definition ignored\n");
+ return False;
+ }
+ si.name= XkbInternAtom(info->dpy,XkbAtomGetString(NULL,def->name),False);
+ if (!HandleSectionBody(def,&si,merge,info))
+ return False;
+ if (!AddSection(info,&si))
+ return False;
+ return True;
+}
+
+/***====================================================================***/
+
+static void
+#if NeedFunctionPrototypes
+HandleGeometryFile( XkbFile * file,
+ XkbDescPtr xkb,
+ unsigned merge,
+ GeometryInfo * info)
+#else
+HandleGeometryFile(file,xkb,merge,info)
+ XkbFile * file;
+ XkbDescPtr xkb;
+ unsigned merge;
+ GeometryInfo * info;
+#endif
+{
+ParseCommon * stmt;
+char * failWhat;
+
+ if (merge==MergeDefault)
+ merge= MergeAugment;
+ info->name= uStringDup(file->name);
+ stmt= file->defs;
+ while (stmt) {
+ failWhat= NULL;
+ switch (stmt->stmtType) {
+ case StmtInclude:
+ if (!HandleIncludeGeometry((IncludeStmt *)stmt,xkb,info,
+ HandleGeometryFile))
+ info->errorCount++;
+ break;
+ case StmtKeyAliasDef:
+ if (!HandleAliasDef((KeyAliasDef *)stmt,
+ merge,info->fileID,&info->aliases)) {
+ info->errorCount++;
+ }
+ break;
+ case StmtVarDef:
+ if (!HandleGeometryVar((VarDef *)stmt,xkb,info))
+ info->errorCount++;
+ break;
+ case StmtShapeDef:
+ if (!HandleShapeDef((ShapeDef *)stmt,xkb,merge,info))
+ info->errorCount++;
+ break;
+ case StmtSectionDef:
+ if (!HandleSectionDef((SectionDef *)stmt,xkb,merge,info))
+ info->errorCount++;
+ break;
+ case StmtIndicatorMapDef:
+ case StmtDoodadDef:
+ if (!HandleDoodadDef((DoodadDef *)stmt,merge,NULL,info))
+ info->errorCount++;
+ break;
+ case StmtVModDef:
+ if (!failWhat) failWhat= "virtual modfier";
+ case StmtInterpDef:
+ if (!failWhat) failWhat= "symbol interpretation";
+ case StmtGroupCompatDef:
+ if (!failWhat) failWhat= "group compatibility map";
+ case StmtKeycodeDef:
+ if (!failWhat) failWhat= "key name";
+ ERROR("Interpretation files may not include other types\n");
+ ACTION1("Ignoring %s definition.\n",failWhat);
+ info->errorCount++;
+ break;
+ default:
+ WSGO1("Unexpected statement type %d in HandleGeometryFile\n",
+ stmt->stmtType);
+ break;
+ }
+ stmt= stmt->next;
+ if (info->errorCount>10) {
+#ifdef NOISY
+ ERROR("Too many errors\n");
+#endif
+ ACTION1("Abandoning geometry file \"%s\"\n",file->topName);
+ break;
+ }
+ }
+ return;
+}
+
+/***====================================================================***/
+
+static Bool
+#if NeedFunctionPrototypes
+CopyShapeDef(Display *dpy,XkbGeometryPtr geom,ShapeInfo *si)
+#else
+CopyShapeDef(dpy,geom,si)
+ Display * dpy;
+ XkbGeometryPtr geom;
+ ShapeInfo * si;
+#endif
+{
+register int i,n;
+XkbShapePtr shape;
+XkbOutlinePtr old_outline,outline;
+Atom name;
+
+ si->index= geom->num_shapes;
+ name= XkbInternAtom(dpy,XkbAtomGetString(NULL,si->name),False);
+ shape= XkbAddGeomShape(geom,name,si->nOutlines);
+ if (!shape) {
+ WSGO("Couldn't allocate shape in geometry\n");
+ ACTION1("Shape %s not compiled\n",shText(dpy,si));
+ return False;
+ }
+ old_outline= si->outlines;
+ for (i=0;i<si->nOutlines;i++,old_outline++) {
+ outline= XkbAddGeomOutline(shape,old_outline->num_points);
+ if (!outline) {
+ WSGO("Couldn't allocate outline in shape\n");
+ ACTION1("Shape %s is incomplete\n",shText(dpy,si));
+ return False;
+ }
+ n= old_outline->num_points;
+ memcpy(outline->points,old_outline->points,n*sizeof(XkbPointRec));
+ outline->num_points= old_outline->num_points;
+ outline->corner_radius= old_outline->corner_radius;
+ }
+ if (si->approx) {
+ n= (si->approx-si->outlines);
+ shape->approx= &shape->outlines[n];
+ }
+ if (si->primary) {
+ n= (si->primary-si->outlines);
+ shape->primary= &shape->outlines[n];
+ }
+ XkbComputeShapeBounds(shape);
+ return True;
+}
+
+static Bool
+#if NeedFunctionPrototypes
+VerifyDoodadInfo(DoodadInfo *di,GeometryInfo *info)
+#else
+VerifyDoodadInfo(di,info)
+ DoodadInfo * di;
+ GeometryInfo * info;
+#endif
+{
+ if ((di->defs.defined&(_GD_Top|_GD_Left))!=(_GD_Top|_GD_Left)) {
+ if (warningLevel<9) {
+ ERROR1("No position defined for doodad %s\n",ddText(info->dpy,di));
+ ACTION("Illegal doodad ignored\n");
+ return False;
+ }
+ }
+ if (di->defs.defined&_GD_Priority==0) {
+ /* calculate priority -- should be just above previous doodad/row */
+ }
+ switch (di->type) {
+ case XkbOutlineDoodad:
+ case XkbSolidDoodad:
+ if ((di->defs.defined&_GD_Shape)==0) {
+ ERROR2("No shape defined for %s doodad %s\n",
+ (di->type==XkbOutlineDoodad?"outline":"filled"),
+ ddText(info->dpy,di));
+ ACTION("Incomplete definition ignored\n");
+ return False;
+ }
+ else {
+ ShapeInfo *si;
+ si= FindShape(info,di->shape, (di->type==XkbOutlineDoodad?
+ "outline doodad":
+ "solid doodad"),
+ ddText(info->dpy,di));
+ if (si)
+ di->shape= si->name;
+ else {
+ ERROR1("No legal shape for %s\n",ddText(info->dpy,di));
+ ACTION("Incomplete definition ignored\n");
+ return False;
+ }
+ }
+ if ((di->defs.defined&_GD_Color)==0) {
+ if (warningLevel>5) {
+ WARN1("No color for doodad %s\n",ddText(info->dpy,di));
+ ACTION("Using black\n");
+ }
+ di->color= XkbInternAtom(NULL,"black",False);
+ }
+ break;
+ case XkbTextDoodad:
+ if ((di->defs.defined&_GD_Text)==0) {
+ ERROR1("No text specified for text doodad %s\n",
+ ddText(info->dpy,di));
+ ACTION("Illegal doodad definition ignored\n");
+ return False;
+ }
+ if ((di->defs.defined&_GD_Angle)==0)
+ di->angle= 0;
+ if ((di->defs.defined&_GD_Color)==0) {
+ if (warningLevel>5) {
+ WARN1("No color specified for doodad %s\n",
+ ddText(info->dpy,di));
+ ACTION("Using black\n");
+ }
+ di->color= XkbInternAtom(NULL,"black",False);
+ }
+ if ((di->defs.defined&_GD_FontSpec)!=0) {
+ if ((di->defs.defined&_GD_FontParts)==0)
+ return True;
+ if (warningLevel<9) {
+ WARN1("Text doodad %s has full and partial font definition\n",
+ ddText(info->dpy,di));
+ ACTION("Full specification ignored\n");
+ }
+ di->defs.defined&= ~_GD_FontSpec;
+ di->fontSpec= None;
+ }
+ if ((di->defs.defined&_GD_Font)==0) {
+ if (warningLevel>5) {
+ WARN1("No font specified for doodad %s\n",
+ ddText(info->dpy,di));
+ ACTION1("Using \"%s\"\n",DFLT_FONT);
+ }
+ di->font= XkbInternAtom(NULL,DFLT_FONT,False);
+ }
+ if ((di->defs.defined&_GD_FontSlant)==0) {
+ if (warningLevel>7) {
+ WARN1("No font slant for text doodad %s\n",
+ ddText(info->dpy,di));
+ ACTION1("Using \"%s\"\n",DFLT_SLANT);
+ }
+ di->fontSlant= XkbInternAtom(NULL,DFLT_SLANT,False);
+ }
+ if ((di->defs.defined&_GD_FontWeight)==0) {
+ if (warningLevel>7) {
+ WARN1("No font weight for text doodad %s\n",
+ ddText(info->dpy,di));
+ ACTION1("Using \"%s\"\n",DFLT_WEIGHT);
+ }
+ di->fontWeight= XkbInternAtom(NULL,DFLT_WEIGHT,False);
+ }
+ if ((di->defs.defined&_GD_FontSetWidth)==0) {
+ if (warningLevel>9) {
+ WARN1("No font set width for text doodad %s\n",
+ ddText(info->dpy,di));
+ ACTION1("Using \"%s\"\n",DFLT_SET_WIDTH);
+ }
+ di->fontSetWidth= XkbInternAtom(NULL,DFLT_SET_WIDTH,False);
+ }
+ if ((di->defs.defined&_GD_FontVariant)==0) {
+ if (warningLevel>9) {
+ WARN1("No font variant for text doodad %s\n",
+ ddText(info->dpy,di));
+ ACTION1("Using \"%s\"\n",DFLT_VARIANT);
+ }
+ di->fontVariant= XkbInternAtom(NULL,DFLT_VARIANT,False);
+ }
+ if ((di->defs.defined&_GD_FontEncoding)==0) {
+ if (warningLevel>7) {
+ WARN1("No font encoding for doodad %s\n",
+ ddText(info->dpy,di));
+ ACTION1("Using \"%s\"\n",DFLT_ENCODING);
+ }
+ di->fontEncoding= XkbInternAtom(NULL,DFLT_ENCODING,False);
+ }
+ if ((di->defs.defined&_GD_FontSize)==0) {
+ if (warningLevel>7) {
+ WARN1("No font size for text doodad %s\n",
+ ddText(info->dpy,di));
+ ACTION1("Using %s point text\n",
+ XkbGeomFPText(DFLT_SIZE,XkbMessage));
+ }
+ di->fontSize= DFLT_SIZE;
+ }
+ if ((di->defs.defined&_GD_Height)==0) {
+ unsigned size,nLines;
+ char *tmp;
+ size= (di->fontSize*120)/100;
+ size= (size*254)/720; /* convert to mm/10 */
+ for (nLines=1,tmp=XkbAtomGetString(NULL,di->text);*tmp;tmp++) {
+ if (*tmp=='\n') nLines++;
+ }
+ size*= nLines;
+ if (warningLevel>5) {
+ WARN1("No height for text doodad %s\n",
+ ddText(info->dpy,di));
+ ACTION1("Using calculated height %s millimeters\n",
+ XkbGeomFPText(size,XkbMessage));
+ }
+ di->height= size;
+ }
+ if ((di->defs.defined&_GD_Width)==0) {
+ unsigned width,tmp;
+ char *str;
+ width= tmp= 0;
+ for (str=XkbAtomGetString(NULL,di->text);*str;str++) {
+ if (*str!='\n')
+ tmp++;
+ else {
+ if (tmp>width)
+ width= tmp;
+ tmp= 1;
+ }
+ }
+ if (width==0)
+ width= tmp;
+ width*= (di->height*2)/3;
+ if (warningLevel>5) {
+ WARN1("No width for text doodad %s\n",ddText(info->dpy,di));
+ ACTION1("Using calculated width %s millimeters\n",
+ XkbGeomFPText(width,XkbMessage));
+ }
+ di->width= width;
+ }
+ break;
+ case XkbIndicatorDoodad:
+ if ((di->defs.defined&_GD_Shape)==0) {
+ ERROR1("No shape defined for indicator doodad %s\n",
+ ddText(info->dpy,di));
+ ACTION("Incomplete definition ignored\n");
+ return False;
+ }
+ else {
+ ShapeInfo *si;
+ si= FindShape(info,di->shape,"indicator doodad",
+ ddText(info->dpy,di));
+ if (si)
+ di->shape= si->name;
+ else {
+ ERROR1("No legal shape for doodad %s\n",
+ ddText(info->dpy,di));
+ ACTION("Incomplete definition ignored\n");
+ return False;
+ }
+ }
+ if ((di->defs.defined&_GD_Color)==0) {
+ if (warningLevel>5) {
+ WARN1("No \"on\" color for indicator doodad %s\n",
+ ddText(info->dpy,di));
+ ACTION("Using green\n");
+ }
+ di->color= XkbInternAtom(NULL,"green",False);
+ }
+ if ((di->defs.defined&_GD_OffColor)==0) {
+ if (warningLevel>5) {
+ WARN1("No \"off\" color for indicator doodad %s\n",
+ ddText(info->dpy,di));
+ ACTION("Using black\n");
+ }
+ di->offColor= XkbInternAtom(NULL,"black",False);
+ }
+ break;
+ case XkbLogoDoodad:
+ if (di->logoName==NULL) {
+ ERROR1("No logo name defined for logo doodad %s\n",
+ ddText(info->dpy,di));
+ ACTION("Incomplete definition ignored\n");
+ return False;
+ }
+ if ((di->defs.defined&_GD_Shape)==0) {
+ ERROR1("No shape defined for logo doodad %s\n",
+ ddText(info->dpy,di));
+ ACTION("Incomplete definition ignored\n");
+ return False;
+ }
+ else {
+ ShapeInfo *si;
+ si= FindShape(info,di->shape,"logo doodad",
+ ddText(info->dpy,di));
+ if (si)
+ di->shape= si->name;
+ else {
+ ERROR1("No legal shape for %s\n",ddText(info->dpy,di));
+ ACTION("Incomplete definition ignored\n");
+ return False;
+ }
+ }
+ if ((di->defs.defined&_GD_Color)==0) {
+ if (warningLevel>5) {
+ WARN1("No color for doodad %s\n",ddText(info->dpy,di));
+ ACTION("Using black\n");
+ }
+ di->color= XkbInternAtom(NULL,"black",False);
+ }
+ break;
+ default:
+ WSGO1("Uknown doodad type %d in VerifyDoodad\n",(unsigned int)di->type);
+ return False;
+ }
+ return True;
+}
+
+#define FONT_TEMPLATE "-*-%s-%s-%s-%s-%s-*-%d-*-*-*-*-%s"
+
+static char *
+#if NeedFunctionPrototypes
+FontFromParts( Atom fontTok,
+ Atom weightTok,
+ Atom slantTok,
+ Atom setWidthTok,
+ Atom varTok,
+ int size,
+ Atom encodingTok)
+#else
+FontFromParts(fontTok,weightTok,slantTok,setWidthTok,varTok,size,encodingTok)
+ Atom fontTok;
+ Atom weightTok;
+ Atom slantTok;
+ Atom setWidthTok;
+ Atom varTok;
+ int size;
+ Atom encodingTok;
+#endif
+{
+int totalSize;
+char *font,*weight,*slant,*setWidth,*variant,*encoding;
+char * rtrn;
+
+ font= (fontTok!=None?XkbAtomGetString(NULL,fontTok):DFLT_FONT);
+ weight= (weightTok!=None?XkbAtomGetString(NULL,weightTok):DFLT_WEIGHT);
+ slant= (slantTok!=None?XkbAtomGetString(NULL,slantTok):DFLT_SLANT);
+ setWidth= (setWidthTok!=None?XkbAtomGetString(NULL,setWidthTok):
+ DFLT_SET_WIDTH);
+ variant= (varTok!=None?XkbAtomGetString(NULL,varTok):DFLT_VARIANT);
+ encoding= (encodingTok!=None?XkbAtomGetString(NULL,encodingTok):
+ DFLT_ENCODING);
+ if (size==0)
+ size= DFLT_SIZE;
+ totalSize= strlen(FONT_TEMPLATE)+strlen(font)+strlen(weight)+strlen(slant);
+ totalSize+= strlen(setWidth)+strlen(variant)+strlen(encoding);
+ rtrn= uCalloc(totalSize,1);
+ if (rtrn) {
+ sprintf(rtrn,FONT_TEMPLATE,font,weight,slant,setWidth,variant,
+ size,encoding);
+ }
+ return rtrn;
+}
+
+static Bool
+#if NeedFunctionPrototypes
+CopyDoodadDef( XkbGeometryPtr geom,
+ XkbSectionPtr section,
+ DoodadInfo * di,
+ GeometryInfo * info)
+#else
+CopyDoodadDef(geom,section,di,info)
+ XkbGeometryPtr geom;
+ XkbSectionPtr section;
+ DoodadInfo * di;
+ GeometryInfo * info;
+#endif
+{
+Atom name;
+XkbDoodadPtr doodad;
+XkbColorPtr color;
+XkbShapePtr shape;
+ShapeInfo * si;
+
+ if (!VerifyDoodadInfo(di,info))
+ return False;
+ name= XkbInternAtom(NULL,XkbAtomGetString(NULL,di->name),False);
+ doodad= XkbAddGeomDoodad(geom,section,name);
+ if (!doodad) {
+ WSGO1("Couldn't allocate doodad in %s\n",
+ (section?"section":"geometry"));
+ ACTION1("Cannot copy doodad %s\n",ddText(info->dpy,di));
+ return False;
+ }
+ doodad->any.type= di->type;
+ doodad->any.priority= di->priority;
+ doodad->any.top= di->top;
+ doodad->any.left= di->left;
+ switch (di->type) {
+ case XkbOutlineDoodad:
+ case XkbSolidDoodad:
+ si= FindShape(info,di->shape,NULL,NULL);
+ if (!si)
+ return False;
+ doodad->shape.angle= di->angle;
+ color= XkbAddGeomColor(geom,XkbAtomGetString(NULL,di->color),geom->num_colors);
+ shape= &geom->shapes[si->index];
+ XkbSetShapeDoodadColor(geom,&doodad->shape,color);
+ XkbSetShapeDoodadShape(geom,&doodad->shape,shape);
+ break;
+ case XkbTextDoodad:
+ doodad->text.angle= di->angle;
+ doodad->text.width= di->width;
+ doodad->text.height= di->height;
+ if (di->fontSpec==None)
+ doodad->text.font= FontFromParts(di->font,di->fontWeight,
+ di->fontSlant,di->fontSetWidth,
+ di->fontVariant,
+ di->fontSize,di->fontEncoding);
+ else doodad->text.font= XkbAtomGetString(NULL,di->fontSpec);
+ doodad->text.text= XkbAtomGetString(NULL,di->text);
+ color= XkbAddGeomColor(geom,XkbAtomGetString(NULL,di->color),geom->num_colors);
+ XkbSetTextDoodadColor(geom,&doodad->text,color);
+ break;
+ case XkbIndicatorDoodad:
+ si= FindShape(info,di->shape,NULL,NULL);
+ if (!si)
+ return False;
+ shape= &geom->shapes[si->index];
+ color= XkbAddGeomColor(geom,XkbAtomGetString(NULL,di->color),geom->num_colors);
+ XkbSetIndicatorDoodadShape(geom,&doodad->indicator,shape);
+ XkbSetIndicatorDoodadOnColor(geom,&doodad->indicator,color);
+ color= XkbAddGeomColor(geom,XkbAtomGetString(NULL,di->offColor),geom->num_colors);
+ XkbSetIndicatorDoodadOffColor(geom,&doodad->indicator,color);
+ break;
+ case XkbLogoDoodad:
+ si= FindShape(info,di->shape,NULL,NULL);
+ if (!si)
+ return False;
+ doodad->logo.angle= di->angle;
+ color= XkbAddGeomColor(geom,XkbAtomGetString(NULL,di->color),geom->num_colors);
+ shape= &geom->shapes[si->index];
+ XkbSetLogoDoodadColor(geom,&doodad->logo,color);
+ XkbSetLogoDoodadShape(geom,&doodad->logo,shape);
+ doodad->logo.logo_name= di->logoName;
+ di->logoName= NULL;
+ break;
+ }
+ return True;
+}
+
+/***====================================================================***/
+
+static Bool
+#if NeedFunctionPrototypes
+VerifyOverlayInfo( XkbGeometryPtr geom,
+ XkbSectionPtr section,
+ OverlayInfo * oi,
+ GeometryInfo * info,
+ short rowMap[256],
+ short rowSize[256])
+#else
+VerifyOverlayInfo(geom,section,oi,info,rowMap,rowSize)
+ XkbGeometryPtr geom;
+ XkbSectionPtr section;
+ OverlayInfo * oi;
+ GeometryInfo * info;
+ short rowMap[256];
+ short rowSize[256];
+#endif
+{
+register OverlayKeyInfo * ki,*next;
+unsigned long oKey,uKey,sKey;
+XkbRowPtr row;
+XkbKeyPtr key;
+int r,k;
+
+ /* find out which row each key is in */
+ for (ki=oi->keys;ki!=NULL;ki=(OverlayKeyInfo *)ki->defs.next) {
+ oKey= KeyNameToLong(ki->over);
+ uKey= KeyNameToLong(ki->under);
+ for (r=0,row=section->rows;(r<section->num_rows)&&oKey;r++,row++) {
+ for (k=0,key=row->keys;(k<row->num_keys)&&oKey;k++,key++) {
+ sKey= KeyNameToLong(key->name.name);
+ if (sKey==oKey) {
+ if (warningLevel>0) {
+ WARN3("Key %s in section \"%s\" and overlay \"%s\"\n",
+ XkbKeyNameText(key->name.name,XkbMessage),
+ XkbAtomText(info->dpy,section->name,XkbMessage),
+ XkbAtomText(info->dpy,oi->name,XkbMessage));
+ ACTION("Overlay definition ignored\n");
+ }
+ oKey= 0;
+ }
+ else if (sKey==uKey) {
+ ki->sectionRow= r;
+ oKey= 0;
+ }
+ }
+ }
+ if ((ki->sectionRow==_GOK_UnknownRow)&&(warningLevel>0)) {
+ WARN3("Key %s not in \"%s\", but has an overlay key in \"%s\"\n",
+ XkbKeyNameText(ki->under,XkbMessage),
+ XkbAtomText(info->dpy,section->name,XkbMessage),
+ XkbAtomText(info->dpy,oi->name,XkbMessage));
+ ACTION("Definition ignored\n");
+ }
+ }
+ /* now prune out keys that aren't in the section */
+ while ((oi->keys!=NULL)&&(oi->keys->sectionRow==_GOK_UnknownRow)) {
+ next= (OverlayKeyInfo *)oi->keys->defs.next;
+ uFree(oi->keys);
+ oi->keys= next;
+ oi->nKeys--;
+ }
+ for (ki=oi->keys;(ki!=NULL)&&(ki->defs.next!=NULL);ki=next) {
+ next= (OverlayKeyInfo *)ki->defs.next;
+ if (next->sectionRow==_GOK_UnknownRow) {
+ ki->defs.next= next->defs.next;
+ oi->nKeys--;
+ uFree(next);
+ next= (OverlayKeyInfo *)ki->defs.next;
+ }
+ }
+ if (oi->nKeys<1) {
+ ERROR2("Overlay \"%s\" for section \"%s\" has no legal keys\n",
+ XkbAtomText(info->dpy,oi->name,XkbMessage),
+ XkbAtomText(info->dpy,section->name,XkbMessage));
+ ACTION("Overlay definition ignored\n");
+ return False;
+ }
+ /* now figure out how many rows are defined for the overlay */
+ bzero(rowSize,sizeof(short)*256);
+ for (k=0;k<256;k++) {
+ rowMap[k]= -1;
+ }
+ oi->nRows= 0;
+ for (ki=oi->keys;ki!=NULL;ki=(OverlayKeyInfo *)ki->defs.next) {
+ if (rowMap[ki->sectionRow]==-1)
+ rowMap[ki->sectionRow]= oi->nRows++;
+ ki->overlayRow= rowMap[ki->sectionRow];
+ rowSize[ki->overlayRow]++;
+ }
+ return True;
+}
+
+static Bool
+#if NeedFunctionPrototypes
+CopyOverlayDef( XkbGeometryPtr geom,
+ XkbSectionPtr section,
+ OverlayInfo * oi,
+ GeometryInfo * info)
+#else
+CopyOverlayDef(geom,section,oi,info)
+ XkbGeometryPtr geom;
+ XkbSectionPtr section;
+ OverlayInfo * oi;
+ GeometryInfo * info;
+#endif
+{
+Atom name;
+XkbOverlayPtr ol;
+XkbOverlayRowPtr row;
+XkbOverlayKeyPtr key;
+OverlayKeyInfo * ki;
+short rowMap[256],rowSize[256];
+int i;
+
+ if (!VerifyOverlayInfo(geom,section,oi,info,rowMap,rowSize))
+ return False;
+ name= XkbInternAtom(NULL,XkbAtomGetString(NULL,oi->name),False);
+ ol= XkbAddGeomOverlay(section,name,oi->nRows);
+ if (!ol) {
+ WSGO2("Couldn't add overlay \"%s\" to section \"%s\"\n",
+ XkbAtomText(info->dpy,name,XkbMessage),
+ XkbAtomText(info->dpy,section->name,XkbMessage));
+ return False;
+ }
+ for (i=0;i<oi->nRows;i++) {
+ int tmp,row_under;
+ for (tmp=0,row_under=-1;(tmp<section->num_rows)&&(row_under<0);tmp++) {
+ if (rowMap[tmp]==i)
+ row_under= tmp;
+ }
+ if (!XkbAddGeomOverlayRow(ol,row_under,rowSize[i])) {
+ WSGO3("Can't add row %d to overlay \"%s\" of section \"%s\"\n",
+ i,XkbAtomText(info->dpy,name,XkbMessage),
+ XkbAtomText(info->dpy,section->name,XkbMessage));
+ return False;
+ }
+ }
+ for (ki=oi->keys;ki!=NULL;ki=(OverlayKeyInfo *)ki->defs.next) {
+ row= &ol->rows[ki->overlayRow];
+ key= &row->keys[row->num_keys++];
+ bzero(key,sizeof(XkbOverlayKeyRec));
+ strncpy(key->over.name,ki->over,XkbKeyNameLength);
+ strncpy(key->under.name,ki->under,XkbKeyNameLength);
+ }
+ return True;
+}
+
+/***====================================================================***/
+
+static Bool
+#if NeedFunctionPrototypes
+CopySectionDef(XkbGeometryPtr geom,SectionInfo *si,GeometryInfo *info)
+#else
+CopySectionDef(geom,si,info)
+ XkbGeometryPtr geom;
+ SectionInfo * si;
+ GeometryInfo * info;
+#endif
+{
+XkbSectionPtr section;
+XkbRowPtr row;
+XkbKeyPtr key;
+KeyInfo * ki;
+RowInfo * ri;
+Atom name;
+
+ name= XkbInternAtom(NULL,XkbAtomGetString(NULL,si->name),False);
+ section= XkbAddGeomSection(geom,name,si->nRows,si->nDoodads,si->nOverlays);
+ if (section==NULL) {
+ WSGO("Couldn't allocate section in geometry\n");
+ ACTION1("Section %s not compiled\n",scText(info->dpy,si));
+ return False;
+ }
+ section->top= si->top;
+ section->left= si->left;
+ section->width= si->width;
+ section->height= si->height;
+ section->angle= si->angle;
+ section->priority= si->priority;
+ for (ri=si->rows;ri!=NULL;ri=(RowInfo *)ri->defs.next) {
+ row= XkbAddGeomRow(section,ri->nKeys);
+ if (row==NULL) {
+ WSGO("Couldn't allocate row in section\n");
+ ACTION1("Section %s is incomplete\n",scText(info->dpy,si));
+ return False;
+ }
+ row->top= ri->top;
+ row->left= ri->left;
+ row->vertical= ri->vertical;
+ for (ki=ri->keys;ki!=NULL;ki=(KeyInfo *)ki->defs.next) {
+ XkbColorPtr color;
+ if ((ki->defs.defined&_GK_Name)==0) {
+ ERROR3("Key %d of row %d in section %s has no name\n",
+ (int)ki->index,(int)ri->index,
+ scText(info->dpy,si));
+ ACTION1("Section %s ignored\n",scText(info->dpy,si));
+ return False;
+ }
+ key= XkbAddGeomKey(row);
+ if (key==NULL) {
+ WSGO("Couldn't allocate key in row\n");
+ ACTION1("Section %s is incomplete\n",scText(info->dpy,si));
+ return False;
+ }
+ memcpy(key->name.name,ki->name,XkbKeyNameLength);
+ key->gap= ki->gap;
+ if (ki->shape==None)
+ key->shape_ndx= 0;
+ else {
+ ShapeInfo *si;
+ si= FindShape(info,ki->shape,"key",keyText(ki));
+ if (!si)
+ return False;
+ key->shape_ndx= si->index;
+ }
+ if (ki->color!=None)
+ color= XkbAddGeomColor(geom,XkbAtomGetString(NULL,ki->color),geom->num_colors);
+ else color= XkbAddGeomColor(geom,"white",geom->num_colors);
+ XkbSetKeyColor(geom,key,color);
+ }
+ }
+ if (si->doodads!=NULL) {
+ DoodadInfo *di;
+ for (di=si->doodads;di!=NULL;di=(DoodadInfo *)di->defs.next) {
+ CopyDoodadDef(geom,section,di,info);
+ }
+ }
+ if (si->overlays!=NULL) {
+ OverlayInfo *oi;
+ for (oi=si->overlays;oi!=NULL;oi=(OverlayInfo *)oi->defs.next) {
+ CopyOverlayDef(geom,section,oi,info);
+ }
+ }
+ if (XkbComputeSectionBounds(geom,section)) {
+ /* 7/6/94 (ef) -- check for negative origin and translate */
+ if ((si->defs.defined&_GS_Width)==0)
+ section->width= section->bounds.x2;
+ if ((si->defs.defined&_GS_Height)==0)
+ section->height= section->bounds.y2;
+ }
+ return True;
+}
+
+/***====================================================================***/
+
+Bool
+#if NeedFunctionPrototypes
+CompileGeometry(XkbFile *file,XkbFileInfo *result,unsigned merge)
+#else
+CompileGeometry(file,result,merge)
+ XkbFile * file;
+ XkbFileInfo * result;
+ unsigned merge;
+#endif
+{
+GeometryInfo info;
+XkbDescPtr xkb;
+
+ xkb= result->xkb;
+ InitGeometryInfo(&info,file->id,merge);
+ info.dpy= xkb->dpy;
+ HandleGeometryFile(file,xkb,merge,&info);
+
+ if (info.errorCount==0) {
+ XkbGeometryPtr geom;
+ XkbGeometrySizesRec sizes;
+ bzero(&sizes,sizeof(sizes));
+ sizes.which= XkbGeomAllMask;
+ sizes.num_properties= info.nProps;
+ sizes.num_colors= 8;
+ sizes.num_shapes= info.nShapes;
+ sizes.num_sections= info.nSections;
+ sizes.num_doodads= info.nDoodads;
+ if (XkbAllocGeometry(xkb,&sizes)!=Success) {
+ WSGO("Couldn't allocate GeometryRec\n");
+ ACTION("Geometry not compiled\n");
+ return False;
+ }
+ geom= xkb->geom;
+
+ geom->width_mm= info.widthMM;
+ geom->height_mm= info.heightMM;
+ if (info.name!=NULL) {
+ geom->name= XkbInternAtom(xkb->dpy,info.name,False);
+ if (XkbAllocNames(xkb,XkbGeometryNameMask,0,0)==Success)
+ xkb->names->geometry= geom->name;
+ }
+ if (info.fontSpec!=None)
+ geom->label_font= uStringDup(XkbAtomGetString(NULL,info.fontSpec));
+ else geom->label_font= FontFromParts(info.font,info.fontWeight,
+ info.fontSlant,info.fontSetWidth,
+ info.fontVariant,
+ info.fontSize,info.fontEncoding);
+ XkbAddGeomColor(geom,"black",geom->num_colors);
+ XkbAddGeomColor(geom,"white",geom->num_colors);
+
+ if (info.baseColor==None)
+ info.baseColor= XkbInternAtom(NULL,"white",False);
+ if (info.labelColor==None)
+ info.labelColor= XkbInternAtom(NULL,"black",False);
+ geom->base_color=
+ XkbAddGeomColor(geom,XkbAtomGetString(NULL,info.baseColor),geom->num_colors);
+ geom->label_color=
+ XkbAddGeomColor(geom,XkbAtomGetString(NULL,info.labelColor),geom->num_colors);
+
+ if (info.props) {
+ PropertyInfo *pi;
+ for (pi= info.props;pi!=NULL;pi=(PropertyInfo *)pi->defs.next) {
+ if (!XkbAddGeomProperty(geom,pi->name,pi->value))
+ return False;
+ }
+ }
+ if (info.shapes) {
+ ShapeInfo *si;
+ for (si= info.shapes;si!=NULL;si=(ShapeInfo *)si->defs.next) {
+ if (!CopyShapeDef(xkb->dpy,geom,si))
+ return False;
+ }
+ }
+ if (info.sections) {
+ SectionInfo *si;
+ for (si= info.sections;si!=NULL;si=(SectionInfo *)si->defs.next) {
+ if (!CopySectionDef(geom,si,&info))
+ return False;
+ }
+ }
+ if (info.doodads) {
+ DoodadInfo *di;
+ for (di= info.doodads;di!=NULL;di=(DoodadInfo *)di->defs.next) {
+ if (!CopyDoodadDef(geom,NULL,di,&info))
+ return False;
+ }
+ }
+ if (info.aliases)
+ ApplyAliases(xkb,True,&info.aliases);
+ ClearGeometryInfo(&info);
+ return True;
+ }
+ return False;
+}
diff --git a/indicators.c b/indicators.c
new file mode 100644
index 0000000..cb09da9
--- /dev/null
+++ b/indicators.c
@@ -0,0 +1,535 @@
+/* $Xorg: indicators.c,v 1.3 2000/08/17 19:54:31 cpqbld Exp $ */
+/************************************************************
+ 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
+ documentation, and that the name of Silicon Graphics not be
+ used in advertising or publicity pertaining to distribution
+ of the software without specific prior written permission.
+ Silicon Graphics makes no representation about the suitability
+ of this software for any purpose. It is provided "as is"
+ without any express or implied warranty.
+
+ SILICON GRAPHICS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS
+ SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+ AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL SILICON
+ 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
+ OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH
+ THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+ ********************************************************/
+
+#include "xkbcomp.h"
+#include "misc.h"
+#include "tokens.h"
+#include "expr.h"
+#include "vmod.h"
+#include "indicators.h"
+
+/***====================================================================***/
+
+#define ReportIndicatorBadType(d,l,f,w) \
+ ReportBadType("indicator map",(f),\
+ XkbAtomText((d),(l)->name,XkbMessage),(w))
+#define ReportIndicatorNotArray(d,l,f) \
+ ReportNotArray("indicator map",(f),\
+ XkbAtomText((d),(l)->name,XkbMessage))
+
+/***====================================================================***/
+
+void
+#if NeedFunctionPrototypes
+ClearIndicatorMapInfo(Display *dpy,LEDInfo *info)
+#else
+ClearIndicatorMapInfo(dpy,info)
+ Display * dpy;
+ LEDInfo * info;
+#endif
+{
+ info->name= XkbInternAtom(dpy,"default",False);
+ info->indicator= _LED_NotBound;
+ info->flags= info->which_mods= info->real_mods= 0;
+ info->vmods= 0;
+ info->which_groups= info->groups= 0;
+ info->ctrls= 0;
+ return;
+}
+
+LEDInfo *
+#if NeedFunctionPrototypes
+AddIndicatorMap(LEDInfo *oldLEDs,LEDInfo *new)
+#else
+AddIndicatorMap(oldLEDs,new)
+ LEDInfo * oldLEDs;
+ LEDInfo * new;
+#endif
+{
+LEDInfo *old,*last;
+unsigned collide;
+
+ last= NULL;
+ for (old=oldLEDs;old!=NULL;old=(LEDInfo *)old->defs.next) {
+ if (old->name==new->name) {
+ if ((old->real_mods==new->real_mods)&&
+ (old->vmods==new->vmods)&&
+ (old->groups==new->groups)&&
+ (old->ctrls==new->ctrls)&&
+ (old->which_mods==new->which_mods)&&
+ (old->which_groups==new->which_groups)) {
+ old->defs.defined|= new->defs.defined;
+ return oldLEDs;
+ }
+ if (new->defs.merge==MergeReplace) {
+ CommonInfo *next= old->defs.next;
+ if (((old->defs.fileID==new->defs.fileID)&&(warningLevel>0))||
+ (warningLevel>9)) {
+ WARN1("Map for indicator %s redefined\n",
+ XkbAtomText(NULL,old->name,XkbMessage));
+ ACTION("Earlier definition ignored\n");
+ }
+ *old= *new;
+ old->defs.next= next;
+ return oldLEDs;
+ }
+ collide= 0;
+ if (UseNewField(_LED_Index,&old->defs,&new->defs,&collide)) {
+ old->indicator= new->indicator;
+ old->defs.defined|= _LED_Index;
+ }
+ if (UseNewField(_LED_Mods,&old->defs,&new->defs,&collide)) {
+ old->which_mods= new->which_mods;
+ old->real_mods= new->real_mods;
+ old->vmods= new->vmods;
+ old->defs.defined|= _LED_Mods;
+ }
+ if (UseNewField(_LED_Groups,&old->defs,&new->defs,&collide)) {
+ old->which_groups= new->which_groups;
+ old->groups= new->groups;
+ old->defs.defined|= _LED_Groups;
+ }
+ if (UseNewField(_LED_Ctrls,&old->defs,&new->defs,&collide)) {
+ old->ctrls= new->ctrls;
+ old->defs.defined|= _LED_Ctrls;
+ }
+ if (UseNewField(_LED_Explicit,&old->defs,&new->defs,&collide)) {
+ old->flags&= ~XkbIM_NoExplicit;
+ old->flags|= (new->flags&XkbIM_NoExplicit);
+ old->defs.defined|= _LED_Explicit;
+ }
+ if (UseNewField(_LED_Automatic,&old->defs,&new->defs,&collide)) {
+ old->flags&= ~XkbIM_NoAutomatic;
+ old->flags|= (new->flags&XkbIM_NoAutomatic);
+ old->defs.defined|= _LED_Automatic;
+ }
+ if (UseNewField(_LED_DrivesKbd,&old->defs,&new->defs,&collide)) {
+ old->flags&= ~XkbIM_LEDDrivesKB;
+ old->flags|= (new->flags&XkbIM_LEDDrivesKB);
+ old->defs.defined|= _LED_DrivesKbd;
+ }
+ if (collide) {
+ WARN1("Map for indicator %s redefined\n",
+ XkbAtomText(NULL,old->name,XkbMessage));
+ ACTION1("Using %s definition for duplicate fields\n",
+ (new->defs.merge==MergeAugment?"first":"last"));
+ }
+ return oldLEDs;
+ }
+ if (old->defs.next==NULL)
+ last= old;
+ }
+ /* new definition */
+ old= uTypedAlloc(LEDInfo);
+ if (!old) {
+ WSGO("Couldn't allocate indicator map\n");
+ ACTION1("Map for indicator %s not compiled\n",
+ XkbAtomText(NULL,new->name,XkbMessage));
+ return False;
+ }
+ *old= *new;
+ old->defs.next= NULL;
+ if (last) {
+ last->defs.next= &old->defs;
+ return oldLEDs;
+ }
+ return old;
+}
+
+LookupEntry modComponentNames[] = {
+ { "base", XkbIM_UseBase },
+ { "latched", XkbIM_UseLatched },
+ { "locked", XkbIM_UseLocked },
+ { "effective", XkbIM_UseEffective },
+ { "compat", XkbIM_UseCompat },
+ { "any", XkbIM_UseAnyMods },
+ { "none", 0 },
+ { NULL, 0 }
+};
+LookupEntry groupComponentNames[] = {
+ { "latched", XkbIM_UseLatched },
+ { "locked", XkbIM_UseLocked },
+ { "effective", XkbIM_UseEffective },
+ { "any", XkbIM_UseAnyGroup },
+ { "none", 0 },
+ { NULL, 0 }
+};
+
+int
+#if NeedFunctionPrototypes
+SetIndicatorMapField( LEDInfo * led,
+ XkbDescPtr xkb,
+ char * field,
+ ExprDef * arrayNdx,
+ ExprDef * value)
+#else
+SetIndicatorMapField(led,xkb,field,arrayNdx,value)
+ LEDInfo * led;
+ XkbDescPtr xkb;
+ char * field;
+ ExprDef * arrayNdx;
+ ExprDef * value;
+#endif
+{
+ExprResult rtrn;
+Bool ok;
+
+ ok= True;
+ if ((uStrCaseCmp(field,"modifiers")==0)||(uStrCaseCmp(field,"mods")==0)) {
+ if (arrayNdx!=NULL)
+ return ReportIndicatorNotArray(xkb->dpy,led,field);
+ if (!ExprResolveModMask(value,&rtrn,LookupVModMask,(XPointer)xkb))
+ return ReportIndicatorBadType(xkb->dpy,led,field,"modifier mask");
+ led->real_mods= rtrn.uval&0xff;
+ led->vmods= (rtrn.uval>>8)&0xff;
+ led->defs.defined|= _LED_Mods;
+ }
+ else if (uStrCaseCmp(field,"groups")==0) {
+ extern LookupEntry groupNames[];
+ if (arrayNdx!=NULL)
+ return ReportIndicatorNotArray(xkb->dpy,led,field);
+ if (!ExprResolveMask(value,&rtrn,SimpleLookup,(XPointer)groupNames))
+ return ReportIndicatorBadType(xkb->dpy,led,field,"group mask");
+ led->groups= rtrn.uval;
+ led->defs.defined|= _LED_Groups;
+ }
+ else if ((uStrCaseCmp(field,"controls")==0)||
+ (uStrCaseCmp(field,"ctrls")==0)) {
+ extern LookupEntry ctrlNames[];
+ if (arrayNdx!=NULL)
+ return ReportIndicatorNotArray(xkb->dpy,led,field);
+ if (!ExprResolveMask(value,&rtrn,SimpleLookup,(XPointer)ctrlNames))
+ return ReportIndicatorBadType(xkb->dpy,led,field,"controls mask");
+ led->ctrls= rtrn.uval;
+ led->defs.defined|= _LED_Ctrls;
+ }
+ else if (uStrCaseCmp(field,"allowexplicit")==0) {
+ if (arrayNdx!=NULL)
+ return ReportIndicatorNotArray(xkb->dpy,led,field);
+ if (!ExprResolveBoolean(value,&rtrn,NULL,NULL))
+ return ReportIndicatorBadType(xkb->dpy,led,field,"boolean");
+ if (rtrn.uval) led->flags&= ~XkbIM_NoExplicit;
+ else led->flags|= XkbIM_NoExplicit;
+ led->defs.defined|= _LED_Explicit;
+ }
+ else if ((uStrCaseCmp(field,"whichmodstate")==0)||
+ (uStrCaseCmp(field,"whichmodifierstate")==0)) {
+ if (arrayNdx!=NULL)
+ return ReportIndicatorNotArray(xkb->dpy,led,field);
+ if (!ExprResolveMask(value,&rtrn,SimpleLookup,
+ (XPointer)modComponentNames)) {
+ return ReportIndicatorBadType(xkb->dpy,led,field,
+ "mask of modifier state components");
+ }
+ led->which_mods= rtrn.uval;
+ }
+ else if (uStrCaseCmp(field,"whichgroupstate")==0) {
+ if (arrayNdx!=NULL)
+ return ReportIndicatorNotArray(xkb->dpy,led,field);
+ if (!ExprResolveMask(value,&rtrn,SimpleLookup,
+ (XPointer)groupComponentNames)){
+ return ReportIndicatorBadType(xkb->dpy,led,field,
+ "mask of group state components");
+ }
+ if ((rtrn.uval&XkbIM_UseCompat)&&(warningLevel>0)) {
+ WARN("Cannot use the compatibilty state for groups\n");
+ ACTION2("Not set in the %s field of the map for indicator %s\n",
+ field,
+ XkbAtomText(NULL,led->name,XkbMessage));
+ rtrn.uval&= ~XkbIM_UseCompat;
+ }
+ led->which_groups= rtrn.uval;
+ }
+ else if ((uStrCaseCmp(field,"driveskbd")==0)||
+ (uStrCaseCmp(field,"driveskeyboard")==0)||
+ (uStrCaseCmp(field,"leddriveskbd")==0)||
+ (uStrCaseCmp(field,"leddriveskeyboard")==0)||
+ (uStrCaseCmp(field,"indicatordriveskbd")==0)||
+ (uStrCaseCmp(field,"indicatordriveskeyboard")==0)) {
+ if (arrayNdx!=NULL)
+ return ReportIndicatorNotArray(xkb->dpy,led,field);
+ if (!ExprResolveBoolean(value,&rtrn,NULL,NULL))
+ return ReportIndicatorBadType(xkb->dpy,led,field,"boolean");
+ if (rtrn.uval) led->flags|= XkbIM_LEDDrivesKB;
+ else led->flags&= ~XkbIM_LEDDrivesKB;
+ led->defs.defined|= _LED_DrivesKbd;
+ }
+ else if (uStrCaseCmp(field,"index")==0) {
+ if (arrayNdx!=NULL)
+ return ReportIndicatorNotArray(xkb->dpy,led,field);
+ if (!ExprResolveInteger(value,&rtrn,NULL,NULL))
+ return ReportIndicatorBadType(xkb->dpy,led,field,"indicator index");
+ if ((rtrn.uval<1)||(rtrn.uval>32)) {
+ ERROR2("Illegal indicator index %d (range 1..%d)\n",rtrn.uval,
+ XkbNumIndicators);
+ ACTION1("Index definition for %s indicator ignored\n",
+ XkbAtomText(NULL,led->name,XkbMessage));
+ return False;
+ }
+ led->indicator= rtrn.uval;
+ led->defs.defined|= _LED_Index;
+ }
+ else {
+ ERROR2("Unknown field %s in map for %s indicator\n",field,
+ XkbAtomText(NULL,led->name,XkbMessage));
+ ACTION("Definition ignored\n");
+ ok= False;
+ }
+ return ok;
+}
+
+LEDInfo *
+#if NeedFunctionPrototypes
+HandleIndicatorMapDef( IndicatorMapDef * def,
+ XkbDescPtr xkb,
+ LEDInfo * dflt,
+ LEDInfo * oldLEDs,
+ unsigned merge)
+#else
+HandleIndicatorMapDef(def,xkb,dflt,oldLEDs,merge)
+ IndicatorMapDef * def;
+ XkbDescPtr xkb;
+ LEDInfo * dflt;
+ LEDInfo * oldLEDs;
+ unsigned merge;
+#endif
+{
+LEDInfo led,*rtrn;
+VarDef * var;
+Bool ok;
+
+ if (def->merge!=MergeDefault)
+ merge= def->merge;
+
+ led= *dflt;
+ led.defs.merge= merge;
+ led.name= def->name;
+
+ ok= True;
+ for (var= def->body;var!=NULL;var= (VarDef *)var->common.next) {
+ ExprResult elem,field;
+ ExprDef * arrayNdx;
+ if (!ExprResolveLhs(var->name,&elem,&field,&arrayNdx)) {
+ ok= False;
+ continue;
+ }
+ if (elem.str!=NULL) {
+ ERROR1("Cannot set defaults for \"%s\" element in indicator map\n",
+ elem.str);
+ ACTION2("Assignment to %s.%s ignored\n",elem.str,field.str);
+ ok= False;
+ }
+ else {
+ ok=SetIndicatorMapField(&led,xkb,field.str,arrayNdx,var->value)&&ok;
+ }
+ }
+ if (ok) {
+ rtrn= AddIndicatorMap(oldLEDs,&led);
+ return rtrn;
+ }
+ return NULL;
+}
+
+Bool
+#if NeedFunctionPrototypes
+CopyIndicatorMapDefs(XkbFileInfo *result,LEDInfo *leds,LEDInfo **unboundRtrn)
+#else
+CopyIndicatorMapDefs(result,leds,unboundRtrn)
+ XkbFileInfo * result;
+ LEDInfo * leds;
+ LEDInfo ** unboundRtrn;
+#endif
+{
+LEDInfo * led,*next;
+LEDInfo * unbound,*last;
+XkbDescPtr xkb;
+
+ xkb= result->xkb;
+ if (XkbAllocNames(xkb,XkbIndicatorNamesMask,0,0)!=Success) {
+ WSGO("Couldn't allocate names\n");
+ ACTION("Indicator names may be incorrect\n");
+ }
+ if (XkbAllocIndicatorMaps(xkb)!=Success) {
+ WSGO("Can't allocate indicator maps\n");
+ ACTION("Indicator map definitions may be lost\n");
+ return False;
+ }
+ last= unbound= (unboundRtrn?*unboundRtrn:NULL);
+ while ((last!=NULL) && (last->defs.next!=NULL)) {
+ last= (LEDInfo *)last->defs.next;
+ }
+ for (led=leds;led!=NULL;led=next) {
+ next= (LEDInfo *)led->defs.next;
+ if ((led->groups!=0)&&(led->which_groups==0))
+ led->which_groups= XkbIM_UseEffective;
+ if ((led->which_mods==0)&&((led->real_mods)||(led->vmods)))
+ led->which_mods= XkbIM_UseEffective;
+ if ((led->indicator==_LED_NotBound)||(!xkb->indicators)) {
+ if (unboundRtrn!=NULL) {
+ led->defs.next= NULL;
+ if (last!=NULL) last->defs.next= (CommonInfo *)led;
+ else unbound= led;
+ last= led;
+ }
+ else uFree(led);
+ }
+ else {
+ register XkbIndicatorMapPtr im;
+ im= &xkb->indicators->maps[led->indicator-1];
+ im->flags= led->flags;
+ im->which_groups= led->which_groups;
+ im->groups= led->groups;
+ im->which_mods= led->which_mods;
+ im->mods.mask= led->real_mods;
+ im->mods.real_mods= led->real_mods;
+ im->mods.vmods= led->vmods;
+ im->ctrls= led->ctrls;
+ if (xkb->names!=NULL)
+ xkb->names->indicators[led->indicator-1]= led->name;
+ uFree(led);
+ }
+ }
+ if (unboundRtrn!=NULL) {
+ *unboundRtrn= unbound;
+ }
+ return True;
+}
+
+Bool
+#if NeedFunctionPrototypes
+BindIndicators( XkbFileInfo * result,
+ Bool force,
+ LEDInfo * unbound,
+ LEDInfo ** unboundRtrn)
+#else
+BindIndicators(result,force,unbound,unboundRtrn)
+ XkbFileInfo * result;
+ Bool force;
+ LEDInfo * unbound;
+ LEDInfo ** unboundRtrn;
+#endif
+{
+XkbDescPtr xkb;
+register int i;
+register LEDInfo *led,*next,*last;
+
+ xkb= result->xkb;
+ if (xkb->names!=NULL) {
+ for (led=unbound;led!=NULL;led= (LEDInfo *)led->defs.next) {
+ if (led->indicator==_LED_NotBound) {
+ for (i=0;i<XkbNumIndicators;i++) {
+ if (xkb->names->indicators[i]==led->name) {
+ led->indicator= i+1;
+ break;
+ }
+ }
+ }
+ }
+ if (force) {
+ for (led=unbound;led!=NULL;led= (LEDInfo *)led->defs.next) {
+ if (led->indicator==_LED_NotBound) {
+ for (i=0;i<XkbNumIndicators;i++) {
+ if (xkb->names->indicators[i]==None) {
+ xkb->names->indicators[i]= led->name;
+ led->indicator= i+1;
+ xkb->indicators->phys_indicators&= ~(1<<i);
+ break;
+ }
+ }
+ if (led->indicator==_LED_NotBound) {
+ ERROR("No unnamed indicators found\n");
+ ACTION1("Virtual indicator map \"%s\" not bound\n",
+ XkbAtomGetString(xkb->dpy,led->name));
+ continue;
+ }
+ }
+ }
+ }
+ }
+ for (last=NULL,led=unbound;led!=NULL;led= next) {
+ next= (LEDInfo *)led->defs.next;
+ if (led->indicator==_LED_NotBound) {
+ if (force) {
+ unbound= next;
+ uFree(led);
+ }
+ else {
+ if (last)
+ last->defs.next= &led->defs;
+ else unbound= led;
+ last= led;
+ }
+ }
+ else {
+ if ((xkb->names!=NULL)&&
+ (xkb->names->indicators[led->indicator-1]!=led->name)) {
+ Atom old= xkb->names->indicators[led->indicator-1];
+ ERROR1("Multiple names bound to indicator %d\n",(unsigned int)led->indicator);
+ ACTION2("Using %s, ignoring %s\n",
+ XkbAtomGetString(xkb->dpy,old),
+ XkbAtomGetString(xkb->dpy,led->name));
+ led->indicator= _LED_NotBound;
+ if (force) {
+ uFree(led);
+ unbound= next;
+ }
+ else {
+ if (last)
+ last->defs.next= &led->defs;
+ else unbound= led;
+ last= led;
+ }
+ }
+ else {
+ XkbIndicatorMapPtr map;
+ map= &xkb->indicators->maps[led->indicator-1];
+ map->flags= led->flags;
+ map->which_groups= led->which_groups;
+ map->groups= led->groups;
+ map->which_mods= led->which_mods;
+ map->mods.mask= led->real_mods;
+ map->mods.real_mods= led->real_mods;
+ map->mods.vmods= led->vmods;
+ map->ctrls= led->ctrls;
+ if (last) last->defs.next= &next->defs;
+ else unbound= next;
+ led->defs.next= NULL;
+ uFree(led);
+ }
+ }
+ }
+ if (unboundRtrn) {
+ *unboundRtrn= unbound;
+ }
+ else if (unbound) {
+ for (led=unbound;led!=NULL;led=next) {
+ next= (LEDInfo *)led->defs.next;
+ uFree(led);
+ }
+ }
+ return True;
+}
diff --git a/indicators.h b/indicators.h
new file mode 100644
index 0000000..461866b
--- /dev/null
+++ b/indicators.h
@@ -0,0 +1,106 @@
+/* $Xorg: indicators.h,v 1.3 2000/08/17 19:54:32 cpqbld Exp $ */
+/************************************************************
+ 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
+ documentation, and that the name of Silicon Graphics not be
+ used in advertising or publicity pertaining to distribution
+ of the software without specific prior written permission.
+ Silicon Graphics makes no representation about the suitability
+ of this software for any purpose. It is provided "as is"
+ without any express or implied warranty.
+
+ SILICON GRAPHICS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS
+ SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+ AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL SILICON
+ 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
+ OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH
+ THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+ ********************************************************/
+
+#ifndef INDICATORS_H
+#define INDICATORS_H 1
+
+#define _LED_Index (1<<0)
+#define _LED_Mods (1<<1)
+#define _LED_Groups (1<<2)
+#define _LED_Ctrls (1<<3)
+#define _LED_Explicit (1<<4)
+#define _LED_Automatic (1<<5)
+#define _LED_DrivesKbd (1<<6)
+
+#define _LED_NotBound 255
+
+typedef struct _LEDInfo {
+ CommonInfo defs;
+ Atom name;
+ unsigned char indicator;
+ unsigned char flags;
+ unsigned char which_mods;
+ unsigned char real_mods;
+ unsigned short vmods;
+ unsigned char which_groups;
+ unsigned char groups;
+ unsigned int ctrls;
+} LEDInfo;
+
+extern void ClearIndicatorMapInfo(
+#if NeedFunctionPrototypes
+ Display * /* dpy */,
+ LEDInfo * /* info */
+#endif
+);
+
+
+extern LEDInfo *AddIndicatorMap(
+#if NeedFunctionPrototypes
+ LEDInfo * /* oldLEDs */,
+ LEDInfo * /* newLED */
+#endif
+);
+
+extern int SetIndicatorMapField(
+#if NeedFunctionPrototypes
+ LEDInfo * /* led */,
+ XkbDescPtr /* xkb */,
+ char * /* field */,
+ ExprDef * /* arrayNdx */,
+ ExprDef * /* value */
+#endif
+);
+
+extern LEDInfo *HandleIndicatorMapDef(
+#if NeedFunctionPrototypes
+ IndicatorMapDef * /* stmt */,
+ XkbDescPtr /* xkb */,
+ LEDInfo * /* dflt */,
+ LEDInfo * /* oldLEDs */,
+ unsigned /* mergeMode */
+#endif
+);
+
+extern Bool CopyIndicatorMapDefs(
+#if NeedFunctionPrototypes
+ XkbFileInfo * /* result */,
+ LEDInfo * /* leds */,
+ LEDInfo ** /* unboundRtrn */
+#endif
+);
+
+extern Bool BindIndicators(
+#if NeedFunctionPrototypes
+ XkbFileInfo * /* result */,
+ Bool /* force */,
+ LEDInfo * /* unbound */,
+ LEDInfo ** /* unboundRtrn */
+#endif
+);
+
+#endif /* INDICATORS_H */
diff --git a/keycodes.c b/keycodes.c
new file mode 100644
index 0000000..6acf0ac
--- /dev/null
+++ b/keycodes.c
@@ -0,0 +1,877 @@
+/* $Xorg: keycodes.c,v 1.4 2000/08/17 19:54:32 cpqbld Exp $ */
+/************************************************************
+ 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
+ documentation, and that the name of Silicon Graphics not be
+ used in advertising or publicity pertaining to distribution
+ of the software without specific prior written permission.
+ Silicon Graphics makes no representation about the suitability
+ of this software for any purpose. It is provided "as is"
+ without any express or implied warranty.
+
+ SILICON GRAPHICS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS
+ SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+ AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL SILICON
+ 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
+ OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH
+ THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+ ********************************************************/
+
+#include "xkbcomp.h"
+#include "tokens.h"
+#include "expr.h"
+#include "keycodes.h"
+#include "misc.h"
+#include "alias.h"
+
+char *
+#if NeedFunctionPrototypes
+longText(unsigned long val,unsigned format)
+#else
+longText(val,format)
+ unsigned long val;
+ unsigned format;
+#endif
+{
+char buf[4];
+
+ LongToKeyName(val,buf);
+ return XkbKeyNameText(buf,format);
+}
+
+/***====================================================================***/
+
+void
+#if NeedFunctionPrototypes
+LongToKeyName(unsigned long val,char *name)
+#else
+LongToKeyName(val,name)
+ unsigned long val;
+ char * name;
+#endif
+{
+ name[0]= ((val>>24)&0xff);
+ name[1]= ((val>>16)&0xff);
+ name[2]= ((val>>8)&0xff);
+ name[3]= (val&0xff);
+ return;
+}
+
+/***====================================================================***/
+
+typedef struct _IndicatorNameInfo {
+ CommonInfo defs;
+ int ndx;
+ Atom name;
+ Bool virtual;
+} IndicatorNameInfo;
+
+typedef struct _KeyNamesInfo {
+ char * name;
+ int errorCount;
+ unsigned fileID;
+ unsigned merge;
+ int computedMin;
+ int computedMax;
+ int explicitMin;
+ int explicitMax;
+ int effectiveMin;
+ int effectiveMax;
+ unsigned long names[XkbMaxLegalKeyCode+1];
+ unsigned files[XkbMaxLegalKeyCode+1];
+ unsigned char has_alt_forms[XkbMaxLegalKeyCode+1];
+ IndicatorNameInfo * leds;
+ AliasInfo * aliases;
+} KeyNamesInfo;
+
+static void
+#if NeedFunctionPrototypes
+InitIndicatorNameInfo(IndicatorNameInfo *ii,KeyNamesInfo *info)
+#else
+InitIndicatorNameInfo(ii,info)
+ IndicatorNameInfo * ii;
+ KeyNamesInfo * info;
+#endif
+{
+ ii->defs.defined= 0;
+ ii->defs.merge= info->merge;
+ ii->defs.fileID= info->fileID;
+ ii->defs.next= NULL;
+ ii->ndx= 0;
+ ii->name= None;
+ ii->virtual= False;
+ return;
+}
+
+static void
+#if NeedFunctionPrototypes
+ClearIndicatorNameInfo(IndicatorNameInfo *ii,KeyNamesInfo *info)
+#else
+ClearIndicatorNameInfo(ii,info)
+ IndicatorNameInfo * ii;
+ KeyNamesInfo * info;
+#endif
+{
+ if (ii==info->leds) {
+ ClearCommonInfo(&ii->defs);
+ info->leds= NULL;
+ }
+ return;
+}
+
+static IndicatorNameInfo *
+#if NeedFunctionPrototypes
+NextIndicatorName(KeyNamesInfo *info)
+#else
+NextIndicatorName(info)
+ KeyNamesInfo * info;
+#endif
+{
+IndicatorNameInfo * ii;
+
+ ii= uTypedAlloc(IndicatorNameInfo);
+ if (ii) {
+ InitIndicatorNameInfo(ii,info);
+ info->leds= (IndicatorNameInfo *)AddCommonInfo(&info->leds->defs,
+ (CommonInfo *)ii);
+ }
+ return ii;
+}
+
+static IndicatorNameInfo *
+#if NeedFunctionPrototypes
+FindIndicatorByIndex(KeyNamesInfo *info,int ndx)
+#else
+FindIndicatorByIndex(info,ndx)
+ KeyNamesInfo * info;
+ int ndx;
+#endif
+{
+IndicatorNameInfo * old;
+
+ for (old= info->leds;old!=NULL;old=(IndicatorNameInfo *)old->defs.next) {
+ if (old->ndx==ndx)
+ return old;
+ }
+ return NULL;
+}
+
+static IndicatorNameInfo *
+#if NeedFunctionPrototypes
+FindIndicatorByName(KeyNamesInfo *info,Atom name)
+#else
+FindIndicatorByName(info,name)
+ KeyNamesInfo * info;
+ Atom name;
+#endif
+{
+IndicatorNameInfo * old;
+
+ for (old= info->leds;old!=NULL;old=(IndicatorNameInfo *)old->defs.next) {
+ if (old->name==name)
+ return old;
+ }
+ return NULL;
+}
+
+static Bool
+#if NeedFunctionPrototypes
+AddIndicatorName(KeyNamesInfo *info,IndicatorNameInfo *new)
+#else
+AddIndicatorName(info,new)
+ KeyNamesInfo * info;
+ IndicatorNameInfo *new;
+#endif
+{
+IndicatorNameInfo *old;
+Bool replace;
+char * action;
+
+ replace= (new->defs.merge==MergeReplace)||
+ (new->defs.merge==MergeOverride);
+ old= FindIndicatorByName(info,new->name);
+ if (old) {
+ if (((old->defs.fileID==new->defs.fileID)&&(warningLevel>0))||
+ (warningLevel>9)) {
+ WARN1("Multiple indicators named %s\n",
+ XkbAtomText(NULL,new->name,XkbMessage));
+ if (old->ndx==new->ndx) {
+ if (old->virtual!=new->virtual) {
+ if (replace)
+ old->virtual= new->virtual;
+ action= "Using %s instead of %s\n";
+ }
+ else {
+ action= "Identical definitions ignored\n";
+ }
+ ACTION2(action,(old->virtual?"virtual":"real"),
+ (old->virtual?"real":"virtual"));
+ return True;
+ }
+ else {
+ if (replace) action= "Ignoring %d, using %d\n";
+ else action= "Using %d, ignoring %d\n";
+ ACTION2(action,old->ndx,new->ndx);
+ }
+ if (replace) {
+ if (info->leds==old)
+ info->leds= (IndicatorNameInfo *)old->defs.next;
+ else {
+ IndicatorNameInfo *tmp;
+ tmp= info->leds;
+ for (;tmp!=NULL;tmp=(IndicatorNameInfo *)tmp->defs.next) {
+ if (tmp->defs.next==(CommonInfo *)old) {
+ tmp->defs.next= old->defs.next;
+ break;
+ }
+ }
+ }
+ uFree(old);
+ }
+ }
+ }
+ old= FindIndicatorByIndex(info,new->ndx);
+ if (old) {
+ if (((old->defs.fileID==new->defs.fileID)&&(warningLevel>0))||
+ (warningLevel>9)) {
+ WARN1("Multiple names for indicator %d\n",new->ndx);
+ if ((old->name==new->name)&&(old->virtual==new->virtual))
+ action= "Identical definitions ignored\n";
+ else {
+ char *oldType,*newType;
+ Atom using,ignoring;
+ if (old->virtual) oldType= "virtual indicator";
+ else oldType= "real indicator";
+ if (new->virtual) newType= "virtual indicator";
+ else newType= "real indicator";
+ if (replace) {
+ using= new->name;
+ ignoring= old->name;
+ }
+ else {
+ using= old->name;
+ ignoring= new->name;
+ }
+ ACTION4("Using %s %s, ignoring %s %s\n",
+ oldType,XkbAtomText(NULL,using,XkbMessage),
+ newType,XkbAtomText(NULL,ignoring,XkbMessage));
+ }
+ }
+ if (replace) {
+ old->name= new->name;
+ old->virtual= new->virtual;
+ }
+ return True;
+ }
+ old= new;
+ new= NextIndicatorName(info);
+ if (!new) {
+ WSGO1("Couldn't allocate name for indicator %d\n",new->ndx);
+ ACTION("Ignored\n");
+ return False;
+ }
+ new->name= old->name;
+ new->ndx= old->ndx;
+ new->virtual= old->virtual;
+ return True;
+}
+
+static void
+#if NeedFunctionPrototypes
+ClearKeyNamesInfo(KeyNamesInfo *info)
+#else
+ClearKeyNamesInfo(info)
+ KeyNamesInfo *info;
+#endif
+{
+ if (info->name!=NULL)
+ uFree(info->name);
+ info->name= NULL;
+ info->computedMax= info->explicitMax= info->explicitMin= -1;
+ info->computedMin= 256;
+ info->effectiveMin= 8;
+ info->effectiveMax= 255;
+ bzero((char *)info->names,sizeof(info->names));
+ bzero((char *)info->files,sizeof(info->files));
+ bzero((char *)info->has_alt_forms,sizeof(info->has_alt_forms));
+ if (info->leds)
+ ClearIndicatorNameInfo(info->leds,info);
+ if (info->aliases)
+ ClearAliases(&info->aliases);
+ return;
+}
+
+static void
+#if NeedFunctionPrototypes
+InitKeyNamesInfo(KeyNamesInfo *info)
+#else
+InitKeyNamesInfo(info)
+ KeyNamesInfo *info;
+#endif
+{
+ info->name= NULL;
+ info->leds= NULL;
+ info->aliases= NULL;
+ ClearKeyNamesInfo(info);
+ info->errorCount= 0;
+ return;
+}
+
+int
+#if NeedFunctionPrototypes
+FindKeyByLong(KeyNamesInfo *info,unsigned long name)
+#else
+FindKeyByLong(info,name)
+ KeyNamesInfo * info;
+ unsigned long name;
+#endif
+{
+register int i;
+
+ for (i=info->effectiveMin;i<=info->effectiveMax;i++) {
+ if (info->names[i]==name)
+ return i;
+ }
+ return 0;
+}
+
+static Bool
+#if NeedFunctionPrototypes
+AddKeyName( KeyNamesInfo * info,
+ int kc,
+ char * name,
+ unsigned merge,
+ unsigned fileID,
+ Bool reportCollisions)
+#else
+AddKeyName(info,kc,name,merge,fileID,reportCollisions)
+ KeyNamesInfo * info;
+ int kc;
+ char * name;
+ unsigned merge;
+ unsigned fileID;
+ Bool reportCollisions;
+#endif
+{
+int old;
+unsigned long lval;
+
+ if ((kc<info->effectiveMin)||(kc>info->effectiveMax)) {
+ ERROR2("Illegal keycode %d for name <%s>\n",kc,name);
+ ACTION2("Must be in the range %d-%d inclusive\n",info->effectiveMin,
+ info->effectiveMax);
+ return False;
+ }
+ if (kc<info->computedMin) info->computedMin= kc;
+ if (kc>info->computedMax) info->computedMax= kc;
+ lval= KeyNameToLong(name);
+
+ if (reportCollisions) {
+ reportCollisions= ((warningLevel>7)||
+ ((warningLevel>0)&&(fileID==info->files[kc])));
+ }
+
+ if (info->names[kc]!=0) {
+ char buf[6];
+
+ LongToKeyName(info->names[kc],buf);
+ buf[4]= '\0';
+ if (info->names[kc]==lval) {
+ if (info->has_alt_forms[kc] || (merge==MergeAltForm)) {
+ info->has_alt_forms[kc]= True;
+ }
+ else if (reportCollisions) {
+ WARN("Multiple identical key name definitions\n");
+ ACTION2("Later occurences of \"<%s> = %d\" ignored\n",buf,kc);
+ }
+ return True;
+ }
+ if (merge==MergeAugment) {
+ if (reportCollisions) {
+ WARN1("Multiple names for keycode %d\n",kc);
+ ACTION2("Using <%s>, ignoring <%s>\n",buf,name);
+ }
+ return True;
+ }
+ else {
+ if (reportCollisions) {
+ WARN1("Multiple names for keycode %d\n",kc);
+ ACTION2("Using <%s>, ignoring <%s>\n",name,buf);
+ }
+ info->names[kc]= 0;
+ info->files[kc]= 0;
+ }
+ }
+ old= FindKeyByLong(info,lval);
+ if ((old!=0)&&(old!=kc)) {
+ if (merge==MergeOverride) {
+ info->names[old]= 0;
+ info->files[old]= 0;
+ info->has_alt_forms[old]= True;
+ if (reportCollisions) {
+ WARN1("Key name <%s> assigned to multiple keys\n",name);
+ ACTION2("Using %d, ignoring %d\n",kc,old);
+ }
+ }
+ else if (merge!=MergeAltForm) {
+ if ((reportCollisions)&&(warningLevel>3)) {
+ WARN1("Key name <%s> assigned to multiple keys\n",name);
+ ACTION2("Using %d, ignoring %d\n",old,kc);
+ ACTION("Use 'alternate' keyword to assign the same name to multiple keys\n");
+ }
+ return True;
+ }
+ else {
+ info->has_alt_forms[old]= True;
+ }
+ }
+ info->names[kc]= lval;
+ info->files[kc]= fileID;
+ info->has_alt_forms[kc]= (merge==MergeAltForm);
+ return True;
+}
+
+/***====================================================================***/
+
+static void
+#if NeedFunctionPrototypes
+MergeIncludedKeycodes(KeyNamesInfo *into,KeyNamesInfo *from,unsigned merge)
+#else
+MergeIncludedKeycodes(into,from,merge)
+ KeyNamesInfo * into;
+ KeyNamesInfo * from;
+ unsigned merge;
+#endif
+{
+register int i;
+char buf[5];
+
+ if (from->errorCount>0) {
+ into->errorCount+= from->errorCount;
+ return;
+ }
+ if (into->name==NULL) {
+ into->name= from->name;
+ from->name= NULL;
+ }
+ for (i=from->computedMin;i<=from->computedMax;i++) {
+ unsigned thisMerge;
+ if (from->names[i]==0)
+ continue;
+ LongToKeyName(from->names[i],buf);
+ buf[4]= '\0';
+ if (from->has_alt_forms[i])
+ thisMerge= MergeAltForm;
+ else thisMerge= merge;
+ if (!AddKeyName(into,i,buf,thisMerge,from->fileID,False))
+ into->errorCount++;
+ }
+ if (from->leds) {
+ IndicatorNameInfo *led,*next;
+ for (led=from->leds;led!=NULL;led=next) {
+ if (merge!=MergeDefault)
+ led->defs.merge= merge;
+ if (!AddIndicatorName(into,led))
+ into->errorCount++;
+ next= (IndicatorNameInfo *)led->defs.next;
+ }
+ }
+ if (!MergeAliases(&into->aliases,&from->aliases,merge))
+ into->errorCount++;
+ if (from->explicitMin>0) {
+ if ((into->explicitMin<0)||(into->explicitMin>from->explicitMin))
+ into->effectiveMin= into->explicitMin= from->explicitMin;
+ }
+ if (from->explicitMax>0) {
+ if ((into->explicitMax<0)||(into->explicitMax<from->explicitMax))
+ into->effectiveMax= into->explicitMax= from->explicitMax;
+ }
+ return;
+}
+
+typedef void (*FileHandler)(
+#if NeedFunctionPrototypes
+ XkbFile * /* rtrn */,
+ XkbDescPtr /* xkb */,
+ unsigned /* merge */,
+ KeyNamesInfo * /* included */
+#endif
+);
+
+static Bool
+#if NeedFunctionPrototypes
+HandleIncludeKeycodes( IncludeStmt * stmt,
+ XkbDescPtr xkb,
+ KeyNamesInfo * info,
+ FileHandler hndlr)
+#else
+HandleIncludeKeycodes(stmt,xkb,info,hndlr)
+ IncludeStmt * stmt;
+ XkbDescPtr xkb;
+ KeyNamesInfo * info;
+ FileHandler hndlr;
+#endif
+{
+unsigned newMerge;
+XkbFile * rtrn;
+KeyNamesInfo included;
+Bool haveSelf;
+
+ haveSelf= False;
+ if ((stmt->file==NULL)&&(stmt->map==NULL)) {
+ haveSelf= True;
+ included= *info;
+ bzero(info,sizeof(KeyNamesInfo));
+ }
+ else if (strcmp(stmt->file,"computed")==0) {
+ xkb->flags|= AutoKeyNames;
+ info->explicitMin= XkbMinLegalKeyCode;
+ info->explicitMax= XkbMaxLegalKeyCode;
+ return (info->errorCount==0);
+ }
+ else if (ProcessIncludeFile(stmt,XkmKeyNamesIndex,&rtrn,&newMerge)) {
+ InitKeyNamesInfo(&included);
+ (*hndlr)(rtrn,xkb,MergeOverride,&included);
+ if (stmt->stmt!=NULL) {
+ if (included.name!=NULL)
+ uFree(included.name);
+ included.name= stmt->stmt;
+ stmt->stmt= NULL;
+ }
+ }
+ else {
+ info->errorCount+= 10;
+ return False;
+ }
+ if ((stmt->next!=NULL)&&(included.errorCount<1)) {
+ IncludeStmt * next;
+ unsigned op;
+ KeyNamesInfo next_incl;
+
+ for (next=stmt->next;next!=NULL;next=next->next) {
+ if ((next->file==NULL)&&(next->map==NULL)) {
+ haveSelf= True;
+ MergeIncludedKeycodes(&included,info,next->merge);
+ ClearKeyNamesInfo(info);
+ }
+ else if (ProcessIncludeFile(next,XkmKeyNamesIndex,&rtrn,&op)) {
+ InitKeyNamesInfo(&next_incl);
+ (*hndlr)(rtrn,xkb,MergeOverride,&next_incl);
+ MergeIncludedKeycodes(&included,&next_incl,op);
+ ClearKeyNamesInfo(&next_incl);
+ }
+ else {
+ info->errorCount+= 10;
+ return False;
+ }
+ }
+ }
+ if (haveSelf)
+ *info= included;
+ else {
+ MergeIncludedKeycodes(info,&included,newMerge);
+ ClearKeyNamesInfo(&included);
+ }
+ return (info->errorCount==0);
+}
+
+static int
+#if NeedFunctionPrototypes
+HandleKeycodeDef( KeycodeDef * stmt,
+ XkbDescPtr xkb,
+ unsigned merge,
+ KeyNamesInfo * info)
+#else
+HandleKeycodeDef(stmt,xkb,merge,info)
+ KeycodeDef * stmt;
+ XkbDescPtr xkb;
+ unsigned merge;
+ KeyNamesInfo * info;
+#endif
+{
+int code;
+ExprResult result;
+
+ if (!ExprResolveInteger(stmt->value,&result,NULL,NULL)) {
+ ACTION1("No value keycode assigned to name <%s>\n",stmt->name);
+ return 0;
+ }
+ code= result.ival;
+ if ((code<info->effectiveMin)||(code>info->effectiveMax)) {
+ ERROR2("Illegal keycode %d for name <%s>\n",code,stmt->name);
+ ACTION2("Must be in the range %d-%d inclusive\n",info->effectiveMin,
+ info->effectiveMax);
+ return 0;
+ }
+ if (stmt->merge!=MergeDefault) {
+ if (stmt->merge==MergeReplace)
+ merge= MergeOverride;
+ else merge= stmt->merge;
+ }
+ return AddKeyName(info,code,stmt->name,merge,info->fileID,True);
+}
+
+#define MIN_KEYCODE_DEF 0
+#define MAX_KEYCODE_DEF 1
+
+static int
+#if NeedFunctionPrototypes
+HandleKeyNameVar(VarDef *stmt,XkbDescPtr xkb,unsigned merge,KeyNamesInfo *info)
+#else
+HandleKeyNameVar(stmt,xkb,merge,info)
+ VarDef * stmt;
+ XkbDescPtr xkb;
+ unsigned merge;
+ KeyNamesInfo * info;
+#endif
+{
+ExprResult tmp,field;
+ExprDef * arrayNdx;
+int which;
+
+ if (ExprResolveLhs(stmt->name,&tmp,&field,&arrayNdx)==0)
+ return 0; /* internal error, already reported */
+
+ if (tmp.str!=NULL) {
+ ERROR1("Unknown element %s encountered\n",tmp.str);
+ ACTION1("Default for field %s ignored\n",field.str);
+ return 0;
+ }
+ if (uStrCaseCmp(field.str,"minimum")==0) which= MIN_KEYCODE_DEF;
+ else if (uStrCaseCmp(field.str,"maximum")==0) which= MAX_KEYCODE_DEF;
+ else {
+ ERROR("Unknown field encountered\n");
+ ACTION1("Assigment to field %s ignored\n",field.str);
+ return 0;
+ }
+ if (arrayNdx!=NULL) {
+ ERROR1("The %s setting is not an array\n",field.str);
+ ACTION("Illegal array reference ignored\n");
+ return 0;
+ }
+
+ if (ExprResolveInteger(stmt->value,&tmp,NULL,NULL)==0) {
+ ACTION1("Assignment to field %s ignored\n",field.str);
+ return 0;
+ }
+ if ((tmp.ival<XkbMinLegalKeyCode)||(tmp.ival>XkbMaxLegalKeyCode)) {
+ ERROR3("Illegal keycode %d (must be in the range %d-%d inclusive)\n",
+ tmp.ival,XkbMinLegalKeyCode,XkbMaxLegalKeyCode);
+ ACTION1("Value of \"%s\" not changed\n",field.str);
+ return 0;
+ }
+ if (which==MIN_KEYCODE_DEF) {
+ if ((info->explicitMax>0)&&(info->explicitMax<tmp.ival)) {
+ ERROR2("Minimum key code (%d) must be <= maximum key code (%d)\n",
+ tmp.ival,info->explicitMax);
+ ACTION("Minimum key code value not changed\n");
+ return 0;
+ }
+ if ((info->computedMax>0)&&(info->computedMin<tmp.ival)) {
+ ERROR2("Minimum key code (%d) must be <= lowest defined key (%d)\n",
+ tmp.ival,info->computedMin);
+ ACTION("Minimum key code value not changed\n");
+ return 0;
+ }
+ info->explicitMin= tmp.ival;
+ info->effectiveMin= tmp.ival;
+ }
+ if (which==MAX_KEYCODE_DEF) {
+ if ((info->explicitMin>0)&&(info->explicitMin>tmp.ival)) {
+ ERROR2("Maximum code (%d) must be >= minimum key code (%d)\n",
+ tmp.ival,info->explicitMin);
+ ACTION("Maximum code value not changed\n");
+ return 0;
+ }
+ if ((info->computedMax>0)&&(info->computedMax>tmp.ival)) {
+ ERROR2("Maximum code (%d) must be >= highest defined key (%d)\n",
+ tmp.ival,info->computedMax);
+ ACTION("Maximum code value not changed\n");
+ return 0;
+ }
+ info->explicitMax= tmp.ival;
+ info->effectiveMax= tmp.ival;
+ }
+ return 1;
+}
+
+static int
+#if NeedFunctionPrototypes
+HandleIndicatorNameDef( IndicatorNameDef * def,
+ XkbDescPtr xkb,
+ unsigned merge,
+ KeyNamesInfo * info)
+#else
+HandleIndicatorNameDef(def,xkb,merge,info)
+ IndicatorNameDef * def;
+ XkbDescPtr xkb;
+ unsigned merge;
+ KeyNamesInfo * info;
+#endif
+{
+IndicatorNameInfo ii;
+ExprResult tmp;
+
+ if ((def->ndx<1)||(def->ndx>XkbNumIndicators)) {
+ info->errorCount++;
+ ERROR1("Name specified for illegal indicator index %d\n",def->ndx);
+ ACTION("Ignored\n");
+ return False;
+ }
+ InitIndicatorNameInfo(&ii,info);
+ ii.ndx= def->ndx;
+ if (!ExprResolveString(def->name,&tmp,NULL,NULL)) {
+ char buf[20];
+ sprintf(buf,"%d",def->ndx);
+ info->errorCount++;
+ return ReportBadType("indicator","name",buf,"string");
+ }
+ ii.name= XkbInternAtom(NULL,tmp.str,False);
+ ii.virtual= def->virtual;
+ if (!AddIndicatorName(info,&ii))
+ return False;
+ return True;
+}
+
+static void
+#if NeedFunctionPrototypes
+HandleKeycodesFile( XkbFile * file,
+ XkbDescPtr xkb,
+ unsigned merge,
+ KeyNamesInfo * info)
+#else
+HandleKeycodesFile(file,xkb,merge,info)
+ XkbFile *file;
+ XkbDescPtr xkb;
+ unsigned merge;
+ KeyNamesInfo *info;
+#endif
+{
+ParseCommon *stmt;
+
+ info->name= uStringDup(file->name);
+ stmt= file->defs;
+ while (stmt) {
+ switch (stmt->stmtType) {
+ case StmtInclude:
+ if (!HandleIncludeKeycodes((IncludeStmt *)stmt,xkb,info,
+ HandleKeycodesFile))
+ info->errorCount++;
+ break;
+ case StmtKeycodeDef:
+ if (!HandleKeycodeDef((KeycodeDef *)stmt,xkb,merge,info))
+ info->errorCount++;
+ break;
+ case StmtKeyAliasDef:
+ if (!HandleAliasDef((KeyAliasDef *)stmt,
+ merge,info->fileID,&info->aliases))
+ info->errorCount++;
+ break;
+ case StmtVarDef:
+ if (!HandleKeyNameVar((VarDef *)stmt,xkb,merge,info))
+ info->errorCount++;
+ break;
+ case StmtIndicatorNameDef:
+ if (!HandleIndicatorNameDef((IndicatorNameDef *)stmt,xkb,
+ merge,info)) {
+ info->errorCount++;
+ }
+ break;
+ case StmtInterpDef:
+ case StmtVModDef:
+ ERROR("Keycode files may define key and indicator names only\n");
+ ACTION1("Ignoring definition of %s\n",
+ ((stmt->stmtType==StmtInterpDef)?
+ "a symbol interpretation":
+ "virtual modifiers"));
+ info->errorCount++;
+ break;
+ default:
+ WSGO1("Unexpected statement type %d in HandleKeycodesFile\n",
+ stmt->stmtType);
+ break;
+ }
+ stmt= stmt->next;
+ if (info->errorCount>10) {
+#ifdef NOISY
+ ERROR("Too many errors\n");
+#endif
+ ACTION1("Abandoning keycodes file \"%s\"\n",file->topName);
+ break;
+ }
+ }
+ return;
+}
+
+Bool
+#if NeedFunctionPrototypes
+CompileKeycodes(XkbFile *file,XkbFileInfo *result,unsigned merge)
+#else
+CompileKeycodes(file,result,merge)
+ XkbFile * file;
+ XkbFileInfo * result;
+ unsigned merge;
+#endif
+{
+KeyNamesInfo info;
+XkbDescPtr xkb;
+
+ xkb= result->xkb;
+ InitKeyNamesInfo(&info);
+ HandleKeycodesFile(file,xkb,merge,&info);
+
+ if (info.errorCount==0) {
+ if (info.explicitMin>0)
+ xkb->min_key_code= info.effectiveMin;
+ else xkb->min_key_code= info.computedMin;
+ if (info.explicitMax>0)
+ xkb->max_key_code= info.effectiveMax;
+ else xkb->max_key_code= info.computedMax;
+ if (XkbAllocNames(xkb,XkbKeyNamesMask|XkbIndicatorNamesMask,0,0)==Success) {
+ register int i;
+ xkb->names->keycodes= XkbInternAtom(xkb->dpy,info.name,False);
+ uDEBUG2(1,"key range: %d..%d\n",xkb->min_key_code,xkb->max_key_code);
+ for (i=info.computedMin;i<=info.computedMax;i++) {
+ LongToKeyName(info.names[i],xkb->names->keys[i].name);
+ uDEBUG2(2,"key %d = %s\n",i,
+ XkbKeyNameText(xkb->names->keys[i].name,XkbMessage));
+ }
+ }
+ else {
+ WSGO("Cannot create XkbNamesRec in CompileKeycodes\n");
+ return False;
+ }
+ if (info.leds) {
+ IndicatorNameInfo *ii;
+ if (XkbAllocIndicatorMaps(xkb)!=Success) {
+ WSGO("Couldn't allocate IndicatorRec in CompileKeycodes\n");
+ ACTION("Physical indicators not set\n");
+ }
+ for (ii=info.leds;ii!=NULL;ii=(IndicatorNameInfo *)ii->defs.next){
+ xkb->names->indicators[ii->ndx-1]=
+ XkbInternAtom(xkb->dpy,
+ XkbAtomGetString(NULL,ii->name),False);
+ if (xkb->indicators!=NULL) {
+ register unsigned bit;
+ bit= 1<<(ii->ndx-1);
+ if (ii->virtual)
+ xkb->indicators->phys_indicators&= ~bit;
+ else xkb->indicators->phys_indicators|= bit;
+ }
+ }
+ }
+ if (info.aliases)
+ ApplyAliases(xkb,False,&info.aliases);
+ return True;
+ }
+ ClearKeyNamesInfo(&info);
+ return False;
+}
diff --git a/keycodes.h b/keycodes.h
new file mode 100644
index 0000000..3e93054
--- /dev/null
+++ b/keycodes.h
@@ -0,0 +1,47 @@
+/* $Xorg: keycodes.h,v 1.3 2000/08/17 19:54:32 cpqbld Exp $ */
+/************************************************************
+ 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
+ documentation, and that the name of Silicon Graphics not be
+ used in advertising or publicity pertaining to distribution
+ of the software without specific prior written permission.
+ Silicon Graphics makes no representation about the suitability
+ of this software for any purpose. It is provided "as is"
+ without any express or implied warranty.
+
+ SILICON GRAPHICS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS
+ SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+ AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL SILICON
+ 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
+ OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH
+ THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+ ********************************************************/
+
+#ifndef KEYCODES_H
+#define KEYCODES_H 1
+
+#define KeyNameToLong(n) ((((unsigned long)n[0])<<24)|(((unsigned long)n[1])<<16)|(((unsigned long)n[2])<<8)|n[3])
+
+extern char * longText(
+#if NeedFunctionPrototypes
+ unsigned long /* val */,
+ unsigned /* format */
+#endif
+);
+
+extern void LongToKeyName(
+#if NeedFunctionPrototypes
+ unsigned long /* val */,
+ char * /* name_rtrn */
+#endif
+);
+
+#endif /* KEYCODES_H */
diff --git a/keymap.c b/keymap.c
new file mode 100644
index 0000000..e696e8d
--- /dev/null
+++ b/keymap.c
@@ -0,0 +1,174 @@
+/* $Xorg: keymap.c,v 1.3 2000/08/17 19:54:32 cpqbld Exp $ */
+/************************************************************
+ 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
+ documentation, and that the name of Silicon Graphics not be
+ used in advertising or publicity pertaining to distribution
+ of the software without specific prior written permission.
+ Silicon Graphics makes no representation about the suitability
+ of this software for any purpose. It is provided "as is"
+ without any express or implied warranty.
+
+ SILICON GRAPHICS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS
+ SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+ AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL SILICON
+ 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
+ OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH
+ THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+ ********************************************************/
+
+#include "xkbcomp.h"
+#include "tokens.h"
+#include "expr.h"
+#include "vmod.h"
+#include "action.h"
+#include "misc.h"
+#include "indicators.h"
+
+#define KEYCODES 0
+#define GEOMETRY 1
+#define TYPES 2
+#define COMPAT 3
+#define SYMBOLS 4
+#define MAX_SECTIONS 5
+
+XkbFile * sections[MAX_SECTIONS];
+
+Bool
+#if NeedFunctionPrototypes
+CompileKeymap(XkbFile *file,XkbFileInfo *result,unsigned merge)
+#else
+CompileKeymap(file,result,merge)
+ XkbFile * file;
+ XkbFileInfo * result;
+ unsigned merge;
+#endif
+{
+unsigned have;
+Bool ok;
+unsigned required,legal;
+unsigned mainType;
+char * mainName;
+LEDInfo * unbound= NULL;
+
+ bzero(sections,MAX_SECTIONS*sizeof(XkbFile *));
+ mainType= file->type;
+ mainName= file->name;
+ switch (mainType) {
+ case XkmSemanticsFile:
+ required= XkmSemanticsRequired;
+ legal= XkmSemanticsLegal;
+ break;
+ case XkmLayoutFile:
+ required= XkmLayoutRequired;
+ legal= XkmKeymapLegal;
+ break;
+ case XkmKeymapFile:
+ required= XkmKeymapRequired;
+ legal= XkmKeymapLegal;
+ break;
+ default:
+ ERROR1("Cannot compile %s alone into an XKM file\n",
+ XkbConfigText(mainType,XkbMessage));
+ return False;
+ }
+ have= 0;
+ ok= 1;
+ file= (XkbFile *)file->defs;
+ while ((file)&&(ok)) {
+ file->topName= mainName;
+ if ((have&(1<<file->type))!=0) {
+ ERROR2("More than one %s section in a %s file\n",
+ XkbConfigText(file->type,XkbMessage),
+ XkbConfigText(mainType,XkbMessage));
+ ACTION("All sections after the first ignored\n");
+ ok= False;
+ }
+ else if ((1<<file->type)&(~legal)) {
+ ERROR2("Cannot define %s in a %s file\n",
+ XkbConfigText(file->type,XkbMessage),
+ XkbConfigText(mainType,XkbMessage));
+ ok= False;
+ }
+ else switch (file->type) {
+ case XkmSemanticsFile:
+ case XkmLayoutFile:
+ case XkmKeymapFile:
+ WSGO2("Illegal %s configuration in a %s file\n",
+ XkbConfigText(file->type,XkbMessage),
+ XkbConfigText(mainType,XkbMessage));
+ ACTION("Ignored\n");
+ ok= False;
+ break;
+ case XkmKeyNamesIndex:
+ sections[KEYCODES]= file;
+ break;
+ case XkmTypesIndex:
+ sections[TYPES]= file;
+ break;
+ case XkmSymbolsIndex:
+ sections[SYMBOLS]= file;
+ break;
+ case XkmCompatMapIndex:
+ sections[COMPAT]= file;
+ break;
+ case XkmGeometryIndex:
+ case XkmGeometryFile:
+ sections[GEOMETRY]= file;
+ break;
+ case XkmVirtualModsIndex:
+ case XkmIndicatorsIndex:
+ WSGO1("Found an isolated %s section\n",
+ XkbConfigText(file->type,XkbMessage));
+ break;
+ default:
+ WSGO1("Unknown file type %d\n",file->type);
+ break;
+ }
+ if (ok)
+ have|= (1<<file->type);
+ file= (XkbFile*)file->common.next;
+ }
+ if (ok) {
+ if (ok && (sections[KEYCODES]!=NULL))
+ ok= CompileKeycodes(sections[KEYCODES],result,MergeOverride);
+ if (ok && (sections[GEOMETRY]!=NULL))
+ ok= CompileGeometry(sections[GEOMETRY],result,MergeOverride);
+ if (ok && (sections[TYPES]!=NULL))
+ ok= CompileKeyTypes(sections[TYPES],result,MergeOverride);
+ if (ok && (sections[COMPAT]!=NULL))
+ ok=CompileCompatMap(sections[COMPAT],result,MergeOverride,&unbound);
+ if (ok && (sections[SYMBOLS]!=NULL))
+ ok= CompileSymbols(sections[SYMBOLS],result,MergeOverride);
+ }
+ if (!ok)
+ return False;
+ result->defined= have;
+ if (required&(~have)) {
+ register int i,bit;
+ unsigned missing;
+ missing= required&(~have);
+ for (i=0,bit=1;missing!=0;i++,bit<<=1) {
+ if (missing&bit) {
+ ERROR2("Missing %s section in a %s file\n",
+ XkbConfigText(i,XkbMessage),
+ XkbConfigText(mainType,XkbMessage));
+ missing&=~bit;
+ }
+ }
+ ACTION1("Description of %s not compiled\n",
+ XkbConfigText(mainType,XkbMessage));
+ ok= False;
+ }
+ ok= BindIndicators(result,True,unbound,NULL);
+ return ok;
+}
+
diff --git a/keytypes.c b/keytypes.c
new file mode 100644
index 0000000..2b2db13
--- /dev/null
+++ b/keytypes.c
@@ -0,0 +1,1353 @@
+/* $Xorg: keytypes.c,v 1.3 2000/08/17 19:54:32 cpqbld Exp $ */
+/************************************************************
+ 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
+ documentation, and that the name of Silicon Graphics not be
+ used in advertising or publicity pertaining to distribution
+ of the software without specific prior written permission.
+ Silicon Graphics makes no representation about the suitability
+ of this software for any purpose. It is provided "as is"
+ without any express or implied warranty.
+
+ SILICON GRAPHICS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS
+ SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+ AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL SILICON
+ 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
+ OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH
+ THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+ ********************************************************/
+
+#include "xkbcomp.h"
+#include "tokens.h"
+#include "expr.h"
+#include "vmod.h"
+#include "action.h"
+#include "misc.h"
+
+typedef struct _PreserveInfo {
+ CommonInfo defs;
+ short matchingMapIndex;
+ unsigned char indexMods;
+ unsigned char preMods;
+ unsigned short indexVMods;
+ unsigned short preVMods;
+} PreserveInfo;
+
+#define _KT_Name (1<<0)
+#define _KT_Mask (1<<1)
+#define _KT_Map (1<<2)
+#define _KT_Preserve (1<<3)
+#define _KT_LevelNames (1<<4)
+
+typedef struct _KeyTypeInfo {
+ CommonInfo defs;
+ Display * dpy;
+ Atom name;
+ int fileID;
+ unsigned mask;
+ unsigned vmask;
+ Bool groupInfo;
+ int numLevels;
+ int nEntries;
+ int szEntries;
+ XkbKTMapEntryPtr entries;
+ PreserveInfo * preserve;
+ int szNames;
+ Atom * lvlNames;
+} KeyTypeInfo;
+
+typedef struct _KeyTypesInfo {
+ Display * dpy;
+ char * name;
+ int errorCount;
+ int fileID;
+ unsigned stdPresent;
+ int nTypes;
+ KeyTypeInfo * types;
+ KeyTypeInfo dflt;
+ VModInfo vmods;
+} KeyTypesInfo;
+
+Atom tok_ONE_LEVEL;
+Atom tok_TWO_LEVEL;
+Atom tok_ALPHABETIC;
+Atom tok_KEYPAD;
+
+/***====================================================================***/
+
+#define ReportTypeShouldBeArray(t,f) \
+ ReportShouldBeArray("key type",(f),TypeTxt(t))
+#define ReportTypeBadType(t,f,w) \
+ ReportBadType("key type",(f),TypeTxt(t),(w))
+
+/***====================================================================***/
+
+_XFUNCPROTOBEGIN
+
+extern Bool AddMapEntry(
+#if NeedFunctionPrototypes
+ XkbDescPtr /* xkb */,
+ KeyTypeInfo * /* type */,
+ XkbKTMapEntryPtr /* new */,
+ Bool /* clobber */,
+ Bool /* report */
+#endif
+);
+
+extern Bool AddPreserve(
+#if NeedFunctionPrototypes
+ XkbDescPtr /* xkb */,
+ KeyTypeInfo * /* type */,
+ PreserveInfo * /* new */,
+ Bool /* clobber */,
+ Bool /* report */
+#endif
+);
+
+extern Bool AddLevelName(
+#if NeedFunctionPrototypes
+ KeyTypeInfo * /* type */,
+ unsigned /* level */,
+ Atom /* name */,
+ Bool /* clobber */,
+ Bool /* report */
+#endif
+);
+
+_XFUNCPROTOEND
+
+#define MapEntryTxt(t,x,e) \
+ XkbVModMaskText((t)->dpy,(x),(e)->mods.real_mods,(e)->mods.vmods,XkbMessage)
+#define PreserveIndexTxt(t,x,p) \
+ XkbVModMaskText((t)->dpy,(x),(p)->indexMods,(p)->indexVMods,XkbMessage)
+#define PreserveTxt(t,x,p) \
+ XkbVModMaskText((t)->dpy,(x),(p)->preMods,(p)->preVMods,XkbMessage)
+#define TypeTxt(t) XkbAtomText((t)->dpy,(t)->name,XkbMessage)
+#define TypeMaskTxt(t,x) \
+ XkbVModMaskText((t)->dpy,(x),(t)->mask,(t)->vmask,XkbMessage)
+
+/***====================================================================***/
+
+static void
+#if NeedFunctionPrototypes
+InitKeyTypesInfo(KeyTypesInfo *info,XkbDescPtr xkb,KeyTypesInfo *from)
+#else
+InitKeyTypesInfo(info,xkb,from)
+ KeyTypesInfo * info;
+ XkbDescPtr xkb;
+ KeyTypesInfo * from;
+#endif
+{
+ tok_ONE_LEVEL= XkbInternAtom(NULL,"ONE_LEVEL",False);
+ tok_TWO_LEVEL= XkbInternAtom(NULL,"TWO_LEVEL",False);
+ tok_ALPHABETIC= XkbInternAtom(NULL,"ALPHABETIC",False);
+ tok_KEYPAD= XkbInternAtom(NULL,"KEYPAD",False);
+ info->dpy= NULL;
+ info->name= uStringDup("default");
+ info->errorCount= 0;
+ info->stdPresent= 0;
+ info->nTypes= 0;
+ info->types= NULL;
+ info->dflt.defs.defined= 0;
+ info->dflt.defs.fileID= 0;
+ info->dflt.defs.merge= MergeOverride;
+ info->dflt.defs.next= NULL;
+ info->dflt.name= None;
+ info->dflt.mask= 0;
+ info->dflt.vmask= 0;
+ info->dflt.groupInfo= False;
+ info->dflt.numLevels= 1;
+ info->dflt.nEntries= info->dflt.szEntries= 0;
+ info->dflt.entries= NULL;
+ info->dflt.szNames= 0;
+ info->dflt.lvlNames= NULL;
+ info->dflt.preserve= NULL;
+ InitVModInfo(&info->vmods,xkb);
+ if (from!=NULL) {
+ info->dpy= from->dpy;
+ info->dflt= from->dflt;
+ if (from->dflt.entries) {
+ info->dflt.entries= uTypedCalloc(from->dflt.szEntries,
+ XkbKTMapEntryRec);
+ if (info->dflt.entries) {
+ unsigned sz = from->dflt.nEntries*sizeof(XkbKTMapEntryRec);
+ memcpy(info->dflt.entries,from->dflt.entries,sz);
+ }
+ }
+ if (from->dflt.lvlNames) {
+ info->dflt.lvlNames= uTypedCalloc(from->dflt.szNames,Atom);
+ if (info->dflt.lvlNames) {
+ register unsigned sz = from->dflt.szNames*sizeof(Atom);
+ memcpy(info->dflt.lvlNames,from->dflt.lvlNames,sz);
+ }
+ }
+ if (from->dflt.preserve) {
+ PreserveInfo *old,*new,*last;
+ last= NULL;
+ old= from->dflt.preserve;
+ for (;old;old=(PreserveInfo *)old->defs.next) {
+ new= uTypedAlloc(PreserveInfo);
+ if (!new)
+ return;
+ *new= *old;
+ new->defs.next= NULL;
+ if (last) last->defs.next= (CommonInfo *)new;
+ else info->dflt.preserve= new;
+ last= new;
+ }
+ }
+ }
+ return;
+}
+
+static void
+#if NeedFunctionPrototypes
+FreeKeyTypeInfo(KeyTypeInfo *type)
+#else
+FreeKeyTypeInfo(type)
+ KeyTypeInfo * type;
+#endif
+{
+ if (type->entries!=NULL) {
+ uFree(type->entries);
+ type->entries= NULL;
+ }
+ if (type->lvlNames!=NULL) {
+ uFree(type->lvlNames);
+ type->lvlNames= NULL;
+ }
+ if (type->preserve!=NULL) {
+ ClearCommonInfo(&type->preserve->defs);
+ type->preserve= NULL;
+ }
+ return;
+}
+
+static void
+#if NeedFunctionPrototypes
+FreeKeyTypesInfo(KeyTypesInfo *info)
+#else
+FreeKeyTypesInfo(info)
+ KeyTypesInfo * info;
+#endif
+{
+ info->dpy= NULL;
+ if (info->name)
+ uFree(info->name);
+ info->name= NULL;
+ if (info->types) {
+ register KeyTypeInfo *type;
+ for (type= info->types;type;type=(KeyTypeInfo *)type->defs.next) {
+ FreeKeyTypeInfo(type);
+ }
+ info->types= (KeyTypeInfo *)ClearCommonInfo(&info->types->defs);
+ }
+ FreeKeyTypeInfo(&info->dflt);
+ return;
+}
+
+static KeyTypeInfo *
+#if NeedFunctionPrototypes
+NextKeyType(KeyTypesInfo *info)
+#else
+NextKeyType(info)
+ KeyTypesInfo * info;
+#endif
+{
+KeyTypeInfo * type;
+
+ type= uTypedAlloc(KeyTypeInfo);
+ if (type!=NULL) {
+ bzero(type,sizeof(KeyTypeInfo));
+ type->defs.fileID= info->fileID;
+ type->dpy= info->dpy;
+ info->types= (KeyTypeInfo *)AddCommonInfo(&info->types->defs,
+ (CommonInfo *)type);
+ info->nTypes++;
+ }
+ return type;
+}
+
+static KeyTypeInfo *
+#if NeedFunctionPrototypes
+FindMatchingKeyType(KeyTypesInfo *info,KeyTypeInfo *new)
+#else
+FindMatchingKeyType(info,new)
+ KeyTypesInfo * info;
+ KeyTypeInfo * new;
+#endif
+{
+KeyTypeInfo *old;
+
+ for (old=info->types;old;old=(KeyTypeInfo *)old->defs.next) {
+ if (old->name==new->name)
+ return old;
+ }
+ return NULL;
+}
+
+static Bool
+#if NeedFunctionPrototypes
+ReportTypeBadWidth(char *type,int has,int needs)
+#else
+ReportTypeBadWidth(type,has,needs)
+ char * type;
+ int has;
+ int needs;
+#endif
+{
+ ERROR3("Key type \"%s\" has %d levels, must have %d\n",type,has,needs);
+ ACTION("Illegal type definition ignored\n");
+ return False;
+}
+
+static Bool
+#if NeedFunctionPrototypes
+AddKeyType(XkbDescPtr xkb,KeyTypesInfo *info,KeyTypeInfo *new)
+#else
+AddKeyType(xkb,info,new)
+ XkbDescPtr xkb;
+ KeyTypesInfo * info;
+ KeyTypeInfo * new;
+#endif
+{
+KeyTypeInfo * old;
+
+ if (new->name==tok_ONE_LEVEL) {
+ if (new->numLevels>1)
+ return ReportTypeBadWidth("ONE_LEVEL",new->numLevels,1);
+ info->stdPresent|= XkbOneLevelMask;
+ }
+ else if (new->name==tok_TWO_LEVEL) {
+ if (new->numLevels>2)
+ return ReportTypeBadWidth("TWO_LEVEL",new->numLevels,2);
+ else if (new->numLevels<2)
+ new->numLevels= 2;
+ info->stdPresent|= XkbTwoLevelMask;
+ }
+ else if (new->name==tok_ALPHABETIC) {
+ if (new->numLevels>2)
+ return ReportTypeBadWidth("ALPHABETIC",new->numLevels,2);
+ else if (new->numLevels<2)
+ new->numLevels= 2;
+ info->stdPresent|= XkbAlphabeticMask;
+ }
+ else if (new->name==tok_KEYPAD) {
+ if (new->numLevels>2)
+ return ReportTypeBadWidth("KEYPAD",new->numLevels,2);
+ else if (new->numLevels<2)
+ new->numLevels= 2;
+ info->stdPresent|= XkbKeypadMask;
+ }
+
+ old= FindMatchingKeyType(info,new);
+ if (old!=NULL) {
+ Bool report;
+ if ((new->defs.merge==MergeReplace)||(new->defs.merge==MergeOverride)) {
+ KeyTypeInfo *next= (KeyTypeInfo *)old->defs.next;
+ if (((old->defs.fileID==new->defs.fileID)&&(warningLevel>0))||
+ (warningLevel>9)) {
+ WARN1("Multiple definitions of the %s key type\n",
+ XkbAtomGetString(NULL,new->name));
+ ACTION("Earlier definition ignored\n");
+ }
+ FreeKeyTypeInfo(old);
+ *old= *new;
+ new->szEntries= new->nEntries= 0;
+ new->entries= NULL;
+ new->preserve= NULL;
+ new->lvlNames= NULL;
+ old->defs.next= &next->defs;
+ return True;
+ }
+ report= (old->defs.fileID==new->defs.fileID)&&(warningLevel>0);
+ if (report) {
+ WARN1("Multiple definitions of the %s key type\n",
+ XkbAtomGetString(NULL,new->name));
+ ACTION("Later definition ignored\n");
+ }
+ FreeKeyTypeInfo(new);
+ return True;
+ }
+ old= NextKeyType(info);
+ if (old==NULL)
+ return False;
+ *old= *new;
+ old->defs.next= NULL;
+ new->nEntries= new->szEntries= 0;
+ new->entries= NULL;
+ new->szNames= 0;
+ new->lvlNames= NULL;
+ new->preserve= NULL;
+ return True;
+}
+
+/***====================================================================***/
+
+static void
+#if NeedFunctionPrototypes
+MergeIncludedKeyTypes( KeyTypesInfo * into,
+ KeyTypesInfo * from,
+ unsigned merge,
+ XkbDescPtr xkb)
+#else
+MergeIncludedKeyTypes(into,from,merge,xkb)
+ KeyTypesInfo *into;
+ KeyTypesInfo *from;
+ unsigned merge;
+ XkbDescPtr xkb;
+#endif
+{
+KeyTypeInfo * type;
+
+ if (from->errorCount>0) {
+ into->errorCount+= from->errorCount;
+ return;
+ }
+ if (into->name==NULL) {
+ into->name= from->name;
+ from->name= NULL;
+ }
+ for (type=from->types;type;type=(KeyTypeInfo *)type->defs.next) {
+ if (merge!=MergeDefault)
+ type->defs.merge= merge;
+ if (!AddKeyType(xkb,into,type))
+ into->errorCount++;
+ }
+ into->stdPresent|= from->stdPresent;
+ return;
+}
+
+typedef void (*FileHandler)(
+#if NeedFunctionPrototypes
+ XkbFile * /* file */,
+ XkbDescPtr /* xkb */,
+ unsigned /* merge */,
+ KeyTypesInfo * /* included */
+#endif
+);
+
+static Bool
+#if NeedFunctionPrototypes
+HandleIncludeKeyTypes( IncludeStmt * stmt,
+ XkbDescPtr xkb,
+ KeyTypesInfo * info,
+ FileHandler hndlr)
+#else
+HandleIncludeKeyTypes(stmt,xkb,info,hndlr)
+ IncludeStmt * stmt;
+ XkbDescPtr xkb;
+ KeyTypesInfo * info;
+ FileHandler hndlr;
+#endif
+{
+unsigned newMerge;
+XkbFile * rtrn;
+KeyTypesInfo included;
+Bool haveSelf;
+
+ haveSelf= False;
+ if ((stmt->file==NULL)&&(stmt->map==NULL)) {
+ haveSelf= True;
+ included= *info;
+ bzero(info,sizeof(KeyTypesInfo));
+ }
+ else if (ProcessIncludeFile(stmt,XkmTypesIndex,&rtrn,&newMerge)) {
+ InitKeyTypesInfo(&included,xkb,info);
+ included.fileID= included.dflt.defs.fileID= rtrn->id;
+ included.dflt.defs.merge= newMerge;
+
+ (*hndlr)(rtrn,xkb,newMerge,&included);
+ if (stmt->stmt!=NULL) {
+ if (included.name!=NULL)
+ uFree(included.name);
+ included.name= stmt->stmt;
+ stmt->stmt= NULL;
+ }
+ }
+ else {
+ info->errorCount+= 10;
+ return False;
+ }
+ if ((stmt->next!=NULL)&&(included.errorCount<1)) {
+ IncludeStmt * next;
+ unsigned op;
+ KeyTypesInfo next_incl;
+
+ for (next=stmt->next;next!=NULL;next=next->next) {
+ if ((next->file==NULL)&&(next->map==NULL)) {
+ haveSelf= True;
+ MergeIncludedKeyTypes(&included,info,next->merge,xkb);
+ FreeKeyTypesInfo(info);
+ }
+ else if (ProcessIncludeFile(next,XkmTypesIndex,&rtrn,&op)) {
+ InitKeyTypesInfo(&next_incl,xkb,&included);
+ next_incl.fileID= next_incl.dflt.defs.fileID= rtrn->id;
+ next_incl.dflt.defs.merge= op;
+ (*hndlr)(rtrn,xkb,op,&next_incl);
+ MergeIncludedKeyTypes(&included,&next_incl,op,xkb);
+ FreeKeyTypesInfo(&next_incl);
+ }
+ else {
+ info->errorCount+= 10;
+ return False;
+ }
+ }
+ }
+ if (haveSelf)
+ *info= included;
+ else {
+ MergeIncludedKeyTypes(info,&included,newMerge,xkb);
+ FreeKeyTypesInfo(&included);
+ }
+ return (info->errorCount==0);
+}
+
+/***====================================================================***/
+
+static XkbKTMapEntryPtr
+#if NeedFunctionPrototypes
+FindMatchingMapEntry(KeyTypeInfo *type,unsigned mask,unsigned vmask)
+#else
+FindMatchingMapEntry(type,mask,vmask)
+ KeyTypeInfo * type;
+ unsigned mask;
+ unsigned vmask;
+#endif
+{
+register int i;
+XkbKTMapEntryPtr entry;
+
+ for (i=0,entry=type->entries;i<type->nEntries;i++,entry++) {
+ if ((entry->mods.real_mods==mask)&&(entry->mods.vmods==vmask))
+ return entry;
+ }
+ return NULL;
+}
+
+static void
+#if NeedFunctionPrototypes
+DeleteLevel1MapEntries(KeyTypeInfo *type)
+#else
+DeleteLevel1MapEntries(type)
+ KeyTypeInfo * type;
+#endif
+{
+register int i,n;
+
+ for (i=0;i<type->nEntries;i++) {
+ if (type->entries[i].level==0) {
+ for (n=i;n<type->nEntries-1;n++) {
+ type->entries[n]= type->entries[n+1];
+ }
+ type->nEntries--;
+ }
+ }
+ return;
+}
+
+static XkbKTMapEntryPtr
+#if NeedFunctionPrototypes
+NextMapEntry(KeyTypeInfo *type)
+#else
+NextMapEntry(type)
+ KeyTypeInfo * type;
+#endif
+{
+ if (type->entries==NULL) {
+ type->entries= uTypedCalloc(2,XkbKTMapEntryRec);
+ if (type->entries==NULL) {
+ ERROR1("Couldn't allocate map entries for %s\n",TypeTxt(type));
+ ACTION("Map entries lost\n");
+ return NULL;
+ }
+ type->szEntries= 2;
+ type->nEntries= 0;
+ }
+ else if (type->nEntries>=type->szEntries) {
+ type->szEntries*=2;
+ type->entries= uTypedRecalloc(type->entries,
+ type->nEntries,type->szEntries,
+ XkbKTMapEntryRec);
+ if (type->entries==NULL) {
+ ERROR1("Couldn't reallocate map entries for %s\n",TypeTxt(type));
+ ACTION("Map entries lost\n");
+ return NULL;
+ }
+ }
+ return &type->entries[type->nEntries++];
+}
+
+Bool
+#if NeedFunctionPrototypes
+AddPreserve( XkbDescPtr xkb,
+ KeyTypeInfo * type,
+ PreserveInfo * new,
+ Bool clobber,
+ Bool report)
+#else
+AddPreserve(xkb,type,new,clobber,report)
+ XkbDescPtr xkb;
+ KeyTypeInfo * type;
+ PreserveInfo * new;
+ Bool clobber;
+ Bool report;
+#endif
+{
+PreserveInfo *old;
+
+ old= type->preserve;
+ while (old!=NULL) {
+ if ((old->indexMods!=new->indexMods)||
+ (old->indexVMods!=new->indexVMods)) {
+ old= (PreserveInfo *)old->defs.next;
+ continue;
+ }
+ if ((old->preMods==new->preMods)&&(old->preVMods==new->preVMods)) {
+ if (warningLevel>9) {
+ WARN2("Identical definitions for preserve[%s] in %s\n",
+ PreserveIndexTxt(type,xkb,old),TypeTxt(type));
+ ACTION("Ignored\n");
+ }
+ return True;
+ }
+ if (report && (warningLevel>0)) {
+ char *str;
+ WARN2("Multiple definitions for preserve[%s] in %s\n",
+ PreserveIndexTxt(type,xkb,old),TypeTxt(type));
+
+ if (clobber) str= PreserveTxt(type,xkb,new);
+ else str= PreserveTxt(type,xkb,old);
+ ACTION1("Using %s, ",str);
+ if (clobber) str= PreserveTxt(type,xkb,old);
+ else str= PreserveTxt(type,xkb,new);
+ INFO1("ignoring %s\n",str);
+ }
+ if (clobber) {
+ old->preMods= new->preMods;
+ old->preVMods= new->preVMods;
+ }
+ return True;
+ }
+ old= uTypedAlloc(PreserveInfo);
+ if (!old) {
+ WSGO1("Couldn't allocate preserve in %s\n",TypeTxt(type));
+ ACTION1("Preserve[%s] lost\n",PreserveIndexTxt(type,xkb,old));
+ return False;
+ }
+ *old= *new;
+ old->matchingMapIndex= -1;
+ type->preserve=(PreserveInfo*)AddCommonInfo(&type->preserve->defs,&old->defs);
+ return True;
+}
+
+Bool
+#if NeedFunctionPrototypes
+AddMapEntry( XkbDescPtr xkb,
+ KeyTypeInfo * type,
+ XkbKTMapEntryPtr new,
+ Bool clobber,
+ Bool report)
+#else
+AddMapEntry(xkb,type,new,clobber,report)
+ XkbDescPtr xkb;
+ KeyTypeInfo * type;
+ XkbKTMapEntryPtr new;
+ Bool clobber;
+ Bool report;
+#endif
+{
+XkbKTMapEntryPtr old;
+
+ if ((old=FindMatchingMapEntry(type,new->mods.real_mods,new->mods.vmods))) {
+ if (report&&(old->level!=new->level)) {
+ unsigned use,ignore;
+ if (clobber) {
+ use= new->level+1;
+ ignore= old->level+1;
+ }
+ else {
+ use= old->level+1;
+ ignore= new->level+1;
+ }
+ WARN2("Multiple map entries for %s in %s\n",
+ MapEntryTxt(type,xkb,new),TypeTxt(type));
+ ACTION2("Using %d, ignoring %d\n",use,ignore);
+ }
+ else if (warningLevel>9) {
+ WARN3("Multiple occurences of map[%s]= %d in %s\n",
+ MapEntryTxt(type,xkb,new),new->level+1,TypeTxt(type));
+ ACTION("Ignored\n");
+ return True;
+ }
+ if (clobber)
+ old->level= new->level;
+ return True;
+ }
+ if ((old=NextMapEntry(type))==NULL)
+ return False; /* allocation failure, already reported */
+ if (new->level>=type->numLevels)
+ type->numLevels= new->level+1;
+ if (new->mods.vmods==0) old->active= True;
+ else old->active= False;
+ old->mods.mask= new->mods.real_mods;
+ old->mods.real_mods= new->mods.real_mods;
+ old->mods.vmods= new->mods.vmods;
+ old->level= new->level;
+ return True;
+}
+
+static LookupEntry lnames[] = {
+ { "level1", 1 },
+ { "level2", 2 },
+ { "level3", 3 },
+ { "level4", 4 },
+ { "level5", 5 },
+ { "level6", 6 },
+ { "level7", 7 },
+ { "level8", 8 },
+ { NULL, 0 }
+};
+
+static Bool
+#if NeedFunctionPrototypes
+SetMapEntry( KeyTypeInfo * type,
+ XkbDescPtr xkb,
+ ExprDef * arrayNdx,
+ ExprDef * value)
+#else
+SetMapEntry(type,xkb,arrayNdx,value)
+ KeyTypeInfo * type;
+ XkbDescPtr xkb;
+ ExprDef * arrayNdx;
+ ExprDef * value;
+#endif
+{
+ExprResult rtrn;
+XkbKTMapEntryRec entry;
+
+ if (arrayNdx==NULL)
+ return ReportTypeShouldBeArray(type,"map entry");
+ if (!ExprResolveModMask(arrayNdx,&rtrn,LookupVModMask,(XPointer)xkb))
+ return ReportTypeBadType(type,"map entry","modifier mask");
+ entry.mods.real_mods= rtrn.uval&0xff;
+ entry.mods.vmods= (rtrn.uval>>8)&0xffff;
+ if ((entry.mods.real_mods&(~type->mask))||
+ ((entry.mods.vmods&(~type->vmask))!=0)) {
+ if (warningLevel>0) {
+ WARN1("Map entry for unused modifiers in %s\n",TypeTxt(type));
+ ACTION1("Using %s instead of ",XkbVModMaskText(type->dpy,xkb,
+ entry.mods.real_mods&type->mask,
+ entry.mods.vmods&type->vmask,
+ XkbMessage));
+ INFO1("%s\n",MapEntryTxt(type,xkb,&entry));
+ }
+ entry.mods.real_mods&= type->mask;
+ entry.mods.vmods&= type->vmask;
+ }
+ if (!ExprResolveInteger(value,&rtrn,SimpleLookup,(XPointer)lnames)) {
+ ERROR("Level specifications in a key type must be integer\n");
+ ACTION("Ignoring malformed level specification\n");
+ return False;
+ }
+ if ((rtrn.ival<1)||(rtrn.ival>XkbMaxShiftLevel+1)) {
+ ERROR3("Shift level %d out of range (1..%d) in key type %s\n",
+ XkbMaxShiftLevel+1,
+ rtrn.ival,TypeTxt(type));
+ ACTION1("Ignoring illegal definition of map[%s]\n",
+ MapEntryTxt(type,xkb,&entry));
+ return False;
+ }
+ entry.level= rtrn.ival-1;
+ return AddMapEntry(xkb,type,&entry,True,True);
+}
+
+static Bool
+#if NeedFunctionPrototypes
+SetPreserve( KeyTypeInfo * type,
+ XkbDescPtr xkb,
+ ExprDef * arrayNdx,
+ ExprDef * value)
+#else
+SetPreserve(type,xkb,arrayNdx,value)
+ KeyTypeInfo * type;
+ XkbDescPtr xkb;
+ ExprDef * arrayNdx;
+ ExprDef * value;
+#endif
+{
+ExprResult rtrn;
+PreserveInfo new;
+
+ if (arrayNdx==NULL)
+ return ReportTypeShouldBeArray(type,"preserve entry");
+ if (!ExprResolveModMask(arrayNdx,&rtrn,LookupVModMask,(XPointer)xkb))
+ return ReportTypeBadType(type,"preserve entry","modifier mask");
+ new.defs= type->defs;
+ new.defs.next= NULL;
+ new.indexMods= rtrn.uval&0xff;
+ new.indexVMods= (rtrn.uval>>8)&0xffff;
+ if ((new.indexMods&(~type->mask))||(new.indexVMods&(~type->vmask))) {
+ if (warningLevel>0) {
+ WARN1("Preserve for modifiers not used by the %s type\n",
+ TypeTxt(type));
+ ACTION1("Index %s converted to ",PreserveIndexTxt(type,xkb,&new));
+ }
+ new.indexMods&= type->mask;
+ new.indexVMods&= type->vmask;
+ if (warningLevel>0)
+ INFO1("%s\n",PreserveIndexTxt(type,xkb,&new));
+ }
+ if (!ExprResolveModMask(value,&rtrn,LookupVModMask,(XPointer)xkb)) {
+ ERROR("Preserve value in a key type is not a modifier mask\n");
+ ACTION2("Ignoring preserve[%s] in type %s\n",
+ PreserveIndexTxt(type,xkb,&new),
+ TypeTxt(type));
+ return False;
+ }
+ new.preMods= rtrn.uval&0xff;
+ new.preVMods= (rtrn.uval>>16)&0xffff;
+ if ((new.preMods&(~new.indexMods))||(new.preVMods&&(~new.indexVMods))) {
+ if (warningLevel>0) {
+ WARN2("Illegal value for preserve[%s] in type %s\n",
+ PreserveTxt(type,xkb,&new),
+ TypeTxt(type));
+ ACTION1("Converted %s to ",PreserveIndexTxt(type,xkb,&new));
+ }
+ new.preMods&= new.indexMods;
+ new.preVMods&= new.indexVMods;
+ if (warningLevel>0) {
+ INFO1("%s\n",PreserveIndexTxt(type,xkb,&new));
+ }
+ }
+ return AddPreserve(xkb,type,&new,True,True);
+}
+
+/***====================================================================***/
+
+Bool
+#if NeedFunctionPrototypes
+AddLevelName( KeyTypeInfo * type,
+ unsigned level,
+ Atom name,
+ Bool clobber,
+ Bool report)
+#else
+AddLevelName(type,level,name,clobber,report)
+ KeyTypeInfo * type;
+ unsigned level;
+ Atom name;
+ Bool clobber;
+ Bool report;
+#endif
+{
+ if ((type->lvlNames==NULL)||(type->szNames<=level)) {
+ type->lvlNames=
+ uTypedRecalloc(type->lvlNames,type->szNames,level+1,Atom);
+ if (type->lvlNames==NULL) {
+ ERROR1("Couldn't allocate level names for type %s\n",TypeTxt(type));
+ ACTION("Level names lost\n");
+ type->szNames= 0;
+ return False;
+ }
+ type->szNames= level+1;
+ }
+ else if (type->lvlNames[level]==name) {
+ if (warningLevel>9) {
+ WARN2("Duplicate names for level %d of key type %s\n",level+1,
+ TypeTxt(type));
+ ACTION("Ignored\n");
+ }
+ return True;
+ }
+ else if (type->lvlNames[level]!=None) {
+ if (warningLevel>0) {
+ char *old,*new;
+ old= XkbAtomText(type->dpy,type->lvlNames[level],XkbMessage);
+ new= XkbAtomText(type->dpy,name,XkbMessage);
+ WARN2("Multiple names for level %d of key type %s\n",level+1,
+ TypeTxt(type));
+ if (clobber)
+ ACTION2("Using %s, ignoring %s\n",new,old);
+ else ACTION2("Using %s, ignoring %s\n",old,new);
+ }
+ if (!clobber)
+ return True;
+ }
+ if (level>=type->numLevels)
+ type->numLevels= level+1;
+ type->lvlNames[level]= name;
+ return True;
+}
+
+static Bool
+#if NeedFunctionPrototypes
+SetLevelName(KeyTypeInfo *type,ExprDef *arrayNdx,ExprDef *value)
+#else
+SetLevelName(type,arrayNdx,value)
+ KeyTypeInfo * type;
+ ExprDef * arrayNdx;
+ ExprDef * value;
+#endif
+{
+ExprResult rtrn;
+unsigned level;
+
+ if (arrayNdx==NULL)
+ return ReportTypeShouldBeArray(type,"level name");
+ if (!ExprResolveInteger(arrayNdx,&rtrn,SimpleLookup,(XPointer)lnames))
+ return ReportTypeBadType(type,"level name","integer");
+ if ((rtrn.ival<1)||(rtrn.ival>XkbMaxShiftLevel+1)) {
+ ERROR3("Level name %d out of range (1..%d) in key type %s\n",
+ rtrn.ival,
+ XkbMaxShiftLevel+1,
+ XkbAtomText(type->dpy,type->name,XkbMessage));
+ ACTION("Ignoring illegal level name definition\n");
+ return False;
+ }
+ level= rtrn.ival-1;
+ if (!ExprResolveString(value,&rtrn,NULL,NULL)) {
+ ERROR2("Non-string name for level %d in key type %s\n",level+1,
+ XkbAtomText(type->dpy,type->name,XkbMessage));
+ ACTION("Ignoring illegal level name definition\n");
+ return False;
+ }
+ return
+ AddLevelName(type,level,XkbInternAtom(NULL,rtrn.str,False),True,True);
+}
+
+/***====================================================================***/
+
+static Bool
+#if NeedFunctionPrototypes
+SetKeyTypeField( KeyTypeInfo * type,
+ XkbDescPtr xkb,
+ char * field,
+ ExprDef * arrayNdx,
+ ExprDef * value,
+ KeyTypesInfo * info)
+#else
+SetKeyTypeField(type,xkb,field,arrayNdx,value,info)
+ KeyTypeInfo * type;
+ XkbDescPtr xkb;
+ char * field;
+ ExprDef * arrayNdx;
+ ExprDef * value;
+ KeyTypesInfo * info;
+#endif
+{
+ExprResult tmp;
+
+ if (uStrCaseCmp(field,"modifiers")==0) {
+ unsigned mods,vmods;
+ if (arrayNdx!=NULL) {
+ WARN("The modifiers field of a key type is not an array\n");
+ ACTION("Illegal array subscript ignored\n");
+ }
+ if (!ExprResolveModMask(value,&tmp,LookupVModMask,(XPointer)xkb)) {
+ ERROR("Key type mask field must be a modifier mask\n");
+ ACTION("Key type definition ignored\n");
+ return False;
+ }
+ mods= tmp.uval&0xff;
+ vmods= (tmp.uval>>8)&0xffff;
+ if (type->defs.defined&_KT_Mask) {
+ WARN1("Multiple modifier mask definitions for key type %s\n",
+ XkbAtomText(type->dpy,type->name,XkbMessage));
+ ACTION1("Using %s, ",TypeMaskTxt(type,xkb));
+ INFO1("ignoring %s\n",XkbVModMaskText(type->dpy,xkb,mods,
+ vmods,
+ XkbMessage));
+ return False;
+ }
+ type->mask= mods;
+ type->vmask= vmods;
+ type->defs.defined|= _KT_Mask;
+ return True;
+ }
+ else if (uStrCaseCmp(field,"map")==0) {
+ type->defs.defined|= _KT_Map;
+ return SetMapEntry(type,xkb,arrayNdx,value);
+ }
+ else if (uStrCaseCmp(field,"preserve")==0) {
+ type->defs.defined|= _KT_Preserve;
+ return SetPreserve(type,xkb,arrayNdx,value);
+ }
+ else if ((uStrCaseCmp(field,"levelname")==0)||
+ (uStrCaseCmp(field,"level_name")==0)) {
+ type->defs.defined|= _KT_LevelNames;
+ return SetLevelName(type,arrayNdx,value);
+ }
+ ERROR2("Unknown field %s in key type %s\n",field,TypeTxt(type));
+ ACTION("Definition ignored\n");
+ return False;
+}
+
+static Bool
+#if NeedFunctionPrototypes
+HandleKeyTypeVar(VarDef *stmt,XkbDescPtr xkb,KeyTypesInfo *info)
+#else
+HandleKeyTypeVar(stmt,xkb,info)
+ VarDef * stmt;
+ XkbDescPtr xkb;
+ KeyTypesInfo * info;
+#endif
+{
+ExprResult elem,field;
+ExprDef * arrayNdx;
+
+ if (!ExprResolveLhs(stmt->name,&elem,&field,&arrayNdx))
+ return False; /* internal error, already reported */
+ if (elem.str&&(uStrCaseCmp(elem.str,"type")==0))
+ return SetKeyTypeField(&info->dflt,xkb,field.str,arrayNdx,stmt->value,
+ info);
+ if (elem.str!=NULL) {
+ ERROR1("Default for unknown element %s\n",uStringText(elem.str));
+ ACTION1("Value for field %s ignored\n",uStringText(field.str));
+ }
+ else if (field.str!=NULL) {
+ ERROR1("Default defined for unknown field %s\n",uStringText(field.str));
+ ACTION("Ignored\n");
+ }
+ return False;
+}
+
+static int
+#if NeedFunctionPrototypes
+HandleKeyTypeBody( VarDef * def,
+ XkbDescPtr xkb,
+ KeyTypeInfo * type,
+ KeyTypesInfo * info)
+#else
+HandleKeyTypeBody(def,xkb,type,info)
+ VarDef * def;
+ XkbDescPtr xkb;
+ KeyTypeInfo * type;
+ KeyTypesInfo * info;
+#endif
+{
+int ok= 1;
+ExprResult tmp,field;
+ExprDef * arrayNdx;
+
+ for (;def!=NULL;def= (VarDef *)def->common.next) {
+ if ((def->name)&&(def->name->type==ExprFieldRef)) {
+ ok= HandleKeyTypeVar(def,xkb,info);
+ continue;
+ }
+ ok= ExprResolveLhs(def->name,&tmp,&field,&arrayNdx);
+ if (ok)
+ ok= SetKeyTypeField(type,xkb,field.str,arrayNdx,def->value,info);
+ }
+ return ok;
+}
+
+static int
+#if NeedFunctionPrototypes
+HandleKeyTypeDef( KeyTypeDef * def,
+ XkbDescPtr xkb,
+ unsigned merge,
+ KeyTypesInfo * info)
+#else
+HandleKeyTypeDef(def,xkb,merge,info)
+ KeyTypeDef * def;
+ XkbDescPtr xkb;
+ unsigned merge;
+ KeyTypesInfo * info;
+#endif
+{
+register int i;
+KeyTypeInfo type;
+
+ if (def->merge!=MergeDefault)
+ merge= def->merge;
+
+ type.defs.defined= 0;
+ type.defs.fileID= info->fileID;
+ type.defs.merge= merge;
+ type.defs.next= 0;
+ type.dpy= info->dpy;
+ type.name= def->name;
+ type.mask= info->dflt.mask;
+ type.vmask= info->dflt.vmask;
+ type.groupInfo= info->dflt.groupInfo;
+ type.numLevels= 1;
+ type.nEntries= type.szEntries= 0;
+ type.entries= NULL;
+ type.szNames= 0;
+ type.lvlNames= NULL;
+ type.preserve= NULL;
+
+ if (!HandleKeyTypeBody(def->body,xkb,&type,info)) {
+ info->errorCount++;
+ return False;
+ }
+
+ /* now copy any appropriate map, preserve or level names from the */
+ /* default type */
+ for (i=0;i<info->dflt.nEntries;i++) {
+ XkbKTMapEntryPtr dflt;
+ dflt= &info->dflt.entries[i];
+ if (((dflt->mods.real_mods&type.mask)==dflt->mods.real_mods)&&
+ ((dflt->mods.vmods&type.vmask)==dflt->mods.vmods)) {
+ AddMapEntry(xkb,&type,dflt,False,False);
+ }
+ }
+ if (info->dflt.preserve) {
+ PreserveInfo *dflt= info->dflt.preserve;
+ while (dflt) {
+ if (((dflt->indexMods&type.mask)==dflt->indexMods)&&
+ ((dflt->indexVMods&type.vmask)==dflt->indexVMods)) {
+ AddPreserve(xkb,&type,dflt,False,False);
+ }
+ dflt= (PreserveInfo *)dflt->defs.next;
+ }
+ }
+ for (i=0;i<info->dflt.szNames;i++) {
+ if ((i<type.numLevels)&&(info->dflt.lvlNames[i]!=None)) {
+ AddLevelName(&type,i,info->dflt.lvlNames[i],False,False);
+ }
+ }
+ if (!AddKeyType(xkb,info,&type)) {
+ info->errorCount++;
+ return False;
+ }
+ return True;
+}
+
+static void
+#if NeedFunctionPrototypes
+HandleKeyTypesFile( XkbFile * file,
+ XkbDescPtr xkb,
+ unsigned merge,
+ KeyTypesInfo * info)
+#else
+HandleKeyTypesFile(file,xkb,merge,info)
+ XkbFile *file;
+ XkbDescPtr xkb;
+ unsigned merge;
+ KeyTypesInfo *info;
+#endif
+{
+ParseCommon *stmt;
+
+ if ((merge==MergeOverride)||(info->name==None))
+ info->name= file->name;
+
+ info->name= file->name;
+ stmt= file->defs;
+ while (stmt) {
+ switch (stmt->stmtType) {
+ case StmtInclude:
+ if (!HandleIncludeKeyTypes((IncludeStmt *)stmt,xkb,info,
+ HandleKeyTypesFile))
+ info->errorCount++;
+ break;
+ case StmtKeyTypeDef:
+ if (!HandleKeyTypeDef((KeyTypeDef *)stmt,xkb,merge,info))
+ info->errorCount++;
+ break;
+ case StmtVarDef:
+ if (!HandleKeyTypeVar((VarDef *)stmt,xkb,info))
+ info->errorCount++;
+ break;
+ case StmtVModDef:
+ if (!HandleVModDef((VModDef *)stmt,merge,&info->vmods))
+ info->errorCount++;
+ break;
+ case StmtKeyAliasDef:
+ ERROR("Key type files may not include other declarations\n");
+ ACTION("Ignoring definition of key alias\n");
+ info->errorCount++;
+ break;
+ case StmtKeycodeDef:
+ ERROR("Key type files may not include other declarations\n");
+ ACTION("Ignoring definition of key name\n");
+ info->errorCount++;
+ break;
+ case StmtInterpDef:
+ ERROR("Key type files may not include other declarations\n");
+ ACTION("Ignoring definition of symbol interpretation\n");
+ info->errorCount++;
+ break;
+ default:
+ WSGO1("Unexpected statement type %d in HandleKeyTypesFile\n",
+ stmt->stmtType);
+ break;
+ }
+ stmt= stmt->next;
+ if (info->errorCount>10) {
+#ifdef NOISY
+ ERROR("Too many errors\n");
+#endif
+ ACTION1("Abandoning keytypes file \"%s\"\n",file->topName);
+ break;
+ }
+ }
+ return;
+}
+
+static Bool
+#if NeedFunctionPrototypes
+CopyDefToKeyType(XkbDescPtr xkb,XkbKeyTypePtr type,KeyTypeInfo *def)
+#else
+CopyDefToKeyType(xkb,type,def)
+ XkbDescPtr xkb;
+ XkbKeyTypePtr type;
+ KeyTypeInfo * def;
+#endif
+{
+register int i;
+PreserveInfo *pre;
+
+ for (pre=def->preserve;pre!=NULL;pre=(PreserveInfo *)pre->defs.next) {
+ XkbKTMapEntryPtr match;
+ XkbKTMapEntryRec tmp;
+ tmp.mods.real_mods= pre->indexMods;
+ tmp.mods.vmods= pre->indexVMods;
+ tmp.level= 0;
+ AddMapEntry(xkb,def,&tmp,False,False);
+ match= FindMatchingMapEntry(def,pre->indexMods,pre->indexVMods);
+ if (!match) {
+ WSGO("Couldn't find matching entry for preserve\n");
+ ACTION("Aborting\n");
+ return False;
+ }
+ pre->matchingMapIndex= match-def->entries;
+ }
+ type->mods.real_mods= def->mask;
+ type->mods.vmods= def->vmask;
+ type->num_levels= def->numLevels;
+ type->map_count= def->nEntries;
+ type->map= def->entries;
+ if (def->preserve) {
+ type->preserve= uTypedCalloc(type->map_count,XkbModsRec);
+ if (!type->preserve) {
+ WARN("Couldn't allocate preserve array in CopyDefToKeyType\n");
+ ACTION1("Preserve setting for type %s lost\n",
+ XkbAtomText(def->dpy,def->name,XkbMessage));
+ }
+ else {
+ pre= def->preserve;
+ for (;pre!=NULL;pre=(PreserveInfo *)pre->defs.next) {
+ int ndx= pre->matchingMapIndex;
+ type->preserve[ndx].mask= pre->preMods;
+ type->preserve[ndx].real_mods= pre->preMods;
+ type->preserve[ndx].vmods= pre->preVMods;
+ }
+ }
+ }
+ else type->preserve= NULL;
+ type->name= (Atom)def->name;
+ if (def->szNames>0) {
+ type->level_names= uTypedCalloc(def->numLevels,Atom);
+
+ /* assert def->szNames<=def->numLevels */
+ for (i=0;i<def->szNames;i++) {
+ type->level_names[i]= (Atom)def->lvlNames[i];
+ }
+ }
+ else {
+ type->level_names= NULL;
+ }
+
+ def->nEntries= def->szEntries= 0;
+ def->entries= NULL;
+ return XkbComputeEffectiveMap(xkb,type,NULL);
+}
+
+Bool
+#if NeedFunctionPrototypes
+CompileKeyTypes(XkbFile *file,XkbFileInfo *result,unsigned merge)
+#else
+CompileKeyTypes(file,result,merge)
+ XkbFile * file;
+ XkbFileInfo * result;
+ unsigned merge;
+#endif
+{
+KeyTypesInfo info;
+XkbDescPtr xkb;
+
+ xkb= result->xkb;
+ InitKeyTypesInfo(&info,xkb,NULL);
+ info.fileID= file->id;
+ HandleKeyTypesFile(file,xkb,merge,&info);
+
+ if (info.errorCount==0) {
+ register int i;
+ register KeyTypeInfo *def;
+ register XkbKeyTypePtr type,next;
+
+ if (info.name!=None) {
+ if (XkbAllocNames(xkb,XkbTypesNameMask,0,0)==Success)
+ xkb->names->types= XkbInternAtom(xkb->dpy,info.name,False);
+ else {
+ WSGO("Couldn't allocate space for types name\n");
+ ACTION2("Name \"%s\" (from %s) NOT assigned\n",scanFile,
+ info.name);
+ }
+ }
+ i= info.nTypes;
+ if ((info.stdPresent&XkbOneLevelMask)==0)
+ i++;
+ if ((info.stdPresent&XkbTwoLevelMask)==0)
+ i++;
+ if ((info.stdPresent&XkbKeypadMask)==0)
+ i++;
+ if ((info.stdPresent&XkbAlphabeticMask)==0)
+ i++;
+ if (XkbAllocClientMap(xkb,XkbKeyTypesMask,i)!=Success) {
+ WSGO("Couldn't allocate client map\n");
+ ACTION("Exiting\n");
+ return False;
+ }
+ xkb->map->num_types= i;
+ if (XkbAllRequiredTypes&(~info.stdPresent)) {
+ unsigned missing,keypadVMod;
+
+ missing= XkbAllRequiredTypes&(~info.stdPresent);
+ keypadVMod= FindKeypadVMod(xkb);
+ if (XkbInitCanonicalKeyTypes(xkb,missing,keypadVMod)!=Success) {
+ WSGO("Couldn't initialize canonical key types\n");
+ ACTION("Exiting\n");
+ return False;
+ }
+ if (missing&XkbOneLevelMask)
+ xkb->map->types[XkbOneLevelIndex].name= tok_ONE_LEVEL;
+ if (missing&XkbTwoLevelMask)
+ xkb->map->types[XkbTwoLevelIndex].name= tok_TWO_LEVEL;
+ if (missing&XkbAlphabeticMask)
+ xkb->map->types[XkbAlphabeticIndex].name= tok_ALPHABETIC;
+ if (missing&XkbKeypadMask)
+ xkb->map->types[XkbKeypadIndex].name= tok_KEYPAD;
+ }
+ next= &xkb->map->types[XkbLastRequiredType+1];
+ for (i=0,def=info.types;i<info.nTypes;i++) {
+ if (def->name==tok_ONE_LEVEL)
+ type= &xkb->map->types[XkbOneLevelIndex];
+ else if (def->name==tok_TWO_LEVEL)
+ type= &xkb->map->types[XkbTwoLevelIndex];
+ else if (def->name==tok_ALPHABETIC)
+ type= &xkb->map->types[XkbAlphabeticIndex];
+ else if (def->name==tok_KEYPAD)
+ type= &xkb->map->types[XkbKeypadIndex];
+ else type= next++;
+ DeleteLevel1MapEntries(def);
+ if (!CopyDefToKeyType(xkb,type,def))
+ return False;
+ def= (KeyTypeInfo *)def->defs.next;
+ }
+ return True;
+ }
+ return False;
+}
+
diff --git a/listing.c b/listing.c
new file mode 100644
index 0000000..c87e178
--- /dev/null
+++ b/listing.c
@@ -0,0 +1,500 @@
+/* $Xorg: listing.c,v 1.5 2001/02/09 02:05:49 xorgcvs Exp $ */
+/************************************************************
+ Copyright 1996 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
+ documentation, and that the name of Silicon Graphics not be
+ used in advertising or publicity pertaining to distribution
+ of the software without specific prior written permission.
+ Silicon Graphics makes no representation about the suitability
+ of this software for any purpose. It is provided "as is"
+ without any express or implied warranty.
+
+ SILICON GRAPHICS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS
+ SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+ AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL SILICON
+ 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
+ OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH
+ THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+ ********************************************************/
+/***********************************************************
+
+Copyright 1988, 1998 The Open Group
+
+Permission to use, copy, modify, distribute, and sell this software and its
+documentation for any purpose is hereby granted without fee, provided that
+the above copyright notice appear in all copies and that both that
+copyright notice and this permission notice appear in supporting
+documentation.
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
+AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+Except as contained in this notice, the name of The Open Group shall not be
+used in advertising or otherwise to promote the sale, use or other dealings
+in this Software without prior written authorization from The Open Group.
+
+
+Copyright 1988 by Digital Equipment Corporation, Maynard, Massachusetts.
+
+ All Rights Reserved
+
+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 documentation, and that the name of Digital not be
+used in advertising or publicity pertaining to distribution of the
+software without specific, written prior permission.
+
+DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
+ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
+DIGITAL 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 OR OTHER TORTIOUS ACTION,
+ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
+SOFTWARE.
+
+******************************************************************/
+
+
+#include <stdio.h>
+#include <ctype.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <X11/keysym.h>
+
+#if defined(sgi)
+#include <malloc.h>
+#endif
+
+#define DEBUG_VAR_NOT_LOCAL
+#define DEBUG_VAR listingDebug
+#include "xkbcomp.h"
+#ifndef X_NOT_STDC_ENV
+#include <stdlib.h>
+#endif
+#ifndef X_NOT_POSIX
+#ifdef _POSIX_SOURCE
+#include <limits.h>
+#else
+#define _POSIX_SOURCE
+#include <limits.h>
+#undef _POSIX_SOURCE
+#endif
+#endif
+#ifndef PATH_MAX
+#ifdef WIN32
+#define PATH_MAX 512
+#else
+#include <sys/param.h>
+#endif
+#ifndef PATH_MAX
+#ifdef MAXPATHLEN
+#define PATH_MAX MAXPATHLEN
+#else
+#define PATH_MAX 1024
+#endif
+#endif
+#endif
+
+#ifdef WIN32
+#define BOOL wBOOL
+#include <windows.h>
+#undef BOOL
+#define FileName(file) file.cFileName
+#else
+#define FileName(file) file->d_name
+#ifndef X_NOT_POSIX
+#include <dirent.h>
+#else
+#ifdef SYSV
+#include <dirent.h>
+#else
+#ifdef USG
+#include <dirent.h>
+#else
+#include <sys/dir.h>
+#ifndef dirent
+#define dirent direct
+#endif
+#endif
+#endif
+#endif
+#endif
+
+#include "xkbpath.h"
+#include "parseutils.h"
+#include "misc.h"
+#include "tokens.h"
+#include <X11/extensions/XKBgeom.h>
+
+#define lowbit(x) ((x) & (-(x)))
+
+static int szListing= 0;
+static int nListed= 0;
+static int nFilesListed= 0;
+
+typedef struct _Listing {
+ char * file;
+ char * map;
+} Listing;
+
+static int szMapOnly;
+static int nMapOnly;
+static char ** mapOnly;
+
+static Listing * list= NULL;
+
+/***====================================================================***/
+
+int
+#if NeedFunctionPrototypes
+AddMapOnly(char *map)
+#else
+AddMapOnly(map)
+ char *map;
+#endif
+{
+ if (nMapOnly>=szMapOnly) {
+ if (szMapOnly<1) szMapOnly= 5;
+ else szMapOnly*= 2;
+ mapOnly= uTypedRealloc(list,szMapOnly,char *);
+ if (!mapOnly) {
+ WSGO("Couldn't allocate list of maps\n");
+ return 0;
+ }
+ }
+ mapOnly[nMapOnly++]= map;
+ return 1;
+}
+
+int
+#if NeedFunctionPrototypes
+AddListing(char *file,char *map)
+#else
+AddListing(file,map)
+ char *file;
+ char *map;
+#endif
+{
+ if (nListed>=szListing) {
+ if (szListing<1) szListing= 10;
+ else szListing*= 2;
+ list= uTypedRealloc(list,szListing,Listing);
+ if (!list) {
+ WSGO("Couldn't allocate list of files and maps\n");
+ ACTION("Exiting\n");
+ exit(1);
+ }
+ }
+
+ list[nListed].file= file;
+ list[nListed].map= map;
+ nListed++;
+ if (file!=NULL)
+ nFilesListed++;
+ return 1;
+}
+
+/***====================================================================***/
+
+static void
+#if NeedFunctionPrototypes
+ListFile(FILE *outFile,char *fileName,XkbFile *map)
+#else
+ListFile(outFile,fileName,map)
+FILE * outFile;
+char * fileName;
+XkbFile * map;
+#endif
+{
+register unsigned flags;
+char * mapName;
+
+ flags= map->flags;
+ if ((flags&XkbLC_Hidden)&&(!(verboseLevel&WantHiddenMaps)))
+ return;
+ if ((flags&XkbLC_Partial)&&(!(verboseLevel&WantPartialMaps)))
+ return;
+ if (verboseLevel&WantLongListing) {
+ fprintf(outFile,(flags&XkbLC_Hidden)?"h":"-");
+ fprintf(outFile,(flags&XkbLC_Default)?"d":"-");
+ fprintf(outFile,(flags&XkbLC_Partial)?"p":"-");
+ fprintf(outFile,"----- ");
+ if (map->type==XkmSymbolsIndex) {
+ fprintf(outFile,(flags&XkbLC_AlphanumericKeys)?"a":"-");
+ fprintf(outFile,(flags&XkbLC_ModifierKeys)?"m":"-");
+ fprintf(outFile,(flags&XkbLC_KeypadKeys)?"k":"-");
+ fprintf(outFile,(flags&XkbLC_FunctionKeys)?"f":"-");
+ fprintf(outFile,(flags&XkbLC_AlternateGroup)?"g":"-");
+ fprintf(outFile,"--- ");
+ }
+ else fprintf(outFile,"-------- ");
+ }
+ mapName= map->name;
+ if ((!(verboseLevel&WantFullNames))&&((flags&XkbLC_Default)!=0))
+ mapName= NULL;
+ if (dirsToStrip>0) {
+ char *tmp,*last;
+ int i;
+ for (i=0,tmp=last=fileName;(i<dirsToStrip)&&tmp;i++) {
+ last= tmp;
+ tmp= strchr(tmp,'/');
+ if (tmp!=NULL)
+ tmp++;
+ }
+ fileName= (tmp?tmp:last);
+ }
+ if (mapName)
+ fprintf(outFile,"%s(%s)\n",fileName,mapName);
+ else fprintf(outFile,"%s\n",fileName);
+ return;
+}
+
+/***====================================================================***/
+
+static int
+#if NeedFunctionPrototypes
+AddDirectory(char *head,char *ptrn,char *rest,char *map)
+#else
+AddDirectory(head,ptrn,rest,map)
+ char * head;
+ char * ptrn;
+ char * rest;
+ char * map;
+#endif
+{
+#ifdef WIN32
+ HANDLE dirh;
+ WIN32_FIND_DATA file;
+#else
+ DIR *dirp;
+ struct dirent *file;
+#endif
+ int nMatch;
+
+ if (map==NULL) {
+ char *tmp = ptrn;
+ if ((rest==NULL)&&(ptrn!=NULL)&&(strchr(ptrn,'/')==NULL)) {
+ tmp= ptrn;
+ map= strchr(ptrn,'(');
+ }
+ else if ((rest==NULL)&&(ptrn==NULL)&&
+ (head!=NULL)&&(strchr(head,'/')==NULL)) {
+ tmp= head;
+ map= strchr(head,'(');
+ }
+ if (map!=NULL) {
+ tmp= strchr(tmp,')');
+ if ((tmp==NULL)||(tmp[1]!='\0')) {
+ ERROR("File and map must have the format file(map)\n");
+ return 0;
+ }
+ *map= '\0'; map++;
+ *tmp= '\0';
+ }
+ }
+#ifdef WIN32
+ if ((dirh = FindFirstFile("*.*", &file)) == INVALID_HANDLE_VALUE)
+ return 0;
+#else
+ if ((dirp = opendir ((head?head:"."))) == NULL)
+ return 0;
+ nMatch= 0;
+#endif
+#ifdef WIN32
+ do
+#else
+ while ((file = readdir (dirp)) != NULL)
+#endif
+ {
+ char *tmp,*filename;
+ struct stat sbuf;
+
+ filename= FileName(file);
+ if (!filename || filename[0]=='.')
+ continue;
+ if (ptrn && (!XkbNameMatchesPattern(filename,ptrn)))
+ continue;
+ tmp= (char *)uAlloc((head?strlen(head):0)+strlen(filename)+2);
+ if (!tmp)
+ continue;
+ sprintf(tmp,"%s%s%s",(head?head:""),(head?"/":""),filename);
+ if (stat(tmp,&sbuf)<0) {
+ uFree(tmp);
+ continue;
+ }
+ if (((rest!=NULL)&&(!S_ISDIR(sbuf.st_mode)))||
+ ((map!=NULL)&&(S_ISDIR(sbuf.st_mode)))) {
+ uFree(tmp);
+ continue;
+ }
+ if (S_ISDIR(sbuf.st_mode)) {
+ if ((rest!=NULL)||(verboseLevel&ListRecursive))
+ nMatch+= AddDirectory(tmp,rest,NULL,map);
+ }
+ else nMatch+= AddListing(tmp,map);
+ }
+#ifdef WIN32
+ while (FindNextFile(dirh, &file));
+#endif
+ return nMatch;
+}
+
+/***====================================================================***/
+
+Bool
+#if NeedFunctionPrototypes
+AddMatchingFiles(char *head_in)
+#else
+AddMatchingFiles(head_in)
+ char * head_in;
+#endif
+{
+char *str,*head,*ptrn,*rest= NULL;
+
+ if (head_in==NULL)
+ return 0;
+ ptrn= NULL;
+ for (str=head_in;(*str!='\0')&&(*str!='?')&&(*str!='*');str++) {
+ if ((str!=head_in)&&(*str=='/'))
+ ptrn= str;
+ }
+ if (*str=='\0') { /* no wildcards */
+ head= head_in;
+ ptrn= NULL;
+ rest= NULL;
+ }
+ else if (ptrn==NULL) { /* no slash before the first wildcard */
+ head= NULL;
+ ptrn= head_in;
+ }
+ else { /* slash followed by wildcard */
+ head= head_in;
+ *ptrn= '\0'; ptrn++;
+ }
+ if (ptrn) {
+ rest= strchr(ptrn,'/');
+ if (rest!=NULL) {
+ *rest= '\0';
+ rest++;
+ }
+ }
+ if(((rest && ptrn)&&((strchr(ptrn,'(')!=NULL)||(strchr(ptrn,')')!=NULL)))||
+ (head && ((strchr(head,'(')!=NULL)||(strchr(head,')')!=NULL)))) {
+ ERROR("Files/maps to list must have the form file(map)\n");
+ ACTION("Illegal specifier ignored\n");
+ return 0;
+ }
+ return AddDirectory(head,ptrn,rest,NULL);
+}
+
+/***====================================================================***/
+
+Bool
+MapMatches(mapToConsider,ptrn)
+ char * mapToConsider;
+ char * ptrn;
+{
+int i;
+
+ if (ptrn!=NULL)
+ return XkbNameMatchesPattern(mapToConsider,ptrn);
+ if (nMapOnly<1)
+ return True;
+ for (i=0;i<nMapOnly;i++) {
+ if (XkbNameMatchesPattern(mapToConsider,mapOnly[i]))
+ return True;
+ }
+ return False;
+}
+
+int
+#if NeedFunctionPrototypes
+GenerateListing(char *out_name)
+#else
+GenerateListing(out_name)
+ char * out_name;
+#endif
+{
+int i;
+FILE * inputFile,*outFile;
+XkbFile * rtrn,*mapToUse;
+unsigned oldWarningLevel;
+char * mapName;
+
+ if (nFilesListed<1) {
+ ERROR("Must specify at least one file or pattern to list\n");
+ return 0;
+ }
+ if ((!out_name)||((out_name[0]=='-')&&(out_name[1]=='\0')))
+ outFile= stdout;
+ else if ((outFile=fopen(out_name,"w"))==NULL) {
+ ERROR1("Cannot open \"%s\" to write keyboard description\n",out_name);
+ ACTION("Exiting\n");
+ return 0;
+ }
+#ifdef DEBUG
+ if (warningLevel>9)
+ fprintf(stderr,"should list:\n");
+#endif
+ for (i=0;i<nListed;i++) {
+#ifdef DEBUG
+ if (warningLevel>9) {
+ fprintf(stderr,"%s(%s)\n",(list[i].file?list[i].file:"*"),
+ (list[i].map?list[i].map:"*"));
+ }
+#endif
+ oldWarningLevel= warningLevel;
+ warningLevel= 0;
+ if (list[i].file) {
+ struct stat sbuf;
+
+ if (stat(list[i].file,&sbuf)<0) {
+ if (oldWarningLevel>5)
+ WARN1("Couldn't open \"%s\"\n",list[i].file);
+ continue;
+ }
+ if (S_ISDIR(sbuf.st_mode)) {
+ if (verboseLevel&ListRecursive)
+ AddDirectory(list[i].file,NULL,NULL,NULL);
+ continue;
+ }
+
+ inputFile= fopen(list[i].file,"r");
+ if (!inputFile) {
+ if (oldWarningLevel>5)
+ WARN1("Couldn't open \"%s\"\n",list[i].file);
+ continue;
+ }
+ if (XKBParseFile(inputFile,&rtrn)&&(rtrn!=NULL)) {
+ mapName= list[i].map;
+ mapToUse= rtrn;
+ for (;mapToUse;mapToUse= (XkbFile *)mapToUse->common.next) {
+ if (!MapMatches(mapToUse->name,mapName))
+ continue;
+ ListFile(outFile,list[i].file,mapToUse);
+ }
+ }
+ fclose(inputFile);
+ }
+ warningLevel= oldWarningLevel;
+ }
+ return 1;
+}
+
diff --git a/misc.c b/misc.c
new file mode 100644
index 0000000..d9dd413
--- /dev/null
+++ b/misc.c
@@ -0,0 +1,605 @@
+/* $Xorg: misc.c,v 1.3 2000/08/17 19:54:33 cpqbld Exp $ */
+/************************************************************
+ 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
+ documentation, and that the name of Silicon Graphics not be
+ used in advertising or publicity pertaining to distribution
+ of the software without specific prior written permission.
+ Silicon Graphics makes no representation about the suitability
+ of this software for any purpose. It is provided "as is"
+ without any express or implied warranty.
+
+ SILICON GRAPHICS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS
+ SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+ AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL SILICON
+ 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
+ OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH
+ THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+ ********************************************************/
+
+#include "xkbcomp.h"
+#include "xkbpath.h"
+#include "tokens.h"
+#include "keycodes.h"
+#include "misc.h"
+#include <X11/keysym.h>
+#include "parseutils.h"
+
+#include <X11/extensions/XKBgeom.h>
+
+/***====================================================================***/
+
+Bool
+#if NeedFunctionPrototypes
+ProcessIncludeFile( IncludeStmt * stmt,
+ unsigned file_type,
+ XkbFile ** file_rtrn,
+ unsigned * merge_rtrn)
+#else
+ProcessIncludeFile(stmt,file_type,file_rtrn,merge_rtrn)
+ IncludeStmt * stmt;
+ unsigned file_type;
+ XkbFile ** file_rtrn;
+ unsigned * merge_rtrn;
+#endif
+{
+FILE *file;
+XkbFile *rtrn,*mapToUse;
+char oldFile[1024];
+int oldLine = lineNum;
+
+ rtrn= XkbFindFileInCache(stmt->file,file_type,&stmt->path);
+ if (rtrn==NULL) {
+ file= XkbFindFileInPath(stmt->file,file_type,&stmt->path);
+ if (file==NULL) {
+ ERROR2("Can't find file \"%s\" for %s include\n",stmt->file,
+ XkbDirectoryForInclude(file_type));
+ ACTION("Exiting\n");
+ return False;
+ }
+ strcpy(oldFile,scanFile);
+ oldLine= lineNum;
+ setScanState(stmt->file,1);
+ if (debugFlags&2)
+ INFO1("About to parse include file %s\n",stmt->file);
+ if ((XKBParseFile(file,&rtrn)==0)||(rtrn==NULL)) {
+ setScanState(oldFile,oldLine);
+ ERROR1("Error interpreting include file \"%s\"\n",stmt->file);
+ ACTION("Exiting\n");
+ 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) {
+ ERROR3("No %s named \"%s\" in the include file \"%s\"\n",
+ XkbConfigText(file_type,XkbMessage),
+ stmt->map,stmt->file);
+ ACTION("Exiting\n");
+ return False;
+ }
+ }
+ else if ((rtrn->common.next!=NULL)&&(warningLevel>5)) {
+ WARN1("No map in include statement, but \"%s\" contains several\n",
+ stmt->file);
+ ACTION1("Using first defined map, \"%s\"\n",rtrn->name);
+ }
+ setScanState(oldFile,oldLine);
+ if (mapToUse->type!=file_type) {
+ ERROR2("Include file wrong type (expected %s, got %s)\n",
+ XkbConfigText(file_type,XkbMessage),
+ XkbConfigText(mapToUse->type,XkbMessage));
+ ACTION1("Include file \"%s\" ignored\n",stmt->file);
+ return False;
+ }
+ if (mapToUse->compiled) {
+ ERROR2("Map \"%s(%s)\" included more than once\n",stmt->file,
+ rtrn->name);
+ ACTION("Later inclusion ignored\n");
+ return False;
+ }
+ mapToUse->compiled= True;
+ *file_rtrn= mapToUse;
+ *merge_rtrn= stmt->merge;
+ return True;
+}
+
+/***====================================================================***/
+
+int
+#if NeedFunctionPrototypes
+ReportNotArray(char *type,char *field,char *name)
+#else
+ReportNotArray(type,field,name)
+ char * type;
+ char * field;
+ char * name;
+#endif
+{
+ ERROR2("The %s %s field is not an array\n",type,field);
+ ACTION1("Ignoring illegal assignment in %s\n",name);
+ return False;
+}
+
+int
+#if NeedFunctionPrototypes
+ReportShouldBeArray(char *type,char *field,char *name)
+#else
+ReportShouldBeArray(type,field,name)
+ char * type;
+ char * field;
+ char * name;
+#endif
+{
+ ERROR2("Missing subscript for %s %s\n",type,field);
+ ACTION1("Ignoring illegal assignment in %s\n",name);
+ return False;
+}
+
+int
+#if NeedFunctionPrototypes
+ReportBadType(char *type,char *field,char *name,char *wanted)
+#else
+ReportBadType(type,field,name,wanted)
+ char *type;
+ char *field;
+ char *name;
+ char *wanted;
+#endif
+{
+ ERROR3("The %s %s field must be a %s\n",type,field,wanted);
+ ACTION1("Ignoring illegal assignment in %s\n",name);
+ return False;
+}
+
+int
+#if NeedFunctionPrototypes
+ReportBadIndexType(char *type,char *field,char *name,char *wanted)
+#else
+ReportBadIndexType(type,field,name,wanted)
+ char *type;
+ char *field;
+ char *name;
+ char *wanted;
+#endif
+{
+ ERROR3("Index for the %s %s field must be a %s\n",type,field,wanted);
+ ACTION1("Ignoring assignment to illegal field in %s\n",name);
+ return False;
+}
+
+int
+#if NeedFunctionPrototypes
+ReportBadField(char *type,char *field,char *name)
+#else
+ReportBadField(type,field,name)
+ char *type;
+ char *field;
+ char *name;
+#endif
+{
+ ERROR3("Unknown %s field %s in %s\n",type,field,name);
+ ACTION1("Ignoring assignment to unknown field in %s\n",name);
+ return False;
+}
+
+int
+#if NeedFunctionPrototypes
+ReportMultipleDefs(char *type,char *field,char *name)
+#else
+ReportMultipleDefs(type,field,name)
+ char *type;
+ char *field;
+ char *name;
+#endif
+{
+ WARN3("Multiple definitions of %s in %s \"%s\"\n",field,type,name);
+ ACTION("Using last definition\n");
+ return False;
+}
+
+/***====================================================================***/
+
+Bool
+#if NeedFunctionPrototypes
+UseNewField( unsigned field,
+ CommonInfo * oldDefs,
+ CommonInfo * newDefs,
+ unsigned * pCollide)
+#else
+UseNewField(field,oldDefs,newDefs,pCollide)
+ unsigned field;
+ CommonInfo * oldDefs;
+ CommonInfo * newDefs;
+ unsigned * pCollide;
+#endif
+{
+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;
+}
+
+Bool
+#if NeedFunctionPrototypes
+MergeNewField( unsigned field,
+ CommonInfo * oldDefs,
+ CommonInfo * newDefs,
+ unsigned * pCollide)
+#else
+MergeNewField(field,oldDefs,newDefs,pCollide)
+ unsigned field;
+ CommonInfo * oldDefs;
+ CommonInfo * newDefs;
+ unsigned * pCollide;
+#endif
+{
+ if ((oldDefs->defined&field)&&(newDefs->defined&field)) {
+ if (((oldDefs->fileID==newDefs->fileID)&&(warningLevel>0))||
+ (warningLevel>9)) {
+ *pCollide|= field;
+ }
+ if (newDefs->merge==MergeAugment)
+ return True;
+ }
+ return False;
+}
+
+XPointer
+#if NeedFunctionPrototypes
+ClearCommonInfo(CommonInfo *cmn)
+#else
+ClearCommonInfo(cmn)
+ CommonInfo * cmn;
+#endif
+{
+ if (cmn!=NULL) {
+ CommonInfo *this,*next;
+ for (this=cmn;this!=NULL;this=next) {
+ next= this->next;
+ uFree(this);
+ }
+ }
+ return NULL;
+}
+
+XPointer
+#if NeedFunctionPrototypes
+AddCommonInfo(CommonInfo *old,CommonInfo *new)
+#else
+AddCommonInfo(old,new)
+ CommonInfo * old;
+ CommonInfo * new;
+#endif
+{
+CommonInfo * first;
+
+ first= old;
+ while ( old && old->next ) {
+ old= old->next;
+ }
+ new->next= NULL;
+ if (old) {
+ old->next= new;
+ return (XPointer)first;
+ }
+ return (XPointer)new;
+}
+
+/***====================================================================***/
+
+typedef struct _KeyNameDesc {
+ KeySym level1;
+ KeySym level2;
+ char name[5];
+ Bool used;
+} KeyNameDesc;
+
+KeyNameDesc dfltKeys[] = {
+ { XK_Escape, NoSymbol, "ESC\0" },
+ { XK_quoteleft, XK_asciitilde, "TLDE" },
+ { XK_1, XK_exclam, "AE01" },
+ { XK_2, XK_at, "AE02" },
+ { XK_3, XK_numbersign, "AE03" },
+ { XK_4, XK_dollar, "AE04" },
+ { XK_5, XK_percent, "AE05" },
+ { XK_6, XK_asciicircum, "AE06" },
+ { XK_7, XK_ampersand, "AE07" },
+ { XK_8, XK_asterisk, "AE08" },
+ { XK_9, XK_parenleft, "AE09" },
+ { XK_0, XK_parenright, "AE10" },
+ { XK_minus, XK_underscore, "AE11" },
+ { XK_equal, XK_plus, "AE12" },
+ { XK_BackSpace, NoSymbol, "BKSP" },
+ { XK_Tab, NoSymbol, "TAB\0" },
+ { XK_q, XK_Q, "AD01" },
+ { XK_w, XK_W, "AD02" },
+ { XK_e, XK_E, "AD03" },
+ { XK_r, XK_R, "AD04" },
+ { XK_t, XK_T, "AD05" },
+ { XK_y, XK_Y, "AD06" },
+ { XK_u, XK_U, "AD07" },
+ { XK_i, XK_I, "AD08" },
+ { XK_o, XK_O, "AD09" },
+ { XK_p, XK_P, "AD10" },
+ { XK_bracketleft, XK_braceleft, "AD11" },
+ { XK_bracketright,XK_braceright, "AD12" },
+ { XK_Return, NoSymbol, "RTRN" },
+ { XK_Caps_Lock, NoSymbol, "CAPS" },
+ { XK_a, XK_A, "AC01" },
+ { XK_s, XK_S, "AC02" },
+ { XK_d, XK_D, "AC03" },
+ { XK_f, XK_F, "AC04" },
+ { XK_g, XK_G, "AC05" },
+ { XK_h, XK_H, "AC06" },
+ { XK_j, XK_J, "AC07" },
+ { XK_k, XK_K, "AC08" },
+ { XK_l, XK_L, "AC09" },
+ { XK_semicolon, XK_colon, "AC10" },
+ { XK_quoteright, XK_quotedbl, "AC11" },
+ { XK_Shift_L, NoSymbol, "LFSH" },
+ { XK_z, XK_Z, "AB01" },
+ { XK_x, XK_X, "AB02" },
+ { XK_c, XK_C, "AB03" },
+ { XK_v, XK_V, "AB04" },
+ { XK_b, XK_B, "AB05" },
+ { XK_n, XK_N, "AB06" },
+ { XK_m, XK_M, "AB07" },
+ { XK_comma, XK_less, "AB08" },
+ { XK_period, XK_greater, "AB09" },
+ { XK_slash, XK_question, "AB10" },
+ { XK_backslash, XK_bar, "BKSL" },
+ { XK_Control_L, NoSymbol, "LCTL" },
+ { XK_space, NoSymbol, "SPCE" },
+ { XK_Shift_R, NoSymbol, "RTSH" },
+ { XK_Alt_L, NoSymbol, "LALT" },
+ { XK_space, NoSymbol, "SPCE" },
+ { XK_Control_R, NoSymbol, "RCTL" },
+ { XK_Alt_R, NoSymbol, "RALT" },
+ { XK_F1, NoSymbol, "FK01" },
+ { XK_F2, NoSymbol, "FK02" },
+ { XK_F3, NoSymbol, "FK03" },
+ { XK_F4, NoSymbol, "FK04" },
+ { XK_F5, NoSymbol, "FK05" },
+ { XK_F6, NoSymbol, "FK06" },
+ { XK_F7, NoSymbol, "FK07" },
+ { XK_F8, NoSymbol, "FK08" },
+ { XK_F9, NoSymbol, "FK09" },
+ { XK_F10, NoSymbol, "FK10" },
+ { XK_F11, NoSymbol, "FK11" },
+ { XK_F12, NoSymbol, "FK12" },
+ { XK_Print, NoSymbol, "PRSC" },
+ { XK_Scroll_Lock, NoSymbol, "SCLK" },
+ { XK_Pause, NoSymbol, "PAUS" },
+ { XK_Insert, NoSymbol, "INS\0" },
+ { XK_Home, NoSymbol, "HOME" },
+ { XK_Prior, NoSymbol, "PGUP" },
+ { XK_Delete, NoSymbol, "DELE" },
+ { XK_End, NoSymbol, "END" },
+ { XK_Next, NoSymbol, "PGDN" },
+ { XK_Up, NoSymbol, "UP\0\0" },
+ { XK_Left, NoSymbol, "LEFT" },
+ { XK_Down, NoSymbol, "DOWN" },
+ { XK_Right, NoSymbol, "RGHT" },
+ { XK_Num_Lock, NoSymbol, "NMLK" },
+ { XK_KP_Divide, NoSymbol, "KPDV" },
+ { XK_KP_Multiply, NoSymbol, "KPMU" },
+ { XK_KP_Subtract, NoSymbol, "KPSU" },
+ { NoSymbol, XK_KP_7, "KP7\0" },
+ { NoSymbol, XK_KP_8, "KP8\0" },
+ { NoSymbol, XK_KP_9, "KP9\0" },
+ { XK_KP_Add, NoSymbol, "KPAD" },
+ { NoSymbol, XK_KP_4, "KP4\0" },
+ { NoSymbol, XK_KP_5, "KP5\0" },
+ { NoSymbol, XK_KP_6, "KP6\0" },
+ { NoSymbol, XK_KP_1, "KP1\0" },
+ { NoSymbol, XK_KP_2, "KP2\0" },
+ { NoSymbol, XK_KP_3, "KP3\0" },
+ { XK_KP_Enter, NoSymbol, "KPEN" },
+ { NoSymbol, XK_KP_0, "KP0\0" },
+ { XK_KP_Delete, NoSymbol, "KPDL" },
+ { XK_less, XK_greater, "LSGT" },
+ { XK_KP_Separator,NoSymbol, "KPCO" },
+ { XK_Find, NoSymbol, "FIND" },
+ { NoSymbol, NoSymbol, "\0\0\0\0" }
+};
+
+Status
+#if NeedFunctionPrototypes
+ComputeKbdDefaults(XkbDescPtr xkb)
+#else
+ComputeKbdDefaults(xkb)
+ XkbDescPtr xkb;
+#endif
+{
+Status rtrn;
+register int i,tmp,nUnknown;
+KeyNameDesc * name;
+KeySym * syms;
+
+ if ((xkb->names==NULL)||(xkb->names->keys==NULL)) {
+ if ((rtrn=XkbAllocNames(xkb,XkbKeyNamesMask,0,0))!=Success)
+ return rtrn;
+ }
+ for (name=dfltKeys;(name->name[0]!='\0');name++) {
+ name->used= False;
+ }
+ nUnknown= 0;
+ for (i=xkb->min_key_code;i<=xkb->max_key_code;i++) {
+ tmp= XkbKeyNumSyms(xkb,i);
+ if ((xkb->names->keys[i].name[0]=='\0')&&(tmp>0)) {
+ tmp= XkbKeyGroupsWidth(xkb,i);
+ syms= XkbKeySymsPtr(xkb,i);
+ for (name=dfltKeys;(name->name[0]!='\0');name++) {
+ Bool match= True;
+ if (((name->level1!=syms[0])&&(name->level1!=NoSymbol))||
+ ((name->level2!=NoSymbol)&&(tmp<2))||
+ ((name->level2!=syms[1])&&(name->level2!=NoSymbol))) {
+ match= False;
+ }
+ if (match) {
+ if (!name->used) {
+ memcpy(xkb->names->keys[i].name,name->name,
+ XkbKeyNameLength);
+ name->used= True;
+ }
+ else {
+ if (warningLevel>2) {
+ WARN1("Several keys match pattern for %s\n",
+ XkbKeyNameText(name->name,XkbMessage));
+ ACTION2("Using <U%03d> for key %d\n",nUnknown,i);
+ }
+ sprintf(xkb->names->keys[i].name,"U%03d",nUnknown++);
+ }
+ break;
+ }
+ }
+ if (xkb->names->keys[i].name[0]=='\0') {
+ if (warningLevel>2) {
+ WARN1("Key %d does not match any defaults\n",i);
+ ACTION1("Using name <U%03d>\n",nUnknown);
+ sprintf(xkb->names->keys[i].name,"U%03d",nUnknown++);
+ }
+ }
+ }
+ }
+ return Success;
+}
+
+Bool
+#if NeedFunctionPrototypes
+FindNamedKey( XkbDescPtr xkb,
+ unsigned long name,
+ unsigned int * kc_rtrn,
+ Bool use_aliases,
+ Bool create,
+ int start_from)
+#else
+FindNamedKey(xkb,name,kc_rtrn,use_aliases,create,start_from)
+ XkbDescPtr xkb;
+ unsigned long name;
+ unsigned int * kc_rtrn;
+ Bool use_aliases;
+ Bool create;
+ int start_from;
+#endif
+{
+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)) {
+ if (xkb->min_key_code<XkbMinLegalKeyCode) {
+ xkb->min_key_code= XkbMinLegalKeyCode;
+ xkb->max_key_code= XkbMaxLegalKeyCode;
+ }
+ if (XkbAllocNames(xkb,XkbKeyNamesMask,0,0)!=Success) {
+ if (warningLevel>0) {
+ WARN("Couldn't allocate key names in FindNamedKey\n");
+ ACTION1("Key \"%s\" not automatically created\n",
+ longText(name,XkbMessage));
+ }
+ return False;
+ }
+ }
+ 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
+#if NeedFunctionPrototypes
+FindKeyNameForAlias(XkbDescPtr xkb,unsigned long lname,unsigned long *real_name)
+#else
+FindKeyNameForAlias(xkb,lname,real_name)
+ XkbDescPtr xkb;
+ unsigned long lname;
+ unsigned long * real_name;
+#endif
+{
+register int i;
+char name[XkbKeyNameLength+1];
+
+ if (xkb&&xkb->geom&&xkb->geom->key_aliases) {
+ XkbKeyAliasPtr a;
+ 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) {
+ XkbKeyAliasPtr a;
+ 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;
+}
diff --git a/misc.h b/misc.h
new file mode 100644
index 0000000..24dfc7d
--- /dev/null
+++ b/misc.h
@@ -0,0 +1,157 @@
+/* $Xorg: misc.h,v 1.3 2000/08/17 19:54:33 cpqbld Exp $ */
+/************************************************************
+ 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
+ documentation, and that the name of Silicon Graphics not be
+ used in advertising or publicity pertaining to distribution
+ of the software without specific prior written permission.
+ Silicon Graphics makes no representation about the suitability
+ of this software for any purpose. It is provided "as is"
+ without any express or implied warranty.
+
+ SILICON GRAPHICS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS
+ SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+ AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL SILICON
+ 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
+ OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH
+ THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+ ********************************************************/
+
+#ifndef MISC_H
+#define MISC_H 1
+
+typedef struct _CommonInfo {
+ unsigned short defined;
+ unsigned char fileID;
+ unsigned char merge;
+ struct _CommonInfo * next;
+} CommonInfo;
+
+_XFUNCPROTOBEGIN
+
+extern Bool UseNewField(
+#if NeedFunctionPrototypes
+ unsigned /* field */,
+ CommonInfo * /* oldDefs */,
+ CommonInfo * /* newDefs */,
+ unsigned * /* pCollide */
+#endif
+);
+
+extern Bool MergeNewField(
+#if NeedFunctionPrototypes
+ unsigned /* field */,
+ CommonInfo * /* oldDefs */,
+ CommonInfo * /* newDefs */,
+ unsigned * /* pCollide */
+#endif
+);
+
+extern XPointer ClearCommonInfo(
+#if NeedFunctionPrototypes
+ CommonInfo * /* cmn */
+#endif
+);
+
+extern XPointer AddCommonInfo(
+#if NeedFunctionPrototypes
+ CommonInfo * /* old */,
+ CommonInfo * /* new */
+#endif
+);
+
+extern int ReportNotArray(
+#if NeedFunctionPrototypes
+ char * /* type */,
+ char * /* field */,
+ char * /* name */
+#endif
+);
+
+extern int ReportShouldBeArray(
+#if NeedFunctionPrototypes
+ char * /* type */,
+ char * /* field */,
+ char * /* name */
+#endif
+);
+
+extern int ReportBadType(
+#if NeedFunctionPrototypes
+ char * /* type */,
+ char * /* field */,
+ char * /* name */,
+ char * /* wanted */
+#endif
+);
+
+extern int ReportBadIndexType(
+#if NeedFunctionPrototypes
+ char * /* type */,
+ char * /* field */,
+ char * /* name */,
+ char * /* wanted */
+#endif
+);
+
+extern int ReportBadField(
+#if NeedFunctionPrototypes
+ char * /* type */,
+ char * /* field */,
+ char * /* name */
+#endif
+);
+
+extern int ReportMultipleDefs(
+#if NeedFunctionPrototypes
+ char * /* type */,
+ char * /* field */,
+ char * /* which */
+#endif
+);
+
+extern Bool ProcessIncludeFile(
+#if NeedFunctionPrototypes
+ IncludeStmt * /* stmt */,
+ unsigned /* file_type */,
+ XkbFile ** /* file_rtrn */,
+ unsigned * /* merge_rtrn */
+#endif
+);
+
+extern Status ComputeKbdDefaults(
+#if NeedFunctionPrototypes
+ XkbDescPtr /* xkb */
+#endif
+);
+
+extern Bool FindNamedKey(
+#if NeedFunctionPrototypes
+ XkbDescPtr /* xkb */,
+ unsigned long /* name */,
+ unsigned int * /* kc_rtrn */,
+ Bool /* use_aliases */,
+ Bool /* create */,
+ int /* start_from */
+#endif
+);
+
+extern Bool FindKeyNameForAlias(
+#if NeedFunctionPrototypes
+ XkbDescPtr /* xkb */,
+ unsigned long /* lname */,
+ unsigned long * /* real_name */
+#endif
+);
+
+_XFUNCPROTOEND
+
+#endif /* MISC_H */
diff --git a/parseutils.c b/parseutils.c
new file mode 100644
index 0000000..468d620
--- /dev/null
+++ b/parseutils.c
@@ -0,0 +1,966 @@
+/* $Xorg: parseutils.c,v 1.3 2000/08/17 19:54:33 cpqbld Exp $ */
+/************************************************************
+ 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
+ documentation, and that the name of Silicon Graphics not be
+ used in advertising or publicity pertaining to distribution
+ of the software without specific prior written permission.
+ Silicon Graphics makes no representation about the suitability
+ of this software for any purpose. It is provided "as is"
+ without any express or implied warranty.
+
+ SILICON GRAPHICS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS
+ SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+ AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL SILICON
+ 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
+ OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH
+ THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+ ********************************************************/
+#define DEBUG_VAR_NOT_LOCAL
+#define DEBUG_VAR parseDebug
+#include "parseutils.h"
+#include "xkbpath.h"
+#include <X11/keysym.h>
+#include <X11/extensions/XKBgeom.h>
+#include <X11/Xalloca.h>
+
+XkbFile *rtrnValue;
+
+ParseCommon *
+#if NeedFunctionPrototypes
+AppendStmt(ParseCommon *to,ParseCommon *append)
+#else
+AppendStmt(to,append)
+ ParseCommon * to;
+ ParseCommon * append;
+#endif
+{
+ParseCommon *start= to;
+
+ if (append==NULL)
+ return to;
+ while ((to!=NULL) && (to->next!=NULL)) {
+ to= to->next;
+ }
+ if (to) {
+ to->next= append;
+ return start;
+ }
+ return append;
+}
+
+ExprDef *
+#if NeedFunctionPrototypes
+ExprCreate(unsigned op,unsigned type)
+#else
+ExprCreate(op,type)
+ unsigned op;
+ unsigned type;
+#endif
+{
+ExprDef *expr;
+ expr= uTypedAlloc(ExprDef);
+ if (expr) {
+ expr->common.stmtType= StmtExpr;
+ expr->common.next= NULL;
+ expr->op= op;
+ expr->type= type;
+ }
+ else {
+ FATAL("Couldn't allocate expression in parser\n");
+ /* NOTREACHED */
+ }
+ return expr;
+}
+
+ExprDef *
+#if NeedFunctionPrototypes
+ExprCreateUnary(unsigned op,unsigned type,ExprDef *child)
+#else
+ExprCreateUnary(op,type,child)
+ unsigned op;
+ unsigned type;
+ ExprDef *child;
+#endif
+{
+ExprDef *expr;
+ expr= uTypedAlloc(ExprDef);
+ if (expr) {
+ expr->common.stmtType= StmtExpr;
+ expr->common.next= NULL;
+ expr->op= op;
+ expr->type= type;
+ expr->value.child= child;
+ }
+ else {
+ FATAL("Couldn't allocate expression in parser\n");
+ /* NOTREACHED */
+ }
+ return expr;
+}
+
+ExprDef *
+#if NeedFunctionPrototypes
+ExprCreateBinary(unsigned op,ExprDef *left,ExprDef *right)
+#else
+ExprCreateBinary(op,left,right)
+ unsigned op;
+ ExprDef *left;
+ ExprDef *right;
+#endif
+{
+ExprDef *expr;
+ expr= uTypedAlloc(ExprDef);
+ if (expr) {
+ expr->common.stmtType= StmtExpr;
+ expr->common.next= NULL;
+ expr->op= op;
+ if ((op==OpAssign)||(left->type==TypeUnknown))
+ expr->type= right->type;
+ else if ((left->type==right->type)||(right->type==TypeUnknown))
+ expr->type= left->type;
+ else expr->type= TypeUnknown;
+ expr->value.binary.left= left;
+ expr->value.binary.right= right;
+ }
+ else {
+ FATAL("Couldn't allocate expression in parser\n");
+ /* NOTREACHED */
+ }
+ return expr;
+}
+
+KeycodeDef *
+#if NeedFunctionPrototypes
+KeycodeCreate(char *name,ExprDef *value)
+#else
+KeycodeCreate(name,value)
+ char * name;
+ ExprDef * value;
+#endif
+{
+KeycodeDef *def;
+
+ def= uTypedAlloc(KeycodeDef);
+ if (def) {
+ def->common.stmtType= StmtKeycodeDef;
+ def->common.next= NULL;
+ strncpy(def->name,name,XkbKeyNameLength);
+ def->name[XkbKeyNameLength]= '\0';
+ def->value= value;
+ }
+ else {
+ FATAL("Couldn't allocate key name definition in parser\n");
+ /* NOTREACHED */
+ }
+ return def;
+}
+
+KeyAliasDef *
+#if NeedFunctionPrototypes
+KeyAliasCreate(char *alias,char *real)
+#else
+KeyAliasCreate(alias,real)
+ char * alias;
+ char * real;
+#endif
+{
+KeyAliasDef *def;
+
+ def= uTypedAlloc(KeyAliasDef);
+ if (def) {
+ def->common.stmtType= StmtKeyAliasDef;
+ def->common.next= NULL;
+ strncpy(def->alias,alias,XkbKeyNameLength);
+ def->alias[XkbKeyNameLength]= '\0';
+ strncpy(def->real,real,XkbKeyNameLength);
+ def->real[XkbKeyNameLength]= '\0';
+ }
+ else {
+ FATAL("Couldn't allocate key alias definition in parser\n");
+ /* NOTREACHED */
+ }
+ return def;
+}
+
+VModDef *
+#if NeedFunctionPrototypes
+VModCreate(Atom name,ExprDef *value)
+#else
+VModCreate(name,value)
+ Atom name;
+ ExprDef * value;
+#endif
+{
+VModDef *def;
+ def= uTypedAlloc(VModDef);
+ if (def) {
+ def->common.stmtType= StmtVModDef;
+ def->common.next= NULL;
+ def->name= name;
+ def->value= value;
+ }
+ else {
+ FATAL("Couldn't allocate variable definition in parser\n");
+ /* NOTREACHED */
+ }
+ return def;
+}
+
+VarDef *
+#if NeedFunctionPrototypes
+VarCreate(ExprDef *name,ExprDef *value)
+#else
+VarCreate(name,value)
+ ExprDef * name;
+ ExprDef * value;
+#endif
+{
+VarDef *def;
+ def= uTypedAlloc(VarDef);
+ if (def) {
+ def->common.stmtType= StmtVarDef;
+ def->common.next= NULL;
+ def->name= name;
+ def->value= value;
+ }
+ else {
+ FATAL("Couldn't allocate variable definition in parser\n");
+ /* NOTREACHED */
+ }
+ return def;
+}
+
+VarDef *
+#if NeedFunctionPrototypes
+BoolVarCreate(Atom nameToken,unsigned set)
+#else
+BoolVarCreate(nameToken,set)
+ Atom nameToken;
+ unsigned set;
+#endif
+{
+ExprDef *name,*value;
+
+ name= ExprCreate(ExprIdent,TypeUnknown);
+ name->value.str= nameToken;
+ value= ExprCreate(ExprValue,TypeBoolean);
+ value->value.uval= set;
+ return VarCreate(name,value);
+}
+
+InterpDef *
+#if NeedFunctionPrototypes
+InterpCreate(KeySym sym,ExprDef *match)
+#else
+InterpCreate(sym,match)
+ KeySym sym;
+ ExprDef * match;
+#endif
+{
+InterpDef *def;
+
+ def= uTypedAlloc(InterpDef);
+ if (def) {
+ def->common.stmtType= StmtInterpDef;
+ def->common.next= NULL;
+ def->sym= sym;
+ def->match= match;
+ }
+ else {
+ FATAL("Couldn't allocate interp definition in parser\n");
+ /* NOTREACHED */
+ }
+ return def;
+}
+
+KeyTypeDef *
+#if NeedFunctionPrototypes
+KeyTypeCreate(Atom name,VarDef *body)
+#else
+KeyTypeCreate(name,body)
+ Atom name;
+ VarDef * body;
+#endif
+{
+KeyTypeDef *def;
+
+ def= uTypedAlloc(KeyTypeDef);
+ if (def) {
+ def->common.stmtType= StmtKeyTypeDef;
+ def->common.next= NULL;
+ def->merge= MergeDefault;
+ def->name= name;
+ def->body= body;
+ }
+ else {
+ FATAL("Couldn't allocate key type definition in parser\n");
+ /* NOTREACHED */
+ }
+ return def;
+}
+
+SymbolsDef *
+#if NeedFunctionPrototypes
+SymbolsCreate(char *keyName,ExprDef *symbols)
+#else
+SymbolsCreate(keyName,symbols)
+ char * keyName;
+ ExprDef * symbols;
+#endif
+{
+SymbolsDef *def;
+
+ def= uTypedAlloc(SymbolsDef);
+ if (def) {
+ def->common.stmtType= StmtSymbolsDef;
+ def->common.next= NULL;
+ def->merge= MergeDefault;
+ bzero(def->keyName,5);
+ strncpy(def->keyName,keyName,4);
+ def->symbols= symbols;
+ }
+ else {
+ FATAL("Couldn't allocate symbols definition in parser\n");
+ /* NOTREACHED */
+ }
+ return def;
+}
+
+GroupCompatDef *
+#if NeedFunctionPrototypes
+GroupCompatCreate(int group,ExprDef *val)
+#else
+GroupCompatCreate(group,val)
+ int group;
+ ExprDef * val;
+#endif
+{
+GroupCompatDef *def;
+
+ def= uTypedAlloc(GroupCompatDef);
+ if (def) {
+ def->common.stmtType= StmtGroupCompatDef;
+ def->common.next= NULL;
+ def->merge= MergeDefault;
+ def->group= group;
+ def->def= val;
+ }
+ else {
+ FATAL("Couldn't allocate group compat definition in parser\n");
+ /* NOTREACHED */
+ }
+ return def;
+}
+
+ModMapDef *
+#if NeedFunctionPrototypes
+ModMapCreate(Atom modifier,ExprDef *keys)
+#else
+ModMapCreate(modifier,keys)
+ Atom modifier;
+ ExprDef * keys;
+#endif
+{
+ModMapDef *def;
+
+ def= uTypedAlloc(ModMapDef);
+ if (def) {
+ def->common.stmtType= StmtModMapDef;
+ def->common.next= NULL;
+ def->merge= MergeDefault;
+ def->modifier= modifier;
+ def->keys= keys;
+ }
+ else {
+ FATAL("Couldn't allocate mod mask definition in parser\n");
+ /* NOTREACHED */
+ }
+ return def;
+}
+
+IndicatorMapDef *
+#if NeedFunctionPrototypes
+IndicatorMapCreate(Atom name,VarDef *body)
+#else
+IndicatorMapCreate(name,body)
+ Atom name;
+ VarDef * body;
+#endif
+{
+IndicatorMapDef *def;
+
+ def= uTypedAlloc(IndicatorMapDef);
+ if (def) {
+ def->common.stmtType= StmtIndicatorMapDef;
+ def->common.next= NULL;
+ def->merge= MergeDefault;
+ def->name= name;
+ def->body= body;
+ }
+ else {
+ FATAL("Couldn't allocate indicator map definition in parser\n");
+ /* NOTREACHED */
+ }
+ return def;
+}
+
+IndicatorNameDef *
+#if NeedFunctionPrototypes
+IndicatorNameCreate(int ndx,ExprDef *name,Bool virtual)
+#else
+IndicatorNameCreate(ndx,name,virtual)
+ int ndx;
+ ExprDef * name;
+ Bool virtual;
+#endif
+{
+IndicatorNameDef *def;
+
+ def= uTypedAlloc(IndicatorNameDef);
+ if (def) {
+ def->common.stmtType= StmtIndicatorNameDef;
+ def->common.next= NULL;
+ def->merge= MergeDefault;
+ def->ndx= ndx;
+ def->name= name;
+ def->virtual= virtual;
+ }
+ else {
+ FATAL("Couldn't allocate indicator index definition in parser\n");
+ /* NOTREACHED */
+ }
+ return def;
+}
+
+ExprDef *
+#if NeedFunctionPrototypes
+ActionCreate(Atom name,ExprDef *args)
+#else
+ActionCreate(name,args)
+ Atom name;
+ ExprDef *args;
+#endif
+{
+ExprDef *act;
+
+ act= uTypedAlloc(ExprDef);
+ if (act) {
+ act->common.stmtType= StmtExpr;
+ act->common.next= NULL;
+ act->op= ExprActionDecl;
+ act->value.action.name= name;
+ act->value.action.args= args;
+ return act;
+ }
+ FATAL("Couldn't allocate ActionDef in parser\n");
+ return NULL;
+}
+
+ExprDef *
+#if NeedFunctionPrototypes
+CreateKeysymList(KeySym sym)
+#else
+CreateKeysymList(sym)
+ KeySym sym;
+#endif
+{
+ExprDef *def;
+
+ def= ExprCreate(ExprKeysymList,TypeSymbols);
+ if (def) {
+ def->value.list.nSyms= 1;
+ def->value.list.szSyms= 2;
+ def->value.list.syms= uTypedCalloc(2,KeySym);
+ if (def->value.list.syms!=NULL) {
+ def->value.list.syms[0]= sym;
+ return def;
+ }
+ }
+ FATAL("Couldn't allocate expression for keysym list in parser\n");
+ return NULL;
+}
+
+ShapeDef *
+#if NeedFunctionPrototypes
+ShapeDeclCreate(Atom name,OutlineDef *outlines)
+#else
+ShapeDeclCreate(name,outlines)
+ Atom name;
+ OutlineDef * outlines;
+#endif
+{
+ShapeDef * shape;
+OutlineDef * ol;
+
+ shape= uTypedAlloc(ShapeDef);
+ if (shape!=NULL) {
+ bzero(shape,sizeof(ShapeDef));
+ shape->common.stmtType= StmtShapeDef;
+ shape->common.next= NULL;
+ shape->merge= MergeDefault;
+ shape->name= name;
+ shape->nOutlines= 0;
+ shape->outlines= outlines;
+ for (ol=outlines;ol!=NULL;ol= (OutlineDef *)ol->common.next) {
+ if (ol->nPoints>0)
+ shape->nOutlines++;
+ }
+ }
+ return shape;
+}
+
+OutlineDef *
+#if NeedFunctionPrototypes
+OutlineCreate(Atom field,ExprDef *points)
+#else
+OutlineCreate(field,points)
+ Atom field;
+ ExprDef * points;
+#endif
+{
+OutlineDef * outline;
+ExprDef * pt;
+
+ outline= uTypedAlloc(OutlineDef);
+ if (outline!=NULL) {
+ bzero(outline,sizeof(OutlineDef));
+ outline->common.stmtType= StmtOutlineDef;
+ outline->common.next= NULL;
+ outline->field= field;
+ outline->nPoints= 0;
+ if (points->op==ExprCoord) {
+ for (pt=points;pt!=NULL;pt= (ExprDef *)pt->common.next) {
+ outline->nPoints++;
+ }
+ }
+ outline->points= points;
+ }
+ return outline;
+}
+
+KeyDef *
+#if NeedFunctionPrototypes
+KeyDeclCreate(char *name,ExprDef *expr)
+#else
+KeyDeclCreate(name,expr)
+ char * name;
+ ExprDef * expr;
+#endif
+{
+KeyDef * key;
+
+ key= uTypedAlloc(KeyDef);
+ if (key!=NULL) {
+ bzero(key,sizeof(KeyDef));
+ key->common.stmtType= StmtKeyDef;
+ key->common.next= NULL;
+ if (name) key->name= name;
+ else key->expr= expr;
+ }
+ return key;
+}
+
+KeyDef *
+#if NeedFunctionPrototypes
+KeyDeclMerge(KeyDef *into,KeyDef *from)
+#else
+KeyDeclMerge(into,from)
+ KeyDef * into;
+ KeyDef * from;
+#endif
+{
+ into->expr= (ExprDef *)AppendStmt(&into->expr->common,&from->expr->common);
+ from->expr= NULL;
+ uFree(from);
+ return into;
+}
+
+RowDef *
+#if NeedFunctionPrototypes
+RowDeclCreate(KeyDef * keys)
+#else
+RowDeclCreate(keys)
+ KeyDef * keys;
+#endif
+{
+RowDef * row;
+KeyDef * key;
+
+ row= uTypedAlloc(RowDef);
+ if (row!=NULL) {
+ bzero(row,sizeof(RowDef));
+ row->common.stmtType= StmtRowDef;
+ row->common.next= NULL;
+ row->nKeys= 0;
+ row->keys= keys;
+ for (key=keys;key!=NULL;key=(KeyDef *)key->common.next) {
+ if (key->common.stmtType==StmtKeyDef)
+ row->nKeys++;
+ }
+ }
+ return row;
+}
+
+SectionDef *
+#if NeedFunctionPrototypes
+SectionDeclCreate(Atom name,RowDef *rows)
+#else
+SectionDeclCreate(name,rows)
+ Atom name;
+ RowDef * rows;
+#endif
+{
+SectionDef * section;
+RowDef * row;
+
+ section= uTypedAlloc(SectionDef);
+ if (section!=NULL) {
+ bzero(section,sizeof(SectionDef));
+ section->common.stmtType= StmtSectionDef;
+ section->common.next= NULL;
+ section->name= name;
+ section->nRows= 0;
+ section->rows= rows;
+ for (row=rows;row!=NULL;row=(RowDef *)row->common.next) {
+ if (row->common.stmtType==StmtRowDef)
+ section->nRows++;
+ }
+ }
+ return section;
+}
+
+OverlayKeyDef *
+#if NeedFunctionPrototypes
+OverlayKeyCreate(char * under,char *over)
+#else
+OverlayKeyCreate(under,over)
+ char * under;
+ char * over;
+#endif
+{
+OverlayKeyDef * key;
+
+ key= uTypedAlloc(OverlayKeyDef);
+ if (key!=NULL) {
+ bzero(key,sizeof(OverlayKeyDef));
+ key->common.stmtType= StmtOverlayKeyDef;
+ strncpy(key->over,over,XkbKeyNameLength);
+ strncpy(key->under,under,XkbKeyNameLength);
+ if (over) uFree(over);
+ if (under) uFree(under);
+ }
+ return key;
+}
+
+OverlayDef *
+#if NeedFunctionPrototypes
+OverlayDeclCreate(Atom name,OverlayKeyDef *keys)
+#else
+OverlayDeclCreate(name,keys)
+ Atom name;
+ OverlayKeyDef * keys;
+#endif
+{
+OverlayDef * ol;
+OverlayKeyDef * key;
+
+ ol= uTypedAlloc(OverlayDef);
+ if (ol!=NULL) {
+ bzero(ol,sizeof(OverlayDef));
+ ol->common.stmtType= StmtOverlayDef;
+ ol->name= name;
+ ol->keys= keys;
+ for (key=keys;key!=NULL;key=(OverlayKeyDef *)key->common.next) {
+ ol->nKeys++;
+ }
+ }
+ return ol;
+}
+
+DoodadDef *
+#if NeedFunctionPrototypes
+DoodadCreate(unsigned type,Atom name,VarDef *body)
+#else
+DoodadCreate(type,name,body)
+ unsigned type;
+ Atom name;
+ VarDef * body;
+#endif
+{
+DoodadDef * doodad;
+
+ doodad= uTypedAlloc(DoodadDef);
+ if (doodad!=NULL) {
+ bzero(doodad,sizeof(DoodadDef));
+ doodad->common.stmtType= StmtDoodadDef;
+ doodad->common.next= NULL;
+ doodad->type= type;
+ doodad->name= name;
+ doodad->body= body;
+ }
+ return doodad;
+}
+
+ExprDef *
+#if NeedFunctionPrototypes
+AppendKeysymList(ExprDef *list,KeySym sym)
+#else
+AppendKeysymList(list,sym)
+ ExprDef * list;
+ KeySym sym;
+#endif
+{
+ if (list->value.list.nSyms>=list->value.list.szSyms) {
+ list->value.list.szSyms*=2;
+ list->value.list.syms= uTypedRecalloc(list->value.list.syms,
+ list->value.list.nSyms,
+ list->value.list.szSyms,
+ KeySym);
+ if (list->value.list.syms==NULL) {
+ FATAL("Couldn't resize list of symbols for append\n");
+ return NULL;
+ }
+ }
+ list->value.list.syms[list->value.list.nSyms++]= sym;
+ return list;
+}
+
+int
+#if NeedFunctionPrototypes
+LookupKeysym(char *str,KeySym *sym_rtrn)
+#else
+LookupKeysym(str,sym_rtrn)
+ char *str;
+ KeySym *sym_rtrn;
+#endif
+{
+KeySym sym;
+
+ if ((!str)||(uStrCaseCmp(str,"any")==0)||(uStrCaseCmp(str,"nosymbol")==0)) {
+ *sym_rtrn= NoSymbol;
+ return 1;
+ }
+ else if ((uStrCaseCmp(str,"none")==0)||(uStrCaseCmp(str,"voidsymbol")==0)) {
+ *sym_rtrn= XK_VoidSymbol;
+ return 1;
+ }
+ sym= XStringToKeysym(str);
+ if (sym!=NoSymbol) {
+ *sym_rtrn= sym;
+ return 1;
+ }
+ return 0;
+}
+
+IncludeStmt *
+#if NeedFunctionPrototypes
+IncludeCreate(char *str,unsigned merge)
+#else
+IncludeCreate(str,merge)
+ char * str;
+ unsigned merge;
+#endif
+{
+IncludeStmt * incl,*first;
+char * file,*map,*stmt,*tmp;
+char nextop;
+Bool haveSelf;
+
+ haveSelf= False;
+ incl= first= NULL;
+ file= map= NULL;
+ tmp= str;
+ stmt= uStringDup(str);
+ while ((tmp)&&(*tmp)) {
+ if (XkbParseIncludeMap(&tmp,&file,&map,&nextop)) {
+ if ((file==NULL)&&(map==NULL)) {
+ if (haveSelf)
+ goto BAIL;
+ haveSelf= True;
+ }
+ if (first==NULL)
+ first= incl= uTypedAlloc(IncludeStmt);
+ else {
+ incl->next= uTypedAlloc(IncludeStmt);
+ incl= incl->next;
+ }
+ if (incl) {
+ incl->common.stmtType= StmtInclude;
+ incl->common.next= NULL;
+ incl->merge= merge;
+ incl->stmt= NULL;
+ incl->file= file;
+ incl->map= map;
+ incl->path= NULL;
+ incl->next= NULL;
+ }
+ else {
+ WSGO("Allocation failure in IncludeCreate\n");
+ ACTION("Using only part of the include\n");
+ break;
+ }
+ if (nextop=='|') merge= MergeAugment;
+ else merge= MergeOverride;
+ }
+ else {
+ goto BAIL;
+ }
+ }
+ if (first) first->stmt= stmt;
+ else if (stmt) uFree(stmt);
+ return first;
+BAIL:
+ ERROR1("Illegal include statement \"%s\"\n",stmt);
+ ACTION("Ignored\n");
+ while (first) {
+ incl= first->next;
+ if (first->file) uFree(first->file);
+ if (first->map) uFree(first->map);
+ if (first->path) uFree(first->path);
+ first->file= first->map= first->path= NULL;
+ uFree(first);
+ first= incl;
+ }
+ if (stmt)
+ uFree(stmt);
+ return NULL;
+}
+
+#ifdef DEBUG
+void
+#if NeedFunctionPrototypes
+PrintStmtAddrs(ParseCommon *stmt)
+#else
+PrintStmtAddrs(stmt)
+ ParseCommon * stmt;
+#endif
+{
+ fprintf(stderr,"0x%x",stmt);
+ if (stmt) {
+ do {
+ fprintf(stderr,"->0x%x",stmt->next);
+ stmt= stmt->next;
+ } while (stmt);
+ }
+ fprintf(stderr,"\n");
+}
+#endif
+
+static void
+#if NeedFunctionPrototypes
+CheckDefaultMap(XkbFile *maps)
+#else
+CheckDefaultMap(maps)
+XkbFile *maps;
+#endif
+{
+XkbFile * dflt,*tmp;
+
+ dflt= NULL;
+ for (tmp=maps,dflt=NULL;tmp!=NULL;tmp=(XkbFile *)tmp->common.next) {
+ if (tmp->flags&XkbLC_Default) {
+ if (dflt==NULL)
+ dflt= tmp;
+ else {
+ if (warningLevel>2) {
+ WARN1("Multiple default components in %s\n",
+ (scanFile?scanFile:"(unknown)"));
+ ACTION2("Using %s, ignoring %s\n",
+ (dflt->name?dflt->name:"(first)"),
+ (tmp->name?tmp->name:"(subsequent)"));
+ }
+ tmp->flags&= (~XkbLC_Default);
+ }
+ }
+ }
+ return;
+}
+
+_XFUNCPROTOBEGIN
+extern int yyparse(
+#if NeedFunctionPrototypes
+ void
+#endif
+);
+_XFUNCPROTOEND
+
+extern FILE * yyin;
+
+int
+#if NeedFunctionPrototypes
+XKBParseFile(FILE *file,XkbFile **pRtrn)
+#else
+XKBParseFile(file,pRtrn)
+FILE *file;
+XkbFile **pRtrn;
+#endif
+{
+ if (file) {
+ yyin= file;
+ rtrnValue= NULL;
+ if (yyparse()==0) {
+ *pRtrn= rtrnValue;
+ CheckDefaultMap(rtrnValue);
+ rtrnValue= NULL;
+ return 1;
+ }
+ *pRtrn= NULL;
+ return 0;
+ }
+ *pRtrn= NULL;
+ return 1;
+}
+
+XkbFile *
+#if NeedFunctionPrototypes
+CreateXKBFile(int type,char *name,ParseCommon *defs,unsigned flags)
+#else
+CreateXKBFile(type,name,defs,flags)
+int type;
+char * name;
+ParseCommon * defs;
+unsigned flags;
+#endif
+{
+XkbFile * file;
+static int fileID;
+
+ file= uTypedAlloc(XkbFile);
+ if (file) {
+ XkbEnsureSafeMapName(name);
+ bzero(file,sizeof(XkbFile));
+ file->type= type;
+ file->topName= uStringDup(name);
+ file->name= name;
+ file->defs= defs;
+ file->id= fileID++;
+ file->compiled= False;
+ file->flags= flags;
+ }
+ return file;
+}
+
+unsigned
+#if NeedFunctionPrototypes
+StmtSetMerge(ParseCommon *stmt,unsigned merge)
+#else
+StmtSetMerge(stmt,merge)
+ ParseCommon * stmt;
+ unsigned merge;
+#endif
+{
+ if ((merge==MergeAltForm) && (stmt->stmtType!=StmtKeycodeDef)) {
+ yyerror("illegal use of 'alternate' merge mode");
+ merge= MergeDefault;
+ }
+ return merge;
+}
diff --git a/parseutils.h b/parseutils.h
new file mode 100644
index 0000000..6393747
--- /dev/null
+++ b/parseutils.h
@@ -0,0 +1,319 @@
+/* $Xorg: parseutils.h,v 1.3 2000/08/17 19:54:33 cpqbld Exp $ */
+/************************************************************
+ 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
+ documentation, and that the name of Silicon Graphics not be
+ used in advertising or publicity pertaining to distribution
+ of the software without specific prior written permission.
+ Silicon Graphics makes no representation about the suitability
+ of this software for any purpose. It is provided "as is"
+ without any express or implied warranty.
+
+ SILICON GRAPHICS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS
+ SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+ AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL SILICON
+ 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
+ OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH
+ THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+ ********************************************************/
+
+#ifndef XKBPARSE_H
+#define XKBPARSE_H 1
+
+#ifndef DEBUG_VAR
+#define DEBUG_VAR parseDebug
+#endif
+
+#include "xkbcomp.h"
+
+extern char *scanStr;
+extern int scanInt;
+extern int lineNum;
+
+extern XkbFile *rtrnValue;
+
+#ifdef DEBUG
+#define d(str) fprintf(stderr,"%s\n",str);
+#define d1(str,a) fprintf(stderr,str,a);
+#define d2(str,a,b) fprintf(stderr,str,a,b);
+#else
+#define d(str)
+#define d1(str,a)
+#define d2(str,a,b)
+#endif
+
+_XFUNCPROTOBEGIN
+
+extern ParseCommon *AppendStmt(
+#if NeedFunctionPrototypes
+ ParseCommon * /* to */,
+ ParseCommon * /* append */
+#endif
+);
+
+extern ExprDef *ExprCreate(
+#if NeedFunctionPrototypes
+ unsigned /* op */,
+ unsigned /* type */
+#endif
+);
+
+extern ExprDef *ExprCreateUnary(
+#if NeedFunctionPrototypes
+ unsigned /* op */,
+ unsigned /* type */,
+ ExprDef * /* child */
+#endif
+);
+
+extern ExprDef *ExprCreateBinary(
+#if NeedFunctionPrototypes
+ unsigned /* op */,
+ ExprDef * /* left */,
+ ExprDef * /* right */
+#endif
+);
+
+extern KeycodeDef *KeycodeCreate(
+#if NeedFunctionPrototypes
+ char * /* name */,
+ ExprDef * /* value */
+#endif
+);
+
+extern KeyAliasDef *KeyAliasCreate(
+#if NeedFunctionPrototypes
+ char * /* alias */,
+ char * /* real */
+#endif
+);
+
+extern VModDef *VModCreate(
+#if NeedFunctionPrototypes
+ Atom /* name */,
+ ExprDef * /* value */
+#endif
+);
+
+extern VarDef *VarCreate(
+#if NeedFunctionPrototypes
+ ExprDef * /* name */,
+ ExprDef * /* value */
+#endif
+);
+
+extern VarDef *BoolVarCreate(
+#if NeedFunctionPrototypes
+ Atom /* nameToken */,
+ unsigned /* set */
+#endif
+);
+
+extern InterpDef *InterpCreate(
+#if NeedFunctionPrototypes
+ KeySym /* sym */,
+ ExprDef * /* match */
+#endif
+);
+
+extern KeyTypeDef *KeyTypeCreate(
+#if NeedFunctionPrototypes
+ Atom /* name */,
+ VarDef * /* body */
+#endif
+);
+
+extern SymbolsDef *SymbolsCreate(
+#if NeedFunctionPrototypes
+ char * /* keyName */,
+ ExprDef * /* symbols */
+#endif
+);
+
+extern GroupCompatDef *GroupCompatCreate(
+#if NeedFunctionPrototypes
+ int /* group */,
+ ExprDef * /* def */
+#endif
+);
+
+extern ModMapDef *ModMapCreate(
+#if NeedFunctionPrototypes
+ Atom /* modifier */,
+ ExprDef * /* keys */
+#endif
+);
+
+extern IndicatorMapDef *IndicatorMapCreate(
+#if NeedFunctionPrototypes
+ Atom /* name */,
+ VarDef * /* body */
+#endif
+);
+
+extern IndicatorNameDef *IndicatorNameCreate(
+#if NeedFunctionPrototypes
+ int /* ndx */,
+ ExprDef * /* name */,
+ Bool /* virtual */
+#endif
+);
+
+extern ExprDef *ActionCreate(
+#if NeedFunctionPrototypes
+ Atom /* name */,
+ ExprDef * /* args */
+#endif
+);
+
+extern ExprDef *CreateKeysymList(
+#if NeedFunctionPrototypes
+ KeySym /* sym */
+#endif
+);
+
+extern ShapeDef *ShapeDeclCreate(
+#if NeedFunctionPrototypes
+ Atom /* name */,
+ OutlineDef * /* outlines */
+#endif
+);
+
+extern OutlineDef *OutlineCreate(
+#if NeedFunctionPrototypes
+ Atom /* field */,
+ ExprDef * /* points */
+#endif
+);
+
+extern KeyDef *KeyDeclCreate(
+#if NeedFunctionPrototypes
+ char * /* name */,
+ ExprDef * /* expr */
+#endif
+);
+
+extern KeyDef *KeyDeclMerge(
+#if NeedFunctionPrototypes
+ KeyDef * /* into */,
+ KeyDef * /* from */
+#endif
+);
+
+extern RowDef *RowDeclCreate(
+#if NeedFunctionPrototypes
+ KeyDef * /* keys */
+#endif
+);
+
+extern SectionDef *SectionDeclCreate(
+#if NeedFunctionPrototypes
+ Atom /* name */,
+ RowDef * /* rows */
+#endif
+);
+
+extern OverlayKeyDef *OverlayKeyCreate(
+#if NeedFunctionPrototypes
+ char * /* under */,
+ char * /* over */
+#endif
+);
+
+extern OverlayDef *OverlayDeclCreate(
+#if NeedFunctionPrototypes
+ Atom /* name */,
+ OverlayKeyDef * /* rows */
+#endif
+);
+
+extern DoodadDef *DoodadCreate(
+#if NeedFunctionPrototypes
+ unsigned /* type */,
+ Atom /* name */,
+ VarDef * /* body */
+#endif
+);
+
+extern ExprDef *AppendKeysymList(
+#if NeedFunctionPrototypes
+ ExprDef * /* list */,
+ KeySym /* sym */
+#endif
+);
+
+extern int LookupKeysym(
+#if NeedFunctionPrototypes
+ char * /* str */,
+ KeySym * /* sym_rtrn */
+#endif
+);
+
+extern IncludeStmt *IncludeCreate(
+#if NeedFunctionPrototypes
+ char * /* str */,
+ unsigned /* merge */
+#endif
+);
+
+extern unsigned StmtSetMerge(
+#if NeedFunctionPrototypes
+ ParseCommon * /* stmt */,
+ unsigned /* merge */
+#endif
+);
+
+#ifdef DEBUG
+extern void PrintStmtAddrs(
+#if NeedFunctionPrototypes
+ ParseCommon * /* stmt */
+#endif
+);
+#endif
+
+extern int XKBParseFile(
+#if NeedFunctionPrototypes
+FILE * /* file */,
+ XkbFile ** /* pRtrn */
+#endif
+);
+
+extern XkbFile *CreateXKBFile(
+#if NeedFunctionPrototypes
+ int /* type */,
+ char * /* name */,
+ ParseCommon * /* defs */,
+ unsigned /* flags */
+#endif
+);
+
+extern void yyerror(
+#if NeedFunctionPrototypes
+ char * /* s */
+#endif
+);
+
+extern int yywrap(
+#if NeedFunctionPrototypes
+ void
+#endif
+);
+
+extern int setScanState(
+#if NeedFunctionPrototypes
+ char * /* file */,
+ int /* line */
+#endif
+);
+
+_XFUNCPROTOEND
+
+#endif /* XKBPARSE_H */
diff --git a/symbols.c b/symbols.c
new file mode 100644
index 0000000..79f76de
--- /dev/null
+++ b/symbols.c
@@ -0,0 +1,1920 @@
+/* $Xorg: symbols.c,v 1.3 2000/08/17 19:54:33 cpqbld Exp $ */
+/************************************************************
+ 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
+ documentation, and that the name of Silicon Graphics not be
+ used in advertising or publicity pertaining to distribution
+ of the software without specific prior written permission.
+ Silicon Graphics makes no representation about the suitability
+ of this software for any purpose. It is provided "as is"
+ without any express or implied warranty.
+
+ SILICON GRAPHICS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS
+ SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+ AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL SILICON
+ 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
+ OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH
+ THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+ ********************************************************/
+
+#include "xkbcomp.h"
+#include "tokens.h"
+#include "expr.h"
+
+#include <X11/keysym.h>
+#include <X11/Xutil.h>
+
+#include "expr.h"
+#include "vmod.h"
+#include "action.h"
+#include "keycodes.h"
+#include "misc.h"
+#include "alias.h"
+
+extern Atom tok_ONE_LEVEL;
+extern Atom tok_TWO_LEVEL;
+extern Atom tok_KEYPAD;
+
+/***====================================================================***/
+
+#define RepeatYes 1
+#define RepeatNo 0
+#define RepeatUndefined ~((unsigned)0)
+
+#define _Key_Syms (1<<0)
+#define _Key_Acts (1<<1)
+#define _Key_Repeat (1<<2)
+#define _Key_Behavior (1<<3)
+#define _Key_Type_Dflt (1<<4)
+#define _Key_Types (1<<5)
+#define _Key_GroupInfo (1<<6)
+#define _Key_VModMap (1<<7)
+
+typedef struct _KeyInfo {
+ CommonInfo defs;
+ unsigned long name;
+ unsigned char groupInfo;
+ unsigned char typesDefined;
+ unsigned char symsDefined;
+ unsigned char actsDefined;
+ short numLevels[XkbNumKbdGroups];
+ KeySym * syms[XkbNumKbdGroups];
+ XkbAction * acts[XkbNumKbdGroups];
+ Atom types[XkbNumKbdGroups];
+ unsigned repeat;
+ XkbBehavior behavior;
+ unsigned short vmodmap;
+ unsigned long nameForOverlayKey;
+ unsigned long allowNone;
+ Atom dfltType;
+} KeyInfo;
+
+static void
+#if NeedFunctionPrototypes
+InitKeyInfo(KeyInfo *info)
+#else
+InitKeyInfo(info)
+ KeyInfo * info;
+#endif
+{
+register int i;
+static char dflt[4]= "*";
+
+ info->defs.defined= 0;
+ info->defs.fileID= 0;
+ info->defs.merge= MergeOverride;
+ info->defs.next= NULL;
+ info->name= KeyNameToLong(dflt);
+ info->groupInfo= 0;
+ info->typesDefined= info->symsDefined= info->actsDefined= 0;
+ for (i=0;i<XkbNumKbdGroups;i++) {
+ info->numLevels[i]= 0;
+ info->types[i]= None;
+ info->syms[i]= NULL;
+ info->acts[i]= NULL;
+ }
+ info->dfltType= None;
+ info->behavior.type= XkbKB_Default;
+ info->behavior.data= 0;
+ info->vmodmap= 0;
+ info->nameForOverlayKey= 0;
+ info->repeat= RepeatUndefined;
+ info->allowNone= 0;
+ return;
+}
+
+static void
+#if NeedFunctionPrototypes
+FreeKeyInfo(KeyInfo *info)
+#else
+FreeKeyInfo(info)
+ KeyInfo * info;
+#endif
+{
+register int i;
+
+ info->defs.defined= 0;
+ info->defs.fileID= 0;
+ info->defs.merge= MergeOverride;
+ info->defs.next= NULL;
+ info->groupInfo= 0;
+ info->typesDefined= info->symsDefined= info->actsDefined= 0;
+ for (i=0;i<XkbNumKbdGroups;i++) {
+ info->numLevels[i]= 0;
+ info->types[i]= None;
+ if (info->syms[i]!=NULL)
+ uFree(info->syms[i]);
+ info->syms[i]= NULL;
+ if (info->acts[i]!=NULL)
+ uFree(info->acts[i]);
+ info->acts[i]= NULL;
+ }
+ info->dfltType= None;
+ info->behavior.type= XkbKB_Default;
+ info->behavior.data= 0;
+ info->vmodmap= 0;
+ info->nameForOverlayKey= 0;
+ info->repeat= RepeatUndefined;
+ return;
+}
+
+static Bool
+#if NeedFunctionPrototypes
+CopyKeyInfo(KeyInfo *old,KeyInfo *new,Bool clearOld)
+#else
+CopyKeyInfo(old,new,clearOld)
+ KeyInfo * old;
+ KeyInfo * new;
+ Bool clearOld;
+#endif
+{
+register int i;
+
+ *new= *old;
+ new->defs.next= NULL;
+ if (clearOld) {
+ for (i=0;i<XkbNumKbdGroups;i++) {
+ old->numLevels[i]= 0;
+ old->syms[i]= NULL;
+ old->acts[i]= NULL;
+ }
+ }
+ else {
+ int width;
+ for (i=0;i<XkbNumKbdGroups;i++) {
+ width= new->numLevels[i];
+ if (old->syms[i]!=NULL) {
+ new->syms[i]= uTypedCalloc(width,KeySym);
+ if (!new->syms[i]) {
+ new->syms[i]= NULL;
+ new->numLevels[i]= 0;
+ return False;
+ }
+ memcpy((char *)new->syms[i],(char *)old->syms[i],
+ width*sizeof(KeySym));
+ }
+ if (old->acts[i]!=NULL) {
+ new->acts[i]= uTypedCalloc(width,XkbAction);
+ if (!new->acts[i]) {
+ new->acts[i]= NULL;
+ return False;
+ }
+ memcpy((char *)new->acts[i],(char *)old->acts[i],
+ width*sizeof(XkbAction));
+ }
+ }
+ }
+ return True;
+}
+
+/***====================================================================***/
+
+typedef struct _ModMapEntry {
+ CommonInfo defs;
+ Bool haveSymbol;
+ int modifier;
+ union {
+ unsigned long keyName;
+ KeySym keySym;
+ } u;
+} ModMapEntry;
+
+#define SYMBOLS_INIT_SIZE 110
+#define SYMBOLS_CHUNK 20
+typedef struct _SymbolsInfo {
+ char * name;
+ int errorCount;
+ unsigned fileID;
+ unsigned merge;
+ unsigned groupInfo;
+ unsigned szKeys;
+ unsigned nKeys;
+ KeyInfo * keys;
+ KeyInfo dflt;
+ VModInfo vmods;
+ ActionInfo * action;
+ Atom groupNames[XkbNumKbdGroups];
+
+ ModMapEntry * modMap;
+ AliasInfo * aliases;
+} SymbolsInfo;
+
+static void
+#if NeedFunctionPrototypes
+InitSymbolsInfo(SymbolsInfo *info,XkbDescPtr xkb)
+#else
+InitSymbolsInfo(info,xkb)
+ SymbolsInfo * info;
+ XkbDescPtr xkb;
+#endif
+{
+register int i;
+
+ tok_ONE_LEVEL= XkbInternAtom(NULL,"ONE_LEVEL",False);
+ tok_TWO_LEVEL= XkbInternAtom(NULL,"TWO_LEVEL",False);
+ tok_KEYPAD= XkbInternAtom(NULL,"KEYPAD",False);
+ info->name= NULL;
+ info->errorCount= 0;
+ info->fileID= 0;
+ info->merge= MergeOverride;
+ info->groupInfo= 0;
+ info->szKeys= SYMBOLS_INIT_SIZE;
+ info->nKeys= 0;
+ info->keys= uTypedCalloc(SYMBOLS_INIT_SIZE,KeyInfo);
+ info->modMap= NULL;
+ for (i=0;i<XkbNumKbdGroups;i++)
+ info->groupNames[i]= None;
+ InitKeyInfo(&info->dflt);
+ InitVModInfo(&info->vmods,xkb);
+ info->action= NULL;
+ info->aliases= NULL;
+ return;
+}
+
+static void
+#if NeedFunctionPrototypes
+FreeSymbolsInfo(SymbolsInfo *info)
+#else
+FreeSymbolsInfo(info)
+ SymbolsInfo * info;
+#endif
+{
+register int i;
+
+ if (info->name)
+ uFree(info->name);
+ info->name= NULL;
+ if (info->keys) {
+ for (i=0;i<info->nKeys;i++) {
+ FreeKeyInfo(&info->keys[i]);
+ }
+ uFree(info->keys);
+ info->keys= NULL;
+ }
+ if (info->modMap) {
+ ClearCommonInfo(&info->modMap->defs);
+ info->modMap= NULL;
+ }
+ if (info->aliases) {
+ ClearAliases(&info->aliases);
+ info->aliases= NULL;
+ }
+ bzero((char *)info,sizeof(SymbolsInfo));
+ return;
+}
+
+static Bool
+#if NeedFunctionPrototypes
+ResizeKeyGroup( KeyInfo * key,
+ unsigned group,
+ unsigned atLeastSize,
+ Bool forceActions)
+#else
+ResizeKeyGroup(key,group,atLeastSize,forceActions)
+ KeyInfo * key;
+ unsigned group;
+ unsigned atLeastSize;
+ Bool forceActions;
+#endif
+{
+Bool tooSmall;
+unsigned newWidth;
+
+ tooSmall= (key->numLevels[group]<atLeastSize);
+ if (tooSmall) newWidth= atLeastSize;
+ else newWidth= key->numLevels[group];
+
+ if ((key->syms[group]==NULL)||tooSmall) {
+ key->syms[group]= uTypedRecalloc(key->syms[group],
+ key->numLevels[group],newWidth,
+ KeySym);
+ if (!key->syms[group])
+ return False;
+ }
+ if (((forceActions)&&(tooSmall||(key->acts[group]==NULL)))||
+ (tooSmall&&(key->acts[group]!=NULL))) {
+ key->acts[group]= uTypedRecalloc(key->acts[group],
+ key->numLevels[group],newWidth,
+ XkbAction);
+ if (!key->acts[group])
+ return False;
+ }
+ key->numLevels[group]= newWidth;
+ return True;
+}
+
+static Bool
+#if NeedFunctionPrototypes
+MergeKeyGroups( SymbolsInfo * info,
+ KeyInfo * into,
+ KeyInfo * from,
+ unsigned group)
+#else
+MergeKeyGroups(info,into,from,group)
+ SymbolsInfo * info;
+ KeyInfo * into;
+ KeyInfo * from;
+ unsigned group;
+#endif
+{
+KeySym * resultSyms;
+XkbAction * resultActs;
+int resultWidth;
+register int i;
+Bool report,clobber;
+
+ clobber= (from->defs.merge!=MergeAugment);
+ report= (warningLevel>9)||
+ ((into->defs.fileID==from->defs.fileID)&&(warningLevel>0));
+ if (into->numLevels[group]>=from->numLevels[group]) {
+ resultSyms= into->syms[group];
+ resultActs= into->acts[group];
+ resultWidth= into->numLevels[group];
+ }
+ else {
+ resultSyms= from->syms[group];
+ resultActs= from->acts[group];
+ resultWidth= from->numLevels[group];
+ }
+ if (resultSyms==NULL) {
+ resultSyms= uTypedCalloc(resultWidth,KeySym);
+ if (!resultSyms) {
+ WSGO("Could not allocate symbols for group merge\n");
+ ACTION2("Group %d of key %s not merged\n",group,
+ longText(into->name,XkbMessage));
+ return False;
+ }
+ }
+ if ((resultActs==NULL)&&(into->acts[group]||from->acts[group])) {
+ resultActs= uTypedCalloc(resultWidth,XkbAction);
+ if (!resultActs) {
+ WSGO("Could not allocate actions for group merge\n");
+ ACTION2("Group %d of key %s not merged\n",group,
+ longText(into->name,XkbMessage));
+ return False;
+ }
+ }
+ for (i=0;i<resultWidth;i++) {
+ KeySym fromSym,toSym;
+ if (from->syms[group] && (i<from->numLevels[group]))
+ fromSym= from->syms[group][i];
+ else fromSym= NoSymbol;
+ if (into->syms[group] && (i<into->numLevels[group]))
+ toSym= into->syms[group][i];
+ else toSym= NoSymbol;
+ if ((fromSym==NoSymbol)||(fromSym==toSym))
+ resultSyms[i]= toSym;
+ else if (toSym==NoSymbol)
+ resultSyms[i]= fromSym;
+ else {
+ KeySym use,ignore;
+ if (clobber) { use= fromSym; ignore= toSym; }
+ else { use= toSym; ignore= fromSym; }
+ if (report) {
+ WARN3("Multiple symbols for level %d/group %d on key %s\n",
+ i+1,group+1,longText(into->name,XkbMessage));
+ ACTION2("Using %s, ignoring %s\n",XkbKeysymText(use,XkbMessage),
+ XkbKeysymText(ignore,XkbMessage));
+ }
+ resultSyms[i]= use;
+ }
+ if (resultActs!=NULL) {
+ XkbAction *fromAct,*toAct;
+ fromAct= (from->acts[group]?&from->acts[group][i]:NULL);
+ toAct= (into->acts[group]?&into->acts[group][i]:NULL);
+ if (((fromAct==NULL)||(fromAct->type==XkbSA_NoAction))&&
+ (toAct!=NULL)) {
+ resultActs[i]= *toAct;
+ }
+ else if (((toAct==NULL)||(toAct->type==XkbSA_NoAction))&&
+ (fromAct!=NULL)) {
+ resultActs[i]= *fromAct;
+ }
+ else {
+ XkbAction *use,*ignore;
+ if (clobber) { use= fromAct; ignore= toAct; }
+ else { use= toAct; ignore= fromAct; }
+ if (report) {
+ WARN3("Multiple actions for level %d/group %d on key %s\n",
+ i+1,group+1,longText(into->name,XkbMessage));
+ ACTION2("Using %s, ignoring %s\n",
+ XkbActionTypeText(use->type,XkbMessage),
+ XkbActionTypeText(ignore->type,XkbMessage));
+ }
+ resultActs[i]= *use;
+ }
+ }
+ }
+ if ((into->syms[group]!=NULL)&&(resultSyms!=into->syms[group]))
+ uFree(into->syms[group]);
+ if ((from->syms[group]!=NULL)&&(resultSyms!=from->syms[group]))
+ uFree(from->syms[group]);
+ into->numLevels[group]= resultWidth;
+ into->syms[group]= resultSyms;
+ from->syms[group]= NULL;
+ into->symsDefined|= (1<<group);
+ from->symsDefined&= ~(1<<group);
+ return True;
+}
+
+static Bool
+#if NeedFunctionPrototypes
+MergeKeys(SymbolsInfo *info,KeyInfo *into,KeyInfo *from)
+#else
+MergeKeys(info,into,from)
+ SymbolsInfo * info;
+ KeyInfo * into;
+ KeyInfo * from;
+#endif
+{
+register int i;
+unsigned collide= 0;
+Bool report;
+
+ if (from->defs.merge==MergeReplace) {
+ for (i=0;i<XkbNumKbdGroups;i++) {
+ if (into->numLevels[i]!=0) {
+ if (into->syms[i])
+ uFree(into->syms[i]);
+ if (into->acts[i])
+ uFree(into->acts[i]);
+ }
+ }
+ *into= *from;
+ bzero(from,sizeof(KeyInfo));
+ return True;
+ }
+ report= ((warningLevel>9)||
+ ((into->defs.fileID==from->defs.fileID)&&(warningLevel>0)));
+ for (i=0;i<XkbNumKbdGroups;i++) {
+ if (from->numLevels[i]>0) {
+ if (into->numLevels[i]==0) {
+ into->numLevels[i]= from->numLevels[i];
+ into->syms[i]= from->syms[i];
+ into->acts[i]= from->acts[i];
+ into->symsDefined|= (1<<i);
+ from->syms[i]= NULL;
+ from->acts[i]= NULL;
+ from->numLevels[i]= 0;
+ from->symsDefined&= ~(1<<i);
+ if (into->syms[i]) into->defs.defined|= _Key_Syms;
+ if (into->acts[i]) into->defs.defined|= _Key_Acts;
+ }
+ else {
+ if (report) {
+ if (into->syms[i]) collide|= _Key_Syms;
+ if (into->acts[i]) collide|= _Key_Acts;
+ }
+ MergeKeyGroups(info,into,from,(unsigned)i);
+ }
+ }
+ if (from->types[i]!=None) {
+ if ((into->types[i]!=None)&&(report)&&
+ (into->types[i]!=from->types[i])) {
+ Atom use,ignore;
+ collide|= _Key_Types;
+ if (from->defs.merge!=MergeAugment) {
+ use= from->types[i];
+ ignore= into->types[i];
+ }
+ else {
+ use= into->types[i];
+ ignore= from->types[i];
+ }
+ WARN2("Multiple definitions for group %d type of key %s\n",
+ i,longText(into->name,XkbMessage));
+ ACTION2("Using %s, ignoring %s\n",
+ XkbAtomText(NULL,use,XkbMessage),
+ XkbAtomText(NULL,ignore,XkbMessage));
+ }
+ if ((from->defs.merge!=MergeAugment)||(into->types[i]==None)) {
+ into->types[i]= from->types[i];
+ }
+ }
+ }
+ if (UseNewField(_Key_Behavior,&into->defs,&from->defs,&collide)) {
+ into->behavior= from->behavior;
+ into->nameForOverlayKey= from->nameForOverlayKey;
+ into->defs.defined|= _Key_Behavior;
+ }
+ if (UseNewField(_Key_VModMap,&into->defs,&from->defs,&collide)) {
+ into->vmodmap= from->vmodmap;
+ into->defs.defined|= _Key_VModMap;
+ }
+ if (UseNewField(_Key_Repeat,&into->defs,&from->defs,&collide)) {
+ into->repeat= from->repeat;
+ into->defs.defined|= _Key_Repeat;
+ }
+ if (UseNewField(_Key_Type_Dflt,&into->defs,&from->defs,&collide)) {
+ into->dfltType= from->dfltType;
+ into->defs.defined|= _Key_Type_Dflt;
+ }
+ if (UseNewField(_Key_GroupInfo,&into->defs,&from->defs,&collide)) {
+ into->groupInfo= from->groupInfo;
+ into->defs.defined|= _Key_GroupInfo;
+ }
+ if ( collide ) {
+ WARN1("Symbol map for key %s redefined\n",
+ longText(into->name,XkbMessage));
+ ACTION1("Using %s definition for conflicting fields\n",
+ (from->defs.merge==MergeAugment?"first":"last"));
+ }
+ return True;
+}
+
+static Bool
+#if NeedFunctionPrototypes
+AddKeySymbols(SymbolsInfo *info,KeyInfo *key)
+#else
+AddKeySymbols(info,key)
+ SymbolsInfo * info;
+ KeyInfo * key;
+#endif
+{
+register int i;
+
+ for (i=0;i<info->nKeys;i++) {
+ if (info->keys[i].name==key->name)
+ return MergeKeys(info,&info->keys[i],key);
+ }
+ if (info->nKeys>=info->szKeys) {
+ info->szKeys+= SYMBOLS_CHUNK;
+ info->keys= uTypedRecalloc(info->keys,info->nKeys,info->szKeys,KeyInfo);
+ if (!info->keys) {
+ WSGO("Could not allocate key symbols descriptions\n");
+ ACTION("Some key symbols definitions may be lost\n");
+ return False;
+ }
+ }
+ return CopyKeyInfo(key,&info->keys[info->nKeys++],True);
+}
+
+static Bool
+#if NeedFunctionPrototypes
+AddModMapEntry(SymbolsInfo *info,ModMapEntry *new)
+#else
+AddModMapEntry(info,new)
+ SymbolsInfo * info;
+ ModMapEntry * new;
+#endif
+{
+ModMapEntry * mm;
+Bool clobber;
+
+ clobber= (new->defs.merge!=MergeAugment);
+ for (mm=info->modMap;mm!=NULL;mm= (ModMapEntry *)mm->defs.next) {
+ if (new->haveSymbol&&mm->haveSymbol&&(new->u.keySym==mm->u.keySym)) {
+ unsigned use,ignore;
+ if (mm->modifier!=new->modifier) {
+ if (clobber) {
+ use= new->modifier;
+ ignore= mm->modifier;
+ }
+ else {
+ use= mm->modifier;
+ ignore= new->modifier;
+ }
+ ERROR1("%s added to symbol map for multiple modifiers\n",
+ XkbKeysymText(new->u.keySym,XkbMessage));
+ ACTION2("Using %s, ignoring %s.\n",
+ XkbModIndexText(use,XkbMessage),
+ XkbModIndexText(ignore,XkbMessage));
+ mm->modifier= use;
+ }
+ return True;
+ }
+ if ((!new->haveSymbol)&&(!mm->haveSymbol)&&
+ (new->u.keyName==mm->u.keyName)) {
+ unsigned use,ignore;
+ if (mm->modifier!=new->modifier) {
+ if (clobber) {
+ use= new->modifier;
+ ignore= mm->modifier;
+ }
+ else {
+ use= mm->modifier;
+ ignore= new->modifier;
+ }
+ ERROR1("Key %s added to map for multiple modifiers\n",
+ longText(new->u.keyName,XkbMessage));
+ ACTION2("Using %s, ignoring %s.\n",
+ XkbModIndexText(use,XkbMessage),
+ XkbModIndexText(ignore,XkbMessage));
+ mm->modifier= use;
+ }
+ return True;
+ }
+ }
+ mm= uTypedAlloc(ModMapEntry);
+ if (mm==NULL) {
+ WSGO("Could not allocate modifier map entry\n");
+ ACTION1("Modifier map for %s will be incomplete\n",
+ XkbModIndexText(new->modifier,XkbMessage));
+ return False;
+ }
+ *mm= *new;
+ mm->defs.next= &info->modMap->defs;
+ info->modMap= mm;
+ return True;
+}
+
+/***====================================================================***/
+
+static void
+#if NeedFunctionPrototypes
+MergeIncludedSymbols(SymbolsInfo *into,SymbolsInfo *from,unsigned merge)
+#else
+MergeIncludedSymbols(into,from,merge)
+ SymbolsInfo * into;
+ SymbolsInfo * from;
+ unsigned merge;
+#endif
+{
+register int i;
+KeyInfo * key;
+
+ if (from->errorCount>0) {
+ into->errorCount+= from->errorCount;
+ return;
+ }
+ if (into->name==NULL) {
+ into->name= from->name;
+ from->name= NULL;
+ }
+ for (i=0;i<XkbNumKbdGroups;i++) {
+ if (from->groupNames[i]!=None) {
+ if ((merge!=MergeAugment)||(into->groupNames[i]==None))
+ into->groupNames[i]= from->groupNames[i];
+ }
+ }
+ for (i=0,key=from->keys;i<from->nKeys;i++,key++) {
+ if (merge!=MergeDefault)
+ key->defs.merge= merge;
+ if (!AddKeySymbols(into,key))
+ into->errorCount++;
+ }
+ if (from->modMap!=NULL) {
+ ModMapEntry *mm,*next;
+ for (mm=from->modMap;mm!=NULL;mm=next) {
+ if (merge!=MergeDefault)
+ mm->defs.merge= merge;
+ if (!AddModMapEntry(into,mm))
+ into->errorCount++;
+ next= (ModMapEntry *)mm->defs.next;
+ uFree(mm);
+ }
+ from->modMap= NULL;
+ }
+ if (!MergeAliases(&into->aliases,&from->aliases,merge))
+ into->errorCount++;
+ return;
+}
+
+typedef void (*FileHandler)(
+#if NeedFunctionPrototypes
+ XkbFile * /* rtrn */,
+ XkbDescPtr /* xkb */,
+ unsigned /* merge */,
+ SymbolsInfo * /* included */
+#endif
+);
+
+static Bool
+#if NeedFunctionPrototypes
+HandleIncludeSymbols( IncludeStmt * stmt,
+ XkbDescPtr xkb,
+ SymbolsInfo * info,
+ FileHandler hndlr)
+#else
+HandleIncludeSymbols(stmt,xkb,info,hndlr)
+ IncludeStmt * stmt;
+ XkbDescPtr xkb;
+ SymbolsInfo * info;
+ void (*hndlr)();
+#endif
+{
+unsigned newMerge;
+XkbFile * rtrn;
+SymbolsInfo included;
+Bool haveSelf;
+
+ haveSelf= False;
+ if ((stmt->file==NULL)&&(stmt->map==NULL)) {
+ haveSelf= True;
+ included= *info;
+ bzero(info,sizeof(SymbolsInfo));
+ }
+ else if (ProcessIncludeFile(stmt,XkmSymbolsIndex,&rtrn,&newMerge)) {
+ InitSymbolsInfo(&included,xkb);
+ included.fileID= included.dflt.defs.fileID= rtrn->id;
+ included.merge= included.dflt.defs.merge= MergeOverride;
+ (*hndlr)(rtrn,xkb,MergeOverride,&included);
+ if (stmt->stmt!=NULL) {
+ if (included.name!=NULL)
+ uFree(included.name);
+ included.name= stmt->stmt;
+ stmt->stmt= NULL;
+ }
+ }
+ else {
+ info->errorCount+= 10;
+ return False;
+ }
+ if ((stmt->next!=NULL)&&(included.errorCount<1)) {
+ IncludeStmt * next;
+ unsigned op;
+ SymbolsInfo next_incl;
+
+ for (next=stmt->next;next!=NULL;next=next->next) {
+ if ((next->file==NULL)&&(next->map==NULL)) {
+ haveSelf= True;
+ MergeIncludedSymbols(&included,info,next->merge);
+ FreeSymbolsInfo(info);
+ }
+ else if (ProcessIncludeFile(next,XkmSymbolsIndex,&rtrn,&op)) {
+ InitSymbolsInfo(&next_incl,xkb);
+ next_incl.fileID= next_incl.dflt.defs.fileID= rtrn->id;
+ next_incl.merge= next_incl.dflt.defs.merge= MergeOverride;
+ (*hndlr)(rtrn,xkb,MergeOverride,&next_incl);
+ MergeIncludedSymbols(&included,&next_incl,op);
+ FreeSymbolsInfo(&next_incl);
+ }
+ else {
+ info->errorCount+= 10;
+ return False;
+ }
+ }
+ }
+ if (haveSelf)
+ *info= included;
+ else {
+ MergeIncludedSymbols(info,&included,newMerge);
+ FreeSymbolsInfo(&included);
+ }
+ return (info->errorCount==0);
+}
+
+static LookupEntry groupNames[]= {
+ { "group1", 1 },
+ { "group2", 2 },
+ { "group3", 3 },
+ { "group4", 4 },
+ { "group5", 5 },
+ { "group6", 6 },
+ { "group7", 7 },
+ { "group8", 8 },
+ { NULL, 0 }
+};
+
+
+#define SYMBOLS 1
+#define ACTIONS 2
+
+static Bool
+#if NeedFunctionPrototypes
+GetGroupIndex( KeyInfo * key,
+ ExprDef * arrayNdx,
+ unsigned what,
+ unsigned * ndx_rtrn)
+#else
+GetGroupIndex(key,arrayNdx,what,ndx_rtrn)
+ KeyInfo * key;
+ ExprDef * arrayNdx;
+ unsigned what;
+ unsigned * ndx_rtrn;
+#endif
+{
+char * name;
+ExprResult tmp;
+
+ if (what==SYMBOLS) name= "symbols";
+ else name= "actions";
+
+ if (arrayNdx==NULL) {
+ register int i;
+ unsigned defined;
+ if (what==SYMBOLS) defined= key->symsDefined;
+ else defined= key->actsDefined;
+
+ for (i=0;i<XkbNumKbdGroups;i++) {
+ if ((defined&(1<<i))==0) {
+ *ndx_rtrn= i;
+ return True;
+ }
+ }
+ ERROR3("Too many groups of %s for key %s (max %d)\n",name,
+ longText(key->name,XkbMessage),
+ XkbNumKbdGroups+1);
+ ACTION1("Ignoring %s defined for extra groups\n",name);
+ return False;
+ }
+ if (!ExprResolveInteger(arrayNdx,&tmp,SimpleLookup,(XPointer)groupNames)) {
+ ERROR2("Illegal group index for %s of key %s\n",name,
+ longText(key->name,XkbMessage));
+ ACTION("Definition with non-integer array index ignored\n");
+ return False;
+ }
+ if ((tmp.uval<1)||(tmp.uval>XkbNumKbdGroups)) {
+ ERROR3("Group index for %s of key %s is out of range (1..%d)\n",name,
+ longText(key->name,XkbMessage),
+ XkbNumKbdGroups+1);
+ ACTION2("Ignoring %s for group %d\n",name,tmp.uval);
+ return False;
+ }
+ *ndx_rtrn= tmp.uval-1;
+ return True;
+}
+
+static Bool
+#if NeedFunctionPrototypes
+AddSymbolsToKey( KeyInfo * key,
+ XkbDescPtr xkb,
+ char * field,
+ ExprDef * arrayNdx,
+ ExprDef * value,
+ SymbolsInfo * info)
+#else
+AddSymbolsToKey(key,xkb,field,arrayNdx,value,info)
+ KeyInfo * key;
+ XkbDescPtr xkb;
+ char * field;
+ ExprDef * arrayNdx;
+ ExprDef * value;
+ SymbolsInfo * info;
+#endif
+{
+unsigned ndx,nSyms;
+int i;
+
+ if (!GetGroupIndex(key,arrayNdx,SYMBOLS,&ndx))
+ return False;
+ if (value==NULL) {
+ key->symsDefined|= (1<<ndx);
+ return True;
+ }
+ if (value->op!=ExprKeysymList) {
+ ERROR1("Expected a list of symbols, found %s\n",exprOpText(value->op));
+ ACTION2("Ignoring symbols for group %d of %s\n",ndx,
+ longText(key->name,XkbMessage));
+ return False;
+ }
+ if (key->syms[ndx]!=NULL) {
+ WSGO2("Symbols for key %s, group %d already defined\n",
+ longText(key->name,XkbMessage),
+ ndx);
+ return False;
+ }
+ nSyms= value->value.list.nSyms;
+ if (((key->numLevels[ndx]<nSyms)||(key->syms[ndx]==NULL))&&
+ (!ResizeKeyGroup(key,ndx,nSyms,False))) {
+ WSGO2("Could not resize group %d of key %s\n",ndx,
+ longText(key->name,XkbMessage));
+ ACTION("Symbols lost\n");
+ return False;
+ }
+ key->symsDefined|= (1<<ndx);
+ memcpy((char *)key->syms[ndx],(char *)value->value.list.syms,
+ nSyms*sizeof(KeySym));
+ uFree(value->value.list.syms);
+ value->value.list.syms= NULL;
+ for (i=key->numLevels[ndx]-1;(i>=0)&&(key->syms[ndx][i]==NoSymbol);i--) {
+ key->numLevels[ndx]--;
+ }
+ return True;
+}
+
+static Bool
+#if NeedFunctionPrototypes
+AddActionsToKey( KeyInfo * key,
+ XkbDescPtr xkb,
+ char * field,
+ ExprDef * arrayNdx,
+ ExprDef * value,
+ SymbolsInfo * info)
+#else
+AddActionsToKey(key,xkb,field,arrayNdx,value,info)
+ KeyInfo * key;
+ XkbDescPtr xkb;
+ char * field;
+ ExprDef * arrayNdx;
+ ExprDef * value;
+ SymbolsInfo * info;
+#endif
+{
+register int i;
+unsigned ndx,nActs;
+ExprDef * act;
+XkbAnyAction * toAct;
+
+ if (!GetGroupIndex(key,arrayNdx,ACTIONS,&ndx))
+ return False;
+
+ if (value==NULL) {
+ key->actsDefined|= (1<<ndx);
+ return True;
+ }
+ if (value->op!=ExprActionList) {
+ WSGO1("Bad expression type (%d) for action list value\n",value->op);
+ ACTION2("Ignoring actions for group %d of %s\n",ndx,
+ longText(key->name,XkbMessage));
+ return False;
+ }
+ if (key->acts[ndx]!=NULL) {
+ WSGO2("Actions for key %s, group %d already defined\n",
+ longText(key->name,XkbMessage),
+ ndx);
+ return False;
+ }
+ for (nActs=0,act= value->value.child;act!=NULL;nActs++) {
+ act= (ExprDef *)act->common.next;
+ }
+ if (nActs<1) {
+ WSGO("Action list but not actions in AddActionsToKey\n");
+ return False;
+ }
+ if (((key->numLevels[ndx]<nActs)||(key->acts[ndx]==NULL))&&
+ (!ResizeKeyGroup(key,ndx,nActs,True))) {
+ WSGO2("Could not resize group %d of key %s\n",ndx,
+ longText(key->name,XkbMessage));
+ ACTION("Actions lost\n");
+ return False;
+ }
+ key->actsDefined|= (1<<ndx);
+
+ toAct= (XkbAnyAction *)key->acts[ndx];
+ act= value->value.child;
+ for (i=0;i<nActs;i++,toAct++) {
+ if (!HandleActionDef(act,xkb,toAct,MergeOverride,info->action)) {
+ ERROR1("Illegal action definition for %s\n",
+ longText(key->name,XkbMessage));
+ ACTION2("Action for group %d/level %d ignored\n",ndx+1,i+1);
+ }
+ act= (ExprDef *)act->common.next;
+ }
+ return True;
+}
+
+static int
+#if NeedFunctionPrototypes
+SetAllowNone(KeyInfo *key,ExprDef *arrayNdx,ExprDef *value)
+#else
+SetAllowNone(key,arrayNdx,value)
+ KeyInfo * key;
+ ExprDef * arrayNdx;
+ ExprDef * value;
+#endif
+{
+ExprResult tmp;
+unsigned radio_groups= 0;
+
+ if (arrayNdx==NULL) {
+ radio_groups= XkbAllRadioGroupsMask;
+ }
+ else {
+ if (!ExprResolveInteger(arrayNdx,&tmp,RadioLookup,NULL)){
+ ERROR("Illegal index in group name definition\n");
+ ACTION("Definition with non-integer array index ignored\n");
+ return False;
+ }
+ if ((tmp.uval<1)||(tmp.uval>XkbMaxRadioGroups)) {
+ ERROR1("Illegal radio group specified (must be 1..%d)\n",
+ XkbMaxRadioGroups+1);
+ ACTION1("Value of \"allow none\" for group %d ignored\n",tmp.uval);
+ return False;
+ }
+ radio_groups|= (1<<(tmp.uval-1));
+ }
+ if (!ExprResolveBoolean(value,&tmp,NULL,NULL)) {
+ ERROR1("Illegal \"allow none\" value for %s\n",
+ longText(key->name,XkbMessage));
+ ACTION("Non-boolean value ignored\n");
+ return False;
+ }
+ if (tmp.uval) key->allowNone|= radio_groups;
+ else key->allowNone&= ~radio_groups;
+ return True;
+}
+
+
+static LookupEntry lockingEntries[] = {
+ { "true", XkbKB_Lock },
+ { "yes", XkbKB_Lock },
+ { "on", XkbKB_Lock },
+ { "false", XkbKB_Default },
+ { "no", XkbKB_Default },
+ { "off", XkbKB_Default },
+ { "permanent", XkbKB_Lock|XkbKB_Permanent },
+ { NULL, 0 }
+};
+
+static LookupEntry repeatEntries[]= {
+ { "true", RepeatYes },
+ { "yes", RepeatYes },
+ { "on", RepeatYes },
+ { "false", RepeatNo },
+ { "no", RepeatNo },
+ { "off", RepeatNo },
+ { "default", RepeatUndefined },
+ { NULL, 0 }
+};
+
+static LookupEntry rgEntries[]= {
+ { "none", 0 },
+ { NULL, 0 }
+};
+
+static Bool
+#if NeedFunctionPrototypes
+SetSymbolsField( KeyInfo * key,
+ XkbDescPtr xkb,
+ char * field,
+ ExprDef * arrayNdx,
+ ExprDef * value,
+ SymbolsInfo * info)
+#else
+SetSymbolsField(key,xkb,field,arrayNdx,value,info)
+ KeyInfo * key;
+ XkbDescPtr xkb;
+ char * field;
+ ExprDef * arrayNdx;
+ ExprDef * value;
+ SymbolsInfo * info;
+#endif
+{
+Bool ok= True;
+ExprResult tmp;
+
+ if (uStrCaseCmp(field,"type")==0) {
+ ExprResult ndx;
+ if ((!ExprResolveString(value,&tmp,NULL,NULL))&&(warningLevel>0)) {
+ WARN("The type field of a key symbol map must be a string\n");
+ ACTION("Ignoring illegal type definition\n");
+ }
+ if (arrayNdx==NULL) {
+ key->dfltType= XkbInternAtom(NULL,tmp.str,False);
+ key->defs.defined|= _Key_Type_Dflt;
+ }
+ else if (!ExprResolveInteger(arrayNdx,&ndx,SimpleLookup,
+ (XPointer)groupNames)) {
+ ERROR1("Illegal group index for type of key %s\n",
+ longText(key->name,XkbMessage));
+ ACTION("Definition with non-integer array index ignored\n");
+ return False;
+ }
+ else if ((ndx.uval<1)||(ndx.uval>XkbNumKbdGroups)) {
+ ERROR2("Group index for type of key %s is out of range (1..%d)\n",
+ longText(key->name,XkbMessage),
+ XkbNumKbdGroups+1);
+ ACTION1("Ignoring type for group %d\n",ndx.uval);
+ return False;
+ }
+ else {
+ key->types[ndx.uval-1]= XkbInternAtom(NULL,tmp.str,False);
+ key->typesDefined|= (1<<(ndx.uval-1));
+ }
+ }
+ else if (uStrCaseCmp(field,"symbols")==0)
+ return AddSymbolsToKey(key,xkb,field,arrayNdx,value,info);
+ else if (uStrCaseCmp(field,"actions")==0)
+ return AddActionsToKey(key,xkb,field,arrayNdx,value,info);
+ else if ((uStrCaseCmp(field,"vmods")==0)||
+ (uStrCaseCmp(field,"virtualmods")==0)||
+ (uStrCaseCmp(field,"virtualmodifiers")==0)) {
+ ok= ExprResolveModMask(value,&tmp,LookupVModMask,(XPointer)xkb);
+ if (ok) {
+ key->vmodmap= (tmp.uval>>8);
+ key->defs.defined|= _Key_VModMap;
+ }
+ else {
+ ERROR1("Expected a virtual modifier mask, found %s\n",
+ exprOpText(value->op));
+ ACTION1("Ignoring virtual modifiers definition for key %s\n",
+ longText(key->name,XkbMessage));
+ }
+ }
+ else if ((uStrCaseCmp(field,"locking")==0)||(uStrCaseCmp(field,"lock")==0)||
+ (uStrCaseCmp(field,"locks")==0)) {
+ ok= ExprResolveEnum(value,&tmp,lockingEntries);
+ if (ok)
+ key->behavior.type= tmp.uval;
+ key->defs.defined|= _Key_Behavior;
+ }
+ else if ((uStrCaseCmp(field,"radiogroup")==0)||
+ (uStrCaseCmp(field,"permanentradiogroup")==0)) {
+ Bool permanent= False;
+ if (uStrCaseCmp(field,"permanentradiogroup")==0)
+ permanent= True;
+ ok= ExprResolveInteger(value,&tmp,SimpleLookup,(XPointer)rgEntries);
+ if (!ok) {
+ ERROR1("Illegal radio group specification for %s\n",
+ longText(key->name,XkbMessage));
+ ACTION("Non-integer radio group ignored\n");
+ return False;
+ }
+ if (tmp.uval==0) {
+ key->behavior.type= XkbKB_Default;
+ key->behavior.data= 0;
+ return ok;
+ }
+ if ((tmp.uval<1)||(tmp.uval>XkbMaxRadioGroups)) {
+ ERROR1("Radio group specification for %s out of range (1..32)\n",
+ longText(key->name,XkbMessage));
+ ACTION1("Illegal radio group %d ignored\n",tmp.uval);
+ return False;
+ }
+ key->behavior.type= XkbKB_RadioGroup|(permanent?XkbKB_Permanent:0);
+ key->behavior.data= tmp.uval-1;
+ if (key->allowNone&(1<<(tmp.uval-1)))
+ key->behavior.data|= XkbKB_RGAllowNone;
+ key->defs.defined|= _Key_Behavior;
+ }
+ else if (uStrCaseEqual(field,"allownone")) {
+ ok= SetAllowNone(key,arrayNdx,value);
+ }
+ else if (uStrCasePrefix("overlay",field)||
+ uStrCasePrefix("permanentoverlay",field)) {
+ Bool permanent= False;
+ char *which;
+ int overlayNdx;
+ if (uStrCasePrefix("permanent",field)) {
+ permanent= True;
+ which= &field[sizeof("permanentoverlay")-1];
+ }
+ else {
+ which= &field[sizeof("overlay")-1];
+ }
+ if (sscanf(which,"%d",&overlayNdx)==1) {
+ if (((overlayNdx<1)||(overlayNdx>2))&&(warningLevel>0)) {
+ ERROR2("Illegal overlay %d specified for %s\n",
+ overlayNdx,
+ longText(key->name,XkbMessage));
+ ACTION("Ignored\n");
+ return False;
+ }
+ }
+ else if (*which=='\0')
+ overlayNdx=1;
+ else if (warningLevel>0) {
+ ERROR2("Illegal overlay \"%s\" specified for %s\n",
+ which,
+ longText(key->name,XkbMessage));
+ ACTION("Ignored\n");
+ return False;
+ }
+ ok= ExprResolveKeyName(value,&tmp,NULL,NULL);
+ if (!ok) {
+ ERROR1("Illegal overlay key specification for %s\n",
+ longText(key->name,XkbMessage));
+ ACTION("Overlay key must be specified by name\n");
+ return False;
+ }
+ if (overlayNdx==1) key->behavior.type= XkbKB_Overlay1;
+ else key->behavior.type= XkbKB_Overlay2;
+ if (permanent)
+ key->behavior.type|= XkbKB_Permanent;
+
+ key->behavior.data= 0;
+ key->nameForOverlayKey= KeyNameToLong(tmp.keyName.name);
+ key->defs.defined|= _Key_Behavior;
+ }
+ else if ((uStrCaseCmp(field,"repeating")==0)||
+ (uStrCaseCmp(field,"repeats")==0)||
+ (uStrCaseCmp(field,"repeat")==0)){
+ ok= ExprResolveEnum(value,&tmp,repeatEntries);
+ if (!ok) {
+ ERROR1("Illegal repeat setting for %s\n",
+ longText(key->name,XkbMessage));
+ ACTION("Non-boolean repeat setting ignored\n");
+ return False;
+ }
+ key->repeat= tmp.uval;
+ key->defs.defined|= _Key_Repeat;
+ }
+ else if ((uStrCaseCmp(field,"groupswrap")==0)||
+ (uStrCaseCmp(field,"wrapgroups")==0)) {
+ ok= ExprResolveBoolean(value,&tmp,NULL,NULL);
+ if (!ok) {
+ ERROR1("Illegal groupsWrap setting for %s\n",
+ longText(key->name,XkbMessage));
+ ACTION("Non-boolean value ignored\n");
+ return False;
+ }
+ if (tmp.uval) key->groupInfo= XkbWrapIntoRange;
+ else key->groupInfo= XkbClampIntoRange;
+ key->defs.defined|= _Key_GroupInfo;
+ }
+ else if ((uStrCaseCmp(field,"groupsclamp")==0)||
+ (uStrCaseCmp(field,"clampgroups")==0)) {
+ ok= ExprResolveBoolean(value,&tmp,NULL,NULL);
+ if (!ok) {
+ ERROR1("Illegal groupsClamp setting for %s\n",
+ longText(key->name,XkbMessage));
+ ACTION("Non-boolean value ignored\n");
+ return False;
+ }
+ if (tmp.uval) key->groupInfo= XkbClampIntoRange;
+ else key->groupInfo= XkbWrapIntoRange;
+ key->defs.defined|= _Key_GroupInfo;
+ }
+ else if ((uStrCaseCmp(field,"groupsredirect")==0)||
+ (uStrCaseCmp(field,"redirectgroups")==0)) {
+ if (!ExprResolveInteger(value,&tmp,SimpleLookup,(XPointer)groupNames)) {
+ ERROR1("Illegal group index for redirect of key %s\n",
+ longText(key->name,XkbMessage));
+ ACTION("Definition with non-integer group ignored\n");
+ return False;
+ }
+ if ((tmp.uval<1)||(tmp.uval>XkbNumKbdGroups)) {
+ ERROR2("Out-of-range (1..%d) group for redirect of key %s\n",
+ XkbNumKbdGroups,
+ longText(key->name,XkbMessage));
+ ERROR1("Ignoring illegal group %d\n",tmp.uval);
+ return False;
+ }
+ key->groupInfo= XkbSetGroupInfo(0,XkbRedirectIntoRange,tmp.uval-1);
+ key->defs.defined|= _Key_GroupInfo;
+ }
+ else {
+ ERROR1("Unknown field %s in a symbol interpretation\n",field);
+ ACTION("Definition ignored\n");
+ ok= False;
+ }
+ return ok;
+}
+
+static int
+#if NeedFunctionPrototypes
+SetGroupName(SymbolsInfo *info,ExprDef *arrayNdx,ExprDef *value)
+#else
+SetGroupName(info,arrayNdx,value)
+ SymbolsInfo * info;
+ ExprDef * arrayNdx;
+ ExprDef * value;
+#endif
+{
+ExprResult tmp,name;
+
+ if ((arrayNdx==NULL)&&(warningLevel>0)) {
+ WARN("You must specify an index when specifying a group name\n");
+ ACTION("Group name definition without array subscript ignored\n");
+ return False;
+ }
+ if (!ExprResolveInteger(arrayNdx,&tmp,SimpleLookup,(XPointer)groupNames)) {
+ ERROR("Illegal index in group name definition\n");
+ ACTION("Definition with non-integer array index ignored\n");
+ return False;
+ }
+ if ((tmp.uval<1)||(tmp.uval>XkbNumKbdGroups)) {
+ ERROR1("Attempt to specify name for illegal group (must be 1..%d)\n",
+ XkbNumKbdGroups+1);
+ ACTION1("Name for group %d ignored\n",tmp.uval);
+ return False;
+ }
+ if (!ExprResolveString(value,&name,NULL,NULL)) {
+ ERROR("Group name must be a string\n");
+ ACTION1("Illegal name for group %d ignored\n",tmp.uval);
+ return False;
+ }
+ info->groupNames[tmp.uval-1]= XkbInternAtom(NULL,name.str,False);
+ return True;
+}
+
+static int
+#if NeedFunctionPrototypes
+HandleSymbolsVar(VarDef *stmt,XkbDescPtr xkb,SymbolsInfo *info)
+#else
+HandleSymbolsVar(stmt,xkb,info)
+ VarDef * stmt;
+ XkbDescPtr xkb;
+ SymbolsInfo * info;
+#endif
+{
+ExprResult elem,field,tmp;
+ExprDef * arrayNdx;
+
+ if (ExprResolveLhs(stmt->name,&elem,&field,&arrayNdx)==0)
+ return 0; /* internal error, already reported */
+ if (elem.str&&(uStrCaseCmp(elem.str,"key")==0)) {
+ return SetSymbolsField(&info->dflt,xkb,field.str,arrayNdx,stmt->value,
+ info);
+ }
+ else if ((elem.str==NULL)&&((uStrCaseCmp(field.str,"name")==0)||
+ (uStrCaseCmp(field.str,"groupname")==0))) {
+ return SetGroupName(info,arrayNdx,stmt->value);
+ }
+ else if ((elem.str==NULL)&&((uStrCaseCmp(field.str,"groupswrap")==0)||
+ (uStrCaseCmp(field.str,"wrapgroups")==0))) {
+ if (!ExprResolveBoolean(stmt->value,&tmp,NULL,NULL)) {
+ ERROR("Illegal setting for global groupsWrap\n");
+ ACTION("Non-boolean value ignored\n");
+ return False;
+ }
+ if (tmp.uval) info->groupInfo= XkbWrapIntoRange;
+ else info->groupInfo= XkbClampIntoRange;
+ return True;
+ }
+ else if ((elem.str==NULL)&&((uStrCaseCmp(field.str,"groupsclamp")==0)||
+ (uStrCaseCmp(field.str,"clampgroups")==0))) {
+ if (!ExprResolveBoolean(stmt->value,&tmp,NULL,NULL)) {
+ ERROR("Illegal setting for global groupsClamp\n");
+ ACTION("Non-boolean value ignored\n");
+ return False;
+ }
+ if (tmp.uval) info->groupInfo= XkbClampIntoRange;
+ else info->groupInfo= XkbWrapIntoRange;
+ return True;
+ }
+ else if ((elem.str==NULL)&&((uStrCaseCmp(field.str,"groupsredirect")==0)||
+ (uStrCaseCmp(field.str,"redirectgroups")==0))) {
+ if (!ExprResolveInteger(stmt->value,&tmp,
+ SimpleLookup,(XPointer)groupNames)) {
+ ERROR("Illegal group index for global groupsRedirect\n");
+ ACTION("Definition with non-integer group ignored\n");
+ return False;
+ }
+ if ((tmp.uval<1)||(tmp.uval>XkbNumKbdGroups)) {
+ ERROR1("Out-of-range (1..%d) group for global groupsRedirect\n",
+ XkbNumKbdGroups);
+ ACTION1("Ignoring illegal group %d\n",tmp.uval);
+ return False;
+ }
+ info->groupInfo= XkbSetGroupInfo(0,XkbRedirectIntoRange,tmp.uval);
+ return True;
+ }
+ else if ((elem.str==NULL)&&(uStrCaseCmp(field.str,"allownone")==0)) {
+ return SetAllowNone(&info->dflt,arrayNdx,stmt->value);
+ }
+ return SetActionField(xkb,elem.str,field.str,arrayNdx,stmt->value,
+ &info->action);
+}
+
+static Bool
+#if NeedFunctionPrototypes
+HandleSymbolsBody( VarDef * def,
+ XkbDescPtr xkb,
+ KeyInfo * key,
+ SymbolsInfo * info)
+#else
+HandleSymbolsBody(def,xkb,key,info)
+ VarDef * def;
+ XkbDescPtr xkb;
+ KeyInfo * key;
+ SymbolsInfo * info;
+#endif
+{
+Bool ok= True;
+ExprResult tmp,field;
+ExprDef * arrayNdx;
+
+ for (;def!=NULL;def= (VarDef *)def->common.next) {
+ if ((def->name)&&(def->name->type==ExprFieldRef)) {
+ ok= HandleSymbolsVar(def,xkb,info);
+ continue;
+ }
+ else {
+ if (def->name==NULL) {
+ if ((def->value==NULL)||(def->value->op==ExprKeysymList))
+ field.str= "symbols";
+ else field.str= "actions";
+ arrayNdx= NULL;
+ }
+ else {
+ ok= ExprResolveLhs(def->name,&tmp,&field,&arrayNdx);
+ }
+ if (ok)
+ ok= SetSymbolsField(key,xkb,field.str,arrayNdx,def->value,info);
+ }
+ }
+ return ok;
+}
+
+static int
+#if NeedFunctionPrototypes
+HandleSymbolsDef( SymbolsDef * stmt,
+ XkbDescPtr xkb,
+ unsigned merge,
+ SymbolsInfo * info)
+#else
+HandleSymbolsDef(stmt,xkb,merge,info)
+ SymbolsDef * stmt;
+ XkbDescPtr xkb;
+ unsigned merge;
+ SymbolsInfo * info;
+#endif
+{
+KeyInfo key;
+
+ InitKeyInfo(&key);
+ CopyKeyInfo(&info->dflt,&key,False);
+ key.defs.merge= stmt->merge;
+ key.name= KeyNameToLong(stmt->keyName);
+ if (!HandleSymbolsBody((VarDef *)stmt->symbols,xkb,&key,info)) {
+ info->errorCount++;
+ return False;
+ }
+
+ if (!AddKeySymbols(info,&key)) {
+ info->errorCount++;
+ return False;
+ }
+ return True;
+}
+
+static Bool
+#if NeedFunctionPrototypes
+HandleModMapDef( ModMapDef * def,
+ XkbDescPtr xkb,
+ unsigned merge,
+ SymbolsInfo * info)
+#else
+HandleModMapDef(def,xkb,merge,info)
+ ModMapDef * def;
+ XkbDescPtr xkb;
+ unsigned merge;
+ SymbolsInfo * info;
+#endif
+{
+ExprDef * key;
+ModMapEntry tmp;
+ExprResult rtrn;
+Bool ok;
+
+ if (!LookupModIndex(NULL,None,def->modifier,TypeInt,&rtrn)) {
+ ERROR("Illegal modifier map definition\n");
+ ACTION1("Ignoring map for non-modifier \"%s\"\n",
+ XkbAtomText(NULL,def->modifier,XkbMessage));
+ return False;
+ }
+ ok= True;
+ tmp.modifier= rtrn.uval;
+ for (key=def->keys;key!=NULL;key=(ExprDef *)key->common.next) {
+ if ((key->op==ExprValue)&&(key->type==TypeKeyName)) {
+ tmp.haveSymbol= False;
+ tmp.u.keyName= KeyNameToLong(key->value.keyName);
+ }
+ else if (ExprResolveKeySym(key,&rtrn,NULL,NULL)) {
+ tmp.haveSymbol= True;
+ tmp.u.keySym= rtrn.uval;
+ }
+ else {
+ ERROR("Modmap entries may contain only key names or keysyms\n");
+ ACTION1("Illegal definition for %s modifier ignored\n",
+ XkbModIndexText(tmp.modifier,XkbMessage));
+ continue;
+ }
+
+ ok= AddModMapEntry(info,&tmp)&&ok;
+ }
+ return ok;
+}
+
+static void
+#if NeedFunctionPrototypes
+HandleSymbolsFile( XkbFile * file,
+ XkbDescPtr xkb,
+ unsigned merge,
+ SymbolsInfo * info)
+#else
+HandleSymbolsFile(file,xkb,merge,info)
+ XkbFile * file;
+ XkbDescPtr xkb;
+ unsigned merge;
+ SymbolsInfo * info;
+#endif
+{
+ParseCommon *stmt;
+
+ info->name= file->name;
+ stmt= file->defs;
+ while (stmt) {
+ switch (stmt->stmtType) {
+ case StmtInclude:
+ if (!HandleIncludeSymbols((IncludeStmt *)stmt,xkb,info,
+ HandleSymbolsFile))
+ info->errorCount++;
+ break;
+ case StmtSymbolsDef:
+ if (!HandleSymbolsDef((SymbolsDef *)stmt,xkb,merge,info))
+ info->errorCount++;
+ break;
+ case StmtVarDef:
+ if (!HandleSymbolsVar((VarDef *)stmt,xkb,info))
+ info->errorCount++;
+ break;
+ case StmtVModDef:
+ if (!HandleVModDef((VModDef *)stmt,merge,&info->vmods))
+ info->errorCount++;
+ break;
+ case StmtInterpDef:
+ ERROR("Interpretation files may not include other types\n");
+ ACTION("Ignoring definition of symbol interpretation\n");
+ info->errorCount++;
+ break;
+ case StmtKeycodeDef:
+ ERROR("Interpretation files may not include other types\n");
+ ACTION("Ignoring definition of key name\n");
+ info->errorCount++;
+ break;
+ case StmtModMapDef:
+ if (!HandleModMapDef((ModMapDef *)stmt,xkb,merge,info))
+ info->errorCount++;
+ break;
+ default:
+ WSGO1("Unexpected statement type %d in HandleSymbolsFile\n",
+ stmt->stmtType);
+ break;
+ }
+ stmt= stmt->next;
+ if (info->errorCount>10) {
+#ifdef NOISY
+ ERROR("Too many errors\n");
+#endif
+ ACTION1("Abandoning symbols file \"%s\"\n",file->topName);
+ break;
+ }
+ }
+ return;
+}
+
+static Bool
+#if NeedFunctionPrototypes
+FindKeyForSymbol(XkbDescPtr xkb,KeySym sym,unsigned int *kc_rtrn)
+#else
+FindKeyForSymbol(xkb,sym,kc_rtrn)
+ XkbDescPtr xkb;
+ KeySym sym;
+ unsigned int * kc_rtrn;
+#endif
+{
+register int i, j;
+register Bool gotOne;
+
+ j= 0;
+ do {
+ gotOne= False;
+ for (i = xkb->min_key_code; i <= (int)xkb->max_key_code; i++) {
+ if ( j<(int)XkbKeyNumSyms(xkb,i) ) {
+ gotOne = True;
+ if ((XkbKeySym(xkb,i,j)==sym)) {
+ *kc_rtrn= i;
+ return True;
+ }
+ }
+ }
+ j++;
+ } while (gotOne);
+ return False;
+}
+
+static Bool
+#if NeedFunctionPrototypes
+FindNamedType(XkbDescPtr xkb,Atom name,unsigned *type_rtrn)
+#else
+FindNamedType(xkb,name,type_rtrn)
+ XkbDescPtr xkb;
+ Atom name;
+ unsigned * type_rtrn;
+#endif
+{
+register unsigned n;
+
+ if (xkb&&xkb->map&&xkb->map->types) {
+ for (n=0;n<xkb->map->num_types;n++) {
+ if (xkb->map->types[n].name==(Atom)name) {
+ *type_rtrn= n;
+ return True;
+ }
+ }
+ }
+ return False;
+}
+
+static Bool
+#if NeedFunctionPrototypes
+FindAutomaticType(int width,KeySym *syms,Atom *typeNameRtrn)
+#else
+FindAutomaticType(width,syms,typeNameRtrn)
+ int width;
+ KeySym * syms;
+ Atom * typeNameRtrn;
+#endif
+{
+ if ((width==1)||(width==0))
+ *typeNameRtrn= XkbInternAtom(NULL,"ONE_LEVEL",False);
+ else if ( syms && XkbKSIsLower(syms[0]) && XkbKSIsUpper(syms[1]) )
+ *typeNameRtrn= XkbInternAtom(NULL,"ALPHABETIC",False);
+ else if ( syms && (XkbKSIsKeypad(syms[0]) || XkbKSIsKeypad(syms[1])) )
+ *typeNameRtrn= XkbInternAtom(NULL,"KEYPAD",False);
+ else *typeNameRtrn= XkbInternAtom(NULL,"TWO_LEVEL",False);
+ return ((width>=0)&&(width<=2));
+}
+
+static Bool
+#if NeedFunctionPrototypes
+CopySymbolsDef(XkbFileInfo *result,KeyInfo *key,int start_from)
+#else
+CopySymbolsDef(result,key,start_from)
+ XkbFileInfo * result;
+ KeyInfo * key;
+ int start_from;
+#endif
+{
+register int i;
+unsigned okc,kc,width,tmp,nGroups;
+XkbKeyTypePtr type;
+Bool haveActions,autoType,useAlias;
+KeySym * outSyms;
+XkbAction * outActs;
+XkbDescPtr xkb;
+unsigned types[XkbNumKbdGroups];
+
+ xkb= result->xkb;
+ useAlias= (start_from==0);
+ if (!FindNamedKey(xkb,key->name,&kc,useAlias,CreateKeyNames(xkb),
+ start_from)) {
+ if ((start_from==0)&&(warningLevel>=5)) {
+ WARN2("Key %s not found in %s keycodes\n",
+ longText(key->name,XkbMessage),
+ XkbAtomText(NULL,xkb->names->keycodes,XkbMessage));
+ ACTION("Symbols ignored\n");
+ }
+ return False;
+ }
+
+ haveActions= False;
+ for (i=width=nGroups=0;i<XkbNumKbdGroups;i++) {
+ if (((i+1)>nGroups)&&(((key->symsDefined|key->actsDefined)&(1<<i))||
+ (key->typesDefined)&(1<<i)))
+ nGroups= i+1;
+ if (key->acts[i])
+ haveActions= True;
+ autoType= False;
+ if (key->types[i]==None) {
+ if (key->dfltType!=None)
+ key->types[i]= key->dfltType;
+ else if (FindAutomaticType(key->numLevels[i],key->syms[i],
+ &key->types[i])) {
+ autoType= True;
+ }
+ else {
+ if (warningLevel>=5) {
+ WARN1("No automatic type for %d symbols\n",
+ (unsigned int)key->numLevels[i]);
+ ACTION3("Using %s for the %s key (keycode %d)\n",
+ XkbAtomText(NULL,key->types[i],XkbMessage),
+ longText(key->name,XkbMessage),kc);
+ }
+ }
+ }
+ if (FindNamedType(xkb,key->types[i],&types[i])) {
+ if (!autoType)
+ xkb->server->explicit[kc]|= (1<<i);
+ }
+ else {
+ if (warningLevel>=3) {
+ WARN1("Type \"%s\" is not defined\n",
+ XkbAtomText(NULL,key->types[i],XkbMessage));
+ ACTION2("Using TWO_LEVEL for the %s key (keycode %d)\n",
+ longText(key->name,XkbMessage),kc);
+ }
+ types[i]= XkbTwoLevelIndex;
+ }
+ type= &xkb->map->types[types[i]];
+ if (type->num_levels<key->numLevels[i]) {
+ if (warningLevel>0) {
+ WARN4("Type \"%s\" has %d levels, but %s has %d symbols\n",
+ XkbAtomText(NULL,type->name,XkbMessage),
+ (unsigned int)type->num_levels,
+ longText(key->name,XkbMessage),
+ (unsigned int)key->numLevels[i]);
+ ACTION("Ignoring extra symbols\n");
+ }
+ key->numLevels[i]= type->num_levels;
+ }
+ if (key->numLevels[i]>width)
+ width= key->numLevels[i];
+ if (type->num_levels>width)
+ width= type->num_levels;
+ }
+
+ i= width*nGroups;
+ outSyms= XkbResizeKeySyms(xkb,kc,i);
+ if (outSyms==NULL) {
+ WSGO2("Could not enlarge symbols for %s (keycode %d)\n",
+ longText(key->name,XkbMessage),kc);
+ return False;
+ }
+ if (haveActions) {
+ outActs= XkbResizeKeyActions(xkb,kc,i);
+ if (outActs==NULL) {
+ WSGO2("Could not enlarge actions for %s (key %d)\n",
+ longText(key->name,XkbMessage),kc);
+ return False;
+ }
+ xkb->server->explicit[kc]|= XkbExplicitInterpretMask;
+ }
+ else outActs= NULL;
+ if (key->defs.defined&_Key_GroupInfo)
+ i= key->groupInfo;
+ else i= xkb->map->key_sym_map[kc].group_info;
+ xkb->map->key_sym_map[kc].group_info= XkbSetNumGroups(i,nGroups);
+ xkb->map->key_sym_map[kc].width= width;
+ for (i=0;i<nGroups;i++) {
+ xkb->map->key_sym_map[kc].kt_index[i]= types[i];
+ if (key->syms[i]!=NULL) {
+ for (tmp=0;tmp<width;tmp++) {
+ if (tmp<key->numLevels[i])
+ outSyms[tmp]= key->syms[i][tmp];
+ else outSyms[tmp]= NoSymbol;
+ if ((outActs!=NULL)&&(key->acts[i]!=NULL)) {
+ if (tmp<key->numLevels[i])
+ outActs[tmp]= key->acts[i][tmp];
+ else outActs[tmp].type= XkbSA_NoAction;
+ }
+ }
+ }
+ outSyms+= width;
+ if (outActs)
+ outActs+= width;
+ }
+ switch (key->behavior.type&XkbKB_OpMask) {
+ case XkbKB_Default:
+ break;
+ case XkbKB_Overlay1:
+ case XkbKB_Overlay2:
+ /* find key by name! */
+ if (!FindNamedKey(xkb,key->nameForOverlayKey,&okc,True,
+ CreateKeyNames(xkb),0)) {
+ if (warningLevel>=1) {
+ WARN2("Key %s not found in %s keycodes\n",
+ longText(key->nameForOverlayKey,XkbMessage),
+ XkbAtomText(NULL,xkb->names->keycodes,XkbMessage));
+ ACTION1("Not treating %s as an overlay key \n",
+ longText(key->name,XkbMessage));
+ }
+ break;
+ }
+ key->behavior.data= okc;
+ default:
+ xkb->server->behaviors[kc]= key->behavior;
+ xkb->server->explicit[kc]|= XkbExplicitBehaviorMask;
+ break;
+ }
+ if (key->defs.defined&_Key_VModMap) {
+ xkb->server->vmodmap[kc]= key->vmodmap;
+ xkb->server->explicit[kc]|= XkbExplicitVModMapMask;
+ }
+ if (key->repeat!=RepeatUndefined) {
+ if (key->repeat==RepeatYes)
+ xkb->ctrls->per_key_repeat[kc/8]|= (1<<(kc%8));
+ else xkb->ctrls->per_key_repeat[kc/8]&= ~(1<<(kc%8));
+ xkb->server->explicit[kc]|= XkbExplicitAutoRepeatMask;
+ }
+ CopySymbolsDef(result,key,kc+1);
+ return True;
+}
+
+static Bool
+#if NeedFunctionPrototypes
+CopyModMapDef(XkbFileInfo *result,ModMapEntry *entry)
+#else
+CopyModMapDef(result,entry)
+ XkbFileInfo * result;
+ ModMapEntry * entry;
+#endif
+{
+unsigned kc;
+XkbDescPtr xkb;
+
+ xkb= result->xkb;
+ if ((!entry->haveSymbol)&&(!FindNamedKey(xkb,entry->u.keyName,&kc,True,
+ CreateKeyNames(xkb),0))) {
+ if (warningLevel>=5) {
+ WARN2("Key %s not found in %s keycodes\n",
+ longText(entry->u.keyName,XkbMessage),
+ XkbAtomText(NULL,xkb->names->keycodes,XkbMessage));
+ ACTION1("Modifier map entry for %s not updated\n",
+ XkbModIndexText(entry->modifier,XkbMessage));
+ }
+ return False;
+ }
+ else if (entry->haveSymbol&&(!FindKeyForSymbol(xkb,entry->u.keySym,&kc))) {
+ if (warningLevel>5) {
+ WARN2("Key \"%s\" not found in %s symbol map\n",
+ XkbKeysymText(entry->u.keySym,XkbMessage),
+ XkbAtomText(NULL,xkb->names->symbols,XkbMessage));
+ ACTION1("Modifier map entry for %s not updated\n",
+ XkbModIndexText(entry->modifier,XkbMessage));
+ }
+ return False;
+ }
+ xkb->map->modmap[kc]|= (1<<entry->modifier);
+ return True;
+}
+
+Bool
+#if NeedFunctionPrototypes
+CompileSymbols(XkbFile *file,XkbFileInfo *result,unsigned merge)
+#else
+CompileSymbols(file,result,merge)
+ XkbFile * file;
+ XkbFileInfo * result;
+ unsigned merge;
+#endif
+{
+register int i;
+SymbolsInfo info;
+XkbDescPtr xkb;
+
+ xkb= result->xkb;
+ InitSymbolsInfo(&info,xkb);
+ info.dflt.defs.fileID= file->id;
+ info.dflt.defs.merge= merge;
+ HandleSymbolsFile(file,xkb,merge,&info);
+
+ if (info.errorCount==0) {
+ KeyInfo *key;
+ if (XkbAllocNames(xkb,XkbSymbolsNameMask|XkbGroupNamesMask,0,0)
+ !=Success) {
+ WSGO("Can not allocate names in CompileSymbols\n");
+ ACTION("Symbols not added\n");
+ return False;
+ }
+ if(XkbAllocClientMap(xkb,XkbKeySymsMask|XkbModifierMapMask,0)!=Success){
+ WSGO("Could not allocate client map in CompileSymbols\n");
+ ACTION("Symbols not added\n");
+ return False;
+ }
+ if (XkbAllocServerMap(xkb,XkbAllServerInfoMask,32)!=Success) {
+ WSGO("Could not allocate server map in CompileSymbols\n");
+ ACTION("Symbols not added\n");
+ return False;
+ }
+ if (XkbAllocControls(xkb,XkbPerKeyRepeatMask)!=Success) {
+ WSGO("Could not allocate controls in CompileSymbols\n");
+ ACTION("Symbols not added\n");
+ return False;
+ }
+ xkb->names->symbols= XkbInternAtom(xkb->dpy,info.name,False);
+ if (info.aliases)
+ ApplyAliases(xkb,False,&info.aliases);
+ for (i=0;i<XkbNumKbdGroups;i++) {
+ if (info.groupNames[i]!=None)
+ xkb->names->groups[i]= info.groupNames[i];
+ }
+ for (key=info.keys,i=0;i<info.nKeys;i++,key++) {
+ if (!CopySymbolsDef(result,key,0))
+ info.errorCount++;
+ }
+ if (warningLevel>3) {
+ for (i=xkb->min_key_code;i<=xkb->max_key_code;i++) {
+ if (xkb->names->keys[i].name[0]=='\0')
+ continue;
+ if (XkbKeyNumGroups(xkb,i)<1) {
+ char buf[5];
+ memcpy(buf,xkb->names->keys[i].name,4);
+ buf[4]= '\0';
+ WARN2("No symbols defined for <%s> (keycode %d)\n",buf,i);
+ }
+ }
+ }
+ if (info.modMap) {
+ ModMapEntry *mm,*next;
+ for (mm=info.modMap;mm!=NULL;mm=next) {
+ if (!CopyModMapDef(result,mm))
+ info.errorCount++;
+ next= (ModMapEntry *)mm->defs.next;
+ }
+ }
+ return True;
+ }
+ return False;
+}
diff --git a/tokens.h b/tokens.h
new file mode 100644
index 0000000..c63c393
--- /dev/null
+++ b/tokens.h
@@ -0,0 +1,100 @@
+/* $Xorg: tokens.h,v 1.3 2000/08/17 19:54:33 cpqbld Exp $ */
+/************************************************************
+ 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
+ documentation, and that the name of Silicon Graphics not be
+ used in advertising or publicity pertaining to distribution
+ of the software without specific prior written permission.
+ Silicon Graphics makes no representation about the suitability
+ of this software for any purpose. It is provided "as is"
+ without any express or implied warranty.
+
+ SILICON GRAPHICS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS
+ SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+ AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL SILICON
+ 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
+ OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH
+ THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+ ********************************************************/
+#ifndef TOKENS_H
+#define TOKENS_H 1
+
+#define END_OF_FILE 0
+#define ERROR_TOK 255
+
+#define XKB_KEYMAP 1
+#define XKB_KEYCODES 2
+#define XKB_TYPES 3
+#define XKB_SYMBOLS 4
+#define XKB_COMPATMAP 5
+#define XKB_GEOMETRY 6
+#define XKB_SEMANTICS 7
+#define XKB_LAYOUT 8
+
+#define INCLUDE 10
+#define OVERRIDE 11
+#define AUGMENT 12
+#define REPLACE 13
+#define ALTERNATE 14
+
+#define VIRTUAL_MODS 20
+#define TYPE 21
+#define INTERPRET 22
+#define ACTION_TOK 23
+#define KEY 24
+#define ALIAS 25
+#define GROUP 26
+#define MODIFIER_MAP 27
+#define INDICATOR 28
+#define SHAPE 29
+#define KEYS 30
+#define ROW 31
+#define SECTION 32
+#define OVERLAY 33
+#define TEXT 34
+#define OUTLINE 35
+#define SOLID 36
+#define LOGO 37
+#define VIRTUAL 38
+
+#define EQUALS 40
+#define PLUS 41
+#define MINUS 42
+#define DIVIDE 43
+#define TIMES 44
+#define OBRACE 45
+#define CBRACE 46
+#define OPAREN 47
+#define CPAREN 48
+#define OBRACKET 49
+#define CBRACKET 50
+#define DOT 51
+#define COMMA 52
+#define SEMI 53
+#define EXCLAM 54
+#define INVERT 55
+
+#define STRING 60
+#define INTEGER 61
+#define FLOAT 62
+#define IDENT 63
+#define KEYNAME 64
+
+#define PARTIAL 70
+#define DEFAULT 71
+#define HIDDEN 72
+#define ALPHANUMERIC_KEYS 73
+#define MODIFIER_KEYS 74
+#define KEYPAD_KEYS 75
+#define FUNCTION_KEYS 76
+#define ALTERNATE_GROUP 77
+
+#endif
diff --git a/utils.c b/utils.c
new file mode 100644
index 0000000..37058c7
--- /dev/null
+++ b/utils.c
@@ -0,0 +1,530 @@
+
+ /*\
+ * $Xorg: utils.c,v 1.4 2000/08/17 19:54:33 cpqbld Exp $
+ *
+ * COPYRIGHT 1990
+ * DIGITAL EQUIPMENT CORPORATION
+ * MAYNARD, MASSACHUSETTS
+ * ALL RIGHTS RESERVED.
+ *
+ * THE INFORMATION IN THIS SOFTWARE IS SUBJECT TO CHANGE WITHOUT NOTICE AND
+ * SHOULD NOT BE CONSTRUED AS A COMMITMENT BY DIGITAL EQUIPMENT CORPORATION.
+ * DIGITAL MAKES NO REPRESENTATIONS ABOUT THE SUITABILITY OF THIS SOFTWARE
+ * FOR ANY PURPOSE. IT IS SUPPLIED "AS IS" WITHOUT EXPRESS OR IMPLIED
+ * WARRANTY.
+ *
+ * IF THE SOFTWARE IS MODIFIED IN A MANNER CREATING DERIVATIVE COPYRIGHT
+ * RIGHTS, APPROPRIATE LEGENDS MAY BE PLACED ON THE DERIVATIVE WORK IN
+ * ADDITION TO THAT SET FORTH ABOVE.
+ *
+ * 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
+ * documentation, and that the name of Digital Equipment Corporation not be
+ * used in advertising or publicity pertaining to distribution of the
+ * software without specific, written prior permission.
+ \*/
+
+#include "utils.h"
+#include <ctype.h>
+#ifndef X_NOT_STDC_ENV
+#include <stdlib.h>
+#else
+char *malloc();
+#endif
+
+/***====================================================================***/
+
+Opaque
+#if NeedFunctionPrototypes
+uAlloc(unsigned size)
+#else
+uAlloc(size)
+ unsigned size;
+#endif
+{
+ return((Opaque)malloc(size));
+}
+
+/***====================================================================***/
+
+Opaque
+#if NeedFunctionPrototypes
+uCalloc(unsigned n,unsigned size)
+#else
+uCalloc(n,size)
+ unsigned n;
+ unsigned size;
+#endif
+{
+ return((Opaque)calloc(n,size));
+}
+
+/***====================================================================***/
+
+Opaque
+#if NeedFunctionPrototypes
+uRealloc(Opaque old,unsigned newSize)
+#else
+uRealloc(old,newSize)
+ Opaque old;
+ unsigned newSize;
+#endif
+{
+ if (old==NULL)
+ return((Opaque)malloc(newSize));
+ else return((Opaque)realloc((char *)old,newSize));
+}
+
+/***====================================================================***/
+
+Opaque
+#if NeedFunctionPrototypes
+uRecalloc(Opaque old,unsigned nOld,unsigned nNew,unsigned itemSize)
+#else
+uRecalloc(old,nOld,nNew,itemSize)
+ Opaque old;
+ unsigned nOld;
+ unsigned nNew;
+ unsigned itemSize;
+#endif
+{
+char *rtrn;
+
+ if (old==NULL)
+ rtrn= (char *)calloc(nNew,itemSize);
+ else {
+ rtrn= (char *)realloc((char *)old,nNew*itemSize);
+ if ((rtrn)&&(nNew>nOld)) {
+ bzero(&rtrn[nOld*itemSize],(nNew-nOld)*itemSize);
+ }
+ }
+ return (Opaque)rtrn;
+}
+
+/***====================================================================***/
+
+void
+#if NeedFunctionPrototypes
+uFree(Opaque ptr)
+#else
+uFree(ptr)
+ Opaque ptr;
+#endif
+{
+ if (ptr!=(Opaque)NULL)
+ free((char *)ptr);
+ return;
+}
+
+/***====================================================================***/
+/*** FUNCTION ENTRY TRACKING ***/
+/***====================================================================***/
+
+static FILE *entryFile= stderr;
+ int uEntryLevel;
+
+Boolean
+#if NeedFunctionPrototypes
+uSetEntryFile(char *name)
+#else
+uSetEntryFile(name)
+ char *name;
+#endif
+{
+ if ((entryFile!=NULL)&&(entryFile!=stderr)) {
+ fprintf(entryFile,"switching to %s\n",name?name:"stderr");
+ fclose(entryFile);
+ }
+ if (name!=NullString) entryFile= fopen(name,"w");
+ else entryFile= stderr;
+ if (entryFile==NULL) {
+ entryFile= stderr;
+ return(False);
+ }
+ return(True);
+}
+
+void
+#if NeedFunctionPrototypes
+uEntry(int l,char *s,Opaque a1,Opaque a2,Opaque a3,Opaque a4,Opaque a5,
+ Opaque a6)
+#else
+uEntry(l,s,a1,a2,a3,a4,a5,a6)
+int l;
+char *s;
+Opaque a1,a2,a3,a4,a5,a6;
+#endif
+{
+int i;
+
+ for (i=0;i<uEntryLevel;i++) {
+ putc(' ',entryFile);
+ }
+ fprintf(entryFile,s,a1,a2,a3,a4,a5,a6);
+ uEntryLevel+= l;
+ return;
+}
+
+void
+#if NeedFunctionPrototypes
+uExit(int l,char *rtVal)
+#else
+uExit(l,rtVal)
+ int l;
+ char * rtVal;
+#endif
+{
+int i;
+
+ uEntryLevel-= l;
+ if (uEntryLevel<0) uEntryLevel= 0;
+ for (i=0;i<uEntryLevel;i++) {
+ putc(' ',entryFile);
+ }
+ fprintf(entryFile,"---> 0x%x\n",rtVal);
+ return;
+}
+
+/***====================================================================***/
+/*** PRINT FUNCTIONS ***/
+/***====================================================================***/
+
+ FILE *uDebugFile= stderr;
+ int uDebugIndentLevel= 0;
+ int uDebugIndentSize= 4;
+
+Boolean
+#if NeedFunctionPrototypes
+uSetDebugFile(char *name)
+#else
+uSetDebugFile(name)
+ char *name;
+#endif
+{
+ if ((uDebugFile!=NULL)&&(uDebugFile!=stderr)) {
+ fprintf(uDebugFile,"switching to %s\n",name?name:"stderr");
+ fclose(uDebugFile);
+ }
+ if (name!=NullString) uDebugFile= fopen(name,"w");
+ else uDebugFile= stderr;
+ if (uDebugFile==NULL) {
+ uDebugFile= stderr;
+ return(False);
+ }
+ return(True);
+}
+
+void
+#if NeedFunctionPrototypes
+uDebug(char *s,Opaque a1,Opaque a2,Opaque a3,Opaque a4,Opaque a5,Opaque a6)
+#else
+uDebug(s,a1,a2,a3,a4,a5,a6)
+char *s;
+Opaque a1,a2,a3,a4,a5,a6;
+#endif
+{
+int i;
+
+ for (i=(uDebugIndentLevel*uDebugIndentSize);i>0;i--) {
+ putc(' ',uDebugFile);
+ }
+ fprintf(uDebugFile,s,a1,a2,a3,a4,a5,a6);
+ fflush(uDebugFile);
+ return;
+}
+
+void
+#if NeedFunctionPrototypes
+uDebugNOI(char *s,Opaque a1,Opaque a2,Opaque a3,Opaque a4,Opaque a5,Opaque a6)
+#else
+uDebugNOI(s,a1,a2,a3,a4,a5,a6)
+char *s;
+Opaque a1,a2,a3,a4,a5,a6;
+#endif
+{
+ fprintf(uDebugFile,s,a1,a2,a3,a4,a5,a6);
+ fflush(uDebugFile);
+ return;
+}
+
+/***====================================================================***/
+
+static FILE *errorFile= stderr;
+static int outCount= 0;
+static char *preMsg= NULL;
+static char *postMsg= NULL;
+static char *prefix= NULL;
+
+Boolean
+#if NeedFunctionPrototypes
+uSetErrorFile(char *name)
+#else
+uSetErrorFile(name)
+ char *name;
+#endif
+{
+ if ((errorFile!=NULL)&&(errorFile!=stderr)) {
+ fprintf(errorFile,"switching to %s\n",name?name:"stderr");
+ fclose(errorFile);
+ }
+ if (name!=NullString) errorFile= fopen(name,"w");
+ else errorFile= stderr;
+ if (errorFile==NULL) {
+ errorFile= stderr;
+ return(False);
+ }
+ return(True);
+}
+
+void
+#if NeedFunctionPrototypes
+uInformation(char *s,Opaque a1,Opaque a2,Opaque a3,Opaque a4,Opaque a5,
+ Opaque a6)
+#else
+uInformation(s,a1,a2,a3,a4,a5,a6)
+char *s;
+Opaque a1,a2,a3,a4,a5,a6;
+#endif
+{
+ fprintf(errorFile,s,a1,a2,a3,a4,a5,a6);
+ fflush(errorFile);
+ return;
+}
+
+/***====================================================================***/
+
+void
+#if NeedFunctionPrototypes
+uAction(char *s,Opaque a1,Opaque a2,Opaque a3,Opaque a4,Opaque a5,Opaque a6)
+#else
+uAction(s,a1,a2,a3,a4,a5,a6)
+char *s;
+Opaque a1,a2,a3,a4,a5,a6;
+#endif
+{
+ if (prefix!=NULL)
+ fprintf(errorFile,"%s",prefix);
+ fprintf(errorFile," ");
+ fprintf(errorFile,s,a1,a2,a3,a4,a5,a6);
+ fflush(errorFile);
+ return;
+}
+
+/***====================================================================***/
+
+void
+#if NeedFunctionPrototypes
+uWarning(char *s,Opaque a1,Opaque a2,Opaque a3,Opaque a4,Opaque a5,Opaque a6)
+#else
+uWarning(s,a1,a2,a3,a4,a5,a6)
+char *s;
+Opaque a1,a2,a3,a4,a5,a6;
+#endif
+{
+ if ((outCount==0)&&(preMsg!=NULL))
+ fprintf(errorFile,"%s\n",preMsg);
+ if (prefix!=NULL)
+ fprintf(errorFile,"%s",prefix);
+ fprintf(errorFile,"Warning: ");
+ fprintf(errorFile,s,a1,a2,a3,a4,a5,a6);
+ fflush(errorFile);
+ outCount++;
+ return;
+}
+
+/***====================================================================***/
+
+void
+#if NeedFunctionPrototypes
+uError(char *s,Opaque a1,Opaque a2,Opaque a3,Opaque a4,Opaque a5,Opaque a6)
+#else
+uError(s,a1,a2,a3,a4,a5,a6)
+char *s;
+Opaque a1,a2,a3,a4,a5,a6;
+#endif
+{
+ if ((outCount==0)&&(preMsg!=NULL))
+ fprintf(errorFile,"%s\n",preMsg);
+ if (prefix!=NULL)
+ fprintf(errorFile,"%s",prefix);
+ fprintf(errorFile,"Error: ");
+ fprintf(errorFile,s,a1,a2,a3,a4,a5,a6);
+ fflush(errorFile);
+ outCount++;
+ return;
+}
+
+/***====================================================================***/
+
+void
+#if NeedFunctionPrototypes
+uFatalError(char *s,Opaque a1,Opaque a2,Opaque a3,Opaque a4,Opaque a5,Opaque a6)
+#else
+uFatalError(s,a1,a2,a3,a4,a5,a6)
+char *s;
+Opaque a1,a2,a3,a4,a5,a6;
+#endif
+{
+ if ((outCount==0)&&(preMsg!=NULL))
+ fprintf(errorFile,"%s\n",preMsg);
+ if (prefix!=NULL)
+ fprintf(errorFile,"%s",prefix);
+ fprintf(errorFile,"Fatal Error: ");
+ fprintf(errorFile,s,a1,a2,a3,a4,a5,a6);
+ fprintf(errorFile," Exiting\n");
+ fflush(errorFile);
+ outCount++;
+ exit(1);
+ /* NOTREACHED */
+}
+
+/***====================================================================***/
+
+void
+#if NeedFunctionPrototypes
+uInternalError(char *s,Opaque a1,Opaque a2,Opaque a3,Opaque a4,Opaque a5,
+ Opaque a6)
+#else
+uInternalError(s,a1,a2,a3,a4,a5,a6)
+char *s;
+Opaque a1,a2,a3,a4,a5,a6;
+#endif
+{
+ if ((outCount==0)&&(preMsg!=NULL))
+ fprintf(errorFile,"%s\n",preMsg);
+ if (prefix!=NULL)
+ fprintf(errorFile,"%s",prefix);
+ fprintf(errorFile,"Internal error: ");
+ fprintf(errorFile,s,a1,a2,a3,a4,a5,a6);
+ fflush(errorFile);
+ outCount++;
+ return;
+}
+
+void
+#if NeedFunctionPrototypes
+uSetPreErrorMessage(char *msg)
+#else
+uSetPreErrorMessage(msg)
+ char *msg;
+#endif
+{
+ outCount= 0;
+ preMsg= msg;
+ return;
+}
+
+void
+#if NeedFunctionPrototypes
+uSetPostErrorMessage(char *msg)
+#else
+uSetPostErrorMessage(msg)
+ char *msg;
+#endif
+{
+ postMsg= msg;
+ return;
+}
+
+void
+#if NeedFunctionPrototypes
+uSetErrorPrefix(char *pre)
+#else
+uSetErrorPrefix(pre)
+ char *pre;
+#endif
+{
+ prefix= pre;
+ return;
+}
+
+void
+#if NeedFunctionPrototypes
+uFinishUp(void)
+#else
+uFinishUp()
+#endif
+{
+ if ((outCount>0)&&(postMsg!=NULL))
+ fprintf(errorFile,"%s\n",postMsg);
+ return;
+}
+
+/***====================================================================***/
+
+#ifndef HAVE_STRDUP
+char *
+#if NeedFunctionPrototypes
+uStringDup(char *str)
+#else
+uStringDup(str)
+ char *str;
+#endif
+{
+char *rtrn;
+
+ if (str==NULL)
+ return NULL;
+ rtrn= (char *)uAlloc(strlen(str)+1);
+ strcpy(rtrn,str);
+ return rtrn;
+}
+#endif
+
+#ifndef HAVE_STRCASECMP
+int
+#if NeedFunctionPrototypes
+uStrCaseCmp(char *str1,char *str2)
+#else
+uStrCaseCmp(str1, str2)
+ char *str1, *str2;
+#endif
+{
+ char buf1[512],buf2[512];
+ char c, *s;
+ register int n;
+
+ for (n=0, s = buf1; (c = *str1++); n++) {
+ if (isupper(c))
+ c = tolower(c);
+ if (n>510)
+ break;
+ *s++ = c;
+ }
+ *s = '\0';
+ for (n=0, s = buf2; (c = *str2++); n++) {
+ if (isupper(c))
+ c = tolower(c);
+ if (n>510)
+ break;
+ *s++ = c;
+ }
+ *s = '\0';
+ return (strcmp(buf1, buf2));
+}
+
+int
+#if NeedFunctionPrototypes
+uStrCasePrefix(char *prefix,char *str)
+#else
+uStrCasePrefix(prefix, str)
+ char *prefix, *str;
+#endif
+{
+ char c1;
+ char c2;
+ while (((c1=*prefix)!='\0')&&((c2=*str)!='\0')) {
+ if (isupper(c1)) c1= tolower(c1);
+ if (isupper(c2)) c2= tolower(c2);
+ if (c1!=c2)
+ return 0;
+ prefix++; str++;
+ }
+ if (c1!='\0')
+ return 0;
+ return 1;
+}
+
+#endif
diff --git a/utils.h b/utils.h
new file mode 100644
index 0000000..e3a71c9
--- /dev/null
+++ b/utils.h
@@ -0,0 +1,453 @@
+#ifndef UTILS_H
+#define UTILS_H 1
+
+ /*\
+ * $Xorg: utils.h,v 1.3 2000/08/17 19:54:33 cpqbld Exp $
+ *
+ * COPYRIGHT 1990
+ * DIGITAL EQUIPMENT CORPORATION
+ * MAYNARD, MASSACHUSETTS
+ * ALL RIGHTS RESERVED.
+ *
+ * THE INFORMATION IN THIS SOFTWARE IS SUBJECT TO CHANGE WITHOUT NOTICE AND
+ * SHOULD NOT BE CONSTRUED AS A COMMITMENT BY DIGITAL EQUIPMENT CORPORATION.
+ * DIGITAL MAKES NO REPRESENTATIONS ABOUT THE SUITABILITY OF THIS SOFTWARE
+ * FOR ANY PURPOSE. IT IS SUPPLIED "AS IS" WITHOUT EXPRESS OR IMPLIED
+ * WARRANTY.
+ *
+ * IF THE SOFTWARE IS MODIFIED IN A MANNER CREATING DERIVATIVE COPYRIGHT
+ * RIGHTS, APPROPRIATE LEGENDS MAY BE PLACED ON THE DERIVATIVE WORK IN
+ * ADDITION TO THAT SET FORTH ABOVE.
+ *
+ * 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
+ * documentation, and that the name of Digital Equipment Corporation not be
+ * used in advertising or publicity pertaining to distribution of the
+ * software without specific, written prior permission.
+ \*/
+
+/***====================================================================***/
+
+#include <stdio.h>
+#include <X11/Xos.h>
+#include <X11/Xfuncproto.h>
+#include <X11/Xfuncs.h>
+
+#ifndef NULL
+#define NULL 0
+#endif
+
+#ifndef NUL
+#define NUL '\0'
+#endif
+
+/***====================================================================***/
+
+#ifndef OPAQUE_DEFINED
+typedef void *Opaque;
+#endif
+#ifndef NullOpaque
+#define NullOpaque ((Opaque)NULL)
+#endif
+
+#ifndef BOOLEAN_DEFINED
+typedef char Boolean;
+#endif
+
+#ifndef True
+#define True ((Boolean)1)
+#define False ((Boolean)0)
+#endif /* ndef True */
+#define booleanText(b) ((b)?"True":"False")
+
+#ifndef COMPARISON_DEFINED
+typedef int Comparison;
+
+#define Greater ((Comparison)1)
+#define Equal ((Comparison)0)
+#define Less ((Comparison)-1)
+#define CannotCompare ((Comparison)-37)
+#define comparisonText(c) ((c)?((c)<0?"Less":"Greater"):"Equal")
+#endif
+
+_XFUNCPROTOBEGIN
+
+typedef union {
+ int i;
+ unsigned u;
+ void *p;
+ void *(*fp)();
+} Union;
+
+/***====================================================================***/
+
+extern Opaque uAlloc(
+#if NeedFunctionPrototypes
+ unsigned /* size */
+#endif
+);
+extern Opaque uCalloc(
+#if NeedFunctionPrototypes
+ unsigned /* n */,
+ unsigned /* size */
+#endif
+);
+extern Opaque uRealloc(
+#if NeedFunctionPrototypes
+ Opaque /* old */,
+ unsigned /* newSize */
+#endif
+);
+extern Opaque uRecalloc(
+#if NeedFunctionPrototypes
+ Opaque /* old */,
+ unsigned /* nOld */,
+ unsigned /* nNew */,
+ unsigned /* newSize */
+#endif
+);
+extern void uFree(
+#if NeedFunctionPrototypes
+ Opaque /* ptr */
+#endif
+);
+
+#define uTypedAlloc(t) ((t *)uAlloc((unsigned)sizeof(t)))
+#define uTypedCalloc(n,t) ((t *)uCalloc((unsigned)n,(unsigned)sizeof(t)))
+#define uTypedRealloc(pO,n,t) ((t *)uRealloc((Opaque)pO,((unsigned)n)*sizeof(t)))
+#define uTypedRecalloc(pO,o,n,t) ((t *)uRecalloc((Opaque)pO,((unsigned)o),((unsigned)n),sizeof(t)))
+#if (defined mdHasAlloca) && (mdHasAlloca)
+#define uTmpAlloc(n) ((Opaque)alloca((unsigned)n))
+#define uTmpFree(p)
+#else
+#define uTmpAlloc(n) uAlloc(n)
+#define uTmpFree(p) uFree(p)
+#endif
+
+/***====================================================================***/
+
+extern Boolean uSetErrorFile(
+#if NeedFunctionPrototypes
+ char * /* name */
+#endif
+);
+
+#define INFO6(s,a,b,c,d,e,f) uInformation((s),(Opaque)(a),(Opaque)(b),\
+ (Opaque)(c),(Opaque)(d),\
+ (Opaque)(e),(Opaque)(f))
+#define INFO5(s,a,b,c,d,e) INFO6(s,a,b,c,d,e,NULL)
+#define INFO4(s,a,b,c,d) INFO5(s,a,b,c,d,NULL)
+#define INFO3(s,a,b,c) INFO4(s,a,b,c,NULL)
+#define INFO2(s,a,b) INFO3(s,a,b,NULL)
+#define INFO1(s,a) INFO2(s,a,NULL)
+#define INFO(s) INFO1(s,NULL)
+
+extern void uInformation(
+#if NeedFunctionPrototypes
+ char * /* s */,
+ Opaque /* a1 */,Opaque /* a2 */,Opaque /* a3 */,
+ Opaque /* a4 */,Opaque /* a5 */,Opaque /* a6 */
+#endif
+);
+
+#define ACTION6(s,a,b,c,d,e,f) uAction((s),(Opaque)(a),(Opaque)(b),\
+ (Opaque)(c),(Opaque)(d),\
+ (Opaque)(e),(Opaque)(f))
+#define ACTION5(s,a,b,c,d,e) ACTION6(s,a,b,c,d,e,NULL)
+#define ACTION4(s,a,b,c,d) ACTION5(s,a,b,c,d,NULL)
+#define ACTION3(s,a,b,c) ACTION4(s,a,b,c,NULL)
+#define ACTION2(s,a,b) ACTION3(s,a,b,NULL)
+#define ACTION1(s,a) ACTION2(s,a,NULL)
+#define ACTION(s) ACTION1(s,NULL)
+extern void uAction(
+#if NeedFunctionPrototypes
+ char * /* s */,
+ Opaque /* a1 */,Opaque /* a2 */,Opaque /* a3 */,
+ Opaque /* a4 */,Opaque /* a5 */,Opaque /* a6 */
+#endif
+);
+
+#define WARN6(s,a,b,c,d,e,f) uWarning((s),(Opaque)(a),(Opaque)(b),\
+ (Opaque)(c),(Opaque)(d),\
+ (Opaque)(e),(Opaque)(f))
+#define WARN5(s,a,b,c,d,e) WARN6(s,a,b,c,d,e,NULL)
+#define WARN4(s,a,b,c,d) WARN5(s,a,b,c,d,NULL)
+#define WARN3(s,a,b,c) WARN4(s,a,b,c,NULL)
+#define WARN2(s,a,b) WARN3(s,a,b,NULL)
+#define WARN1(s,a) WARN2(s,a,NULL)
+#define WARN(s) WARN1(s,NULL)
+extern void uWarning(
+#if NeedFunctionPrototypes
+ char * /* s */,
+ Opaque /* a1 */,Opaque /* a2 */,Opaque /* a3 */,
+ Opaque /* a4 */,Opaque /* a5 */,Opaque /* a6 */
+#endif
+);
+
+#define ERROR6(s,a,b,c,d,e,f) uError((s),(Opaque)(a),(Opaque)(b),\
+ (Opaque)(c),(Opaque)(d),\
+ (Opaque)(e),(Opaque)(f))
+#define ERROR5(s,a,b,c,d,e) ERROR6(s,a,b,c,d,e,NULL)
+#define ERROR4(s,a,b,c,d) ERROR5(s,a,b,c,d,NULL)
+#define ERROR3(s,a,b,c) ERROR4(s,a,b,c,NULL)
+#define ERROR2(s,a,b) ERROR3(s,a,b,NULL)
+#define ERROR1(s,a) ERROR2(s,a,NULL)
+#define ERROR(s) ERROR1(s,NULL)
+extern void uError(
+#if NeedFunctionPrototypes
+ char * /* s */,
+ Opaque /* a1 */,Opaque /* a2 */,Opaque /* a3 */,
+ Opaque /* a4 */,Opaque /* a5 */,Opaque /* a6 */
+#endif
+);
+
+#define FATAL6(s,a,b,c,d,e,f) uFatalError((s),(Opaque)(a),(Opaque)(b),\
+ (Opaque)(c),(Opaque)(d),\
+ (Opaque)(e),(Opaque)(f))
+#define FATAL5(s,a,b,c,d,e) FATAL6(s,a,b,c,d,e,NULL)
+#define FATAL4(s,a,b,c,d) FATAL5(s,a,b,c,d,NULL)
+#define FATAL3(s,a,b,c) FATAL4(s,a,b,c,NULL)
+#define FATAL2(s,a,b) FATAL3(s,a,b,NULL)
+#define FATAL1(s,a) FATAL2(s,a,NULL)
+#define FATAL(s) FATAL1(s,NULL)
+extern void uFatalError(
+#if NeedFunctionPrototypes
+ char * /* s */,
+ Opaque /* a1 */,Opaque /* a2 */,Opaque /* a3 */,
+ Opaque /* a4 */,Opaque /* a5 */,Opaque /* a6 */
+#endif
+);
+
+ /* WSGO stands for "Weird Stuff Going On" */
+#define WSGO6(s,a,b,c,d,e,f) uInternalError((s),(Opaque)(a),(Opaque)(b),\
+ (Opaque)(c),(Opaque)(d),\
+ (Opaque)(e),(Opaque)(f))
+#define WSGO5(s,a,b,c,d,e) WSGO6(s,a,b,c,d,e,NULL)
+#define WSGO4(s,a,b,c,d) WSGO5(s,a,b,c,d,NULL)
+#define WSGO3(s,a,b,c) WSGO4(s,a,b,c,NULL)
+#define WSGO2(s,a,b) WSGO3(s,a,b,NULL)
+#define WSGO1(s,a) WSGO2(s,a,NULL)
+#define WSGO(s) WSGO1(s,NULL)
+extern void uInternalError(
+#if NeedFunctionPrototypes
+ char * /* s */,
+ Opaque /* a1 */,Opaque /* a2 */,Opaque /* a3 */,
+ Opaque /* a4 */,Opaque /* a5 */,Opaque /* a6 */
+#endif
+);
+
+extern void uSetPreErrorMessage(
+#if NeedFunctionPrototypes
+ char * /* msg */
+#endif
+);
+
+extern void uSetPostErrorMessage(
+#if NeedFunctionPrototypes
+ char * /* msg */
+#endif
+);
+
+extern void uSetErrorPrefix(
+#if NeedFunctionPrototypes
+ char * /* void */
+#endif
+);
+
+extern void uFinishUp(
+#if NeedFunctionPrototypes
+ void
+#endif
+);
+
+
+/***====================================================================***/
+
+#define NullString ((char *)NULL)
+
+#define uStringText(s) ((s)==NullString?"<NullString>":(s))
+#define uStringEqual(s1,s2) (uStringCompare(s1,s2)==Equal)
+#define uStringPrefix(p,s) (strncmp(p,s,strlen(p))==0)
+#define uStringCompare(s1,s2) (strcmp(s1,s2))
+#define uStrCaseEqual(s1,s2) (uStrCaseCmp(s1,s2)==0)
+#ifdef HAVE_STRCASECMP
+#define uStrCaseCmp(s1,s2) (strcasecmp(s1,s2))
+#define uStrCasePrefix(p,s) (strncasecmp(p,s,strlen(p))==0)
+#else
+extern int uStrCaseCmp(
+#if NeedFunctionPrototypes
+ char * /* s1 */,
+ char * /* s2 */
+#endif
+);
+extern int uStrCasePrefix(
+#if NeedFunctionPrototypes
+ char * /* p */,
+ char * /* str */
+#endif
+);
+#endif
+#ifdef HAVE_STRDUP
+#define uStringDup(s1) (strdup(s1))
+#else
+extern char *uStringDup(
+#if NeedFunctionPrototypes
+ char * /* s1 */
+#endif
+);
+#endif
+
+/***====================================================================***/
+
+#ifdef ASSERTIONS_ON
+#define uASSERT(where,why) \
+ {if (!(why)) uFatalError("assertion botched in %s ( why )\n",where);}
+#else
+#define uASSERT(where,why)
+#endif
+
+/***====================================================================***/
+
+#ifndef DEBUG_VAR
+#define DEBUG_VAR debugFlags
+#endif
+
+#ifdef DEBUG_VAR_NOT_LOCAL
+extern
+#endif
+unsigned int DEBUG_VAR;
+
+extern void uDebug(
+#if NeedFunctionPrototypes
+ char * /* s */,
+ Opaque /* a1 */,Opaque /* a2 */,Opaque /* a3 */,
+ Opaque /* a4 */,Opaque /* a5 */,Opaque /* a6 */
+#endif
+);
+
+extern void uDebugNOI( /* no indent */
+#if NeedFunctionPrototypes
+ char * /* s */,
+ Opaque /* a1 */,Opaque /* a2 */,Opaque /* a3 */,
+ Opaque /* a4 */,Opaque /* a5 */,Opaque /* a6 */
+#endif
+);
+
+extern Boolean uSetDebugFile(
+#if NeedFunctionPrototypes
+ char *name
+#endif
+);
+
+extern FILE *uDebugFile;
+extern int uDebugIndentLevel;
+extern int uDebugIndentSize;
+#define uDebugIndent(l) (uDebugIndentLevel+=(l))
+#define uDebugOutdent(l) (uDebugIndentLevel-=(l))
+#ifdef DEBUG_ON
+#define uDEBUG(f,s) { if (DEBUG_VAR&(f)) uDebug(s);}
+#define uDEBUG1(f,s,a) { if (DEBUG_VAR&(f)) uDebug(s,a);}
+#define uDEBUG2(f,s,a,b) { if (DEBUG_VAR&(f)) uDebug(s,a,b);}
+#define uDEBUG3(f,s,a,b,c) { if (DEBUG_VAR&(f)) uDebug(s,a,b,c);}
+#define uDEBUG4(f,s,a,b,c,d) { if (DEBUG_VAR&(f)) uDebug(s,a,b,c,d);}
+#define uDEBUG5(f,s,a,b,c,d,e) { if (DEBUG_VAR&(f)) uDebug(s,a,b,c,d,e);}
+#define uDEBUG_NOI(f,s) { if (DEBUG_VAR&(f)) uDebug(s);}
+#define uDEBUG_NOI1(f,s,a) { if (DEBUG_VAR&(f)) uDebugNOI(s,a);}
+#define uDEBUG_NOI2(f,s,a,b) { if (DEBUG_VAR&(f)) uDebugNOI(s,a,b);}
+#define uDEBUG_NOI3(f,s,a,b,c) { if (DEBUG_VAR&(f)) uDebugNOI(s,a,b,c);}
+#define uDEBUG_NOI4(f,s,a,b,c,d) { if (DEBUG_VAR&(f)) uDebugNOI(s,a,b,c,d);}
+#define uDEBUG_NOI5(f,s,a,b,c,d,e) { if (DEBUG_VAR&(f)) uDebugNOI(s,a,b,c,d,e);}
+#else
+#define uDEBUG(f,s)
+#define uDEBUG1(f,s,a)
+#define uDEBUG2(f,s,a,b)
+#define uDEBUG3(f,s,a,b,c)
+#define uDEBUG4(f,s,a,b,c,d)
+#define uDEBUG5(f,s,a,b,c,d,e)
+#define uDEBUG_NOI(f,s)
+#define uDEBUG_NOI1(f,s,a)
+#define uDEBUG_NOI2(f,s,a,b)
+#define uDEBUG_NOI3(f,s,a,b,c)
+#define uDEBUG_NOI4(f,s,a,b,c,d)
+#define uDEBUG_NOI5(f,s,a,b,c,d,e)
+#endif
+
+extern Boolean uSetEntryFile(
+#if NeedFunctionPrototypes
+ char *name
+#endif
+);
+extern void uEntry(
+#if NeedFunctionPrototypes
+ int /* l */,
+ char * /* s */,
+ Opaque /* a1 */,Opaque /* a2 */,Opaque /* a3 */,
+ Opaque /* a4 */,Opaque /* a5 */,Opaque /* a6 */
+#endif
+);
+
+extern void uExit(
+#if NeedFunctionPrototypes
+ int l,char *rtVal
+#endif
+);
+#ifdef ENTRY_TRACKING_ON
+#define ENTRY_BIT 0x10
+#define LOW_ENTRY_BIT 0x1000
+#define ENTER (DEBUG_VAR&ENTRY_BIT)
+#define FLAG(fLag) (DEBUG_VAR&(fLag))
+
+extern int uEntryLevel;
+
+#define uENTRY(s) { if (ENTER) uEntry(1,s);}
+#define uENTRY1(s,a) { if (ENTER) uEntry(1,s,a);}
+#define uENTRY2(s,a,b) { if (ENTER) uEntry(1,s,a,b);}
+#define uENTRY3(s,a,b,c) { if (ENTER) uEntry(1,s,a,b,c);}
+#define uENTRY4(s,a,b,c,d) { if (ENTER) uEntry(1,s,a,b,c,d);}
+#define uENTRY5(s,a,b,c,d,e) { if (ENTER) uEntry(1,s,a,b,c,d,e);}
+#define uENTRY6(s,a,b,c,d,e,f) { if (ENTER) uEntry(1,s,a,b,c,d,e,f);}
+#define uENTRY7(s,a,b,c,d,e,f,g) { if (ENTER) uEntry(1,s,a,b,c,d,e,f,g);}
+#define uRETURN(v) { if (ENTER) uEntryLevel--; return(v); }
+#define uVOIDRETURN { if (ENTER) uEntryLevel--; return; }
+
+#define uFLAG_ENTRY(w,s) { if (FLAG(w)) uEntry(0,s);}
+#define uFLAG_ENTRY1(w,s,a) { if (FLAG(w)) uEntry(0,s,a);}
+#define uFLAG_ENTRY2(w,s,a,b) { if (FLAG(w)) uEntry(0,s,a,b);}
+#define uFLAG_ENTRY3(w,s,a,b,c) { if (FLAG(w)) uEntry(0,s,a,b,c);}
+#define uFLAG_ENTRY4(w,s,a,b,c,d) { if (FLAG(w)) uEntry(0,s,a,b,c,d);}
+#define uFLAG_ENTRY5(w,s,a,b,c,d,e) { if (FLAG(w)) uEntry(0,s,a,b,c,d,e);}
+#define uFLAG_ENTRY6(w,s,a,b,c,d,e,f) { if (FLAG(w)) uEntry(0,s,a,b,c,d,e,f);}
+#define uFLAG_ENTRY7(w,s,a,b,c,d,e,f,g) { if(FLAG(w))uEntry(0,s,a,b,c,d,e,f,g);}
+#define uFLAG_RETURN(v) { return(v);}
+#define uFLAG_VOIDRETURN { return; }
+#else
+#define uENTRY(s)
+#define uENTRY1(s,a)
+#define uENTRY2(s,a1,a2)
+#define uENTRY3(s,a1,a2,a3)
+#define uENTRY4(s,a1,a2,a3,a4)
+#define uENTRY5(s,a1,a2,a3,a4,a5)
+#define uENTRY6(s,a1,a2,a3,a4,a5,a6)
+#define uENTRY7(s,a1,a2,a3,a4,a5,a6,a7)
+#define uRETURN(v) { return(v); }
+#define uVOIDRETURN { return; }
+
+#define uFLAG_ENTRY(f,s)
+#define uFLAG_ENTRY1(f,s,a)
+#define uFLAG_ENTRY2(f,s,a,b)
+#define uFLAG_ENTRY3(f,s,a,b,c)
+#define uFLAG_ENTRY4(f,s,a,b,c,d)
+#define uFLAG_ENTRY5(f,s,a,b,c,d,e)
+#define uFLAG_ENTRY6(f,s,a,b,c,d,e,g)
+#define uFLAG_ENTRY7(f,s,a,b,c,d,e,g,h)
+#define uFLAG_RETURN(v) { return(v);}
+#define uFLAG_VOIDRETURN { return; }
+#endif
+
+_XFUNCPROTOEND
+
+#endif /* UTILS_H */
+
+
diff --git a/vmod.c b/vmod.c
new file mode 100644
index 0000000..b67c34e
--- /dev/null
+++ b/vmod.c
@@ -0,0 +1,271 @@
+/* $Xorg: vmod.c,v 1.3 2000/08/17 19:54:33 cpqbld Exp $ */
+/************************************************************
+ 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
+ documentation, and that the name of Silicon Graphics not be
+ used in advertising or publicity pertaining to distribution
+ of the software without specific prior written permission.
+ Silicon Graphics makes no representation about the suitability
+ of this software for any purpose. It is provided "as is"
+ without any express or implied warranty.
+
+ SILICON GRAPHICS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS
+ SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+ AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL SILICON
+ 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
+ OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH
+ THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+ ********************************************************/
+#define DEBUG_VAR_NOT_LOCAL
+#define DEBUG_VAR debugFlags
+#include <stdio.h>
+#include "xkbcomp.h"
+#include "tokens.h"
+#include "expr.h"
+#include "misc.h"
+
+#include <X11/extensions/XKB.h>
+#include <X11/extensions/XKBstr.h>
+
+#include "vmod.h"
+
+void
+#if NeedFunctionPrototypes
+InitVModInfo(VModInfo *info,XkbDescPtr xkb)
+#else
+InitVModInfo(info,xkb)
+ VModInfo * info;
+ XkbDescPtr xkb;
+#endif
+{
+ ClearVModInfo(info,xkb);
+ info->errorCount= 0;
+ return;
+}
+
+void
+#if NeedFunctionPrototypes
+ClearVModInfo(VModInfo *info,XkbDescPtr xkb)
+#else
+ClearVModInfo(info,xkb)
+ VModInfo * info;
+ XkbDescPtr xkb;
+#endif
+{
+register int i;
+
+ if (XkbAllocNames(xkb,XkbVirtualModNamesMask,0,0)!=Success)
+ return;
+ if (XkbAllocServerMap(xkb,XkbVirtualModsMask,0)!=Success)
+ return;
+ info->xkb= xkb;
+ info->newlyDefined= info->defined= info->available= 0;
+ if (xkb && xkb->names) {
+ register int bit;
+ for (i=0,bit=1;i<XkbNumVirtualMods;i++,bit<<=1) {
+ if (xkb->names->vmods[i]!=None)
+ info->defined|= bit;
+ }
+ }
+ return;
+}
+
+/***====================================================================***/
+
+Bool
+#if NeedFunctionPrototypes
+HandleVModDef(VModDef *stmt,unsigned mergeMode,VModInfo *info)
+#else
+HandleVModDef(stmt,mergeMode,info)
+ VModDef * stmt;
+ unsigned mergeMode;
+ VModInfo * info;
+#endif
+{
+register int i,bit,nextFree;
+ExprResult mod;
+XkbServerMapPtr srv;
+XkbNamesPtr names;
+Atom stmtName;
+
+ srv= info->xkb->server;
+ names= info->xkb->names;
+ stmtName= XkbInternAtom(info->xkb->dpy,XkbAtomGetString(NULL,stmt->name),
+ False);
+ for (i=0,bit=1,nextFree= -1;i<XkbNumVirtualMods;i++,bit<<=1) {
+ if (info->defined&bit) {
+ if (names->vmods[i]==stmtName) { /* already defined */
+ info->available|= bit;
+ if (stmt->value==NULL)
+ return True;
+ else {
+ char *str1,*str2= "";
+ if (!ExprResolveModMask(stmt->value,&mod,NULL,NULL)) {
+ str1= XkbAtomText(NULL,stmt->name,XkbMessage);
+ ACTION1("Declaration of %s ignored\n",str1);
+ return False;
+ }
+ if (mod.uval==srv->vmods[i])
+ return True;
+
+ str1= XkbAtomText(NULL,stmt->name,XkbMessage);
+ WARN1("Virtual modifier %s multiply defined\n",str1);
+ str1= XkbModMaskText(srv->vmods[i],XkbCFile);
+ if (mergeMode==MergeOverride) {
+ str2= str1;
+ str1= XkbModMaskText(mod.uval,XkbCFile);
+ }
+ ACTION2("Using %s, ignoring %s\n",str1,str2);
+ if (mergeMode==MergeOverride)
+ srv->vmods[i]= mod.uval;
+ return True;
+ }
+ }
+ }
+ else if (nextFree<0)
+ nextFree= i;
+ }
+ if (nextFree<0) {
+ ERROR1("Too many virtual modifiers defined (maximum %d)\n",
+ XkbNumVirtualMods);
+ ACTION("Exiting\n");
+ return False;
+ }
+ info->defined|= (1<<nextFree);
+ info->newlyDefined|= (1<<nextFree);
+ info->available|= (1<<nextFree);
+ names->vmods[nextFree]= stmtName;
+ if (stmt->value==NULL)
+ return True;
+ if (ExprResolveModMask(stmt->value,&mod,NULL,NULL)) {
+ srv->vmods[nextFree]= mod.uval;
+ return True;
+ }
+ ACTION1("Declaration of %s ignored\n",
+ XkbAtomText(NULL,stmt->name,XkbMessage));
+ return False;
+}
+
+int
+#if NeedFunctionPrototypes
+LookupVModIndex( XPointer priv,
+ Atom elem,
+ Atom field,
+ unsigned type,
+ ExprResult * val_rtrn)
+#else
+LookupVModIndex(priv,elem,field,type,val_rtrn)
+ XPointer priv;
+ Atom elem;
+ Atom field;
+ unsigned type;
+ ExprResult * val_rtrn;
+#endif
+{
+register int i;
+register char * fieldStr;
+register char * modStr;
+XkbDescPtr xkb;
+
+ xkb= (XkbDescPtr)priv;
+ if ((xkb==NULL)||(xkb->names==NULL)||(elem!=None)||(type!=TypeInt)) {
+ return False;
+ }
+ fieldStr= XkbAtomGetString(xkb->dpy,field);
+ if (fieldStr==NULL)
+ return False;
+ for (i=0;i<XkbNumVirtualMods;i++) {
+ modStr= XkbAtomGetString(xkb->dpy,xkb->names->vmods[i]);
+ if ((modStr!=NULL)&&(uStrCaseCmp(fieldStr,modStr)==0)) {
+ val_rtrn->uval= i;
+ return True;
+ }
+ }
+ return False;
+}
+
+int
+#if NeedFunctionPrototypes
+LookupVModMask( XPointer priv,
+ Atom elem,
+ Atom field,
+ unsigned type,
+ ExprResult * val_rtrn)
+#else
+LookupVModMask(priv,elem,field,type,val_rtrn)
+ XPointer priv;
+ Atom elem;
+ Atom field;
+ unsigned type;
+ ExprResult * val_rtrn;
+#endif
+{
+ if (LookupVModIndex(priv,elem,field,type,val_rtrn)) {
+ register unsigned ndx= val_rtrn->uval;
+ val_rtrn->uval= (1<<(XkbNumModifiers+ndx));
+ return True;
+ }
+ return False;
+}
+
+int
+#if NeedFunctionPrototypes
+FindKeypadVMod(XkbDescPtr xkb)
+#else
+FindKeypadVMod(xkb)
+ XkbDescPtr xkb;
+#endif
+{
+Atom name;
+ExprResult rtrn;
+
+ name= XkbInternAtom(xkb->dpy,"NumLock",False);
+ if ((xkb)&&
+ LookupVModIndex((XPointer)xkb,None,name,TypeInt,&rtrn)) {
+ return rtrn.ival;
+ }
+ return -1;
+}
+
+Bool
+#if NeedFunctionPrototypes
+ResolveVirtualModifier(ExprDef *def,ExprResult *val_rtrn,VModInfo *info)
+#else
+ResolveVirtualModifier(def,val_rtrn,info)
+ ExprDef * def;
+ ExprResult * val_rtrn;
+ VModInfo * info;
+#endif
+{
+XkbNamesPtr names;
+
+ names= info->xkb->names;
+ if (def->op==ExprIdent) {
+ register int i,bit;
+ for (i=0,bit=1;i<XkbNumVirtualMods;i++,bit<<=1) {
+ char *str1,*str2;
+ str1= XkbAtomGetString(info->xkb->dpy,names->vmods[i]);
+ str2= XkbAtomGetString(NULL,def->value.str);
+ if ((info->available&bit)&&
+ (uStrCaseCmp(str1,str2)==Equal)) {
+ val_rtrn->uval= i;
+ return True;
+ }
+ }
+ }
+ if (ExprResolveInteger(def,val_rtrn,NULL,NULL)) {
+ if (val_rtrn->uval<XkbNumVirtualMods)
+ return True;
+ ERROR2("Illegal virtual modifier %d (must be 0..%d inclusive)\n",
+ val_rtrn->uval,XkbNumVirtualMods-1);
+ }
+ return False;
+}
diff --git a/vmod.h b/vmod.h
new file mode 100644
index 0000000..eddf312
--- /dev/null
+++ b/vmod.h
@@ -0,0 +1,101 @@
+/* $Xorg: vmod.h,v 1.3 2000/08/17 19:54:33 cpqbld Exp $ */
+/************************************************************
+ 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
+ documentation, and that the name of Silicon Graphics not be
+ used in advertising or publicity pertaining to distribution
+ of the software without specific prior written permission.
+ Silicon Graphics makes no representation about the suitability
+ of this software for any purpose. It is provided "as is"
+ without any express or implied warranty.
+
+ SILICON GRAPHICS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS
+ SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+ AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL SILICON
+ 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
+ OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH
+ THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+ ********************************************************/
+#ifndef VMOD_H
+#define VMOD_H 1
+
+typedef struct _VModInfo {
+ XkbDescPtr xkb;
+ unsigned defined;
+ unsigned available;
+ unsigned newlyDefined;
+ int errorCount;
+} VModInfo;
+
+extern void InitVModInfo(
+#if NeedFunctionPrototypes
+ VModInfo * /* info */,
+ XkbDescPtr /* xkb */
+#endif
+);
+
+extern void ClearVModInfo(
+#if NeedFunctionPrototypes
+ VModInfo * /* info */,
+ XkbDescPtr /* xkb */
+#endif
+);
+
+extern Bool HandleVModDef(
+#if NeedFunctionPrototypes
+ VModDef * /* stmt */,
+ unsigned /* mergeMode */,
+ VModInfo * /* info */
+#endif
+);
+
+extern Bool ApplyVModDefs(
+#if NeedFunctionPrototypes
+ VModInfo * /* info */,
+ XkbDescPtr /* xkb */
+#endif
+);
+
+extern int LookupVModIndex(
+#if NeedFunctionPrototypes
+ XPointer /* priv */,
+ Atom /* elem */,
+ Atom /* field */,
+ unsigned /* type */,
+ ExprResult * /* val_rtrn */
+#endif
+);
+
+extern int LookupVModMask(
+#if NeedFunctionPrototypes
+ XPointer /* priv */,
+ Atom /* elem */,
+ Atom /* field */,
+ unsigned /* type */,
+ ExprResult * /* val_rtrn */
+#endif
+);
+
+extern int FindKeypadVMod(
+#if NeedFunctionPrototypes
+ XkbDescPtr /* xkb */
+#endif
+);
+
+extern Bool ResolveVirtualModifier(
+#if NeedFunctionPrototypes
+ ExprDef * /* def */,
+ ExprResult * /* value_rtrn */,
+ VModInfo * /* info */
+#endif
+);
+
+#endif /* VMOD_H */
diff --git a/xkbcomp.c b/xkbcomp.c
new file mode 100644
index 0000000..29df701
--- /dev/null
+++ b/xkbcomp.c
@@ -0,0 +1,932 @@
+/* $Xorg: xkbcomp.c,v 1.4 2000/08/17 19:54:33 cpqbld Exp $ */
+/************************************************************
+ 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
+ documentation, and that the name of Silicon Graphics not be
+ used in advertising or publicity pertaining to distribution
+ of the software without specific prior written permission.
+ Silicon Graphics makes no representation about the suitability
+ of this software for any purpose. It is provided "as is"
+ without any express or implied warranty.
+
+ SILICON GRAPHICS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS
+ SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+ AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL SILICON
+ 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
+ OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH
+ THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+ ********************************************************/
+
+#include <stdio.h>
+#include <ctype.h>
+#include <X11/keysym.h>
+
+#if defined(sgi)
+#include <malloc.h>
+#endif
+
+#define DEBUG_VAR_NOT_LOCAL
+#define DEBUG_VAR debugFlags
+#include "xkbcomp.h"
+#ifndef X_NOT_STDC_ENV
+#include <stdlib.h>
+#endif
+#include "xkbpath.h"
+#include "parseutils.h"
+#include "misc.h"
+#include "tokens.h"
+#include <X11/extensions/XKBgeom.h>
+
+#define lowbit(x) ((x) & (-(x)))
+
+/***====================================================================***/
+
+#define WANT_DEFAULT 0
+#define WANT_XKM_FILE 1
+#define WANT_C_HDR 2
+#define WANT_XKB_FILE 3
+#define WANT_X_SERVER 4
+#define WANT_LISTING 5
+
+#define INPUT_UNKNOWN 0
+#define INPUT_XKB 1
+#define INPUT_XKM 2
+
+static char *fileTypeExt[] = {
+ "XXX",
+ "xkm",
+ "h",
+ "xkb",
+ "dir"
+};
+
+static unsigned inputFormat,outputFormat;
+ char * rootDir;
+static char * inputFile;
+static char * inputMap;
+static char * outputFile;
+static char * inDpyName;
+static char * outDpyName;
+static Display * inDpy;
+static Display * outDpy;
+static Bool showImplicit= False;
+static Bool synch= False;
+static Bool merge= False;
+static Bool computeDflts= False;
+static Bool xkblist= False;
+ unsigned warningLevel= 5;
+ unsigned verboseLevel= 0;
+ unsigned dirsToStrip= 0;
+ unsigned optionalParts= 0;
+static char * preErrorMsg= NULL;
+static char * postErrorMsg= NULL;
+static char * errorPrefix= NULL;
+
+/***====================================================================***/
+
+#define M(m) fprintf(stderr,(m))
+#define M1(m,a) fprintf(stderr,(m),(a))
+
+static void
+#if NeedFunctionPrototypes
+Usage(int argc,char *argv[])
+#else
+Usage(argc,argv)
+ int argc;
+ char * argv[];
+#endif
+{
+ if (!xkblist)
+ M1("Usage: %s [options] input-file [ output-file ]\n",argv[0]);
+ else M1("Usage: %s [options] file[(map)] ...\n",argv[0]);
+ M("Legal options:\n");
+ M("-?,-help Print this message\n");
+ if (!xkblist) {
+ M("-a Show all actions\n");
+ M("-C Create a C header file\n");
+ }
+#ifdef DEBUG
+ M("-d [flags] Report debugging information\n");
+#endif
+ M("-em1 <msg> Print <msg> before printing first error message\n");
+ M("-emp <msg> Print <msg> at the start of each message line\n");
+ M("-eml <msg> If there were any errors, print <msg> before exiting\n");
+ if (!xkblist) {
+ M("-dflts Compute defaults for missing parts\n");
+ M("-I[<dir>] Specifies a top level directory for include\n");
+ M(" directives. Multiple directories are legal.\n");
+ M("-l [flags] List matching maps in the specified files\n");
+ M(" f: list fully specified names\n");
+ M(" h: also list hidden maps\n");
+ M(" l: long listing (show flags)\n");
+ M(" p: also list partial maps\n");
+ M(" R: recursively list subdirectories\n");
+ M(" default is all options off\n");
+ }
+ M("-m[ap] <map> Specifies map to compile\n");
+ if (!xkblist)
+ M("-merge Merge file with map on server\n");
+ M("-o <file> Specifies output file name\n");
+ if (!xkblist) {
+ M("-opt[ional] <parts> Specifies optional components of keymap\n");
+ M(" Errors in optional parts are not fatal\n");
+ M(" <parts> can be any combination of:\n");
+ M(" c: compat map g: geometry\n");
+ M(" k: keycodes s: symbols\n");
+ M(" t: types\n");
+ }
+ if (xkblist) {
+ M("-p <count> Specifies the number of slashes to be stripped\n");
+ M(" from the front of the map name on output\n");
+ }
+ M("-R[<DIR>] Specifies the root directory for\n");
+ M(" relative path names\n");
+ M("-synch Force synchronization\n");
+ if (xkblist) {
+ M("-v [<flags>] Set level of detail for listing.\n");
+ M(" flags are as for the -l option\n");
+ }
+ M("-w [<lvl>] Set warning level (0=none, 10=all)\n");
+ if (!xkblist) {
+ M("-xkb Create an XKB source (.xkb) file\n");
+ M("-xkm Create a compiled key map (.xkm) file\n");
+ }
+ return;
+}
+
+/***====================================================================***/
+
+static void
+#if NeedFunctionPrototypes
+setVerboseFlags(char *str)
+#else
+setVerboseFlags(str)
+ char * str;
+#endif
+{
+ for (;*str;str++) {
+ switch (*str) {
+ case 'f': verboseLevel|= WantFullNames; break;
+ case 'h': verboseLevel|= WantHiddenMaps; break;
+ case 'l': verboseLevel|= WantLongListing; break;
+ case 'p': verboseLevel|= WantPartialMaps; break;
+ case 'R': verboseLevel|= ListRecursive; break;
+ default:
+ if (warningLevel>4) {
+ WARN1("Unknown verbose option \"%c\"\n",(unsigned int)*str);
+ ACTION("Ignored\n");
+ }
+ break;
+ }
+ }
+ return;
+}
+
+static Bool
+#if NeedFunctionPrototypes
+parseArgs(int argc,char *argv[])
+#else
+parseArgs(argc,argv)
+ int argc;
+ char * argv[];
+#endif
+{
+register int i,tmp;
+
+ i= strlen(argv[0]);
+ tmp= strlen("xkblist");
+ if ((i>=tmp)&&(strcmp(&argv[0][i-tmp],"xkblist")==0)) {
+ xkblist= True;
+ }
+ for (i=1;i<argc;i++) {
+ if ((argv[i][0]!='-')||(uStringEqual(argv[i],"-"))) {
+ if (!xkblist) {
+ if (inputFile==NULL)
+ inputFile= argv[i];
+ else if (outputFile==NULL)
+ outputFile= argv[i];
+ else if (warningLevel>0) {
+ WARN("Too many file names on command line\n");
+ ACTION3("Compiling %s, writing to %s, ignoring %s\n",
+ inputFile,outputFile,argv[i]);
+ }
+ }
+ else if (!AddMatchingFiles(argv[i]))
+ return False;
+ }
+ else if ((strcmp(argv[i],"-?")==0)||(strcmp(argv[i],"-help")==0)) {
+ Usage(argc,argv);
+ exit(0);
+ }
+ else if ((strcmp(argv[i],"-a")==0)&&(!xkblist)) {
+ showImplicit= True;
+ }
+ else if ((strcmp(argv[i],"-C")==0)&&(!xkblist)) {
+ if ((outputFormat!=WANT_DEFAULT)&&(outputFormat!=WANT_C_HDR)) {
+ if (warningLevel>0) {
+ WARN("Multiple output file formats specified\n");
+ ACTION1("\"%s\" flag ignored\n",argv[i]);
+ }
+ }
+ else outputFormat= WANT_C_HDR;
+ }
+#ifdef DEBUG
+ else if (strcmp(argv[i],"-d")==0) {
+ if ((i>=(argc-1))||(!isdigit(argv[i+1][0]))) {
+ debugFlags= 1;
+ }
+ else {
+ sscanf(argv[++i],"%i",&debugFlags);
+ }
+ INFO1("Setting debug flags to %d\n",debugFlags);
+ }
+#endif
+ else if ((strcmp(argv[i],"-dflts")==0)&&(!xkblist)) {
+ computeDflts= True;
+ }
+ else if (strcmp(argv[i],"-em1")==0) {
+ if (++i>=argc) {
+ if (warningLevel>0) {
+ WARN("No pre-error message specified\n");
+ ACTION("Trailing \"-em1\" option ignored\n");
+ }
+ }
+ else if (preErrorMsg!=NULL) {
+ if (warningLevel>0) {
+ WARN("Multiple pre-error messsages specified\n");
+ ACTION2("Compiling %s, ignoring %s\n",preErrorMsg,argv[i]);
+ }
+ }
+ else preErrorMsg= argv[i];
+ }
+ else if (strcmp(argv[i],"-emp")==0) {
+ if (++i>=argc) {
+ if (warningLevel>0) {
+ WARN("No error prefix specified\n");
+ ACTION("Trailing \"-emp\" option ignored\n");
+ }
+ }
+ else if (errorPrefix!=NULL) {
+ if (warningLevel>0) {
+ WARN("Multiple error prefixes specified\n");
+ ACTION2("Compiling %s, ignoring %s\n",errorPrefix,argv[i]);
+ }
+ }
+ else errorPrefix= argv[i];
+ }
+ else if (strcmp(argv[i],"-eml")==0) {
+ if (++i>=argc) {
+ if (warningLevel>0) {
+ WARN("No post-error message specified\n");
+ ACTION("Trailing \"-eml\" option ignored\n");
+ }
+ }
+ else if (postErrorMsg!=NULL) {
+ if (warningLevel>0) {
+ WARN("Multiple post-error messages specified\n");
+ ACTION2("Compiling %s, ignoring %s\n",postErrorMsg,argv[i]);
+ }
+ }
+ else postErrorMsg= argv[i];
+ }
+ else if ((strncmp(argv[i],"-I",2)==0)&&(!xkblist)) {
+ if (!XkbAddDirectoryToPath(&argv[i][2])) {
+ ACTION("Exiting\n");
+ exit(1);
+ }
+ }
+ else if ((strncmp(argv[i],"-l",2)==0)&&(!xkblist)) {
+ if (outputFormat!=WANT_DEFAULT) {
+ if (warningLevel>0) {
+ WARN("Multiple output file formats specified\n");
+ ACTION1("\"%s\" flag ignored\n",argv[i]);
+ }
+ }
+ else {
+ if (argv[i][2]!='\0')
+ setVerboseFlags(&argv[i][2]);
+ xkblist= True;
+ if ((inputFile)&&(!AddMatchingFiles(inputFile)))
+ return False;
+ else inputFile= NULL;
+ if ((outputFile)&&(!AddMatchingFiles(outputFile)))
+ return False;
+ else outputFile= NULL;
+ }
+ }
+ else if ((strcmp(argv[i],"-m")==0)||(strcmp(argv[i],"-map")==0)) {
+ if (++i>=argc) {
+ if (warningLevel>0) {
+ WARN("No map name specified\n");
+ ACTION1("Trailing \"%s\" option ignored\n",argv[i-1]);
+ }
+ }
+ else if (xkblist) {
+ if (!AddMapOnly(argv[i]))
+ return False;
+ }
+ else if (inputMap!=NULL) {
+ if (warningLevel>0) {
+ WARN("Multiple map names specified\n");
+ ACTION2("Compiling %s, ignoring %s\n",inputMap,argv[i]);
+ }
+ }
+ else inputMap= argv[i];
+ }
+ else if ((strcmp(argv[i],"-merge")==0)&&(!xkblist)) {
+ merge= True;
+ }
+ else if (strcmp(argv[i],"-o")==0) {
+ if (++i>=argc) {
+ if (warningLevel>0) {
+ WARN("No output file specified\n");
+ ACTION("Trailing \"-o\" option ignored\n");
+ }
+ }
+ else if (outputFile!=NULL) {
+ if (warningLevel>0) {
+ WARN("Multiple output files specified\n");
+ ACTION2("Compiling %s, ignoring %s\n",outputFile,argv[i]);
+ }
+ }
+ else outputFile= argv[i];
+ }
+ else if (((strcmp(argv[i],"-opt")==0)||(strcmp(argv[i],"optional")==0))
+ &&(!xkblist)) {
+ if (++i>=argc) {
+ if (warningLevel>0) {
+ WARN("No optional components specified\n");
+ ACTION1("Trailing \"%s\" option ignored\n",argv[i-1]);
+ }
+ }
+ else {
+ char *tmp;
+ for (tmp=argv[i];(*tmp!='\0');tmp++) {
+ switch (*tmp) {
+ case 'c': case 'C':
+ optionalParts|= XkmCompatMapMask;
+ break;
+ case 'g': case 'G':
+ optionalParts|= XkmGeometryMask;
+ break;
+ case 'k': case 'K':
+ optionalParts|= XkmKeyNamesMask;
+ break;
+ case 's': case 'S':
+ optionalParts|= XkmSymbolsMask;
+ break;
+ case 't': case 'T':
+ optionalParts|= XkmTypesMask;
+ break;
+ default:
+ if (warningLevel>0) {
+ WARN1("Illegal component for %s option\n",
+ argv[i-1]);
+ ACTION1("Ignoring unknown specifier \"%c\"\n",
+ (unsigned int)*tmp);
+ }
+ break;
+ }
+ }
+ }
+ }
+ else if (strncmp(argv[i],"-p",2)==0) {
+ if (isdigit(argv[i][2])) {
+ sscanf(&argv[i][2],"%i",&dirsToStrip);
+ }
+ else if ((i<(argc-1))&&(isdigit(argv[i+1][0]))) {
+ sscanf(argv[++i],"%i",&dirsToStrip);
+ }
+ else {
+ dirsToStrip= 0;
+ }
+ if (warningLevel>5)
+ INFO1("Setting path count to %d\n",dirsToStrip);
+ }
+ else if (strncmp(argv[i],"-R",2)==0) {
+ if (argv[i][2]=='\0') {
+ if (warningLevel>0) {
+ WARN("No root directory specified\n");
+ ACTION("Ignoring -R option\n");
+ }
+ }
+ else if (rootDir!=NULL) {
+ if (warningLevel>0) {
+ WARN("Multiple root directories specified\n");
+ ACTION2("Using %s, ignoring %s\n",rootDir,argv[i]);
+ }
+ }
+ else {
+ rootDir= &argv[i][2];
+ if (warningLevel>8) {
+ WARN1("Changing root directory to \"%s\"\n",rootDir);
+ }
+ if ((chdir(rootDir)<0) && (warningLevel>0)) {
+ WARN1("Couldn't change directory to \"%s\"\n",rootDir);
+ ACTION("Root directory (-R) option ignored\n");
+ rootDir= NULL;
+ }
+ }
+ }
+ else if ((strcmp(argv[i],"-synch")==0)||(strcmp(argv[i],"-s")==0)) {
+ synch= True;
+ }
+ else if (strncmp(argv[i],"-v",2)==0) {
+ char *str;
+ if (argv[i][2]!='\0')
+ str= &argv[i][2];
+ else if ((i<(argc-1))&&(argv[i+1][0]!='-'))
+ str= argv[++i];
+ else str= NULL;
+ if (str)
+ setVerboseFlags(str);
+ }
+ else if (strncmp(argv[i],"-w",2)==0) {
+ if ((i>=(argc-1))||(!isdigit(argv[i+1][0]))) {
+ if (isdigit(argv[i][1]))
+ sscanf(&argv[i][1],"%i",&warningLevel);
+ else warningLevel= 0;
+ }
+ else {
+ sscanf(argv[++i],"%i",&warningLevel);
+ }
+ }
+ else if ((strcmp(argv[i],"-xkb")==0)&&(!xkblist)) {
+ if ((outputFormat!=WANT_DEFAULT)&&(outputFormat!=WANT_XKB_FILE)) {
+ if (warningLevel>0) {
+ WARN("Multiple output file formats specified\n");
+ ACTION1("\"%s\" flag ignored\n",argv[i]);
+ }
+ }
+ else outputFormat= WANT_XKB_FILE;
+ }
+ else if ((strcmp(argv[i],"-xkm")==0)&&(!xkblist)) {
+ if ((outputFormat!=WANT_DEFAULT)&&(outputFormat!=WANT_XKM_FILE)) {
+ if (warningLevel>0) {
+ WARN("Multiple output file formats specified\n");
+ ACTION1("\"%s\" flag ignored\n",argv[i]);
+ }
+ }
+ else outputFormat= WANT_XKM_FILE;
+ }
+ else {
+ ERROR1("Unknown flag \"%s\" on command line\n",argv[i]);
+ Usage(argc,argv);
+ return False;
+ }
+ }
+ if (xkblist)
+ inputFormat= INPUT_XKB;
+ else if (inputFile==NULL) {
+ ERROR("No input file specified\n");
+ return False;
+ }
+ else if (uStringEqual(inputFile,"-")) {
+ inputFormat= INPUT_XKB;
+ }
+ else if (strchr(inputFile,':')==0) {
+ int len;
+ len= strlen(inputFile);
+ if (inputFile[len-1]==')') {
+ char *tmp;
+ if ((tmp=strchr(inputFile,'('))!=0) {
+ *tmp= '\0'; inputFile[len-1]= '\0';
+ tmp++;
+ if (*tmp=='\0') {
+ WARN("Empty map in filename\n");
+ ACTION("Ignored\n");
+ }
+ else if (inputMap==NULL) {
+ inputMap= uStringDup(tmp);
+ }
+ else {
+ WARN("Map specified in filename and with -m flag\n");
+ ACTION1("map from name (\"%s\") ignored\n",tmp);
+ }
+ }
+ else {
+ ERROR1("Illegal name \"%s\" for input file\n",inputFile);
+ return False;
+ }
+ }
+ if ((len>4)&&(strcmp(&inputFile[len-4],".xkm")==0)) {
+ inputFormat= INPUT_XKM;
+ }
+ else {
+ FILE *file;
+ file= fopen(inputFile,"r");
+ if (file) {
+ if (XkmProbe(file)) inputFormat= INPUT_XKM;
+ else inputFormat= INPUT_XKB;
+ fclose(file);
+ }
+ else {
+ fprintf(stderr,"Cannot open \"%s\" for reading\n",inputFile);
+ return False;
+ }
+ }
+ }
+ else {
+ inDpyName= inputFile;
+ inputFile= NULL;
+ inputFormat= INPUT_XKM;
+ }
+
+ if (outputFormat==WANT_DEFAULT) {
+ if (xkblist) outputFormat= WANT_LISTING;
+ else if (inputFormat==INPUT_XKB) outputFormat= WANT_XKM_FILE;
+ else outputFormat= WANT_XKB_FILE;
+ }
+ if ((outputFormat==WANT_LISTING)&&(inputFormat!=INPUT_XKB)) {
+ if (inputFile)
+ ERROR("Cannot generate a listing from a .xkm file (yet)\n");
+ else ERROR("Cannot generate a listing from an X connection (yet)\n");
+ return False;
+ }
+ if (xkblist) {
+ if (outputFile==NULL) outputFile= uStringDup("-");
+ else if (strchr(outputFile,':')!=NULL) {
+ ERROR("Cannot write a listing to an X connection\n");
+ return False;
+ }
+ }
+ else if ((!outputFile) && (inputFile) && uStringEqual(inputFile,"-")) {
+ int len= strlen("stdin")+strlen(fileTypeExt[outputFormat])+2;
+ outputFile= uTypedCalloc(len,char);
+ if (outputFile==NULL) {
+ WSGO("Cannot allocate space for output file name\n");
+ ACTION("Exiting\n");
+ exit(1);
+ }
+ sprintf(outputFile,"stdin.%s",fileTypeExt[outputFormat]);
+ }
+ else if ((outputFile==NULL)&&(inputFile!=NULL)) {
+ int len;
+ char *base,*ext;
+
+ if (inputMap==NULL) {
+ base= strrchr(inputFile,'/');
+ if (base==NULL) base= inputFile;
+ else base++;
+ }
+ else base= inputMap;
+
+ len= strlen(base)+strlen(fileTypeExt[outputFormat])+2;
+ outputFile= uTypedCalloc(len,char);
+ if (outputFile==NULL) {
+ WSGO("Cannot allocate space for output file name\n");
+ ACTION("Exiting\n");
+ exit(1);
+ }
+ ext= strrchr(base,'.');
+ if (ext==NULL)
+ sprintf(outputFile,"%s.%s",base,fileTypeExt[outputFormat]);
+ else {
+ strcpy(outputFile,base);
+ strcpy(&outputFile[ext-base+1],fileTypeExt[outputFormat]);
+ }
+ }
+ else if (outputFile==NULL) {
+ int len;
+ char *ch,*name,buf[128];
+ if (inDpyName[0]==':')
+ sprintf(name=buf,"server%s",inDpyName);
+ else name= inDpyName;
+
+ len= strlen(name)+strlen(fileTypeExt[outputFormat])+2;
+ outputFile= uTypedCalloc(len,char);
+ if (outputFile==NULL) {
+ WSGO("Cannot allocate space for output file name\n");
+ ACTION("Exiting\n");
+ exit(1);
+ }
+ strcpy(outputFile,name);
+ for (ch=outputFile;(*ch)!='\0';ch++) {
+ if (*ch==':') *ch= '-';
+ else if (*ch=='.') *ch= '_';
+ }
+ *ch++= '.';
+ strcpy(ch,fileTypeExt[outputFormat]);
+ }
+ else if (strchr(outputFile,':')!=NULL) {
+ outDpyName= outputFile;
+ outputFile= NULL;
+ outputFormat= WANT_X_SERVER;
+ }
+ return True;
+}
+
+static Display *
+#if NeedFunctionPrototypes
+GetDisplay(char *program,char *dpyName)
+#else
+GetDisplay(program,dpyName)
+ char * program;
+ char * dpyName;
+#endif
+{
+int mjr,mnr,error;
+Display *dpy;
+
+ mjr= XkbMajorVersion;
+ mnr= XkbMinorVersion;
+ dpy= XkbOpenDisplay(dpyName,NULL,NULL,&mjr,&mnr,&error);
+ if (dpy==NULL) {
+ switch (error) {
+ case XkbOD_BadLibraryVersion:
+ INFO3("%s was compiled with XKB version %d.%02d\n",
+ program,XkbMajorVersion,XkbMinorVersion);
+ ERROR2("X library supports incompatible version %d.%02d\n",
+ mjr,mnr);
+ break;
+ case XkbOD_ConnectionRefused:
+ ERROR1("Cannot open display \"%s\"\n",dpyName);
+ break;
+ case XkbOD_NonXkbServer:
+ ERROR1("XKB extension not present on %s\n",dpyName);
+ break;
+ case XkbOD_BadServerVersion:
+ INFO3("%s was compiled with XKB version %d.%02d\n",
+ program,XkbMajorVersion,XkbMinorVersion);
+ ERROR3("Server %s uses incompatible version %d.%02d\n",
+ dpyName,mjr,mnr);
+ break;
+ default:
+ WSGO1("Unknown error %d from XkbOpenDisplay\n",error);
+ }
+ }
+ else if (synch)
+ XSynchronize(dpy,True);
+ return dpy;
+}
+
+/***====================================================================***/
+
+extern int yydebug;
+
+int
+#if NeedFunctionPrototypes
+main(int argc,char *argv[])
+#else
+main(argc,argv)
+ int argc;
+ char * argv[];
+#endif
+{
+FILE * file;
+XkbFile * rtrn;
+XkbFile * mapToUse;
+int ok;
+XkbFileInfo result;
+Status status;
+
+ if (!parseArgs(argc,argv))
+ exit(1);
+#ifdef DEBUG
+ if (debugFlags&0x2)
+ yydebug= 1;
+#endif
+ if (preErrorMsg)
+ uSetPreErrorMessage(preErrorMsg);
+ if (errorPrefix)
+ uSetErrorPrefix(errorPrefix);
+ if (postErrorMsg)
+ uSetPostErrorMessage(postErrorMsg);
+ file= NULL;
+ XkbInitAtoms(NULL);
+ XkbInitIncludePath();
+ if (xkblist) {
+ Bool gotSome;
+ gotSome= GenerateListing(outputFile);
+ if ((warningLevel>7)&&(!gotSome))
+ return -1;
+ return 0;
+ }
+ if (inputFile!=NULL) {
+ if (uStringEqual(inputFile,"-")) {
+ static char *in= "stdin";
+ file= stdin;
+ inputFile= in;
+ }
+ else {
+ file= fopen(inputFile,"r");
+ }
+ }
+ else if (inDpyName!=NULL) {
+ inDpy= GetDisplay(argv[0],inDpyName);
+ if (!inDpy) {
+ ACTION("Exiting\n");
+ exit(1);
+ }
+ }
+ if (outDpyName!=NULL) {
+ outDpy= GetDisplay(argv[0],outDpyName);
+ if (!outDpy) {
+ ACTION("Exiting\n");
+ exit(1);
+ }
+ }
+ if ((inDpy==NULL) && (outDpy==NULL)) {
+ int mjr,mnr;
+ mjr= XkbMajorVersion;
+ mnr= XkbMinorVersion;
+ if (!XkbLibraryVersion(&mjr,&mnr)) {
+ INFO3("%s was compiled with XKB version %d.%02d\n",
+ argv[0],XkbMajorVersion,XkbMinorVersion);
+ ERROR2("X library supports incompatible version %d.%02d\n",
+ mjr,mnr);
+ ACTION("Exiting\n");
+ exit(1);
+ }
+ }
+ if (file) {
+ ok= True;
+ setScanState(inputFile,1);
+ if ((inputFormat==INPUT_XKB)&&(XKBParseFile(file,&rtrn)&&(rtrn!=NULL))){
+ fclose(file);
+ mapToUse= rtrn;
+ if (inputMap!=NULL) {
+ while ((mapToUse)&&(!uStringEqual(mapToUse->name,inputMap))) {
+ mapToUse= (XkbFile *)mapToUse->common.next;
+ }
+ if (!mapToUse) {
+ FATAL2("No map named \"%s\" in \"%s\"\n",inputMap,
+ inputFile);
+ /* NOTREACHED */
+ }
+ }
+ else if (rtrn->common.next!=NULL) {
+ mapToUse= rtrn;
+ for (;mapToUse;mapToUse= (XkbFile*)mapToUse->common.next) {
+ if (mapToUse->flags&XkbLC_Default)
+ break;
+ }
+ if (!mapToUse) {
+ mapToUse= rtrn;
+ if (warningLevel>4) {
+ WARN1("No map specified, but \"%s\" has several\n",
+ inputFile);
+ ACTION1("Using the first defined map, \"%s\"\n",
+ mapToUse->name);
+ }
+ }
+ }
+ bzero((char *)&result,sizeof(result));
+ result.type= mapToUse->type;
+ if ((result.xkb= XkbAllocKeyboard())==NULL) {
+ WSGO("Cannot allocate keyboard description\n");
+ /* NOTREACHED */
+ }
+ switch (mapToUse->type) {
+ case XkmSemanticsFile:
+ case XkmLayoutFile:
+ case XkmKeymapFile:
+ ok= CompileKeymap(mapToUse,&result,MergeReplace);
+ break;
+ case XkmKeyNamesIndex:
+ ok= CompileKeycodes(mapToUse,&result,MergeReplace);
+ break;
+ case XkmTypesIndex:
+ ok= CompileKeyTypes(mapToUse,&result,MergeReplace);
+ break;
+ case XkmSymbolsIndex:
+ /* if it's just symbols, invent key names */
+ result.xkb->flags|= AutoKeyNames;
+ ok= False;
+ break;
+ case XkmCompatMapIndex:
+ ok= CompileCompatMap(mapToUse,&result,MergeReplace,NULL);
+ break;
+ case XkmGeometryFile:
+ case XkmGeometryIndex:
+ /* if it's just a geometry, invent key names */
+ result.xkb->flags|= AutoKeyNames;
+ ok= CompileGeometry(mapToUse,&result,MergeReplace);
+ break;
+ default:
+ WSGO1("Unknown file type %d\n",mapToUse->type);
+ ok= False;
+ break;
+ }
+ }
+ else if (inputFormat==INPUT_XKM) {
+ unsigned tmp;
+ bzero((char *)&result,sizeof(result));
+ if ((result.xkb= XkbAllocKeyboard())==NULL) {
+ WSGO("Cannot allocate keyboard description\n");
+ /* NOTREACHED */
+ }
+ tmp= XkmReadFile(file,0,XkmKeymapLegal,&result);
+ if (tmp==XkmKeymapLegal) {
+ ERROR1("Cannot read XKM file \"%s\"\n",inputFile);
+ ok= False;
+ }
+ }
+ else {
+ INFO1("Errors encountered in %s; not compiled.\n",inputFile);
+ ok= False;
+ }
+ }
+ else if (inDpy!=NULL) {
+ bzero((char *)&result,sizeof(result));
+ result.type= XkmKeymapFile;
+ result.xkb= XkbGetMap(inDpy,XkbAllMapComponentsMask,XkbUseCoreKbd);
+ if (result.xkb==NULL)
+ WSGO("Cannot load keyboard description\n");
+ if (XkbGetIndicatorMap(inDpy,~0,result.xkb)!=Success)
+ WSGO("Could not load indicator map\n");
+ if (XkbGetControls(inDpy,XkbAllControlsMask,result.xkb)!=Success)
+ WSGO("Could not load keyboard controls\n");
+ if (XkbGetCompatMap(inDpy,XkbAllCompatMask,result.xkb)!=Success)
+ WSGO("Could not load compatibility map\n");
+ if (XkbGetNames(inDpy,XkbAllNamesMask,result.xkb)!=Success)
+ WSGO("Could not load names\n");
+ if ((status=XkbGetGeometry(inDpy,result.xkb))!=Success) {
+ if (warningLevel>3) {
+ char buf[100];
+ buf[0]= '\0';
+ XGetErrorText(inDpy,status,buf,100);
+ WARN1("Could not load keyboard geometry for %s\n",inDpyName);
+ ACTION1("%s\n",buf);
+ ACTION("Resulting keymap file will not describe geometry\n");
+ }
+ }
+ if (computeDflts)
+ ok= (ComputeKbdDefaults(result.xkb)==Success);
+ else ok= True;
+ }
+ else {
+ fprintf(stderr,"Cannot open \"%s\" to compile\n",inputFile);
+ ok= 0;
+ }
+ if (ok) {
+ FILE *out= stdout;
+ if ((inDpy!=outDpy)&&
+ (XkbChangeKbdDisplay(outDpy,&result)!=Success)) {
+ WSGO2("Error converting keyboard display from %s to %s\n",
+ inDpyName,outDpyName);
+ exit(1);
+ }
+ if (outputFile!=NULL) {
+ if (uStringEqual(outputFile,"-"))
+ outputFile= "stdout";
+ else {
+ out= fopen(outputFile,"w");
+ if (out==NULL) {
+ ERROR1("Cannot open \"%s\" to write keyboard description\n",
+ outputFile);
+ ACTION("Exiting\n");
+ exit(1);
+ }
+ }
+ }
+ switch (outputFormat) {
+ case WANT_XKM_FILE:
+ ok= XkbWriteXKMFile(out,&result);
+ break;
+ case WANT_XKB_FILE:
+ ok= XkbWriteXKBFile(out,&result,showImplicit,NULL,NULL);
+ break;
+ case WANT_C_HDR:
+ ok= XkbWriteCFile(out,outputFile,&result);
+ break;
+ case WANT_X_SERVER:
+ if (!(ok= XkbWriteToServer(&result))) {
+ ERROR2("%s in %s\n",_XkbErrMessages[_XkbErrCode],
+ _XkbErrLocation?_XkbErrLocation:"unknown");
+ ACTION1("Couldn't write keyboard description to %s\n",
+ outDpyName);
+ }
+ break;
+ default:
+ WSGO1("Unknown output format %d\n",outputFormat);
+ ACTION("No output file created\n");
+ ok= False;
+ break;
+ }
+ if (outputFormat!=WANT_X_SERVER) {
+ fclose(out);
+ if (!ok) {
+ ERROR2("%s in %s\n",_XkbErrMessages[_XkbErrCode],
+ _XkbErrLocation?_XkbErrLocation:"unknown");
+ ACTION1("Output file \"%s\" removed\n",outputFile);
+ unlink(outputFile);
+ }
+ }
+ }
+ if (inDpy)
+ XCloseDisplay(inDpy);
+ inDpy= NULL;
+ if (outDpy)
+ XCloseDisplay(outDpy);
+ uFinishUp();
+ return (ok==0);
+}
diff --git a/xkbcomp.h b/xkbcomp.h
new file mode 100644
index 0000000..46fe4a4
--- /dev/null
+++ b/xkbcomp.h
@@ -0,0 +1,408 @@
+/* $Xorg: xkbcomp.h,v 1.3 2000/08/17 19:54:33 cpqbld Exp $ */
+/************************************************************
+ 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
+ documentation, and that the name of Silicon Graphics not be
+ used in advertising or publicity pertaining to distribution
+ of the software without specific prior written permission.
+ Silicon Graphics makes no representation about the suitability
+ of this software for any purpose. It is provided "as is"
+ without any express or implied warranty.
+
+ SILICON GRAPHICS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS
+ SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+ AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL SILICON
+ 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
+ OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH
+ THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+ ********************************************************/
+
+#ifndef XKBCOMP_H
+#define XKBCOMP_H 1
+
+#ifndef DEBUG_VAR
+#define DEBUG_VAR_NOT_LOCAL
+#define DEBUG_VAR debugFlags
+#endif
+
+#include <X11/Xlib.h>
+#include <X11/XKBlib.h>
+
+#include "utils.h"
+
+#include <X11/extensions/XKM.h>
+#include <X11/extensions/XKBfile.h>
+
+extern char *scanFile;
+
+#define TypeUnknown 0
+#define TypeBoolean 1
+#define TypeInt 2
+#define TypeFloat 3
+#define TypeString 4
+#define TypeAction 5
+#define TypeKeyName 6
+#define TypeSymbols 7
+
+#define StmtUnknown 0
+#define StmtInclude 1
+#define StmtKeycodeDef 2
+#define StmtKeyAliasDef 3
+#define StmtExpr 4
+#define StmtVarDef 5
+#define StmtKeyTypeDef 6
+#define StmtInterpDef 7
+#define StmtVModDef 8
+#define StmtSymbolsDef 9
+#define StmtModMapDef 10
+#define StmtGroupCompatDef 11
+#define StmtIndicatorMapDef 12
+#define StmtIndicatorNameDef 13
+#define StmtOutlineDef 14
+#define StmtShapeDef 15
+#define StmtKeyDef 16
+#define StmtRowDef 17
+#define StmtSectionDef 18
+#define StmtOverlayKeyDef 19
+#define StmtOverlayDef 20
+#define StmtDoodadDef 21
+
+#define FileSymInterp 100
+
+typedef struct _ParseCommon {
+ unsigned stmtType;
+ struct _ParseCommon *next;
+} ParseCommon;
+
+#define ExprValue 0
+#define ExprIdent 1
+#define ExprActionDecl 2
+#define ExprFieldRef 3
+#define ExprArrayRef 4
+#define ExprKeysymList 5
+#define ExprActionList 6
+#define ExprCoord 7
+
+#define OpAdd 20
+#define OpSubtract 21
+#define OpMultiply 22
+#define OpDivide 23
+#define OpAssign 24
+#define OpNot 25
+#define OpNegate 26
+#define OpInvert 27
+#define OpUnaryPlus 28
+
+#define MergeDefault 0
+#define MergeAugment 1
+#define MergeOverride 2
+#define MergeReplace 3
+#define MergeAltForm 4
+
+#define AutoKeyNames (1L << 0)
+#define CreateKeyNames(x) ((x)->flags&AutoKeyNames)
+
+extern unsigned warningLevel;
+extern unsigned optionalParts;
+
+typedef struct _IncludeStmt {
+ ParseCommon common;
+ unsigned merge;
+ char *stmt;
+ char *file;
+ char *map;
+ char *path;
+ struct _IncludeStmt *next;
+} IncludeStmt;
+
+typedef struct _Expr {
+ ParseCommon common;
+ unsigned op;
+ unsigned type;
+ union {
+ struct {
+ struct _Expr *left;
+ struct _Expr *right;
+ } binary;
+ struct {
+ Atom element;
+ Atom field;
+ } field;
+ struct {
+ Atom element;
+ Atom field;
+ struct _Expr *entry;
+ } array;
+ struct {
+ Atom name;
+ struct _Expr *args;
+ } action;
+ struct {
+ int nSyms;
+ int szSyms;
+ KeySym * syms;
+ } list;
+ struct {
+ int x;
+ int y;
+ } coord;
+ struct _Expr *child;
+ Atom str;
+ unsigned uval;
+ int ival;
+ char keyName[5];
+ Opaque ptr;
+ } value;
+} ExprDef;
+
+typedef struct _VarDef {
+ ParseCommon common;
+ unsigned merge;
+ ExprDef *name;
+ ExprDef *value;
+} VarDef;
+
+typedef struct _VModDef {
+ ParseCommon common;
+ unsigned merge;
+ Atom name;
+ ExprDef *value;
+} VModDef;
+
+typedef struct _KeycodeDef {
+ ParseCommon common;
+ unsigned merge;
+ char name[5];
+ ExprDef *value;
+} KeycodeDef;
+
+typedef struct _KeyAliasDef {
+ ParseCommon common;
+ unsigned merge;
+ char alias[5];
+ char real[5];
+} KeyAliasDef;
+
+typedef struct _KeyTypeDef {
+ ParseCommon common;
+ unsigned merge;
+ Atom name;
+ VarDef *body;
+} KeyTypeDef;
+
+typedef struct _SymbolsDef {
+ ParseCommon common;
+ unsigned merge;
+ char keyName[5];
+ ExprDef * symbols;
+} SymbolsDef;
+
+typedef struct _ModMapDef {
+ ParseCommon common;
+ unsigned merge;
+ Atom modifier;
+ ExprDef * keys;
+} ModMapDef;
+
+typedef struct _GroupCompatDef {
+ ParseCommon common;
+ unsigned merge;
+ int group;
+ ExprDef * def;
+} GroupCompatDef;
+
+typedef struct _InterpDef {
+ ParseCommon common;
+ unsigned merge;
+ KeySym sym;
+ ExprDef *match;
+ VarDef *def;
+} InterpDef;
+
+typedef struct _IndicatorMapDef {
+ ParseCommon common;
+ unsigned merge;
+ Atom name;
+ VarDef * body;
+} IndicatorMapDef;
+
+typedef struct _IndicatorNameDef {
+ ParseCommon common;
+ unsigned merge;
+ int ndx;
+ ExprDef * name;
+ Bool virtual;
+} IndicatorNameDef;
+
+typedef struct _OutlineDef {
+ ParseCommon common;
+ Atom field;
+ int nPoints;
+ ExprDef * points;
+} OutlineDef;
+
+typedef struct _ShapeDef {
+ ParseCommon common;
+ unsigned merge;
+ Atom name;
+ int nOutlines;
+ OutlineDef * outlines;
+} ShapeDef;
+
+typedef struct _KeyDef {
+ ParseCommon common;
+ unsigned defined;
+ char * name;
+ ExprDef * expr;
+} KeyDef;
+
+typedef struct _RowDef {
+ ParseCommon common;
+ int nKeys;
+ KeyDef * keys;
+} RowDef;
+
+typedef struct _SectionDef {
+ ParseCommon common;
+ unsigned merge;
+ Atom name;
+ int nRows;
+ RowDef * rows;
+} SectionDef;
+
+typedef struct _OverlayKeyDef {
+ ParseCommon common;
+ char over[5];
+ char under[5];
+} OverlayKeyDef;
+
+typedef struct _OverlayDef {
+ ParseCommon common;
+ unsigned merge;
+ Atom name;
+ int nKeys;
+ OverlayKeyDef * keys;
+} OverlayDef;
+
+typedef struct _DoodadDef {
+ ParseCommon common;
+ unsigned merge;
+ unsigned type;
+ Atom name;
+ VarDef * body;
+} DoodadDef;
+
+typedef struct _XkbFile {
+ ParseCommon common;
+ int type;
+ char * topName;
+ char * name;
+ ParseCommon *defs;
+ int id;
+ unsigned flags;
+ Bool compiled;
+} XkbFile;
+
+_XFUNCPROTOBEGIN
+
+extern Bool CompileKeymap(
+#if NeedFunctionPrototypes
+ XkbFile * /* file */,
+ XkbFileInfo * /* result */,
+ unsigned /* merge */
+#endif
+);
+
+extern Bool CompileKeycodes(
+#if NeedFunctionPrototypes
+ XkbFile * /* file */,
+ XkbFileInfo * /* result */,
+ unsigned /* merge */
+#endif
+);
+
+extern Bool CompileGeometry(
+#if NeedFunctionPrototypes
+ XkbFile * /* file */,
+ XkbFileInfo * /* result */,
+ unsigned /* merge */
+#endif
+);
+
+extern Bool CompileKeyTypes(
+#if NeedFunctionPrototypes
+ XkbFile * /* file */,
+ XkbFileInfo * /* result */,
+ unsigned /* merge */
+#endif
+);
+
+typedef struct _LEDInfo *LEDInfoPtr;
+
+extern Bool CompileCompatMap(
+#if NeedFunctionPrototypes
+ XkbFile * /* file */,
+ XkbFileInfo * /* result */,
+ unsigned /* merge */,
+ LEDInfoPtr * /* unboundLEDs */
+#endif
+);
+
+extern Bool CompileSymbols(
+#if NeedFunctionPrototypes
+ XkbFile * /* file */,
+ XkbFileInfo * /* result */,
+ unsigned /* merge */
+#endif
+);
+
+_XFUNCPROTOEND
+
+#define WantLongListing (1<<0)
+#define WantPartialMaps (1<<1)
+#define WantHiddenMaps (1<<2)
+#define WantFullNames (1<<3)
+#define ListRecursive (1<<4)
+
+extern char * rootDir;
+extern unsigned verboseLevel;
+extern unsigned dirsToStrip;
+
+_XFUNCPROTOBEGIN
+
+extern Bool AddListing(
+#if NeedFunctionPrototypes
+ char * /* file */,
+ char * /* map */
+#endif
+);
+
+extern Bool AddMatchingFiles(
+#if NeedFunctionPrototypes
+ char * /* head_in */
+#endif
+);
+
+extern int AddMapOnly(
+#if NeedFunctionPrototypes
+ char * /* map */
+#endif
+);
+
+extern int GenerateListing(
+#if NeedFunctionPrototypes
+ char * /* filename */
+#endif
+);
+
+_XFUNCPROTOEND
+
+#endif /* XKBCOMP_H */
diff --git a/xkbcomp.man b/xkbcomp.man
new file mode 100644
index 0000000..32bb4ff
--- /dev/null
+++ b/xkbcomp.man
@@ -0,0 +1,97 @@
+.\" $Xorg: xkbcomp.man,v 1.3 2000/08/17 19:54:33 cpqbld Exp $
+.TH XKBCOMP 1 "Release 6.4" "X Version 11"
+.SH NAME
+xkbcomp \- compile XKB keyboard description
+.SH SYNOPSIS
+.B xkbcomp
+[option] source [ destination ]
+.SH DESCRIPTION
+.PP
+The
+.I xkbcomp
+keymap compiler converts a description of an XKB keymap into one of several
+output formats. The most common use for xkbcomp is to create a compiled
+keymap file (.xkm extension) which can be read directly by XKB-capable X
+servers or utilities. The keymap compiler can also produce C header
+files or XKB source files. The C header files produced by xkbcomp can be
+included by X servers or utilities that need a built-in default keymap.
+The XKB source files produced by \fIxkbcomp\fP are fully resolved and can be
+used to verify that the files which typically make up an XKB keymap
+are merged correctly or to create a single file which contains a complete
+description of the keymap.
+.PP
+The \fIsource\fP may specify an X display, or an \fI.xkb\fP or
+\fI.xkm\fP file; unless explicitly specified, the format of \fIdestination\fP
+depends on the format of the source. Compiling a \fI.xkb\fP (keymap source)
+file generates a \fI.xkm\fP (compiled keymap file) by default. If the
+source is a \fI.xkm\fP file or an X display, \fIxkbcomp\fP generates a
+keymap source file by default.
+.PP
+If the \fIdestination\fP is an X display, the keymap for the display
+is updated with the compiled keymap.
+.PP
+The name of the \fIdestination\fP is usually computed from the name
+of the source, with the extension replaced as appropriate. When compiling
+a single map from a file which contains several maps, \fIxkbcom\fP constructs
+the destination file name by appending an appropriate extension to the
+name of the map to be used.
+.SH OPTIONS
+.TP 8
+.B \-a
+Show all keyboard information, reporting implicit or dervied information
+as a comment. Only affects \fI.xkb\fP format output.
+.TP 8
+.B \-C
+Produce a C header file as output (.h extension).
+.TP 8
+.B \-dflts
+Compute defaults for any missing components, such as key names.
+.TP 8
+.B \-I\fIdir\fP
+Specifies top-level directories to be searched for files included by the
+keymap description.
+.TP 8
+.B \-l
+List maps that specify the \fImap\fP pattern in any files listed on the
+command line (not implemented yet).
+.TP 8
+.B \-m\ \fIname\fP
+Specifies a map to be compiled from an file with multiple entries.
+.TP 8
+.B \-merge
+Merge the compiled information with the map from the server (not implemented
+yet).
+.TP 8
+.B \-o\ \fIname\fP
+Specifies a name for the generated output file. The default is the name of
+the source file with an appropriate extension for the output format.
+.TP 8
+.B \-opt\ \fIparts\fP
+Specifies a list of optional parts. Compilation errors in any optional parts
+are not fatal. Parts may consist of any combination of the letters \fIc\fP,
+\fIg\fP,\fIk\fP,\fIs\fP,\fIt\fP which specify the compatibility map, geometry,
+keycodes, symbols and types, respectively.
+.TP 8
+.B -R\fIdir\fP
+Specifies the root directory for relative path names.
+.TP 8
+.B -synch
+Force synchonization for X requests.
+.TP 8
+.B \-w\ \fIlvl\fP
+Controls the reporting of warnings during compilation. A warning level
+of 0 disables all warnings; a warning level of 10 enables them all.
+.TP 8
+.B \-xkb
+Generate a source description of the keyboard as output (.xkb extension).
+.TP 8
+.B \-xkm
+Generate a compiled keymap file as output (.xkm extension).
+.SH "SEE ALSO"
+X(1)
+.SH COPYRIGHT
+Copyright 1994, Silicon Graphics Computer Systems and X Consortium, Inc.
+.br
+See \fIX(1)\fP for a full statement of rights and permissions.
+.SH AUTHOR
+Erik Fortune, Silicon Graphics
diff --git a/xkbparse.y b/xkbparse.y
new file mode 100644
index 0000000..78589f4
--- /dev/null
+++ b/xkbparse.y
@@ -0,0 +1,806 @@
+/* $Xorg: xkbparse.y,v 1.3 2000/08/17 19:54:34 cpqbld Exp $ */
+/************************************************************
+ 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
+ documentation, and that the name of Silicon Graphics not be
+ used in advertising or publicity pertaining to distribution
+ of the software without specific prior written permission.
+ Silicon Graphics makes no representation about the suitability
+ of this software for any purpose. It is provided "as is"
+ without any express or implied warranty.
+
+ SILICON GRAPHICS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS
+ SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+ AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL SILICON
+ 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
+ OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH
+ THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+ ********************************************************/
+%token
+ END_OF_FILE 0
+ ERROR_TOK 255
+ XKB_KEYMAP 1
+ XKB_KEYCODES 2
+ XKB_TYPES 3
+ XKB_SYMBOLS 4
+ XKB_COMPATMAP 5
+ XKB_GEOMETRY 6
+ XKB_SEMANTICS 7
+ XKB_LAYOUT 8
+ INCLUDE 10
+ OVERRIDE 11
+ AUGMENT 12
+ REPLACE 13
+ ALTERNATE 14
+ VIRTUAL_MODS 20
+ TYPE 21
+ INTERPRET 22
+ ACTION_TOK 23
+ KEY 24
+ ALIAS 25
+ GROUP 26
+ MODIFIER_MAP 27
+ INDICATOR 28
+ SHAPE 29
+ KEYS 30
+ ROW 31
+ SECTION 32
+ OVERLAY 33
+ TEXT 34
+ OUTLINE 35
+ SOLID 36
+ LOGO 37
+ VIRTUAL 38
+ EQUALS 40
+ PLUS 41
+ MINUS 42
+ DIVIDE 43
+ TIMES 44
+ OBRACE 45
+ CBRACE 46
+ OPAREN 47
+ CPAREN 48
+ OBRACKET 49
+ CBRACKET 50
+ DOT 51
+ COMMA 52
+ SEMI 53
+ EXCLAM 54
+ INVERT 55
+ STRING 60
+ INTEGER 61
+ FLOAT 62
+ IDENT 63
+ KEYNAME 64
+ PARTIAL 70
+ DEFAULT 71
+ HIDDEN 72
+ ALPHANUMERIC_KEYS 73
+ MODIFIER_KEYS 74
+ KEYPAD_KEYS 75
+ FUNCTION_KEYS 76
+ ALTERNATE_GROUP 77
+%{
+#ifdef DEBUG
+#define YYDEBUG 1
+#endif
+#define DEBUG_VAR parseDebug
+#include "parseutils.h"
+#include <X11/keysym.h>
+#include <X11/extensions/XKBgeom.h>
+
+_XFUNCPROTOBEGIN
+extern int yylex(
+#if NeedFunctionPrototypes
+ void
+#endif
+);
+_XFUNCPROTOEND
+%}
+%right EQUALS
+%left PLUS MINUS
+%left TIMES DIVIDE
+%left EXCLAM INVERT
+%left OPAREN
+%start XkbFile
+%union {
+ int ival;
+ unsigned uval;
+ char *str;
+ Atom sval;
+ ParseCommon *any;
+ ExprDef *expr;
+ VarDef *var;
+ VModDef *vmod;
+ InterpDef *interp;
+ KeyTypeDef *keyType;
+ SymbolsDef *syms;
+ ModMapDef *modMask;
+ GroupCompatDef *groupCompat;
+ IndicatorMapDef *ledMap;
+ IndicatorNameDef *ledName;
+ KeycodeDef *keyName;
+ KeyAliasDef *keyAlias;
+ ShapeDef *shape;
+ SectionDef *section;
+ RowDef *row;
+ KeyDef *key;
+ OverlayDef *overlay;
+ OverlayKeyDef *olKey;
+ OutlineDef *outline;
+ DoodadDef *doodad;
+ XkbFile *file;
+}
+%type <ival> Number Integer Float
+%type <uval> XkbCompositeType FileType MergeMode OptMergeMode KeySym
+%type <uval> DoodadType Flag Flags OptFlags
+%type <str> KeyName MapName OptMapName
+%type <sval> FieldSpec Ident Element String
+%type <any> DeclList Decl
+%type <expr> OptExprList ExprList Expr Term Lhs Terminal ArrayInit
+%type <expr> OptKeySymList KeySymList Action ActionList Coord CoordList
+%type <var> VarDecl VarDeclList SymbolsBody SymbolsVarDecl
+%type <vmod> VModDecl VModDefList VModDef
+%type <interp> InterpretDecl InterpretMatch
+%type <keyType> KeyTypeDecl
+%type <syms> SymbolsDecl
+%type <modMask> ModMapDecl
+%type <groupCompat> GroupCompatDecl
+%type <ledMap> IndicatorMapDecl
+%type <ledName> IndicatorNameDecl
+%type <keyName> KeyNameDecl
+%type <keyAlias> KeyAliasDecl
+%type <shape> ShapeDecl
+%type <section> SectionDecl
+%type <row> SectionBody SectionBodyItem
+%type <key> RowBody RowBodyItem Keys Key
+%type <overlay> OverlayDecl
+%type <olKey> OverlayKeyList OverlayKey
+%type <outline> OutlineList OutlineInList
+%type <doodad> DoodadDecl
+%type <file> XkbFile XkbMapConfigList XkbMapConfig XkbConfig
+%type <file> XkbCompositeMap XkbCompMapList
+%%
+XkbFile : XkbCompMapList
+ { $$= rtrnValue= $1; }
+ | XkbMapConfigList
+ { $$= rtrnValue= $1; }
+ | XkbConfig
+ { $$= rtrnValue= $1; }
+ ;
+
+XkbCompMapList : XkbCompMapList XkbCompositeMap
+ { $$= (XkbFile *)AppendStmt(&$1->common,&$2->common); }
+ | XkbCompositeMap
+ { $$= $1; }
+ ;
+
+XkbCompositeMap : OptFlags XkbCompositeType OptMapName OBRACE
+ XkbMapConfigList
+ CBRACE SEMI
+ { $$= CreateXKBFile($2,$3,&$5->common,$1); }
+ ;
+
+XkbCompositeType: XKB_KEYMAP { $$= XkmKeymapFile; }
+ | XKB_SEMANTICS { $$= XkmSemanticsFile; }
+ | XKB_LAYOUT { $$= XkmLayoutFile; }
+ ;
+
+XkbMapConfigList : XkbMapConfigList XkbMapConfig
+ { $$= (XkbFile *)AppendStmt(&$1->common,&$2->common); }
+ | XkbMapConfig
+ { $$= $1; }
+ ;
+
+XkbMapConfig : OptFlags FileType OptMapName OBRACE
+ DeclList
+ CBRACE SEMI
+ { $$= CreateXKBFile($2,$3,$5,$1); }
+ ;
+
+XkbConfig : OptFlags FileType OptMapName DeclList
+ { $$= CreateXKBFile($2,$3,$4,$1); }
+ ;
+
+
+FileType : XKB_KEYCODES { $$= XkmKeyNamesIndex; }
+ | XKB_TYPES { $$= XkmTypesIndex; }
+ | XKB_COMPATMAP { $$= XkmCompatMapIndex; }
+ | XKB_SYMBOLS { $$= XkmSymbolsIndex; }
+ | XKB_GEOMETRY { $$= XkmGeometryIndex; }
+ ;
+
+OptFlags : Flags { $$= $1; }
+ | { $$= 0; }
+ ;
+
+Flags : Flags Flag { $$= (($1)|($2)); }
+ | Flag { $$= $1; }
+ ;
+
+Flag : PARTIAL { $$= XkbLC_Partial; }
+ | DEFAULT { $$= XkbLC_Default; }
+ | HIDDEN { $$= XkbLC_Hidden; }
+ | ALPHANUMERIC_KEYS { $$= XkbLC_AlphanumericKeys; }
+ | MODIFIER_KEYS { $$= XkbLC_ModifierKeys; }
+ | KEYPAD_KEYS { $$= XkbLC_KeypadKeys; }
+ | FUNCTION_KEYS { $$= XkbLC_FunctionKeys; }
+ | ALTERNATE_GROUP { $$= XkbLC_AlternateGroup; }
+ ;
+
+DeclList : DeclList Decl
+ { $$= AppendStmt($1,$2); }
+ | { $$= NULL; }
+ ;
+
+Decl : OptMergeMode VarDecl
+ {
+ $2->merge= StmtSetMerge(&$2->common,$1);
+ $$= &$2->common;
+ }
+ | OptMergeMode VModDecl
+ {
+ $2->merge= StmtSetMerge(&$2->common,$1);
+ $$= &$2->common;
+ }
+ | OptMergeMode InterpretDecl
+ {
+ $2->merge= StmtSetMerge(&$2->common,$1);
+ $$= &$2->common;
+ }
+ | OptMergeMode KeyNameDecl
+ {
+ $2->merge= StmtSetMerge(&$2->common,$1);
+ $$= &$2->common;
+ }
+ | OptMergeMode KeyAliasDecl
+ {
+ $2->merge= StmtSetMerge(&$2->common,$1);
+ $$= &$2->common;
+ }
+ | OptMergeMode KeyTypeDecl
+ {
+ $2->merge= StmtSetMerge(&$2->common,$1);
+ $$= &$2->common;
+ }
+ | OptMergeMode SymbolsDecl
+ {
+ $2->merge= StmtSetMerge(&$2->common,$1);
+ $$= &$2->common;
+ }
+ | OptMergeMode ModMapDecl
+ {
+ $2->merge= StmtSetMerge(&$2->common,$1);
+ $$= &$2->common;
+ }
+ | OptMergeMode GroupCompatDecl
+ {
+ $2->merge= StmtSetMerge(&$2->common,$1);
+ $$= &$2->common;
+ }
+ | OptMergeMode IndicatorMapDecl
+ {
+ $2->merge= StmtSetMerge(&$2->common,$1);
+ $$= &$2->common;
+ }
+ | OptMergeMode IndicatorNameDecl
+ {
+ $2->merge= StmtSetMerge(&$2->common,$1);
+ $$= &$2->common;
+ }
+ | OptMergeMode ShapeDecl
+ {
+ $2->merge= StmtSetMerge(&$2->common,$1);
+ $$= &$2->common;
+ }
+ | OptMergeMode SectionDecl
+ {
+ $2->merge= StmtSetMerge(&$2->common,$1);
+ $$= &$2->common;
+ }
+ | OptMergeMode DoodadDecl
+ {
+ $2->merge= StmtSetMerge(&$2->common,$1);
+ $$= &$2->common;
+ }
+ | MergeMode STRING
+ {
+ if ($1==MergeAltForm) {
+ yyerror("cannot use 'alternate' to include other maps");
+ $$= &IncludeCreate(scanStr,MergeDefault)->common;
+ }
+ else {
+ $$= &IncludeCreate(scanStr,$1)->common;
+ }
+ }
+ ;
+
+VarDecl : Lhs EQUALS Expr SEMI
+ { $$= VarCreate($1,$3); }
+ | Ident SEMI
+ { $$= BoolVarCreate($1,1); }
+ | EXCLAM Ident SEMI
+ { $$= BoolVarCreate($2,0); }
+ ;
+
+KeyNameDecl : KeyName EQUALS Expr SEMI
+ {
+ KeycodeDef *def;
+
+ def= KeycodeCreate($1,$3);
+ if ($1)
+ free($1);
+ $$= def;
+ }
+ ;
+
+KeyAliasDecl : ALIAS KeyName EQUALS KeyName SEMI
+ {
+ KeyAliasDef *def;
+ def= KeyAliasCreate($2,$4);
+ if ($2) free($2);
+ if ($4) free($4);
+ $$= def;
+ }
+ ;
+
+VModDecl : VIRTUAL_MODS VModDefList SEMI
+ { $$= $2; }
+ ;
+
+VModDefList : VModDefList COMMA VModDef
+ { $$= (VModDef *)AppendStmt(&$1->common,&$3->common); }
+ | VModDef
+ { $$= $1; }
+ ;
+
+VModDef : Ident
+ { $$= VModCreate($1,NULL); }
+ | Ident EQUALS Expr
+ { $$= VModCreate($1,$3); }
+ ;
+
+InterpretDecl : INTERPRET InterpretMatch OBRACE
+ VarDeclList
+ CBRACE SEMI
+ {
+ $2->def= $4;
+ $$= $2;
+ }
+ ;
+
+InterpretMatch : KeySym PLUS Expr
+ { $$= InterpCreate((KeySym)$1,$3); }
+ | KeySym
+ { $$= InterpCreate((KeySym)$1,NULL); }
+ ;
+
+VarDeclList : VarDeclList VarDecl
+ { $$= (VarDef *)AppendStmt(&$1->common,&$2->common); }
+ | VarDecl
+ { $$= $1; }
+ ;
+
+KeyTypeDecl : TYPE String OBRACE
+ VarDeclList
+ CBRACE SEMI
+ { $$= KeyTypeCreate($2,$4); }
+ ;
+
+SymbolsDecl : KEY KeyName OBRACE
+ SymbolsBody
+ CBRACE SEMI
+ { $$= SymbolsCreate($2,(ExprDef *)$4); }
+ ;
+
+SymbolsBody : SymbolsBody COMMA SymbolsVarDecl
+ { $$= (VarDef *)AppendStmt(&$1->common,&$3->common); }
+ | SymbolsVarDecl
+ { $$= $1; }
+ ;
+
+SymbolsVarDecl : Lhs EQUALS Expr
+ { $$= VarCreate($1,$3); }
+ | Lhs EQUALS ArrayInit
+ { $$= VarCreate($1,$3); }
+ | Ident
+ { $$= BoolVarCreate($1,1); }
+ | EXCLAM Ident
+ { $$= BoolVarCreate($2,0); }
+ | ArrayInit
+ { $$= VarCreate(NULL,$1); }
+ ;
+
+ArrayInit : OBRACKET OptKeySymList CBRACKET
+ { $$= $2; }
+ | OBRACKET ActionList CBRACKET
+ { $$= ExprCreateUnary(ExprActionList,TypeAction,$2); }
+ ;
+
+GroupCompatDecl : GROUP Integer EQUALS Expr SEMI
+ { $$= GroupCompatCreate($2,$4); }
+ ;
+
+ModMapDecl : MODIFIER_MAP Ident OBRACE ExprList CBRACE SEMI
+ { $$= ModMapCreate($2,$4); }
+ ;
+
+IndicatorMapDecl: INDICATOR String OBRACE VarDeclList CBRACE SEMI
+ { $$= IndicatorMapCreate($2,$4); }
+ ;
+
+IndicatorNameDecl: INDICATOR Integer EQUALS Expr SEMI
+ { $$= IndicatorNameCreate($2,$4,False); }
+ | VIRTUAL INDICATOR Integer EQUALS Expr SEMI
+ { $$= IndicatorNameCreate($3,$5,True); }
+ ;
+
+ShapeDecl : SHAPE String OBRACE OutlineList CBRACE SEMI
+ { $$= ShapeDeclCreate($2,(OutlineDef *)&$4->common); }
+ ;
+ | SHAPE String OBRACE CoordList CBRACE SEMI
+ {
+ OutlineDef *outlines;
+ outlines= OutlineCreate(None,$4);
+ $$= ShapeDeclCreate($2,outlines);
+ }
+ ;
+
+SectionDecl : SECTION String OBRACE SectionBody CBRACE SEMI
+ { $$= SectionDeclCreate($2,$4); }
+ ;
+
+SectionBody : SectionBody SectionBodyItem
+ { $$=(RowDef *)AppendStmt(&$1->common,&$2->common);}
+ | SectionBodyItem
+ { $$= $1; }
+ ;
+
+SectionBodyItem : ROW OBRACE RowBody CBRACE SEMI
+ { $$= RowDeclCreate($3); }
+ | VarDecl
+ { $$= (RowDef *)$1; }
+ | DoodadDecl
+ { $$= (RowDef *)$1; }
+ | IndicatorMapDecl
+ { $$= (RowDef *)$1; }
+ | OverlayDecl
+ { $$= (RowDef *)$1; }
+ ;
+
+RowBody : RowBody RowBodyItem
+ { $$=(KeyDef *)AppendStmt(&$1->common,&$2->common);}
+ | RowBodyItem
+ { $$= $1; }
+ ;
+
+RowBodyItem : KEYS OBRACE Keys CBRACE SEMI
+ { $$= $3; }
+ | VarDecl
+ { $$= (KeyDef *)$1; }
+ ;
+
+Keys : Keys COMMA Key
+ { $$=(KeyDef *)AppendStmt(&$1->common,&$3->common);}
+ | Key
+ { $$= $1; }
+ ;
+
+Key : KeyName
+ { $$= KeyDeclCreate($1,NULL); }
+ | OBRACE ExprList CBRACE
+ { $$= KeyDeclCreate(NULL,$2); }
+ ;
+
+OverlayDecl : OVERLAY String OBRACE OverlayKeyList CBRACE SEMI
+ { $$= OverlayDeclCreate($2,$4); }
+ ;
+
+OverlayKeyList : OverlayKeyList COMMA OverlayKey
+ {
+ $$= (OverlayKeyDef *)
+ AppendStmt(&$1->common,&$3->common);
+ };
+ | OverlayKey
+ { $$= $1; }
+ ;
+
+OverlayKey : KeyName EQUALS KeyName
+ { $$= OverlayKeyCreate($1,$3); }
+ ;
+
+OutlineList : OutlineList COMMA OutlineInList
+ { $$=(OutlineDef *)AppendStmt(&$1->common,&$3->common);}
+ | OutlineInList
+ { $$= $1; }
+ ;
+
+OutlineInList : OBRACE CoordList CBRACE
+ { $$= OutlineCreate(None,$2); }
+ | Ident EQUALS OBRACE CoordList CBRACE
+ { $$= OutlineCreate($1,$4); }
+ | Ident EQUALS Expr
+ { $$= OutlineCreate($1,$3); }
+ ;
+
+CoordList : CoordList COMMA Coord
+ { $$= (ExprDef *)AppendStmt(&$1->common,&$3->common); }
+ | Coord
+ { $$= $1; }
+ ;
+
+Coord : OBRACKET Number COMMA Number CBRACKET
+ {
+ ExprDef *expr;
+ expr= ExprCreate(ExprCoord,TypeUnknown);
+ expr->value.coord.x= $2;
+ expr->value.coord.y= $4;
+ $$= expr;
+ }
+ ;
+
+DoodadDecl : DoodadType String OBRACE VarDeclList CBRACE SEMI
+ { $$= DoodadCreate($1,$2,$4); }
+ ;
+
+DoodadType : TEXT { $$= XkbTextDoodad; }
+ | OUTLINE { $$= XkbOutlineDoodad; }
+ | SOLID { $$= XkbSolidDoodad; }
+ | LOGO { $$= XkbLogoDoodad; }
+ ;
+
+FieldSpec : Ident { $$= $1; }
+ | Element { $$= $1; }
+ ;
+
+Element : ACTION_TOK
+ { $$= XkbInternAtom(NULL,"action",False); }
+ | INTERPRET
+ { $$= XkbInternAtom(NULL,"interpret",False); }
+ | TYPE
+ { $$= XkbInternAtom(NULL,"type",False); }
+ | KEY
+ { $$= XkbInternAtom(NULL,"key",False); }
+ | GROUP
+ { $$= XkbInternAtom(NULL,"group",False); }
+ | MODIFIER_MAP
+ {$$=XkbInternAtom(NULL,"modifier_map",False);}
+ | INDICATOR
+ { $$= XkbInternAtom(NULL,"indicator",False); }
+ | SHAPE
+ { $$= XkbInternAtom(NULL,"shape",False); }
+ | ROW
+ { $$= XkbInternAtom(NULL,"row",False); }
+ | SECTION
+ { $$= XkbInternAtom(NULL,"section",False); }
+ | TEXT
+ { $$= XkbInternAtom(NULL,"text",False); }
+ ;
+
+OptMergeMode : MergeMode { $$= $1; }
+ | { $$= MergeDefault; }
+ ;
+
+MergeMode : INCLUDE { $$= MergeDefault; }
+ | AUGMENT { $$= MergeAugment; }
+ | OVERRIDE { $$= MergeOverride; }
+ | REPLACE { $$= MergeReplace; }
+ | ALTERNATE { $$= MergeAltForm; }
+ ;
+
+OptExprList : ExprList { $$= $1; }
+ | { $$= NULL; }
+ ;
+
+ExprList : ExprList COMMA Expr
+ { $$= (ExprDef *)AppendStmt(&$1->common,&$3->common); }
+ | Expr
+ { $$= $1; }
+ ;
+
+Expr : Expr DIVIDE Expr
+ { $$= ExprCreateBinary(OpDivide,$1,$3); }
+ | Expr PLUS Expr
+ { $$= ExprCreateBinary(OpAdd,$1,$3); }
+ | Expr MINUS Expr
+ { $$= ExprCreateBinary(OpSubtract,$1,$3); }
+ | Expr TIMES Expr
+ { $$= ExprCreateBinary(OpMultiply,$1,$3); }
+ | Lhs EQUALS Expr
+ { $$= ExprCreateBinary(OpAssign,$1,$3); }
+ | Term
+ { $$= $1; }
+ ;
+
+Term : MINUS Term
+ { $$= ExprCreateUnary(OpNegate,$2->type,$2); }
+ | PLUS Term
+ { $$= ExprCreateUnary(OpUnaryPlus,$2->type,$2); }
+ | EXCLAM Term
+ { $$= ExprCreateUnary(OpNot,TypeBoolean,$2); }
+ | INVERT Term
+ { $$= ExprCreateUnary(OpInvert,$2->type,$2); }
+ | Lhs
+ { $$= $1; }
+ | FieldSpec OPAREN OptExprList CPAREN %prec OPAREN
+ { $$= ActionCreate($1,$3); }
+ | Terminal
+ { $$= $1; }
+ | OPAREN Expr CPAREN
+ { $$= $2; }
+ ;
+
+ActionList : ActionList COMMA Action
+ { $$= (ExprDef *)AppendStmt(&$1->common,&$3->common); }
+ | Action
+ { $$= $1; }
+ ;
+
+Action : FieldSpec OPAREN OptExprList CPAREN
+ { $$= ActionCreate($1,$3); }
+ ;
+
+Lhs : FieldSpec
+ {
+ ExprDef *expr;
+ expr= ExprCreate(ExprIdent,TypeUnknown);
+ expr->value.str= $1;
+ $$= expr;
+ }
+ | FieldSpec DOT FieldSpec
+ {
+ ExprDef *expr;
+ expr= ExprCreate(ExprFieldRef,TypeUnknown);
+ expr->value.field.element= $1;
+ expr->value.field.field= $3;
+ $$= expr;
+ }
+ | FieldSpec OBRACKET Expr CBRACKET
+ {
+ ExprDef *expr;
+ expr= ExprCreate(ExprArrayRef,TypeUnknown);
+ expr->value.array.element= None;
+ expr->value.array.field= $1;
+ expr->value.array.entry= $3;
+ $$= expr;
+ }
+ | FieldSpec DOT FieldSpec OBRACKET Expr CBRACKET
+ {
+ ExprDef *expr;
+ expr= ExprCreate(ExprArrayRef,TypeUnknown);
+ expr->value.array.element= $1;
+ expr->value.array.field= $3;
+ expr->value.array.entry= $5;
+ $$= expr;
+ }
+ ;
+
+Terminal : String
+ {
+ ExprDef *expr;
+ expr= ExprCreate(ExprValue,TypeString);
+ expr->value.str= $1;
+ $$= expr;
+ }
+ | Integer
+ {
+ ExprDef *expr;
+ expr= ExprCreate(ExprValue,TypeInt);
+ expr->value.ival= $1;
+ $$= expr;
+ }
+ | Float
+ {
+ ExprDef *expr;
+ expr= ExprCreate(ExprValue,TypeFloat);
+ expr->value.ival= $1;
+ $$= expr;
+ }
+ | KeyName
+ {
+ ExprDef *expr;
+ expr= ExprCreate(ExprValue,TypeKeyName);
+ memcpy(expr->value.keyName,$1,4);
+ free($1);
+ $$= expr;
+ }
+ ;
+
+OptKeySymList : KeySymList { $$= $1; }
+ | { $$= NULL; }
+ ;
+
+KeySymList : KeySymList COMMA KeySym
+ { $$= AppendKeysymList($1,(KeySym)$3); }
+ | KeySym
+ { $$= CreateKeysymList((KeySym)$1); }
+ ;
+
+KeySym : IDENT
+ {
+ KeySym sym;
+ if (LookupKeysym(scanStr,&sym))
+ $$= sym;
+ else {
+ char buf[120];
+ sprintf(buf,"expected keysym, got %s",
+ uStringText(scanStr));
+ yyerror(buf);
+ yynerrs++;
+ $$= NoSymbol;
+ }
+ }
+ | SECTION
+ {
+ $$= XK_section;
+ }
+ | Integer
+ {
+ if ($1<10) $$= $1+'0'; /* XK_0 .. XK_9 */
+ else $$= $1;
+ }
+ ;
+
+Number : FLOAT { $$= scanInt; }
+ | INTEGER { $$= scanInt*XkbGeomPtsPerMM; }
+ ;
+
+Float : FLOAT { $$= scanInt; }
+ ;
+
+Integer : INTEGER { $$= scanInt; }
+ ;
+
+KeyName : KEYNAME { $$= scanStr; scanStr= NULL; }
+ ;
+
+Ident : IDENT { $$= XkbInternAtom(NULL,scanStr,False); }
+ | DEFAULT { $$= XkbInternAtom(NULL,"default",False); }
+ ;
+
+String : STRING { $$= XkbInternAtom(NULL,scanStr,False); }
+ ;
+
+OptMapName : MapName { $$= $1; }
+ | { $$= NULL; }
+ ;
+
+MapName : STRING { $$= scanStr; scanStr= NULL; }
+ ;
+%%
+void
+#if NeedFunctionPrototypes
+yyerror(char *s)
+#else
+yyerror(s)
+char *s;
+#endif
+{
+ if (warningLevel>0) {
+ (void)fprintf(stderr,"%s: line %d of %s\n",s,lineNum,
+ (scanFile?scanFile:"(unknown)"));
+ if ((scanStr)&&(warningLevel>3))
+ (void)fprintf(stderr,"last scanned symbol is: %s\n",scanStr);
+ }
+ return;
+}
+
+
+int
+#if NeedFunctionPrototypes
+yywrap(void)
+#else
+yywrap()
+#endif
+{
+ return 1;
+}
+
diff --git a/xkbpath.c b/xkbpath.c
new file mode 100644
index 0000000..8e21a7b
--- /dev/null
+++ b/xkbpath.c
@@ -0,0 +1,359 @@
+/* $Xorg: xkbpath.c,v 1.3 2000/08/17 19:54:34 cpqbld Exp $ */
+/************************************************************
+ 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
+ documentation, and that the name of Silicon Graphics not be
+ used in advertising or publicity pertaining to distribution
+ of the software without specific prior written permission.
+ Silicon Graphics makes no representation about the suitability
+ of this software for any purpose. It is provided "as is"
+ without any express or implied warranty.
+
+ SILICON GRAPHICS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS
+ SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+ AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL SILICON
+ 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
+ OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH
+ THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+ ********************************************************/
+
+#include <X11/Xlib.h>
+#include <X11/XKBlib.h>
+
+#define DEBUG_VAR_NOT_LOCAL
+#define DEBUG_VAR debugFlags
+#include "utils.h"
+#ifndef X_NOT_STDC_ENV
+#include <stdlib.h>
+#endif
+#include <X11/extensions/XKM.h>
+#include "xkbpath.h"
+
+#ifndef DFLT_XKB_CONFIG_ROOT
+#define DFLT_XKB_CONFIG_ROOT "/usr/lib/X11/xkb"
+#endif
+
+#ifndef PATH_MAX
+#define PATH_MAX 1024
+#endif
+
+#define PATH_CHUNK 8
+
+static int longestPath;
+static int szPath;
+static int nPathEntries;
+static char ** includePath;
+
+Bool
+#if NeedFunctionPrototypes
+XkbParseIncludeMap(char **str_inout,char **file_rtrn,char **map_rtrn,
+ char *nextop_rtrn)
+#else
+XkbParseIncludeMap(str_inout,file_rtrn,map_rtrn,nextop_rtrn)
+ char ** str_inout;
+ char ** file_rtrn;
+ char ** map_rtrn;
+ char * nextop_rtrn;
+#endif
+{
+char *tmp,*str,*next;
+
+ str= *str_inout;
+ if ((*str=='+')||(*str=='|')) {
+ *file_rtrn= *map_rtrn= NULL;
+ *nextop_rtrn= *str;
+ next= str+1;
+ }
+ else if (*str=='%') {
+ *file_rtrn= *map_rtrn= NULL;
+ *nextop_rtrn= str[1];
+ next= str+2;
+ }
+ else {
+ next= strpbrk(str,"|+");
+ if (next) {
+ *nextop_rtrn= *next;
+ *next++= '\0';
+ }
+ else {
+ *nextop_rtrn= '\0';
+ next= NULL;
+ }
+ tmp= strchr(str,'(');
+ if (tmp==NULL) {
+ *file_rtrn= uStringDup(str);
+ *map_rtrn= NULL;
+ }
+ else if (str[0]=='(') {
+ return False;
+ }
+ else {
+ *tmp++= '\0';
+ *file_rtrn= uStringDup(str);
+ str= tmp;
+ tmp= strchr(str,')');
+ if ((tmp==NULL)||(tmp[1]!='\0')) {
+ uFree(*file_rtrn);
+ return False;
+ }
+ *tmp++= '\0';
+ *map_rtrn= uStringDup(str);
+ }
+ }
+ if (*nextop_rtrn=='\0')
+ *str_inout= NULL;
+ else if ((*nextop_rtrn=='|')||(*nextop_rtrn=='+'))
+ *str_inout= next;
+ else return False;
+ return True;
+}
+
+Bool
+#if NeedFunctionPrototypes
+XkbInitIncludePath(void)
+#else
+XkbInitIncludePath()
+#endif
+{
+ szPath= PATH_CHUNK;
+ includePath= (char **)calloc(szPath,sizeof(char *));
+ if (includePath==NULL)
+ return False;
+ XkbAddDirectoryToPath(".");
+ XkbAddDirectoryToPath(DFLT_XKB_CONFIG_ROOT);
+ return True;
+}
+
+void
+#if NeedFunctionPrototypes
+XkbClearIncludePath(void)
+#else
+XkbClearIncludePath()
+#endif
+{
+register int i;
+
+ if (szPath>0) {
+ for (i=0;i<nPathEntries;i++) {
+ if (includePath[i]!=NULL) {
+ uFree(includePath[i]);
+ includePath[i]= NULL;
+ }
+ }
+ nPathEntries= 0;
+ longestPath= 0;
+ }
+ return;
+}
+
+Bool
+#if NeedFunctionPrototypes
+XkbAddDirectoryToPath(char *dir)
+#else
+XkbAddDirectoryToPath(dir)
+ char *dir;
+#endif
+{
+int len;
+ if ((dir==NULL)||(dir[0]=='\0')) {
+ XkbClearIncludePath();
+ return True;
+ }
+ len= strlen(dir);
+ if (len+2>=PATH_MAX) { /* allow for '/' and at least one character */
+ ERROR2("Path entry (%s) too long (maxiumum length is %d)\n",
+ dir,PATH_MAX-3);
+ return False;
+ }
+ if (len>longestPath)
+ longestPath= len;
+ if (nPathEntries>=szPath) {
+ szPath+= PATH_CHUNK;
+ includePath= (char **)realloc(includePath,szPath*sizeof(char *));
+ if (includePath==NULL) {
+ WSGO("Allocation failed (includePath)\n");
+ return False;
+ }
+ }
+ includePath[nPathEntries]= (char *)calloc(strlen(dir)+1,sizeof(char));
+ if (includePath[nPathEntries]==NULL) {
+ WSGO1("Allocation failed (includePath[%d])\n",nPathEntries);
+ return False;
+ }
+ strcpy(includePath[nPathEntries++],dir);
+ return True;
+}
+
+/***====================================================================***/
+
+char *
+#if NeedFunctionPrototypes
+XkbDirectoryForInclude(unsigned type)
+#else
+XkbDirectoryForInclude(type)
+ unsigned type;
+#endif
+{
+static char buf[32];
+
+ switch (type) {
+ case XkmSemanticsFile:
+ strcpy(buf,"semantics");
+ break;
+ case XkmLayoutFile:
+ strcpy(buf,"layout");
+ break;
+ case XkmKeymapFile:
+ strcpy(buf,"keymap");
+ break;
+ case XkmKeyNamesIndex:
+ strcpy(buf,"keycodes");
+ break;
+ case XkmTypesIndex:
+ strcpy(buf,"types");
+ break;
+ case XkmSymbolsIndex:
+ strcpy(buf,"symbols");
+ break;
+ case XkmCompatMapIndex:
+ strcpy(buf,"compat");
+ break;
+ case XkmGeometryFile:
+ case XkmGeometryIndex:
+ strcpy(buf,"geometry");
+ break;
+ default:
+ strcpy(buf,"");
+ break;
+ }
+ return buf;
+}
+
+/***====================================================================***/
+
+typedef struct _FileCacheEntry {
+ char * name;
+ unsigned type;
+ char * path;
+ void * data;
+ struct _FileCacheEntry * next;
+} FileCacheEntry;
+static FileCacheEntry *fileCache;
+
+void *
+#if NeedFunctionPrototypes
+XkbAddFileToCache(char *name,unsigned type,char *path,void *data)
+#else
+XkbAddFileToCache(name,type,path,data)
+ char * name;
+ unsigned type;
+ char * path;
+ void * data;
+#endif
+{
+FileCacheEntry *entry;
+
+ for (entry=fileCache;entry!=NULL;entry=entry->next) {
+ if ((type==entry->type)&&(uStringEqual(name,entry->name))) {
+ void *old= entry->data;
+ WSGO2("Replacing file cache entry (%s/%d)\n",name,type);
+ entry->path= path;
+ entry->data= data;
+ return old;
+ }
+ }
+ entry= uTypedAlloc(FileCacheEntry);
+ if (entry!=NULL) {
+ entry->name= name;
+ entry->type= type;
+ entry->path= path;
+ entry->data= data;
+ entry->next= fileCache;
+ fileCache= entry;
+ }
+ return NULL;
+}
+
+void *
+#if NeedFunctionPrototypes
+XkbFindFileInCache(char *name,unsigned type,char **pathRtrn)
+#else
+XkbFindFileInCache(name,type,pathRtrn)
+ char * name;
+ unsigned type;
+ char ** pathRtrn;
+#endif
+{
+FileCacheEntry *entry;
+
+ for (entry=fileCache;entry!=NULL;entry=entry->next) {
+ if ((type==entry->type)&&(uStringEqual(name,entry->name))) {
+ *pathRtrn= entry->path;
+ return entry->data;
+ }
+ }
+ return NULL;
+}
+
+/***====================================================================***/
+
+FILE *
+#if NeedFunctionPrototypes
+XkbFindFileInPath(char *name,unsigned type,char **pathRtrn)
+#else
+XkbFindFileInPath(name,type,pathRtrn)
+ char * name;
+ unsigned type;
+ char ** pathRtrn;
+#endif
+{
+register int i;
+FILE *file= NULL;
+int nameLen,typeLen,pathLen;
+char buf[PATH_MAX],*typeDir;
+
+ typeDir= XkbDirectoryForInclude(type);
+ nameLen= strlen(name);
+ typeLen= strlen(typeDir);
+ for (i=0;i<nPathEntries;i++) {
+ pathLen= strlen(includePath[i]);
+ if ((nameLen+pathLen+1)>=PATH_MAX) {
+ ERROR2("File name (%s/%s) too long\n",includePath[i],name);
+ ACTION("Ignored\n");
+ continue;
+ }
+ sprintf(buf,"%s/%s",includePath[i],name);
+ file= fopen(buf,"r");
+ if (file!=NULL)
+ break;
+ else if (typeLen<1)
+ continue;
+
+ if ((nameLen+typeLen+pathLen+2)>=PATH_MAX) {
+ ERROR3("File name (%s/%s/%s) too long\n",includePath[i],typeDir,
+ name);
+ ACTION("Ignored\n");
+ continue;
+ }
+ sprintf(buf,"%s/%s/%s",includePath[i],typeDir,name);
+ file= fopen(buf,"r");
+ if (file!=NULL)
+ break;
+ }
+
+ if ((file!=NULL)&&(pathRtrn!=NULL)) {
+ *pathRtrn= (char *)calloc(strlen(buf)+1,sizeof(char));
+ if (*pathRtrn!=NULL)
+ strcpy(*pathRtrn,buf);
+ }
+ return file;
+}
+
diff --git a/xkbpath.h b/xkbpath.h
new file mode 100644
index 0000000..c12a2ad
--- /dev/null
+++ b/xkbpath.h
@@ -0,0 +1,89 @@
+/* $XConsortium $ */
+/************************************************************
+ 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
+ documentation, and that the name of Silicon Graphics not be
+ used in advertising or publicity pertaining to distribution
+ of the software without specific prior written permission.
+ Silicon Graphics makes no representation about the suitability
+ of this software for any purpose. It is provided "as is"
+ without any express or implied warranty.
+
+ SILICON GRAPHICS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS
+ SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+ AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL SILICON
+ 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
+ OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH
+ THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+ ********************************************************/
+
+#ifndef _XKBPATH_H_
+#define _XKBPATH_H_ 1
+
+extern Bool XkbInitIncludePath(
+#if NeedFunctionPrototypes
+ void
+#endif
+);
+
+extern void XkbClearIncludePath(
+#if NeedFunctionPrototypes
+ void
+#endif
+);
+
+extern Bool XkbAddDirectoryToPath(
+#if NeedFunctionPrototypes
+ char * /* dir */
+#endif
+);
+
+extern char * XkbDirectoryForInclude(
+#if NeedFunctionPrototypes
+ unsigned /* type */
+#endif
+);
+
+extern FILE *XkbFindFileInPath(
+#if NeedFunctionPrototypes
+ char * /* name */,
+ unsigned /* type */,
+ char ** /* pathRtrn */
+#endif
+);
+
+extern void * XkbAddFileToCache(
+#if NeedFunctionPrototypes
+ char * /* name */,
+ unsigned /* type */,
+ char * /* path */,
+ void * /* data */
+#endif
+);
+
+extern void * XkbFindFileInCache(
+#if NeedFunctionPrototypes
+ char * /* name */,
+ unsigned /* type */,
+ char ** /* pathRtrn */
+#endif
+);
+
+extern Bool XkbParseIncludeMap(
+#if NeedFunctionPrototypes
+ char ** /* str_inout */,
+ char ** /* file_rtrn */,
+ char ** /* map_rtrn */,
+ char * /* nextop_rtrn */
+#endif
+);
+
+#endif /* _XKBPATH_H_ */
diff --git a/xkbscan.c b/xkbscan.c
new file mode 100644
index 0000000..9cda90d
--- /dev/null
+++ b/xkbscan.c
@@ -0,0 +1,496 @@
+/* $Xorg: xkbscan.c,v 1.3 2000/08/17 19:54:34 cpqbld Exp $ */
+/************************************************************
+ 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
+ documentation, and that the name of Silicon Graphics not be
+ used in advertising or publicity pertaining to distribution
+ of the software without specific prior written permission.
+ Silicon Graphics makes no representation about the suitability
+ of this software for any purpose. It is provided "as is"
+ without any express or implied warranty.
+
+ SILICON GRAPHICS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS
+ SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+ AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL SILICON
+ 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
+ OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH
+ THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+ ********************************************************/
+
+#include <stdio.h>
+#include <ctype.h>
+#include <X11/Xos.h>
+#include <X11/Xlib.h>
+#include <X11/XKBlib.h>
+
+#include "tokens.h"
+#define DEBUG_VAR scanDebug
+#include "utils.h"
+
+FILE *yyin = stdin;
+
+static char scanFileBuf[1024];
+char * scanFile= scanFileBuf;
+int lineNum= 0;
+
+int scanInt;
+char *scanIntStr;
+int scanIntClass;
+
+char *scanStr = NULL;
+int scanStrLine= 0;
+
+#define BUFSIZE 512
+static int nInBuf = 0;
+static char buf[BUFSIZE];
+
+#ifdef DEBUG
+
+extern unsigned debugFlags;
+
+static char *
+#if NeedFunctionPrototypes
+tokText(int tok)
+#else
+tokText(tok)
+ int tok;
+#endif
+{
+static char buf[32];
+
+ switch (tok) {
+ case END_OF_FILE: sprintf(buf, "END_OF_FILE");break;
+ case ERROR_TOK: sprintf(buf, "ERROR"); break;
+
+ case XKB_KEYMAP: sprintf(buf, "XKB_KEYMAP"); break;
+ case XKB_KEYCODES: sprintf(buf, "XKB_KEYCODES"); break;
+ case XKB_TYPES: sprintf(buf, "XKB_TYPES"); break;
+ case XKB_SYMBOLS: sprintf(buf, "XKB_SYMBOLS"); break;
+ case XKB_COMPATMAP: sprintf(buf, "XKB_COMPATMAP"); break;
+ case XKB_GEOMETRY: sprintf(buf, "XKB_GEOMETRY"); break;
+ case XKB_SEMANTICS: sprintf(buf, "XKB_SEMANTICS"); break;
+ case XKB_LAYOUT: sprintf(buf, "XKB_LAYOUT"); break;
+
+ case INCLUDE: sprintf(buf, "INCLUDE"); break;
+ case OVERRIDE: sprintf(buf, "OVERRIDE"); break;
+ case AUGMENT: sprintf(buf, "AUGMENT"); break;
+ case REPLACE: sprintf(buf, "REPLACE"); break;
+ case ALTERNATE: sprintf(buf, "ALTERNATE"); break;
+
+ case VIRTUAL_MODS: sprintf(buf, "VIRTUAL_MODS"); break;
+ case TYPE: sprintf(buf, "TYPE"); break;
+ case INTERPRET: sprintf(buf, "INTERPRET"); break;
+ case ACTION_TOK: sprintf(buf, "ACTION"); break;
+ case KEY: sprintf(buf, "KEY"); break;
+ case ALIAS: sprintf(buf, "ALIAS"); break;
+ case GROUP: sprintf(buf, "GROUP"); break;
+ case MODIFIER_MAP: sprintf(buf, "MODIFIER_MAP"); break;
+ case INDICATOR: sprintf(buf, "INDICATOR"); break;
+ case SHAPE: sprintf(buf, "SHAPE"); break;
+ case KEYS: sprintf(buf, "KEYS"); break;
+ case ROW: sprintf(buf, "ROW"); break;
+ case SECTION: sprintf(buf, "SECTION"); break;
+ case OVERLAY: sprintf(buf, "OVERLAY"); break;
+ case TEXT: sprintf(buf, "TEXT"); break;
+ case OUTLINE: sprintf(buf, "OUTLINE"); break;
+ case SOLID: sprintf(buf, "SOLID"); break;
+ case LOGO: sprintf(buf, "LOGO"); break;
+ case VIRTUAL: sprintf(buf, "VIRTUAL"); break;
+
+ case EQUALS: sprintf(buf, "EQUALS"); break;
+ case PLUS: sprintf(buf, "PLUS"); break;
+ case MINUS: sprintf(buf, "MINUS"); break;
+ case DIVIDE: sprintf(buf, "DIVIDE"); break;
+ case TIMES: sprintf(buf, "TIMES"); break;
+ case OBRACE: sprintf(buf, "OBRACE"); break;
+ case CBRACE: sprintf(buf, "CBRACE"); break;
+ case OPAREN: sprintf(buf, "OPAREN"); break;
+ case CPAREN: sprintf(buf, "CPAREN"); break;
+ case OBRACKET: sprintf(buf, "OBRACKET");break;
+ case CBRACKET: sprintf(buf, "CBRACKET");break;
+ case DOT: sprintf(buf, "DOT"); break;
+ case COMMA: sprintf(buf, "COMMA"); break;
+ case SEMI: sprintf(buf, "SEMI"); break;
+ case EXCLAM: sprintf(buf, "EXCLAM"); break;
+ case INVERT: sprintf(buf, "INVERT"); break;
+
+ case STRING: sprintf(buf, "STRING (%s)",scanStr); break;
+ case INTEGER: sprintf(buf, "INTEGER (0x%x)",scanInt); break;
+ case FLOAT: sprintf(buf, "FLOAT (%d.%d)",
+ scanInt/XkbGeomPtsPerMM,
+ scanInt%XkbGeomPtsPerMM);break;
+ case IDENT: sprintf(buf, "IDENT (%s)",scanStr); break;
+ case KEYNAME: sprintf(buf, "KEYNAME (%s)",scanStr); break;
+
+ case PARTIAL: sprintf(buf, "PARTIAL"); break;
+ case DEFAULT: sprintf(buf, "DEFAULT"); break;
+ case HIDDEN: sprintf(buf, "HIDDEN"); break;
+
+ case ALPHANUMERIC_KEYS: sprintf(buf, "ALPHANUMERIC_KEYS"); break;
+ case MODIFIER_KEYS: sprintf(buf, "MODIFIER_KEYS"); break;
+ case KEYPAD_KEYS: sprintf(buf, "KEYPAD_KEYS"); break;
+ case FUNCTION_KEYS: sprintf(buf, "FUNCTION_KEYS"); break;
+ case ALTERNATE_GROUP: sprintf(buf, "ALTERNATE_GROUP"); break;
+
+ default: sprintf(buf, "UNKNOWN"); break;
+ }
+ return buf;
+}
+#endif
+
+int
+#if NeedFunctionPrototypes
+setScanState(char *file,int line)
+#else
+setScanState(file,line)
+ char * file;
+ int line;
+#endif
+{
+ if (file!=NULL)
+ strncpy(scanFile,file,1024);
+ if (line>=0)
+ lineNum= line;
+ return 1;
+}
+
+int
+#if NeedFunctionPrototypes
+yyGetString(void)
+#else
+yyGetString()
+#endif
+{
+int ch;
+
+ nInBuf = 0;
+ while ( ((ch=getc(yyin))!=EOF) && (ch!='"') ) {
+ if ( ch == '\\' ) {
+ if ((ch = getc(yyin))!=EOF) {
+ if ( ch=='n' ) ch = '\n';
+ else if ( ch == 't' ) ch = '\t';
+ else if ( ch == 'v' ) ch = '\v';
+ else if ( ch == 'b' ) ch = '\b';
+ else if ( ch == 'r' ) ch = '\r';
+ else if ( ch == 'f' ) ch = '\f';
+ else if ( ch == 'e' ) ch = '\033';
+ else if ( ch == '0' ) {
+ int tmp,stop;
+ ch = stop = 0;
+ if (((tmp=getc(yyin))!=EOF) && (isdigit(tmp)) &&
+ (tmp!='8') && (tmp!='9')) {
+ ch= (ch*8)+(tmp-'0');
+ }
+ else {
+ stop= 1;
+ ungetc(tmp,yyin);
+ }
+ if ((!stop) && ((tmp=getc(yyin))!=EOF) && (isdigit(tmp)) &&
+ (tmp!='8') && (tmp!='9')) {
+ ch= (ch*8)+(tmp-'0');
+ }
+ else {
+ stop= 1;
+ ungetc(tmp,yyin);
+ }
+ if ((!stop) && ((tmp=getc(yyin))!=EOF) && (isdigit(tmp)) &&
+ (tmp!='8') && (tmp!='9')) {
+ ch= (ch*8)+(tmp-'0');
+ }
+ else {
+ stop= 1;
+ ungetc(tmp,yyin);
+ }
+ }
+ }
+ else return ERROR_TOK;
+ }
+
+ if ( nInBuf < BUFSIZE-1 )
+ buf[nInBuf++] = ch;
+ }
+ if ( ch == '"' ) {
+ buf[nInBuf++] = '\0';
+ if ( scanStr )
+ uFree( scanStr );
+ scanStr = (char *)uStringDup(buf);
+ scanStrLine = lineNum;
+ return STRING;
+ }
+ return ERROR_TOK;
+}
+
+int
+#if NeedFunctionPrototypes
+yyGetKeyName(void)
+#else
+yyGetKeyName()
+#endif
+{
+int ch;
+
+ nInBuf = 0;
+ while ( ((ch=getc(yyin))!=EOF) && (ch!='>') ) {
+ if ( ch == '\\' ) {
+ if ((ch = getc(yyin))!=EOF) {
+ if ( ch=='n' ) ch = '\n';
+ else if ( ch == 't' ) ch = '\t';
+ else if ( ch == 'v' ) ch = '\v';
+ else if ( ch == 'b' ) ch = '\b';
+ else if ( ch == 'r' ) ch = '\r';
+ else if ( ch == 'f' ) ch = '\f';
+ else if ( ch == 'e' ) ch = '\033';
+ else if ( ch == '0' ) {
+ int tmp,stop;
+ ch = stop = 0;
+ if (((tmp=getc(yyin))!=EOF) && (isdigit(tmp)) &&
+ (tmp!='8') && (tmp!='9')) {
+ ch= (ch*8)+(tmp-'0');
+ }
+ else {
+ stop= 1;
+ ungetc(tmp,yyin);
+ }
+ if ((!stop) && ((tmp=getc(yyin))!=EOF) && (isdigit(tmp)) &&
+ (tmp!='8') && (tmp!='9')) {
+ ch= (ch*8)+(tmp-'0');
+ }
+ else {
+ stop= 1;
+ ungetc(tmp,yyin);
+ }
+ if ((!stop) && ((tmp=getc(yyin))!=EOF) && (isdigit(tmp)) &&
+ (tmp!='8') && (tmp!='9')) {
+ ch= (ch*8)+(tmp-'0');
+ }
+ else {
+ stop= 1;
+ ungetc(tmp,yyin);
+ }
+ }
+ }
+ else return ERROR_TOK;
+ }
+
+ if ( nInBuf < BUFSIZE-1 )
+ buf[nInBuf++] = ch;
+ }
+ if (( ch == '>' )&&(nInBuf<5)) {
+ buf[nInBuf++] = '\0';
+ if ( scanStr )
+ uFree( scanStr );
+ scanStr = (char *)uStringDup(buf);
+ scanStrLine = lineNum;
+ return KEYNAME;
+ }
+ return ERROR_TOK;
+}
+
+struct _Keyword {
+ char *keyword;
+ int token;
+} keywords[] = {
+ { "xkb_keymap", XKB_KEYMAP },
+ { "xkb_keycodes", XKB_KEYCODES },
+ { "xkb_types", XKB_TYPES },
+ { "xkb_symbols", XKB_SYMBOLS },
+ { "xkb_compat", XKB_COMPATMAP },
+ { "xkb_compat_map", XKB_COMPATMAP },
+ { "xkb_compatibility", XKB_COMPATMAP },
+ { "xkb_compatibility_map", XKB_COMPATMAP },
+ { "xkb_geometry", XKB_GEOMETRY },
+ { "xkb_semantics", XKB_SEMANTICS },
+ { "xkb_layout", XKB_LAYOUT },
+ { "include", INCLUDE },
+ { "override", OVERRIDE },
+ { "augment", AUGMENT },
+ { "replace", REPLACE },
+ { "alternate", ALTERNATE },
+ { "partial", PARTIAL },
+ { "default", DEFAULT },
+ { "hidden", HIDDEN },
+ { "virtual_modifiers", VIRTUAL_MODS },
+ { "type", TYPE },
+ { "interpret", INTERPRET },
+ { "action", ACTION_TOK },
+ { "key", KEY },
+ { "alias", ALIAS },
+ { "group", GROUP },
+ { "modmap", MODIFIER_MAP },
+ { "mod_map", MODIFIER_MAP },
+ { "modifier_map", MODIFIER_MAP },
+ { "indicator", INDICATOR },
+ { "shape", SHAPE },
+ { "row", ROW },
+ { "keys", KEYS },
+ { "section", SECTION },
+ { "overlay", OVERLAY },
+ { "text", TEXT },
+ { "outline", OUTLINE },
+ { "solid", SOLID },
+ { "logo", LOGO },
+ { "virtual", VIRTUAL },
+ { "alphanumeric_keys", ALPHANUMERIC_KEYS },
+ { "modifier_keys", MODIFIER_KEYS },
+ { "keypad_keys", KEYPAD_KEYS },
+ { "function_keys", FUNCTION_KEYS },
+ { "alternate_group", ALTERNATE_GROUP }
+};
+int numKeywords = sizeof(keywords)/sizeof(struct _Keyword);
+
+int
+#if NeedFunctionPrototypes
+yyGetIdent(int first)
+#else
+yyGetIdent(first)
+ int first;
+#endif
+{
+int ch,i,found;
+int rtrn= IDENT;
+
+ buf[0] = first; nInBuf = 1;
+ while ( ((ch=getc(yyin))!=EOF) && (isalnum(ch)||(ch=='_')) ) {
+ if ( nInBuf < BUFSIZE - 1 )
+ buf[nInBuf++] = ch;
+ }
+ buf[nInBuf++] = '\0';
+ found= 0;
+
+ for (i=0;(!found)&&(i<numKeywords);i++) {
+ if (uStrCaseCmp(buf,keywords[i].keyword)==0) {
+ rtrn= keywords[i].token;
+ found= 1;
+ }
+ }
+ if (!found) {
+ if ( scanStr )
+ uFree( scanStr );
+ scanStr = (char *)uStringDup(buf);
+ scanStrLine = lineNum;
+ rtrn = IDENT;
+ }
+
+ if ( (ch!=EOF) && (!isspace(ch)) )
+ ungetc( ch, yyin );
+ else if ( ch=='\n' )
+ lineNum++;
+
+ return rtrn;
+}
+
+int
+#if NeedFunctionPrototypes
+yyGetNumber(int ch)
+#else
+yyGetNumber(ch)
+ int ch;
+#endif
+{
+int isFloat= 0;
+
+ buf[0]= ch;
+ nInBuf= 1;
+ while (((ch=getc(yyin))!=EOF)&&(isxdigit(ch)||((nInBuf==1)&&(ch=='x')))) {
+ buf[nInBuf++]= ch;
+ }
+ if (ch=='.') {
+ isFloat= 1;
+ buf[nInBuf++]= ch;
+ while (((ch=getc(yyin))!=EOF)&&(isxdigit(ch))) {
+ buf[nInBuf++]= ch;
+ }
+ }
+ buf[nInBuf++]= '\0';
+ if ((ch!=EOF)&&(!isspace(ch)))
+ ungetc( ch, yyin );
+
+ if (isFloat) {
+ float tmp;
+ if (sscanf(buf,"%g",&tmp)==1) {
+ scanInt= tmp*XkbGeomPtsPerMM;
+ return FLOAT;
+ }
+ }
+ else if ( sscanf(buf,"%i",&scanInt)==1 )
+ return INTEGER;
+ fprintf(stderr,"Malformed number %s\n",buf);
+ return ERROR_TOK;
+}
+
+int
+#if NeedFunctionPrototypes
+yylex(void)
+#else
+yylex()
+#endif
+{
+int ch;
+int rtrn;
+
+ do {
+ ch = getc(yyin);
+ if ( ch == '\n' ) {
+ lineNum++;
+ }
+ else if ( ch=='#' ) { /* handle shell style '#' comments */
+ do {
+ ch= getc(yyin);
+ } while ((ch!='\n')&&(ch!=EOF));
+ lineNum++;
+ }
+ else if ( ch=='/' ) { /* handle C++ style double-/ comments */
+ int newch= getc(yyin);
+ if (newch=='/') {
+ do {
+ ch= getc(yyin);
+ } while ((ch!='\n')&&(ch!=EOF));
+ lineNum++;
+ }
+ else if (newch!=EOF) {
+ ungetc(newch,yyin);
+ }
+ }
+ } while ((ch!=EOF)&&(isspace(ch)));
+ if ( ch == '=' ) rtrn = EQUALS;
+ else if ( ch == '+' ) rtrn = PLUS;
+ else if ( ch == '-' ) rtrn = MINUS;
+ else if ( ch == '/' ) rtrn = DIVIDE;
+ else if ( ch == '*' ) rtrn = TIMES;
+ else if ( ch == '{' ) rtrn = OBRACE;
+ else if ( ch == '}' ) rtrn = CBRACE;
+ else if ( ch == '(' ) rtrn = OPAREN;
+ else if ( ch == ')' ) rtrn = CPAREN;
+ else if ( ch == '[' ) rtrn = OBRACKET;
+ else if ( ch == ']' ) rtrn = CBRACKET;
+ else if ( ch == '.' ) rtrn = DOT;
+ else if ( ch == ',' ) rtrn = COMMA;
+ else if ( ch == ';' ) rtrn = SEMI;
+ else if ( ch == '!' ) rtrn = EXCLAM;
+ else if ( ch == '~' ) rtrn = INVERT;
+ else if ( ch == '"' ) rtrn = yyGetString();
+ else if ( ch == '<' ) rtrn = yyGetKeyName();
+ else if ( isalpha(ch) || (ch=='_')) rtrn = yyGetIdent(ch);
+ else if ( isdigit(ch) ) rtrn = yyGetNumber(ch);
+ else if ( ch == EOF ) rtrn = END_OF_FILE;
+ else {
+#ifdef DEBUG
+ if (debugFlags)
+ fprintf(stderr,"Unexpected character %c (%d) in input stream\n",ch,ch);
+#endif
+ rtrn = ERROR_TOK;
+ }
+#ifdef DEBUG
+ if (debugFlags&0x2)
+ fprintf(stderr,"scan: %s\n",tokText(rtrn));
+#endif
+ return rtrn;
+}