xref: /aosp_15_r20/external/libxkbcommon/src/xkbcomp/action.c (revision 2b949d0487e80d67f1fda82db69e101e761f8064)
1*2b949d04SAndroid Build Coastguard Worker /************************************************************
2*2b949d04SAndroid Build Coastguard Worker  * Copyright (c) 1994 by Silicon Graphics Computer Systems, Inc.
3*2b949d04SAndroid Build Coastguard Worker  *
4*2b949d04SAndroid Build Coastguard Worker  * Permission to use, copy, modify, and distribute this
5*2b949d04SAndroid Build Coastguard Worker  * software and its documentation for any purpose and without
6*2b949d04SAndroid Build Coastguard Worker  * fee is hereby granted, provided that the above copyright
7*2b949d04SAndroid Build Coastguard Worker  * notice appear in all copies and that both that copyright
8*2b949d04SAndroid Build Coastguard Worker  * notice and this permission notice appear in supporting
9*2b949d04SAndroid Build Coastguard Worker  * documentation, and that the name of Silicon Graphics not be
10*2b949d04SAndroid Build Coastguard Worker  * used in advertising or publicity pertaining to distribution
11*2b949d04SAndroid Build Coastguard Worker  * of the software without specific prior written permission.
12*2b949d04SAndroid Build Coastguard Worker  * Silicon Graphics makes no representation about the suitability
13*2b949d04SAndroid Build Coastguard Worker  * of this software for any purpose. It is provided "as is"
14*2b949d04SAndroid Build Coastguard Worker  * without any express or implied warranty.
15*2b949d04SAndroid Build Coastguard Worker  *
16*2b949d04SAndroid Build Coastguard Worker  * SILICON GRAPHICS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS
17*2b949d04SAndroid Build Coastguard Worker  * SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
18*2b949d04SAndroid Build Coastguard Worker  * AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL SILICON
19*2b949d04SAndroid Build Coastguard Worker  * GRAPHICS BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL
20*2b949d04SAndroid Build Coastguard Worker  * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
21*2b949d04SAndroid Build Coastguard Worker  * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
22*2b949d04SAndroid Build Coastguard Worker  * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION  WITH
23*2b949d04SAndroid Build Coastguard Worker  * THE USE OR PERFORMANCE OF THIS SOFTWARE.
24*2b949d04SAndroid Build Coastguard Worker  *
25*2b949d04SAndroid Build Coastguard Worker  ********************************************************/
26*2b949d04SAndroid Build Coastguard Worker 
27*2b949d04SAndroid Build Coastguard Worker /*
28*2b949d04SAndroid Build Coastguard Worker  * Copyright © 2012 Intel Corporation
29*2b949d04SAndroid Build Coastguard Worker  * Copyright © 2012 Ran Benita <[email protected]>
30*2b949d04SAndroid Build Coastguard Worker  *
31*2b949d04SAndroid Build Coastguard Worker  * Permission is hereby granted, free of charge, to any person obtaining a
32*2b949d04SAndroid Build Coastguard Worker  * copy of this software and associated documentation files (the "Software"),
33*2b949d04SAndroid Build Coastguard Worker  * to deal in the Software without restriction, including without limitation
34*2b949d04SAndroid Build Coastguard Worker  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
35*2b949d04SAndroid Build Coastguard Worker  * and/or sell copies of the Software, and to permit persons to whom the
36*2b949d04SAndroid Build Coastguard Worker  * Software is furnished to do so, subject to the following conditions:
37*2b949d04SAndroid Build Coastguard Worker  *
38*2b949d04SAndroid Build Coastguard Worker  * The above copyright notice and this permission notice (including the next
39*2b949d04SAndroid Build Coastguard Worker  * paragraph) shall be included in all copies or substantial portions of the
40*2b949d04SAndroid Build Coastguard Worker  * Software.
41*2b949d04SAndroid Build Coastguard Worker  *
42*2b949d04SAndroid Build Coastguard Worker  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
43*2b949d04SAndroid Build Coastguard Worker  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
44*2b949d04SAndroid Build Coastguard Worker  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
45*2b949d04SAndroid Build Coastguard Worker  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
46*2b949d04SAndroid Build Coastguard Worker  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
47*2b949d04SAndroid Build Coastguard Worker  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
48*2b949d04SAndroid Build Coastguard Worker  * DEALINGS IN THE SOFTWARE.
49*2b949d04SAndroid Build Coastguard Worker  *
50*2b949d04SAndroid Build Coastguard Worker  * Author: Daniel Stone <[email protected]>
51*2b949d04SAndroid Build Coastguard Worker  *         Ran Benita <[email protected]>
52*2b949d04SAndroid Build Coastguard Worker  */
53*2b949d04SAndroid Build Coastguard Worker 
54*2b949d04SAndroid Build Coastguard Worker #include "config.h"
55*2b949d04SAndroid Build Coastguard Worker 
56*2b949d04SAndroid Build Coastguard Worker #include "xkbcomp-priv.h"
57*2b949d04SAndroid Build Coastguard Worker #include "text.h"
58*2b949d04SAndroid Build Coastguard Worker #include "expr.h"
59*2b949d04SAndroid Build Coastguard Worker #include "action.h"
60*2b949d04SAndroid Build Coastguard Worker 
61*2b949d04SAndroid Build Coastguard Worker static const ExprBoolean constTrue = {
62*2b949d04SAndroid Build Coastguard Worker     .expr = {
63*2b949d04SAndroid Build Coastguard Worker         .common = { .type = STMT_EXPR, .next = NULL },
64*2b949d04SAndroid Build Coastguard Worker         .op = EXPR_VALUE,
65*2b949d04SAndroid Build Coastguard Worker         .value_type = EXPR_TYPE_BOOLEAN,
66*2b949d04SAndroid Build Coastguard Worker     },
67*2b949d04SAndroid Build Coastguard Worker     .set = true,
68*2b949d04SAndroid Build Coastguard Worker };
69*2b949d04SAndroid Build Coastguard Worker 
70*2b949d04SAndroid Build Coastguard Worker static const ExprBoolean constFalse = {
71*2b949d04SAndroid Build Coastguard Worker     .expr = {
72*2b949d04SAndroid Build Coastguard Worker         .common = { .type = STMT_EXPR, .next = NULL },
73*2b949d04SAndroid Build Coastguard Worker         .op = EXPR_VALUE,
74*2b949d04SAndroid Build Coastguard Worker         .value_type = EXPR_TYPE_BOOLEAN,
75*2b949d04SAndroid Build Coastguard Worker     },
76*2b949d04SAndroid Build Coastguard Worker     .set = false,
77*2b949d04SAndroid Build Coastguard Worker };
78*2b949d04SAndroid Build Coastguard Worker 
79*2b949d04SAndroid Build Coastguard Worker enum action_field {
80*2b949d04SAndroid Build Coastguard Worker     ACTION_FIELD_CLEAR_LOCKS,
81*2b949d04SAndroid Build Coastguard Worker     ACTION_FIELD_LATCH_TO_LOCK,
82*2b949d04SAndroid Build Coastguard Worker     ACTION_FIELD_GEN_KEY_EVENT,
83*2b949d04SAndroid Build Coastguard Worker     ACTION_FIELD_REPORT,
84*2b949d04SAndroid Build Coastguard Worker     ACTION_FIELD_DEFAULT,
85*2b949d04SAndroid Build Coastguard Worker     ACTION_FIELD_AFFECT,
86*2b949d04SAndroid Build Coastguard Worker     ACTION_FIELD_INCREMENT,
87*2b949d04SAndroid Build Coastguard Worker     ACTION_FIELD_MODIFIERS,
88*2b949d04SAndroid Build Coastguard Worker     ACTION_FIELD_GROUP,
89*2b949d04SAndroid Build Coastguard Worker     ACTION_FIELD_X,
90*2b949d04SAndroid Build Coastguard Worker     ACTION_FIELD_Y,
91*2b949d04SAndroid Build Coastguard Worker     ACTION_FIELD_ACCEL,
92*2b949d04SAndroid Build Coastguard Worker     ACTION_FIELD_BUTTON,
93*2b949d04SAndroid Build Coastguard Worker     ACTION_FIELD_VALUE,
94*2b949d04SAndroid Build Coastguard Worker     ACTION_FIELD_CONTROLS,
95*2b949d04SAndroid Build Coastguard Worker     ACTION_FIELD_TYPE,
96*2b949d04SAndroid Build Coastguard Worker     ACTION_FIELD_COUNT,
97*2b949d04SAndroid Build Coastguard Worker     ACTION_FIELD_SCREEN,
98*2b949d04SAndroid Build Coastguard Worker     ACTION_FIELD_SAME,
99*2b949d04SAndroid Build Coastguard Worker     ACTION_FIELD_DATA,
100*2b949d04SAndroid Build Coastguard Worker     ACTION_FIELD_DEVICE,
101*2b949d04SAndroid Build Coastguard Worker     ACTION_FIELD_KEYCODE,
102*2b949d04SAndroid Build Coastguard Worker     ACTION_FIELD_MODS_TO_CLEAR,
103*2b949d04SAndroid Build Coastguard Worker };
104*2b949d04SAndroid Build Coastguard Worker 
105*2b949d04SAndroid Build Coastguard Worker ActionsInfo *
NewActionsInfo(void)106*2b949d04SAndroid Build Coastguard Worker NewActionsInfo(void)
107*2b949d04SAndroid Build Coastguard Worker {
108*2b949d04SAndroid Build Coastguard Worker     enum xkb_action_type type;
109*2b949d04SAndroid Build Coastguard Worker     ActionsInfo *info;
110*2b949d04SAndroid Build Coastguard Worker 
111*2b949d04SAndroid Build Coastguard Worker     info = calloc(1, sizeof(*info));
112*2b949d04SAndroid Build Coastguard Worker     if (!info)
113*2b949d04SAndroid Build Coastguard Worker         return NULL;
114*2b949d04SAndroid Build Coastguard Worker 
115*2b949d04SAndroid Build Coastguard Worker     for (type = 0; type < _ACTION_TYPE_NUM_ENTRIES; type++)
116*2b949d04SAndroid Build Coastguard Worker         info->actions[type].type = type;
117*2b949d04SAndroid Build Coastguard Worker 
118*2b949d04SAndroid Build Coastguard Worker     /* Apply some "factory defaults". */
119*2b949d04SAndroid Build Coastguard Worker 
120*2b949d04SAndroid Build Coastguard Worker     /* Increment default button. */
121*2b949d04SAndroid Build Coastguard Worker     info->actions[ACTION_TYPE_PTR_DEFAULT].dflt.flags = 0;
122*2b949d04SAndroid Build Coastguard Worker     info->actions[ACTION_TYPE_PTR_DEFAULT].dflt.value = 1;
123*2b949d04SAndroid Build Coastguard Worker     info->actions[ACTION_TYPE_PTR_MOVE].ptr.flags = ACTION_ACCEL;
124*2b949d04SAndroid Build Coastguard Worker     info->actions[ACTION_TYPE_SWITCH_VT].screen.flags = ACTION_SAME_SCREEN;
125*2b949d04SAndroid Build Coastguard Worker 
126*2b949d04SAndroid Build Coastguard Worker     return info;
127*2b949d04SAndroid Build Coastguard Worker }
128*2b949d04SAndroid Build Coastguard Worker 
129*2b949d04SAndroid Build Coastguard Worker void
FreeActionsInfo(ActionsInfo * info)130*2b949d04SAndroid Build Coastguard Worker FreeActionsInfo(ActionsInfo *info)
131*2b949d04SAndroid Build Coastguard Worker {
132*2b949d04SAndroid Build Coastguard Worker     free(info);
133*2b949d04SAndroid Build Coastguard Worker }
134*2b949d04SAndroid Build Coastguard Worker 
135*2b949d04SAndroid Build Coastguard Worker static const LookupEntry fieldStrings[] = {
136*2b949d04SAndroid Build Coastguard Worker     { "clearLocks",       ACTION_FIELD_CLEAR_LOCKS   },
137*2b949d04SAndroid Build Coastguard Worker     { "latchToLock",      ACTION_FIELD_LATCH_TO_LOCK },
138*2b949d04SAndroid Build Coastguard Worker     { "genKeyEvent",      ACTION_FIELD_GEN_KEY_EVENT },
139*2b949d04SAndroid Build Coastguard Worker     { "generateKeyEvent", ACTION_FIELD_GEN_KEY_EVENT },
140*2b949d04SAndroid Build Coastguard Worker     { "report",           ACTION_FIELD_REPORT        },
141*2b949d04SAndroid Build Coastguard Worker     { "default",          ACTION_FIELD_DEFAULT       },
142*2b949d04SAndroid Build Coastguard Worker     { "affect",           ACTION_FIELD_AFFECT        },
143*2b949d04SAndroid Build Coastguard Worker     { "increment",        ACTION_FIELD_INCREMENT     },
144*2b949d04SAndroid Build Coastguard Worker     { "modifiers",        ACTION_FIELD_MODIFIERS     },
145*2b949d04SAndroid Build Coastguard Worker     { "mods",             ACTION_FIELD_MODIFIERS     },
146*2b949d04SAndroid Build Coastguard Worker     { "group",            ACTION_FIELD_GROUP         },
147*2b949d04SAndroid Build Coastguard Worker     { "x",                ACTION_FIELD_X             },
148*2b949d04SAndroid Build Coastguard Worker     { "y",                ACTION_FIELD_Y             },
149*2b949d04SAndroid Build Coastguard Worker     { "accel",            ACTION_FIELD_ACCEL         },
150*2b949d04SAndroid Build Coastguard Worker     { "accelerate",       ACTION_FIELD_ACCEL         },
151*2b949d04SAndroid Build Coastguard Worker     { "repeat",           ACTION_FIELD_ACCEL         },
152*2b949d04SAndroid Build Coastguard Worker     { "button",           ACTION_FIELD_BUTTON        },
153*2b949d04SAndroid Build Coastguard Worker     { "value",            ACTION_FIELD_VALUE         },
154*2b949d04SAndroid Build Coastguard Worker     { "controls",         ACTION_FIELD_CONTROLS      },
155*2b949d04SAndroid Build Coastguard Worker     { "ctrls",            ACTION_FIELD_CONTROLS      },
156*2b949d04SAndroid Build Coastguard Worker     { "type",             ACTION_FIELD_TYPE          },
157*2b949d04SAndroid Build Coastguard Worker     { "count",            ACTION_FIELD_COUNT         },
158*2b949d04SAndroid Build Coastguard Worker     { "screen",           ACTION_FIELD_SCREEN        },
159*2b949d04SAndroid Build Coastguard Worker     { "same",             ACTION_FIELD_SAME          },
160*2b949d04SAndroid Build Coastguard Worker     { "sameServer",       ACTION_FIELD_SAME          },
161*2b949d04SAndroid Build Coastguard Worker     { "data",             ACTION_FIELD_DATA          },
162*2b949d04SAndroid Build Coastguard Worker     { "device",           ACTION_FIELD_DEVICE        },
163*2b949d04SAndroid Build Coastguard Worker     { "dev",              ACTION_FIELD_DEVICE        },
164*2b949d04SAndroid Build Coastguard Worker     { "key",              ACTION_FIELD_KEYCODE       },
165*2b949d04SAndroid Build Coastguard Worker     { "keycode",          ACTION_FIELD_KEYCODE       },
166*2b949d04SAndroid Build Coastguard Worker     { "kc",               ACTION_FIELD_KEYCODE       },
167*2b949d04SAndroid Build Coastguard Worker     { "clearmods",        ACTION_FIELD_MODS_TO_CLEAR },
168*2b949d04SAndroid Build Coastguard Worker     { "clearmodifiers",   ACTION_FIELD_MODS_TO_CLEAR },
169*2b949d04SAndroid Build Coastguard Worker     { NULL,               0                          }
170*2b949d04SAndroid Build Coastguard Worker };
171*2b949d04SAndroid Build Coastguard Worker 
172*2b949d04SAndroid Build Coastguard Worker static bool
stringToAction(const char * str,enum xkb_action_type * type_rtrn)173*2b949d04SAndroid Build Coastguard Worker stringToAction(const char *str, enum xkb_action_type *type_rtrn)
174*2b949d04SAndroid Build Coastguard Worker {
175*2b949d04SAndroid Build Coastguard Worker     return LookupString(actionTypeNames, str, type_rtrn);
176*2b949d04SAndroid Build Coastguard Worker }
177*2b949d04SAndroid Build Coastguard Worker 
178*2b949d04SAndroid Build Coastguard Worker static bool
stringToField(const char * str,enum action_field * field_rtrn)179*2b949d04SAndroid Build Coastguard Worker stringToField(const char *str, enum action_field *field_rtrn)
180*2b949d04SAndroid Build Coastguard Worker {
181*2b949d04SAndroid Build Coastguard Worker     return LookupString(fieldStrings, str, field_rtrn);
182*2b949d04SAndroid Build Coastguard Worker }
183*2b949d04SAndroid Build Coastguard Worker 
184*2b949d04SAndroid Build Coastguard Worker static const char *
fieldText(enum action_field field)185*2b949d04SAndroid Build Coastguard Worker fieldText(enum action_field field)
186*2b949d04SAndroid Build Coastguard Worker {
187*2b949d04SAndroid Build Coastguard Worker     return LookupValue(fieldStrings, field);
188*2b949d04SAndroid Build Coastguard Worker }
189*2b949d04SAndroid Build Coastguard Worker 
190*2b949d04SAndroid Build Coastguard Worker /***====================================================================***/
191*2b949d04SAndroid Build Coastguard Worker 
192*2b949d04SAndroid Build Coastguard Worker static inline bool
ReportMismatch(struct xkb_context * ctx,enum xkb_action_type action,enum action_field field,const char * type)193*2b949d04SAndroid Build Coastguard Worker ReportMismatch(struct xkb_context *ctx, enum xkb_action_type action,
194*2b949d04SAndroid Build Coastguard Worker                enum action_field field, const char *type)
195*2b949d04SAndroid Build Coastguard Worker {
196*2b949d04SAndroid Build Coastguard Worker     log_err(ctx,
197*2b949d04SAndroid Build Coastguard Worker             "Value of %s field must be of type %s; "
198*2b949d04SAndroid Build Coastguard Worker             "Action %s definition ignored\n",
199*2b949d04SAndroid Build Coastguard Worker             fieldText(field), type, ActionTypeText(action));
200*2b949d04SAndroid Build Coastguard Worker     return false;
201*2b949d04SAndroid Build Coastguard Worker }
202*2b949d04SAndroid Build Coastguard Worker 
203*2b949d04SAndroid Build Coastguard Worker static inline bool
ReportIllegal(struct xkb_context * ctx,enum xkb_action_type action,enum action_field field)204*2b949d04SAndroid Build Coastguard Worker ReportIllegal(struct xkb_context *ctx, enum xkb_action_type action,
205*2b949d04SAndroid Build Coastguard Worker               enum action_field field)
206*2b949d04SAndroid Build Coastguard Worker {
207*2b949d04SAndroid Build Coastguard Worker     log_err(ctx,
208*2b949d04SAndroid Build Coastguard Worker             "Field %s is not defined for an action of type %s; "
209*2b949d04SAndroid Build Coastguard Worker             "Action definition ignored\n",
210*2b949d04SAndroid Build Coastguard Worker             fieldText(field), ActionTypeText(action));
211*2b949d04SAndroid Build Coastguard Worker     return false;
212*2b949d04SAndroid Build Coastguard Worker }
213*2b949d04SAndroid Build Coastguard Worker 
214*2b949d04SAndroid Build Coastguard Worker static inline bool
ReportActionNotArray(struct xkb_context * ctx,enum xkb_action_type action,enum action_field field)215*2b949d04SAndroid Build Coastguard Worker ReportActionNotArray(struct xkb_context *ctx, enum xkb_action_type action,
216*2b949d04SAndroid Build Coastguard Worker                      enum action_field field)
217*2b949d04SAndroid Build Coastguard Worker {
218*2b949d04SAndroid Build Coastguard Worker     log_err(ctx,
219*2b949d04SAndroid Build Coastguard Worker             "The %s field in the %s action is not an array; "
220*2b949d04SAndroid Build Coastguard Worker             "Action definition ignored\n",
221*2b949d04SAndroid Build Coastguard Worker             fieldText(field), ActionTypeText(action));
222*2b949d04SAndroid Build Coastguard Worker     return false;
223*2b949d04SAndroid Build Coastguard Worker }
224*2b949d04SAndroid Build Coastguard Worker 
225*2b949d04SAndroid Build Coastguard Worker static bool
HandleNoAction(struct xkb_context * ctx,const struct xkb_mod_set * mods,union xkb_action * action,enum action_field field,const ExprDef * array_ndx,const ExprDef * value)226*2b949d04SAndroid Build Coastguard Worker HandleNoAction(struct xkb_context *ctx, const struct xkb_mod_set *mods,
227*2b949d04SAndroid Build Coastguard Worker                union xkb_action *action, enum action_field field,
228*2b949d04SAndroid Build Coastguard Worker                const ExprDef *array_ndx, const ExprDef *value)
229*2b949d04SAndroid Build Coastguard Worker 
230*2b949d04SAndroid Build Coastguard Worker {
231*2b949d04SAndroid Build Coastguard Worker     return true;
232*2b949d04SAndroid Build Coastguard Worker }
233*2b949d04SAndroid Build Coastguard Worker 
234*2b949d04SAndroid Build Coastguard Worker static bool
CheckBooleanFlag(struct xkb_context * ctx,enum xkb_action_type action,enum action_field field,enum xkb_action_flags flag,const ExprDef * array_ndx,const ExprDef * value,enum xkb_action_flags * flags_inout)235*2b949d04SAndroid Build Coastguard Worker CheckBooleanFlag(struct xkb_context *ctx, enum xkb_action_type action,
236*2b949d04SAndroid Build Coastguard Worker                  enum action_field field, enum xkb_action_flags flag,
237*2b949d04SAndroid Build Coastguard Worker                  const ExprDef *array_ndx, const ExprDef *value,
238*2b949d04SAndroid Build Coastguard Worker                  enum xkb_action_flags *flags_inout)
239*2b949d04SAndroid Build Coastguard Worker {
240*2b949d04SAndroid Build Coastguard Worker     bool set;
241*2b949d04SAndroid Build Coastguard Worker 
242*2b949d04SAndroid Build Coastguard Worker     if (array_ndx)
243*2b949d04SAndroid Build Coastguard Worker         return ReportActionNotArray(ctx, action, field);
244*2b949d04SAndroid Build Coastguard Worker 
245*2b949d04SAndroid Build Coastguard Worker     if (!ExprResolveBoolean(ctx, value, &set))
246*2b949d04SAndroid Build Coastguard Worker         return ReportMismatch(ctx, action, field, "boolean");
247*2b949d04SAndroid Build Coastguard Worker 
248*2b949d04SAndroid Build Coastguard Worker     if (set)
249*2b949d04SAndroid Build Coastguard Worker         *flags_inout |= flag;
250*2b949d04SAndroid Build Coastguard Worker     else
251*2b949d04SAndroid Build Coastguard Worker         *flags_inout &= ~flag;
252*2b949d04SAndroid Build Coastguard Worker 
253*2b949d04SAndroid Build Coastguard Worker     return true;
254*2b949d04SAndroid Build Coastguard Worker }
255*2b949d04SAndroid Build Coastguard Worker 
256*2b949d04SAndroid Build Coastguard Worker static bool
CheckModifierField(struct xkb_context * ctx,const struct xkb_mod_set * mods,enum xkb_action_type action,const ExprDef * array_ndx,const ExprDef * value,enum xkb_action_flags * flags_inout,xkb_mod_mask_t * mods_rtrn)257*2b949d04SAndroid Build Coastguard Worker CheckModifierField(struct xkb_context *ctx, const struct xkb_mod_set *mods,
258*2b949d04SAndroid Build Coastguard Worker                    enum xkb_action_type action, const ExprDef *array_ndx,
259*2b949d04SAndroid Build Coastguard Worker                    const ExprDef *value, enum xkb_action_flags *flags_inout,
260*2b949d04SAndroid Build Coastguard Worker                    xkb_mod_mask_t *mods_rtrn)
261*2b949d04SAndroid Build Coastguard Worker {
262*2b949d04SAndroid Build Coastguard Worker     if (array_ndx)
263*2b949d04SAndroid Build Coastguard Worker         return ReportActionNotArray(ctx, action, ACTION_FIELD_MODIFIERS);
264*2b949d04SAndroid Build Coastguard Worker 
265*2b949d04SAndroid Build Coastguard Worker     if (value->expr.op == EXPR_IDENT) {
266*2b949d04SAndroid Build Coastguard Worker         const char *valStr;
267*2b949d04SAndroid Build Coastguard Worker         valStr = xkb_atom_text(ctx, value->ident.ident);
268*2b949d04SAndroid Build Coastguard Worker         if (valStr && (istreq(valStr, "usemodmapmods") ||
269*2b949d04SAndroid Build Coastguard Worker                        istreq(valStr, "modmapmods"))) {
270*2b949d04SAndroid Build Coastguard Worker             *mods_rtrn = 0;
271*2b949d04SAndroid Build Coastguard Worker             *flags_inout |= ACTION_MODS_LOOKUP_MODMAP;
272*2b949d04SAndroid Build Coastguard Worker             return true;
273*2b949d04SAndroid Build Coastguard Worker         }
274*2b949d04SAndroid Build Coastguard Worker     }
275*2b949d04SAndroid Build Coastguard Worker 
276*2b949d04SAndroid Build Coastguard Worker     if (!ExprResolveModMask(ctx, value, MOD_BOTH, mods, mods_rtrn))
277*2b949d04SAndroid Build Coastguard Worker         return ReportMismatch(ctx, action,
278*2b949d04SAndroid Build Coastguard Worker                               ACTION_FIELD_MODIFIERS, "modifier mask");
279*2b949d04SAndroid Build Coastguard Worker 
280*2b949d04SAndroid Build Coastguard Worker     *flags_inout &= ~ACTION_MODS_LOOKUP_MODMAP;
281*2b949d04SAndroid Build Coastguard Worker     return true;
282*2b949d04SAndroid Build Coastguard Worker }
283*2b949d04SAndroid Build Coastguard Worker 
284*2b949d04SAndroid Build Coastguard Worker static const LookupEntry lockWhich[] = {
285*2b949d04SAndroid Build Coastguard Worker     { "both", 0 },
286*2b949d04SAndroid Build Coastguard Worker     { "lock", ACTION_LOCK_NO_UNLOCK },
287*2b949d04SAndroid Build Coastguard Worker     { "neither", (ACTION_LOCK_NO_LOCK | ACTION_LOCK_NO_UNLOCK) },
288*2b949d04SAndroid Build Coastguard Worker     { "unlock", ACTION_LOCK_NO_LOCK },
289*2b949d04SAndroid Build Coastguard Worker     { NULL, 0 }
290*2b949d04SAndroid Build Coastguard Worker };
291*2b949d04SAndroid Build Coastguard Worker 
292*2b949d04SAndroid Build Coastguard Worker static bool
CheckAffectField(struct xkb_context * ctx,enum xkb_action_type action,const ExprDef * array_ndx,const ExprDef * value,enum xkb_action_flags * flags_inout)293*2b949d04SAndroid Build Coastguard Worker CheckAffectField(struct xkb_context *ctx, enum xkb_action_type action,
294*2b949d04SAndroid Build Coastguard Worker                  const ExprDef *array_ndx, const ExprDef *value,
295*2b949d04SAndroid Build Coastguard Worker                  enum xkb_action_flags *flags_inout)
296*2b949d04SAndroid Build Coastguard Worker {
297*2b949d04SAndroid Build Coastguard Worker     enum xkb_action_flags flags;
298*2b949d04SAndroid Build Coastguard Worker 
299*2b949d04SAndroid Build Coastguard Worker     if (array_ndx)
300*2b949d04SAndroid Build Coastguard Worker         return ReportActionNotArray(ctx, action, ACTION_FIELD_AFFECT);
301*2b949d04SAndroid Build Coastguard Worker 
302*2b949d04SAndroid Build Coastguard Worker     if (!ExprResolveEnum(ctx, value, &flags, lockWhich))
303*2b949d04SAndroid Build Coastguard Worker         return ReportMismatch(ctx, action, ACTION_FIELD_AFFECT,
304*2b949d04SAndroid Build Coastguard Worker                               "lock, unlock, both, neither");
305*2b949d04SAndroid Build Coastguard Worker 
306*2b949d04SAndroid Build Coastguard Worker     *flags_inout &= ~(ACTION_LOCK_NO_LOCK | ACTION_LOCK_NO_UNLOCK);
307*2b949d04SAndroid Build Coastguard Worker     *flags_inout |= flags;
308*2b949d04SAndroid Build Coastguard Worker     return true;
309*2b949d04SAndroid Build Coastguard Worker }
310*2b949d04SAndroid Build Coastguard Worker 
311*2b949d04SAndroid Build Coastguard Worker static bool
HandleSetLatchLockMods(struct xkb_context * ctx,const struct xkb_mod_set * mods,union xkb_action * action,enum action_field field,const ExprDef * array_ndx,const ExprDef * value)312*2b949d04SAndroid Build Coastguard Worker HandleSetLatchLockMods(struct xkb_context *ctx, const struct xkb_mod_set *mods,
313*2b949d04SAndroid Build Coastguard Worker                        union xkb_action *action, enum action_field field,
314*2b949d04SAndroid Build Coastguard Worker                        const ExprDef *array_ndx, const ExprDef *value)
315*2b949d04SAndroid Build Coastguard Worker {
316*2b949d04SAndroid Build Coastguard Worker     struct xkb_mod_action *act = &action->mods;
317*2b949d04SAndroid Build Coastguard Worker     const enum xkb_action_type type = action->type;
318*2b949d04SAndroid Build Coastguard Worker 
319*2b949d04SAndroid Build Coastguard Worker     if (field == ACTION_FIELD_MODIFIERS)
320*2b949d04SAndroid Build Coastguard Worker         return CheckModifierField(ctx, mods, action->type, array_ndx, value,
321*2b949d04SAndroid Build Coastguard Worker                                   &act->flags, &act->mods.mods);
322*2b949d04SAndroid Build Coastguard Worker     if ((type == ACTION_TYPE_MOD_SET || type == ACTION_TYPE_MOD_LATCH) &&
323*2b949d04SAndroid Build Coastguard Worker         field == ACTION_FIELD_CLEAR_LOCKS)
324*2b949d04SAndroid Build Coastguard Worker         return CheckBooleanFlag(ctx, action->type, field,
325*2b949d04SAndroid Build Coastguard Worker                                 ACTION_LOCK_CLEAR, array_ndx, value,
326*2b949d04SAndroid Build Coastguard Worker                                 &act->flags);
327*2b949d04SAndroid Build Coastguard Worker     if (type == ACTION_TYPE_MOD_LATCH &&
328*2b949d04SAndroid Build Coastguard Worker         field == ACTION_FIELD_LATCH_TO_LOCK)
329*2b949d04SAndroid Build Coastguard Worker         return CheckBooleanFlag(ctx, action->type, field,
330*2b949d04SAndroid Build Coastguard Worker                                 ACTION_LATCH_TO_LOCK, array_ndx, value,
331*2b949d04SAndroid Build Coastguard Worker                                 &act->flags);
332*2b949d04SAndroid Build Coastguard Worker     if (type == ACTION_TYPE_MOD_LOCK &&
333*2b949d04SAndroid Build Coastguard Worker         field == ACTION_FIELD_AFFECT)
334*2b949d04SAndroid Build Coastguard Worker         return CheckAffectField(ctx, action->type, array_ndx, value,
335*2b949d04SAndroid Build Coastguard Worker                                 &act->flags);
336*2b949d04SAndroid Build Coastguard Worker 
337*2b949d04SAndroid Build Coastguard Worker     return ReportIllegal(ctx, action->type, field);
338*2b949d04SAndroid Build Coastguard Worker }
339*2b949d04SAndroid Build Coastguard Worker 
340*2b949d04SAndroid Build Coastguard Worker static bool
CheckGroupField(struct xkb_context * ctx,enum xkb_action_type action,const ExprDef * array_ndx,const ExprDef * value,enum xkb_action_flags * flags_inout,int32_t * group_rtrn)341*2b949d04SAndroid Build Coastguard Worker CheckGroupField(struct xkb_context *ctx, enum xkb_action_type action,
342*2b949d04SAndroid Build Coastguard Worker                 const ExprDef *array_ndx, const ExprDef *value,
343*2b949d04SAndroid Build Coastguard Worker                 enum xkb_action_flags *flags_inout, int32_t *group_rtrn)
344*2b949d04SAndroid Build Coastguard Worker {
345*2b949d04SAndroid Build Coastguard Worker     const ExprDef *spec;
346*2b949d04SAndroid Build Coastguard Worker     xkb_layout_index_t idx;
347*2b949d04SAndroid Build Coastguard Worker     enum xkb_action_flags flags = *flags_inout;
348*2b949d04SAndroid Build Coastguard Worker 
349*2b949d04SAndroid Build Coastguard Worker     if (array_ndx)
350*2b949d04SAndroid Build Coastguard Worker         return ReportActionNotArray(ctx, action, ACTION_FIELD_GROUP);
351*2b949d04SAndroid Build Coastguard Worker 
352*2b949d04SAndroid Build Coastguard Worker     if (value->expr.op == EXPR_NEGATE || value->expr.op == EXPR_UNARY_PLUS) {
353*2b949d04SAndroid Build Coastguard Worker         flags &= ~ACTION_ABSOLUTE_SWITCH;
354*2b949d04SAndroid Build Coastguard Worker         spec = value->unary.child;
355*2b949d04SAndroid Build Coastguard Worker     }
356*2b949d04SAndroid Build Coastguard Worker     else {
357*2b949d04SAndroid Build Coastguard Worker         flags |= ACTION_ABSOLUTE_SWITCH;
358*2b949d04SAndroid Build Coastguard Worker         spec = value;
359*2b949d04SAndroid Build Coastguard Worker     }
360*2b949d04SAndroid Build Coastguard Worker 
361*2b949d04SAndroid Build Coastguard Worker     if (!ExprResolveGroup(ctx, spec, &idx))
362*2b949d04SAndroid Build Coastguard Worker         return ReportMismatch(ctx, action, ACTION_FIELD_GROUP,
363*2b949d04SAndroid Build Coastguard Worker                               "integer (range 1..8)");
364*2b949d04SAndroid Build Coastguard Worker 
365*2b949d04SAndroid Build Coastguard Worker     /* +n, -n are relative, n is absolute. */
366*2b949d04SAndroid Build Coastguard Worker     if (value->expr.op == EXPR_NEGATE || value->expr.op == EXPR_UNARY_PLUS) {
367*2b949d04SAndroid Build Coastguard Worker         *group_rtrn = (int32_t) idx;
368*2b949d04SAndroid Build Coastguard Worker         if (value->expr.op == EXPR_NEGATE)
369*2b949d04SAndroid Build Coastguard Worker             *group_rtrn = -*group_rtrn;
370*2b949d04SAndroid Build Coastguard Worker     }
371*2b949d04SAndroid Build Coastguard Worker     else {
372*2b949d04SAndroid Build Coastguard Worker         *group_rtrn = (int32_t) (idx - 1);
373*2b949d04SAndroid Build Coastguard Worker     }
374*2b949d04SAndroid Build Coastguard Worker     *flags_inout = flags;
375*2b949d04SAndroid Build Coastguard Worker     return true;
376*2b949d04SAndroid Build Coastguard Worker }
377*2b949d04SAndroid Build Coastguard Worker 
378*2b949d04SAndroid Build Coastguard Worker static bool
HandleSetLatchLockGroup(struct xkb_context * ctx,const struct xkb_mod_set * mods,union xkb_action * action,enum action_field field,const ExprDef * array_ndx,const ExprDef * value)379*2b949d04SAndroid Build Coastguard Worker HandleSetLatchLockGroup(struct xkb_context *ctx, const struct xkb_mod_set *mods,
380*2b949d04SAndroid Build Coastguard Worker                         union xkb_action *action, enum action_field field,
381*2b949d04SAndroid Build Coastguard Worker                         const ExprDef *array_ndx, const ExprDef *value)
382*2b949d04SAndroid Build Coastguard Worker {
383*2b949d04SAndroid Build Coastguard Worker     struct xkb_group_action *act = &action->group;
384*2b949d04SAndroid Build Coastguard Worker     const enum xkb_action_type type = action->type;
385*2b949d04SAndroid Build Coastguard Worker 
386*2b949d04SAndroid Build Coastguard Worker     if (field == ACTION_FIELD_GROUP)
387*2b949d04SAndroid Build Coastguard Worker         return CheckGroupField(ctx, action->type, array_ndx, value,
388*2b949d04SAndroid Build Coastguard Worker                                &act->flags, &act->group);
389*2b949d04SAndroid Build Coastguard Worker     if ((type == ACTION_TYPE_GROUP_SET || type == ACTION_TYPE_GROUP_LATCH) &&
390*2b949d04SAndroid Build Coastguard Worker         field == ACTION_FIELD_CLEAR_LOCKS)
391*2b949d04SAndroid Build Coastguard Worker         return CheckBooleanFlag(ctx, action->type, field,
392*2b949d04SAndroid Build Coastguard Worker                                 ACTION_LOCK_CLEAR, array_ndx, value,
393*2b949d04SAndroid Build Coastguard Worker                                 &act->flags);
394*2b949d04SAndroid Build Coastguard Worker     if (type == ACTION_TYPE_GROUP_LATCH &&
395*2b949d04SAndroid Build Coastguard Worker         field == ACTION_FIELD_LATCH_TO_LOCK)
396*2b949d04SAndroid Build Coastguard Worker         return CheckBooleanFlag(ctx, action->type, field,
397*2b949d04SAndroid Build Coastguard Worker                                 ACTION_LATCH_TO_LOCK, array_ndx, value,
398*2b949d04SAndroid Build Coastguard Worker                                 &act->flags);
399*2b949d04SAndroid Build Coastguard Worker 
400*2b949d04SAndroid Build Coastguard Worker     return ReportIllegal(ctx, action->type, field);
401*2b949d04SAndroid Build Coastguard Worker }
402*2b949d04SAndroid Build Coastguard Worker 
403*2b949d04SAndroid Build Coastguard Worker static bool
HandleMovePtr(struct xkb_context * ctx,const struct xkb_mod_set * mods,union xkb_action * action,enum action_field field,const ExprDef * array_ndx,const ExprDef * value)404*2b949d04SAndroid Build Coastguard Worker HandleMovePtr(struct xkb_context *ctx, const struct xkb_mod_set *mods,
405*2b949d04SAndroid Build Coastguard Worker               union xkb_action *action, enum action_field field,
406*2b949d04SAndroid Build Coastguard Worker               const ExprDef *array_ndx, const ExprDef *value)
407*2b949d04SAndroid Build Coastguard Worker {
408*2b949d04SAndroid Build Coastguard Worker     struct xkb_pointer_action *act = &action->ptr;
409*2b949d04SAndroid Build Coastguard Worker 
410*2b949d04SAndroid Build Coastguard Worker     if (field == ACTION_FIELD_X || field == ACTION_FIELD_Y) {
411*2b949d04SAndroid Build Coastguard Worker         int val;
412*2b949d04SAndroid Build Coastguard Worker         const bool absolute = (value->expr.op != EXPR_NEGATE &&
413*2b949d04SAndroid Build Coastguard Worker                                value->expr.op != EXPR_UNARY_PLUS);
414*2b949d04SAndroid Build Coastguard Worker 
415*2b949d04SAndroid Build Coastguard Worker         if (array_ndx)
416*2b949d04SAndroid Build Coastguard Worker             return ReportActionNotArray(ctx, action->type, field);
417*2b949d04SAndroid Build Coastguard Worker 
418*2b949d04SAndroid Build Coastguard Worker         if (!ExprResolveInteger(ctx, value, &val))
419*2b949d04SAndroid Build Coastguard Worker             return ReportMismatch(ctx, action->type, field, "integer");
420*2b949d04SAndroid Build Coastguard Worker 
421*2b949d04SAndroid Build Coastguard Worker         if (val < INT16_MIN || val > INT16_MAX) {
422*2b949d04SAndroid Build Coastguard Worker             log_err(ctx,
423*2b949d04SAndroid Build Coastguard Worker                     "The %s field in the %s action must be in range %d..%d; "
424*2b949d04SAndroid Build Coastguard Worker                     "Action definition ignored\n",
425*2b949d04SAndroid Build Coastguard Worker                     fieldText(field), ActionTypeText(action->type),
426*2b949d04SAndroid Build Coastguard Worker                     INT16_MIN, INT16_MAX);
427*2b949d04SAndroid Build Coastguard Worker             return false;
428*2b949d04SAndroid Build Coastguard Worker         }
429*2b949d04SAndroid Build Coastguard Worker 
430*2b949d04SAndroid Build Coastguard Worker         if (field == ACTION_FIELD_X) {
431*2b949d04SAndroid Build Coastguard Worker             if (absolute)
432*2b949d04SAndroid Build Coastguard Worker                 act->flags |= ACTION_ABSOLUTE_X;
433*2b949d04SAndroid Build Coastguard Worker             act->x = (int16_t) val;
434*2b949d04SAndroid Build Coastguard Worker         }
435*2b949d04SAndroid Build Coastguard Worker         else {
436*2b949d04SAndroid Build Coastguard Worker             if (absolute)
437*2b949d04SAndroid Build Coastguard Worker                 act->flags |= ACTION_ABSOLUTE_Y;
438*2b949d04SAndroid Build Coastguard Worker             act->y = (int16_t) val;
439*2b949d04SAndroid Build Coastguard Worker         }
440*2b949d04SAndroid Build Coastguard Worker 
441*2b949d04SAndroid Build Coastguard Worker         return true;
442*2b949d04SAndroid Build Coastguard Worker     }
443*2b949d04SAndroid Build Coastguard Worker     else if (field == ACTION_FIELD_ACCEL) {
444*2b949d04SAndroid Build Coastguard Worker         return CheckBooleanFlag(ctx, action->type, field,
445*2b949d04SAndroid Build Coastguard Worker                                 ACTION_ACCEL, array_ndx, value, &act->flags);
446*2b949d04SAndroid Build Coastguard Worker     }
447*2b949d04SAndroid Build Coastguard Worker 
448*2b949d04SAndroid Build Coastguard Worker     return ReportIllegal(ctx, action->type, field);
449*2b949d04SAndroid Build Coastguard Worker }
450*2b949d04SAndroid Build Coastguard Worker 
451*2b949d04SAndroid Build Coastguard Worker static bool
HandlePtrBtn(struct xkb_context * ctx,const struct xkb_mod_set * mods,union xkb_action * action,enum action_field field,const ExprDef * array_ndx,const ExprDef * value)452*2b949d04SAndroid Build Coastguard Worker HandlePtrBtn(struct xkb_context *ctx, const struct xkb_mod_set *mods,
453*2b949d04SAndroid Build Coastguard Worker              union xkb_action *action, enum action_field field,
454*2b949d04SAndroid Build Coastguard Worker              const ExprDef *array_ndx, const ExprDef *value)
455*2b949d04SAndroid Build Coastguard Worker {
456*2b949d04SAndroid Build Coastguard Worker     struct xkb_pointer_button_action *act = &action->btn;
457*2b949d04SAndroid Build Coastguard Worker 
458*2b949d04SAndroid Build Coastguard Worker     if (field == ACTION_FIELD_BUTTON) {
459*2b949d04SAndroid Build Coastguard Worker         int btn;
460*2b949d04SAndroid Build Coastguard Worker 
461*2b949d04SAndroid Build Coastguard Worker         if (array_ndx)
462*2b949d04SAndroid Build Coastguard Worker             return ReportActionNotArray(ctx, action->type, field);
463*2b949d04SAndroid Build Coastguard Worker 
464*2b949d04SAndroid Build Coastguard Worker         if (!ExprResolveButton(ctx, value, &btn))
465*2b949d04SAndroid Build Coastguard Worker             return ReportMismatch(ctx, action->type, field,
466*2b949d04SAndroid Build Coastguard Worker                                   "integer (range 1..5)");
467*2b949d04SAndroid Build Coastguard Worker 
468*2b949d04SAndroid Build Coastguard Worker         if (btn < 0 || btn > 5) {
469*2b949d04SAndroid Build Coastguard Worker             log_err(ctx,
470*2b949d04SAndroid Build Coastguard Worker                     "Button must specify default or be in the range 1..5; "
471*2b949d04SAndroid Build Coastguard Worker                     "Illegal button value %d ignored\n", btn);
472*2b949d04SAndroid Build Coastguard Worker             return false;
473*2b949d04SAndroid Build Coastguard Worker         }
474*2b949d04SAndroid Build Coastguard Worker 
475*2b949d04SAndroid Build Coastguard Worker         act->button = btn;
476*2b949d04SAndroid Build Coastguard Worker         return true;
477*2b949d04SAndroid Build Coastguard Worker     }
478*2b949d04SAndroid Build Coastguard Worker     else if (action->type == ACTION_TYPE_PTR_LOCK &&
479*2b949d04SAndroid Build Coastguard Worker              field == ACTION_FIELD_AFFECT) {
480*2b949d04SAndroid Build Coastguard Worker         return CheckAffectField(ctx, action->type, array_ndx, value,
481*2b949d04SAndroid Build Coastguard Worker                                 &act->flags);
482*2b949d04SAndroid Build Coastguard Worker     }
483*2b949d04SAndroid Build Coastguard Worker     else if (field == ACTION_FIELD_COUNT) {
484*2b949d04SAndroid Build Coastguard Worker         int val;
485*2b949d04SAndroid Build Coastguard Worker 
486*2b949d04SAndroid Build Coastguard Worker         if (array_ndx)
487*2b949d04SAndroid Build Coastguard Worker             return ReportActionNotArray(ctx, action->type, field);
488*2b949d04SAndroid Build Coastguard Worker 
489*2b949d04SAndroid Build Coastguard Worker         if (!ExprResolveInteger(ctx, value, &val))
490*2b949d04SAndroid Build Coastguard Worker             return ReportMismatch(ctx, action->type, field, "integer");
491*2b949d04SAndroid Build Coastguard Worker 
492*2b949d04SAndroid Build Coastguard Worker         if (val < 0 || val > 255) {
493*2b949d04SAndroid Build Coastguard Worker             log_err(ctx,
494*2b949d04SAndroid Build Coastguard Worker                     "The count field must have a value in the range 0..255; "
495*2b949d04SAndroid Build Coastguard Worker                     "Illegal count %d ignored\n", val);
496*2b949d04SAndroid Build Coastguard Worker             return false;
497*2b949d04SAndroid Build Coastguard Worker         }
498*2b949d04SAndroid Build Coastguard Worker 
499*2b949d04SAndroid Build Coastguard Worker         act->count = (uint8_t) val;
500*2b949d04SAndroid Build Coastguard Worker         return true;
501*2b949d04SAndroid Build Coastguard Worker     }
502*2b949d04SAndroid Build Coastguard Worker 
503*2b949d04SAndroid Build Coastguard Worker     return ReportIllegal(ctx, action->type, field);
504*2b949d04SAndroid Build Coastguard Worker }
505*2b949d04SAndroid Build Coastguard Worker 
506*2b949d04SAndroid Build Coastguard Worker static const LookupEntry ptrDflts[] = {
507*2b949d04SAndroid Build Coastguard Worker     { "dfltbtn", 1 },
508*2b949d04SAndroid Build Coastguard Worker     { "defaultbutton", 1 },
509*2b949d04SAndroid Build Coastguard Worker     { "button", 1 },
510*2b949d04SAndroid Build Coastguard Worker     { NULL, 0 }
511*2b949d04SAndroid Build Coastguard Worker };
512*2b949d04SAndroid Build Coastguard Worker 
513*2b949d04SAndroid Build Coastguard Worker static bool
HandleSetPtrDflt(struct xkb_context * ctx,const struct xkb_mod_set * mods,union xkb_action * action,enum action_field field,const ExprDef * array_ndx,const ExprDef * value)514*2b949d04SAndroid Build Coastguard Worker HandleSetPtrDflt(struct xkb_context *ctx, const struct xkb_mod_set *mods,
515*2b949d04SAndroid Build Coastguard Worker                  union xkb_action *action, enum action_field field,
516*2b949d04SAndroid Build Coastguard Worker                  const ExprDef *array_ndx, const ExprDef *value)
517*2b949d04SAndroid Build Coastguard Worker {
518*2b949d04SAndroid Build Coastguard Worker     struct xkb_pointer_default_action *act = &action->dflt;
519*2b949d04SAndroid Build Coastguard Worker 
520*2b949d04SAndroid Build Coastguard Worker     if (field == ACTION_FIELD_AFFECT) {
521*2b949d04SAndroid Build Coastguard Worker         unsigned int val;
522*2b949d04SAndroid Build Coastguard Worker 
523*2b949d04SAndroid Build Coastguard Worker         if (array_ndx)
524*2b949d04SAndroid Build Coastguard Worker             return ReportActionNotArray(ctx, action->type, field);
525*2b949d04SAndroid Build Coastguard Worker 
526*2b949d04SAndroid Build Coastguard Worker         if (!ExprResolveEnum(ctx, value, &val, ptrDflts))
527*2b949d04SAndroid Build Coastguard Worker             return ReportMismatch(ctx, action->type, field,
528*2b949d04SAndroid Build Coastguard Worker                                   "pointer component");
529*2b949d04SAndroid Build Coastguard Worker         return true;
530*2b949d04SAndroid Build Coastguard Worker     }
531*2b949d04SAndroid Build Coastguard Worker     else if (field == ACTION_FIELD_BUTTON || field == ACTION_FIELD_VALUE) {
532*2b949d04SAndroid Build Coastguard Worker         const ExprDef *button;
533*2b949d04SAndroid Build Coastguard Worker         int btn;
534*2b949d04SAndroid Build Coastguard Worker 
535*2b949d04SAndroid Build Coastguard Worker         if (array_ndx)
536*2b949d04SAndroid Build Coastguard Worker             return ReportActionNotArray(ctx, action->type, field);
537*2b949d04SAndroid Build Coastguard Worker 
538*2b949d04SAndroid Build Coastguard Worker         if (value->expr.op == EXPR_NEGATE ||
539*2b949d04SAndroid Build Coastguard Worker             value->expr.op == EXPR_UNARY_PLUS) {
540*2b949d04SAndroid Build Coastguard Worker             act->flags &= ~ACTION_ABSOLUTE_SWITCH;
541*2b949d04SAndroid Build Coastguard Worker             button = value->unary.child;
542*2b949d04SAndroid Build Coastguard Worker         }
543*2b949d04SAndroid Build Coastguard Worker         else {
544*2b949d04SAndroid Build Coastguard Worker             act->flags |= ACTION_ABSOLUTE_SWITCH;
545*2b949d04SAndroid Build Coastguard Worker             button = value;
546*2b949d04SAndroid Build Coastguard Worker         }
547*2b949d04SAndroid Build Coastguard Worker 
548*2b949d04SAndroid Build Coastguard Worker         if (!ExprResolveButton(ctx, button, &btn))
549*2b949d04SAndroid Build Coastguard Worker             return ReportMismatch(ctx, action->type, field,
550*2b949d04SAndroid Build Coastguard Worker                                   "integer (range 1..5)");
551*2b949d04SAndroid Build Coastguard Worker 
552*2b949d04SAndroid Build Coastguard Worker         if (btn < 0 || btn > 5) {
553*2b949d04SAndroid Build Coastguard Worker             log_err(ctx,
554*2b949d04SAndroid Build Coastguard Worker                     "New default button value must be in the range 1..5; "
555*2b949d04SAndroid Build Coastguard Worker                     "Illegal default button value %d ignored\n", btn);
556*2b949d04SAndroid Build Coastguard Worker             return false;
557*2b949d04SAndroid Build Coastguard Worker         }
558*2b949d04SAndroid Build Coastguard Worker         if (btn == 0) {
559*2b949d04SAndroid Build Coastguard Worker             log_err(ctx,
560*2b949d04SAndroid Build Coastguard Worker                     "Cannot set default pointer button to \"default\"; "
561*2b949d04SAndroid Build Coastguard Worker                     "Illegal default button setting ignored\n");
562*2b949d04SAndroid Build Coastguard Worker             return false;
563*2b949d04SAndroid Build Coastguard Worker         }
564*2b949d04SAndroid Build Coastguard Worker 
565*2b949d04SAndroid Build Coastguard Worker         act->value = (value->expr.op == EXPR_NEGATE ? -btn: btn);
566*2b949d04SAndroid Build Coastguard Worker         return true;
567*2b949d04SAndroid Build Coastguard Worker     }
568*2b949d04SAndroid Build Coastguard Worker 
569*2b949d04SAndroid Build Coastguard Worker     return ReportIllegal(ctx, action->type, field);
570*2b949d04SAndroid Build Coastguard Worker }
571*2b949d04SAndroid Build Coastguard Worker 
572*2b949d04SAndroid Build Coastguard Worker static bool
HandleSwitchScreen(struct xkb_context * ctx,const struct xkb_mod_set * mods,union xkb_action * action,enum action_field field,const ExprDef * array_ndx,const ExprDef * value)573*2b949d04SAndroid Build Coastguard Worker HandleSwitchScreen(struct xkb_context *ctx, const struct xkb_mod_set *mods,
574*2b949d04SAndroid Build Coastguard Worker                    union xkb_action *action, enum action_field field,
575*2b949d04SAndroid Build Coastguard Worker                    const ExprDef *array_ndx, const ExprDef *value)
576*2b949d04SAndroid Build Coastguard Worker {
577*2b949d04SAndroid Build Coastguard Worker     struct xkb_switch_screen_action *act = &action->screen;
578*2b949d04SAndroid Build Coastguard Worker 
579*2b949d04SAndroid Build Coastguard Worker     if (field == ACTION_FIELD_SCREEN) {
580*2b949d04SAndroid Build Coastguard Worker         const ExprDef *scrn;
581*2b949d04SAndroid Build Coastguard Worker         int val;
582*2b949d04SAndroid Build Coastguard Worker 
583*2b949d04SAndroid Build Coastguard Worker         if (array_ndx)
584*2b949d04SAndroid Build Coastguard Worker             return ReportActionNotArray(ctx, action->type, field);
585*2b949d04SAndroid Build Coastguard Worker 
586*2b949d04SAndroid Build Coastguard Worker         if (value->expr.op == EXPR_NEGATE ||
587*2b949d04SAndroid Build Coastguard Worker             value->expr.op == EXPR_UNARY_PLUS) {
588*2b949d04SAndroid Build Coastguard Worker             act->flags &= ~ACTION_ABSOLUTE_SWITCH;
589*2b949d04SAndroid Build Coastguard Worker             scrn = value->unary.child;
590*2b949d04SAndroid Build Coastguard Worker         }
591*2b949d04SAndroid Build Coastguard Worker         else {
592*2b949d04SAndroid Build Coastguard Worker             act->flags |= ACTION_ABSOLUTE_SWITCH;
593*2b949d04SAndroid Build Coastguard Worker             scrn = value;
594*2b949d04SAndroid Build Coastguard Worker         }
595*2b949d04SAndroid Build Coastguard Worker 
596*2b949d04SAndroid Build Coastguard Worker         if (!ExprResolveInteger(ctx, scrn, &val))
597*2b949d04SAndroid Build Coastguard Worker             return ReportMismatch(ctx, action->type, field,
598*2b949d04SAndroid Build Coastguard Worker                                   "integer (0..255)");
599*2b949d04SAndroid Build Coastguard Worker 
600*2b949d04SAndroid Build Coastguard Worker         if (val < 0 || val > 255) {
601*2b949d04SAndroid Build Coastguard Worker             log_err(ctx,
602*2b949d04SAndroid Build Coastguard Worker                     "Screen index must be in the range 1..255; "
603*2b949d04SAndroid Build Coastguard Worker                     "Illegal screen value %d ignored\n", val);
604*2b949d04SAndroid Build Coastguard Worker             return false;
605*2b949d04SAndroid Build Coastguard Worker         }
606*2b949d04SAndroid Build Coastguard Worker 
607*2b949d04SAndroid Build Coastguard Worker         act->screen = (value->expr.op == EXPR_NEGATE ? -val : val);
608*2b949d04SAndroid Build Coastguard Worker         return true;
609*2b949d04SAndroid Build Coastguard Worker     }
610*2b949d04SAndroid Build Coastguard Worker     else if (field == ACTION_FIELD_SAME) {
611*2b949d04SAndroid Build Coastguard Worker         return CheckBooleanFlag(ctx, action->type, field,
612*2b949d04SAndroid Build Coastguard Worker                                 ACTION_SAME_SCREEN, array_ndx, value,
613*2b949d04SAndroid Build Coastguard Worker                                 &act->flags);
614*2b949d04SAndroid Build Coastguard Worker     }
615*2b949d04SAndroid Build Coastguard Worker 
616*2b949d04SAndroid Build Coastguard Worker     return ReportIllegal(ctx, action->type, field);
617*2b949d04SAndroid Build Coastguard Worker }
618*2b949d04SAndroid Build Coastguard Worker 
619*2b949d04SAndroid Build Coastguard Worker static bool
HandleSetLockControls(struct xkb_context * ctx,const struct xkb_mod_set * mods,union xkb_action * action,enum action_field field,const ExprDef * array_ndx,const ExprDef * value)620*2b949d04SAndroid Build Coastguard Worker HandleSetLockControls(struct xkb_context *ctx, const struct xkb_mod_set *mods,
621*2b949d04SAndroid Build Coastguard Worker                       union xkb_action *action, enum action_field field,
622*2b949d04SAndroid Build Coastguard Worker                       const ExprDef *array_ndx, const ExprDef *value)
623*2b949d04SAndroid Build Coastguard Worker {
624*2b949d04SAndroid Build Coastguard Worker     struct xkb_controls_action *act = &action->ctrls;
625*2b949d04SAndroid Build Coastguard Worker 
626*2b949d04SAndroid Build Coastguard Worker     if (field == ACTION_FIELD_CONTROLS) {
627*2b949d04SAndroid Build Coastguard Worker         enum xkb_action_controls mask;
628*2b949d04SAndroid Build Coastguard Worker 
629*2b949d04SAndroid Build Coastguard Worker         if (array_ndx)
630*2b949d04SAndroid Build Coastguard Worker             return ReportActionNotArray(ctx, action->type, field);
631*2b949d04SAndroid Build Coastguard Worker 
632*2b949d04SAndroid Build Coastguard Worker         if (!ExprResolveMask(ctx, value, &mask, ctrlMaskNames))
633*2b949d04SAndroid Build Coastguard Worker             return ReportMismatch(ctx, action->type, field,
634*2b949d04SAndroid Build Coastguard Worker                                   "controls mask");
635*2b949d04SAndroid Build Coastguard Worker 
636*2b949d04SAndroid Build Coastguard Worker         act->ctrls = mask;
637*2b949d04SAndroid Build Coastguard Worker         return true;
638*2b949d04SAndroid Build Coastguard Worker     }
639*2b949d04SAndroid Build Coastguard Worker     else if (field == ACTION_FIELD_AFFECT) {
640*2b949d04SAndroid Build Coastguard Worker         return CheckAffectField(ctx, action->type, array_ndx, value,
641*2b949d04SAndroid Build Coastguard Worker                                 &act->flags);
642*2b949d04SAndroid Build Coastguard Worker     }
643*2b949d04SAndroid Build Coastguard Worker 
644*2b949d04SAndroid Build Coastguard Worker     return ReportIllegal(ctx, action->type, field);
645*2b949d04SAndroid Build Coastguard Worker }
646*2b949d04SAndroid Build Coastguard Worker 
647*2b949d04SAndroid Build Coastguard Worker static bool
HandlePrivate(struct xkb_context * ctx,const struct xkb_mod_set * mods,union xkb_action * action,enum action_field field,const ExprDef * array_ndx,const ExprDef * value)648*2b949d04SAndroid Build Coastguard Worker HandlePrivate(struct xkb_context *ctx, const struct xkb_mod_set *mods,
649*2b949d04SAndroid Build Coastguard Worker               union xkb_action *action, enum action_field field,
650*2b949d04SAndroid Build Coastguard Worker               const ExprDef *array_ndx, const ExprDef *value)
651*2b949d04SAndroid Build Coastguard Worker {
652*2b949d04SAndroid Build Coastguard Worker     struct xkb_private_action *act = &action->priv;
653*2b949d04SAndroid Build Coastguard Worker 
654*2b949d04SAndroid Build Coastguard Worker     if (field == ACTION_FIELD_TYPE) {
655*2b949d04SAndroid Build Coastguard Worker         int type;
656*2b949d04SAndroid Build Coastguard Worker 
657*2b949d04SAndroid Build Coastguard Worker         if (array_ndx)
658*2b949d04SAndroid Build Coastguard Worker             return ReportActionNotArray(ctx, action->type, field);
659*2b949d04SAndroid Build Coastguard Worker 
660*2b949d04SAndroid Build Coastguard Worker         if (!ExprResolveInteger(ctx, value, &type))
661*2b949d04SAndroid Build Coastguard Worker             return ReportMismatch(ctx, ACTION_TYPE_PRIVATE, field, "integer");
662*2b949d04SAndroid Build Coastguard Worker 
663*2b949d04SAndroid Build Coastguard Worker         if (type < 0 || type > 255) {
664*2b949d04SAndroid Build Coastguard Worker             log_err(ctx,
665*2b949d04SAndroid Build Coastguard Worker                     "Private action type must be in the range 0..255; "
666*2b949d04SAndroid Build Coastguard Worker                     "Illegal type %d ignored\n", type);
667*2b949d04SAndroid Build Coastguard Worker             return false;
668*2b949d04SAndroid Build Coastguard Worker         }
669*2b949d04SAndroid Build Coastguard Worker 
670*2b949d04SAndroid Build Coastguard Worker         /*
671*2b949d04SAndroid Build Coastguard Worker          * It's possible for someone to write something like this:
672*2b949d04SAndroid Build Coastguard Worker          *      actions = [ Private(type=3,data[0]=1,data[1]=3,data[2]=3) ]
673*2b949d04SAndroid Build Coastguard Worker          * where the type refers to some existing action type, e.g. LockMods.
674*2b949d04SAndroid Build Coastguard Worker          * This assumes that this action's struct is laid out in memory
675*2b949d04SAndroid Build Coastguard Worker          * exactly as described in the XKB specification and libraries.
676*2b949d04SAndroid Build Coastguard Worker          * We, however, have changed these structs in various ways, so this
677*2b949d04SAndroid Build Coastguard Worker          * assumption is no longer true. Since this is a lousy "feature", we
678*2b949d04SAndroid Build Coastguard Worker          * make actions like these no-ops for now.
679*2b949d04SAndroid Build Coastguard Worker          */
680*2b949d04SAndroid Build Coastguard Worker         if (type < ACTION_TYPE_PRIVATE) {
681*2b949d04SAndroid Build Coastguard Worker             log_info(ctx,
682*2b949d04SAndroid Build Coastguard Worker                      "Private actions of type %s are not supported; Ignored\n",
683*2b949d04SAndroid Build Coastguard Worker                      ActionTypeText(type));
684*2b949d04SAndroid Build Coastguard Worker             act->type = ACTION_TYPE_NONE;
685*2b949d04SAndroid Build Coastguard Worker         }
686*2b949d04SAndroid Build Coastguard Worker         else {
687*2b949d04SAndroid Build Coastguard Worker             act->type = (enum xkb_action_type) type;
688*2b949d04SAndroid Build Coastguard Worker         }
689*2b949d04SAndroid Build Coastguard Worker 
690*2b949d04SAndroid Build Coastguard Worker         return true;
691*2b949d04SAndroid Build Coastguard Worker     }
692*2b949d04SAndroid Build Coastguard Worker     else if (field == ACTION_FIELD_DATA) {
693*2b949d04SAndroid Build Coastguard Worker         if (array_ndx == NULL) {
694*2b949d04SAndroid Build Coastguard Worker             xkb_atom_t val;
695*2b949d04SAndroid Build Coastguard Worker             const char *str;
696*2b949d04SAndroid Build Coastguard Worker             size_t len;
697*2b949d04SAndroid Build Coastguard Worker 
698*2b949d04SAndroid Build Coastguard Worker             if (!ExprResolveString(ctx, value, &val))
699*2b949d04SAndroid Build Coastguard Worker                 return ReportMismatch(ctx, action->type, field, "string");
700*2b949d04SAndroid Build Coastguard Worker 
701*2b949d04SAndroid Build Coastguard Worker             str = xkb_atom_text(ctx, val);
702*2b949d04SAndroid Build Coastguard Worker             len = strlen(str);
703*2b949d04SAndroid Build Coastguard Worker             if (len < 1 || len > sizeof(act->data)) {
704*2b949d04SAndroid Build Coastguard Worker                 log_warn(ctx,
705*2b949d04SAndroid Build Coastguard Worker                          "A private action has %ld data bytes; "
706*2b949d04SAndroid Build Coastguard Worker                          "Illegal data ignored\n", sizeof(act->data));
707*2b949d04SAndroid Build Coastguard Worker                 return false;
708*2b949d04SAndroid Build Coastguard Worker             }
709*2b949d04SAndroid Build Coastguard Worker 
710*2b949d04SAndroid Build Coastguard Worker             /* act->data may not be null-terminated, this is intentional */
711*2b949d04SAndroid Build Coastguard Worker             memset(act->data, 0, sizeof(act->data));
712*2b949d04SAndroid Build Coastguard Worker             memcpy(act->data, str, len);
713*2b949d04SAndroid Build Coastguard Worker             return true;
714*2b949d04SAndroid Build Coastguard Worker         }
715*2b949d04SAndroid Build Coastguard Worker         else {
716*2b949d04SAndroid Build Coastguard Worker             int ndx, datum;
717*2b949d04SAndroid Build Coastguard Worker 
718*2b949d04SAndroid Build Coastguard Worker             if (!ExprResolveInteger(ctx, array_ndx, &ndx)) {
719*2b949d04SAndroid Build Coastguard Worker                 log_err(ctx,
720*2b949d04SAndroid Build Coastguard Worker                         "Array subscript must be integer; "
721*2b949d04SAndroid Build Coastguard Worker                         "Illegal subscript ignored\n");
722*2b949d04SAndroid Build Coastguard Worker                 return false;
723*2b949d04SAndroid Build Coastguard Worker             }
724*2b949d04SAndroid Build Coastguard Worker 
725*2b949d04SAndroid Build Coastguard Worker             if (ndx < 0 || (size_t) ndx >= sizeof(act->data)) {
726*2b949d04SAndroid Build Coastguard Worker                 log_err(ctx,
727*2b949d04SAndroid Build Coastguard Worker                         "The data for a private action is %lu bytes long; "
728*2b949d04SAndroid Build Coastguard Worker                         "Attempt to use data[%d] ignored\n",
729*2b949d04SAndroid Build Coastguard Worker                         (unsigned long) sizeof(act->data), ndx);
730*2b949d04SAndroid Build Coastguard Worker                 return false;
731*2b949d04SAndroid Build Coastguard Worker             }
732*2b949d04SAndroid Build Coastguard Worker 
733*2b949d04SAndroid Build Coastguard Worker             if (!ExprResolveInteger(ctx, value, &datum))
734*2b949d04SAndroid Build Coastguard Worker                 return ReportMismatch(ctx, act->type, field, "integer");
735*2b949d04SAndroid Build Coastguard Worker 
736*2b949d04SAndroid Build Coastguard Worker             if (datum < 0 || datum > 255) {
737*2b949d04SAndroid Build Coastguard Worker                 log_err(ctx,
738*2b949d04SAndroid Build Coastguard Worker                         "All data for a private action must be 0..255; "
739*2b949d04SAndroid Build Coastguard Worker                         "Illegal datum %d ignored\n", datum);
740*2b949d04SAndroid Build Coastguard Worker                 return false;
741*2b949d04SAndroid Build Coastguard Worker             }
742*2b949d04SAndroid Build Coastguard Worker 
743*2b949d04SAndroid Build Coastguard Worker             act->data[ndx] = (uint8_t) datum;
744*2b949d04SAndroid Build Coastguard Worker             return true;
745*2b949d04SAndroid Build Coastguard Worker         }
746*2b949d04SAndroid Build Coastguard Worker     }
747*2b949d04SAndroid Build Coastguard Worker 
748*2b949d04SAndroid Build Coastguard Worker     return ReportIllegal(ctx, ACTION_TYPE_NONE, field);
749*2b949d04SAndroid Build Coastguard Worker }
750*2b949d04SAndroid Build Coastguard Worker 
751*2b949d04SAndroid Build Coastguard Worker typedef bool (*actionHandler)(struct xkb_context *ctx,
752*2b949d04SAndroid Build Coastguard Worker                               const struct xkb_mod_set *mods,
753*2b949d04SAndroid Build Coastguard Worker                               union xkb_action *action,
754*2b949d04SAndroid Build Coastguard Worker                               enum action_field field,
755*2b949d04SAndroid Build Coastguard Worker                               const ExprDef *array_ndx,
756*2b949d04SAndroid Build Coastguard Worker                               const ExprDef *value);
757*2b949d04SAndroid Build Coastguard Worker 
758*2b949d04SAndroid Build Coastguard Worker static const actionHandler handleAction[_ACTION_TYPE_NUM_ENTRIES] = {
759*2b949d04SAndroid Build Coastguard Worker     [ACTION_TYPE_NONE] = HandleNoAction,
760*2b949d04SAndroid Build Coastguard Worker     [ACTION_TYPE_MOD_SET] = HandleSetLatchLockMods,
761*2b949d04SAndroid Build Coastguard Worker     [ACTION_TYPE_MOD_LATCH] = HandleSetLatchLockMods,
762*2b949d04SAndroid Build Coastguard Worker     [ACTION_TYPE_MOD_LOCK] = HandleSetLatchLockMods,
763*2b949d04SAndroid Build Coastguard Worker     [ACTION_TYPE_GROUP_SET] = HandleSetLatchLockGroup,
764*2b949d04SAndroid Build Coastguard Worker     [ACTION_TYPE_GROUP_LATCH] = HandleSetLatchLockGroup,
765*2b949d04SAndroid Build Coastguard Worker     [ACTION_TYPE_GROUP_LOCK] = HandleSetLatchLockGroup,
766*2b949d04SAndroid Build Coastguard Worker     [ACTION_TYPE_PTR_MOVE] = HandleMovePtr,
767*2b949d04SAndroid Build Coastguard Worker     [ACTION_TYPE_PTR_BUTTON] = HandlePtrBtn,
768*2b949d04SAndroid Build Coastguard Worker     [ACTION_TYPE_PTR_LOCK] = HandlePtrBtn,
769*2b949d04SAndroid Build Coastguard Worker     [ACTION_TYPE_PTR_DEFAULT] = HandleSetPtrDflt,
770*2b949d04SAndroid Build Coastguard Worker     [ACTION_TYPE_TERMINATE] = HandleNoAction,
771*2b949d04SAndroid Build Coastguard Worker     [ACTION_TYPE_SWITCH_VT] = HandleSwitchScreen,
772*2b949d04SAndroid Build Coastguard Worker     [ACTION_TYPE_CTRL_SET] = HandleSetLockControls,
773*2b949d04SAndroid Build Coastguard Worker     [ACTION_TYPE_CTRL_LOCK] = HandleSetLockControls,
774*2b949d04SAndroid Build Coastguard Worker     [ACTION_TYPE_PRIVATE] = HandlePrivate,
775*2b949d04SAndroid Build Coastguard Worker };
776*2b949d04SAndroid Build Coastguard Worker 
777*2b949d04SAndroid Build Coastguard Worker /***====================================================================***/
778*2b949d04SAndroid Build Coastguard Worker 
779*2b949d04SAndroid Build Coastguard Worker bool
HandleActionDef(struct xkb_context * ctx,ActionsInfo * info,const struct xkb_mod_set * mods,ExprDef * def,union xkb_action * action)780*2b949d04SAndroid Build Coastguard Worker HandleActionDef(struct xkb_context *ctx, ActionsInfo *info,
781*2b949d04SAndroid Build Coastguard Worker                 const struct xkb_mod_set *mods, ExprDef *def,
782*2b949d04SAndroid Build Coastguard Worker                 union xkb_action *action)
783*2b949d04SAndroid Build Coastguard Worker {
784*2b949d04SAndroid Build Coastguard Worker     ExprDef *arg;
785*2b949d04SAndroid Build Coastguard Worker     const char *str;
786*2b949d04SAndroid Build Coastguard Worker     enum xkb_action_type handler_type;
787*2b949d04SAndroid Build Coastguard Worker 
788*2b949d04SAndroid Build Coastguard Worker     if (def->expr.op != EXPR_ACTION_DECL) {
789*2b949d04SAndroid Build Coastguard Worker         log_err(ctx, "Expected an action definition, found %s\n",
790*2b949d04SAndroid Build Coastguard Worker                 expr_op_type_to_string(def->expr.op));
791*2b949d04SAndroid Build Coastguard Worker         return false;
792*2b949d04SAndroid Build Coastguard Worker     }
793*2b949d04SAndroid Build Coastguard Worker 
794*2b949d04SAndroid Build Coastguard Worker     str = xkb_atom_text(ctx, def->action.name);
795*2b949d04SAndroid Build Coastguard Worker     if (!stringToAction(str, &handler_type)) {
796*2b949d04SAndroid Build Coastguard Worker         log_err(ctx, "Unknown action %s\n", str);
797*2b949d04SAndroid Build Coastguard Worker         return false;
798*2b949d04SAndroid Build Coastguard Worker     }
799*2b949d04SAndroid Build Coastguard Worker 
800*2b949d04SAndroid Build Coastguard Worker     /*
801*2b949d04SAndroid Build Coastguard Worker      * Get the default values for this action type, as modified by
802*2b949d04SAndroid Build Coastguard Worker      * statements such as:
803*2b949d04SAndroid Build Coastguard Worker      *     latchMods.clearLocks = True;
804*2b949d04SAndroid Build Coastguard Worker      */
805*2b949d04SAndroid Build Coastguard Worker     *action = info->actions[handler_type];
806*2b949d04SAndroid Build Coastguard Worker 
807*2b949d04SAndroid Build Coastguard Worker     /*
808*2b949d04SAndroid Build Coastguard Worker      * Now change the action properties as specified for this
809*2b949d04SAndroid Build Coastguard Worker      * particular instance, e.g. "modifiers" and "clearLocks" in:
810*2b949d04SAndroid Build Coastguard Worker      *     SetMods(modifiers=Alt,clearLocks);
811*2b949d04SAndroid Build Coastguard Worker      */
812*2b949d04SAndroid Build Coastguard Worker     for (arg = def->action.args; arg != NULL;
813*2b949d04SAndroid Build Coastguard Worker          arg = (ExprDef *) arg->common.next) {
814*2b949d04SAndroid Build Coastguard Worker         const ExprDef *value;
815*2b949d04SAndroid Build Coastguard Worker         ExprDef *field, *arrayRtrn;
816*2b949d04SAndroid Build Coastguard Worker         const char *elemRtrn, *fieldRtrn;
817*2b949d04SAndroid Build Coastguard Worker         enum action_field fieldNdx;
818*2b949d04SAndroid Build Coastguard Worker 
819*2b949d04SAndroid Build Coastguard Worker         if (arg->expr.op == EXPR_ASSIGN) {
820*2b949d04SAndroid Build Coastguard Worker             field = arg->binary.left;
821*2b949d04SAndroid Build Coastguard Worker             value = arg->binary.right;
822*2b949d04SAndroid Build Coastguard Worker         }
823*2b949d04SAndroid Build Coastguard Worker         else if (arg->expr.op == EXPR_NOT || arg->expr.op == EXPR_INVERT) {
824*2b949d04SAndroid Build Coastguard Worker             field = arg->unary.child;
825*2b949d04SAndroid Build Coastguard Worker             value = (const ExprDef *) &constFalse;
826*2b949d04SAndroid Build Coastguard Worker         }
827*2b949d04SAndroid Build Coastguard Worker         else {
828*2b949d04SAndroid Build Coastguard Worker             field = arg;
829*2b949d04SAndroid Build Coastguard Worker             value = (const ExprDef *) &constTrue;
830*2b949d04SAndroid Build Coastguard Worker         }
831*2b949d04SAndroid Build Coastguard Worker 
832*2b949d04SAndroid Build Coastguard Worker         if (!ExprResolveLhs(ctx, field, &elemRtrn, &fieldRtrn, &arrayRtrn))
833*2b949d04SAndroid Build Coastguard Worker             return false;
834*2b949d04SAndroid Build Coastguard Worker 
835*2b949d04SAndroid Build Coastguard Worker         if (elemRtrn) {
836*2b949d04SAndroid Build Coastguard Worker             log_err(ctx,
837*2b949d04SAndroid Build Coastguard Worker                     "Cannot change defaults in an action definition; "
838*2b949d04SAndroid Build Coastguard Worker                     "Ignoring attempt to change %s.%s\n",
839*2b949d04SAndroid Build Coastguard Worker                     elemRtrn, fieldRtrn);
840*2b949d04SAndroid Build Coastguard Worker             return false;
841*2b949d04SAndroid Build Coastguard Worker         }
842*2b949d04SAndroid Build Coastguard Worker 
843*2b949d04SAndroid Build Coastguard Worker         if (!stringToField(fieldRtrn, &fieldNdx)) {
844*2b949d04SAndroid Build Coastguard Worker             log_err(ctx, "Unknown field name %s\n", fieldRtrn);
845*2b949d04SAndroid Build Coastguard Worker             return false;
846*2b949d04SAndroid Build Coastguard Worker         }
847*2b949d04SAndroid Build Coastguard Worker 
848*2b949d04SAndroid Build Coastguard Worker         if (!handleAction[handler_type](ctx, mods, action, fieldNdx,
849*2b949d04SAndroid Build Coastguard Worker                                         arrayRtrn, value))
850*2b949d04SAndroid Build Coastguard Worker             return false;
851*2b949d04SAndroid Build Coastguard Worker     }
852*2b949d04SAndroid Build Coastguard Worker 
853*2b949d04SAndroid Build Coastguard Worker     return true;
854*2b949d04SAndroid Build Coastguard Worker }
855*2b949d04SAndroid Build Coastguard Worker 
856*2b949d04SAndroid Build Coastguard Worker bool
SetActionField(struct xkb_context * ctx,ActionsInfo * info,struct xkb_mod_set * mods,const char * elem,const char * field,ExprDef * array_ndx,ExprDef * value)857*2b949d04SAndroid Build Coastguard Worker SetActionField(struct xkb_context *ctx, ActionsInfo *info,
858*2b949d04SAndroid Build Coastguard Worker                struct xkb_mod_set *mods, const char *elem,
859*2b949d04SAndroid Build Coastguard Worker                const char *field, ExprDef *array_ndx, ExprDef *value)
860*2b949d04SAndroid Build Coastguard Worker {
861*2b949d04SAndroid Build Coastguard Worker     enum xkb_action_type action;
862*2b949d04SAndroid Build Coastguard Worker     enum action_field action_field;
863*2b949d04SAndroid Build Coastguard Worker 
864*2b949d04SAndroid Build Coastguard Worker     if (!stringToAction(elem, &action))
865*2b949d04SAndroid Build Coastguard Worker         return false;
866*2b949d04SAndroid Build Coastguard Worker 
867*2b949d04SAndroid Build Coastguard Worker     if (!stringToField(field, &action_field)) {
868*2b949d04SAndroid Build Coastguard Worker         log_err(ctx, "\"%s\" is not a legal field name\n", field);
869*2b949d04SAndroid Build Coastguard Worker         return false;
870*2b949d04SAndroid Build Coastguard Worker     }
871*2b949d04SAndroid Build Coastguard Worker 
872*2b949d04SAndroid Build Coastguard Worker     return handleAction[action](ctx, mods, &info->actions[action],
873*2b949d04SAndroid Build Coastguard Worker                                 action_field, array_ndx, value);
874*2b949d04SAndroid Build Coastguard Worker }
875