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_desc * 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_desc * 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_desc * 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_desc * 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_desc * 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_desc * 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_desc * 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_desc * 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_desc * 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_desc * 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_desc * 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_desc * 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_desc * 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_desc * 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_desc * 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_desc * 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_desc * 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_desc * /* xkb */ ,
1069 struct xkb_any_action * /* action */ ,
1070 unsigned /* field */ ,
1071 ExprDef * /* array_ndx */ ,
1072 ExprDef * /* value */
1075 static const actionHandler handleAction[XkbSA_NumActions + 1] = {
1076 HandleNoAction /* NoAction */ ,
1077 HandleSetLatchMods /* SetMods */ ,
1078 HandleSetLatchMods /* LatchMods */ ,
1079 HandleLockMods /* LockMods */ ,
1080 HandleSetLatchGroup /* SetGroup */ ,
1081 HandleSetLatchGroup /* LatchGroup */ ,
1082 HandleLockGroup /* LockGroup */ ,
1083 HandleMovePtr /* MovePtr */ ,
1084 HandlePtrBtn /* PtrBtn */ ,
1085 HandlePtrBtn /* LockPtrBtn */ ,
1086 HandleSetPtrDflt /* SetPtrDflt */ ,
1087 HandleISOLock /* ISOLock */ ,
1088 HandleNoAction /* Terminate */ ,
1089 HandleSwitchScreen /* SwitchScreen */ ,
1090 HandleSetLockControls /* SetControls */ ,
1091 HandleSetLockControls /* LockControls */ ,
1092 HandleActionMessage /* ActionMessage */ ,
1093 HandleRedirectKey /* RedirectKey */ ,
1094 HandleDeviceBtn /* DeviceBtn */ ,
1095 HandleDeviceBtn /* LockDeviceBtn */ ,
1096 HandleDeviceValuator /* DeviceValuatr */ ,
1097 HandlePrivate /* Private */
1100 /***====================================================================***/
1103 ApplyActionFactoryDefaults(union xkb_action * action)
1105 if (action->type == XkbSA_SetPtrDflt)
1106 { /* increment default button */
1107 action->dflt.affect = XkbSA_AffectDfltBtn;
1108 action->dflt.flags = 0;
1109 action->dflt.value = 1;
1111 else if (action->type == XkbSA_ISOLock)
1113 action->iso.real_mods = LockMask;
1121 HandleActionDef(ExprDef * def,
1122 struct xkb_desc * xkb,
1123 struct xkb_any_action * action, unsigned mergeMode, ActionInfo * info)
1127 unsigned tmp, hndlrType;
1129 if (!actionsInitialized)
1132 if (def->op != ExprActionDecl)
1134 ERROR("Expected an action definition, found %s\n",
1135 exprOpText(def->op));
1138 str = XkbcAtomText(def->value.action.name);
1141 WSGO("Missing name in action definition!!\n");
1144 if (!stringToAction(str, &tmp))
1146 ERROR("Unknown action %s\n", str);
1149 action->type = hndlrType = tmp;
1150 if (action->type != XkbSA_NoAction)
1152 ApplyActionFactoryDefaults((union xkb_action *) action);
1155 if ((info->action == XkbSA_NoAction)
1156 || (info->action == hndlrType))
1158 if (!(*handleAction[hndlrType]) (xkb, action,
1169 for (arg = def->value.action.args; arg != NULL;
1170 arg = (ExprDef *) arg->common.next)
1172 ExprDef *field, *value, *arrayRtrn;
1173 ExprResult elemRtrn, fieldRtrn;
1176 if (arg->op == OpAssign)
1178 field = arg->value.binary.left;
1179 value = arg->value.binary.right;
1183 if ((arg->op == OpNot) || (arg->op == OpInvert))
1185 field = arg->value.child;
1186 value = &constFalse;
1194 if (!ExprResolveLhs(field, &elemRtrn, &fieldRtrn, &arrayRtrn))
1195 return False; /* internal error -- already reported */
1197 if (elemRtrn.str != NULL)
1199 ERROR("Cannot change defaults in an action definition\n");
1200 ACTION("Ignoring attempt to change %s.%s\n", elemRtrn.str,
1203 free(fieldRtrn.str);
1206 if (!stringToField(fieldRtrn.str, &fieldNdx))
1208 ERROR("Unknown field name %s\n", uStringText(fieldRtrn.str));
1210 free(fieldRtrn.str);
1214 free(fieldRtrn.str);
1215 if (!(*handleAction[hndlrType])
1216 (xkb, action, fieldNdx, arrayRtrn, value))
1224 /***====================================================================***/
1227 SetActionField(struct xkb_desc * xkb,
1230 ExprDef * array_ndx, ExprDef * value, ActionInfo ** info_rtrn)
1232 ActionInfo *new, *old;
1234 if (!actionsInitialized)
1237 new = uTypedAlloc(ActionInfo);
1240 WSGO("Couldn't allocate space for action default\n");
1243 if (strcasecmp(elem, "action") == 0)
1244 new->action = XkbSA_NoAction;
1247 if (!stringToAction(elem, &new->action))
1252 if (new->action == XkbSA_NoAction)
1254 ERROR("\"%s\" is not a valid field in a NoAction action\n",
1260 if (!stringToField(field, &new->field))
1262 ERROR("\"%s\" is not a legal field name\n", field);
1266 new->array_ndx = array_ndx;
1270 while ((old) && (old->next))
1279 /***====================================================================***/
1284 if (!actionsInitialized)
1286 memset(&constTrue, 0, sizeof(constTrue));
1287 memset(&constFalse, 0, sizeof(constFalse));
1288 constTrue.common.stmtType = StmtExpr;
1289 constTrue.common.next = NULL;
1290 constTrue.op = ExprIdent;
1291 constTrue.type = TypeBoolean;
1292 constTrue.value.str = xkb_intern_atom("true");
1293 constFalse.common.stmtType = StmtExpr;
1294 constFalse.common.next = NULL;
1295 constFalse.op = ExprIdent;
1296 constFalse.type = TypeBoolean;
1297 constFalse.value.str = xkb_intern_atom("false");
1298 actionsInitialized = 1;