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
9bfe6082cSmrg documentation, and that the name of Silicon Graphics not be
10bfe6082cSmrg used in advertising or publicity pertaining to distribution
11f46a6179Smrg of the software without specific prior written permission.
12bfe6082cSmrg 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.
15bfe6082cSmrg
16bfe6082cSmrg SILICON GRAPHICS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS
17bfe6082cSmrg SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
18f46a6179Smrg AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL SILICON
19bfe6082cSmrg GRAPHICS BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL
20bfe6082cSmrg DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
21bfe6082cSmrg 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
416930ead5Smrgstatic void ActionsInit(void);
426930ead5Smrg
43f46a6179Smrg/***====================================================================***/
44f46a6179Smrg
45f46a6179Smrgstatic Bool
46c82dfdfbSmrgstringToAction(const char *str, unsigned *type_rtrn)
47f46a6179Smrg{
4834345a63Smrg    if (str == NULL)
4934345a63Smrg        return False;
5034345a63Smrg
5134345a63Smrg    if (uStrCaseCmp(str, "noaction") == 0)
5234345a63Smrg        *type_rtrn = XkbSA_NoAction;
5334345a63Smrg    else if (uStrCaseCmp(str, "setmods") == 0)
5434345a63Smrg        *type_rtrn = XkbSA_SetMods;
5534345a63Smrg    else if (uStrCaseCmp(str, "latchmods") == 0)
5634345a63Smrg        *type_rtrn = XkbSA_LatchMods;
5734345a63Smrg    else if (uStrCaseCmp(str, "lockmods") == 0)
5834345a63Smrg        *type_rtrn = XkbSA_LockMods;
5934345a63Smrg    else if (uStrCaseCmp(str, "setgroup") == 0)
6034345a63Smrg        *type_rtrn = XkbSA_SetGroup;
6134345a63Smrg    else if (uStrCaseCmp(str, "latchgroup") == 0)
6234345a63Smrg        *type_rtrn = XkbSA_LatchGroup;
6334345a63Smrg    else if (uStrCaseCmp(str, "lockgroup") == 0)
6434345a63Smrg        *type_rtrn = XkbSA_LockGroup;
6534345a63Smrg    else if (uStrCaseCmp(str, "moveptr") == 0)
6634345a63Smrg        *type_rtrn = XkbSA_MovePtr;
6734345a63Smrg    else if (uStrCaseCmp(str, "movepointer") == 0)
6834345a63Smrg        *type_rtrn = XkbSA_MovePtr;
6934345a63Smrg    else if (uStrCaseCmp(str, "ptrbtn") == 0)
7034345a63Smrg        *type_rtrn = XkbSA_PtrBtn;
7134345a63Smrg    else if (uStrCaseCmp(str, "pointerbutton") == 0)
7234345a63Smrg        *type_rtrn = XkbSA_PtrBtn;
7334345a63Smrg    else if (uStrCaseCmp(str, "lockptrbtn") == 0)
7434345a63Smrg        *type_rtrn = XkbSA_LockPtrBtn;
7534345a63Smrg    else if (uStrCaseCmp(str, "lockpointerbutton") == 0)
7634345a63Smrg        *type_rtrn = XkbSA_LockPtrBtn;
7734345a63Smrg    else if (uStrCaseCmp(str, "lockptrbutton") == 0)
7834345a63Smrg        *type_rtrn = XkbSA_LockPtrBtn;
7934345a63Smrg    else if (uStrCaseCmp(str, "lockpointerbtn") == 0)
8034345a63Smrg        *type_rtrn = XkbSA_LockPtrBtn;
8134345a63Smrg    else if (uStrCaseCmp(str, "setptrdflt") == 0)
8234345a63Smrg        *type_rtrn = XkbSA_SetPtrDflt;
8334345a63Smrg    else if (uStrCaseCmp(str, "setpointerdefault") == 0)
8434345a63Smrg        *type_rtrn = XkbSA_SetPtrDflt;
8534345a63Smrg    else if (uStrCaseCmp(str, "isolock") == 0)
8634345a63Smrg        *type_rtrn = XkbSA_ISOLock;
8734345a63Smrg    else if (uStrCaseCmp(str, "terminate") == 0)
8834345a63Smrg        *type_rtrn = XkbSA_Terminate;
8934345a63Smrg    else if (uStrCaseCmp(str, "terminateserver") == 0)
9034345a63Smrg        *type_rtrn = XkbSA_Terminate;
9134345a63Smrg    else if (uStrCaseCmp(str, "switchscreen") == 0)
9234345a63Smrg        *type_rtrn = XkbSA_SwitchScreen;
9334345a63Smrg    else if (uStrCaseCmp(str, "setcontrols") == 0)
9434345a63Smrg        *type_rtrn = XkbSA_SetControls;
9534345a63Smrg    else if (uStrCaseCmp(str, "lockcontrols") == 0)
9634345a63Smrg        *type_rtrn = XkbSA_LockControls;
9734345a63Smrg    else if (uStrCaseCmp(str, "actionmessage") == 0)
9834345a63Smrg        *type_rtrn = XkbSA_ActionMessage;
9934345a63Smrg    else if (uStrCaseCmp(str, "messageaction") == 0)
10034345a63Smrg        *type_rtrn = XkbSA_ActionMessage;
10134345a63Smrg    else if (uStrCaseCmp(str, "message") == 0)
10234345a63Smrg        *type_rtrn = XkbSA_ActionMessage;
10334345a63Smrg    else if (uStrCaseCmp(str, "redirect") == 0)
10434345a63Smrg        *type_rtrn = XkbSA_RedirectKey;
10534345a63Smrg    else if (uStrCaseCmp(str, "redirectkey") == 0)
10634345a63Smrg        *type_rtrn = XkbSA_RedirectKey;
10734345a63Smrg    else if (uStrCaseCmp(str, "devbtn") == 0)
10834345a63Smrg        *type_rtrn = XkbSA_DeviceBtn;
10934345a63Smrg    else if (uStrCaseCmp(str, "devicebtn") == 0)
11034345a63Smrg        *type_rtrn = XkbSA_DeviceBtn;
11134345a63Smrg    else if (uStrCaseCmp(str, "devbutton") == 0)
11234345a63Smrg        *type_rtrn = XkbSA_DeviceBtn;
11334345a63Smrg    else if (uStrCaseCmp(str, "devicebutton") == 0)
11434345a63Smrg        *type_rtrn = XkbSA_DeviceBtn;
11534345a63Smrg    else if (uStrCaseCmp(str, "lockdevbtn") == 0)
116bfe6082cSmrg        *type_rtrn = XkbSA_LockDeviceBtn;
11734345a63Smrg    else if (uStrCaseCmp(str, "lockdevicebtn") == 0)
11834345a63Smrg        *type_rtrn = XkbSA_LockDeviceBtn;
11934345a63Smrg    else if (uStrCaseCmp(str, "lockdevbutton") == 0)
12034345a63Smrg        *type_rtrn = XkbSA_LockDeviceBtn;
12134345a63Smrg    else if (uStrCaseCmp(str, "lockdevicebutton") == 0)
12234345a63Smrg        *type_rtrn = XkbSA_LockDeviceBtn;
12334345a63Smrg    else if (uStrCaseCmp(str, "devval") == 0)
12434345a63Smrg        *type_rtrn = XkbSA_DeviceValuator;
12534345a63Smrg    else if (uStrCaseCmp(str, "deviceval") == 0)
12634345a63Smrg        *type_rtrn = XkbSA_DeviceValuator;
12734345a63Smrg    else if (uStrCaseCmp(str, "devvaluator") == 0)
12834345a63Smrg        *type_rtrn = XkbSA_DeviceValuator;
12934345a63Smrg    else if (uStrCaseCmp(str, "devicevaluator") == 0)
13034345a63Smrg        *type_rtrn = XkbSA_DeviceValuator;
13134345a63Smrg    else if (uStrCaseCmp(str, "private") == 0)
13234345a63Smrg        *type_rtrn = PrivateAction;
13334345a63Smrg    else
13434345a63Smrg        return False;
135f46a6179Smrg    return True;
136f46a6179Smrg}
137f46a6179Smrg
138f46a6179Smrgstatic Bool
139c82dfdfbSmrgstringToField(const char *str, unsigned *field_rtrn)
140f46a6179Smrg{
141f46a6179Smrg
14234345a63Smrg    if (str == NULL)
14334345a63Smrg        return False;
14434345a63Smrg
14534345a63Smrg    if (uStrCaseCmp(str, "clearlocks") == 0)
14634345a63Smrg        *field_rtrn = F_ClearLocks;
14734345a63Smrg    else if (uStrCaseCmp(str, "latchtolock") == 0)
14834345a63Smrg        *field_rtrn = F_LatchToLock;
14934345a63Smrg    else if (uStrCaseCmp(str, "genkeyevent") == 0)
15034345a63Smrg        *field_rtrn = F_GenKeyEvent;
15134345a63Smrg    else if (uStrCaseCmp(str, "generatekeyevent") == 0)
15234345a63Smrg        *field_rtrn = F_GenKeyEvent;
15334345a63Smrg    else if (uStrCaseCmp(str, "report") == 0)
15434345a63Smrg        *field_rtrn = F_Report;
15534345a63Smrg    else if (uStrCaseCmp(str, "default") == 0)
15634345a63Smrg        *field_rtrn = F_Default;
15734345a63Smrg    else if (uStrCaseCmp(str, "affect") == 0)
15834345a63Smrg        *field_rtrn = F_Affect;
15934345a63Smrg    else if (uStrCaseCmp(str, "increment") == 0)
16034345a63Smrg        *field_rtrn = F_Increment;
16134345a63Smrg    else if (uStrCaseCmp(str, "mods") == 0)
16234345a63Smrg        *field_rtrn = F_Modifiers;
16334345a63Smrg    else if (uStrCaseCmp(str, "modifiers") == 0)
16434345a63Smrg        *field_rtrn = F_Modifiers;
16534345a63Smrg    else if (uStrCaseCmp(str, "group") == 0)
16634345a63Smrg        *field_rtrn = F_Group;
16734345a63Smrg    else if (uStrCaseCmp(str, "x") == 0)
16834345a63Smrg        *field_rtrn = F_X;
16934345a63Smrg    else if (uStrCaseCmp(str, "y") == 0)
17034345a63Smrg        *field_rtrn = F_Y;
17134345a63Smrg    else if (uStrCaseCmp(str, "accel") == 0)
17234345a63Smrg        *field_rtrn = F_Accel;
17334345a63Smrg    else if (uStrCaseCmp(str, "accelerate") == 0)
17434345a63Smrg        *field_rtrn = F_Accel;
17534345a63Smrg    else if (uStrCaseCmp(str, "repeat") == 0)
17634345a63Smrg        *field_rtrn = F_Accel;
17734345a63Smrg    else if (uStrCaseCmp(str, "button") == 0)
17834345a63Smrg        *field_rtrn = F_Button;
17934345a63Smrg    else if (uStrCaseCmp(str, "value") == 0)
18034345a63Smrg        *field_rtrn = F_Value;
18134345a63Smrg    else if (uStrCaseCmp(str, "controls") == 0)
18234345a63Smrg        *field_rtrn = F_Controls;
18334345a63Smrg    else if (uStrCaseCmp(str, "ctrls") == 0)
18434345a63Smrg        *field_rtrn = F_Controls;
18534345a63Smrg    else if (uStrCaseCmp(str, "type") == 0)
18634345a63Smrg        *field_rtrn = F_Type;
18734345a63Smrg    else if (uStrCaseCmp(str, "count") == 0)
18834345a63Smrg        *field_rtrn = F_Count;
18934345a63Smrg    else if (uStrCaseCmp(str, "screen") == 0)
19034345a63Smrg        *field_rtrn = F_Screen;
19134345a63Smrg    else if (uStrCaseCmp(str, "same") == 0)
19234345a63Smrg        *field_rtrn = F_Same;
19334345a63Smrg    else if (uStrCaseCmp(str, "sameserver") == 0)
19434345a63Smrg        *field_rtrn = F_Same;
19534345a63Smrg    else if (uStrCaseCmp(str, "data") == 0)
19634345a63Smrg        *field_rtrn = F_Data;
19734345a63Smrg    else if (uStrCaseCmp(str, "device") == 0)
19834345a63Smrg        *field_rtrn = F_Device;
19934345a63Smrg    else if (uStrCaseCmp(str, "dev") == 0)
20034345a63Smrg        *field_rtrn = F_Device;
20134345a63Smrg    else if (uStrCaseCmp(str, "key") == 0)
20234345a63Smrg        *field_rtrn = F_Keycode;
20334345a63Smrg    else if (uStrCaseCmp(str, "keycode") == 0)
20434345a63Smrg        *field_rtrn = F_Keycode;
20534345a63Smrg    else if (uStrCaseCmp(str, "kc") == 0)
20634345a63Smrg        *field_rtrn = F_Keycode;
20734345a63Smrg    else if (uStrCaseCmp(str, "clearmods") == 0)
20834345a63Smrg        *field_rtrn = F_ModsToClear;
20934345a63Smrg    else if (uStrCaseCmp(str, "clearmodifiers") == 0)
21034345a63Smrg        *field_rtrn = F_ModsToClear;
21134345a63Smrg    else
21234345a63Smrg        return False;
213f46a6179Smrg    return True;
214f46a6179Smrg}
215f46a6179Smrg
216f46a6179Smrgstatic char *
217f46a6179SmrgfieldText(unsigned field)
218f46a6179Smrg{
21934345a63Smrg    static char buf[32];
22034345a63Smrg
22134345a63Smrg    switch (field)
22234345a63Smrg    {
22334345a63Smrg    case F_ClearLocks:
22434345a63Smrg        strcpy(buf, "clearLocks");
22534345a63Smrg        break;
22634345a63Smrg    case F_LatchToLock:
22734345a63Smrg        strcpy(buf, "latchToLock");
22834345a63Smrg        break;
22934345a63Smrg    case F_GenKeyEvent:
23034345a63Smrg        strcpy(buf, "genKeyEvent");
23134345a63Smrg        break;
23234345a63Smrg    case F_Report:
23334345a63Smrg        strcpy(buf, "report");
23434345a63Smrg        break;
23534345a63Smrg    case F_Default:
23634345a63Smrg        strcpy(buf, "default");
23734345a63Smrg        break;
23834345a63Smrg    case F_Affect:
23934345a63Smrg        strcpy(buf, "affect");
24034345a63Smrg        break;
24134345a63Smrg    case F_Increment:
24234345a63Smrg        strcpy(buf, "increment");
24334345a63Smrg        break;
24434345a63Smrg    case F_Modifiers:
24534345a63Smrg        strcpy(buf, "modifiers");
24634345a63Smrg        break;
24734345a63Smrg    case F_Group:
24834345a63Smrg        strcpy(buf, "group");
24934345a63Smrg        break;
25034345a63Smrg    case F_X:
25134345a63Smrg        strcpy(buf, "x");
25234345a63Smrg        break;
25334345a63Smrg    case F_Y:
25434345a63Smrg        strcpy(buf, "y");
25534345a63Smrg        break;
25634345a63Smrg    case F_Accel:
25734345a63Smrg        strcpy(buf, "accel");
25834345a63Smrg        break;
25934345a63Smrg    case F_Button:
26034345a63Smrg        strcpy(buf, "button");
26134345a63Smrg        break;
26234345a63Smrg    case F_Value:
26334345a63Smrg        strcpy(buf, "value");
26434345a63Smrg        break;
26534345a63Smrg    case F_Controls:
26634345a63Smrg        strcpy(buf, "controls");
26734345a63Smrg        break;
26834345a63Smrg    case F_Type:
26934345a63Smrg        strcpy(buf, "type");
27034345a63Smrg        break;
27134345a63Smrg    case F_Count:
27234345a63Smrg        strcpy(buf, "count");
27334345a63Smrg        break;
27434345a63Smrg    case F_Screen:
27534345a63Smrg        strcpy(buf, "screen");
27634345a63Smrg        break;
27734345a63Smrg    case F_Same:
27834345a63Smrg        strcpy(buf, "sameServer");
27934345a63Smrg        break;
28034345a63Smrg    case F_Data:
28134345a63Smrg        strcpy(buf, "data");
28234345a63Smrg        break;
28334345a63Smrg    case F_Device:
28434345a63Smrg        strcpy(buf, "device");
28534345a63Smrg        break;
28634345a63Smrg    case F_Keycode:
28734345a63Smrg        strcpy(buf, "keycode");
28834345a63Smrg        break;
28934345a63Smrg    case F_ModsToClear:
29034345a63Smrg        strcpy(buf, "clearmods");
29134345a63Smrg        break;
29234345a63Smrg    default:
29334345a63Smrg        strcpy(buf, "unknown");
29434345a63Smrg        break;
295f46a6179Smrg    }
296f46a6179Smrg    return buf;
297f46a6179Smrg}
298f46a6179Smrg
299f46a6179Smrg/***====================================================================***/
300f46a6179Smrg
301f46a6179Smrgstatic Bool
302f46a6179SmrgReportMismatch(unsigned action, unsigned field, const char *type)
303f46a6179Smrg{
304bfe6082cSmrg    ERROR("Value of %s field must be of type %s\n", fieldText(field), type);
305bfe6082cSmrg    ACTION("Action %s definition ignored\n",
30634345a63Smrg            XkbActionTypeText(action, XkbMessage));
307f46a6179Smrg    return False;
308f46a6179Smrg}
309f46a6179Smrg
310f46a6179Smrgstatic Bool
31134345a63SmrgReportIllegal(unsigned action, unsigned field)
312f46a6179Smrg{
313bfe6082cSmrg    ERROR("Field %s is not defined for an action of type %s\n",
31434345a63Smrg           fieldText(field), XkbActionTypeText(action, XkbMessage));
315f46a6179Smrg    ACTION("Action definition ignored\n");
316f46a6179Smrg    return False;
317f46a6179Smrg}
318f46a6179Smrg
319f46a6179Smrgstatic Bool
32034345a63SmrgReportActionNotArray(unsigned action, unsigned field)
321f46a6179Smrg{
322bfe6082cSmrg    ERROR("The %s field in the %s action is not an array\n",
32334345a63Smrg           fieldText(field), XkbActionTypeText(action, XkbMessage));
324f46a6179Smrg    ACTION("Action definition ignored\n");
325f46a6179Smrg    return False;
326f46a6179Smrg}
327f46a6179Smrg
328f46a6179Smrgstatic Bool
329f46a6179SmrgReportNotFound(unsigned action, unsigned field, const char *what, char *bad)
330f46a6179Smrg{
331bfe6082cSmrg    ERROR("%s named %s not found\n", what, bad);
332bfe6082cSmrg    ACTION("Ignoring the %s field of an %s action\n", fieldText(field),
33334345a63Smrg            XkbActionTypeText(action, XkbMessage));
334f46a6179Smrg    return False;
335f46a6179Smrg}
336f46a6179Smrg
337f46a6179Smrgstatic Bool
3386930ead5SmrgHandleNoAction(XkbDescPtr xkb, XkbAnyAction *action, unsigned field,
3396930ead5Smrg               const ExprDef *array_ndx, const ExprDef *value)
340f46a6179Smrg{
34134345a63Smrg    return ReportIllegal(action->type, field);
342f46a6179Smrg}
343f46a6179Smrg
344f46a6179Smrgstatic Bool
3456930ead5SmrgCheckLatchLockFlags(unsigned action, unsigned field,
3466930ead5Smrg                    const ExprDef *value, unsigned *flags_inout)
347f46a6179Smrg{
34834345a63Smrg    unsigned tmp;
34934345a63Smrg    ExprResult result;
35034345a63Smrg
35134345a63Smrg    if (field == F_ClearLocks)
35234345a63Smrg        tmp = XkbSA_ClearLocks;
35334345a63Smrg    else if (field == F_LatchToLock)
35434345a63Smrg        tmp = XkbSA_LatchToLock;
35534345a63Smrg    else
35634345a63Smrg        return False;           /* WSGO! */
35734345a63Smrg    if (!ExprResolveBoolean(value, &result, NULL, NULL))
35834345a63Smrg        return ReportMismatch(action, field, "boolean");
35934345a63Smrg    if (result.uval)
36034345a63Smrg        *flags_inout |= tmp;
36134345a63Smrg    else
36234345a63Smrg        *flags_inout &= ~tmp;
363f46a6179Smrg    return True;
364f46a6179Smrg}
365f46a6179Smrg
366f46a6179Smrgstatic Bool
3676930ead5SmrgCheckModifierField(XkbDescPtr xkb, unsigned action, const ExprDef *value,
36834345a63Smrg                   unsigned *flags_inout, unsigned *mods_rtrn)
369f46a6179Smrg{
37034345a63Smrg    ExprResult rtrn;
37134345a63Smrg
37234345a63Smrg    if (value->op == ExprIdent)
37334345a63Smrg    {
3746930ead5Smrg        char *valStr;
37534345a63Smrg        valStr = XkbAtomGetString(NULL, value->value.str);
37634345a63Smrg        if (valStr && ((uStrCaseCmp(valStr, "usemodmapmods") == 0) ||
37734345a63Smrg                       (uStrCaseCmp(valStr, "modmapmods") == 0)))
37834345a63Smrg        {
37934345a63Smrg
38034345a63Smrg            *mods_rtrn = 0;
38134345a63Smrg            *flags_inout |= XkbSA_UseModMapMods;
38234345a63Smrg            return True;
38334345a63Smrg        }
384f46a6179Smrg    }
38534345a63Smrg    if (!ExprResolveModMask(value, &rtrn, LookupVModMask, (XPointer) xkb))
38634345a63Smrg        return ReportMismatch(action, F_Modifiers, "modifier mask");
38734345a63Smrg    *mods_rtrn = rtrn.uval;
38834345a63Smrg    *flags_inout &= ~XkbSA_UseModMapMods;
389f46a6179Smrg    return True;
390f46a6179Smrg}
391f46a6179Smrg
392f46a6179Smrgstatic Bool
3936930ead5SmrgHandleSetLatchMods(XkbDescPtr xkb, XkbAnyAction *action, unsigned field,
3946930ead5Smrg                   const ExprDef *array_ndx, const ExprDef *value)
395f46a6179Smrg{
39634345a63Smrg    XkbModAction *act;
39734345a63Smrg
39834345a63Smrg    act = (XkbModAction *) action;
39934345a63Smrg    if (array_ndx != NULL)
40034345a63Smrg    {
40134345a63Smrg        switch (field)
40234345a63Smrg        {
40334345a63Smrg        case F_ClearLocks:
40434345a63Smrg        case F_LatchToLock:
40534345a63Smrg        case F_Modifiers:
40634345a63Smrg            return ReportActionNotArray(action->type, field);
40734345a63Smrg        }
408f46a6179Smrg    }
40934345a63Smrg    switch (field)
41034345a63Smrg    {
41134345a63Smrg    case F_ClearLocks:
41234345a63Smrg    case F_LatchToLock:
4136930ead5Smrg    {
4146930ead5Smrg        unsigned rtrn = act->flags;
41534345a63Smrg        if (CheckLatchLockFlags(action->type, field, value, &rtrn))
41634345a63Smrg        {
41734345a63Smrg            act->flags = rtrn;
41834345a63Smrg            return True;
41934345a63Smrg        }
42034345a63Smrg        return False;
4216930ead5Smrg    }
42234345a63Smrg    case F_Modifiers:
4236930ead5Smrg    {
4246930ead5Smrg        unsigned t1 = act->flags, t2;
42534345a63Smrg        if (CheckModifierField(xkb, action->type, value, &t1, &t2))
42634345a63Smrg        {
42734345a63Smrg            act->flags = t1;
42834345a63Smrg            act->real_mods = act->mask = (t2 & 0xff);
42934345a63Smrg            t2 = (t2 >> 8) & 0xffff;
43034345a63Smrg            XkbSetModActionVMods(act, t2);
43134345a63Smrg            return True;
43234345a63Smrg        }
43334345a63Smrg        return False;
434f46a6179Smrg    }
4356930ead5Smrg    }
43634345a63Smrg    return ReportIllegal(action->type, field);
437f46a6179Smrg}
438f46a6179Smrg
439bfe6082cSmrgstatic LookupEntry lockWhich[] = {
440bfe6082cSmrg    {"both", 0},
441bfe6082cSmrg    {"lock", XkbSA_LockNoUnlock},
442bfe6082cSmrg    {"neither", (XkbSA_LockNoLock | XkbSA_LockNoUnlock)},
443bfe6082cSmrg    {"unlock", XkbSA_LockNoLock},
444bfe6082cSmrg    {NULL, 0}
445bfe6082cSmrg};
446bfe6082cSmrg
447f46a6179Smrgstatic Bool
4486930ead5SmrgHandleLockMods(XkbDescPtr xkb, XkbAnyAction *action, unsigned field,
4496930ead5Smrg               const ExprDef *array_ndx, const ExprDef *value)
450f46a6179Smrg{
45134345a63Smrg    XkbModAction *act;
45234345a63Smrg
45334345a63Smrg    act = (XkbModAction *) action;
454bfe6082cSmrg    if ((array_ndx != NULL) && (field == F_Modifiers || field == F_Affect))
45534345a63Smrg        return ReportActionNotArray(action->type, field);
45634345a63Smrg    switch (field)
45734345a63Smrg    {
458bfe6082cSmrg    case F_Affect:
4596930ead5Smrg    {
4606930ead5Smrg        ExprResult rtrn;
461bfe6082cSmrg        if (!ExprResolveEnum(value, &rtrn, lockWhich))
462bfe6082cSmrg            return ReportMismatch(action->type, field, "lock or unlock");
463bfe6082cSmrg        act->flags &= ~(XkbSA_LockNoLock | XkbSA_LockNoUnlock);
464bfe6082cSmrg        act->flags |= rtrn.uval;
465bfe6082cSmrg        return True;
4666930ead5Smrg    }
46734345a63Smrg    case F_Modifiers:
4686930ead5Smrg    {
4696930ead5Smrg        unsigned t1 = act->flags, t2;
47034345a63Smrg        if (CheckModifierField(xkb, action->type, value, &t1, &t2))
47134345a63Smrg        {
47234345a63Smrg            act->flags = t1;
47334345a63Smrg            act->real_mods = act->mask = (t2 & 0xff);
47434345a63Smrg            t2 = (t2 >> 8) & 0xffff;
47534345a63Smrg            XkbSetModActionVMods(act, t2);
47634345a63Smrg            return True;
47734345a63Smrg        }
47834345a63Smrg        return False;
479f46a6179Smrg    }
4806930ead5Smrg    }
48134345a63Smrg    return ReportIllegal(action->type, field);
482f46a6179Smrg}
483f46a6179Smrg
484f46a6179Smrgstatic LookupEntry groupNames[] = {
48534345a63Smrg    {"group1", 1},
48634345a63Smrg    {"group2", 2},
48734345a63Smrg    {"group3", 3},
48834345a63Smrg    {"group4", 4},
48934345a63Smrg    {"group5", 5},
49034345a63Smrg    {"group6", 6},
49134345a63Smrg    {"group7", 7},
49234345a63Smrg    {"group8", 8},
49334345a63Smrg    {NULL, 0},
494f46a6179Smrg};
495f46a6179Smrg
496f46a6179Smrgstatic Bool
4976930ead5SmrgCheckGroupField(unsigned action, const ExprDef *value,
4986930ead5Smrg                unsigned *flags_inout, int *grp_rtrn)
499f46a6179Smrg{
5006930ead5Smrg    const ExprDef *spec;
50134345a63Smrg    ExprResult rtrn;
502f46a6179Smrg
50334345a63Smrg    if ((value->op == OpNegate) || (value->op == OpUnaryPlus))
50434345a63Smrg    {
50534345a63Smrg        *flags_inout &= ~XkbSA_GroupAbsolute;
50634345a63Smrg        spec = value->value.child;
507f46a6179Smrg    }
50834345a63Smrg    else
50934345a63Smrg    {
51034345a63Smrg        *flags_inout |= XkbSA_GroupAbsolute;
51134345a63Smrg        spec = value;
512f46a6179Smrg    }
513f46a6179Smrg
51434345a63Smrg    if (!ExprResolveInteger(spec, &rtrn, SimpleLookup, (XPointer) groupNames))
51534345a63Smrg        return ReportMismatch(action, F_Group, "integer (range 1..8)");
51634345a63Smrg    if ((rtrn.ival < 1) || (rtrn.ival > XkbNumKbdGroups))
51734345a63Smrg    {
518bfe6082cSmrg        ERROR("Illegal group %d (must be in the range 1..%d)\n", rtrn.ival,
51934345a63Smrg               XkbNumKbdGroups);
520bfe6082cSmrg        ACTION("Action %s definition ignored\n",
52134345a63Smrg                XkbActionTypeText(action, XkbMessage));
52234345a63Smrg        return False;
523f46a6179Smrg    }
52434345a63Smrg    if (value->op == OpNegate)
52534345a63Smrg        *grp_rtrn = -rtrn.ival;
52634345a63Smrg    else if (value->op == OpUnaryPlus)
52734345a63Smrg        *grp_rtrn = rtrn.ival;
52834345a63Smrg    else
52934345a63Smrg        *grp_rtrn = rtrn.ival - 1;
530f46a6179Smrg    return True;
531f46a6179Smrg}
532f46a6179Smrg
533f46a6179Smrgstatic Bool
5346930ead5SmrgHandleSetLatchGroup(XkbDescPtr xkb, XkbAnyAction *action, unsigned field,
5356930ead5Smrg                    const ExprDef *array_ndx, const ExprDef *value)
536f46a6179Smrg{
53734345a63Smrg    XkbGroupAction *act;
53834345a63Smrg
53934345a63Smrg    act = (XkbGroupAction *) action;
54034345a63Smrg    if (array_ndx != NULL)
54134345a63Smrg    {
54234345a63Smrg        switch (field)
54334345a63Smrg        {
54434345a63Smrg        case F_ClearLocks:
54534345a63Smrg        case F_LatchToLock:
54634345a63Smrg        case F_Group:
54734345a63Smrg            return ReportActionNotArray(action->type, field);
54834345a63Smrg        }
549f46a6179Smrg    }
55034345a63Smrg    switch (field)
55134345a63Smrg    {
55234345a63Smrg    case F_ClearLocks:
55334345a63Smrg    case F_LatchToLock:
5546930ead5Smrg    {
5556930ead5Smrg        unsigned rtrn = act->flags;
55634345a63Smrg        if (CheckLatchLockFlags(action->type, field, value, &rtrn))
55734345a63Smrg        {
55834345a63Smrg            act->flags = rtrn;
55934345a63Smrg            return True;
56034345a63Smrg        }
56134345a63Smrg        return False;
5626930ead5Smrg    }
56334345a63Smrg    case F_Group:
5646930ead5Smrg    {
5656930ead5Smrg        unsigned t1 = act->flags;
5666930ead5Smrg        int t2;
56734345a63Smrg        if (CheckGroupField(action->type, value, &t1, &t2))
56834345a63Smrg        {
56934345a63Smrg            act->flags = t1;
57034345a63Smrg            XkbSASetGroup(act, t2);
57134345a63Smrg            return True;
57234345a63Smrg        }
57334345a63Smrg        return False;
574f46a6179Smrg    }
5756930ead5Smrg    }
57634345a63Smrg    return ReportIllegal(action->type, field);
577f46a6179Smrg}
578f46a6179Smrg
579f46a6179Smrgstatic Bool
5806930ead5SmrgHandleLockGroup(XkbDescPtr xkb, XkbAnyAction *action, unsigned field,
5816930ead5Smrg                const ExprDef * array_ndx, const ExprDef *value)
582f46a6179Smrg{
58334345a63Smrg    XkbGroupAction *act;
58434345a63Smrg
58534345a63Smrg    act = (XkbGroupAction *) action;
58634345a63Smrg    if ((array_ndx != NULL) && (field == F_Group))
58734345a63Smrg        return ReportActionNotArray(action->type, field);
58834345a63Smrg    if (field == F_Group)
58934345a63Smrg    {
5906930ead5Smrg        unsigned t1 = act->flags;
5916930ead5Smrg        int t2;
59234345a63Smrg        if (CheckGroupField(action->type, value, &t1, &t2))
59334345a63Smrg        {
59434345a63Smrg            act->flags = t1;
59534345a63Smrg            XkbSASetGroup(act, t2);
59634345a63Smrg            return True;
59734345a63Smrg        }
59834345a63Smrg        return False;
599f46a6179Smrg    }
60034345a63Smrg    return ReportIllegal(action->type, field);
601f46a6179Smrg}
602f46a6179Smrg
603f46a6179Smrgstatic Bool
6046930ead5SmrgHandleMovePtr(XkbDescPtr xkb, XkbAnyAction *action, unsigned field,
6056930ead5Smrg              const ExprDef *array_ndx, const ExprDef *value)
606f46a6179Smrg{
60734345a63Smrg    ExprResult rtrn;
60834345a63Smrg    XkbPtrAction *act;
60934345a63Smrg
61034345a63Smrg    act = (XkbPtrAction *) action;
61134345a63Smrg    if ((array_ndx != NULL) && ((field == F_X) || (field == F_Y)))
61234345a63Smrg        return ReportActionNotArray(action->type, field);
61334345a63Smrg
61434345a63Smrg    if ((field == F_X) || (field == F_Y))
61534345a63Smrg    {
6166930ead5Smrg        Bool absolute;
6176930ead5Smrg
61834345a63Smrg        if ((value->op == OpNegate) || (value->op == OpUnaryPlus))
61934345a63Smrg            absolute = False;
62034345a63Smrg        else
62134345a63Smrg            absolute = True;
62234345a63Smrg        if (!ExprResolveInteger(value, &rtrn, NULL, NULL))
62334345a63Smrg            return ReportMismatch(action->type, field, "integer");
62434345a63Smrg        if (field == F_X)
62534345a63Smrg        {
62634345a63Smrg            if (absolute)
62734345a63Smrg                act->flags |= XkbSA_MoveAbsoluteX;
62834345a63Smrg            XkbSetPtrActionX(act, rtrn.ival);
62934345a63Smrg        }
63034345a63Smrg        else
63134345a63Smrg        {
63234345a63Smrg            if (absolute)
63334345a63Smrg                act->flags |= XkbSA_MoveAbsoluteY;
63434345a63Smrg            XkbSetPtrActionY(act, rtrn.ival);
63534345a63Smrg        }
63634345a63Smrg        return True;
637f46a6179Smrg    }
63834345a63Smrg    else if (field == F_Accel)
63934345a63Smrg    {
64034345a63Smrg        if (!ExprResolveBoolean(value, &rtrn, NULL, NULL))
64134345a63Smrg            return ReportMismatch(action->type, field, "boolean");
64234345a63Smrg        if (rtrn.uval)
64334345a63Smrg            act->flags &= ~XkbSA_NoAcceleration;
64434345a63Smrg        else
64534345a63Smrg            act->flags |= XkbSA_NoAcceleration;
646bfe6082cSmrg        return True;
647f46a6179Smrg    }
64834345a63Smrg    return ReportIllegal(action->type, field);
649f46a6179Smrg}
650f46a6179Smrg
651f46a6179Smrgstatic LookupEntry btnNames[] = {
65234345a63Smrg    {"button1", 1},
65334345a63Smrg    {"button2", 2},
65434345a63Smrg    {"button3", 3},
65534345a63Smrg    {"button4", 4},
65634345a63Smrg    {"button5", 5},
65734345a63Smrg    {"default", 0},
65834345a63Smrg    {NULL, 0}
659f46a6179Smrg};
660f46a6179Smrg
661f46a6179Smrgstatic Bool
6626930ead5SmrgHandlePtrBtn(XkbDescPtr xkb, XkbAnyAction *action, unsigned field,
6636930ead5Smrg             const ExprDef *array_ndx, const ExprDef *value)
664f46a6179Smrg{
66534345a63Smrg    ExprResult rtrn;
66634345a63Smrg    XkbPtrBtnAction *act;
66734345a63Smrg
66834345a63Smrg    act = (XkbPtrBtnAction *) action;
66934345a63Smrg    if (field == F_Button)
67034345a63Smrg    {
67134345a63Smrg        if (array_ndx != NULL)
67234345a63Smrg            return ReportActionNotArray(action->type, field);
67334345a63Smrg        if (!ExprResolveInteger
67434345a63Smrg            (value, &rtrn, SimpleLookup, (XPointer) btnNames))
67534345a63Smrg            return ReportMismatch(action->type, field,
67634345a63Smrg                                  "integer (range 1..5)");
67734345a63Smrg        if ((rtrn.ival < 0) || (rtrn.ival > 5))
67834345a63Smrg        {
67934345a63Smrg            ERROR("Button must specify default or be in the range 1..5\n");
680bfe6082cSmrg            ACTION("Illegal button value %d ignored\n", rtrn.ival);
68134345a63Smrg            return False;
68234345a63Smrg        }
68334345a63Smrg        act->button = rtrn.ival;
68434345a63Smrg        return True;
685f46a6179Smrg    }
68634345a63Smrg    else if ((action->type == XkbSA_LockPtrBtn) && (field == F_Affect))
68734345a63Smrg    {
68834345a63Smrg        if (array_ndx != NULL)
68934345a63Smrg            return ReportActionNotArray(action->type, field);
69034345a63Smrg        if (!ExprResolveEnum(value, &rtrn, lockWhich))
69134345a63Smrg            return ReportMismatch(action->type, field, "lock or unlock");
69234345a63Smrg        act->flags &= ~(XkbSA_LockNoLock | XkbSA_LockNoUnlock);
693bfe6082cSmrg        act->flags |= rtrn.uval;
69434345a63Smrg        return True;
695f46a6179Smrg    }
69634345a63Smrg    else if (field == F_Count)
69734345a63Smrg    {
69834345a63Smrg        if (array_ndx != NULL)
69934345a63Smrg            return ReportActionNotArray(action->type, field);
70034345a63Smrg        if (!ExprResolveInteger
70134345a63Smrg            (value, &rtrn, SimpleLookup, (XPointer) btnNames))
70234345a63Smrg            return ReportMismatch(action->type, field, "integer");
70334345a63Smrg        if ((rtrn.ival < 0) || (rtrn.ival > 255))
70434345a63Smrg        {
70534345a63Smrg            ERROR("The count field must have a value in the range 0..255\n");
706bfe6082cSmrg            ACTION("Illegal count %d ignored\n", rtrn.ival);
70734345a63Smrg            return False;
70834345a63Smrg        }
70934345a63Smrg        act->count = rtrn.ival;
71034345a63Smrg        return True;
711f46a6179Smrg    }
71234345a63Smrg    return ReportIllegal(action->type, field);
713f46a6179Smrg}
714f46a6179Smrg
715f46a6179Smrgstatic LookupEntry ptrDflts[] = {
71634345a63Smrg    {"dfltbtn", XkbSA_AffectDfltBtn},
71734345a63Smrg    {"defaultbutton", XkbSA_AffectDfltBtn},
71834345a63Smrg    {"button", XkbSA_AffectDfltBtn},
71934345a63Smrg    {NULL, 0}
720f46a6179Smrg};
721f46a6179Smrg
722f46a6179Smrgstatic Bool
7236930ead5SmrgHandleSetPtrDflt(XkbDescPtr xkb, XkbAnyAction *action, unsigned field,
7246930ead5Smrg                 const ExprDef *array_ndx, const ExprDef *value)
725f46a6179Smrg{
72634345a63Smrg    ExprResult rtrn;
72734345a63Smrg    XkbPtrDfltAction *act;
72834345a63Smrg
72934345a63Smrg    act = (XkbPtrDfltAction *) action;
73034345a63Smrg    if (field == F_Affect)
73134345a63Smrg    {
73234345a63Smrg        if (array_ndx != NULL)
73334345a63Smrg            return ReportActionNotArray(action->type, field);
73434345a63Smrg        if (!ExprResolveEnum(value, &rtrn, ptrDflts))
73534345a63Smrg            return ReportMismatch(action->type, field, "pointer component");
73634345a63Smrg        act->affect = rtrn.uval;
73734345a63Smrg        return True;
738f46a6179Smrg    }
73934345a63Smrg    else if ((field == F_Button) || (field == F_Value))
74034345a63Smrg    {
7416930ead5Smrg        const ExprDef *btn;
74234345a63Smrg        if (array_ndx != NULL)
74334345a63Smrg            return ReportActionNotArray(action->type, field);
74434345a63Smrg        if ((value->op == OpNegate) || (value->op == OpUnaryPlus))
74534345a63Smrg        {
74634345a63Smrg            act->flags &= ~XkbSA_DfltBtnAbsolute;
74734345a63Smrg            btn = value->value.child;
74834345a63Smrg        }
74934345a63Smrg        else
75034345a63Smrg        {
75134345a63Smrg            act->flags |= XkbSA_DfltBtnAbsolute;
75234345a63Smrg            btn = value;
75334345a63Smrg        }
75434345a63Smrg
75534345a63Smrg        if (!ExprResolveInteger
75634345a63Smrg            (btn, &rtrn, SimpleLookup, (XPointer) btnNames))
75734345a63Smrg            return ReportMismatch(action->type, field,
75834345a63Smrg                                  "integer (range 1..5)");
75934345a63Smrg        if ((rtrn.ival < 0) || (rtrn.ival > 5))
76034345a63Smrg        {
76134345a63Smrg            ERROR("New default button value must be in the range 1..5\n");
762bfe6082cSmrg            ACTION("Illegal default button value %d ignored\n", rtrn.ival);
76334345a63Smrg            return False;
76434345a63Smrg        }
76534345a63Smrg        if (rtrn.ival == 0)
76634345a63Smrg        {
76734345a63Smrg            ERROR("Cannot set default pointer button to \"default\"\n");
76834345a63Smrg            ACTION("Illegal default button setting ignored\n");
76934345a63Smrg            return False;
77034345a63Smrg        }
77134345a63Smrg        if (value->op == OpNegate)
77234345a63Smrg            XkbSASetPtrDfltValue(act, -rtrn.ival);
77334345a63Smrg        else
77434345a63Smrg            XkbSASetPtrDfltValue(act, rtrn.ival);
77534345a63Smrg        return True;
776f46a6179Smrg    }
77734345a63Smrg    return ReportIllegal(action->type, field);
778f46a6179Smrg}
779f46a6179Smrg
78034345a63Smrgstatic LookupEntry isoNames[] = {
78134345a63Smrg    {"mods", XkbSA_ISONoAffectMods},
78234345a63Smrg    {"modifiers", XkbSA_ISONoAffectMods},
78334345a63Smrg    {"group", XkbSA_ISONoAffectGroup},
78434345a63Smrg    {"groups", XkbSA_ISONoAffectGroup},
78534345a63Smrg    {"ptr", XkbSA_ISONoAffectPtr},
78634345a63Smrg    {"pointer", XkbSA_ISONoAffectPtr},
78734345a63Smrg    {"ctrls", XkbSA_ISONoAffectCtrls},
78834345a63Smrg    {"controls", XkbSA_ISONoAffectCtrls},
789bfe6082cSmrg    {"all", XkbSA_ISOAffectMask},
79034345a63Smrg    {"none", 0},
791bfe6082cSmrg    {"both", 0},
792bfe6082cSmrg    {"lock", XkbSA_LockNoUnlock},
793bfe6082cSmrg    {"neither", (XkbSA_LockNoLock | XkbSA_LockNoUnlock)},
794bfe6082cSmrg    {"unlock", XkbSA_LockNoLock},
79534345a63Smrg    {NULL, 0},
796f46a6179Smrg};
797f46a6179Smrg
798f46a6179Smrgstatic Bool
7996930ead5SmrgHandleISOLock(XkbDescPtr xkb,  XkbAnyAction *action, unsigned field,
8006930ead5Smrg              const ExprDef *array_ndx, const ExprDef *value)
801f46a6179Smrg{
80234345a63Smrg    ExprResult rtrn;
80334345a63Smrg    XkbISOAction *act;
8046930ead5Smrg    unsigned flags;
80534345a63Smrg
80634345a63Smrg    act = (XkbISOAction *) action;
80734345a63Smrg    switch (field)
80834345a63Smrg    {
80934345a63Smrg    case F_Modifiers:
8106930ead5Smrg    {
8116930ead5Smrg        unsigned mods;
81234345a63Smrg        if (array_ndx != NULL)
81334345a63Smrg            return ReportActionNotArray(action->type, field);
81434345a63Smrg        flags = act->flags;
81534345a63Smrg        if (CheckModifierField(xkb, action->type, value, &flags, &mods))
81634345a63Smrg        {
81734345a63Smrg            act->flags = flags & (~XkbSA_ISODfltIsGroup);
818bfe6082cSmrg            act->real_mods = act->mask = (mods & 0xff);
819bfe6082cSmrg            mods = (mods >> 8) & 0xffff;
82034345a63Smrg            XkbSetModActionVMods(act, mods);
82134345a63Smrg            return True;
82234345a63Smrg        }
82334345a63Smrg        return False;
8246930ead5Smrg    }
82534345a63Smrg    case F_Group:
8266930ead5Smrg    {
8276930ead5Smrg        int group;
82834345a63Smrg        if (array_ndx != NULL)
82934345a63Smrg            return ReportActionNotArray(action->type, field);
83034345a63Smrg        flags = act->flags;
83134345a63Smrg        if (CheckGroupField(action->type, value, &flags, &group))
83234345a63Smrg        {
83334345a63Smrg            act->flags = flags | XkbSA_ISODfltIsGroup;
83434345a63Smrg            XkbSASetGroup(act, group);
83534345a63Smrg            return True;
83634345a63Smrg        }
83734345a63Smrg        return False;
8386930ead5Smrg    }
83934345a63Smrg    case F_Affect:
84034345a63Smrg        if (array_ndx != NULL)
84134345a63Smrg            return ReportActionNotArray(action->type, field);
84234345a63Smrg        if (!ExprResolveMask(value, &rtrn, SimpleLookup, (XPointer) isoNames))
84334345a63Smrg            return ReportMismatch(action->type, field, "keyboard component");
84434345a63Smrg        act->affect = (~rtrn.uval) & XkbSA_ISOAffectMask;
845bfe6082cSmrg        act->flags &= ~(XkbSA_LockNoLock | XkbSA_LockNoUnlock);
846bfe6082cSmrg        act->flags |= rtrn.uval & (XkbSA_LockNoLock | XkbSA_LockNoUnlock);
84734345a63Smrg        return True;
848f46a6179Smrg    }
84934345a63Smrg    return ReportIllegal(action->type, field);
850f46a6179Smrg}
851f46a6179Smrg
852f46a6179Smrgstatic Bool
8536930ead5SmrgHandleSwitchScreen(XkbDescPtr xkb, XkbAnyAction *action, unsigned field,
8546930ead5Smrg                   const ExprDef *array_ndx, const ExprDef *value)
855f46a6179Smrg{
85634345a63Smrg    ExprResult rtrn;
85734345a63Smrg    XkbSwitchScreenAction *act;
85834345a63Smrg
85934345a63Smrg    act = (XkbSwitchScreenAction *) action;
86034345a63Smrg    if (field == F_Screen)
86134345a63Smrg    {
8626930ead5Smrg        const ExprDef *scrn;
86334345a63Smrg        if (array_ndx != NULL)
86434345a63Smrg            return ReportActionNotArray(action->type, field);
86534345a63Smrg        if ((value->op == OpNegate) || (value->op == OpUnaryPlus))
86634345a63Smrg        {
86734345a63Smrg            act->flags &= ~XkbSA_SwitchAbsolute;
86834345a63Smrg            scrn = value->value.child;
86934345a63Smrg        }
87034345a63Smrg        else
87134345a63Smrg        {
87234345a63Smrg            act->flags |= XkbSA_SwitchAbsolute;
87334345a63Smrg            scrn = value;
87434345a63Smrg        }
87534345a63Smrg
87634345a63Smrg        if (!ExprResolveInteger(scrn, &rtrn, NULL, NULL))
87734345a63Smrg            return ReportMismatch(action->type, field, "integer (0..255)");
87834345a63Smrg        if ((rtrn.ival < 0) || (rtrn.ival > 255))
87934345a63Smrg        {
88034345a63Smrg            ERROR("Screen index must be in the range 1..255\n");
881bfe6082cSmrg            ACTION("Illegal screen value %d ignored\n", rtrn.ival);
88234345a63Smrg            return False;
88334345a63Smrg        }
88434345a63Smrg        if (value->op == OpNegate)
88534345a63Smrg            XkbSASetScreen(act, -rtrn.ival);
88634345a63Smrg        else
88734345a63Smrg            XkbSASetScreen(act, rtrn.ival);
88834345a63Smrg        return True;
889f46a6179Smrg    }
89034345a63Smrg    else if (field == F_Same)
89134345a63Smrg    {
89234345a63Smrg        if (array_ndx != NULL)
89334345a63Smrg            return ReportActionNotArray(action->type, field);
89434345a63Smrg        if (!ExprResolveBoolean(value, &rtrn, NULL, NULL))
89534345a63Smrg            return ReportMismatch(action->type, field, "boolean");
89634345a63Smrg        if (rtrn.uval)
89734345a63Smrg            act->flags &= ~XkbSA_SwitchApplication;
89834345a63Smrg        else
89934345a63Smrg            act->flags |= XkbSA_SwitchApplication;
90034345a63Smrg        return True;
901f46a6179Smrg    }
90234345a63Smrg    return ReportIllegal(action->type, field);
903f46a6179Smrg}
904f46a6179Smrg
90534345a63SmrgLookupEntry ctrlNames[] = {
90634345a63Smrg    {"repeatkeys", XkbRepeatKeysMask}
90734345a63Smrg    ,
90834345a63Smrg    {"repeat", XkbRepeatKeysMask}
90934345a63Smrg    ,
91034345a63Smrg    {"autorepeat", XkbRepeatKeysMask}
91134345a63Smrg    ,
91234345a63Smrg    {"slowkeys", XkbSlowKeysMask}
91334345a63Smrg    ,
91434345a63Smrg    {"bouncekeys", XkbBounceKeysMask}
91534345a63Smrg    ,
91634345a63Smrg    {"stickykeys", XkbStickyKeysMask}
91734345a63Smrg    ,
91834345a63Smrg    {"mousekeys", XkbMouseKeysMask}
91934345a63Smrg    ,
92034345a63Smrg    {"mousekeysaccel", XkbMouseKeysAccelMask}
92134345a63Smrg    ,
92234345a63Smrg    {"accessxkeys", XkbAccessXKeysMask}
92334345a63Smrg    ,
92434345a63Smrg    {"accessxtimeout", XkbAccessXTimeoutMask}
92534345a63Smrg    ,
92634345a63Smrg    {"accessxfeedback", XkbAccessXFeedbackMask}
92734345a63Smrg    ,
92834345a63Smrg    {"audiblebell", XkbAudibleBellMask}
92934345a63Smrg    ,
93034345a63Smrg    {"overlay1", XkbOverlay1Mask}
93134345a63Smrg    ,
93234345a63Smrg    {"overlay2", XkbOverlay2Mask}
93334345a63Smrg    ,
93434345a63Smrg    {"ignoregrouplock", XkbIgnoreGroupLockMask}
93534345a63Smrg    ,
93634345a63Smrg    {"all", XkbAllBooleanCtrlsMask}
93734345a63Smrg    ,
93834345a63Smrg    {"none", 0}
93934345a63Smrg    ,
94034345a63Smrg    {NULL, 0}
941f46a6179Smrg};
942f46a6179Smrg
943f46a6179Smrgstatic Bool
9446930ead5SmrgHandleSetLockControls(XkbDescPtr xkb, XkbAnyAction *action, unsigned field,
9456930ead5Smrg                      const ExprDef *array_ndx, const ExprDef *value)
946f46a6179Smrg{
94734345a63Smrg    ExprResult rtrn;
94834345a63Smrg    XkbCtrlsAction *act;
94934345a63Smrg
95034345a63Smrg    act = (XkbCtrlsAction *) action;
95134345a63Smrg    if (field == F_Controls)
95234345a63Smrg    {
95334345a63Smrg        if (array_ndx != NULL)
95434345a63Smrg            return ReportActionNotArray(action->type, field);
95534345a63Smrg        if (!ExprResolveMask
95634345a63Smrg            (value, &rtrn, SimpleLookup, (XPointer) ctrlNames))
95734345a63Smrg            return ReportMismatch(action->type, field, "controls mask");
95834345a63Smrg        XkbActionSetCtrls(act, rtrn.uval);
95934345a63Smrg        return True;
960f46a6179Smrg    }
961bfe6082cSmrg    else if (field == F_Affect && action->type == XkbSA_LockControls) {
962bfe6082cSmrg        if (array_ndx != NULL)
963bfe6082cSmrg            return ReportActionNotArray(action->type, field);
964bfe6082cSmrg        if (!ExprResolveEnum(value, &rtrn, lockWhich))
965bfe6082cSmrg            return ReportMismatch(action->type, field, "lock or unlock");
966bfe6082cSmrg        act->flags &= ~(XkbSA_LockNoLock | XkbSA_LockNoUnlock);
967bfe6082cSmrg        act->flags |= rtrn.uval;
968bfe6082cSmrg        return True;
969bfe6082cSmrg    }
97034345a63Smrg    return ReportIllegal(action->type, field);
971f46a6179Smrg}
972f46a6179Smrg
97334345a63Smrgstatic LookupEntry evNames[] = {
97434345a63Smrg    {"press", XkbSA_MessageOnPress},
97534345a63Smrg    {"keypress", XkbSA_MessageOnPress},
97634345a63Smrg    {"release", XkbSA_MessageOnRelease},
97734345a63Smrg    {"keyrelease", XkbSA_MessageOnRelease},
97834345a63Smrg    {"all", XkbSA_MessageOnPress | XkbSA_MessageOnRelease},
97934345a63Smrg    {"none", 0},
98034345a63Smrg    {NULL, 0}
981f46a6179Smrg};
982f46a6179Smrg
983f46a6179Smrgstatic Bool
9846930ead5SmrgHandleActionMessage(XkbDescPtr xkb, XkbAnyAction *action, unsigned field,
9856930ead5Smrg                    const ExprDef *array_ndx, const ExprDef *value)
986f46a6179Smrg{
98734345a63Smrg    ExprResult rtrn;
98834345a63Smrg    XkbMessageAction *act;
98934345a63Smrg
99034345a63Smrg    act = (XkbMessageAction *) action;
99134345a63Smrg    switch (field)
99234345a63Smrg    {
99334345a63Smrg    case F_Report:
99434345a63Smrg        if (array_ndx != NULL)
99534345a63Smrg            return ReportActionNotArray(action->type, field);
99634345a63Smrg        if (!ExprResolveMask(value, &rtrn, SimpleLookup, (XPointer) evNames))
99734345a63Smrg            return ReportMismatch(action->type, field, "key event mask");
99834345a63Smrg        act->flags &= ~(XkbSA_MessageOnPress | XkbSA_MessageOnRelease);
99934345a63Smrg        act->flags =
100034345a63Smrg            rtrn.uval & (XkbSA_MessageOnPress | XkbSA_MessageOnRelease);
100134345a63Smrg        return True;
100234345a63Smrg    case F_GenKeyEvent:
100334345a63Smrg        if (array_ndx != NULL)
100434345a63Smrg            return ReportActionNotArray(action->type, field);
100534345a63Smrg        if (!ExprResolveBoolean(value, &rtrn, NULL, NULL))
100634345a63Smrg            return ReportMismatch(action->type, field, "boolean");
100734345a63Smrg        if (rtrn.uval)
100834345a63Smrg            act->flags |= XkbSA_MessageGenKeyEvent;
100934345a63Smrg        else
101034345a63Smrg            act->flags &= ~XkbSA_MessageGenKeyEvent;
101134345a63Smrg        return True;
101234345a63Smrg    case F_Data:
101334345a63Smrg        if (array_ndx == NULL)
101434345a63Smrg        {
101534345a63Smrg            if (!ExprResolveString(value, &rtrn, NULL, NULL))
101634345a63Smrg                return ReportMismatch(action->type, field, "string");
101734345a63Smrg            else
101834345a63Smrg            {
101934345a63Smrg                int len = strlen(rtrn.str);
102034345a63Smrg                if ((len < 1) || (len > 6))
102134345a63Smrg                {
102234345a63Smrg                    WARN("An action message can hold only 6 bytes\n");
1023bfe6082cSmrg                    ACTION("Extra %d bytes ignored\n", len - 6);
102434345a63Smrg                }
102534345a63Smrg                strncpy((char *) act->message, rtrn.str, 6);
102634345a63Smrg            }
102734345a63Smrg            return True;
102834345a63Smrg        }
102934345a63Smrg        else
103034345a63Smrg        {
103134345a63Smrg            unsigned ndx;
103234345a63Smrg            if (!ExprResolveInteger(array_ndx, &rtrn, NULL, NULL))
103334345a63Smrg            {
103434345a63Smrg                ERROR("Array subscript must be integer\n");
103534345a63Smrg                ACTION("Illegal subscript ignored\n");
103634345a63Smrg                return False;
103734345a63Smrg            }
103834345a63Smrg            ndx = rtrn.uval;
103934345a63Smrg            if (ndx > 5)
104034345a63Smrg            {
104134345a63Smrg                ERROR("An action message is at most 6 bytes long\n");
1042bfe6082cSmrg                ACTION("Attempt to use data[%d] ignored\n", ndx);
104334345a63Smrg                return False;
104434345a63Smrg            }
104534345a63Smrg            if (!ExprResolveInteger(value, &rtrn, NULL, NULL))
104634345a63Smrg                return ReportMismatch(action->type, field, "integer");
104734345a63Smrg            if ((rtrn.ival < 0) || (rtrn.ival > 255))
104834345a63Smrg            {
104934345a63Smrg                ERROR("Message data must be in the range 0..255\n");
1050bfe6082cSmrg                ACTION("Illegal datum %d ignored\n", rtrn.ival);
105134345a63Smrg                return False;
105234345a63Smrg            }
105334345a63Smrg            act->message[ndx] = rtrn.uval;
105434345a63Smrg        }
105534345a63Smrg        return True;
1056f46a6179Smrg    }
105734345a63Smrg    return ReportIllegal(action->type, field);
1058f46a6179Smrg}
1059f46a6179Smrg
1060f46a6179Smrgstatic Bool
10616930ead5SmrgHandleRedirectKey(XkbDescPtr xkb, XkbAnyAction *action, unsigned field,
10626930ead5Smrg                  const ExprDef *array_ndx, const ExprDef *value)
1063f46a6179Smrg{
106434345a63Smrg    ExprResult rtrn;
106534345a63Smrg    XkbRedirectKeyAction *act;
106634345a63Smrg
106734345a63Smrg    if (array_ndx != NULL)
106834345a63Smrg        return ReportActionNotArray(action->type, field);
106934345a63Smrg
107034345a63Smrg    act = (XkbRedirectKeyAction *) action;
107134345a63Smrg    switch (field)
107234345a63Smrg    {
107334345a63Smrg    case F_Keycode:
10746930ead5Smrg    {
10756930ead5Smrg        unsigned int t1;
10766930ead5Smrg        unsigned long tmp;
10776930ead5Smrg
107834345a63Smrg        if (!ExprResolveKeyName(value, &rtrn, NULL, NULL))
107934345a63Smrg            return ReportMismatch(action->type, field, "key name");
108034345a63Smrg        tmp = KeyNameToLong(rtrn.keyName.name);
108134345a63Smrg        if (!FindNamedKey(xkb, tmp, &t1, True, CreateKeyNames(xkb), 0))
108234345a63Smrg        {
108334345a63Smrg            return ReportNotFound(action->type, field, "Key",
108434345a63Smrg                                  XkbKeyNameText(rtrn.keyName.name,
108534345a63Smrg                                                 XkbMessage));
108634345a63Smrg        }
108734345a63Smrg        act->new_key = t1;
108834345a63Smrg        return True;
10896930ead5Smrg    }
109034345a63Smrg    case F_ModsToClear:
109134345a63Smrg    case F_Modifiers:
10926930ead5Smrg    {
10936930ead5Smrg        unsigned t1 = 0, t2;
10946930ead5Smrg
109534345a63Smrg        if (CheckModifierField(xkb, action->type, value, &t1, &t2))
109634345a63Smrg        {
10976930ead5Smrg            unsigned vmods, vmask;
10986930ead5Smrg
109934345a63Smrg            act->mods_mask |= (t2 & 0xff);
110034345a63Smrg            if (field == F_Modifiers)
110134345a63Smrg                act->mods |= (t2 & 0xff);
110234345a63Smrg            else
110334345a63Smrg                act->mods &= ~(t2 & 0xff);
110434345a63Smrg
110534345a63Smrg            t2 = (t2 >> 8) & 0xffff;
110634345a63Smrg            vmods = XkbSARedirectVMods(act);
110734345a63Smrg            vmask = XkbSARedirectVModsMask(act);
110834345a63Smrg            vmask |= t2;
110934345a63Smrg            if (field == F_Modifiers)
111034345a63Smrg                vmods |= t2;
111134345a63Smrg            else
111234345a63Smrg                vmods &= ~t2;
111334345a63Smrg            XkbSARedirectSetVMods(act, vmods);
111434345a63Smrg            XkbSARedirectSetVModsMask(act, vmask);
111534345a63Smrg            return True;
111634345a63Smrg        }
111734345a63Smrg        return True;
1118f46a6179Smrg    }
11196930ead5Smrg    }
112034345a63Smrg    return ReportIllegal(action->type, field);
1121f46a6179Smrg}
1122f46a6179Smrg
1123f46a6179Smrgstatic Bool
11246930ead5SmrgHandleDeviceBtn(XkbDescPtr xkb, XkbAnyAction *action, unsigned field,
11256930ead5Smrg                const ExprDef *array_ndx, const ExprDef *value)
1126f46a6179Smrg{
112734345a63Smrg    ExprResult rtrn;
112834345a63Smrg    XkbDeviceBtnAction *act;
112934345a63Smrg
113034345a63Smrg    act = (XkbDeviceBtnAction *) action;
113134345a63Smrg    if (field == F_Button)
113234345a63Smrg    {
113334345a63Smrg        if (array_ndx != NULL)
113434345a63Smrg            return ReportActionNotArray(action->type, field);
113534345a63Smrg        if (!ExprResolveInteger(value, &rtrn, NULL, NULL))
113634345a63Smrg            return ReportMismatch(action->type, field,
113734345a63Smrg                                  "integer (range 1..255)");
113834345a63Smrg        if ((rtrn.ival < 0) || (rtrn.ival > 255))
113934345a63Smrg        {
114034345a63Smrg            ERROR("Button must specify default or be in the range 1..255\n");
1141bfe6082cSmrg            ACTION("Illegal button value %d ignored\n", rtrn.ival);
114234345a63Smrg            return False;
114334345a63Smrg        }
114434345a63Smrg        act->button = rtrn.ival;
114534345a63Smrg        return True;
1146f46a6179Smrg    }
114734345a63Smrg    else if ((action->type == XkbSA_LockDeviceBtn) && (field == F_Affect))
114834345a63Smrg    {
114934345a63Smrg        if (array_ndx != NULL)
115034345a63Smrg            return ReportActionNotArray(action->type, field);
115134345a63Smrg        if (!ExprResolveEnum(value, &rtrn, lockWhich))
115234345a63Smrg            return ReportMismatch(action->type, field, "lock or unlock");
115334345a63Smrg        act->flags &= ~(XkbSA_LockNoLock | XkbSA_LockNoUnlock);
1154bfe6082cSmrg        act->flags |= rtrn.uval;
115534345a63Smrg        return True;
1156f46a6179Smrg    }
115734345a63Smrg    else if (field == F_Count)
115834345a63Smrg    {
115934345a63Smrg        if (array_ndx != NULL)
116034345a63Smrg            return ReportActionNotArray(action->type, field);
116134345a63Smrg        if (!ExprResolveInteger
116234345a63Smrg            (value, &rtrn, SimpleLookup, (XPointer) btnNames))
116334345a63Smrg            return ReportMismatch(action->type, field, "integer");
116434345a63Smrg        if ((rtrn.ival < 0) || (rtrn.ival > 255))
116534345a63Smrg        {
116634345a63Smrg            ERROR("The count field must have a value in the range 0..255\n");
1167bfe6082cSmrg            ACTION("Illegal count %d ignored\n", rtrn.ival);
116834345a63Smrg            return False;
116934345a63Smrg        }
117034345a63Smrg        act->count = rtrn.ival;
117134345a63Smrg        return True;
1172f46a6179Smrg    }
117334345a63Smrg    else if (field == F_Device)
117434345a63Smrg    {
117534345a63Smrg        if (array_ndx != NULL)
117634345a63Smrg            return ReportActionNotArray(action->type, field);
117734345a63Smrg        if (!ExprResolveInteger(value, &rtrn, NULL, NULL))
117834345a63Smrg            return ReportMismatch(action->type, field,
117934345a63Smrg                                  "integer (range 1..255)");
118034345a63Smrg        if ((rtrn.ival < 0) || (rtrn.ival > 255))
118134345a63Smrg        {
118234345a63Smrg            ERROR("Device must specify default or be in the range 1..255\n");
1183bfe6082cSmrg            ACTION("Illegal device value %d ignored\n", rtrn.ival);
118434345a63Smrg            return False;
118534345a63Smrg        }
118634345a63Smrg        act->device = rtrn.ival;
118734345a63Smrg        return True;
1188f46a6179Smrg    }
118934345a63Smrg    return ReportIllegal(action->type, field);
1190f46a6179Smrg}
1191f46a6179Smrg
1192f46a6179Smrgstatic Bool
11936930ead5SmrgHandleDeviceValuator(XkbDescPtr xkb, XkbAnyAction *action, unsigned field,
11946930ead5Smrg                     const ExprDef *array_ndx, const ExprDef *value)
1195f46a6179Smrg{
1196f46a6179Smrg#if 0
119734345a63Smrg    ExprResult rtrn;
119834345a63Smrg    XkbDeviceValuatorAction *act;
1199f46a6179Smrg
120034345a63Smrg    act = (XkbDeviceValuatorAction *) action;
1201f46a6179Smrg    /*  XXX - Not yet implemented */
1202f46a6179Smrg#endif
1203f46a6179Smrg    return False;
1204f46a6179Smrg}
1205f46a6179Smrg
1206f46a6179Smrgstatic Bool
12076930ead5SmrgHandlePrivate(XkbDescPtr xkb, XkbAnyAction *action, unsigned field,
12086930ead5Smrg              const ExprDef *array_ndx, const ExprDef *value)
1209f46a6179Smrg{
121034345a63Smrg    ExprResult rtrn;
121134345a63Smrg
121234345a63Smrg    switch (field)
121334345a63Smrg    {
121434345a63Smrg    case F_Type:
121534345a63Smrg        if (!ExprResolveInteger(value, &rtrn, NULL, NULL))
121634345a63Smrg            return ReportMismatch(PrivateAction, field, "integer");
121734345a63Smrg        if ((rtrn.ival < 0) || (rtrn.ival > 255))
121834345a63Smrg        {
121934345a63Smrg            ERROR("Private action type must be in the range 0..255\n");
1220bfe6082cSmrg            ACTION("Illegal type %d ignored\n", rtrn.ival);
122134345a63Smrg            return False;
122234345a63Smrg        }
122334345a63Smrg        action->type = rtrn.uval;
122434345a63Smrg        return True;
122534345a63Smrg    case F_Data:
122634345a63Smrg        if (array_ndx == NULL)
122734345a63Smrg        {
122834345a63Smrg            if (!ExprResolveString(value, &rtrn, NULL, NULL))
122934345a63Smrg                return ReportMismatch(action->type, field, "string");
123034345a63Smrg            else
123134345a63Smrg            {
123234345a63Smrg                int len = strlen(rtrn.str);
123334345a63Smrg                if ((len < 1) || (len > 7))
123434345a63Smrg                {
123534345a63Smrg                    WARN("A private action has 7 data bytes\n");
1236bfe6082cSmrg                    ACTION("Extra %d bytes ignored\n", len - 6);
123734345a63Smrg                    return False;
123834345a63Smrg                }
123934345a63Smrg                strncpy((char *) action->data, rtrn.str, 7);
124034345a63Smrg            }
124134345a63Smrg            return True;
124234345a63Smrg        }
124334345a63Smrg        else
124434345a63Smrg        {
124534345a63Smrg            unsigned ndx;
124634345a63Smrg            if (!ExprResolveInteger(array_ndx, &rtrn, NULL, NULL))
124734345a63Smrg            {
124834345a63Smrg                ERROR("Array subscript must be integer\n");
124934345a63Smrg                ACTION("Illegal subscript ignored\n");
125034345a63Smrg                return False;
125134345a63Smrg            }
125234345a63Smrg            ndx = rtrn.uval;
125334345a63Smrg            if (ndx > 6)
125434345a63Smrg            {
125534345a63Smrg                ERROR("The data for a private action is 7 bytes long\n");
1256bfe6082cSmrg                ACTION("Attempt to use data[%d] ignored\n", ndx);
125734345a63Smrg                return False;
125834345a63Smrg            }
125934345a63Smrg            if (!ExprResolveInteger(value, &rtrn, NULL, NULL))
126034345a63Smrg                return ReportMismatch(action->type, field, "integer");
126134345a63Smrg            if ((rtrn.ival < 0) || (rtrn.ival > 255))
126234345a63Smrg            {
126334345a63Smrg                ERROR("All data for a private action must be 0..255\n");
1264bfe6082cSmrg                ACTION("Illegal datum %d ignored\n", rtrn.ival);
126534345a63Smrg                return False;
126634345a63Smrg            }
126734345a63Smrg            action->data[ndx] = rtrn.uval;
126834345a63Smrg            return True;
126934345a63Smrg        }
1270f46a6179Smrg    }
127134345a63Smrg    return ReportIllegal(PrivateAction, field);
1272f46a6179Smrg}
1273f46a6179Smrg
127434345a63Smrgtypedef Bool(*actionHandler) (XkbDescPtr /* xkb */ ,
127534345a63Smrg                              XkbAnyAction * /* action */ ,
127634345a63Smrg                              unsigned /* field */ ,
12776930ead5Smrg                              const ExprDef * /* array_ndx */ ,
12786930ead5Smrg                              const ExprDef * /* value */
127934345a63Smrg    );
128034345a63Smrg
128134345a63Smrgstatic actionHandler handleAction[XkbSA_NumActions + 1] = {
128234345a63Smrg    HandleNoAction /* NoAction     */ ,
128334345a63Smrg    HandleSetLatchMods /* SetMods      */ ,
128434345a63Smrg    HandleSetLatchMods /* LatchMods    */ ,
128534345a63Smrg    HandleLockMods /* LockMods     */ ,
128634345a63Smrg    HandleSetLatchGroup /* SetGroup     */ ,
128734345a63Smrg    HandleSetLatchGroup /* LatchGroup   */ ,
128834345a63Smrg    HandleLockGroup /* LockGroup    */ ,
128934345a63Smrg    HandleMovePtr /* MovePtr      */ ,
129034345a63Smrg    HandlePtrBtn /* PtrBtn       */ ,
129134345a63Smrg    HandlePtrBtn /* LockPtrBtn   */ ,
129234345a63Smrg    HandleSetPtrDflt /* SetPtrDflt   */ ,
129334345a63Smrg    HandleISOLock /* ISOLock      */ ,
129434345a63Smrg    HandleNoAction /* Terminate    */ ,
129534345a63Smrg    HandleSwitchScreen /* SwitchScreen */ ,
129634345a63Smrg    HandleSetLockControls /* SetControls  */ ,
129734345a63Smrg    HandleSetLockControls /* LockControls */ ,
129834345a63Smrg    HandleActionMessage /* ActionMessage */ ,
129934345a63Smrg    HandleRedirectKey /* RedirectKey  */ ,
130034345a63Smrg    HandleDeviceBtn /* DeviceBtn    */ ,
130134345a63Smrg    HandleDeviceBtn /* LockDeviceBtn */ ,
130234345a63Smrg    HandleDeviceValuator /* DeviceValuatr */ ,
130334345a63Smrg    HandlePrivate               /* Private      */
1304f46a6179Smrg};
1305f46a6179Smrg
1306f46a6179Smrg/***====================================================================***/
1307f46a6179Smrg
1308f46a6179Smrgstatic void
130934345a63SmrgApplyActionFactoryDefaults(XkbAction * action)
1310f46a6179Smrg{
131134345a63Smrg    if (action->type == XkbSA_SetPtrDflt)
131234345a63Smrg    {                           /* increment default button */
131334345a63Smrg        action->dflt.affect = XkbSA_AffectDfltBtn;
131434345a63Smrg        action->dflt.flags = 0;
131534345a63Smrg        XkbSASetPtrDfltValue(&action->dflt, 1);
1316f46a6179Smrg    }
131734345a63Smrg    else if (action->type == XkbSA_ISOLock)
131834345a63Smrg    {
1319bfe6082cSmrg        action->iso.real_mods = action->iso.mask = LockMask;
1320f46a6179Smrg    }
1321f46a6179Smrg    return;
1322f46a6179Smrg}
1323f46a6179Smrg
1324f46a6179Smrg
132534345a63Smrgint
13266930ead5SmrgHandleActionDef(const ExprDef *def, XkbDescPtr xkb, XkbAnyAction *action,
13276930ead5Smrg                unsigned mergeMode, const ActionInfo *info)
1328f46a6179Smrg{
132934345a63Smrg    ExprDef *arg;
13306930ead5Smrg    const char *str;
133134345a63Smrg    unsigned tmp, hndlrType;
1332f46a6179Smrg
1333f46a6179Smrg    if (!actionsInitialized)
133434345a63Smrg        ActionsInit();
1335f46a6179Smrg
133634345a63Smrg    if (def->op != ExprActionDecl)
133734345a63Smrg    {
1338bfe6082cSmrg        ERROR("Expected an action definition, found %s\n",
133934345a63Smrg               exprOpText(def->op));
134034345a63Smrg        return False;
1341f46a6179Smrg    }
134234345a63Smrg    str = XkbAtomGetString(NULL, def->value.action.name);
134334345a63Smrg    if (!str)
134434345a63Smrg    {
134534345a63Smrg        WSGO("Missing name in action definition!!\n");
134634345a63Smrg        return False;
1347f46a6179Smrg    }
134834345a63Smrg    if (!stringToAction(str, &tmp))
134934345a63Smrg    {
1350bfe6082cSmrg        ERROR("Unknown action %s\n", str);
135134345a63Smrg        return False;
1352f46a6179Smrg    }
135334345a63Smrg    action->type = hndlrType = tmp;
135434345a63Smrg    if (action->type != XkbSA_NoAction)
135534345a63Smrg    {
135634345a63Smrg        ApplyActionFactoryDefaults((XkbAction *) action);
135734345a63Smrg        while (info)
135834345a63Smrg        {
135934345a63Smrg            if ((info->action == XkbSA_NoAction)
136034345a63Smrg                || (info->action == hndlrType))
136134345a63Smrg            {
136234345a63Smrg                if (!(*handleAction[hndlrType]) (xkb, action,
136334345a63Smrg                                                 info->field,
136434345a63Smrg                                                 info->array_ndx,
136534345a63Smrg                                                 info->value))
136634345a63Smrg                {
136734345a63Smrg                    return False;
136834345a63Smrg                }
136934345a63Smrg            }
137034345a63Smrg            info = info->next;
137134345a63Smrg        }
1372f46a6179Smrg    }
137334345a63Smrg    for (arg = def->value.action.args; arg != NULL;
137434345a63Smrg         arg = (ExprDef *) arg->common.next)
137534345a63Smrg    {
137634345a63Smrg        ExprDef *field, *value, *arrayRtrn;
137734345a63Smrg        ExprResult elemRtrn, fieldRtrn;
137834345a63Smrg        unsigned fieldNdx;
137934345a63Smrg
138034345a63Smrg        if (arg->op == OpAssign)
138134345a63Smrg        {
138234345a63Smrg            field = arg->value.binary.left;
138334345a63Smrg            value = arg->value.binary.right;
138434345a63Smrg        }
138534345a63Smrg        else
138634345a63Smrg        {
138734345a63Smrg            if ((arg->op == OpNot) || (arg->op == OpInvert))
138834345a63Smrg            {
138934345a63Smrg                field = arg->value.child;
139034345a63Smrg                value = &constFalse;
139134345a63Smrg            }
139234345a63Smrg            else
139334345a63Smrg            {
139434345a63Smrg                field = arg;
139534345a63Smrg                value = &constTrue;
139634345a63Smrg            }
139734345a63Smrg        }
139834345a63Smrg        if (!ExprResolveLhs(field, &elemRtrn, &fieldRtrn, &arrayRtrn))
139934345a63Smrg            return False;       /* internal error -- already reported */
140034345a63Smrg
140134345a63Smrg        if (elemRtrn.str != NULL)
140234345a63Smrg        {
140334345a63Smrg            ERROR("Cannot change defaults in an action definition\n");
1404bfe6082cSmrg            ACTION("Ignoring attempt to change %s.%s\n", elemRtrn.str,
140534345a63Smrg                    fieldRtrn.str);
140634345a63Smrg            return False;
140734345a63Smrg        }
140834345a63Smrg        if (!stringToField(fieldRtrn.str, &fieldNdx))
140934345a63Smrg        {
1410bfe6082cSmrg            ERROR("Unknown field name %s\n", uStringText(fieldRtrn.str));
141134345a63Smrg            return False;
141234345a63Smrg        }
141334345a63Smrg        if (!(*handleAction[hndlrType])
141434345a63Smrg            (xkb, action, fieldNdx, arrayRtrn, value))
141534345a63Smrg        {
141634345a63Smrg            return False;
141734345a63Smrg        }
1418f46a6179Smrg    }
1419f46a6179Smrg    return True;
1420f46a6179Smrg}
1421f46a6179Smrg
1422f46a6179Smrg/***====================================================================***/
1423f46a6179Smrg
142434345a63Smrgint
14256930ead5SmrgSetActionField(XkbDescPtr xkb, const char *elem, const char *field,
14266930ead5Smrg               ExprDef *array_ndx, ExprDef *value, ActionInfo **info_rtrn)
1427f46a6179Smrg{
142834345a63Smrg    ActionInfo *new, *old;
1429f46a6179Smrg
1430f46a6179Smrg    if (!actionsInitialized)
143134345a63Smrg        ActionsInit();
1432f46a6179Smrg
14336930ead5Smrg    new = malloc(sizeof(ActionInfo));
143434345a63Smrg    if (new == NULL)
143534345a63Smrg    {
143634345a63Smrg        WSGO("Couldn't allocate space for action default\n");
143734345a63Smrg        return False;
1438f46a6179Smrg    }
143934345a63Smrg    if (uStrCaseCmp(elem, "action") == 0)
144034345a63Smrg        new->action = XkbSA_NoAction;
144134345a63Smrg    else
144234345a63Smrg    {
144334345a63Smrg        if (!stringToAction(elem, &new->action))
144434345a63Smrg            return False;
144534345a63Smrg        if (new->action == XkbSA_NoAction)
144634345a63Smrg        {
1447bfe6082cSmrg            ERROR("\"%s\" is not a valid field in a NoAction action\n",
144834345a63Smrg                   field);
144934345a63Smrg            return False;
145034345a63Smrg        }
1451f46a6179Smrg    }
145234345a63Smrg    if (!stringToField(field, &new->field))
145334345a63Smrg    {
1454bfe6082cSmrg        ERROR("\"%s\" is not a legal field name\n", field);
145534345a63Smrg        return False;
1456f46a6179Smrg    }
145734345a63Smrg    new->array_ndx = array_ndx;
145834345a63Smrg    new->value = value;
145934345a63Smrg    new->next = NULL;
146034345a63Smrg    old = *info_rtrn;
146134345a63Smrg    while ((old) && (old->next))
146234345a63Smrg        old = old->next;
146334345a63Smrg    if (old == NULL)
146434345a63Smrg        *info_rtrn = new;
146534345a63Smrg    else
146634345a63Smrg        old->next = new;
1467f46a6179Smrg    return True;
1468f46a6179Smrg}
1469f46a6179Smrg
1470f46a6179Smrg/***====================================================================***/
1471f46a6179Smrg
14726930ead5Smrgstatic void
1473f46a6179SmrgActionsInit(void)
1474f46a6179Smrg{
147534345a63Smrg    if (!actionsInitialized)
147634345a63Smrg    {
14776930ead5Smrg        bzero(&constTrue, sizeof(constTrue));
14786930ead5Smrg        constTrue = (ExprDef) {
14796930ead5Smrg            .common.stmtType = StmtExpr,
14806930ead5Smrg            .common.next = NULL,
14816930ead5Smrg            .op = ExprIdent,
14826930ead5Smrg            .type = TypeBoolean,
14836930ead5Smrg            .value.str = XkbInternAtom(NULL, "true", False)
14846930ead5Smrg        };
14856930ead5Smrg        bzero(&constFalse, sizeof(constFalse));
14866930ead5Smrg        constFalse = (ExprDef) {
14876930ead5Smrg            .common.stmtType = StmtExpr,
14886930ead5Smrg            .common.next = NULL,
14896930ead5Smrg            .op = ExprIdent,
14906930ead5Smrg            .type = TypeBoolean,
14916930ead5Smrg            .value.str = XkbInternAtom(NULL, "false", False)
14926930ead5Smrg        };
149334345a63Smrg        actionsInitialized = 1;
1494f46a6179Smrg    }
1495f46a6179Smrg    return;
1496f46a6179Smrg}
1497