aboutsummaryrefslogtreecommitdiff
path: root/xkbcomp/action.c
diff options
context:
space:
mode:
authormarha <marha@users.sourceforge.net>2009-06-28 22:07:26 +0000
committermarha <marha@users.sourceforge.net>2009-06-28 22:07:26 +0000
commit3562e78743202e43aec8727005182a2558117eca (patch)
tree8f9113a77d12470c5c851a2a8e4cb02e89df7d43 /xkbcomp/action.c
downloadvcxsrv-3562e78743202e43aec8727005182a2558117eca.tar.gz
vcxsrv-3562e78743202e43aec8727005182a2558117eca.tar.bz2
vcxsrv-3562e78743202e43aec8727005182a2558117eca.zip
Checked in the following released items:
xkeyboard-config-1.4.tar.gz ttf-bitstream-vera-1.10.tar.gz font-alias-1.0.1.tar.gz font-sun-misc-1.0.0.tar.gz font-sun-misc-1.0.0.tar.gz font-sony-misc-1.0.0.tar.gz font-schumacher-misc-1.0.0.tar.gz font-mutt-misc-1.0.0.tar.gz font-misc-misc-1.0.0.tar.gz font-misc-meltho-1.0.0.tar.gz font-micro-misc-1.0.0.tar.gz font-jis-misc-1.0.0.tar.gz font-isas-misc-1.0.0.tar.gz font-dec-misc-1.0.0.tar.gz font-daewoo-misc-1.0.0.tar.gz font-cursor-misc-1.0.0.tar.gz font-arabic-misc-1.0.0.tar.gz font-winitzki-cyrillic-1.0.0.tar.gz font-misc-cyrillic-1.0.0.tar.gz font-cronyx-cyrillic-1.0.0.tar.gz font-screen-cyrillic-1.0.1.tar.gz font-xfree86-type1-1.0.1.tar.gz font-adobe-utopia-type1-1.0.1.tar.gz font-ibm-type1-1.0.0.tar.gz font-bitstream-type1-1.0.0.tar.gz font-bitstream-speedo-1.0.0.tar.gz font-bh-ttf-1.0.0.tar.gz font-bh-type1-1.0.0.tar.gz font-bitstream-100dpi-1.0.0.tar.gz font-bh-lucidatypewriter-100dpi-1.0.0.tar.gz font-bh-100dpi-1.0.0.tar.gz font-adobe-utopia-100dpi-1.0.1.tar.gz font-adobe-100dpi-1.0.0.tar.gz font-util-1.0.1.tar.gz font-bitstream-75dpi-1.0.0.tar.gz font-bh-lucidatypewriter-75dpi-1.0.0.tar.gz font-adobe-utopia-75dpi-1.0.1.tar.gz font-bh-75dpi-1.0.0.tar.gz bdftopcf-1.0.1.tar.gz font-adobe-75dpi-1.0.0.tar.gz mkfontscale-1.0.6.tar.gz openssl-0.9.8k.tar.gz bigreqsproto-1.0.2.tar.gz xtrans-1.2.2.tar.gz resourceproto-1.0.2.tar.gz inputproto-1.4.4.tar.gz compositeproto-0.4.tar.gz damageproto-1.1.0.tar.gz zlib-1.2.3.tar.gz xkbcomp-1.0.5.tar.gz freetype-2.3.9.tar.gz pthreads-w32-2-8-0-release.tar.gz pixman-0.12.0.tar.gz kbproto-1.0.3.tar.gz evieext-1.0.2.tar.gz fixesproto-4.0.tar.gz recordproto-1.13.2.tar.gz randrproto-1.2.2.tar.gz scrnsaverproto-1.1.0.tar.gz renderproto-0.9.3.tar.gz xcmiscproto-1.1.2.tar.gz fontsproto-2.0.2.tar.gz xextproto-7.0.3.tar.gz xproto-7.0.14.tar.gz libXdmcp-1.0.2.tar.gz libxkbfile-1.0.5.tar.gz libfontenc-1.0.4.tar.gz libXfont-1.3.4.tar.gz libX11-1.1.5.tar.gz libXau-1.0.4.tar.gz libxcb-1.1.tar.gz xorg-server-1.5.3.tar.gz
Diffstat (limited to 'xkbcomp/action.c')
-rw-r--r--xkbcomp/action.c1252
1 files changed, 1252 insertions, 0 deletions
diff --git a/xkbcomp/action.c b/xkbcomp/action.c
new file mode 100644
index 000000000..8b0ba6507
--- /dev/null
+++ b/xkbcomp/action.c
@@ -0,0 +1,1252 @@
+/* $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.
+
+ ********************************************************/
+/* $XFree86: xc/programs/xkbcomp/action.c,v 3.10tsi Exp $ */
+
+#include "xkbcomp.h"
+#include "tokens.h"
+#include "expr.h"
+
+#include "keycodes.h"
+#include "vmod.h"
+#include "misc.h"
+#include "action.h"
+#include "misc.h"
+
+static Bool actionsInitialized;
+static ExprDef constTrue;
+static ExprDef constFalse;
+
+/***====================================================================***/
+
+static Bool
+stringToAction(char *str,unsigned *type_rtrn)
+{
+ 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
+stringToField(char *str,unsigned *field_rtrn)
+{
+
+ 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 *
+fieldText(unsigned field)
+{
+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
+ReportMismatch(unsigned action, unsigned field, const char *type)
+{
+ 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
+ReportIllegal(unsigned action,unsigned field)
+{
+ 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
+ReportActionNotArray(unsigned action,unsigned field)
+{
+ 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
+ReportNotFound(unsigned action, unsigned field, const char *what, char *bad)
+{
+ 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
+HandleNoAction( XkbDescPtr xkb,
+ XkbAnyAction * action,
+ unsigned field,
+ ExprDef * array_ndx,
+ ExprDef * value)
+{
+ return ReportIllegal(action->type,field);
+}
+
+static Bool
+CheckLatchLockFlags( unsigned action,
+ unsigned field,
+ ExprDef * value,
+ unsigned * flags_inout)
+{
+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
+CheckModifierField( XkbDescPtr xkb,
+ unsigned action,
+ ExprDef * value,
+ unsigned * flags_inout,
+ unsigned * mods_rtrn)
+{
+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
+HandleSetLatchMods( XkbDescPtr xkb,
+ XkbAnyAction * action,
+ unsigned field,
+ ExprDef * array_ndx,
+ ExprDef * value)
+{
+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
+HandleLockMods( XkbDescPtr xkb,
+ XkbAnyAction * action,
+ unsigned field,
+ ExprDef * array_ndx,
+ ExprDef * value)
+{
+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
+CheckGroupField( unsigned action,
+ ExprDef * value,
+ unsigned * flags_inout,
+ int * grp_rtrn)
+{
+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
+HandleSetLatchGroup( XkbDescPtr xkb,
+ XkbAnyAction * action,
+ unsigned field,
+ ExprDef * array_ndx,
+ ExprDef * value)
+{
+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
+HandleLockGroup( XkbDescPtr xkb,
+ XkbAnyAction * action,
+ unsigned field,
+ ExprDef * array_ndx,
+ ExprDef * value)
+{
+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
+HandleMovePtr( XkbDescPtr xkb,
+ XkbAnyAction * action,
+ unsigned field,
+ ExprDef * array_ndx,
+ ExprDef * value)
+{
+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
+HandlePtrBtn( XkbDescPtr xkb,
+ XkbAnyAction * action,
+ unsigned field,
+ ExprDef * array_ndx,
+ ExprDef * value)
+{
+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
+HandleSetPtrDflt( XkbDescPtr xkb,
+ XkbAnyAction * action,
+ unsigned field,
+ ExprDef * array_ndx,
+ ExprDef * value)
+{
+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
+HandleISOLock( XkbDescPtr xkb,
+ XkbAnyAction * action,
+ unsigned field,
+ ExprDef * array_ndx,
+ ExprDef * value)
+{
+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
+HandleSwitchScreen( XkbDescPtr xkb,
+ XkbAnyAction * action,
+ unsigned field,
+ ExprDef * array_ndx,
+ ExprDef * value)
+{
+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 },
+ { "audiblebell", XkbAudibleBellMask },
+ { "overlay1", XkbOverlay1Mask },
+ { "overlay2", XkbOverlay2Mask },
+ { "ignoregrouplock", XkbIgnoreGroupLockMask },
+ { "all", XkbAllBooleanCtrlsMask },
+ { "none", 0 },
+ { NULL, 0 }
+};
+
+static Bool
+HandleSetLockControls( XkbDescPtr xkb,
+ XkbAnyAction * action,
+ unsigned field,
+ ExprDef * array_ndx,
+ ExprDef * value)
+{
+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
+HandleActionMessage( XkbDescPtr xkb,
+ XkbAnyAction * action,
+ unsigned field,
+ ExprDef * array_ndx,
+ ExprDef * value)
+{
+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
+HandleRedirectKey( XkbDescPtr xkb,
+ XkbAnyAction * action,
+ unsigned field,
+ ExprDef * array_ndx,
+ ExprDef * value)
+{
+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
+HandleDeviceBtn( XkbDescPtr xkb,
+ XkbAnyAction * action,
+ unsigned field,
+ ExprDef * array_ndx,
+ ExprDef * value)
+{
+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
+HandleDeviceValuator( XkbDescPtr xkb,
+ XkbAnyAction * action,
+ unsigned field,
+ ExprDef * array_ndx,
+ ExprDef * value)
+{
+#if 0
+ExprResult rtrn;
+XkbDeviceValuatorAction * act;
+
+ act= (XkbDeviceValuatorAction *)action;
+ /* XXX - Not yet implemented */
+#endif
+ return False;
+}
+
+static Bool
+HandlePrivate( XkbDescPtr xkb,
+ XkbAnyAction * action,
+ unsigned field,
+ ExprDef * array_ndx,
+ ExprDef * value)
+{
+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)(
+ XkbDescPtr /* xkb */,
+ XkbAnyAction * /* action */,
+ unsigned /* field */,
+ ExprDef * /* array_ndx */,
+ ExprDef * /* value */
+);
+
+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*/,
+ HandleDeviceValuator /* DeviceValuatr*/,
+ HandlePrivate /* Private */
+};
+
+/***====================================================================***/
+
+static void
+ApplyActionFactoryDefaults(XkbAction *action)
+{
+ 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
+HandleActionDef( ExprDef * def,
+ XkbDescPtr xkb,
+ XkbAnyAction * action,
+ unsigned mergeMode,
+ ActionInfo * info)
+{
+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
+SetActionField( XkbDescPtr xkb,
+ char * elem,
+ char * field,
+ ExprDef * array_ndx,
+ ExprDef * value,
+ ActionInfo ** info_rtrn)
+{
+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
+ActionsInit(void)
+{
+ 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;
+}
+