action.c revision c82dfdfb
1f46a6179Smrg/************************************************************
2f46a6179Smrg Copyright (c) 1994 by Silicon Graphics Computer Systems, Inc.
3f46a6179Smrg
4f46a6179Smrg Permission to use, copy, modify, and distribute this
5f46a6179Smrg software and its documentation for any purpose and without
6f46a6179Smrg fee is hereby granted, provided that the above copyright
7f46a6179Smrg notice appear in all copies and that both that copyright
8f46a6179Smrg notice and this permission notice appear in supporting
9f46a6179Smrg documentation, and that the name of Silicon Graphics not be
10f46a6179Smrg used in advertising or publicity pertaining to distribution
11f46a6179Smrg of the software without specific prior written permission.
12f46a6179Smrg Silicon Graphics makes no representation about the suitability
13f46a6179Smrg of this software for any purpose. It is provided "as is"
14f46a6179Smrg without any express or implied warranty.
15f46a6179Smrg
16f46a6179Smrg SILICON GRAPHICS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS
17f46a6179Smrg SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
18f46a6179Smrg AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL SILICON
19f46a6179Smrg GRAPHICS BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL
20f46a6179Smrg DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
21f46a6179Smrg DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
22f46a6179Smrg OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION  WITH
23f46a6179Smrg THE USE OR PERFORMANCE OF THIS SOFTWARE.
24f46a6179Smrg
25f46a6179Smrg ********************************************************/
26f46a6179Smrg
27f46a6179Smrg#include "xkbcomp.h"
28f46a6179Smrg#include "tokens.h"
29f46a6179Smrg#include "expr.h"
30f46a6179Smrg
31f46a6179Smrg#include "keycodes.h"
32f46a6179Smrg#include "vmod.h"
33f46a6179Smrg#include "misc.h"
34f46a6179Smrg#include "action.h"
35f46a6179Smrg#include "misc.h"
36f46a6179Smrg
3734345a63Smrgstatic Bool actionsInitialized;
3834345a63Smrgstatic ExprDef constTrue;
3934345a63Smrgstatic ExprDef constFalse;
40f46a6179Smrg
41f46a6179Smrg/***====================================================================***/
42f46a6179Smrg
43f46a6179Smrgstatic Bool
44c82dfdfbSmrgstringToAction(const char *str, unsigned *type_rtrn)
45f46a6179Smrg{
4634345a63Smrg    if (str == NULL)
4734345a63Smrg        return False;
4834345a63Smrg
4934345a63Smrg    if (uStrCaseCmp(str, "noaction") == 0)
5034345a63Smrg        *type_rtrn = XkbSA_NoAction;
5134345a63Smrg    else if (uStrCaseCmp(str, "setmods") == 0)
5234345a63Smrg        *type_rtrn = XkbSA_SetMods;
5334345a63Smrg    else if (uStrCaseCmp(str, "latchmods") == 0)
5434345a63Smrg        *type_rtrn = XkbSA_LatchMods;
5534345a63Smrg    else if (uStrCaseCmp(str, "lockmods") == 0)
5634345a63Smrg        *type_rtrn = XkbSA_LockMods;
5734345a63Smrg    else if (uStrCaseCmp(str, "setgroup") == 0)
5834345a63Smrg        *type_rtrn = XkbSA_SetGroup;
5934345a63Smrg    else if (uStrCaseCmp(str, "latchgroup") == 0)
6034345a63Smrg        *type_rtrn = XkbSA_LatchGroup;
6134345a63Smrg    else if (uStrCaseCmp(str, "lockgroup") == 0)
6234345a63Smrg        *type_rtrn = XkbSA_LockGroup;
6334345a63Smrg    else if (uStrCaseCmp(str, "moveptr") == 0)
6434345a63Smrg        *type_rtrn = XkbSA_MovePtr;
6534345a63Smrg    else if (uStrCaseCmp(str, "movepointer") == 0)
6634345a63Smrg        *type_rtrn = XkbSA_MovePtr;
6734345a63Smrg    else if (uStrCaseCmp(str, "ptrbtn") == 0)
6834345a63Smrg        *type_rtrn = XkbSA_PtrBtn;
6934345a63Smrg    else if (uStrCaseCmp(str, "pointerbutton") == 0)
7034345a63Smrg        *type_rtrn = XkbSA_PtrBtn;
7134345a63Smrg    else if (uStrCaseCmp(str, "lockptrbtn") == 0)
7234345a63Smrg        *type_rtrn = XkbSA_LockPtrBtn;
7334345a63Smrg    else if (uStrCaseCmp(str, "lockpointerbutton") == 0)
7434345a63Smrg        *type_rtrn = XkbSA_LockPtrBtn;
7534345a63Smrg    else if (uStrCaseCmp(str, "lockptrbutton") == 0)
7634345a63Smrg        *type_rtrn = XkbSA_LockPtrBtn;
7734345a63Smrg    else if (uStrCaseCmp(str, "lockpointerbtn") == 0)
7834345a63Smrg        *type_rtrn = XkbSA_LockPtrBtn;
7934345a63Smrg    else if (uStrCaseCmp(str, "setptrdflt") == 0)
8034345a63Smrg        *type_rtrn = XkbSA_SetPtrDflt;
8134345a63Smrg    else if (uStrCaseCmp(str, "setpointerdefault") == 0)
8234345a63Smrg        *type_rtrn = XkbSA_SetPtrDflt;
8334345a63Smrg    else if (uStrCaseCmp(str, "isolock") == 0)
8434345a63Smrg        *type_rtrn = XkbSA_ISOLock;
8534345a63Smrg    else if (uStrCaseCmp(str, "terminate") == 0)
8634345a63Smrg        *type_rtrn = XkbSA_Terminate;
8734345a63Smrg    else if (uStrCaseCmp(str, "terminateserver") == 0)
8834345a63Smrg        *type_rtrn = XkbSA_Terminate;
8934345a63Smrg    else if (uStrCaseCmp(str, "switchscreen") == 0)
9034345a63Smrg        *type_rtrn = XkbSA_SwitchScreen;
9134345a63Smrg    else if (uStrCaseCmp(str, "setcontrols") == 0)
9234345a63Smrg        *type_rtrn = XkbSA_SetControls;
9334345a63Smrg    else if (uStrCaseCmp(str, "lockcontrols") == 0)
9434345a63Smrg        *type_rtrn = XkbSA_LockControls;
9534345a63Smrg    else if (uStrCaseCmp(str, "actionmessage") == 0)
9634345a63Smrg        *type_rtrn = XkbSA_ActionMessage;
9734345a63Smrg    else if (uStrCaseCmp(str, "messageaction") == 0)
9834345a63Smrg        *type_rtrn = XkbSA_ActionMessage;
9934345a63Smrg    else if (uStrCaseCmp(str, "message") == 0)
10034345a63Smrg        *type_rtrn = XkbSA_ActionMessage;
10134345a63Smrg    else if (uStrCaseCmp(str, "redirect") == 0)
10234345a63Smrg        *type_rtrn = XkbSA_RedirectKey;
10334345a63Smrg    else if (uStrCaseCmp(str, "redirectkey") == 0)
10434345a63Smrg        *type_rtrn = XkbSA_RedirectKey;
10534345a63Smrg    else if (uStrCaseCmp(str, "devbtn") == 0)
10634345a63Smrg        *type_rtrn = XkbSA_DeviceBtn;
10734345a63Smrg    else if (uStrCaseCmp(str, "devicebtn") == 0)
10834345a63Smrg        *type_rtrn = XkbSA_DeviceBtn;
10934345a63Smrg    else if (uStrCaseCmp(str, "devbutton") == 0)
11034345a63Smrg        *type_rtrn = XkbSA_DeviceBtn;
11134345a63Smrg    else if (uStrCaseCmp(str, "devicebutton") == 0)
11234345a63Smrg        *type_rtrn = XkbSA_DeviceBtn;
11334345a63Smrg    else if (uStrCaseCmp(str, "lockdevbtn") == 0)
11434345a63Smrg        *type_rtrn = XkbSA_DeviceBtn;
11534345a63Smrg    else if (uStrCaseCmp(str, "lockdevicebtn") == 0)
11634345a63Smrg        *type_rtrn = XkbSA_LockDeviceBtn;
11734345a63Smrg    else if (uStrCaseCmp(str, "lockdevbutton") == 0)
11834345a63Smrg        *type_rtrn = XkbSA_LockDeviceBtn;
11934345a63Smrg    else if (uStrCaseCmp(str, "lockdevicebutton") == 0)
12034345a63Smrg        *type_rtrn = XkbSA_LockDeviceBtn;
12134345a63Smrg    else if (uStrCaseCmp(str, "devval") == 0)
12234345a63Smrg        *type_rtrn = XkbSA_DeviceValuator;
12334345a63Smrg    else if (uStrCaseCmp(str, "deviceval") == 0)
12434345a63Smrg        *type_rtrn = XkbSA_DeviceValuator;
12534345a63Smrg    else if (uStrCaseCmp(str, "devvaluator") == 0)
12634345a63Smrg        *type_rtrn = XkbSA_DeviceValuator;
12734345a63Smrg    else if (uStrCaseCmp(str, "devicevaluator") == 0)
12834345a63Smrg        *type_rtrn = XkbSA_DeviceValuator;
12934345a63Smrg    else if (uStrCaseCmp(str, "private") == 0)
13034345a63Smrg        *type_rtrn = PrivateAction;
13134345a63Smrg    else
13234345a63Smrg        return False;
133f46a6179Smrg    return True;
134f46a6179Smrg}
135f46a6179Smrg
136f46a6179Smrgstatic Bool
137c82dfdfbSmrgstringToField(const char *str, unsigned *field_rtrn)
138f46a6179Smrg{
139f46a6179Smrg
14034345a63Smrg    if (str == NULL)
14134345a63Smrg        return False;
14234345a63Smrg
14334345a63Smrg    if (uStrCaseCmp(str, "clearlocks") == 0)
14434345a63Smrg        *field_rtrn = F_ClearLocks;
14534345a63Smrg    else if (uStrCaseCmp(str, "latchtolock") == 0)
14634345a63Smrg        *field_rtrn = F_LatchToLock;
14734345a63Smrg    else if (uStrCaseCmp(str, "genkeyevent") == 0)
14834345a63Smrg        *field_rtrn = F_GenKeyEvent;
14934345a63Smrg    else if (uStrCaseCmp(str, "generatekeyevent") == 0)
15034345a63Smrg        *field_rtrn = F_GenKeyEvent;
15134345a63Smrg    else if (uStrCaseCmp(str, "report") == 0)
15234345a63Smrg        *field_rtrn = F_Report;
15334345a63Smrg    else if (uStrCaseCmp(str, "default") == 0)
15434345a63Smrg        *field_rtrn = F_Default;
15534345a63Smrg    else if (uStrCaseCmp(str, "affect") == 0)
15634345a63Smrg        *field_rtrn = F_Affect;
15734345a63Smrg    else if (uStrCaseCmp(str, "increment") == 0)
15834345a63Smrg        *field_rtrn = F_Increment;
15934345a63Smrg    else if (uStrCaseCmp(str, "mods") == 0)
16034345a63Smrg        *field_rtrn = F_Modifiers;
16134345a63Smrg    else if (uStrCaseCmp(str, "modifiers") == 0)
16234345a63Smrg        *field_rtrn = F_Modifiers;
16334345a63Smrg    else if (uStrCaseCmp(str, "group") == 0)
16434345a63Smrg        *field_rtrn = F_Group;
16534345a63Smrg    else if (uStrCaseCmp(str, "x") == 0)
16634345a63Smrg        *field_rtrn = F_X;
16734345a63Smrg    else if (uStrCaseCmp(str, "y") == 0)
16834345a63Smrg        *field_rtrn = F_Y;
16934345a63Smrg    else if (uStrCaseCmp(str, "accel") == 0)
17034345a63Smrg        *field_rtrn = F_Accel;
17134345a63Smrg    else if (uStrCaseCmp(str, "accelerate") == 0)
17234345a63Smrg        *field_rtrn = F_Accel;
17334345a63Smrg    else if (uStrCaseCmp(str, "repeat") == 0)
17434345a63Smrg        *field_rtrn = F_Accel;
17534345a63Smrg    else if (uStrCaseCmp(str, "button") == 0)
17634345a63Smrg        *field_rtrn = F_Button;
17734345a63Smrg    else if (uStrCaseCmp(str, "value") == 0)
17834345a63Smrg        *field_rtrn = F_Value;
17934345a63Smrg    else if (uStrCaseCmp(str, "controls") == 0)
18034345a63Smrg        *field_rtrn = F_Controls;
18134345a63Smrg    else if (uStrCaseCmp(str, "ctrls") == 0)
18234345a63Smrg        *field_rtrn = F_Controls;
18334345a63Smrg    else if (uStrCaseCmp(str, "type") == 0)
18434345a63Smrg        *field_rtrn = F_Type;
18534345a63Smrg    else if (uStrCaseCmp(str, "count") == 0)
18634345a63Smrg        *field_rtrn = F_Count;
18734345a63Smrg    else if (uStrCaseCmp(str, "screen") == 0)
18834345a63Smrg        *field_rtrn = F_Screen;
18934345a63Smrg    else if (uStrCaseCmp(str, "same") == 0)
19034345a63Smrg        *field_rtrn = F_Same;
19134345a63Smrg    else if (uStrCaseCmp(str, "sameserver") == 0)
19234345a63Smrg        *field_rtrn = F_Same;
19334345a63Smrg    else if (uStrCaseCmp(str, "data") == 0)
19434345a63Smrg        *field_rtrn = F_Data;
19534345a63Smrg    else if (uStrCaseCmp(str, "device") == 0)
19634345a63Smrg        *field_rtrn = F_Device;
19734345a63Smrg    else if (uStrCaseCmp(str, "dev") == 0)
19834345a63Smrg        *field_rtrn = F_Device;
19934345a63Smrg    else if (uStrCaseCmp(str, "key") == 0)
20034345a63Smrg        *field_rtrn = F_Keycode;
20134345a63Smrg    else if (uStrCaseCmp(str, "keycode") == 0)
20234345a63Smrg        *field_rtrn = F_Keycode;
20334345a63Smrg    else if (uStrCaseCmp(str, "kc") == 0)
20434345a63Smrg        *field_rtrn = F_Keycode;
20534345a63Smrg    else if (uStrCaseCmp(str, "clearmods") == 0)
20634345a63Smrg        *field_rtrn = F_ModsToClear;
20734345a63Smrg    else if (uStrCaseCmp(str, "clearmodifiers") == 0)
20834345a63Smrg        *field_rtrn = F_ModsToClear;
20934345a63Smrg    else
21034345a63Smrg        return False;
211f46a6179Smrg    return True;
212f46a6179Smrg}
213f46a6179Smrg
214f46a6179Smrgstatic char *
215f46a6179SmrgfieldText(unsigned field)
216f46a6179Smrg{
21734345a63Smrg    static char buf[32];
21834345a63Smrg
21934345a63Smrg    switch (field)
22034345a63Smrg    {
22134345a63Smrg    case F_ClearLocks:
22234345a63Smrg        strcpy(buf, "clearLocks");
22334345a63Smrg        break;
22434345a63Smrg    case F_LatchToLock:
22534345a63Smrg        strcpy(buf, "latchToLock");
22634345a63Smrg        break;
22734345a63Smrg    case F_GenKeyEvent:
22834345a63Smrg        strcpy(buf, "genKeyEvent");
22934345a63Smrg        break;
23034345a63Smrg    case F_Report:
23134345a63Smrg        strcpy(buf, "report");
23234345a63Smrg        break;
23334345a63Smrg    case F_Default:
23434345a63Smrg        strcpy(buf, "default");
23534345a63Smrg        break;
23634345a63Smrg    case F_Affect:
23734345a63Smrg        strcpy(buf, "affect");
23834345a63Smrg        break;
23934345a63Smrg    case F_Increment:
24034345a63Smrg        strcpy(buf, "increment");
24134345a63Smrg        break;
24234345a63Smrg    case F_Modifiers:
24334345a63Smrg        strcpy(buf, "modifiers");
24434345a63Smrg        break;
24534345a63Smrg    case F_Group:
24634345a63Smrg        strcpy(buf, "group");
24734345a63Smrg        break;
24834345a63Smrg    case F_X:
24934345a63Smrg        strcpy(buf, "x");
25034345a63Smrg        break;
25134345a63Smrg    case F_Y:
25234345a63Smrg        strcpy(buf, "y");
25334345a63Smrg        break;
25434345a63Smrg    case F_Accel:
25534345a63Smrg        strcpy(buf, "accel");
25634345a63Smrg        break;
25734345a63Smrg    case F_Button:
25834345a63Smrg        strcpy(buf, "button");
25934345a63Smrg        break;
26034345a63Smrg    case F_Value:
26134345a63Smrg        strcpy(buf, "value");
26234345a63Smrg        break;
26334345a63Smrg    case F_Controls:
26434345a63Smrg        strcpy(buf, "controls");
26534345a63Smrg        break;
26634345a63Smrg    case F_Type:
26734345a63Smrg        strcpy(buf, "type");
26834345a63Smrg        break;
26934345a63Smrg    case F_Count:
27034345a63Smrg        strcpy(buf, "count");
27134345a63Smrg        break;
27234345a63Smrg    case F_Screen:
27334345a63Smrg        strcpy(buf, "screen");
27434345a63Smrg        break;
27534345a63Smrg    case F_Same:
27634345a63Smrg        strcpy(buf, "sameServer");
27734345a63Smrg        break;
27834345a63Smrg    case F_Data:
27934345a63Smrg        strcpy(buf, "data");
28034345a63Smrg        break;
28134345a63Smrg    case F_Device:
28234345a63Smrg        strcpy(buf, "device");
28334345a63Smrg        break;
28434345a63Smrg    case F_Keycode:
28534345a63Smrg        strcpy(buf, "keycode");
28634345a63Smrg        break;
28734345a63Smrg    case F_ModsToClear:
28834345a63Smrg        strcpy(buf, "clearmods");
28934345a63Smrg        break;
29034345a63Smrg    default:
29134345a63Smrg        strcpy(buf, "unknown");
29234345a63Smrg        break;
293f46a6179Smrg    }
294f46a6179Smrg    return buf;
295f46a6179Smrg}
296f46a6179Smrg
297f46a6179Smrg/***====================================================================***/
298f46a6179Smrg
299f46a6179Smrgstatic Bool
300f46a6179SmrgReportMismatch(unsigned action, unsigned field, const char *type)
301f46a6179Smrg{
30234345a63Smrg    ERROR2("Value of %s field must be of type %s\n", fieldText(field), type);
303f46a6179Smrg    ACTION1("Action %s definition ignored\n",
30434345a63Smrg            XkbActionTypeText(action, XkbMessage));
305f46a6179Smrg    return False;
306f46a6179Smrg}
307f46a6179Smrg
308f46a6179Smrgstatic Bool
30934345a63SmrgReportIllegal(unsigned action, unsigned field)
310f46a6179Smrg{
311f46a6179Smrg    ERROR2("Field %s is not defined for an action of type %s\n",
31234345a63Smrg           fieldText(field), XkbActionTypeText(action, XkbMessage));
313f46a6179Smrg    ACTION("Action definition ignored\n");
314f46a6179Smrg    return False;
315f46a6179Smrg}
316f46a6179Smrg
317f46a6179Smrgstatic Bool
31834345a63SmrgReportActionNotArray(unsigned action, unsigned field)
319f46a6179Smrg{
320f46a6179Smrg    ERROR2("The %s field in the %s action is not an array\n",
32134345a63Smrg           fieldText(field), XkbActionTypeText(action, XkbMessage));
322f46a6179Smrg    ACTION("Action definition ignored\n");
323f46a6179Smrg    return False;
324f46a6179Smrg}
325f46a6179Smrg
326f46a6179Smrgstatic Bool
327f46a6179SmrgReportNotFound(unsigned action, unsigned field, const char *what, char *bad)
328f46a6179Smrg{
32934345a63Smrg    ERROR2("%s named %s not found\n", what, bad);
33034345a63Smrg    ACTION2("Ignoring the %s field of an %s action\n", fieldText(field),
33134345a63Smrg            XkbActionTypeText(action, XkbMessage));
332f46a6179Smrg    return False;
333f46a6179Smrg}
334f46a6179Smrg
335f46a6179Smrgstatic Bool
33634345a63SmrgHandleNoAction(XkbDescPtr xkb,
33734345a63Smrg               XkbAnyAction * action,
33834345a63Smrg               unsigned field, ExprDef * array_ndx, ExprDef * value)
339f46a6179Smrg{
34034345a63Smrg    return ReportIllegal(action->type, field);
341f46a6179Smrg}
342f46a6179Smrg
343f46a6179Smrgstatic Bool
34434345a63SmrgCheckLatchLockFlags(unsigned action,
34534345a63Smrg                    unsigned field, ExprDef * value, unsigned *flags_inout)
346f46a6179Smrg{
34734345a63Smrg    unsigned tmp;
34834345a63Smrg    ExprResult result;
34934345a63Smrg
35034345a63Smrg    if (field == F_ClearLocks)
35134345a63Smrg        tmp = XkbSA_ClearLocks;
35234345a63Smrg    else if (field == F_LatchToLock)
35334345a63Smrg        tmp = XkbSA_LatchToLock;
35434345a63Smrg    else
35534345a63Smrg        return False;           /* WSGO! */
35634345a63Smrg    if (!ExprResolveBoolean(value, &result, NULL, NULL))
35734345a63Smrg        return ReportMismatch(action, field, "boolean");
35834345a63Smrg    if (result.uval)
35934345a63Smrg        *flags_inout |= tmp;
36034345a63Smrg    else
36134345a63Smrg        *flags_inout &= ~tmp;
362f46a6179Smrg    return True;
363f46a6179Smrg}
364f46a6179Smrg
365f46a6179Smrgstatic Bool
36634345a63SmrgCheckModifierField(XkbDescPtr xkb,
36734345a63Smrg                   unsigned action,
36834345a63Smrg                   ExprDef * value,
36934345a63Smrg                   unsigned *flags_inout, unsigned *mods_rtrn)
370f46a6179Smrg{
37134345a63Smrg    ExprResult rtrn;
37234345a63Smrg
37334345a63Smrg    if (value->op == ExprIdent)
37434345a63Smrg    {
37534345a63Smrg        register char *valStr;
37634345a63Smrg        valStr = XkbAtomGetString(NULL, value->value.str);
37734345a63Smrg        if (valStr && ((uStrCaseCmp(valStr, "usemodmapmods") == 0) ||
37834345a63Smrg                       (uStrCaseCmp(valStr, "modmapmods") == 0)))
37934345a63Smrg        {
38034345a63Smrg
38134345a63Smrg            *mods_rtrn = 0;
38234345a63Smrg            *flags_inout |= XkbSA_UseModMapMods;
38334345a63Smrg            return True;
38434345a63Smrg        }
385f46a6179Smrg    }
38634345a63Smrg    if (!ExprResolveModMask(value, &rtrn, LookupVModMask, (XPointer) xkb))
38734345a63Smrg        return ReportMismatch(action, F_Modifiers, "modifier mask");
38834345a63Smrg    *mods_rtrn = rtrn.uval;
38934345a63Smrg    *flags_inout &= ~XkbSA_UseModMapMods;
390f46a6179Smrg    return True;
391f46a6179Smrg}
392f46a6179Smrg
393f46a6179Smrgstatic Bool
39434345a63SmrgHandleSetLatchMods(XkbDescPtr xkb,
39534345a63Smrg                   XkbAnyAction * action,
39634345a63Smrg                   unsigned field, ExprDef * array_ndx, ExprDef * value)
397f46a6179Smrg{
39834345a63Smrg    XkbModAction *act;
39934345a63Smrg    unsigned rtrn;
40034345a63Smrg    unsigned t1, t2;
40134345a63Smrg
40234345a63Smrg    act = (XkbModAction *) action;
40334345a63Smrg    if (array_ndx != NULL)
40434345a63Smrg    {
40534345a63Smrg        switch (field)
40634345a63Smrg        {
40734345a63Smrg        case F_ClearLocks:
40834345a63Smrg        case F_LatchToLock:
40934345a63Smrg        case F_Modifiers:
41034345a63Smrg            return ReportActionNotArray(action->type, field);
41134345a63Smrg        }
412f46a6179Smrg    }
41334345a63Smrg    switch (field)
41434345a63Smrg    {
41534345a63Smrg    case F_ClearLocks:
41634345a63Smrg    case F_LatchToLock:
41734345a63Smrg        rtrn = act->flags;
41834345a63Smrg        if (CheckLatchLockFlags(action->type, field, value, &rtrn))
41934345a63Smrg        {
42034345a63Smrg            act->flags = rtrn;
42134345a63Smrg            return True;
42234345a63Smrg        }
42334345a63Smrg        return False;
42434345a63Smrg    case F_Modifiers:
42534345a63Smrg        t1 = act->flags;
42634345a63Smrg        if (CheckModifierField(xkb, action->type, value, &t1, &t2))
42734345a63Smrg        {
42834345a63Smrg            act->flags = t1;
42934345a63Smrg            act->real_mods = act->mask = (t2 & 0xff);
43034345a63Smrg            t2 = (t2 >> 8) & 0xffff;
43134345a63Smrg            XkbSetModActionVMods(act, t2);
43234345a63Smrg            return True;
43334345a63Smrg        }
43434345a63Smrg        return False;
435f46a6179Smrg    }
43634345a63Smrg    return ReportIllegal(action->type, field);
437f46a6179Smrg}
438f46a6179Smrg
439f46a6179Smrgstatic Bool
44034345a63SmrgHandleLockMods(XkbDescPtr xkb,
44134345a63Smrg               XkbAnyAction * action,
44234345a63Smrg               unsigned field, ExprDef * array_ndx, ExprDef * value)
443f46a6179Smrg{
44434345a63Smrg    XkbModAction *act;
44534345a63Smrg    unsigned t1, t2;
44634345a63Smrg
44734345a63Smrg    act = (XkbModAction *) action;
44834345a63Smrg    if ((array_ndx != NULL) && (field == F_Modifiers))
44934345a63Smrg        return ReportActionNotArray(action->type, field);
45034345a63Smrg    switch (field)
45134345a63Smrg    {
45234345a63Smrg    case F_Modifiers:
45334345a63Smrg        t1 = act->flags;
45434345a63Smrg        if (CheckModifierField(xkb, action->type, value, &t1, &t2))
45534345a63Smrg        {
45634345a63Smrg            act->flags = t1;
45734345a63Smrg            act->real_mods = act->mask = (t2 & 0xff);
45834345a63Smrg            t2 = (t2 >> 8) & 0xffff;
45934345a63Smrg            XkbSetModActionVMods(act, t2);
46034345a63Smrg            return True;
46134345a63Smrg        }
46234345a63Smrg        return False;
463f46a6179Smrg    }
46434345a63Smrg    return ReportIllegal(action->type, field);
465f46a6179Smrg}
466f46a6179Smrg
467f46a6179Smrgstatic LookupEntry groupNames[] = {
46834345a63Smrg    {"group1", 1},
46934345a63Smrg    {"group2", 2},
47034345a63Smrg    {"group3", 3},
47134345a63Smrg    {"group4", 4},
47234345a63Smrg    {"group5", 5},
47334345a63Smrg    {"group6", 6},
47434345a63Smrg    {"group7", 7},
47534345a63Smrg    {"group8", 8},
47634345a63Smrg    {NULL, 0},
477f46a6179Smrg};
478f46a6179Smrg
479f46a6179Smrgstatic Bool
48034345a63SmrgCheckGroupField(unsigned action,
48134345a63Smrg                ExprDef * value, unsigned *flags_inout, int *grp_rtrn)
482f46a6179Smrg{
48334345a63Smrg    ExprDef *spec;
48434345a63Smrg    ExprResult rtrn;
485f46a6179Smrg
48634345a63Smrg    if ((value->op == OpNegate) || (value->op == OpUnaryPlus))
48734345a63Smrg    {
48834345a63Smrg        *flags_inout &= ~XkbSA_GroupAbsolute;
48934345a63Smrg        spec = value->value.child;
490f46a6179Smrg    }
49134345a63Smrg    else
49234345a63Smrg    {
49334345a63Smrg        *flags_inout |= XkbSA_GroupAbsolute;
49434345a63Smrg        spec = value;
495f46a6179Smrg    }
496f46a6179Smrg
49734345a63Smrg    if (!ExprResolveInteger(spec, &rtrn, SimpleLookup, (XPointer) groupNames))
49834345a63Smrg        return ReportMismatch(action, F_Group, "integer (range 1..8)");
49934345a63Smrg    if ((rtrn.ival < 1) || (rtrn.ival > XkbNumKbdGroups))
50034345a63Smrg    {
50134345a63Smrg        ERROR2("Illegal group %d (must be in the range 1..%d)\n", rtrn.ival,
50234345a63Smrg               XkbNumKbdGroups);
50334345a63Smrg        ACTION1("Action %s definition ignored\n",
50434345a63Smrg                XkbActionTypeText(action, XkbMessage));
50534345a63Smrg        return False;
506f46a6179Smrg    }
50734345a63Smrg    if (value->op == OpNegate)
50834345a63Smrg        *grp_rtrn = -rtrn.ival;
50934345a63Smrg    else if (value->op == OpUnaryPlus)
51034345a63Smrg        *grp_rtrn = rtrn.ival;
51134345a63Smrg    else
51234345a63Smrg        *grp_rtrn = rtrn.ival - 1;
513f46a6179Smrg    return True;
514f46a6179Smrg}
515f46a6179Smrg
516f46a6179Smrgstatic Bool
51734345a63SmrgHandleSetLatchGroup(XkbDescPtr xkb,
51834345a63Smrg                    XkbAnyAction * action,
51934345a63Smrg                    unsigned field, ExprDef * array_ndx, ExprDef * value)
520f46a6179Smrg{
52134345a63Smrg    XkbGroupAction *act;
52234345a63Smrg    unsigned rtrn;
52334345a63Smrg    unsigned t1;
52434345a63Smrg    int t2;
52534345a63Smrg
52634345a63Smrg    act = (XkbGroupAction *) action;
52734345a63Smrg    if (array_ndx != NULL)
52834345a63Smrg    {
52934345a63Smrg        switch (field)
53034345a63Smrg        {
53134345a63Smrg        case F_ClearLocks:
53234345a63Smrg        case F_LatchToLock:
53334345a63Smrg        case F_Group:
53434345a63Smrg            return ReportActionNotArray(action->type, field);
53534345a63Smrg        }
536f46a6179Smrg    }
53734345a63Smrg    switch (field)
53834345a63Smrg    {
53934345a63Smrg    case F_ClearLocks:
54034345a63Smrg    case F_LatchToLock:
54134345a63Smrg        rtrn = act->flags;
54234345a63Smrg        if (CheckLatchLockFlags(action->type, field, value, &rtrn))
54334345a63Smrg        {
54434345a63Smrg            act->flags = rtrn;
54534345a63Smrg            return True;
54634345a63Smrg        }
54734345a63Smrg        return False;
54834345a63Smrg    case F_Group:
54934345a63Smrg        t1 = act->flags;
55034345a63Smrg        if (CheckGroupField(action->type, value, &t1, &t2))
55134345a63Smrg        {
55234345a63Smrg            act->flags = t1;
55334345a63Smrg            XkbSASetGroup(act, t2);
55434345a63Smrg            return True;
55534345a63Smrg        }
55634345a63Smrg        return False;
557f46a6179Smrg    }
55834345a63Smrg    return ReportIllegal(action->type, field);
559f46a6179Smrg}
560f46a6179Smrg
561f46a6179Smrgstatic Bool
56234345a63SmrgHandleLockGroup(XkbDescPtr xkb,
56334345a63Smrg                XkbAnyAction * action,
56434345a63Smrg                unsigned field, ExprDef * array_ndx, ExprDef * value)
565f46a6179Smrg{
56634345a63Smrg    XkbGroupAction *act;
56734345a63Smrg    unsigned t1;
56834345a63Smrg    int t2;
56934345a63Smrg
57034345a63Smrg    act = (XkbGroupAction *) action;
57134345a63Smrg    if ((array_ndx != NULL) && (field == F_Group))
57234345a63Smrg        return ReportActionNotArray(action->type, field);
57334345a63Smrg    if (field == F_Group)
57434345a63Smrg    {
57534345a63Smrg        t1 = act->flags;
57634345a63Smrg        if (CheckGroupField(action->type, value, &t1, &t2))
57734345a63Smrg        {
57834345a63Smrg            act->flags = t1;
57934345a63Smrg            XkbSASetGroup(act, t2);
58034345a63Smrg            return True;
58134345a63Smrg        }
58234345a63Smrg        return False;
583f46a6179Smrg    }
58434345a63Smrg    return ReportIllegal(action->type, field);
585f46a6179Smrg}
586f46a6179Smrg
587f46a6179Smrgstatic Bool
58834345a63SmrgHandleMovePtr(XkbDescPtr xkb,
58934345a63Smrg              XkbAnyAction * action,
59034345a63Smrg              unsigned field, ExprDef * array_ndx, ExprDef * value)
591f46a6179Smrg{
59234345a63Smrg    ExprResult rtrn;
59334345a63Smrg    XkbPtrAction *act;
59434345a63Smrg    Bool absolute;
59534345a63Smrg
59634345a63Smrg    act = (XkbPtrAction *) action;
59734345a63Smrg    if ((array_ndx != NULL) && ((field == F_X) || (field == F_Y)))
59834345a63Smrg        return ReportActionNotArray(action->type, field);
59934345a63Smrg
60034345a63Smrg    if ((field == F_X) || (field == F_Y))
60134345a63Smrg    {
60234345a63Smrg        if ((value->op == OpNegate) || (value->op == OpUnaryPlus))
60334345a63Smrg            absolute = False;
60434345a63Smrg        else
60534345a63Smrg            absolute = True;
60634345a63Smrg        if (!ExprResolveInteger(value, &rtrn, NULL, NULL))
60734345a63Smrg            return ReportMismatch(action->type, field, "integer");
60834345a63Smrg        if (field == F_X)
60934345a63Smrg        {
61034345a63Smrg            if (absolute)
61134345a63Smrg                act->flags |= XkbSA_MoveAbsoluteX;
61234345a63Smrg            XkbSetPtrActionX(act, rtrn.ival);
61334345a63Smrg        }
61434345a63Smrg        else
61534345a63Smrg        {
61634345a63Smrg            if (absolute)
61734345a63Smrg                act->flags |= XkbSA_MoveAbsoluteY;
61834345a63Smrg            XkbSetPtrActionY(act, rtrn.ival);
61934345a63Smrg        }
62034345a63Smrg        return True;
621f46a6179Smrg    }
62234345a63Smrg    else if (field == F_Accel)
62334345a63Smrg    {
62434345a63Smrg        if (!ExprResolveBoolean(value, &rtrn, NULL, NULL))
62534345a63Smrg            return ReportMismatch(action->type, field, "boolean");
62634345a63Smrg        if (rtrn.uval)
62734345a63Smrg            act->flags &= ~XkbSA_NoAcceleration;
62834345a63Smrg        else
62934345a63Smrg            act->flags |= XkbSA_NoAcceleration;
630f46a6179Smrg    }
63134345a63Smrg    return ReportIllegal(action->type, field);
632f46a6179Smrg}
633f46a6179Smrg
634f46a6179Smrgstatic LookupEntry btnNames[] = {
63534345a63Smrg    {"button1", 1},
63634345a63Smrg    {"button2", 2},
63734345a63Smrg    {"button3", 3},
63834345a63Smrg    {"button4", 4},
63934345a63Smrg    {"button5", 5},
64034345a63Smrg    {"default", 0},
64134345a63Smrg    {NULL, 0}
642f46a6179Smrg};
643f46a6179Smrg
644f46a6179Smrgstatic LookupEntry lockWhich[] = {
64534345a63Smrg    {"both", 0},
64634345a63Smrg    {"lock", XkbSA_LockNoUnlock},
64734345a63Smrg    {"neither", (XkbSA_LockNoLock | XkbSA_LockNoUnlock)},
64834345a63Smrg    {"unlock", XkbSA_LockNoLock},
64934345a63Smrg    {NULL, 0}
650f46a6179Smrg};
651f46a6179Smrg
652f46a6179Smrgstatic Bool
65334345a63SmrgHandlePtrBtn(XkbDescPtr xkb,
65434345a63Smrg             XkbAnyAction * action,
65534345a63Smrg             unsigned field, ExprDef * array_ndx, ExprDef * value)
656f46a6179Smrg{
65734345a63Smrg    ExprResult rtrn;
65834345a63Smrg    XkbPtrBtnAction *act;
65934345a63Smrg
66034345a63Smrg    act = (XkbPtrBtnAction *) action;
66134345a63Smrg    if (field == F_Button)
66234345a63Smrg    {
66334345a63Smrg        if (array_ndx != NULL)
66434345a63Smrg            return ReportActionNotArray(action->type, field);
66534345a63Smrg        if (!ExprResolveInteger
66634345a63Smrg            (value, &rtrn, SimpleLookup, (XPointer) btnNames))
66734345a63Smrg            return ReportMismatch(action->type, field,
66834345a63Smrg                                  "integer (range 1..5)");
66934345a63Smrg        if ((rtrn.ival < 0) || (rtrn.ival > 5))
67034345a63Smrg        {
67134345a63Smrg            ERROR("Button must specify default or be in the range 1..5\n");
67234345a63Smrg            ACTION1("Illegal button value %d ignored\n", rtrn.ival);
67334345a63Smrg            return False;
67434345a63Smrg        }
67534345a63Smrg        act->button = rtrn.ival;
67634345a63Smrg        return True;
677f46a6179Smrg    }
67834345a63Smrg    else if ((action->type == XkbSA_LockPtrBtn) && (field == F_Affect))
67934345a63Smrg    {
68034345a63Smrg        if (array_ndx != NULL)
68134345a63Smrg            return ReportActionNotArray(action->type, field);
68234345a63Smrg        if (!ExprResolveEnum(value, &rtrn, lockWhich))
68334345a63Smrg            return ReportMismatch(action->type, field, "lock or unlock");
68434345a63Smrg        act->flags &= ~(XkbSA_LockNoLock | XkbSA_LockNoUnlock);
68534345a63Smrg        act->flags |= rtrn.ival;
68634345a63Smrg        return True;
687f46a6179Smrg    }
68834345a63Smrg    else if (field == F_Count)
68934345a63Smrg    {
69034345a63Smrg        if (array_ndx != NULL)
69134345a63Smrg            return ReportActionNotArray(action->type, field);
69234345a63Smrg        if (!ExprResolveInteger
69334345a63Smrg            (value, &rtrn, SimpleLookup, (XPointer) btnNames))
69434345a63Smrg            return ReportMismatch(action->type, field, "integer");
69534345a63Smrg        if ((rtrn.ival < 0) || (rtrn.ival > 255))
69634345a63Smrg        {
69734345a63Smrg            ERROR("The count field must have a value in the range 0..255\n");
69834345a63Smrg            ACTION1("Illegal count %d ignored\n", rtrn.ival);
69934345a63Smrg            return False;
70034345a63Smrg        }
70134345a63Smrg        act->count = rtrn.ival;
70234345a63Smrg        return True;
703f46a6179Smrg    }
70434345a63Smrg    return ReportIllegal(action->type, field);
705f46a6179Smrg}
706f46a6179Smrg
707f46a6179Smrgstatic LookupEntry ptrDflts[] = {
70834345a63Smrg    {"dfltbtn", XkbSA_AffectDfltBtn},
70934345a63Smrg    {"defaultbutton", XkbSA_AffectDfltBtn},
71034345a63Smrg    {"button", XkbSA_AffectDfltBtn},
71134345a63Smrg    {NULL, 0}
712f46a6179Smrg};
713f46a6179Smrg
714f46a6179Smrgstatic Bool
71534345a63SmrgHandleSetPtrDflt(XkbDescPtr xkb,
71634345a63Smrg                 XkbAnyAction * action,
71734345a63Smrg                 unsigned field, ExprDef * array_ndx, ExprDef * value)
718f46a6179Smrg{
71934345a63Smrg    ExprResult rtrn;
72034345a63Smrg    XkbPtrDfltAction *act;
72134345a63Smrg
72234345a63Smrg    act = (XkbPtrDfltAction *) action;
72334345a63Smrg    if (field == F_Affect)
72434345a63Smrg    {
72534345a63Smrg        if (array_ndx != NULL)
72634345a63Smrg            return ReportActionNotArray(action->type, field);
72734345a63Smrg        if (!ExprResolveEnum(value, &rtrn, ptrDflts))
72834345a63Smrg            return ReportMismatch(action->type, field, "pointer component");
72934345a63Smrg        act->affect = rtrn.uval;
73034345a63Smrg        return True;
731f46a6179Smrg    }
73234345a63Smrg    else if ((field == F_Button) || (field == F_Value))
73334345a63Smrg    {
73434345a63Smrg        ExprDef *btn;
73534345a63Smrg        if (array_ndx != NULL)
73634345a63Smrg            return ReportActionNotArray(action->type, field);
73734345a63Smrg        if ((value->op == OpNegate) || (value->op == OpUnaryPlus))
73834345a63Smrg        {
73934345a63Smrg            act->flags &= ~XkbSA_DfltBtnAbsolute;
74034345a63Smrg            btn = value->value.child;
74134345a63Smrg        }
74234345a63Smrg        else
74334345a63Smrg        {
74434345a63Smrg            act->flags |= XkbSA_DfltBtnAbsolute;
74534345a63Smrg            btn = value;
74634345a63Smrg        }
74734345a63Smrg
74834345a63Smrg        if (!ExprResolveInteger
74934345a63Smrg            (btn, &rtrn, SimpleLookup, (XPointer) btnNames))
75034345a63Smrg            return ReportMismatch(action->type, field,
75134345a63Smrg                                  "integer (range 1..5)");
75234345a63Smrg        if ((rtrn.ival < 0) || (rtrn.ival > 5))
75334345a63Smrg        {
75434345a63Smrg            ERROR("New default button value must be in the range 1..5\n");
75534345a63Smrg            ACTION1("Illegal default button value %d ignored\n", rtrn.ival);
75634345a63Smrg            return False;
75734345a63Smrg        }
75834345a63Smrg        if (rtrn.ival == 0)
75934345a63Smrg        {
76034345a63Smrg            ERROR("Cannot set default pointer button to \"default\"\n");
76134345a63Smrg            ACTION("Illegal default button setting ignored\n");
76234345a63Smrg            return False;
76334345a63Smrg        }
76434345a63Smrg        if (value->op == OpNegate)
76534345a63Smrg            XkbSASetPtrDfltValue(act, -rtrn.ival);
76634345a63Smrg        else
76734345a63Smrg            XkbSASetPtrDfltValue(act, rtrn.ival);
76834345a63Smrg        return True;
769f46a6179Smrg    }
77034345a63Smrg    return ReportIllegal(action->type, field);
771f46a6179Smrg}
772f46a6179Smrg
77334345a63Smrgstatic LookupEntry isoNames[] = {
77434345a63Smrg    {"mods", XkbSA_ISONoAffectMods},
77534345a63Smrg    {"modifiers", XkbSA_ISONoAffectMods},
77634345a63Smrg    {"group", XkbSA_ISONoAffectGroup},
77734345a63Smrg    {"groups", XkbSA_ISONoAffectGroup},
77834345a63Smrg    {"ptr", XkbSA_ISONoAffectPtr},
77934345a63Smrg    {"pointer", XkbSA_ISONoAffectPtr},
78034345a63Smrg    {"ctrls", XkbSA_ISONoAffectCtrls},
78134345a63Smrg    {"controls", XkbSA_ISONoAffectCtrls},
78234345a63Smrg    {"all", ~((unsigned) 0)},
78334345a63Smrg    {"none", 0},
78434345a63Smrg    {NULL, 0},
785f46a6179Smrg};
786f46a6179Smrg
787f46a6179Smrgstatic Bool
78834345a63SmrgHandleISOLock(XkbDescPtr xkb,
78934345a63Smrg              XkbAnyAction * action,
79034345a63Smrg              unsigned field, ExprDef * array_ndx, ExprDef * value)
791f46a6179Smrg{
79234345a63Smrg    ExprResult rtrn;
79334345a63Smrg    XkbISOAction *act;
79434345a63Smrg    unsigned flags, mods;
79534345a63Smrg    int group;
79634345a63Smrg
79734345a63Smrg    act = (XkbISOAction *) action;
79834345a63Smrg    switch (field)
79934345a63Smrg    {
80034345a63Smrg    case F_Modifiers:
80134345a63Smrg        if (array_ndx != NULL)
80234345a63Smrg            return ReportActionNotArray(action->type, field);
80334345a63Smrg        flags = act->flags;
80434345a63Smrg        if (CheckModifierField(xkb, action->type, value, &flags, &mods))
80534345a63Smrg        {
80634345a63Smrg            act->flags = flags & (~XkbSA_ISODfltIsGroup);
80734345a63Smrg            act->real_mods = mods & 0xff;
80834345a63Smrg            mods = (mods >> 8) & 0xff;
80934345a63Smrg            XkbSetModActionVMods(act, mods);
81034345a63Smrg            return True;
81134345a63Smrg        }
81234345a63Smrg        return False;
81334345a63Smrg    case F_Group:
81434345a63Smrg        if (array_ndx != NULL)
81534345a63Smrg            return ReportActionNotArray(action->type, field);
81634345a63Smrg        flags = act->flags;
81734345a63Smrg        if (CheckGroupField(action->type, value, &flags, &group))
81834345a63Smrg        {
81934345a63Smrg            act->flags = flags | XkbSA_ISODfltIsGroup;
82034345a63Smrg            XkbSASetGroup(act, group);
82134345a63Smrg            return True;
82234345a63Smrg        }
82334345a63Smrg        return False;
82434345a63Smrg    case F_Affect:
82534345a63Smrg        if (array_ndx != NULL)
82634345a63Smrg            return ReportActionNotArray(action->type, field);
82734345a63Smrg        if (!ExprResolveMask(value, &rtrn, SimpleLookup, (XPointer) isoNames))
82834345a63Smrg            return ReportMismatch(action->type, field, "keyboard component");
82934345a63Smrg        act->affect = (~rtrn.uval) & XkbSA_ISOAffectMask;
83034345a63Smrg        return True;
831f46a6179Smrg    }
83234345a63Smrg    return ReportIllegal(action->type, field);
833f46a6179Smrg}
834f46a6179Smrg
835f46a6179Smrgstatic Bool
83634345a63SmrgHandleSwitchScreen(XkbDescPtr xkb,
83734345a63Smrg                   XkbAnyAction * action,
83834345a63Smrg                   unsigned field, ExprDef * array_ndx, ExprDef * value)
839f46a6179Smrg{
84034345a63Smrg    ExprResult rtrn;
84134345a63Smrg    XkbSwitchScreenAction *act;
84234345a63Smrg
84334345a63Smrg    act = (XkbSwitchScreenAction *) action;
84434345a63Smrg    if (field == F_Screen)
84534345a63Smrg    {
84634345a63Smrg        ExprDef *scrn;
84734345a63Smrg        if (array_ndx != NULL)
84834345a63Smrg            return ReportActionNotArray(action->type, field);
84934345a63Smrg        if ((value->op == OpNegate) || (value->op == OpUnaryPlus))
85034345a63Smrg        {
85134345a63Smrg            act->flags &= ~XkbSA_SwitchAbsolute;
85234345a63Smrg            scrn = value->value.child;
85334345a63Smrg        }
85434345a63Smrg        else
85534345a63Smrg        {
85634345a63Smrg            act->flags |= XkbSA_SwitchAbsolute;
85734345a63Smrg            scrn = value;
85834345a63Smrg        }
85934345a63Smrg
86034345a63Smrg        if (!ExprResolveInteger(scrn, &rtrn, NULL, NULL))
86134345a63Smrg            return ReportMismatch(action->type, field, "integer (0..255)");
86234345a63Smrg        if ((rtrn.ival < 0) || (rtrn.ival > 255))
86334345a63Smrg        {
86434345a63Smrg            ERROR("Screen index must be in the range 1..255\n");
86534345a63Smrg            ACTION1("Illegal screen value %d ignored\n", rtrn.ival);
86634345a63Smrg            return False;
86734345a63Smrg        }
86834345a63Smrg        if (value->op == OpNegate)
86934345a63Smrg            XkbSASetScreen(act, -rtrn.ival);
87034345a63Smrg        else
87134345a63Smrg            XkbSASetScreen(act, rtrn.ival);
87234345a63Smrg        return True;
873f46a6179Smrg    }
87434345a63Smrg    else if (field == F_Same)
87534345a63Smrg    {
87634345a63Smrg        if (array_ndx != NULL)
87734345a63Smrg            return ReportActionNotArray(action->type, field);
87834345a63Smrg        if (!ExprResolveBoolean(value, &rtrn, NULL, NULL))
87934345a63Smrg            return ReportMismatch(action->type, field, "boolean");
88034345a63Smrg        if (rtrn.uval)
88134345a63Smrg            act->flags &= ~XkbSA_SwitchApplication;
88234345a63Smrg        else
88334345a63Smrg            act->flags |= XkbSA_SwitchApplication;
88434345a63Smrg        return True;
885f46a6179Smrg    }
88634345a63Smrg    return ReportIllegal(action->type, field);
887f46a6179Smrg}
888f46a6179Smrg
88934345a63SmrgLookupEntry ctrlNames[] = {
89034345a63Smrg    {"repeatkeys", XkbRepeatKeysMask}
89134345a63Smrg    ,
89234345a63Smrg    {"repeat", XkbRepeatKeysMask}
89334345a63Smrg    ,
89434345a63Smrg    {"autorepeat", XkbRepeatKeysMask}
89534345a63Smrg    ,
89634345a63Smrg    {"slowkeys", XkbSlowKeysMask}
89734345a63Smrg    ,
89834345a63Smrg    {"bouncekeys", XkbBounceKeysMask}
89934345a63Smrg    ,
90034345a63Smrg    {"stickykeys", XkbStickyKeysMask}
90134345a63Smrg    ,
90234345a63Smrg    {"mousekeys", XkbMouseKeysMask}
90334345a63Smrg    ,
90434345a63Smrg    {"mousekeysaccel", XkbMouseKeysAccelMask}
90534345a63Smrg    ,
90634345a63Smrg    {"accessxkeys", XkbAccessXKeysMask}
90734345a63Smrg    ,
90834345a63Smrg    {"accessxtimeout", XkbAccessXTimeoutMask}
90934345a63Smrg    ,
91034345a63Smrg    {"accessxfeedback", XkbAccessXFeedbackMask}
91134345a63Smrg    ,
91234345a63Smrg    {"audiblebell", XkbAudibleBellMask}
91334345a63Smrg    ,
91434345a63Smrg    {"overlay1", XkbOverlay1Mask}
91534345a63Smrg    ,
91634345a63Smrg    {"overlay2", XkbOverlay2Mask}
91734345a63Smrg    ,
91834345a63Smrg    {"ignoregrouplock", XkbIgnoreGroupLockMask}
91934345a63Smrg    ,
92034345a63Smrg    {"all", XkbAllBooleanCtrlsMask}
92134345a63Smrg    ,
92234345a63Smrg    {"none", 0}
92334345a63Smrg    ,
92434345a63Smrg    {NULL, 0}
925f46a6179Smrg};
926f46a6179Smrg
927f46a6179Smrgstatic Bool
92834345a63SmrgHandleSetLockControls(XkbDescPtr xkb,
92934345a63Smrg                      XkbAnyAction * action,
93034345a63Smrg                      unsigned field, ExprDef * array_ndx, ExprDef * value)
931f46a6179Smrg{
93234345a63Smrg    ExprResult rtrn;
93334345a63Smrg    XkbCtrlsAction *act;
93434345a63Smrg
93534345a63Smrg    act = (XkbCtrlsAction *) action;
93634345a63Smrg    if (field == F_Controls)
93734345a63Smrg    {
93834345a63Smrg        if (array_ndx != NULL)
93934345a63Smrg            return ReportActionNotArray(action->type, field);
94034345a63Smrg        if (!ExprResolveMask
94134345a63Smrg            (value, &rtrn, SimpleLookup, (XPointer) ctrlNames))
94234345a63Smrg            return ReportMismatch(action->type, field, "controls mask");
94334345a63Smrg        XkbActionSetCtrls(act, rtrn.uval);
94434345a63Smrg        return True;
945f46a6179Smrg    }
94634345a63Smrg    return ReportIllegal(action->type, field);
947f46a6179Smrg}
948f46a6179Smrg
94934345a63Smrgstatic LookupEntry evNames[] = {
95034345a63Smrg    {"press", XkbSA_MessageOnPress},
95134345a63Smrg    {"keypress", XkbSA_MessageOnPress},
95234345a63Smrg    {"release", XkbSA_MessageOnRelease},
95334345a63Smrg    {"keyrelease", XkbSA_MessageOnRelease},
95434345a63Smrg    {"all", XkbSA_MessageOnPress | XkbSA_MessageOnRelease},
95534345a63Smrg    {"none", 0},
95634345a63Smrg    {NULL, 0}
957f46a6179Smrg};
958f46a6179Smrg
959f46a6179Smrgstatic Bool
96034345a63SmrgHandleActionMessage(XkbDescPtr xkb,
96134345a63Smrg                    XkbAnyAction * action,
96234345a63Smrg                    unsigned field, ExprDef * array_ndx, ExprDef * value)
963f46a6179Smrg{
96434345a63Smrg    ExprResult rtrn;
96534345a63Smrg    XkbMessageAction *act;
96634345a63Smrg
96734345a63Smrg    act = (XkbMessageAction *) action;
96834345a63Smrg    switch (field)
96934345a63Smrg    {
97034345a63Smrg    case F_Report:
97134345a63Smrg        if (array_ndx != NULL)
97234345a63Smrg            return ReportActionNotArray(action->type, field);
97334345a63Smrg        if (!ExprResolveMask(value, &rtrn, SimpleLookup, (XPointer) evNames))
97434345a63Smrg            return ReportMismatch(action->type, field, "key event mask");
97534345a63Smrg        act->flags &= ~(XkbSA_MessageOnPress | XkbSA_MessageOnRelease);
97634345a63Smrg        act->flags =
97734345a63Smrg            rtrn.uval & (XkbSA_MessageOnPress | XkbSA_MessageOnRelease);
97834345a63Smrg        return True;
97934345a63Smrg    case F_GenKeyEvent:
98034345a63Smrg        if (array_ndx != NULL)
98134345a63Smrg            return ReportActionNotArray(action->type, field);
98234345a63Smrg        if (!ExprResolveBoolean(value, &rtrn, NULL, NULL))
98334345a63Smrg            return ReportMismatch(action->type, field, "boolean");
98434345a63Smrg        if (rtrn.uval)
98534345a63Smrg            act->flags |= XkbSA_MessageGenKeyEvent;
98634345a63Smrg        else
98734345a63Smrg            act->flags &= ~XkbSA_MessageGenKeyEvent;
98834345a63Smrg        return True;
98934345a63Smrg    case F_Data:
99034345a63Smrg        if (array_ndx == NULL)
99134345a63Smrg        {
99234345a63Smrg            if (!ExprResolveString(value, &rtrn, NULL, NULL))
99334345a63Smrg                return ReportMismatch(action->type, field, "string");
99434345a63Smrg            else
99534345a63Smrg            {
99634345a63Smrg                int len = strlen(rtrn.str);
99734345a63Smrg                if ((len < 1) || (len > 6))
99834345a63Smrg                {
99934345a63Smrg                    WARN("An action message can hold only 6 bytes\n");
100034345a63Smrg                    ACTION1("Extra %d bytes ignored\n", len - 6);
100134345a63Smrg                }
100234345a63Smrg                strncpy((char *) act->message, rtrn.str, 6);
100334345a63Smrg            }
100434345a63Smrg            return True;
100534345a63Smrg        }
100634345a63Smrg        else
100734345a63Smrg        {
100834345a63Smrg            unsigned ndx;
100934345a63Smrg            if (!ExprResolveInteger(array_ndx, &rtrn, NULL, NULL))
101034345a63Smrg            {
101134345a63Smrg                ERROR("Array subscript must be integer\n");
101234345a63Smrg                ACTION("Illegal subscript ignored\n");
101334345a63Smrg                return False;
101434345a63Smrg            }
101534345a63Smrg            ndx = rtrn.uval;
101634345a63Smrg            if (ndx > 5)
101734345a63Smrg            {
101834345a63Smrg                ERROR("An action message is at most 6 bytes long\n");
101934345a63Smrg                ACTION1("Attempt to use data[%d] ignored\n", ndx);
102034345a63Smrg                return False;
102134345a63Smrg            }
102234345a63Smrg            if (!ExprResolveInteger(value, &rtrn, NULL, NULL))
102334345a63Smrg                return ReportMismatch(action->type, field, "integer");
102434345a63Smrg            if ((rtrn.ival < 0) || (rtrn.ival > 255))
102534345a63Smrg            {
102634345a63Smrg                ERROR("Message data must be in the range 0..255\n");
102734345a63Smrg                ACTION1("Illegal datum %d ignored\n", rtrn.ival);
102834345a63Smrg                return False;
102934345a63Smrg            }
103034345a63Smrg            act->message[ndx] = rtrn.uval;
103134345a63Smrg        }
103234345a63Smrg        return True;
1033f46a6179Smrg    }
103434345a63Smrg    return ReportIllegal(action->type, field);
1035f46a6179Smrg}
1036f46a6179Smrg
1037f46a6179Smrgstatic Bool
103834345a63SmrgHandleRedirectKey(XkbDescPtr xkb,
103934345a63Smrg                  XkbAnyAction * action,
104034345a63Smrg                  unsigned field, ExprDef * array_ndx, ExprDef * value)
1041f46a6179Smrg{
104234345a63Smrg    ExprResult rtrn;
104334345a63Smrg    XkbRedirectKeyAction *act;
104434345a63Smrg    unsigned t1, t2, vmods, vmask;
104534345a63Smrg    unsigned long tmp;
104634345a63Smrg
104734345a63Smrg    if (array_ndx != NULL)
104834345a63Smrg        return ReportActionNotArray(action->type, field);
104934345a63Smrg
105034345a63Smrg    act = (XkbRedirectKeyAction *) action;
105134345a63Smrg    switch (field)
105234345a63Smrg    {
105334345a63Smrg    case F_Keycode:
105434345a63Smrg        if (!ExprResolveKeyName(value, &rtrn, NULL, NULL))
105534345a63Smrg            return ReportMismatch(action->type, field, "key name");
105634345a63Smrg        tmp = KeyNameToLong(rtrn.keyName.name);
105734345a63Smrg        if (!FindNamedKey(xkb, tmp, &t1, True, CreateKeyNames(xkb), 0))
105834345a63Smrg        {
105934345a63Smrg            return ReportNotFound(action->type, field, "Key",
106034345a63Smrg                                  XkbKeyNameText(rtrn.keyName.name,
106134345a63Smrg                                                 XkbMessage));
106234345a63Smrg        }
106334345a63Smrg        act->new_key = t1;
106434345a63Smrg        return True;
106534345a63Smrg    case F_ModsToClear:
106634345a63Smrg    case F_Modifiers:
106734345a63Smrg        t1 = 0;
106834345a63Smrg        if (CheckModifierField(xkb, action->type, value, &t1, &t2))
106934345a63Smrg        {
107034345a63Smrg            act->mods_mask |= (t2 & 0xff);
107134345a63Smrg            if (field == F_Modifiers)
107234345a63Smrg                act->mods |= (t2 & 0xff);
107334345a63Smrg            else
107434345a63Smrg                act->mods &= ~(t2 & 0xff);
107534345a63Smrg
107634345a63Smrg            t2 = (t2 >> 8) & 0xffff;
107734345a63Smrg            vmods = XkbSARedirectVMods(act);
107834345a63Smrg            vmask = XkbSARedirectVModsMask(act);
107934345a63Smrg            vmask |= t2;
108034345a63Smrg            if (field == F_Modifiers)
108134345a63Smrg                vmods |= t2;
108234345a63Smrg            else
108334345a63Smrg                vmods &= ~t2;
108434345a63Smrg            XkbSARedirectSetVMods(act, vmods);
108534345a63Smrg            XkbSARedirectSetVModsMask(act, vmask);
108634345a63Smrg            return True;
108734345a63Smrg        }
108834345a63Smrg        return True;
1089f46a6179Smrg    }
109034345a63Smrg    return ReportIllegal(action->type, field);
1091f46a6179Smrg}
1092f46a6179Smrg
1093f46a6179Smrgstatic Bool
109434345a63SmrgHandleDeviceBtn(XkbDescPtr xkb,
109534345a63Smrg                XkbAnyAction * action,
109634345a63Smrg                unsigned field, ExprDef * array_ndx, ExprDef * value)
1097f46a6179Smrg{
109834345a63Smrg    ExprResult rtrn;
109934345a63Smrg    XkbDeviceBtnAction *act;
110034345a63Smrg
110134345a63Smrg    act = (XkbDeviceBtnAction *) action;
110234345a63Smrg    if (field == F_Button)
110334345a63Smrg    {
110434345a63Smrg        if (array_ndx != NULL)
110534345a63Smrg            return ReportActionNotArray(action->type, field);
110634345a63Smrg        if (!ExprResolveInteger(value, &rtrn, NULL, NULL))
110734345a63Smrg            return ReportMismatch(action->type, field,
110834345a63Smrg                                  "integer (range 1..255)");
110934345a63Smrg        if ((rtrn.ival < 0) || (rtrn.ival > 255))
111034345a63Smrg        {
111134345a63Smrg            ERROR("Button must specify default or be in the range 1..255\n");
111234345a63Smrg            ACTION1("Illegal button value %d ignored\n", rtrn.ival);
111334345a63Smrg            return False;
111434345a63Smrg        }
111534345a63Smrg        act->button = rtrn.ival;
111634345a63Smrg        return True;
1117f46a6179Smrg    }
111834345a63Smrg    else if ((action->type == XkbSA_LockDeviceBtn) && (field == F_Affect))
111934345a63Smrg    {
112034345a63Smrg        if (array_ndx != NULL)
112134345a63Smrg            return ReportActionNotArray(action->type, field);
112234345a63Smrg        if (!ExprResolveEnum(value, &rtrn, lockWhich))
112334345a63Smrg            return ReportMismatch(action->type, field, "lock or unlock");
112434345a63Smrg        act->flags &= ~(XkbSA_LockNoLock | XkbSA_LockNoUnlock);
112534345a63Smrg        act->flags |= rtrn.ival;
112634345a63Smrg        return True;
1127f46a6179Smrg    }
112834345a63Smrg    else if (field == F_Count)
112934345a63Smrg    {
113034345a63Smrg        if (array_ndx != NULL)
113134345a63Smrg            return ReportActionNotArray(action->type, field);
113234345a63Smrg        if (!ExprResolveInteger
113334345a63Smrg            (value, &rtrn, SimpleLookup, (XPointer) btnNames))
113434345a63Smrg            return ReportMismatch(action->type, field, "integer");
113534345a63Smrg        if ((rtrn.ival < 0) || (rtrn.ival > 255))
113634345a63Smrg        {
113734345a63Smrg            ERROR("The count field must have a value in the range 0..255\n");
113834345a63Smrg            ACTION1("Illegal count %d ignored\n", rtrn.ival);
113934345a63Smrg            return False;
114034345a63Smrg        }
114134345a63Smrg        act->count = rtrn.ival;
114234345a63Smrg        return True;
1143f46a6179Smrg    }
114434345a63Smrg    else if (field == F_Device)
114534345a63Smrg    {
114634345a63Smrg        if (array_ndx != NULL)
114734345a63Smrg            return ReportActionNotArray(action->type, field);
114834345a63Smrg        if (!ExprResolveInteger(value, &rtrn, NULL, NULL))
114934345a63Smrg            return ReportMismatch(action->type, field,
115034345a63Smrg                                  "integer (range 1..255)");
115134345a63Smrg        if ((rtrn.ival < 0) || (rtrn.ival > 255))
115234345a63Smrg        {
115334345a63Smrg            ERROR("Device must specify default or be in the range 1..255\n");
115434345a63Smrg            ACTION1("Illegal device value %d ignored\n", rtrn.ival);
115534345a63Smrg            return False;
115634345a63Smrg        }
115734345a63Smrg        act->device = rtrn.ival;
115834345a63Smrg        return True;
1159f46a6179Smrg    }
116034345a63Smrg    return ReportIllegal(action->type, field);
1161f46a6179Smrg}
1162f46a6179Smrg
1163f46a6179Smrgstatic Bool
116434345a63SmrgHandleDeviceValuator(XkbDescPtr xkb,
116534345a63Smrg                     XkbAnyAction * action,
116634345a63Smrg                     unsigned field, ExprDef * array_ndx, ExprDef * value)
1167f46a6179Smrg{
1168f46a6179Smrg#if 0
116934345a63Smrg    ExprResult rtrn;
117034345a63Smrg    XkbDeviceValuatorAction *act;
1171f46a6179Smrg
117234345a63Smrg    act = (XkbDeviceValuatorAction *) action;
1173f46a6179Smrg    /*  XXX - Not yet implemented */
1174f46a6179Smrg#endif
1175f46a6179Smrg    return False;
1176f46a6179Smrg}
1177f46a6179Smrg
1178f46a6179Smrgstatic Bool
117934345a63SmrgHandlePrivate(XkbDescPtr xkb,
118034345a63Smrg              XkbAnyAction * action,
118134345a63Smrg              unsigned field, ExprDef * array_ndx, ExprDef * value)
1182f46a6179Smrg{
118334345a63Smrg    ExprResult rtrn;
118434345a63Smrg
118534345a63Smrg    switch (field)
118634345a63Smrg    {
118734345a63Smrg    case F_Type:
118834345a63Smrg        if (!ExprResolveInteger(value, &rtrn, NULL, NULL))
118934345a63Smrg            return ReportMismatch(PrivateAction, field, "integer");
119034345a63Smrg        if ((rtrn.ival < 0) || (rtrn.ival > 255))
119134345a63Smrg        {
119234345a63Smrg            ERROR("Private action type must be in the range 0..255\n");
119334345a63Smrg            ACTION1("Illegal type %d ignored\n", rtrn.ival);
119434345a63Smrg            return False;
119534345a63Smrg        }
119634345a63Smrg        action->type = rtrn.uval;
119734345a63Smrg        return True;
119834345a63Smrg    case F_Data:
119934345a63Smrg        if (array_ndx == NULL)
120034345a63Smrg        {
120134345a63Smrg            if (!ExprResolveString(value, &rtrn, NULL, NULL))
120234345a63Smrg                return ReportMismatch(action->type, field, "string");
120334345a63Smrg            else
120434345a63Smrg            {
120534345a63Smrg                int len = strlen(rtrn.str);
120634345a63Smrg                if ((len < 1) || (len > 7))
120734345a63Smrg                {
120834345a63Smrg                    WARN("A private action has 7 data bytes\n");
120934345a63Smrg                    ACTION1("Extra %d bytes ignored\n", len - 6);
121034345a63Smrg                    return False;
121134345a63Smrg                }
121234345a63Smrg                strncpy((char *) action->data, rtrn.str, 7);
121334345a63Smrg            }
121434345a63Smrg            return True;
121534345a63Smrg        }
121634345a63Smrg        else
121734345a63Smrg        {
121834345a63Smrg            unsigned ndx;
121934345a63Smrg            if (!ExprResolveInteger(array_ndx, &rtrn, NULL, NULL))
122034345a63Smrg            {
122134345a63Smrg                ERROR("Array subscript must be integer\n");
122234345a63Smrg                ACTION("Illegal subscript ignored\n");
122334345a63Smrg                return False;
122434345a63Smrg            }
122534345a63Smrg            ndx = rtrn.uval;
122634345a63Smrg            if (ndx > 6)
122734345a63Smrg            {
122834345a63Smrg                ERROR("The data for a private action is 7 bytes long\n");
122934345a63Smrg                ACTION1("Attempt to use data[%d] ignored\n", ndx);
123034345a63Smrg                return False;
123134345a63Smrg            }
123234345a63Smrg            if (!ExprResolveInteger(value, &rtrn, NULL, NULL))
123334345a63Smrg                return ReportMismatch(action->type, field, "integer");
123434345a63Smrg            if ((rtrn.ival < 0) || (rtrn.ival > 255))
123534345a63Smrg            {
123634345a63Smrg                ERROR("All data for a private action must be 0..255\n");
123734345a63Smrg                ACTION1("Illegal datum %d ignored\n", rtrn.ival);
123834345a63Smrg                return False;
123934345a63Smrg            }
124034345a63Smrg            action->data[ndx] = rtrn.uval;
124134345a63Smrg            return True;
124234345a63Smrg        }
1243f46a6179Smrg    }
124434345a63Smrg    return ReportIllegal(PrivateAction, field);
1245f46a6179Smrg}
1246f46a6179Smrg
124734345a63Smrgtypedef Bool(*actionHandler) (XkbDescPtr /* xkb */ ,
124834345a63Smrg                              XkbAnyAction * /* action */ ,
124934345a63Smrg                              unsigned /* field */ ,
125034345a63Smrg                              ExprDef * /* array_ndx */ ,
125134345a63Smrg                              ExprDef * /* value */
125234345a63Smrg    );
125334345a63Smrg
125434345a63Smrgstatic actionHandler handleAction[XkbSA_NumActions + 1] = {
125534345a63Smrg    HandleNoAction /* NoAction     */ ,
125634345a63Smrg    HandleSetLatchMods /* SetMods      */ ,
125734345a63Smrg    HandleSetLatchMods /* LatchMods    */ ,
125834345a63Smrg    HandleLockMods /* LockMods     */ ,
125934345a63Smrg    HandleSetLatchGroup /* SetGroup     */ ,
126034345a63Smrg    HandleSetLatchGroup /* LatchGroup   */ ,
126134345a63Smrg    HandleLockGroup /* LockGroup    */ ,
126234345a63Smrg    HandleMovePtr /* MovePtr      */ ,
126334345a63Smrg    HandlePtrBtn /* PtrBtn       */ ,
126434345a63Smrg    HandlePtrBtn /* LockPtrBtn   */ ,
126534345a63Smrg    HandleSetPtrDflt /* SetPtrDflt   */ ,
126634345a63Smrg    HandleISOLock /* ISOLock      */ ,
126734345a63Smrg    HandleNoAction /* Terminate    */ ,
126834345a63Smrg    HandleSwitchScreen /* SwitchScreen */ ,
126934345a63Smrg    HandleSetLockControls /* SetControls  */ ,
127034345a63Smrg    HandleSetLockControls /* LockControls */ ,
127134345a63Smrg    HandleActionMessage /* ActionMessage */ ,
127234345a63Smrg    HandleRedirectKey /* RedirectKey  */ ,
127334345a63Smrg    HandleDeviceBtn /* DeviceBtn    */ ,
127434345a63Smrg    HandleDeviceBtn /* LockDeviceBtn */ ,
127534345a63Smrg    HandleDeviceValuator /* DeviceValuatr */ ,
127634345a63Smrg    HandlePrivate               /* Private      */
1277f46a6179Smrg};
1278f46a6179Smrg
1279f46a6179Smrg/***====================================================================***/
1280f46a6179Smrg
1281f46a6179Smrgstatic void
128234345a63SmrgApplyActionFactoryDefaults(XkbAction * action)
1283f46a6179Smrg{
128434345a63Smrg    if (action->type == XkbSA_SetPtrDflt)
128534345a63Smrg    {                           /* increment default button */
128634345a63Smrg        action->dflt.affect = XkbSA_AffectDfltBtn;
128734345a63Smrg        action->dflt.flags = 0;
128834345a63Smrg        XkbSASetPtrDfltValue(&action->dflt, 1);
1289f46a6179Smrg    }
129034345a63Smrg    else if (action->type == XkbSA_ISOLock)
129134345a63Smrg    {
129234345a63Smrg        action->iso.real_mods = LockMask;
1293f46a6179Smrg    }
1294f46a6179Smrg    return;
1295f46a6179Smrg}
1296f46a6179Smrg
1297f46a6179Smrg
129834345a63Smrgint
129934345a63SmrgHandleActionDef(ExprDef * def,
130034345a63Smrg                XkbDescPtr xkb,
130134345a63Smrg                XkbAnyAction * action, unsigned mergeMode, ActionInfo * info)
1302f46a6179Smrg{
130334345a63Smrg    ExprDef *arg;
130434345a63Smrg    register char *str;
130534345a63Smrg    unsigned tmp, hndlrType;
1306f46a6179Smrg
1307f46a6179Smrg    if (!actionsInitialized)
130834345a63Smrg        ActionsInit();
1309f46a6179Smrg
131034345a63Smrg    if (def->op != ExprActionDecl)
131134345a63Smrg    {
131234345a63Smrg        ERROR1("Expected an action definition, found %s\n",
131334345a63Smrg               exprOpText(def->op));
131434345a63Smrg        return False;
1315f46a6179Smrg    }
131634345a63Smrg    str = XkbAtomGetString(NULL, def->value.action.name);
131734345a63Smrg    if (!str)
131834345a63Smrg    {
131934345a63Smrg        WSGO("Missing name in action definition!!\n");
132034345a63Smrg        return False;
1321f46a6179Smrg    }
132234345a63Smrg    if (!stringToAction(str, &tmp))
132334345a63Smrg    {
132434345a63Smrg        ERROR1("Unknown action %s\n", str);
132534345a63Smrg        return False;
1326f46a6179Smrg    }
132734345a63Smrg    action->type = hndlrType = tmp;
132834345a63Smrg    if (action->type != XkbSA_NoAction)
132934345a63Smrg    {
133034345a63Smrg        ApplyActionFactoryDefaults((XkbAction *) action);
133134345a63Smrg        while (info)
133234345a63Smrg        {
133334345a63Smrg            if ((info->action == XkbSA_NoAction)
133434345a63Smrg                || (info->action == hndlrType))
133534345a63Smrg            {
133634345a63Smrg                if (!(*handleAction[hndlrType]) (xkb, action,
133734345a63Smrg                                                 info->field,
133834345a63Smrg                                                 info->array_ndx,
133934345a63Smrg                                                 info->value))
134034345a63Smrg                {
134134345a63Smrg                    return False;
134234345a63Smrg                }
134334345a63Smrg            }
134434345a63Smrg            info = info->next;
134534345a63Smrg        }
1346f46a6179Smrg    }
134734345a63Smrg    for (arg = def->value.action.args; arg != NULL;
134834345a63Smrg         arg = (ExprDef *) arg->common.next)
134934345a63Smrg    {
135034345a63Smrg        ExprDef *field, *value, *arrayRtrn;
135134345a63Smrg        ExprResult elemRtrn, fieldRtrn;
135234345a63Smrg        unsigned fieldNdx;
135334345a63Smrg
135434345a63Smrg        if (arg->op == OpAssign)
135534345a63Smrg        {
135634345a63Smrg            field = arg->value.binary.left;
135734345a63Smrg            value = arg->value.binary.right;
135834345a63Smrg        }
135934345a63Smrg        else
136034345a63Smrg        {
136134345a63Smrg            if ((arg->op == OpNot) || (arg->op == OpInvert))
136234345a63Smrg            {
136334345a63Smrg                field = arg->value.child;
136434345a63Smrg                value = &constFalse;
136534345a63Smrg            }
136634345a63Smrg            else
136734345a63Smrg            {
136834345a63Smrg                field = arg;
136934345a63Smrg                value = &constTrue;
137034345a63Smrg            }
137134345a63Smrg        }
137234345a63Smrg        if (!ExprResolveLhs(field, &elemRtrn, &fieldRtrn, &arrayRtrn))
137334345a63Smrg            return False;       /* internal error -- already reported */
137434345a63Smrg
137534345a63Smrg        if (elemRtrn.str != NULL)
137634345a63Smrg        {
137734345a63Smrg            ERROR("Cannot change defaults in an action definition\n");
137834345a63Smrg            ACTION2("Ignoring attempt to change %s.%s\n", elemRtrn.str,
137934345a63Smrg                    fieldRtrn.str);
138034345a63Smrg            return False;
138134345a63Smrg        }
138234345a63Smrg        if (!stringToField(fieldRtrn.str, &fieldNdx))
138334345a63Smrg        {
138434345a63Smrg            ERROR1("Unknown field name %s\n", uStringText(fieldRtrn.str));
138534345a63Smrg            return False;
138634345a63Smrg        }
138734345a63Smrg        if (!(*handleAction[hndlrType])
138834345a63Smrg            (xkb, action, fieldNdx, arrayRtrn, value))
138934345a63Smrg        {
139034345a63Smrg            return False;
139134345a63Smrg        }
1392f46a6179Smrg    }
1393f46a6179Smrg    return True;
1394f46a6179Smrg}
1395f46a6179Smrg
1396f46a6179Smrg/***====================================================================***/
1397f46a6179Smrg
139834345a63Smrgint
139934345a63SmrgSetActionField(XkbDescPtr xkb,
1400c82dfdfbSmrg               const char *elem,
1401c82dfdfbSmrg               const char *field,
140234345a63Smrg               ExprDef * array_ndx, ExprDef * value, ActionInfo ** info_rtrn)
1403f46a6179Smrg{
140434345a63Smrg    ActionInfo *new, *old;
1405f46a6179Smrg
1406f46a6179Smrg    if (!actionsInitialized)
140734345a63Smrg        ActionsInit();
1408f46a6179Smrg
140934345a63Smrg    new = uTypedAlloc(ActionInfo);
141034345a63Smrg    if (new == NULL)
141134345a63Smrg    {
141234345a63Smrg        WSGO("Couldn't allocate space for action default\n");
141334345a63Smrg        return False;
1414f46a6179Smrg    }
141534345a63Smrg    if (uStrCaseCmp(elem, "action") == 0)
141634345a63Smrg        new->action = XkbSA_NoAction;
141734345a63Smrg    else
141834345a63Smrg    {
141934345a63Smrg        if (!stringToAction(elem, &new->action))
142034345a63Smrg            return False;
142134345a63Smrg        if (new->action == XkbSA_NoAction)
142234345a63Smrg        {
142334345a63Smrg            ERROR1("\"%s\" is not a valid field in a NoAction action\n",
142434345a63Smrg                   field);
142534345a63Smrg            return False;
142634345a63Smrg        }
1427f46a6179Smrg    }
142834345a63Smrg    if (!stringToField(field, &new->field))
142934345a63Smrg    {
143034345a63Smrg        ERROR1("\"%s\" is not a legal field name\n", field);
143134345a63Smrg        return False;
1432f46a6179Smrg    }
143334345a63Smrg    new->array_ndx = array_ndx;
143434345a63Smrg    new->value = value;
143534345a63Smrg    new->next = NULL;
143634345a63Smrg    old = *info_rtrn;
143734345a63Smrg    while ((old) && (old->next))
143834345a63Smrg        old = old->next;
143934345a63Smrg    if (old == NULL)
144034345a63Smrg        *info_rtrn = new;
144134345a63Smrg    else
144234345a63Smrg        old->next = new;
1443f46a6179Smrg    return True;
1444f46a6179Smrg}
1445f46a6179Smrg
1446f46a6179Smrg/***====================================================================***/
1447f46a6179Smrg
1448f46a6179Smrgvoid
1449f46a6179SmrgActionsInit(void)
1450f46a6179Smrg{
145134345a63Smrg    if (!actionsInitialized)
145234345a63Smrg    {
145334345a63Smrg        bzero((char *) &constTrue, sizeof(constTrue));
145434345a63Smrg        bzero((char *) &constFalse, sizeof(constFalse));
145534345a63Smrg        constTrue.common.stmtType = StmtExpr;
145634345a63Smrg        constTrue.common.next = NULL;
145734345a63Smrg        constTrue.op = ExprIdent;
145834345a63Smrg        constTrue.type = TypeBoolean;
145934345a63Smrg        constTrue.value.str = XkbInternAtom(NULL, "true", False);
146034345a63Smrg        constFalse.common.stmtType = StmtExpr;
146134345a63Smrg        constFalse.common.next = NULL;
146234345a63Smrg        constFalse.op = ExprIdent;
146334345a63Smrg        constFalse.type = TypeBoolean;
146434345a63Smrg        constFalse.value.str = XkbInternAtom(NULL, "false", False);
146534345a63Smrg        actionsInitialized = 1;
1466f46a6179Smrg    }
1467f46a6179Smrg    return;
1468f46a6179Smrg}
1469