1 /************************************************************
2 Copyright (c) 1994 by Silicon Graphics Computer Systems, Inc.
3
4 Permission to use, copy, modify, and distribute this
5 software and its documentation for any purpose and without
6 fee is hereby granted, provided that the above copyright
7 notice appear in all copies and that both that copyright
8 notice and this permission notice appear in supporting
9 documentation, and that the name of Silicon Graphics not be
10 used in advertising or publicity pertaining to distribution
11 of the software without specific prior written permission.
12 Silicon Graphics makes no representation about the suitability
13 of this software for any purpose. It is provided "as is"
14 without any express or implied warranty.
15
16 SILICON GRAPHICS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS
17 SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
18 AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL SILICON
19 GRAPHICS BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL
20 DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
21 DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
22 OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH
23 THE USE OR PERFORMANCE OF THIS SOFTWARE.
24
25 ********************************************************/
26
27 #include "xkbcomp.h"
28 #include "tokens.h"
29 #include "expr.h"
30
31 #include "keycodes.h"
32 #include "vmod.h"
33 #include "misc.h"
34 #include "action.h"
35 #include "misc.h"
36
37 static Bool actionsInitialized;
38 static ExprDef constTrue;
39 static ExprDef constFalse;
40
41 /***====================================================================***/
42
43 static Bool
stringToAction(const char * str,unsigned * type_rtrn)44 stringToAction(const char *str, unsigned *type_rtrn)
45 {
46 if (str == NULL)
47 return False;
48
49 if (uStrCaseCmp(str, "noaction") == 0)
50 *type_rtrn = XkbSA_NoAction;
51 else if (uStrCaseCmp(str, "setmods") == 0)
52 *type_rtrn = XkbSA_SetMods;
53 else if (uStrCaseCmp(str, "latchmods") == 0)
54 *type_rtrn = XkbSA_LatchMods;
55 else if (uStrCaseCmp(str, "lockmods") == 0)
56 *type_rtrn = XkbSA_LockMods;
57 else if (uStrCaseCmp(str, "setgroup") == 0)
58 *type_rtrn = XkbSA_SetGroup;
59 else if (uStrCaseCmp(str, "latchgroup") == 0)
60 *type_rtrn = XkbSA_LatchGroup;
61 else if (uStrCaseCmp(str, "lockgroup") == 0)
62 *type_rtrn = XkbSA_LockGroup;
63 else if (uStrCaseCmp(str, "moveptr") == 0)
64 *type_rtrn = XkbSA_MovePtr;
65 else if (uStrCaseCmp(str, "movepointer") == 0)
66 *type_rtrn = XkbSA_MovePtr;
67 else if (uStrCaseCmp(str, "ptrbtn") == 0)
68 *type_rtrn = XkbSA_PtrBtn;
69 else if (uStrCaseCmp(str, "pointerbutton") == 0)
70 *type_rtrn = XkbSA_PtrBtn;
71 else if (uStrCaseCmp(str, "lockptrbtn") == 0)
72 *type_rtrn = XkbSA_LockPtrBtn;
73 else if (uStrCaseCmp(str, "lockpointerbutton") == 0)
74 *type_rtrn = XkbSA_LockPtrBtn;
75 else if (uStrCaseCmp(str, "lockptrbutton") == 0)
76 *type_rtrn = XkbSA_LockPtrBtn;
77 else if (uStrCaseCmp(str, "lockpointerbtn") == 0)
78 *type_rtrn = XkbSA_LockPtrBtn;
79 else if (uStrCaseCmp(str, "setptrdflt") == 0)
80 *type_rtrn = XkbSA_SetPtrDflt;
81 else if (uStrCaseCmp(str, "setpointerdefault") == 0)
82 *type_rtrn = XkbSA_SetPtrDflt;
83 else if (uStrCaseCmp(str, "isolock") == 0)
84 *type_rtrn = XkbSA_ISOLock;
85 else if (uStrCaseCmp(str, "terminate") == 0)
86 *type_rtrn = XkbSA_Terminate;
87 else if (uStrCaseCmp(str, "terminateserver") == 0)
88 *type_rtrn = XkbSA_Terminate;
89 else if (uStrCaseCmp(str, "switchscreen") == 0)
90 *type_rtrn = XkbSA_SwitchScreen;
91 else if (uStrCaseCmp(str, "setcontrols") == 0)
92 *type_rtrn = XkbSA_SetControls;
93 else if (uStrCaseCmp(str, "lockcontrols") == 0)
94 *type_rtrn = XkbSA_LockControls;
95 else if (uStrCaseCmp(str, "actionmessage") == 0)
96 *type_rtrn = XkbSA_ActionMessage;
97 else if (uStrCaseCmp(str, "messageaction") == 0)
98 *type_rtrn = XkbSA_ActionMessage;
99 else if (uStrCaseCmp(str, "message") == 0)
100 *type_rtrn = XkbSA_ActionMessage;
101 else if (uStrCaseCmp(str, "redirect") == 0)
102 *type_rtrn = XkbSA_RedirectKey;
103 else if (uStrCaseCmp(str, "redirectkey") == 0)
104 *type_rtrn = XkbSA_RedirectKey;
105 else if (uStrCaseCmp(str, "devbtn") == 0)
106 *type_rtrn = XkbSA_DeviceBtn;
107 else if (uStrCaseCmp(str, "devicebtn") == 0)
108 *type_rtrn = XkbSA_DeviceBtn;
109 else if (uStrCaseCmp(str, "devbutton") == 0)
110 *type_rtrn = XkbSA_DeviceBtn;
111 else if (uStrCaseCmp(str, "devicebutton") == 0)
112 *type_rtrn = XkbSA_DeviceBtn;
113 else if (uStrCaseCmp(str, "lockdevbtn") == 0)
114 *type_rtrn = XkbSA_LockDeviceBtn;
115 else if (uStrCaseCmp(str, "lockdevicebtn") == 0)
116 *type_rtrn = XkbSA_LockDeviceBtn;
117 else if (uStrCaseCmp(str, "lockdevbutton") == 0)
118 *type_rtrn = XkbSA_LockDeviceBtn;
119 else if (uStrCaseCmp(str, "lockdevicebutton") == 0)
120 *type_rtrn = XkbSA_LockDeviceBtn;
121 else if (uStrCaseCmp(str, "devval") == 0)
122 *type_rtrn = XkbSA_DeviceValuator;
123 else if (uStrCaseCmp(str, "deviceval") == 0)
124 *type_rtrn = XkbSA_DeviceValuator;
125 else if (uStrCaseCmp(str, "devvaluator") == 0)
126 *type_rtrn = XkbSA_DeviceValuator;
127 else if (uStrCaseCmp(str, "devicevaluator") == 0)
128 *type_rtrn = XkbSA_DeviceValuator;
129 else if (uStrCaseCmp(str, "private") == 0)
130 *type_rtrn = PrivateAction;
131 else
132 return False;
133 return True;
134 }
135
136 static Bool
stringToField(const char * str,unsigned * field_rtrn)137 stringToField(const char *str, unsigned *field_rtrn)
138 {
139
140 if (str == NULL)
141 return False;
142
143 if (uStrCaseCmp(str, "clearlocks") == 0)
144 *field_rtrn = F_ClearLocks;
145 else if (uStrCaseCmp(str, "latchtolock") == 0)
146 *field_rtrn = F_LatchToLock;
147 else if (uStrCaseCmp(str, "genkeyevent") == 0)
148 *field_rtrn = F_GenKeyEvent;
149 else if (uStrCaseCmp(str, "generatekeyevent") == 0)
150 *field_rtrn = F_GenKeyEvent;
151 else if (uStrCaseCmp(str, "report") == 0)
152 *field_rtrn = F_Report;
153 else if (uStrCaseCmp(str, "default") == 0)
154 *field_rtrn = F_Default;
155 else if (uStrCaseCmp(str, "affect") == 0)
156 *field_rtrn = F_Affect;
157 else if (uStrCaseCmp(str, "increment") == 0)
158 *field_rtrn = F_Increment;
159 else if (uStrCaseCmp(str, "mods") == 0)
160 *field_rtrn = F_Modifiers;
161 else if (uStrCaseCmp(str, "modifiers") == 0)
162 *field_rtrn = F_Modifiers;
163 else if (uStrCaseCmp(str, "group") == 0)
164 *field_rtrn = F_Group;
165 else if (uStrCaseCmp(str, "x") == 0)
166 *field_rtrn = F_X;
167 else if (uStrCaseCmp(str, "y") == 0)
168 *field_rtrn = F_Y;
169 else if (uStrCaseCmp(str, "accel") == 0)
170 *field_rtrn = F_Accel;
171 else if (uStrCaseCmp(str, "accelerate") == 0)
172 *field_rtrn = F_Accel;
173 else if (uStrCaseCmp(str, "repeat") == 0)
174 *field_rtrn = F_Accel;
175 else if (uStrCaseCmp(str, "button") == 0)
176 *field_rtrn = F_Button;
177 else if (uStrCaseCmp(str, "value") == 0)
178 *field_rtrn = F_Value;
179 else if (uStrCaseCmp(str, "controls") == 0)
180 *field_rtrn = F_Controls;
181 else if (uStrCaseCmp(str, "ctrls") == 0)
182 *field_rtrn = F_Controls;
183 else if (uStrCaseCmp(str, "type") == 0)
184 *field_rtrn = F_Type;
185 else if (uStrCaseCmp(str, "count") == 0)
186 *field_rtrn = F_Count;
187 else if (uStrCaseCmp(str, "screen") == 0)
188 *field_rtrn = F_Screen;
189 else if (uStrCaseCmp(str, "same") == 0)
190 *field_rtrn = F_Same;
191 else if (uStrCaseCmp(str, "sameserver") == 0)
192 *field_rtrn = F_Same;
193 else if (uStrCaseCmp(str, "data") == 0)
194 *field_rtrn = F_Data;
195 else if (uStrCaseCmp(str, "device") == 0)
196 *field_rtrn = F_Device;
197 else if (uStrCaseCmp(str, "dev") == 0)
198 *field_rtrn = F_Device;
199 else if (uStrCaseCmp(str, "key") == 0)
200 *field_rtrn = F_Keycode;
201 else if (uStrCaseCmp(str, "keycode") == 0)
202 *field_rtrn = F_Keycode;
203 else if (uStrCaseCmp(str, "kc") == 0)
204 *field_rtrn = F_Keycode;
205 else if (uStrCaseCmp(str, "clearmods") == 0)
206 *field_rtrn = F_ModsToClear;
207 else if (uStrCaseCmp(str, "clearmodifiers") == 0)
208 *field_rtrn = F_ModsToClear;
209 else
210 return False;
211 return True;
212 }
213
214 static char *
fieldText(unsigned field)215 fieldText(unsigned field)
216 {
217 static char buf[32];
218
219 switch (field)
220 {
221 case F_ClearLocks:
222 strcpy(buf, "clearLocks");
223 break;
224 case F_LatchToLock:
225 strcpy(buf, "latchToLock");
226 break;
227 case F_GenKeyEvent:
228 strcpy(buf, "genKeyEvent");
229 break;
230 case F_Report:
231 strcpy(buf, "report");
232 break;
233 case F_Default:
234 strcpy(buf, "default");
235 break;
236 case F_Affect:
237 strcpy(buf, "affect");
238 break;
239 case F_Increment:
240 strcpy(buf, "increment");
241 break;
242 case F_Modifiers:
243 strcpy(buf, "modifiers");
244 break;
245 case F_Group:
246 strcpy(buf, "group");
247 break;
248 case F_X:
249 strcpy(buf, "x");
250 break;
251 case F_Y:
252 strcpy(buf, "y");
253 break;
254 case F_Accel:
255 strcpy(buf, "accel");
256 break;
257 case F_Button:
258 strcpy(buf, "button");
259 break;
260 case F_Value:
261 strcpy(buf, "value");
262 break;
263 case F_Controls:
264 strcpy(buf, "controls");
265 break;
266 case F_Type:
267 strcpy(buf, "type");
268 break;
269 case F_Count:
270 strcpy(buf, "count");
271 break;
272 case F_Screen:
273 strcpy(buf, "screen");
274 break;
275 case F_Same:
276 strcpy(buf, "sameServer");
277 break;
278 case F_Data:
279 strcpy(buf, "data");
280 break;
281 case F_Device:
282 strcpy(buf, "device");
283 break;
284 case F_Keycode:
285 strcpy(buf, "keycode");
286 break;
287 case F_ModsToClear:
288 strcpy(buf, "clearmods");
289 break;
290 default:
291 strcpy(buf, "unknown");
292 break;
293 }
294 return buf;
295 }
296
297 /***====================================================================***/
298
299 static Bool
ReportMismatch(unsigned action,unsigned field,const char * type)300 ReportMismatch(unsigned action, unsigned field, const char *type)
301 {
302 ERROR("Value of %s field must be of type %s\n", fieldText(field), type);
303 ACTION("Action %s definition ignored\n",
304 XkbActionTypeText(action, XkbMessage));
305 return False;
306 }
307
308 static Bool
ReportIllegal(unsigned action,unsigned field)309 ReportIllegal(unsigned action, unsigned field)
310 {
311 ERROR("Field %s is not defined for an action of type %s\n",
312 fieldText(field), XkbActionTypeText(action, XkbMessage));
313 ACTION("Action definition ignored\n");
314 return False;
315 }
316
317 static Bool
ReportActionNotArray(unsigned action,unsigned field)318 ReportActionNotArray(unsigned action, unsigned field)
319 {
320 ERROR("The %s field in the %s action is not an array\n",
321 fieldText(field), XkbActionTypeText(action, XkbMessage));
322 ACTION("Action definition ignored\n");
323 return False;
324 }
325
326 static Bool
ReportNotFound(unsigned action,unsigned field,const char * what,char * bad)327 ReportNotFound(unsigned action, unsigned field, const char *what, char *bad)
328 {
329 ERROR("%s named %s not found\n", what, bad);
330 ACTION("Ignoring the %s field of an %s action\n", fieldText(field),
331 XkbActionTypeText(action, XkbMessage));
332 return False;
333 }
334
335 static Bool
HandleNoAction(XkbDescPtr xkb,XkbAnyAction * action,unsigned field,ExprDef * array_ndx,ExprDef * value)336 HandleNoAction(XkbDescPtr xkb,
337 XkbAnyAction * action,
338 unsigned field, ExprDef * array_ndx, ExprDef * value)
339 {
340 return ReportIllegal(action->type, field);
341 }
342
343 static Bool
CheckLatchLockFlags(unsigned action,unsigned field,ExprDef * value,unsigned * flags_inout)344 CheckLatchLockFlags(unsigned action,
345 unsigned field, ExprDef * value, unsigned *flags_inout)
346 {
347 unsigned tmp;
348 ExprResult result;
349
350 if (field == F_ClearLocks)
351 tmp = XkbSA_ClearLocks;
352 else if (field == F_LatchToLock)
353 tmp = XkbSA_LatchToLock;
354 else
355 return False; /* WSGO! */
356 if (!ExprResolveBoolean(value, &result, NULL, NULL))
357 return ReportMismatch(action, field, "boolean");
358 if (result.uval)
359 *flags_inout |= tmp;
360 else
361 *flags_inout &= ~tmp;
362 return True;
363 }
364
365 static Bool
CheckModifierField(XkbDescPtr xkb,unsigned action,ExprDef * value,unsigned * flags_inout,unsigned * mods_rtrn)366 CheckModifierField(XkbDescPtr xkb,
367 unsigned action,
368 ExprDef * value,
369 unsigned *flags_inout, unsigned *mods_rtrn)
370 {
371 ExprResult rtrn;
372
373 if (value->op == ExprIdent)
374 {
375 register char *valStr;
376 valStr = XkbAtomGetString(NULL, value->value.str);
377 if (valStr && ((uStrCaseCmp(valStr, "usemodmapmods") == 0) ||
378 (uStrCaseCmp(valStr, "modmapmods") == 0)))
379 {
380
381 *mods_rtrn = 0;
382 *flags_inout |= XkbSA_UseModMapMods;
383 return True;
384 }
385 }
386 if (!ExprResolveModMask(value, &rtrn, LookupVModMask, (XPointer) xkb))
387 return ReportMismatch(action, F_Modifiers, "modifier mask");
388 *mods_rtrn = rtrn.uval;
389 *flags_inout &= ~XkbSA_UseModMapMods;
390 return True;
391 }
392
393 static Bool
HandleSetLatchMods(XkbDescPtr xkb,XkbAnyAction * action,unsigned field,ExprDef * array_ndx,ExprDef * value)394 HandleSetLatchMods(XkbDescPtr xkb,
395 XkbAnyAction * action,
396 unsigned field, ExprDef * array_ndx, ExprDef * value)
397 {
398 XkbModAction *act;
399 unsigned rtrn;
400 unsigned t1, t2;
401
402 act = (XkbModAction *) action;
403 if (array_ndx != NULL)
404 {
405 switch (field)
406 {
407 case F_ClearLocks:
408 case F_LatchToLock:
409 case F_Modifiers:
410 return ReportActionNotArray(action->type, field);
411 }
412 }
413 switch (field)
414 {
415 case F_ClearLocks:
416 case F_LatchToLock:
417 rtrn = act->flags;
418 if (CheckLatchLockFlags(action->type, field, value, &rtrn))
419 {
420 act->flags = rtrn;
421 return True;
422 }
423 return False;
424 case F_Modifiers:
425 t1 = act->flags;
426 if (CheckModifierField(xkb, action->type, value, &t1, &t2))
427 {
428 act->flags = t1;
429 act->real_mods = act->mask = (t2 & 0xff);
430 t2 = (t2 >> 8) & 0xffff;
431 XkbSetModActionVMods(act, t2);
432 return True;
433 }
434 return False;
435 }
436 return ReportIllegal(action->type, field);
437 }
438
439 static LookupEntry lockWhich[] = {
440 {"both", 0},
441 {"lock", XkbSA_LockNoUnlock},
442 {"neither", (XkbSA_LockNoLock | XkbSA_LockNoUnlock)},
443 {"unlock", XkbSA_LockNoLock},
444 {NULL, 0}
445 };
446
447 static Bool
HandleLockMods(XkbDescPtr xkb,XkbAnyAction * action,unsigned field,ExprDef * array_ndx,ExprDef * value)448 HandleLockMods(XkbDescPtr xkb,
449 XkbAnyAction * action,
450 unsigned field, ExprDef * array_ndx, ExprDef * value)
451 {
452 XkbModAction *act;
453 unsigned t1, t2;
454 ExprResult rtrn;
455
456 act = (XkbModAction *) action;
457 if ((array_ndx != NULL) && (field == F_Modifiers || field == F_Affect))
458 return ReportActionNotArray(action->type, field);
459 switch (field)
460 {
461 case F_Affect:
462 if (!ExprResolveEnum(value, &rtrn, lockWhich))
463 return ReportMismatch(action->type, field, "lock or unlock");
464 act->flags &= ~(XkbSA_LockNoLock | XkbSA_LockNoUnlock);
465 act->flags |= rtrn.uval;
466 return True;
467 case F_Modifiers:
468 t1 = act->flags;
469 if (CheckModifierField(xkb, action->type, value, &t1, &t2))
470 {
471 act->flags = t1;
472 act->real_mods = act->mask = (t2 & 0xff);
473 t2 = (t2 >> 8) & 0xffff;
474 XkbSetModActionVMods(act, t2);
475 return True;
476 }
477 return False;
478 }
479 return ReportIllegal(action->type, field);
480 }
481
482 static LookupEntry groupNames[] = {
483 {"group1", 1},
484 {"group2", 2},
485 {"group3", 3},
486 {"group4", 4},
487 {"group5", 5},
488 {"group6", 6},
489 {"group7", 7},
490 {"group8", 8},
491 {NULL, 0},
492 };
493
494 static Bool
CheckGroupField(unsigned action,ExprDef * value,unsigned * flags_inout,int * grp_rtrn)495 CheckGroupField(unsigned action,
496 ExprDef * value, unsigned *flags_inout, int *grp_rtrn)
497 {
498 ExprDef *spec;
499 ExprResult rtrn;
500
501 if ((value->op == OpNegate) || (value->op == OpUnaryPlus))
502 {
503 *flags_inout &= ~XkbSA_GroupAbsolute;
504 spec = value->value.child;
505 }
506 else
507 {
508 *flags_inout |= XkbSA_GroupAbsolute;
509 spec = value;
510 }
511
512 if (!ExprResolveInteger(spec, &rtrn, SimpleLookup, (XPointer) groupNames))
513 return ReportMismatch(action, F_Group, "integer (range 1..8)");
514 if ((rtrn.ival < 1) || (rtrn.ival > XkbNumKbdGroups))
515 {
516 ERROR("Illegal group %d (must be in the range 1..%d)\n", rtrn.ival,
517 XkbNumKbdGroups);
518 ACTION("Action %s definition ignored\n",
519 XkbActionTypeText(action, XkbMessage));
520 return False;
521 }
522 if (value->op == OpNegate)
523 *grp_rtrn = -rtrn.ival;
524 else if (value->op == OpUnaryPlus)
525 *grp_rtrn = rtrn.ival;
526 else
527 *grp_rtrn = rtrn.ival - 1;
528 return True;
529 }
530
531 static Bool
HandleSetLatchGroup(XkbDescPtr xkb,XkbAnyAction * action,unsigned field,ExprDef * array_ndx,ExprDef * value)532 HandleSetLatchGroup(XkbDescPtr xkb,
533 XkbAnyAction * action,
534 unsigned field, ExprDef * array_ndx, ExprDef * value)
535 {
536 XkbGroupAction *act;
537 unsigned rtrn;
538 unsigned t1;
539 int t2;
540
541 act = (XkbGroupAction *) action;
542 if (array_ndx != NULL)
543 {
544 switch (field)
545 {
546 case F_ClearLocks:
547 case F_LatchToLock:
548 case F_Group:
549 return ReportActionNotArray(action->type, field);
550 }
551 }
552 switch (field)
553 {
554 case F_ClearLocks:
555 case F_LatchToLock:
556 rtrn = act->flags;
557 if (CheckLatchLockFlags(action->type, field, value, &rtrn))
558 {
559 act->flags = rtrn;
560 return True;
561 }
562 return False;
563 case F_Group:
564 t1 = act->flags;
565 if (CheckGroupField(action->type, value, &t1, &t2))
566 {
567 act->flags = t1;
568 XkbSASetGroup(act, t2);
569 return True;
570 }
571 return False;
572 }
573 return ReportIllegal(action->type, field);
574 }
575
576 static Bool
HandleLockGroup(XkbDescPtr xkb,XkbAnyAction * action,unsigned field,ExprDef * array_ndx,ExprDef * value)577 HandleLockGroup(XkbDescPtr xkb,
578 XkbAnyAction * action,
579 unsigned field, ExprDef * array_ndx, ExprDef * value)
580 {
581 XkbGroupAction *act;
582 unsigned t1;
583 int t2;
584
585 act = (XkbGroupAction *) action;
586 if ((array_ndx != NULL) && (field == F_Group))
587 return ReportActionNotArray(action->type, field);
588 if (field == F_Group)
589 {
590 t1 = act->flags;
591 if (CheckGroupField(action->type, value, &t1, &t2))
592 {
593 act->flags = t1;
594 XkbSASetGroup(act, t2);
595 return True;
596 }
597 return False;
598 }
599 return ReportIllegal(action->type, field);
600 }
601
602 static Bool
HandleMovePtr(XkbDescPtr xkb,XkbAnyAction * action,unsigned field,ExprDef * array_ndx,ExprDef * value)603 HandleMovePtr(XkbDescPtr xkb,
604 XkbAnyAction * action,
605 unsigned field, ExprDef * array_ndx, ExprDef * value)
606 {
607 ExprResult rtrn;
608 XkbPtrAction *act;
609 Bool absolute;
610
611 act = (XkbPtrAction *) action;
612 if ((array_ndx != NULL) && ((field == F_X) || (field == F_Y)))
613 return ReportActionNotArray(action->type, field);
614
615 if ((field == F_X) || (field == F_Y))
616 {
617 if ((value->op == OpNegate) || (value->op == OpUnaryPlus))
618 absolute = False;
619 else
620 absolute = True;
621 if (!ExprResolveInteger(value, &rtrn, NULL, NULL))
622 return ReportMismatch(action->type, field, "integer");
623 if (field == F_X)
624 {
625 if (absolute)
626 act->flags |= XkbSA_MoveAbsoluteX;
627 XkbSetPtrActionX(act, rtrn.ival);
628 }
629 else
630 {
631 if (absolute)
632 act->flags |= XkbSA_MoveAbsoluteY;
633 XkbSetPtrActionY(act, rtrn.ival);
634 }
635 return True;
636 }
637 else if (field == F_Accel)
638 {
639 if (!ExprResolveBoolean(value, &rtrn, NULL, NULL))
640 return ReportMismatch(action->type, field, "boolean");
641 if (rtrn.uval)
642 act->flags &= ~XkbSA_NoAcceleration;
643 else
644 act->flags |= XkbSA_NoAcceleration;
645 return True;
646 }
647 return ReportIllegal(action->type, field);
648 }
649
650 static LookupEntry btnNames[] = {
651 {"button1", 1},
652 {"button2", 2},
653 {"button3", 3},
654 {"button4", 4},
655 {"button5", 5},
656 {"default", 0},
657 {NULL, 0}
658 };
659
660 static Bool
HandlePtrBtn(XkbDescPtr xkb,XkbAnyAction * action,unsigned field,ExprDef * array_ndx,ExprDef * value)661 HandlePtrBtn(XkbDescPtr xkb,
662 XkbAnyAction * action,
663 unsigned field, ExprDef * array_ndx, ExprDef * value)
664 {
665 ExprResult rtrn;
666 XkbPtrBtnAction *act;
667
668 act = (XkbPtrBtnAction *) action;
669 if (field == F_Button)
670 {
671 if (array_ndx != NULL)
672 return ReportActionNotArray(action->type, field);
673 if (!ExprResolveInteger
674 (value, &rtrn, SimpleLookup, (XPointer) btnNames))
675 return ReportMismatch(action->type, field,
676 "integer (range 1..5)");
677 if ((rtrn.ival < 0) || (rtrn.ival > 5))
678 {
679 ERROR("Button must specify default or be in the range 1..5\n");
680 ACTION("Illegal button value %d ignored\n", rtrn.ival);
681 return False;
682 }
683 act->button = rtrn.ival;
684 return True;
685 }
686 else if ((action->type == XkbSA_LockPtrBtn) && (field == F_Affect))
687 {
688 if (array_ndx != NULL)
689 return ReportActionNotArray(action->type, field);
690 if (!ExprResolveEnum(value, &rtrn, lockWhich))
691 return ReportMismatch(action->type, field, "lock or unlock");
692 act->flags &= ~(XkbSA_LockNoLock | XkbSA_LockNoUnlock);
693 act->flags |= rtrn.uval;
694 return True;
695 }
696 else if (field == F_Count)
697 {
698 if (array_ndx != NULL)
699 return ReportActionNotArray(action->type, field);
700 if (!ExprResolveInteger
701 (value, &rtrn, SimpleLookup, (XPointer) btnNames))
702 return ReportMismatch(action->type, field, "integer");
703 if ((rtrn.ival < 0) || (rtrn.ival > 255))
704 {
705 ERROR("The count field must have a value in the range 0..255\n");
706 ACTION("Illegal count %d ignored\n", rtrn.ival);
707 return False;
708 }
709 act->count = rtrn.ival;
710 return True;
711 }
712 return ReportIllegal(action->type, field);
713 }
714
715 static LookupEntry ptrDflts[] = {
716 {"dfltbtn", XkbSA_AffectDfltBtn},
717 {"defaultbutton", XkbSA_AffectDfltBtn},
718 {"button", XkbSA_AffectDfltBtn},
719 {NULL, 0}
720 };
721
722 static Bool
HandleSetPtrDflt(XkbDescPtr xkb,XkbAnyAction * action,unsigned field,ExprDef * array_ndx,ExprDef * value)723 HandleSetPtrDflt(XkbDescPtr xkb,
724 XkbAnyAction * action,
725 unsigned field, ExprDef * array_ndx, ExprDef * value)
726 {
727 ExprResult rtrn;
728 XkbPtrDfltAction *act;
729
730 act = (XkbPtrDfltAction *) action;
731 if (field == F_Affect)
732 {
733 if (array_ndx != NULL)
734 return ReportActionNotArray(action->type, field);
735 if (!ExprResolveEnum(value, &rtrn, ptrDflts))
736 return ReportMismatch(action->type, field, "pointer component");
737 act->affect = rtrn.uval;
738 return True;
739 }
740 else if ((field == F_Button) || (field == F_Value))
741 {
742 ExprDef *btn;
743 if (array_ndx != NULL)
744 return ReportActionNotArray(action->type, field);
745 if ((value->op == OpNegate) || (value->op == OpUnaryPlus))
746 {
747 act->flags &= ~XkbSA_DfltBtnAbsolute;
748 btn = value->value.child;
749 }
750 else
751 {
752 act->flags |= XkbSA_DfltBtnAbsolute;
753 btn = value;
754 }
755
756 if (!ExprResolveInteger
757 (btn, &rtrn, SimpleLookup, (XPointer) btnNames))
758 return ReportMismatch(action->type, field,
759 "integer (range 1..5)");
760 if ((rtrn.ival < 0) || (rtrn.ival > 5))
761 {
762 ERROR("New default button value must be in the range 1..5\n");
763 ACTION("Illegal default button value %d ignored\n", rtrn.ival);
764 return False;
765 }
766 if (rtrn.ival == 0)
767 {
768 ERROR("Cannot set default pointer button to \"default\"\n");
769 ACTION("Illegal default button setting ignored\n");
770 return False;
771 }
772 if (value->op == OpNegate)
773 XkbSASetPtrDfltValue(act, -rtrn.ival);
774 else
775 XkbSASetPtrDfltValue(act, rtrn.ival);
776 return True;
777 }
778 return ReportIllegal(action->type, field);
779 }
780
781 static LookupEntry isoNames[] = {
782 {"mods", XkbSA_ISONoAffectMods},
783 {"modifiers", XkbSA_ISONoAffectMods},
784 {"group", XkbSA_ISONoAffectGroup},
785 {"groups", XkbSA_ISONoAffectGroup},
786 {"ptr", XkbSA_ISONoAffectPtr},
787 {"pointer", XkbSA_ISONoAffectPtr},
788 {"ctrls", XkbSA_ISONoAffectCtrls},
789 {"controls", XkbSA_ISONoAffectCtrls},
790 {"all", XkbSA_ISOAffectMask},
791 {"none", 0},
792 {"both", 0},
793 {"lock", XkbSA_LockNoUnlock},
794 {"neither", (XkbSA_LockNoLock | XkbSA_LockNoUnlock)},
795 {"unlock", XkbSA_LockNoLock},
796 {NULL, 0},
797 };
798
799 static Bool
HandleISOLock(XkbDescPtr xkb,XkbAnyAction * action,unsigned field,ExprDef * array_ndx,ExprDef * value)800 HandleISOLock(XkbDescPtr xkb,
801 XkbAnyAction * action,
802 unsigned field, ExprDef * array_ndx, ExprDef * value)
803 {
804 ExprResult rtrn;
805 XkbISOAction *act;
806 unsigned flags, mods;
807 int group;
808
809 act = (XkbISOAction *) action;
810 switch (field)
811 {
812 case F_Modifiers:
813 if (array_ndx != NULL)
814 return ReportActionNotArray(action->type, field);
815 flags = act->flags;
816 if (CheckModifierField(xkb, action->type, value, &flags, &mods))
817 {
818 act->flags = flags & (~XkbSA_ISODfltIsGroup);
819 act->real_mods = act->mask = (mods & 0xff);
820 mods = (mods >> 8) & 0xffff;
821 XkbSetModActionVMods(act, mods);
822 return True;
823 }
824 return False;
825 case F_Group:
826 if (array_ndx != NULL)
827 return ReportActionNotArray(action->type, field);
828 flags = act->flags;
829 if (CheckGroupField(action->type, value, &flags, &group))
830 {
831 act->flags = flags | XkbSA_ISODfltIsGroup;
832 XkbSASetGroup(act, group);
833 return True;
834 }
835 return False;
836 case F_Affect:
837 if (array_ndx != NULL)
838 return ReportActionNotArray(action->type, field);
839 if (!ExprResolveMask(value, &rtrn, SimpleLookup, (XPointer) isoNames))
840 return ReportMismatch(action->type, field, "keyboard component");
841 act->affect = (~rtrn.uval) & XkbSA_ISOAffectMask;
842 act->flags &= ~(XkbSA_LockNoLock | XkbSA_LockNoUnlock);
843 act->flags |= rtrn.uval & (XkbSA_LockNoLock | XkbSA_LockNoUnlock);
844 return True;
845 }
846 return ReportIllegal(action->type, field);
847 }
848
849 static Bool
HandleSwitchScreen(XkbDescPtr xkb,XkbAnyAction * action,unsigned field,ExprDef * array_ndx,ExprDef * value)850 HandleSwitchScreen(XkbDescPtr xkb,
851 XkbAnyAction * action,
852 unsigned field, ExprDef * array_ndx, ExprDef * value)
853 {
854 ExprResult rtrn;
855 XkbSwitchScreenAction *act;
856
857 act = (XkbSwitchScreenAction *) action;
858 if (field == F_Screen)
859 {
860 ExprDef *scrn;
861 if (array_ndx != NULL)
862 return ReportActionNotArray(action->type, field);
863 if ((value->op == OpNegate) || (value->op == OpUnaryPlus))
864 {
865 act->flags &= ~XkbSA_SwitchAbsolute;
866 scrn = value->value.child;
867 }
868 else
869 {
870 act->flags |= XkbSA_SwitchAbsolute;
871 scrn = value;
872 }
873
874 if (!ExprResolveInteger(scrn, &rtrn, NULL, NULL))
875 return ReportMismatch(action->type, field, "integer (0..255)");
876 if ((rtrn.ival < 0) || (rtrn.ival > 255))
877 {
878 ERROR("Screen index must be in the range 1..255\n");
879 ACTION("Illegal screen value %d ignored\n", rtrn.ival);
880 return False;
881 }
882 if (value->op == OpNegate)
883 XkbSASetScreen(act, -rtrn.ival);
884 else
885 XkbSASetScreen(act, rtrn.ival);
886 return True;
887 }
888 else if (field == F_Same)
889 {
890 if (array_ndx != NULL)
891 return ReportActionNotArray(action->type, field);
892 if (!ExprResolveBoolean(value, &rtrn, NULL, NULL))
893 return ReportMismatch(action->type, field, "boolean");
894 if (rtrn.uval)
895 act->flags &= ~XkbSA_SwitchApplication;
896 else
897 act->flags |= XkbSA_SwitchApplication;
898 return True;
899 }
900 return ReportIllegal(action->type, field);
901 }
902
903 LookupEntry ctrlNames[] = {
904 {"repeatkeys", XkbRepeatKeysMask}
905 ,
906 {"repeat", XkbRepeatKeysMask}
907 ,
908 {"autorepeat", XkbRepeatKeysMask}
909 ,
910 {"slowkeys", XkbSlowKeysMask}
911 ,
912 {"bouncekeys", XkbBounceKeysMask}
913 ,
914 {"stickykeys", XkbStickyKeysMask}
915 ,
916 {"mousekeys", XkbMouseKeysMask}
917 ,
918 {"mousekeysaccel", XkbMouseKeysAccelMask}
919 ,
920 {"accessxkeys", XkbAccessXKeysMask}
921 ,
922 {"accessxtimeout", XkbAccessXTimeoutMask}
923 ,
924 {"accessxfeedback", XkbAccessXFeedbackMask}
925 ,
926 {"audiblebell", XkbAudibleBellMask}
927 ,
928 {"overlay1", XkbOverlay1Mask}
929 ,
930 {"overlay2", XkbOverlay2Mask}
931 ,
932 {"ignoregrouplock", XkbIgnoreGroupLockMask}
933 ,
934 {"all", XkbAllBooleanCtrlsMask}
935 ,
936 {"none", 0}
937 ,
938 {NULL, 0}
939 };
940
941 static Bool
HandleSetLockControls(XkbDescPtr xkb,XkbAnyAction * action,unsigned field,ExprDef * array_ndx,ExprDef * value)942 HandleSetLockControls(XkbDescPtr xkb,
943 XkbAnyAction * action,
944 unsigned field, ExprDef * array_ndx, ExprDef * value)
945 {
946 ExprResult rtrn;
947 XkbCtrlsAction *act;
948
949 act = (XkbCtrlsAction *) action;
950 if (field == F_Controls)
951 {
952 if (array_ndx != NULL)
953 return ReportActionNotArray(action->type, field);
954 if (!ExprResolveMask
955 (value, &rtrn, SimpleLookup, (XPointer) ctrlNames))
956 return ReportMismatch(action->type, field, "controls mask");
957 XkbActionSetCtrls(act, rtrn.uval);
958 return True;
959 }
960 else if (field == F_Affect && action->type == XkbSA_LockControls) {
961 if (array_ndx != NULL)
962 return ReportActionNotArray(action->type, field);
963 if (!ExprResolveEnum(value, &rtrn, lockWhich))
964 return ReportMismatch(action->type, field, "lock or unlock");
965 act->flags &= ~(XkbSA_LockNoLock | XkbSA_LockNoUnlock);
966 act->flags |= rtrn.uval;
967 return True;
968 }
969 return ReportIllegal(action->type, field);
970 }
971
972 static LookupEntry evNames[] = {
973 {"press", XkbSA_MessageOnPress},
974 {"keypress", XkbSA_MessageOnPress},
975 {"release", XkbSA_MessageOnRelease},
976 {"keyrelease", XkbSA_MessageOnRelease},
977 {"all", XkbSA_MessageOnPress | XkbSA_MessageOnRelease},
978 {"none", 0},
979 {NULL, 0}
980 };
981
982 static Bool
HandleActionMessage(XkbDescPtr xkb,XkbAnyAction * action,unsigned field,ExprDef * array_ndx,ExprDef * value)983 HandleActionMessage(XkbDescPtr xkb,
984 XkbAnyAction * action,
985 unsigned field, ExprDef * array_ndx, ExprDef * value)
986 {
987 ExprResult rtrn;
988 XkbMessageAction *act;
989
990 act = (XkbMessageAction *) action;
991 switch (field)
992 {
993 case F_Report:
994 if (array_ndx != NULL)
995 return ReportActionNotArray(action->type, field);
996 if (!ExprResolveMask(value, &rtrn, SimpleLookup, (XPointer) evNames))
997 return ReportMismatch(action->type, field, "key event mask");
998 act->flags &= ~(XkbSA_MessageOnPress | XkbSA_MessageOnRelease);
999 act->flags =
1000 rtrn.uval & (XkbSA_MessageOnPress | XkbSA_MessageOnRelease);
1001 return True;
1002 case F_GenKeyEvent:
1003 if (array_ndx != NULL)
1004 return ReportActionNotArray(action->type, field);
1005 if (!ExprResolveBoolean(value, &rtrn, NULL, NULL))
1006 return ReportMismatch(action->type, field, "boolean");
1007 if (rtrn.uval)
1008 act->flags |= XkbSA_MessageGenKeyEvent;
1009 else
1010 act->flags &= ~XkbSA_MessageGenKeyEvent;
1011 return True;
1012 case F_Data:
1013 if (array_ndx == NULL)
1014 {
1015 if (!ExprResolveString(value, &rtrn, NULL, NULL))
1016 return ReportMismatch(action->type, field, "string");
1017 else
1018 {
1019 int len = strlen(rtrn.str);
1020 if ((len < 1) || (len > 6))
1021 {
1022 WARN("An action message can hold only 6 bytes\n");
1023 ACTION("Extra %d bytes ignored\n", len - 6);
1024 }
1025 strncpy((char *) act->message, rtrn.str, 6);
1026 }
1027 return True;
1028 }
1029 else
1030 {
1031 unsigned ndx;
1032 if (!ExprResolveInteger(array_ndx, &rtrn, NULL, NULL))
1033 {
1034 ERROR("Array subscript must be integer\n");
1035 ACTION("Illegal subscript ignored\n");
1036 return False;
1037 }
1038 ndx = rtrn.uval;
1039 if (ndx > 5)
1040 {
1041 ERROR("An action message is at most 6 bytes long\n");
1042 ACTION("Attempt to use data[%d] ignored\n", ndx);
1043 return False;
1044 }
1045 if (!ExprResolveInteger(value, &rtrn, NULL, NULL))
1046 return ReportMismatch(action->type, field, "integer");
1047 if ((rtrn.ival < 0) || (rtrn.ival > 255))
1048 {
1049 ERROR("Message data must be in the range 0..255\n");
1050 ACTION("Illegal datum %d ignored\n", rtrn.ival);
1051 return False;
1052 }
1053 act->message[ndx] = rtrn.uval;
1054 }
1055 return True;
1056 }
1057 return ReportIllegal(action->type, field);
1058 }
1059
1060 static Bool
HandleRedirectKey(XkbDescPtr xkb,XkbAnyAction * action,unsigned field,ExprDef * array_ndx,ExprDef * value)1061 HandleRedirectKey(XkbDescPtr xkb,
1062 XkbAnyAction * action,
1063 unsigned field, ExprDef * array_ndx, ExprDef * value)
1064 {
1065 ExprResult rtrn;
1066 XkbRedirectKeyAction *act;
1067 unsigned t1, t2, vmods, vmask;
1068 unsigned long tmp;
1069
1070 if (array_ndx != NULL)
1071 return ReportActionNotArray(action->type, field);
1072
1073 act = (XkbRedirectKeyAction *) action;
1074 switch (field)
1075 {
1076 case F_Keycode:
1077 if (!ExprResolveKeyName(value, &rtrn, NULL, NULL))
1078 return ReportMismatch(action->type, field, "key name");
1079 tmp = KeyNameToLong(rtrn.keyName.name);
1080 if (!FindNamedKey(xkb, tmp, &t1, True, CreateKeyNames(xkb), 0))
1081 {
1082 return ReportNotFound(action->type, field, "Key",
1083 XkbKeyNameText(rtrn.keyName.name,
1084 XkbMessage));
1085 }
1086 act->new_key = t1;
1087 return True;
1088 case F_ModsToClear:
1089 case F_Modifiers:
1090 t1 = 0;
1091 if (CheckModifierField(xkb, action->type, value, &t1, &t2))
1092 {
1093 act->mods_mask |= (t2 & 0xff);
1094 if (field == F_Modifiers)
1095 act->mods |= (t2 & 0xff);
1096 else
1097 act->mods &= ~(t2 & 0xff);
1098
1099 t2 = (t2 >> 8) & 0xffff;
1100 vmods = XkbSARedirectVMods(act);
1101 vmask = XkbSARedirectVModsMask(act);
1102 vmask |= t2;
1103 if (field == F_Modifiers)
1104 vmods |= t2;
1105 else
1106 vmods &= ~t2;
1107 XkbSARedirectSetVMods(act, vmods);
1108 XkbSARedirectSetVModsMask(act, vmask);
1109 return True;
1110 }
1111 return True;
1112 }
1113 return ReportIllegal(action->type, field);
1114 }
1115
1116 static Bool
HandleDeviceBtn(XkbDescPtr xkb,XkbAnyAction * action,unsigned field,ExprDef * array_ndx,ExprDef * value)1117 HandleDeviceBtn(XkbDescPtr xkb,
1118 XkbAnyAction * action,
1119 unsigned field, ExprDef * array_ndx, ExprDef * value)
1120 {
1121 ExprResult rtrn;
1122 XkbDeviceBtnAction *act;
1123
1124 act = (XkbDeviceBtnAction *) action;
1125 if (field == F_Button)
1126 {
1127 if (array_ndx != NULL)
1128 return ReportActionNotArray(action->type, field);
1129 if (!ExprResolveInteger(value, &rtrn, NULL, NULL))
1130 return ReportMismatch(action->type, field,
1131 "integer (range 1..255)");
1132 if ((rtrn.ival < 0) || (rtrn.ival > 255))
1133 {
1134 ERROR("Button must specify default or be in the range 1..255\n");
1135 ACTION("Illegal button value %d ignored\n", rtrn.ival);
1136 return False;
1137 }
1138 act->button = rtrn.ival;
1139 return True;
1140 }
1141 else if ((action->type == XkbSA_LockDeviceBtn) && (field == F_Affect))
1142 {
1143 if (array_ndx != NULL)
1144 return ReportActionNotArray(action->type, field);
1145 if (!ExprResolveEnum(value, &rtrn, lockWhich))
1146 return ReportMismatch(action->type, field, "lock or unlock");
1147 act->flags &= ~(XkbSA_LockNoLock | XkbSA_LockNoUnlock);
1148 act->flags |= rtrn.uval;
1149 return True;
1150 }
1151 else if (field == F_Count)
1152 {
1153 if (array_ndx != NULL)
1154 return ReportActionNotArray(action->type, field);
1155 if (!ExprResolveInteger
1156 (value, &rtrn, SimpleLookup, (XPointer) btnNames))
1157 return ReportMismatch(action->type, field, "integer");
1158 if ((rtrn.ival < 0) || (rtrn.ival > 255))
1159 {
1160 ERROR("The count field must have a value in the range 0..255\n");
1161 ACTION("Illegal count %d ignored\n", rtrn.ival);
1162 return False;
1163 }
1164 act->count = rtrn.ival;
1165 return True;
1166 }
1167 else if (field == F_Device)
1168 {
1169 if (array_ndx != NULL)
1170 return ReportActionNotArray(action->type, field);
1171 if (!ExprResolveInteger(value, &rtrn, NULL, NULL))
1172 return ReportMismatch(action->type, field,
1173 "integer (range 1..255)");
1174 if ((rtrn.ival < 0) || (rtrn.ival > 255))
1175 {
1176 ERROR("Device must specify default or be in the range 1..255\n");
1177 ACTION("Illegal device value %d ignored\n", rtrn.ival);
1178 return False;
1179 }
1180 act->device = rtrn.ival;
1181 return True;
1182 }
1183 return ReportIllegal(action->type, field);
1184 }
1185
1186 static Bool
HandleDeviceValuator(XkbDescPtr xkb,XkbAnyAction * action,unsigned field,ExprDef * array_ndx,ExprDef * value)1187 HandleDeviceValuator(XkbDescPtr xkb,
1188 XkbAnyAction * action,
1189 unsigned field, ExprDef * array_ndx, ExprDef * value)
1190 {
1191 #if 0
1192 ExprResult rtrn;
1193 XkbDeviceValuatorAction *act;
1194
1195 act = (XkbDeviceValuatorAction *) action;
1196 /* XXX - Not yet implemented */
1197 #endif
1198 return False;
1199 }
1200
1201 static Bool
HandlePrivate(XkbDescPtr xkb,XkbAnyAction * action,unsigned field,ExprDef * array_ndx,ExprDef * value)1202 HandlePrivate(XkbDescPtr xkb,
1203 XkbAnyAction * action,
1204 unsigned field, ExprDef * array_ndx, ExprDef * value)
1205 {
1206 ExprResult rtrn;
1207
1208 switch (field)
1209 {
1210 case F_Type:
1211 if (!ExprResolveInteger(value, &rtrn, NULL, NULL))
1212 return ReportMismatch(PrivateAction, field, "integer");
1213 if ((rtrn.ival < 0) || (rtrn.ival > 255))
1214 {
1215 ERROR("Private action type must be in the range 0..255\n");
1216 ACTION("Illegal type %d ignored\n", rtrn.ival);
1217 return False;
1218 }
1219 action->type = rtrn.uval;
1220 return True;
1221 case F_Data:
1222 if (array_ndx == NULL)
1223 {
1224 if (!ExprResolveString(value, &rtrn, NULL, NULL))
1225 return ReportMismatch(action->type, field, "string");
1226 else
1227 {
1228 int len = strlen(rtrn.str);
1229 if ((len < 1) || (len > 7))
1230 {
1231 WARN("A private action has 7 data bytes\n");
1232 ACTION("Extra %d bytes ignored\n", len - 6);
1233 return False;
1234 }
1235 strncpy((char *) action->data, rtrn.str, 7);
1236 }
1237 return True;
1238 }
1239 else
1240 {
1241 unsigned ndx;
1242 if (!ExprResolveInteger(array_ndx, &rtrn, NULL, NULL))
1243 {
1244 ERROR("Array subscript must be integer\n");
1245 ACTION("Illegal subscript ignored\n");
1246 return False;
1247 }
1248 ndx = rtrn.uval;
1249 if (ndx > 6)
1250 {
1251 ERROR("The data for a private action is 7 bytes long\n");
1252 ACTION("Attempt to use data[%d] ignored\n", ndx);
1253 return False;
1254 }
1255 if (!ExprResolveInteger(value, &rtrn, NULL, NULL))
1256 return ReportMismatch(action->type, field, "integer");
1257 if ((rtrn.ival < 0) || (rtrn.ival > 255))
1258 {
1259 ERROR("All data for a private action must be 0..255\n");
1260 ACTION("Illegal datum %d ignored\n", rtrn.ival);
1261 return False;
1262 }
1263 action->data[ndx] = rtrn.uval;
1264 return True;
1265 }
1266 }
1267 return ReportIllegal(PrivateAction, field);
1268 }
1269
1270 typedef Bool(*actionHandler) (XkbDescPtr /* xkb */ ,
1271 XkbAnyAction * /* action */ ,
1272 unsigned /* field */ ,
1273 ExprDef * /* array_ndx */ ,
1274 ExprDef * /* value */
1275 );
1276
1277 static actionHandler handleAction[XkbSA_NumActions + 1] = {
1278 HandleNoAction /* NoAction */ ,
1279 HandleSetLatchMods /* SetMods */ ,
1280 HandleSetLatchMods /* LatchMods */ ,
1281 HandleLockMods /* LockMods */ ,
1282 HandleSetLatchGroup /* SetGroup */ ,
1283 HandleSetLatchGroup /* LatchGroup */ ,
1284 HandleLockGroup /* LockGroup */ ,
1285 HandleMovePtr /* MovePtr */ ,
1286 HandlePtrBtn /* PtrBtn */ ,
1287 HandlePtrBtn /* LockPtrBtn */ ,
1288 HandleSetPtrDflt /* SetPtrDflt */ ,
1289 HandleISOLock /* ISOLock */ ,
1290 HandleNoAction /* Terminate */ ,
1291 HandleSwitchScreen /* SwitchScreen */ ,
1292 HandleSetLockControls /* SetControls */ ,
1293 HandleSetLockControls /* LockControls */ ,
1294 HandleActionMessage /* ActionMessage */ ,
1295 HandleRedirectKey /* RedirectKey */ ,
1296 HandleDeviceBtn /* DeviceBtn */ ,
1297 HandleDeviceBtn /* LockDeviceBtn */ ,
1298 HandleDeviceValuator /* DeviceValuatr */ ,
1299 HandlePrivate /* Private */
1300 };
1301
1302 /***====================================================================***/
1303
1304 static void
ApplyActionFactoryDefaults(XkbAction * action)1305 ApplyActionFactoryDefaults(XkbAction * action)
1306 {
1307 if (action->type == XkbSA_SetPtrDflt)
1308 { /* increment default button */
1309 action->dflt.affect = XkbSA_AffectDfltBtn;
1310 action->dflt.flags = 0;
1311 XkbSASetPtrDfltValue(&action->dflt, 1);
1312 }
1313 else if (action->type == XkbSA_ISOLock)
1314 {
1315 action->iso.real_mods = action->iso.mask = LockMask;
1316 }
1317 return;
1318 }
1319
1320
1321 int
HandleActionDef(ExprDef * def,XkbDescPtr xkb,XkbAnyAction * action,unsigned mergeMode,ActionInfo * info)1322 HandleActionDef(ExprDef * def,
1323 XkbDescPtr xkb,
1324 XkbAnyAction * action, unsigned mergeMode, ActionInfo * info)
1325 {
1326 ExprDef *arg;
1327 register char *str;
1328 unsigned tmp, hndlrType;
1329
1330 if (!actionsInitialized)
1331 ActionsInit();
1332
1333 if (def->op != ExprActionDecl)
1334 {
1335 ERROR("Expected an action definition, found %s\n",
1336 exprOpText(def->op));
1337 return False;
1338 }
1339 str = XkbAtomGetString(NULL, def->value.action.name);
1340 if (!str)
1341 {
1342 WSGO("Missing name in action definition!!\n");
1343 return False;
1344 }
1345 if (!stringToAction(str, &tmp))
1346 {
1347 ERROR("Unknown action %s\n", str);
1348 return False;
1349 }
1350 action->type = hndlrType = tmp;
1351 if (action->type != XkbSA_NoAction)
1352 {
1353 ApplyActionFactoryDefaults((XkbAction *) action);
1354 while (info)
1355 {
1356 if ((info->action == XkbSA_NoAction)
1357 || (info->action == hndlrType))
1358 {
1359 if (!(*handleAction[hndlrType]) (xkb, action,
1360 info->field,
1361 info->array_ndx,
1362 info->value))
1363 {
1364 return False;
1365 }
1366 }
1367 info = info->next;
1368 }
1369 }
1370 for (arg = def->value.action.args; arg != NULL;
1371 arg = (ExprDef *) arg->common.next)
1372 {
1373 ExprDef *field, *value, *arrayRtrn;
1374 ExprResult elemRtrn, fieldRtrn;
1375 unsigned fieldNdx;
1376
1377 if (arg->op == OpAssign)
1378 {
1379 field = arg->value.binary.left;
1380 value = arg->value.binary.right;
1381 }
1382 else
1383 {
1384 if ((arg->op == OpNot) || (arg->op == OpInvert))
1385 {
1386 field = arg->value.child;
1387 value = &constFalse;
1388 }
1389 else
1390 {
1391 field = arg;
1392 value = &constTrue;
1393 }
1394 }
1395 if (!ExprResolveLhs(field, &elemRtrn, &fieldRtrn, &arrayRtrn))
1396 return False; /* internal error -- already reported */
1397
1398 if (elemRtrn.str != NULL)
1399 {
1400 ERROR("Cannot change defaults in an action definition\n");
1401 ACTION("Ignoring attempt to change %s.%s\n", elemRtrn.str,
1402 fieldRtrn.str);
1403 return False;
1404 }
1405 if (!stringToField(fieldRtrn.str, &fieldNdx))
1406 {
1407 ERROR("Unknown field name %s\n", uStringText(fieldRtrn.str));
1408 return False;
1409 }
1410 if (!(*handleAction[hndlrType])
1411 (xkb, action, fieldNdx, arrayRtrn, value))
1412 {
1413 return False;
1414 }
1415 }
1416 return True;
1417 }
1418
1419 /***====================================================================***/
1420
1421 int
SetActionField(XkbDescPtr xkb,const char * elem,const char * field,ExprDef * array_ndx,ExprDef * value,ActionInfo ** info_rtrn)1422 SetActionField(XkbDescPtr xkb,
1423 const char *elem,
1424 const char *field,
1425 ExprDef * array_ndx, ExprDef * value, ActionInfo ** info_rtrn)
1426 {
1427 ActionInfo *new, *old;
1428
1429 if (!actionsInitialized)
1430 ActionsInit();
1431
1432 new = uTypedAlloc(ActionInfo);
1433 if (new == NULL)
1434 {
1435 WSGO("Couldn't allocate space for action default\n");
1436 return False;
1437 }
1438 if (uStrCaseCmp(elem, "action") == 0)
1439 new->action = XkbSA_NoAction;
1440 else
1441 {
1442 if (!stringToAction(elem, &new->action))
1443 return False;
1444 if (new->action == XkbSA_NoAction)
1445 {
1446 ERROR("\"%s\" is not a valid field in a NoAction action\n",
1447 field);
1448 return False;
1449 }
1450 }
1451 if (!stringToField(field, &new->field))
1452 {
1453 ERROR("\"%s\" is not a legal field name\n", field);
1454 return False;
1455 }
1456 new->array_ndx = array_ndx;
1457 new->value = value;
1458 new->next = NULL;
1459 old = *info_rtrn;
1460 while ((old) && (old->next))
1461 old = old->next;
1462 if (old == NULL)
1463 *info_rtrn = new;
1464 else
1465 old->next = new;
1466 return True;
1467 }
1468
1469 /***====================================================================***/
1470
1471 void
ActionsInit(void)1472 ActionsInit(void)
1473 {
1474 if (!actionsInitialized)
1475 {
1476 bzero((char *) &constTrue, sizeof(constTrue));
1477 bzero((char *) &constFalse, sizeof(constFalse));
1478 constTrue.common.stmtType = StmtExpr;
1479 constTrue.common.next = NULL;
1480 constTrue.op = ExprIdent;
1481 constTrue.type = TypeBoolean;
1482 constTrue.value.str = XkbInternAtom(NULL, "true", False);
1483 constFalse.common.stmtType = StmtExpr;
1484 constFalse.common.next = NULL;
1485 constFalse.op = ExprIdent;
1486 constFalse.type = TypeBoolean;
1487 constFalse.value.str = XkbInternAtom(NULL, "false", False);
1488 actionsInitialized = 1;
1489 }
1490 return;
1491 }
1492