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 ********************************************************/
39 static bool actionsInitialized;
40 static ExprDef constTrue;
41 static ExprDef constFalse;
43 /***====================================================================***/
45 static const LookupEntry actionStrings[] = {
46 { "noaction", XkbSA_NoAction },
47 { "setmods", XkbSA_SetMods },
48 { "latchmods", XkbSA_LatchMods },
49 { "lockmods", XkbSA_LockMods },
50 { "setgroup", XkbSA_SetGroup },
51 { "latchgroup", XkbSA_LatchGroup },
52 { "lockgroup", XkbSA_LockGroup },
53 { "moveptr", XkbSA_MovePtr },
54 { "movepointer", XkbSA_MovePtr },
55 { "ptrbtn", XkbSA_PtrBtn },
56 { "pointerbutton", XkbSA_PtrBtn },
57 { "lockptrbtn", XkbSA_LockPtrBtn },
58 { "lockpointerbutton", XkbSA_LockPtrBtn },
59 { "lockptrbutton", XkbSA_LockPtrBtn },
60 { "lockpointerbtn", XkbSA_LockPtrBtn },
61 { "setptrdflt", XkbSA_SetPtrDflt },
62 { "setpointerdefault", XkbSA_SetPtrDflt },
63 { "isolock", XkbSA_ISOLock },
64 { "terminate", XkbSA_Terminate },
65 { "terminateserver", XkbSA_Terminate },
66 { "switchscreen", XkbSA_SwitchScreen },
67 { "setcontrols", XkbSA_SetControls },
68 { "lockcontrols", XkbSA_LockControls },
69 { "actionmessage", XkbSA_ActionMessage },
70 { "messageaction", XkbSA_ActionMessage },
71 { "message", XkbSA_ActionMessage },
72 { "redirect", XkbSA_RedirectKey },
73 { "redirectkey", XkbSA_RedirectKey },
74 { "devbtn", XkbSA_DeviceBtn },
75 { "devicebtn", XkbSA_DeviceBtn },
76 { "devbutton", XkbSA_DeviceBtn },
77 { "devicebutton", XkbSA_DeviceBtn },
78 { "lockdevbtn", XkbSA_DeviceBtn },
79 { "lockdevicebtn", XkbSA_LockDeviceBtn },
80 { "lockdevbutton", XkbSA_LockDeviceBtn },
81 { "lockdevicebutton", XkbSA_LockDeviceBtn },
82 { "devval", XkbSA_DeviceValuator },
83 { "deviceval", XkbSA_DeviceValuator },
84 { "devvaluator", XkbSA_DeviceValuator },
85 { "devicevaluator", XkbSA_DeviceValuator },
86 { "private", PrivateAction },
90 static const LookupEntry fieldStrings[] = {
91 { "clearLocks", F_ClearLocks },
92 { "latchToLock", F_LatchToLock },
93 { "genKeyEvent", F_GenKeyEvent },
94 { "generateKeyEvent", F_GenKeyEvent },
95 { "report", F_Report },
96 { "default", F_Default },
97 { "affect", F_Affect },
98 { "increment", F_Increment },
99 { "modifiers", F_Modifiers },
100 { "mods", F_Modifiers },
101 { "group", F_Group },
104 { "accel", F_Accel },
105 { "accelerate", F_Accel },
106 { "repeat", F_Accel },
107 { "button", F_Button },
108 { "value", F_Value },
109 { "controls", F_Controls },
110 { "ctrls", F_Controls },
112 { "count", F_Count },
113 { "screen", F_Screen },
115 { "sameServer", F_Same },
117 { "device", F_Device },
119 { "key", F_Keycode },
120 { "keycode", F_Keycode },
122 { "clearmods", F_ModsToClear },
123 { "clearmodifiers", F_ModsToClear },
128 stringToValue(const LookupEntry tab[], const char *string,
129 unsigned *value_rtrn)
131 const LookupEntry *entry;
136 for (entry = tab; entry->name != NULL; entry++) {
137 if (strcasecmp(entry->name, string) == 0) {
138 *value_rtrn = entry->result;
147 valueToString(const LookupEntry tab[], unsigned value)
149 const LookupEntry *entry;
151 for (entry = tab; entry->name != NULL; entry++)
152 if (entry->result == value)
159 stringToAction(const char *str, unsigned *type_rtrn)
161 return stringToValue(actionStrings, str, type_rtrn);
165 stringToField(const char *str, unsigned *field_rtrn)
167 return stringToValue(fieldStrings, str, field_rtrn);
171 fieldText(unsigned field)
173 return valueToString(fieldStrings, field);
176 /***====================================================================***/
179 ReportMismatch(unsigned action, unsigned field, const char *type)
181 ERROR("Value of %s field must be of type %s\n", fieldText(field), type);
182 ACTION("Action %s definition ignored\n", XkbcActionTypeText(action));
187 ReportIllegal(unsigned action, unsigned field)
189 ERROR("Field %s is not defined for an action of type %s\n",
190 fieldText(field), XkbcActionTypeText(action));
191 ACTION("Action definition ignored\n");
196 ReportActionNotArray(unsigned action, unsigned field)
198 ERROR("The %s field in the %s action is not an array\n",
199 fieldText(field), XkbcActionTypeText(action));
200 ACTION("Action definition ignored\n");
205 ReportNotFound(unsigned action, unsigned field, const char *what,
208 ERROR("%s named %s not found\n", what, bad);
209 ACTION("Ignoring the %s field of an %s action\n", fieldText(field),
210 XkbcActionTypeText(action));
215 HandleNoAction(struct xkb_keymap * xkb,
216 struct xkb_any_action * action,
217 unsigned field, ExprDef * array_ndx, ExprDef * value)
219 return ReportIllegal(action->type, field);
223 CheckLatchLockFlags(unsigned action,
224 unsigned field, ExprDef * value, unsigned *flags_inout)
229 if (field == F_ClearLocks)
230 tmp = XkbSA_ClearLocks;
231 else if (field == F_LatchToLock)
232 tmp = XkbSA_LatchToLock;
234 return false; /* WSGO! */
235 if (!ExprResolveBoolean(value, &result))
236 return ReportMismatch(action, field, "boolean");
240 *flags_inout &= ~tmp;
245 CheckModifierField(struct xkb_keymap * xkb,
248 unsigned *flags_inout, unsigned *mods_rtrn)
252 if (value->op == ExprIdent)
255 valStr = XkbcAtomText(value->value.str);
256 if (valStr && ((strcasecmp(valStr, "usemodmapmods") == 0) ||
257 (strcasecmp(valStr, "modmapmods") == 0)))
261 *flags_inout |= XkbSA_UseModMapMods;
265 if (!ExprResolveVModMask(value, &rtrn, xkb))
266 return ReportMismatch(action, F_Modifiers, "modifier mask");
267 *mods_rtrn = rtrn.uval;
268 *flags_inout &= ~XkbSA_UseModMapMods;
273 HandleSetLatchMods(struct xkb_keymap * xkb,
274 struct xkb_any_action * action,
275 unsigned field, ExprDef * array_ndx, ExprDef * value)
277 struct xkb_mod_action *act;
281 act = (struct xkb_mod_action *) action;
282 if (array_ndx != NULL)
289 return ReportActionNotArray(action->type, field);
297 if (CheckLatchLockFlags(action->type, field, value, &rtrn))
305 if (CheckModifierField(xkb, action->type, value, &t1, &t2))
308 act->real_mods = act->mask = (t2 & 0xff);
309 act->vmods = (t2 >> 8) & 0xffff;
314 return ReportIllegal(action->type, field);
318 HandleLockMods(struct xkb_keymap * xkb,
319 struct xkb_any_action * action,
320 unsigned field, ExprDef * array_ndx, ExprDef * value)
322 struct xkb_mod_action *act;
325 act = (struct xkb_mod_action *) action;
326 if ((array_ndx != NULL) && (field == F_Modifiers))
327 return ReportActionNotArray(action->type, field);
332 if (CheckModifierField(xkb, action->type, value, &t1, &t2))
335 act->real_mods = act->mask = (t2 & 0xff);
336 act->vmods = (t2 >> 8) & 0xffff;
341 return ReportIllegal(action->type, field);
345 CheckGroupField(unsigned action,
346 ExprDef * value, unsigned *flags_inout, int *grp_rtrn)
351 if ((value->op == OpNegate) || (value->op == OpUnaryPlus))
353 *flags_inout &= ~XkbSA_GroupAbsolute;
354 spec = value->value.child;
358 *flags_inout |= XkbSA_GroupAbsolute;
362 if (!ExprResolveGroup(spec, &rtrn))
363 return ReportMismatch(action, F_Group, "integer (range 1..8)");
364 if (value->op == OpNegate)
365 *grp_rtrn = -rtrn.ival;
366 else if (value->op == OpUnaryPlus)
367 *grp_rtrn = rtrn.ival;
369 *grp_rtrn = rtrn.ival - 1;
374 HandleSetLatchGroup(struct xkb_keymap * xkb,
375 struct xkb_any_action * action,
376 unsigned field, ExprDef * array_ndx, ExprDef * value)
378 struct xkb_group_action *act;
383 act = (struct xkb_group_action *) action;
384 if (array_ndx != NULL)
391 return ReportActionNotArray(action->type, field);
399 if (CheckLatchLockFlags(action->type, field, value, &rtrn))
407 if (CheckGroupField(action->type, value, &t1, &t2))
415 return ReportIllegal(action->type, field);
419 HandleLockGroup(struct xkb_keymap * xkb,
420 struct xkb_any_action * action,
421 unsigned field, ExprDef * array_ndx, ExprDef * value)
423 struct xkb_group_action *act;
427 act = (struct xkb_group_action *) action;
428 if ((array_ndx != NULL) && (field == F_Group))
429 return ReportActionNotArray(action->type, field);
430 if (field == F_Group)
433 if (CheckGroupField(action->type, value, &t1, &t2))
441 return ReportIllegal(action->type, field);
445 HandleMovePtr(struct xkb_keymap * xkb,
446 struct xkb_any_action * action,
447 unsigned field, ExprDef * array_ndx, ExprDef * value)
450 struct xkb_pointer_action *act;
453 act = (struct xkb_pointer_action *) action;
454 if ((array_ndx != NULL) && ((field == F_X) || (field == F_Y)))
455 return ReportActionNotArray(action->type, field);
457 if ((field == F_X) || (field == F_Y))
459 if ((value->op == OpNegate) || (value->op == OpUnaryPlus))
463 if (!ExprResolveInteger(value, &rtrn))
464 return ReportMismatch(action->type, field, "integer");
468 act->flags |= XkbSA_MoveAbsoluteX;
474 act->flags |= XkbSA_MoveAbsoluteY;
479 else if (field == F_Accel)
481 if (!ExprResolveBoolean(value, &rtrn))
482 return ReportMismatch(action->type, field, "boolean");
484 act->flags &= ~XkbSA_NoAcceleration;
486 act->flags |= XkbSA_NoAcceleration;
488 return ReportIllegal(action->type, field);
491 static const LookupEntry lockWhich[] = {
493 {"lock", XkbSA_LockNoUnlock},
494 {"neither", (XkbSA_LockNoLock | XkbSA_LockNoUnlock)},
495 {"unlock", XkbSA_LockNoLock},
500 HandlePtrBtn(struct xkb_keymap * xkb,
501 struct xkb_any_action * action,
502 unsigned field, ExprDef * array_ndx, ExprDef * value)
505 struct xkb_pointer_button_action *act;
507 act = (struct xkb_pointer_button_action *) action;
508 if (field == F_Button)
510 if (array_ndx != NULL)
511 return ReportActionNotArray(action->type, field);
512 if (!ExprResolveButton(value, &rtrn))
513 return ReportMismatch(action->type, field,
514 "integer (range 1..5)");
515 if ((rtrn.ival < 0) || (rtrn.ival > 5))
517 ERROR("Button must specify default or be in the range 1..5\n");
518 ACTION("Illegal button value %d ignored\n", rtrn.ival);
521 act->button = rtrn.ival;
524 else if ((action->type == XkbSA_LockPtrBtn) && (field == F_Affect))
526 if (array_ndx != NULL)
527 return ReportActionNotArray(action->type, field);
528 if (!ExprResolveEnum(value, &rtrn, lockWhich))
529 return ReportMismatch(action->type, field, "lock or unlock");
530 act->flags &= ~(XkbSA_LockNoLock | XkbSA_LockNoUnlock);
531 act->flags |= rtrn.ival;
534 else if (field == F_Count)
536 if (array_ndx != NULL)
537 return ReportActionNotArray(action->type, field);
538 if (!ExprResolveButton(value, &rtrn))
539 return ReportMismatch(action->type, field, "integer");
540 if ((rtrn.ival < 0) || (rtrn.ival > 255))
542 ERROR("The count field must have a value in the range 0..255\n");
543 ACTION("Illegal count %d ignored\n", rtrn.ival);
546 act->count = rtrn.ival;
549 return ReportIllegal(action->type, field);
552 static const LookupEntry ptrDflts[] = {
553 {"dfltbtn", XkbSA_AffectDfltBtn},
554 {"defaultbutton", XkbSA_AffectDfltBtn},
555 {"button", XkbSA_AffectDfltBtn},
560 HandleSetPtrDflt(struct xkb_keymap * xkb,
561 struct xkb_any_action * action,
562 unsigned field, ExprDef * array_ndx, ExprDef * value)
565 struct xkb_pointer_default_action *act;
567 act = (struct xkb_pointer_default_action *) action;
568 if (field == F_Affect)
570 if (array_ndx != NULL)
571 return ReportActionNotArray(action->type, field);
572 if (!ExprResolveEnum(value, &rtrn, ptrDflts))
573 return ReportMismatch(action->type, field, "pointer component");
574 act->affect = rtrn.uval;
577 else if ((field == F_Button) || (field == F_Value))
580 if (array_ndx != NULL)
581 return ReportActionNotArray(action->type, field);
582 if ((value->op == OpNegate) || (value->op == OpUnaryPlus))
584 act->flags &= ~XkbSA_DfltBtnAbsolute;
585 btn = value->value.child;
589 act->flags |= XkbSA_DfltBtnAbsolute;
593 if (!ExprResolveButton(btn, &rtrn))
594 return ReportMismatch(action->type, field,
595 "integer (range 1..5)");
596 if ((rtrn.ival < 0) || (rtrn.ival > 5))
598 ERROR("New default button value must be in the range 1..5\n");
599 ACTION("Illegal default button value %d ignored\n", rtrn.ival);
604 ERROR("Cannot set default pointer button to \"default\"\n");
605 ACTION("Illegal default button setting ignored\n");
608 if (value->op == OpNegate)
609 act->value = -rtrn.ival;
611 act->value = rtrn.ival;
614 return ReportIllegal(action->type, field);
617 static const LookupEntry isoNames[] = {
618 {"mods", XkbSA_ISONoAffectMods},
619 {"modifiers", XkbSA_ISONoAffectMods},
620 {"group", XkbSA_ISONoAffectGroup},
621 {"groups", XkbSA_ISONoAffectGroup},
622 {"ptr", XkbSA_ISONoAffectPtr},
623 {"pointer", XkbSA_ISONoAffectPtr},
624 {"ctrls", XkbSA_ISONoAffectCtrls},
625 {"controls", XkbSA_ISONoAffectCtrls},
626 {"all", ~((unsigned) 0)},
632 HandleISOLock(struct xkb_keymap * xkb,
633 struct xkb_any_action * action,
634 unsigned field, ExprDef * array_ndx, ExprDef * value)
637 struct xkb_iso_action *act;
638 unsigned flags, mods;
641 act = (struct xkb_iso_action *) action;
645 if (array_ndx != NULL)
646 return ReportActionNotArray(action->type, field);
648 if (CheckModifierField(xkb, action->type, value, &flags, &mods))
650 act->flags = flags & (~XkbSA_ISODfltIsGroup);
651 act->real_mods = mods & 0xff;
652 act->vmods = (mods >> 8) & 0xff;
657 if (array_ndx != NULL)
658 return ReportActionNotArray(action->type, field);
660 if (CheckGroupField(action->type, value, &flags, &group))
662 act->flags = flags | XkbSA_ISODfltIsGroup;
668 if (array_ndx != NULL)
669 return ReportActionNotArray(action->type, field);
670 if (!ExprResolveMask(value, &rtrn, isoNames))
671 return ReportMismatch(action->type, field, "keyboard component");
672 act->affect = (~rtrn.uval) & XkbSA_ISOAffectMask;
675 return ReportIllegal(action->type, field);
679 HandleSwitchScreen(struct xkb_keymap * xkb,
680 struct xkb_any_action * action,
681 unsigned field, ExprDef * array_ndx, ExprDef * value)
684 struct xkb_switch_screen_action *act;
686 act = (struct xkb_switch_screen_action *) action;
687 if (field == F_Screen)
690 if (array_ndx != NULL)
691 return ReportActionNotArray(action->type, field);
692 if ((value->op == OpNegate) || (value->op == OpUnaryPlus))
694 act->flags &= ~XkbSA_SwitchAbsolute;
695 scrn = value->value.child;
699 act->flags |= XkbSA_SwitchAbsolute;
703 if (!ExprResolveInteger(scrn, &rtrn))
704 return ReportMismatch(action->type, field, "integer (0..255)");
705 if ((rtrn.ival < 0) || (rtrn.ival > 255))
707 ERROR("Screen index must be in the range 1..255\n");
708 ACTION("Illegal screen value %d ignored\n", rtrn.ival);
711 if (value->op == OpNegate)
712 act->screen = -rtrn.ival;
714 act->screen = rtrn.ival;
717 else if (field == F_Same)
719 if (array_ndx != NULL)
720 return ReportActionNotArray(action->type, field);
721 if (!ExprResolveBoolean(value, &rtrn))
722 return ReportMismatch(action->type, field, "boolean");
724 act->flags &= ~XkbSA_SwitchApplication;
726 act->flags |= XkbSA_SwitchApplication;
729 return ReportIllegal(action->type, field);
732 const LookupEntry ctrlNames[] = {
733 {"repeatkeys", XkbRepeatKeysMask},
734 {"repeat", XkbRepeatKeysMask},
735 {"autorepeat", XkbRepeatKeysMask},
736 {"slowkeys", XkbSlowKeysMask},
737 {"bouncekeys", XkbBounceKeysMask},
738 {"stickykeys", XkbStickyKeysMask},
739 {"mousekeys", XkbMouseKeysMask},
740 {"mousekeysaccel", XkbMouseKeysAccelMask},
741 {"accessxkeys", XkbAccessXKeysMask},
742 {"accessxtimeout", XkbAccessXTimeoutMask},
743 {"accessxfeedback", XkbAccessXFeedbackMask},
744 {"audiblebell", XkbAudibleBellMask},
745 {"ignoregrouplock", XkbIgnoreGroupLockMask},
746 {"all", XkbAllBooleanCtrlsMask},
754 HandleSetLockControls(struct xkb_keymap * xkb,
755 struct xkb_any_action * action,
756 unsigned field, ExprDef * array_ndx, ExprDef * value)
759 struct xkb_controls_action *act;
761 act = (struct xkb_controls_action *) action;
762 if (field == F_Controls)
764 if (array_ndx != NULL)
765 return ReportActionNotArray(action->type, field);
766 if (!ExprResolveMask(value, &rtrn, ctrlNames))
767 return ReportMismatch(action->type, field, "controls mask");
768 act->ctrls = rtrn.uval;
771 return ReportIllegal(action->type, field);
774 static const LookupEntry evNames[] = {
775 {"press", XkbSA_MessageOnPress},
776 {"keypress", XkbSA_MessageOnPress},
777 {"release", XkbSA_MessageOnRelease},
778 {"keyrelease", XkbSA_MessageOnRelease},
779 {"all", XkbSA_MessageOnPress | XkbSA_MessageOnRelease},
785 HandleActionMessage(struct xkb_keymap * xkb,
786 struct xkb_any_action * action,
787 unsigned field, ExprDef * array_ndx, ExprDef * value)
790 struct xkb_message_action *act;
792 act = (struct xkb_message_action *) action;
796 if (array_ndx != NULL)
797 return ReportActionNotArray(action->type, field);
798 if (!ExprResolveMask(value, &rtrn, evNames))
799 return ReportMismatch(action->type, field, "key event mask");
800 act->flags &= ~(XkbSA_MessageOnPress | XkbSA_MessageOnRelease);
802 rtrn.uval & (XkbSA_MessageOnPress | XkbSA_MessageOnRelease);
805 if (array_ndx != NULL)
806 return ReportActionNotArray(action->type, field);
807 if (!ExprResolveBoolean(value, &rtrn))
808 return ReportMismatch(action->type, field, "boolean");
810 act->flags |= XkbSA_MessageGenKeyEvent;
812 act->flags &= ~XkbSA_MessageGenKeyEvent;
815 if (array_ndx == NULL)
817 if (!ExprResolveString(value, &rtrn))
818 return ReportMismatch(action->type, field, "string");
821 int len = strlen(rtrn.str);
822 if ((len < 1) || (len > 6))
824 WARN("An action message can hold only 6 bytes\n");
825 ACTION("Extra %d bytes ignored\n", len - 6);
827 strncpy((char *) act->message, rtrn.str, 6);
834 if (!ExprResolveInteger(array_ndx, &rtrn))
836 ERROR("Array subscript must be integer\n");
837 ACTION("Illegal subscript ignored\n");
843 ERROR("An action message is at most 6 bytes long\n");
844 ACTION("Attempt to use data[%d] ignored\n", ndx);
847 if (!ExprResolveInteger(value, &rtrn))
848 return ReportMismatch(action->type, field, "integer");
849 if ((rtrn.ival < 0) || (rtrn.ival > 255))
851 ERROR("Message data must be in the range 0..255\n");
852 ACTION("Illegal datum %d ignored\n", rtrn.ival);
855 act->message[ndx] = rtrn.uval;
859 return ReportIllegal(action->type, field);
863 HandleRedirectKey(struct xkb_keymap * xkb,
864 struct xkb_any_action * action,
865 unsigned field, ExprDef * array_ndx, ExprDef * value)
868 struct xkb_redirect_key_action *act;
873 if (array_ndx != NULL)
874 return ReportActionNotArray(action->type, field);
876 act = (struct xkb_redirect_key_action *) action;
880 if (!ExprResolveKeyName(value, &rtrn))
881 return ReportMismatch(action->type, field, "key name");
882 tmp = KeyNameToLong(rtrn.keyName.name);
883 if (!FindNamedKey(xkb, tmp, &kc, true, CreateKeyNames(xkb), 0))
885 return ReportNotFound(action->type, field, "Key",
886 XkbcKeyNameText(rtrn.keyName.name));
893 if (CheckModifierField(xkb, action->type, value, &t1, &t2))
895 act->mods_mask |= (t2 & 0xff);
896 if (field == F_Modifiers)
897 act->mods |= (t2 & 0xff);
899 act->mods &= ~(t2 & 0xff);
901 t2 = (t2 >> 8) & 0xffff;
902 act->vmods_mask |= t2;
903 if (field == F_Modifiers)
911 return ReportIllegal(action->type, field);
915 HandleDeviceBtn(struct xkb_keymap * xkb,
916 struct xkb_any_action * action,
917 unsigned field, ExprDef * array_ndx, ExprDef * value)
920 struct xkb_device_button_action *act;
922 act = (struct xkb_device_button_action *) action;
923 if (field == F_Button)
925 if (array_ndx != NULL)
926 return ReportActionNotArray(action->type, field);
927 if (!ExprResolveInteger(value, &rtrn))
928 return ReportMismatch(action->type, field,
929 "integer (range 1..255)");
930 if ((rtrn.ival < 0) || (rtrn.ival > 255))
932 ERROR("Button must specify default or be in the range 1..255\n");
933 ACTION("Illegal button value %d ignored\n", rtrn.ival);
936 act->button = rtrn.ival;
939 else if ((action->type == XkbSA_LockDeviceBtn) && (field == F_Affect))
941 if (array_ndx != NULL)
942 return ReportActionNotArray(action->type, field);
943 if (!ExprResolveEnum(value, &rtrn, lockWhich))
944 return ReportMismatch(action->type, field, "lock or unlock");
945 act->flags &= ~(XkbSA_LockNoLock | XkbSA_LockNoUnlock);
946 act->flags |= rtrn.ival;
949 else if (field == F_Count)
951 if (array_ndx != NULL)
952 return ReportActionNotArray(action->type, field);
953 if (!ExprResolveButton(value, &rtrn))
954 return ReportMismatch(action->type, field, "integer");
955 if ((rtrn.ival < 0) || (rtrn.ival > 255))
957 ERROR("The count field must have a value in the range 0..255\n");
958 ACTION("Illegal count %d ignored\n", rtrn.ival);
961 act->count = rtrn.ival;
964 else if (field == F_Device)
966 if (array_ndx != NULL)
967 return ReportActionNotArray(action->type, field);
968 if (!ExprResolveInteger(value, &rtrn))
969 return ReportMismatch(action->type, field,
970 "integer (range 1..255)");
971 if ((rtrn.ival < 0) || (rtrn.ival > 255))
973 ERROR("Device must specify default or be in the range 1..255\n");
974 ACTION("Illegal device value %d ignored\n", rtrn.ival);
977 act->device = rtrn.ival;
980 return ReportIllegal(action->type, field);
984 HandleDeviceValuator(struct xkb_keymap * xkb,
985 struct xkb_any_action * action,
986 unsigned field, ExprDef * array_ndx, ExprDef * value)
990 struct xkb_device_valuator_action *act;
992 act = (struct xkb_device_valuator_action *) action;
993 /* XXX - Not yet implemented */
999 HandlePrivate(struct xkb_keymap * xkb,
1000 struct xkb_any_action * action,
1001 unsigned field, ExprDef * array_ndx, ExprDef * value)
1008 if (!ExprResolveInteger(value, &rtrn))
1009 return ReportMismatch(PrivateAction, field, "integer");
1010 if ((rtrn.ival < 0) || (rtrn.ival > 255))
1012 ERROR("Private action type must be in the range 0..255\n");
1013 ACTION("Illegal type %d ignored\n", rtrn.ival);
1016 action->type = rtrn.uval;
1019 if (array_ndx == NULL)
1021 if (!ExprResolveString(value, &rtrn))
1022 return ReportMismatch(action->type, field, "string");
1025 int len = strlen(rtrn.str);
1026 if ((len < 1) || (len > 7))
1028 WARN("A private action has 7 data bytes\n");
1029 ACTION("Extra %d bytes ignored\n", len - 6);
1032 strncpy((char *) action->data, rtrn.str, sizeof action->data);
1040 if (!ExprResolveInteger(array_ndx, &rtrn))
1042 ERROR("Array subscript must be integer\n");
1043 ACTION("Illegal subscript ignored\n");
1047 if (ndx >= sizeof action->data)
1049 ERROR("The data for a private action is 18 bytes long\n");
1050 ACTION("Attempt to use data[%d] ignored\n", ndx);
1053 if (!ExprResolveInteger(value, &rtrn))
1054 return ReportMismatch(action->type, field, "integer");
1055 if ((rtrn.ival < 0) || (rtrn.ival > 255))
1057 ERROR("All data for a private action must be 0..255\n");
1058 ACTION("Illegal datum %d ignored\n", rtrn.ival);
1061 action->data[ndx] = rtrn.uval;
1065 return ReportIllegal(PrivateAction, field);
1068 typedef bool (*actionHandler) (struct xkb_keymap *xkb,
1069 struct xkb_any_action *action, unsigned field,
1070 ExprDef *array_ndx, ExprDef *value);
1072 static const actionHandler handleAction[XkbSA_NumActions + 1] = {
1073 [XkbSA_NoAction] = HandleNoAction,
1074 [XkbSA_SetMods] = HandleSetLatchMods,
1075 [XkbSA_LatchMods] = HandleSetLatchMods,
1076 [XkbSA_LockMods] = HandleLockMods,
1077 [XkbSA_SetGroup] = HandleSetLatchGroup,
1078 [XkbSA_LatchGroup] = HandleSetLatchGroup,
1079 [XkbSA_LockGroup] = HandleLockGroup,
1080 [XkbSA_MovePtr] = HandleMovePtr,
1081 [XkbSA_PtrBtn] = HandlePtrBtn,
1082 [XkbSA_LockPtrBtn] = HandlePtrBtn,
1083 [XkbSA_SetPtrDflt] = HandleSetPtrDflt,
1084 [XkbSA_ISOLock] = HandleISOLock,
1085 [XkbSA_Terminate] = HandleNoAction,
1086 [XkbSA_SwitchScreen] = HandleSwitchScreen,
1087 [XkbSA_SetControls] = HandleSetLockControls,
1088 [XkbSA_LockControls] = HandleSetLockControls,
1089 [XkbSA_ActionMessage] = HandleActionMessage,
1090 [XkbSA_RedirectKey] = HandleRedirectKey,
1091 [XkbSA_DeviceBtn] = HandleDeviceBtn,
1092 [XkbSA_LockDeviceBtn] = HandleDeviceBtn,
1093 [XkbSA_DeviceValuator] = HandleDeviceValuator,
1094 [PrivateAction] = HandlePrivate,
1097 /***====================================================================***/
1100 ApplyActionFactoryDefaults(union xkb_action * action)
1102 if (action->type == XkbSA_SetPtrDflt)
1103 { /* increment default button */
1104 action->dflt.affect = XkbSA_AffectDfltBtn;
1105 action->dflt.flags = 0;
1106 action->dflt.value = 1;
1108 else if (action->type == XkbSA_ISOLock)
1110 action->iso.real_mods = LockMask;
1118 HandleActionDef(ExprDef * def,
1119 struct xkb_keymap * xkb,
1120 struct xkb_any_action * action, ActionInfo * info)
1124 unsigned tmp, hndlrType;
1126 if (!actionsInitialized)
1129 if (def->op != ExprActionDecl)
1131 ERROR("Expected an action definition, found %s\n",
1132 exprOpText(def->op));
1135 str = XkbcAtomText(def->value.action.name);
1138 WSGO("Missing name in action definition!!\n");
1141 if (!stringToAction(str, &tmp))
1143 ERROR("Unknown action %s\n", str);
1146 action->type = hndlrType = tmp;
1147 if (action->type != XkbSA_NoAction)
1149 ApplyActionFactoryDefaults((union xkb_action *) action);
1152 if ((info->action == XkbSA_NoAction)
1153 || (info->action == hndlrType))
1155 if (!(*handleAction[hndlrType]) (xkb, action,
1166 for (arg = def->value.action.args; arg != NULL;
1167 arg = (ExprDef *) arg->common.next)
1169 ExprDef *field, *value, *arrayRtrn;
1170 ExprResult elemRtrn, fieldRtrn;
1173 if (arg->op == OpAssign)
1175 field = arg->value.binary.left;
1176 value = arg->value.binary.right;
1180 if ((arg->op == OpNot) || (arg->op == OpInvert))
1182 field = arg->value.child;
1183 constFalse.value.str = xkb_intern_atom("false");
1184 value = &constFalse;
1189 constTrue.value.str = xkb_intern_atom("true");
1193 if (!ExprResolveLhs(field, &elemRtrn, &fieldRtrn, &arrayRtrn))
1194 return false; /* internal error -- already reported */
1196 if (elemRtrn.str != NULL)
1198 ERROR("Cannot change defaults in an action definition\n");
1199 ACTION("Ignoring attempt to change %s.%s\n", elemRtrn.str,
1202 free(fieldRtrn.str);
1205 if (!stringToField(fieldRtrn.str, &fieldNdx))
1207 ERROR("Unknown field name %s\n", uStringText(fieldRtrn.str));
1209 free(fieldRtrn.str);
1213 free(fieldRtrn.str);
1214 if (!(*handleAction[hndlrType])
1215 (xkb, action, fieldNdx, arrayRtrn, value))
1223 /***====================================================================***/
1226 SetActionField(struct xkb_keymap * xkb,
1229 ExprDef * array_ndx, ExprDef * value, ActionInfo ** info_rtrn)
1231 ActionInfo *new, *old;
1233 if (!actionsInitialized)
1236 new = uTypedAlloc(ActionInfo);
1239 WSGO("Couldn't allocate space for action default\n");
1242 if (strcasecmp(elem, "action") == 0)
1243 new->action = XkbSA_NoAction;
1246 if (!stringToAction(elem, &new->action))
1251 if (new->action == XkbSA_NoAction)
1253 ERROR("\"%s\" is not a valid field in a NoAction action\n",
1259 if (!stringToField(field, &new->field))
1261 ERROR("\"%s\" is not a legal field name\n", field);
1265 new->array_ndx = array_ndx;
1269 while ((old) && (old->next))
1278 /***====================================================================***/
1283 if (!actionsInitialized)
1285 memset(&constTrue, 0, sizeof(constTrue));
1286 memset(&constFalse, 0, sizeof(constFalse));
1287 constTrue.common.stmtType = StmtExpr;
1288 constTrue.common.next = NULL;
1289 constTrue.op = ExprIdent;
1290 constTrue.type = TypeBoolean;
1291 constTrue.value.str = xkb_intern_atom("true");
1292 constFalse.common.stmtType = StmtExpr;
1293 constFalse.common.next = NULL;
1294 constFalse.op = ExprIdent;
1295 constFalse.type = TypeBoolean;
1296 constFalse.value.str = xkb_intern_atom("false");
1297 actionsInitialized = 1;