1253 lines
36 KiB
C
1253 lines
36 KiB
C
|
/* $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,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,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;
|
||
|
}
|
||
|
|