1 /************************************************************
2 Copyright (c) 1994 by Silicon Graphics Computer Systems, Inc.
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.
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.
25 ********************************************************/
30 static bool actionsInitialized;
31 static ExprDef constTrue;
32 static ExprDef constFalse;
34 /***====================================================================***/
36 static const LookupEntry actionStrings[] = {
37 { "noaction", XkbSA_NoAction },
38 { "setmods", XkbSA_SetMods },
39 { "latchmods", XkbSA_LatchMods },
40 { "lockmods", XkbSA_LockMods },
41 { "setgroup", XkbSA_SetGroup },
42 { "latchgroup", XkbSA_LatchGroup },
43 { "lockgroup", XkbSA_LockGroup },
44 { "moveptr", XkbSA_MovePtr },
45 { "movepointer", XkbSA_MovePtr },
46 { "ptrbtn", XkbSA_PtrBtn },
47 { "pointerbutton", XkbSA_PtrBtn },
48 { "lockptrbtn", XkbSA_LockPtrBtn },
49 { "lockpointerbutton", XkbSA_LockPtrBtn },
50 { "lockptrbutton", XkbSA_LockPtrBtn },
51 { "lockpointerbtn", XkbSA_LockPtrBtn },
52 { "setptrdflt", XkbSA_SetPtrDflt },
53 { "setpointerdefault", XkbSA_SetPtrDflt },
54 { "isolock", XkbSA_ISOLock },
55 { "terminate", XkbSA_Terminate },
56 { "terminateserver", XkbSA_Terminate },
57 { "switchscreen", XkbSA_SwitchScreen },
58 { "setcontrols", XkbSA_SetControls },
59 { "lockcontrols", XkbSA_LockControls },
60 { "actionmessage", XkbSA_ActionMessage },
61 { "messageaction", XkbSA_ActionMessage },
62 { "message", XkbSA_ActionMessage },
63 { "redirect", XkbSA_RedirectKey },
64 { "redirectkey", XkbSA_RedirectKey },
65 { "devbtn", XkbSA_DeviceBtn },
66 { "devicebtn", XkbSA_DeviceBtn },
67 { "devbutton", XkbSA_DeviceBtn },
68 { "devicebutton", XkbSA_DeviceBtn },
69 { "lockdevbtn", XkbSA_DeviceBtn },
70 { "lockdevicebtn", XkbSA_LockDeviceBtn },
71 { "lockdevbutton", XkbSA_LockDeviceBtn },
72 { "lockdevicebutton", XkbSA_LockDeviceBtn },
73 { "devval", XkbSA_DeviceValuator },
74 { "deviceval", XkbSA_DeviceValuator },
75 { "devvaluator", XkbSA_DeviceValuator },
76 { "devicevaluator", XkbSA_DeviceValuator },
77 { "private", PrivateAction },
81 static const LookupEntry fieldStrings[] = {
82 { "clearLocks", F_ClearLocks },
83 { "latchToLock", F_LatchToLock },
84 { "genKeyEvent", F_GenKeyEvent },
85 { "generateKeyEvent", F_GenKeyEvent },
86 { "report", F_Report },
87 { "default", F_Default },
88 { "affect", F_Affect },
89 { "increment", F_Increment },
90 { "modifiers", F_Modifiers },
91 { "mods", F_Modifiers },
96 { "accelerate", F_Accel },
97 { "repeat", F_Accel },
98 { "button", F_Button },
100 { "controls", F_Controls },
101 { "ctrls", F_Controls },
103 { "count", F_Count },
104 { "screen", F_Screen },
106 { "sameServer", F_Same },
108 { "device", F_Device },
110 { "key", F_Keycode },
111 { "keycode", F_Keycode },
113 { "clearmods", F_ModsToClear },
114 { "clearmodifiers", F_ModsToClear },
119 stringToValue(const LookupEntry tab[], const char *string,
120 unsigned *value_rtrn)
122 const LookupEntry *entry;
127 for (entry = tab; entry->name != NULL; entry++) {
128 if (strcasecmp(entry->name, string) == 0) {
129 *value_rtrn = entry->result;
138 valueToString(const LookupEntry tab[], unsigned value)
140 const LookupEntry *entry;
142 for (entry = tab; entry->name != NULL; entry++)
143 if (entry->result == value)
150 stringToAction(const char *str, unsigned *type_rtrn)
152 return stringToValue(actionStrings, str, type_rtrn);
156 stringToField(const char *str, unsigned *field_rtrn)
158 return stringToValue(fieldStrings, str, field_rtrn);
162 fieldText(unsigned field)
164 return valueToString(fieldStrings, field);
167 /***====================================================================***/
170 ReportMismatch(unsigned action, unsigned field, const char *type)
172 ERROR("Value of %s field must be of type %s\n", fieldText(field), type);
173 ACTION("Action %s definition ignored\n", XkbcActionTypeText(action));
178 ReportIllegal(unsigned action, unsigned field)
180 ERROR("Field %s is not defined for an action of type %s\n",
181 fieldText(field), XkbcActionTypeText(action));
182 ACTION("Action definition ignored\n");
187 ReportActionNotArray(unsigned action, unsigned field)
189 ERROR("The %s field in the %s action is not an array\n",
190 fieldText(field), XkbcActionTypeText(action));
191 ACTION("Action definition ignored\n");
196 ReportNotFound(unsigned action, unsigned field, const char *what,
199 ERROR("%s named %s not found\n", what, bad);
200 ACTION("Ignoring the %s field of an %s action\n", fieldText(field),
201 XkbcActionTypeText(action));
206 HandleNoAction(struct xkb_keymap * xkb,
207 struct xkb_any_action * action,
208 unsigned field, ExprDef * array_ndx, ExprDef * value)
210 return ReportIllegal(action->type, field);
214 CheckLatchLockFlags(unsigned action,
215 unsigned field, ExprDef * value, unsigned *flags_inout)
220 if (field == F_ClearLocks)
221 tmp = XkbSA_ClearLocks;
222 else if (field == F_LatchToLock)
223 tmp = XkbSA_LatchToLock;
225 return false; /* WSGO! */
226 if (!ExprResolveBoolean(value, &result))
227 return ReportMismatch(action, field, "boolean");
231 *flags_inout &= ~tmp;
236 CheckModifierField(struct xkb_keymap * xkb,
239 unsigned *flags_inout, unsigned *mods_rtrn)
243 if (value->op == ExprIdent)
246 valStr = XkbcAtomText(value->value.str);
247 if (valStr && ((strcasecmp(valStr, "usemodmapmods") == 0) ||
248 (strcasecmp(valStr, "modmapmods") == 0)))
252 *flags_inout |= XkbSA_UseModMapMods;
256 if (!ExprResolveVModMask(value, &rtrn, xkb))
257 return ReportMismatch(action, F_Modifiers, "modifier mask");
258 *mods_rtrn = rtrn.uval;
259 *flags_inout &= ~XkbSA_UseModMapMods;
264 HandleSetLatchMods(struct xkb_keymap * xkb,
265 struct xkb_any_action * action,
266 unsigned field, ExprDef * array_ndx, ExprDef * value)
268 struct xkb_mod_action *act;
272 act = (struct xkb_mod_action *) action;
273 if (array_ndx != NULL)
280 return ReportActionNotArray(action->type, field);
288 if (CheckLatchLockFlags(action->type, field, value, &rtrn))
296 if (CheckModifierField(xkb, action->type, value, &t1, &t2))
299 act->real_mods = act->mask = (t2 & 0xff);
300 act->vmods = (t2 >> 8) & 0xffff;
305 return ReportIllegal(action->type, field);
309 HandleLockMods(struct xkb_keymap * xkb,
310 struct xkb_any_action * action,
311 unsigned field, ExprDef * array_ndx, ExprDef * value)
313 struct xkb_mod_action *act;
316 act = (struct xkb_mod_action *) action;
317 if ((array_ndx != NULL) && (field == F_Modifiers))
318 return ReportActionNotArray(action->type, field);
323 if (CheckModifierField(xkb, action->type, value, &t1, &t2))
326 act->real_mods = act->mask = (t2 & 0xff);
327 act->vmods = (t2 >> 8) & 0xffff;
332 return ReportIllegal(action->type, field);
336 CheckGroupField(unsigned action,
337 ExprDef * value, unsigned *flags_inout, int *grp_rtrn)
342 if ((value->op == OpNegate) || (value->op == OpUnaryPlus))
344 *flags_inout &= ~XkbSA_GroupAbsolute;
345 spec = value->value.child;
349 *flags_inout |= XkbSA_GroupAbsolute;
353 if (!ExprResolveGroup(spec, &rtrn))
354 return ReportMismatch(action, F_Group, "integer (range 1..8)");
355 if (value->op == OpNegate)
356 *grp_rtrn = -rtrn.ival;
357 else if (value->op == OpUnaryPlus)
358 *grp_rtrn = rtrn.ival;
360 *grp_rtrn = rtrn.ival - 1;
365 HandleSetLatchGroup(struct xkb_keymap * xkb,
366 struct xkb_any_action * action,
367 unsigned field, ExprDef * array_ndx, ExprDef * value)
369 struct xkb_group_action *act;
374 act = (struct xkb_group_action *) action;
375 if (array_ndx != NULL)
382 return ReportActionNotArray(action->type, field);
390 if (CheckLatchLockFlags(action->type, field, value, &rtrn))
398 if (CheckGroupField(action->type, value, &t1, &t2))
406 return ReportIllegal(action->type, field);
410 HandleLockGroup(struct xkb_keymap * xkb,
411 struct xkb_any_action * action,
412 unsigned field, ExprDef * array_ndx, ExprDef * value)
414 struct xkb_group_action *act;
418 act = (struct xkb_group_action *) action;
419 if ((array_ndx != NULL) && (field == F_Group))
420 return ReportActionNotArray(action->type, field);
421 if (field == F_Group)
424 if (CheckGroupField(action->type, value, &t1, &t2))
432 return ReportIllegal(action->type, field);
436 HandleMovePtr(struct xkb_keymap * xkb,
437 struct xkb_any_action * action,
438 unsigned field, ExprDef * array_ndx, ExprDef * value)
441 struct xkb_pointer_action *act;
444 act = (struct xkb_pointer_action *) action;
445 if ((array_ndx != NULL) && ((field == F_X) || (field == F_Y)))
446 return ReportActionNotArray(action->type, field);
448 if ((field == F_X) || (field == F_Y))
450 if ((value->op == OpNegate) || (value->op == OpUnaryPlus))
454 if (!ExprResolveInteger(value, &rtrn))
455 return ReportMismatch(action->type, field, "integer");
459 act->flags |= XkbSA_MoveAbsoluteX;
465 act->flags |= XkbSA_MoveAbsoluteY;
470 else if (field == F_Accel)
472 if (!ExprResolveBoolean(value, &rtrn))
473 return ReportMismatch(action->type, field, "boolean");
475 act->flags &= ~XkbSA_NoAcceleration;
477 act->flags |= XkbSA_NoAcceleration;
479 return ReportIllegal(action->type, field);
482 static const LookupEntry lockWhich[] = {
484 {"lock", XkbSA_LockNoUnlock},
485 {"neither", (XkbSA_LockNoLock | XkbSA_LockNoUnlock)},
486 {"unlock", XkbSA_LockNoLock},
491 HandlePtrBtn(struct xkb_keymap * xkb,
492 struct xkb_any_action * action,
493 unsigned field, ExprDef * array_ndx, ExprDef * value)
496 struct xkb_pointer_button_action *act;
498 act = (struct xkb_pointer_button_action *) action;
499 if (field == F_Button)
501 if (array_ndx != NULL)
502 return ReportActionNotArray(action->type, field);
503 if (!ExprResolveButton(value, &rtrn))
504 return ReportMismatch(action->type, field,
505 "integer (range 1..5)");
506 if ((rtrn.ival < 0) || (rtrn.ival > 5))
508 ERROR("Button must specify default or be in the range 1..5\n");
509 ACTION("Illegal button value %d ignored\n", rtrn.ival);
512 act->button = rtrn.ival;
515 else if ((action->type == XkbSA_LockPtrBtn) && (field == F_Affect))
517 if (array_ndx != NULL)
518 return ReportActionNotArray(action->type, field);
519 if (!ExprResolveEnum(value, &rtrn, lockWhich))
520 return ReportMismatch(action->type, field, "lock or unlock");
521 act->flags &= ~(XkbSA_LockNoLock | XkbSA_LockNoUnlock);
522 act->flags |= rtrn.ival;
525 else if (field == F_Count)
527 if (array_ndx != NULL)
528 return ReportActionNotArray(action->type, field);
529 if (!ExprResolveButton(value, &rtrn))
530 return ReportMismatch(action->type, field, "integer");
531 if ((rtrn.ival < 0) || (rtrn.ival > 255))
533 ERROR("The count field must have a value in the range 0..255\n");
534 ACTION("Illegal count %d ignored\n", rtrn.ival);
537 act->count = rtrn.ival;
540 return ReportIllegal(action->type, field);
543 static const LookupEntry ptrDflts[] = {
544 {"dfltbtn", XkbSA_AffectDfltBtn},
545 {"defaultbutton", XkbSA_AffectDfltBtn},
546 {"button", XkbSA_AffectDfltBtn},
551 HandleSetPtrDflt(struct xkb_keymap * xkb,
552 struct xkb_any_action * action,
553 unsigned field, ExprDef * array_ndx, ExprDef * value)
556 struct xkb_pointer_default_action *act;
558 act = (struct xkb_pointer_default_action *) action;
559 if (field == F_Affect)
561 if (array_ndx != NULL)
562 return ReportActionNotArray(action->type, field);
563 if (!ExprResolveEnum(value, &rtrn, ptrDflts))
564 return ReportMismatch(action->type, field, "pointer component");
565 act->affect = rtrn.uval;
568 else if ((field == F_Button) || (field == F_Value))
571 if (array_ndx != NULL)
572 return ReportActionNotArray(action->type, field);
573 if ((value->op == OpNegate) || (value->op == OpUnaryPlus))
575 act->flags &= ~XkbSA_DfltBtnAbsolute;
576 btn = value->value.child;
580 act->flags |= XkbSA_DfltBtnAbsolute;
584 if (!ExprResolveButton(btn, &rtrn))
585 return ReportMismatch(action->type, field,
586 "integer (range 1..5)");
587 if ((rtrn.ival < 0) || (rtrn.ival > 5))
589 ERROR("New default button value must be in the range 1..5\n");
590 ACTION("Illegal default button value %d ignored\n", rtrn.ival);
595 ERROR("Cannot set default pointer button to \"default\"\n");
596 ACTION("Illegal default button setting ignored\n");
599 if (value->op == OpNegate)
600 act->value = -rtrn.ival;
602 act->value = rtrn.ival;
605 return ReportIllegal(action->type, field);
608 static const LookupEntry isoNames[] = {
609 {"mods", XkbSA_ISONoAffectMods},
610 {"modifiers", XkbSA_ISONoAffectMods},
611 {"group", XkbSA_ISONoAffectGroup},
612 {"groups", XkbSA_ISONoAffectGroup},
613 {"ptr", XkbSA_ISONoAffectPtr},
614 {"pointer", XkbSA_ISONoAffectPtr},
615 {"ctrls", XkbSA_ISONoAffectCtrls},
616 {"controls", XkbSA_ISONoAffectCtrls},
617 {"all", ~((unsigned) 0)},
623 HandleISOLock(struct xkb_keymap * xkb,
624 struct xkb_any_action * action,
625 unsigned field, ExprDef * array_ndx, ExprDef * value)
628 struct xkb_iso_action *act;
629 unsigned flags, mods;
632 act = (struct xkb_iso_action *) action;
636 if (array_ndx != NULL)
637 return ReportActionNotArray(action->type, field);
639 if (CheckModifierField(xkb, action->type, value, &flags, &mods))
641 act->flags = flags & (~XkbSA_ISODfltIsGroup);
642 act->real_mods = mods & 0xff;
643 act->vmods = (mods >> 8) & 0xff;
648 if (array_ndx != NULL)
649 return ReportActionNotArray(action->type, field);
651 if (CheckGroupField(action->type, value, &flags, &group))
653 act->flags = flags | XkbSA_ISODfltIsGroup;
659 if (array_ndx != NULL)
660 return ReportActionNotArray(action->type, field);
661 if (!ExprResolveMask(value, &rtrn, isoNames))
662 return ReportMismatch(action->type, field, "keyboard component");
663 act->affect = (~rtrn.uval) & XkbSA_ISOAffectMask;
666 return ReportIllegal(action->type, field);
670 HandleSwitchScreen(struct xkb_keymap * xkb,
671 struct xkb_any_action * action,
672 unsigned field, ExprDef * array_ndx, ExprDef * value)
675 struct xkb_switch_screen_action *act;
677 act = (struct xkb_switch_screen_action *) action;
678 if (field == F_Screen)
681 if (array_ndx != NULL)
682 return ReportActionNotArray(action->type, field);
683 if ((value->op == OpNegate) || (value->op == OpUnaryPlus))
685 act->flags &= ~XkbSA_SwitchAbsolute;
686 scrn = value->value.child;
690 act->flags |= XkbSA_SwitchAbsolute;
694 if (!ExprResolveInteger(scrn, &rtrn))
695 return ReportMismatch(action->type, field, "integer (0..255)");
696 if ((rtrn.ival < 0) || (rtrn.ival > 255))
698 ERROR("Screen index must be in the range 1..255\n");
699 ACTION("Illegal screen value %d ignored\n", rtrn.ival);
702 if (value->op == OpNegate)
703 act->screen = -rtrn.ival;
705 act->screen = rtrn.ival;
708 else if (field == F_Same)
710 if (array_ndx != NULL)
711 return ReportActionNotArray(action->type, field);
712 if (!ExprResolveBoolean(value, &rtrn))
713 return ReportMismatch(action->type, field, "boolean");
715 act->flags &= ~XkbSA_SwitchApplication;
717 act->flags |= XkbSA_SwitchApplication;
720 return ReportIllegal(action->type, field);
723 const LookupEntry ctrlNames[] = {
724 {"repeatkeys", XkbRepeatKeysMask},
725 {"repeat", XkbRepeatKeysMask},
726 {"autorepeat", XkbRepeatKeysMask},
727 {"slowkeys", XkbSlowKeysMask},
728 {"bouncekeys", XkbBounceKeysMask},
729 {"stickykeys", XkbStickyKeysMask},
730 {"mousekeys", XkbMouseKeysMask},
731 {"mousekeysaccel", XkbMouseKeysAccelMask},
732 {"accessxkeys", XkbAccessXKeysMask},
733 {"accessxtimeout", XkbAccessXTimeoutMask},
734 {"accessxfeedback", XkbAccessXFeedbackMask},
735 {"audiblebell", XkbAudibleBellMask},
736 {"ignoregrouplock", XkbIgnoreGroupLockMask},
737 {"all", XkbAllBooleanCtrlsMask},
745 HandleSetLockControls(struct xkb_keymap * xkb,
746 struct xkb_any_action * action,
747 unsigned field, ExprDef * array_ndx, ExprDef * value)
750 struct xkb_controls_action *act;
752 act = (struct xkb_controls_action *) action;
753 if (field == F_Controls)
755 if (array_ndx != NULL)
756 return ReportActionNotArray(action->type, field);
757 if (!ExprResolveMask(value, &rtrn, ctrlNames))
758 return ReportMismatch(action->type, field, "controls mask");
759 act->ctrls = rtrn.uval;
762 return ReportIllegal(action->type, field);
765 static const LookupEntry evNames[] = {
766 {"press", XkbSA_MessageOnPress},
767 {"keypress", XkbSA_MessageOnPress},
768 {"release", XkbSA_MessageOnRelease},
769 {"keyrelease", XkbSA_MessageOnRelease},
770 {"all", XkbSA_MessageOnPress | XkbSA_MessageOnRelease},
776 HandleActionMessage(struct xkb_keymap * xkb,
777 struct xkb_any_action * action,
778 unsigned field, ExprDef * array_ndx, ExprDef * value)
781 struct xkb_message_action *act;
783 act = (struct xkb_message_action *) action;
787 if (array_ndx != NULL)
788 return ReportActionNotArray(action->type, field);
789 if (!ExprResolveMask(value, &rtrn, evNames))
790 return ReportMismatch(action->type, field, "key event mask");
791 act->flags &= ~(XkbSA_MessageOnPress | XkbSA_MessageOnRelease);
793 rtrn.uval & (XkbSA_MessageOnPress | XkbSA_MessageOnRelease);
796 if (array_ndx != NULL)
797 return ReportActionNotArray(action->type, field);
798 if (!ExprResolveBoolean(value, &rtrn))
799 return ReportMismatch(action->type, field, "boolean");
801 act->flags |= XkbSA_MessageGenKeyEvent;
803 act->flags &= ~XkbSA_MessageGenKeyEvent;
806 if (array_ndx == NULL)
808 if (!ExprResolveString(value, &rtrn))
809 return ReportMismatch(action->type, field, "string");
812 int len = strlen(rtrn.str);
813 if ((len < 1) || (len > 6))
815 WARN("An action message can hold only 6 bytes\n");
816 ACTION("Extra %d bytes ignored\n", len - 6);
818 strncpy((char *) act->message, rtrn.str, 6);
825 if (!ExprResolveInteger(array_ndx, &rtrn))
827 ERROR("Array subscript must be integer\n");
828 ACTION("Illegal subscript ignored\n");
834 ERROR("An action message is at most 6 bytes long\n");
835 ACTION("Attempt to use data[%d] ignored\n", ndx);
838 if (!ExprResolveInteger(value, &rtrn))
839 return ReportMismatch(action->type, field, "integer");
840 if ((rtrn.ival < 0) || (rtrn.ival > 255))
842 ERROR("Message data must be in the range 0..255\n");
843 ACTION("Illegal datum %d ignored\n", rtrn.ival);
846 act->message[ndx] = rtrn.uval;
850 return ReportIllegal(action->type, field);
854 HandleRedirectKey(struct xkb_keymap * xkb,
855 struct xkb_any_action * action,
856 unsigned field, ExprDef * array_ndx, ExprDef * value)
859 struct xkb_redirect_key_action *act;
864 if (array_ndx != NULL)
865 return ReportActionNotArray(action->type, field);
867 act = (struct xkb_redirect_key_action *) action;
871 if (!ExprResolveKeyName(value, &rtrn))
872 return ReportMismatch(action->type, field, "key name");
873 tmp = KeyNameToLong(rtrn.keyName.name);
874 if (!FindNamedKey(xkb, tmp, &kc, true, CreateKeyNames(xkb), 0))
876 return ReportNotFound(action->type, field, "Key",
877 XkbcKeyNameText(rtrn.keyName.name));
884 if (CheckModifierField(xkb, action->type, value, &t1, &t2))
886 act->mods_mask |= (t2 & 0xff);
887 if (field == F_Modifiers)
888 act->mods |= (t2 & 0xff);
890 act->mods &= ~(t2 & 0xff);
892 t2 = (t2 >> 8) & 0xffff;
893 act->vmods_mask |= t2;
894 if (field == F_Modifiers)
902 return ReportIllegal(action->type, field);
906 HandleDeviceBtn(struct xkb_keymap * xkb,
907 struct xkb_any_action * action,
908 unsigned field, ExprDef * array_ndx, ExprDef * value)
911 struct xkb_device_button_action *act;
913 act = (struct xkb_device_button_action *) action;
914 if (field == F_Button)
916 if (array_ndx != NULL)
917 return ReportActionNotArray(action->type, field);
918 if (!ExprResolveInteger(value, &rtrn))
919 return ReportMismatch(action->type, field,
920 "integer (range 1..255)");
921 if ((rtrn.ival < 0) || (rtrn.ival > 255))
923 ERROR("Button must specify default or be in the range 1..255\n");
924 ACTION("Illegal button value %d ignored\n", rtrn.ival);
927 act->button = rtrn.ival;
930 else if ((action->type == XkbSA_LockDeviceBtn) && (field == F_Affect))
932 if (array_ndx != NULL)
933 return ReportActionNotArray(action->type, field);
934 if (!ExprResolveEnum(value, &rtrn, lockWhich))
935 return ReportMismatch(action->type, field, "lock or unlock");
936 act->flags &= ~(XkbSA_LockNoLock | XkbSA_LockNoUnlock);
937 act->flags |= rtrn.ival;
940 else if (field == F_Count)
942 if (array_ndx != NULL)
943 return ReportActionNotArray(action->type, field);
944 if (!ExprResolveButton(value, &rtrn))
945 return ReportMismatch(action->type, field, "integer");
946 if ((rtrn.ival < 0) || (rtrn.ival > 255))
948 ERROR("The count field must have a value in the range 0..255\n");
949 ACTION("Illegal count %d ignored\n", rtrn.ival);
952 act->count = rtrn.ival;
955 else if (field == F_Device)
957 if (array_ndx != NULL)
958 return ReportActionNotArray(action->type, field);
959 if (!ExprResolveInteger(value, &rtrn))
960 return ReportMismatch(action->type, field,
961 "integer (range 1..255)");
962 if ((rtrn.ival < 0) || (rtrn.ival > 255))
964 ERROR("Device must specify default or be in the range 1..255\n");
965 ACTION("Illegal device value %d ignored\n", rtrn.ival);
968 act->device = rtrn.ival;
971 return ReportIllegal(action->type, field);
975 HandleDeviceValuator(struct xkb_keymap * xkb,
976 struct xkb_any_action * action,
977 unsigned field, ExprDef * array_ndx, ExprDef * value)
981 struct xkb_device_valuator_action *act;
983 act = (struct xkb_device_valuator_action *) action;
984 /* XXX - Not yet implemented */
990 HandlePrivate(struct xkb_keymap * xkb,
991 struct xkb_any_action * action,
992 unsigned field, ExprDef * array_ndx, ExprDef * value)
999 if (!ExprResolveInteger(value, &rtrn))
1000 return ReportMismatch(PrivateAction, field, "integer");
1001 if ((rtrn.ival < 0) || (rtrn.ival > 255))
1003 ERROR("Private action type must be in the range 0..255\n");
1004 ACTION("Illegal type %d ignored\n", rtrn.ival);
1007 action->type = rtrn.uval;
1010 if (array_ndx == NULL)
1012 if (!ExprResolveString(value, &rtrn))
1013 return ReportMismatch(action->type, field, "string");
1016 int len = strlen(rtrn.str);
1017 if ((len < 1) || (len > 7))
1019 WARN("A private action has 7 data bytes\n");
1020 ACTION("Extra %d bytes ignored\n", len - 6);
1023 strncpy((char *) action->data, rtrn.str, sizeof action->data);
1031 if (!ExprResolveInteger(array_ndx, &rtrn))
1033 ERROR("Array subscript must be integer\n");
1034 ACTION("Illegal subscript ignored\n");
1038 if (ndx >= sizeof action->data)
1040 ERROR("The data for a private action is 18 bytes long\n");
1041 ACTION("Attempt to use data[%d] ignored\n", ndx);
1044 if (!ExprResolveInteger(value, &rtrn))
1045 return ReportMismatch(action->type, field, "integer");
1046 if ((rtrn.ival < 0) || (rtrn.ival > 255))
1048 ERROR("All data for a private action must be 0..255\n");
1049 ACTION("Illegal datum %d ignored\n", rtrn.ival);
1052 action->data[ndx] = rtrn.uval;
1056 return ReportIllegal(PrivateAction, field);
1059 typedef bool (*actionHandler) (struct xkb_keymap *xkb,
1060 struct xkb_any_action *action, unsigned field,
1061 ExprDef *array_ndx, ExprDef *value);
1063 static const actionHandler handleAction[XkbSA_NumActions + 1] = {
1064 [XkbSA_NoAction] = HandleNoAction,
1065 [XkbSA_SetMods] = HandleSetLatchMods,
1066 [XkbSA_LatchMods] = HandleSetLatchMods,
1067 [XkbSA_LockMods] = HandleLockMods,
1068 [XkbSA_SetGroup] = HandleSetLatchGroup,
1069 [XkbSA_LatchGroup] = HandleSetLatchGroup,
1070 [XkbSA_LockGroup] = HandleLockGroup,
1071 [XkbSA_MovePtr] = HandleMovePtr,
1072 [XkbSA_PtrBtn] = HandlePtrBtn,
1073 [XkbSA_LockPtrBtn] = HandlePtrBtn,
1074 [XkbSA_SetPtrDflt] = HandleSetPtrDflt,
1075 [XkbSA_ISOLock] = HandleISOLock,
1076 [XkbSA_Terminate] = HandleNoAction,
1077 [XkbSA_SwitchScreen] = HandleSwitchScreen,
1078 [XkbSA_SetControls] = HandleSetLockControls,
1079 [XkbSA_LockControls] = HandleSetLockControls,
1080 [XkbSA_ActionMessage] = HandleActionMessage,
1081 [XkbSA_RedirectKey] = HandleRedirectKey,
1082 [XkbSA_DeviceBtn] = HandleDeviceBtn,
1083 [XkbSA_LockDeviceBtn] = HandleDeviceBtn,
1084 [XkbSA_DeviceValuator] = HandleDeviceValuator,
1085 [PrivateAction] = HandlePrivate,
1088 /***====================================================================***/
1091 ApplyActionFactoryDefaults(union xkb_action * action)
1093 if (action->type == XkbSA_SetPtrDflt)
1094 { /* increment default button */
1095 action->dflt.affect = XkbSA_AffectDfltBtn;
1096 action->dflt.flags = 0;
1097 action->dflt.value = 1;
1099 else if (action->type == XkbSA_ISOLock)
1101 action->iso.real_mods = LockMask;
1109 HandleActionDef(ExprDef * def,
1110 struct xkb_keymap * xkb,
1111 struct xkb_any_action * action, ActionInfo * info)
1115 unsigned tmp, hndlrType;
1117 if (!actionsInitialized)
1120 if (def->op != ExprActionDecl)
1122 ERROR("Expected an action definition, found %s\n",
1123 exprOpText(def->op));
1126 str = XkbcAtomText(def->value.action.name);
1129 WSGO("Missing name in action definition!!\n");
1132 if (!stringToAction(str, &tmp))
1134 ERROR("Unknown action %s\n", str);
1137 action->type = hndlrType = tmp;
1138 if (action->type != XkbSA_NoAction)
1140 ApplyActionFactoryDefaults((union xkb_action *) action);
1143 if ((info->action == XkbSA_NoAction)
1144 || (info->action == hndlrType))
1146 if (!(*handleAction[hndlrType]) (xkb, action,
1157 for (arg = def->value.action.args; arg != NULL;
1158 arg = (ExprDef *) arg->common.next)
1160 ExprDef *field, *value, *arrayRtrn;
1161 ExprResult elemRtrn, fieldRtrn;
1164 if (arg->op == OpAssign)
1166 field = arg->value.binary.left;
1167 value = arg->value.binary.right;
1171 if ((arg->op == OpNot) || (arg->op == OpInvert))
1173 field = arg->value.child;
1174 constFalse.value.str = xkb_intern_atom("false");
1175 value = &constFalse;
1180 constTrue.value.str = xkb_intern_atom("true");
1184 if (!ExprResolveLhs(field, &elemRtrn, &fieldRtrn, &arrayRtrn))
1185 return false; /* internal error -- already reported */
1187 if (elemRtrn.str != NULL)
1189 ERROR("Cannot change defaults in an action definition\n");
1190 ACTION("Ignoring attempt to change %s.%s\n", elemRtrn.str,
1193 free(fieldRtrn.str);
1196 if (!stringToField(fieldRtrn.str, &fieldNdx))
1198 ERROR("Unknown field name %s\n", uStringText(fieldRtrn.str));
1200 free(fieldRtrn.str);
1204 free(fieldRtrn.str);
1205 if (!(*handleAction[hndlrType])
1206 (xkb, action, fieldNdx, arrayRtrn, value))
1214 /***====================================================================***/
1217 SetActionField(struct xkb_keymap * xkb,
1220 ExprDef * array_ndx, ExprDef * value, ActionInfo ** info_rtrn)
1222 ActionInfo *new, *old;
1224 if (!actionsInitialized)
1227 new = uTypedAlloc(ActionInfo);
1230 WSGO("Couldn't allocate space for action default\n");
1233 if (strcasecmp(elem, "action") == 0)
1234 new->action = XkbSA_NoAction;
1237 if (!stringToAction(elem, &new->action))
1242 if (new->action == XkbSA_NoAction)
1244 ERROR("\"%s\" is not a valid field in a NoAction action\n",
1250 if (!stringToField(field, &new->field))
1252 ERROR("\"%s\" is not a legal field name\n", field);
1256 new->array_ndx = array_ndx;
1260 while ((old) && (old->next))
1269 /***====================================================================***/
1274 if (!actionsInitialized)
1276 memset(&constTrue, 0, sizeof(constTrue));
1277 memset(&constFalse, 0, sizeof(constFalse));
1278 constTrue.common.stmtType = StmtExpr;
1279 constTrue.common.next = NULL;
1280 constTrue.op = ExprIdent;
1281 constTrue.type = TypeBoolean;
1282 constTrue.value.str = xkb_intern_atom("true");
1283 constFalse.common.stmtType = StmtExpr;
1284 constFalse.common.next = NULL;
1285 constFalse.op = ExprIdent;
1286 constFalse.type = TypeBoolean;
1287 constFalse.value.str = xkb_intern_atom("false");
1288 actionsInitialized = 1;