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 ********************************************************/
37 static Bool actionsInitialized;
38 static ExprDef constTrue;
39 static ExprDef constFalse;
41 /***====================================================================***/
43 static const LookupEntry actionStrings[] = {
44 { "noaction", XkbSA_NoAction },
45 { "setmods", XkbSA_SetMods },
46 { "latchmods", XkbSA_LatchMods },
47 { "lockmods", XkbSA_LockMods },
48 { "setgroup", XkbSA_SetGroup },
49 { "latchgroup", XkbSA_LatchGroup },
50 { "lockgroup", XkbSA_LockGroup },
51 { "moveptr", XkbSA_MovePtr },
52 { "movepointer", XkbSA_MovePtr },
53 { "ptrbtn", XkbSA_PtrBtn },
54 { "pointerbutton", XkbSA_PtrBtn },
55 { "lockptrbtn", XkbSA_LockPtrBtn },
56 { "lockpointerbutton", XkbSA_LockPtrBtn },
57 { "lockptrbutton", XkbSA_LockPtrBtn },
58 { "lockpointerbtn", XkbSA_LockPtrBtn },
59 { "setptrdflt", XkbSA_SetPtrDflt },
60 { "setpointerdefault", XkbSA_SetPtrDflt },
61 { "isolock", XkbSA_ISOLock },
62 { "terminate", XkbSA_Terminate },
63 { "terminateserver", XkbSA_Terminate },
64 { "switchscreen", XkbSA_SwitchScreen },
65 { "setcontrols", XkbSA_SetControls },
66 { "lockcontrols", XkbSA_LockControls },
67 { "actionmessage", XkbSA_ActionMessage },
68 { "messageaction", XkbSA_ActionMessage },
69 { "message", XkbSA_ActionMessage },
70 { "redirect", XkbSA_RedirectKey },
71 { "redirectkey", XkbSA_RedirectKey },
72 { "devbtn", XkbSA_DeviceBtn },
73 { "devicebtn", XkbSA_DeviceBtn },
74 { "devbutton", XkbSA_DeviceBtn },
75 { "devicebutton", XkbSA_DeviceBtn },
76 { "lockdevbtn", XkbSA_DeviceBtn },
77 { "lockdevicebtn", XkbSA_LockDeviceBtn },
78 { "lockdevbutton", XkbSA_LockDeviceBtn },
79 { "lockdevicebutton", XkbSA_LockDeviceBtn },
80 { "devval", XkbSA_DeviceValuator },
81 { "deviceval", XkbSA_DeviceValuator },
82 { "devvaluator", XkbSA_DeviceValuator },
83 { "devicevaluator", XkbSA_DeviceValuator },
84 { "private", PrivateAction },
88 static const LookupEntry fieldStrings[] = {
89 { "clearLocks", F_ClearLocks },
90 { "latchToLock", F_LatchToLock },
91 { "genKeyEvent", F_GenKeyEvent },
92 { "generateKeyEvent", F_GenKeyEvent },
93 { "report", F_Report },
94 { "default", F_Default },
95 { "affect", F_Affect },
96 { "increment", F_Increment },
97 { "modifiers", F_Modifiers },
98 { "mods", F_Modifiers },
102 { "accel", F_Accel },
103 { "accelerate", F_Accel },
104 { "repeat", F_Accel },
105 { "button", F_Button },
106 { "value", F_Value },
107 { "controls", F_Controls },
108 { "ctrls", F_Controls },
110 { "count", F_Count },
111 { "screen", F_Screen },
113 { "sameServer", F_Same },
115 { "device", F_Device },
117 { "key", F_Keycode },
118 { "keycode", F_Keycode },
120 { "clearmods", F_ModsToClear },
121 { "clearmodifiers", F_ModsToClear },
126 stringToValue(const LookupEntry tab[], const char *string,
127 unsigned *value_rtrn)
129 const LookupEntry *entry;
134 for (entry = tab; entry->name != NULL; entry++) {
135 if (strcasecmp(entry->name, string) == 0) {
136 *value_rtrn = entry->result;
145 valueToString(const LookupEntry tab[], unsigned value)
147 const LookupEntry *entry;
149 for (entry = tab; entry->name != NULL; entry++)
150 if (entry->result == value)
157 stringToAction(const char *str, unsigned *type_rtrn)
159 return stringToValue(actionStrings, str, type_rtrn);
163 stringToField(const char *str, unsigned *field_rtrn)
165 return stringToValue(fieldStrings, str, field_rtrn);
169 fieldText(unsigned field)
171 return valueToString(fieldStrings, field);
174 /***====================================================================***/
177 ReportMismatch(unsigned action, unsigned field, const char *type)
179 ERROR("Value of %s field must be of type %s\n", fieldText(field), type);
180 ACTION("Action %s definition ignored\n", XkbcActionTypeText(action));
185 ReportIllegal(unsigned action, unsigned field)
187 ERROR("Field %s is not defined for an action of type %s\n",
188 fieldText(field), XkbcActionTypeText(action));
189 ACTION("Action definition ignored\n");
194 ReportActionNotArray(unsigned action, unsigned field)
196 ERROR("The %s field in the %s action is not an array\n",
197 fieldText(field), XkbcActionTypeText(action));
198 ACTION("Action definition ignored\n");
203 ReportNotFound(unsigned action, unsigned field, const char *what,
206 ERROR("%s named %s not found\n", what, bad);
207 ACTION("Ignoring the %s field of an %s action\n", fieldText(field),
208 XkbcActionTypeText(action));
213 HandleNoAction(struct xkb_desc * xkb,
214 struct xkb_any_action * action,
215 unsigned field, ExprDef * array_ndx, ExprDef * value)
217 return ReportIllegal(action->type, field);
221 CheckLatchLockFlags(unsigned action,
222 unsigned field, ExprDef * value, unsigned *flags_inout)
227 if (field == F_ClearLocks)
228 tmp = XkbSA_ClearLocks;
229 else if (field == F_LatchToLock)
230 tmp = XkbSA_LatchToLock;
232 return False; /* WSGO! */
233 if (!ExprResolveBoolean(value, &result))
234 return ReportMismatch(action, field, "boolean");
238 *flags_inout &= ~tmp;
243 CheckModifierField(struct xkb_desc * xkb,
246 unsigned *flags_inout, unsigned *mods_rtrn)
250 if (value->op == ExprIdent)
253 valStr = XkbcAtomText(value->value.str);
254 if (valStr && ((strcasecmp(valStr, "usemodmapmods") == 0) ||
255 (strcasecmp(valStr, "modmapmods") == 0)))
259 *flags_inout |= XkbSA_UseModMapMods;
263 if (!ExprResolveVModMask(value, &rtrn, xkb))
264 return ReportMismatch(action, F_Modifiers, "modifier mask");
265 *mods_rtrn = rtrn.uval;
266 *flags_inout &= ~XkbSA_UseModMapMods;
271 HandleSetLatchMods(struct xkb_desc * xkb,
272 struct xkb_any_action * action,
273 unsigned field, ExprDef * array_ndx, ExprDef * value)
275 struct xkb_mod_action *act;
279 act = (struct xkb_mod_action *) action;
280 if (array_ndx != NULL)
287 return ReportActionNotArray(action->type, field);
295 if (CheckLatchLockFlags(action->type, field, value, &rtrn))
303 if (CheckModifierField(xkb, action->type, value, &t1, &t2))
306 act->real_mods = act->mask = (t2 & 0xff);
307 act->vmods = (t2 >> 8) & 0xffff;
312 return ReportIllegal(action->type, field);
316 HandleLockMods(struct xkb_desc * xkb,
317 struct xkb_any_action * action,
318 unsigned field, ExprDef * array_ndx, ExprDef * value)
320 struct xkb_mod_action *act;
323 act = (struct xkb_mod_action *) action;
324 if ((array_ndx != NULL) && (field == F_Modifiers))
325 return ReportActionNotArray(action->type, field);
330 if (CheckModifierField(xkb, action->type, value, &t1, &t2))
333 act->real_mods = act->mask = (t2 & 0xff);
334 act->vmods = (t2 >> 8) & 0xffff;
339 return ReportIllegal(action->type, field);
343 CheckGroupField(unsigned action,
344 ExprDef * value, unsigned *flags_inout, int *grp_rtrn)
349 if ((value->op == OpNegate) || (value->op == OpUnaryPlus))
351 *flags_inout &= ~XkbSA_GroupAbsolute;
352 spec = value->value.child;
356 *flags_inout |= XkbSA_GroupAbsolute;
360 if (!ExprResolveGroup(spec, &rtrn))
361 return ReportMismatch(action, F_Group, "integer (range 1..8)");
362 if (value->op == OpNegate)
363 *grp_rtrn = -rtrn.ival;
364 else if (value->op == OpUnaryPlus)
365 *grp_rtrn = rtrn.ival;
367 *grp_rtrn = rtrn.ival - 1;
372 HandleSetLatchGroup(struct xkb_desc * xkb,
373 struct xkb_any_action * action,
374 unsigned field, ExprDef * array_ndx, ExprDef * value)
376 struct xkb_group_action *act;
381 act = (struct xkb_group_action *) action;
382 if (array_ndx != NULL)
389 return ReportActionNotArray(action->type, field);
397 if (CheckLatchLockFlags(action->type, field, value, &rtrn))
405 if (CheckGroupField(action->type, value, &t1, &t2))
413 return ReportIllegal(action->type, field);
417 HandleLockGroup(struct xkb_desc * xkb,
418 struct xkb_any_action * action,
419 unsigned field, ExprDef * array_ndx, ExprDef * value)
421 struct xkb_group_action *act;
425 act = (struct xkb_group_action *) action;
426 if ((array_ndx != NULL) && (field == F_Group))
427 return ReportActionNotArray(action->type, field);
428 if (field == F_Group)
431 if (CheckGroupField(action->type, value, &t1, &t2))
439 return ReportIllegal(action->type, field);
443 HandleMovePtr(struct xkb_desc * xkb,
444 struct xkb_any_action * action,
445 unsigned field, ExprDef * array_ndx, ExprDef * value)
448 struct xkb_pointer_action *act;
451 act = (struct xkb_pointer_action *) action;
452 if ((array_ndx != NULL) && ((field == F_X) || (field == F_Y)))
453 return ReportActionNotArray(action->type, field);
455 if ((field == F_X) || (field == F_Y))
457 if ((value->op == OpNegate) || (value->op == OpUnaryPlus))
461 if (!ExprResolveInteger(value, &rtrn))
462 return ReportMismatch(action->type, field, "integer");
466 act->flags |= XkbSA_MoveAbsoluteX;
472 act->flags |= XkbSA_MoveAbsoluteY;
477 else if (field == F_Accel)
479 if (!ExprResolveBoolean(value, &rtrn))
480 return ReportMismatch(action->type, field, "boolean");
482 act->flags &= ~XkbSA_NoAcceleration;
484 act->flags |= XkbSA_NoAcceleration;
486 return ReportIllegal(action->type, field);
489 static const LookupEntry lockWhich[] = {
491 {"lock", XkbSA_LockNoUnlock},
492 {"neither", (XkbSA_LockNoLock | XkbSA_LockNoUnlock)},
493 {"unlock", XkbSA_LockNoLock},
498 HandlePtrBtn(struct xkb_desc * xkb,
499 struct xkb_any_action * action,
500 unsigned field, ExprDef * array_ndx, ExprDef * value)
503 struct xkb_pointer_button_action *act;
505 act = (struct xkb_pointer_button_action *) action;
506 if (field == F_Button)
508 if (array_ndx != NULL)
509 return ReportActionNotArray(action->type, field);
510 if (!ExprResolveButton(value, &rtrn))
511 return ReportMismatch(action->type, field,
512 "integer (range 1..5)");
513 if ((rtrn.ival < 0) || (rtrn.ival > 5))
515 ERROR("Button must specify default or be in the range 1..5\n");
516 ACTION("Illegal button value %d ignored\n", rtrn.ival);
519 act->button = rtrn.ival;
522 else if ((action->type == XkbSA_LockPtrBtn) && (field == F_Affect))
524 if (array_ndx != NULL)
525 return ReportActionNotArray(action->type, field);
526 if (!ExprResolveEnum(value, &rtrn, lockWhich))
527 return ReportMismatch(action->type, field, "lock or unlock");
528 act->flags &= ~(XkbSA_LockNoLock | XkbSA_LockNoUnlock);
529 act->flags |= rtrn.ival;
532 else if (field == F_Count)
534 if (array_ndx != NULL)
535 return ReportActionNotArray(action->type, field);
536 if (!ExprResolveButton(value, &rtrn))
537 return ReportMismatch(action->type, field, "integer");
538 if ((rtrn.ival < 0) || (rtrn.ival > 255))
540 ERROR("The count field must have a value in the range 0..255\n");
541 ACTION("Illegal count %d ignored\n", rtrn.ival);
544 act->count = rtrn.ival;
547 return ReportIllegal(action->type, field);
550 static const LookupEntry ptrDflts[] = {
551 {"dfltbtn", XkbSA_AffectDfltBtn},
552 {"defaultbutton", XkbSA_AffectDfltBtn},
553 {"button", XkbSA_AffectDfltBtn},
558 HandleSetPtrDflt(struct xkb_desc * xkb,
559 struct xkb_any_action * action,
560 unsigned field, ExprDef * array_ndx, ExprDef * value)
563 struct xkb_pointer_default_action *act;
565 act = (struct xkb_pointer_default_action *) action;
566 if (field == F_Affect)
568 if (array_ndx != NULL)
569 return ReportActionNotArray(action->type, field);
570 if (!ExprResolveEnum(value, &rtrn, ptrDflts))
571 return ReportMismatch(action->type, field, "pointer component");
572 act->affect = rtrn.uval;
575 else if ((field == F_Button) || (field == F_Value))
578 if (array_ndx != NULL)
579 return ReportActionNotArray(action->type, field);
580 if ((value->op == OpNegate) || (value->op == OpUnaryPlus))
582 act->flags &= ~XkbSA_DfltBtnAbsolute;
583 btn = value->value.child;
587 act->flags |= XkbSA_DfltBtnAbsolute;
591 if (!ExprResolveButton(btn, &rtrn))
592 return ReportMismatch(action->type, field,
593 "integer (range 1..5)");
594 if ((rtrn.ival < 0) || (rtrn.ival > 5))
596 ERROR("New default button value must be in the range 1..5\n");
597 ACTION("Illegal default button value %d ignored\n", rtrn.ival);
602 ERROR("Cannot set default pointer button to \"default\"\n");
603 ACTION("Illegal default button setting ignored\n");
606 if (value->op == OpNegate)
607 act->value = -rtrn.ival;
609 act->value = rtrn.ival;
612 return ReportIllegal(action->type, field);
615 static const LookupEntry isoNames[] = {
616 {"mods", XkbSA_ISONoAffectMods},
617 {"modifiers", XkbSA_ISONoAffectMods},
618 {"group", XkbSA_ISONoAffectGroup},
619 {"groups", XkbSA_ISONoAffectGroup},
620 {"ptr", XkbSA_ISONoAffectPtr},
621 {"pointer", XkbSA_ISONoAffectPtr},
622 {"ctrls", XkbSA_ISONoAffectCtrls},
623 {"controls", XkbSA_ISONoAffectCtrls},
624 {"all", ~((unsigned) 0)},
630 HandleISOLock(struct xkb_desc * xkb,
631 struct xkb_any_action * action,
632 unsigned field, ExprDef * array_ndx, ExprDef * value)
635 struct xkb_iso_action *act;
636 unsigned flags, mods;
639 act = (struct xkb_iso_action *) action;
643 if (array_ndx != NULL)
644 return ReportActionNotArray(action->type, field);
646 if (CheckModifierField(xkb, action->type, value, &flags, &mods))
648 act->flags = flags & (~XkbSA_ISODfltIsGroup);
649 act->real_mods = mods & 0xff;
650 act->vmods = (mods >> 8) & 0xff;
655 if (array_ndx != NULL)
656 return ReportActionNotArray(action->type, field);
658 if (CheckGroupField(action->type, value, &flags, &group))
660 act->flags = flags | XkbSA_ISODfltIsGroup;
666 if (array_ndx != NULL)
667 return ReportActionNotArray(action->type, field);
668 if (!ExprResolveMask(value, &rtrn, isoNames))
669 return ReportMismatch(action->type, field, "keyboard component");
670 act->affect = (~rtrn.uval) & XkbSA_ISOAffectMask;
673 return ReportIllegal(action->type, field);
677 HandleSwitchScreen(struct xkb_desc * xkb,
678 struct xkb_any_action * action,
679 unsigned field, ExprDef * array_ndx, ExprDef * value)
682 struct xkb_switch_screen_action *act;
684 act = (struct xkb_switch_screen_action *) action;
685 if (field == F_Screen)
688 if (array_ndx != NULL)
689 return ReportActionNotArray(action->type, field);
690 if ((value->op == OpNegate) || (value->op == OpUnaryPlus))
692 act->flags &= ~XkbSA_SwitchAbsolute;
693 scrn = value->value.child;
697 act->flags |= XkbSA_SwitchAbsolute;
701 if (!ExprResolveInteger(scrn, &rtrn))
702 return ReportMismatch(action->type, field, "integer (0..255)");
703 if ((rtrn.ival < 0) || (rtrn.ival > 255))
705 ERROR("Screen index must be in the range 1..255\n");
706 ACTION("Illegal screen value %d ignored\n", rtrn.ival);
709 if (value->op == OpNegate)
710 act->screen = -rtrn.ival;
712 act->screen = rtrn.ival;
715 else if (field == F_Same)
717 if (array_ndx != NULL)
718 return ReportActionNotArray(action->type, field);
719 if (!ExprResolveBoolean(value, &rtrn))
720 return ReportMismatch(action->type, field, "boolean");
722 act->flags &= ~XkbSA_SwitchApplication;
724 act->flags |= XkbSA_SwitchApplication;
727 return ReportIllegal(action->type, field);
730 const LookupEntry ctrlNames[] = {
731 {"repeatkeys", XkbRepeatKeysMask},
732 {"repeat", XkbRepeatKeysMask},
733 {"autorepeat", XkbRepeatKeysMask},
734 {"slowkeys", XkbSlowKeysMask},
735 {"bouncekeys", XkbBounceKeysMask},
736 {"stickykeys", XkbStickyKeysMask},
737 {"mousekeys", XkbMouseKeysMask},
738 {"mousekeysaccel", XkbMouseKeysAccelMask},
739 {"accessxkeys", XkbAccessXKeysMask},
740 {"accessxtimeout", XkbAccessXTimeoutMask},
741 {"accessxfeedback", XkbAccessXFeedbackMask},
742 {"audiblebell", XkbAudibleBellMask},
743 {"ignoregrouplock", XkbIgnoreGroupLockMask},
744 {"all", XkbAllBooleanCtrlsMask},
752 HandleSetLockControls(struct xkb_desc * xkb,
753 struct xkb_any_action * action,
754 unsigned field, ExprDef * array_ndx, ExprDef * value)
757 struct xkb_controls_action *act;
759 act = (struct xkb_controls_action *) action;
760 if (field == F_Controls)
762 if (array_ndx != NULL)
763 return ReportActionNotArray(action->type, field);
764 if (!ExprResolveMask(value, &rtrn, ctrlNames))
765 return ReportMismatch(action->type, field, "controls mask");
766 act->ctrls = rtrn.uval;
769 return ReportIllegal(action->type, field);
772 static const LookupEntry evNames[] = {
773 {"press", XkbSA_MessageOnPress},
774 {"keypress", XkbSA_MessageOnPress},
775 {"release", XkbSA_MessageOnRelease},
776 {"keyrelease", XkbSA_MessageOnRelease},
777 {"all", XkbSA_MessageOnPress | XkbSA_MessageOnRelease},
783 HandleActionMessage(struct xkb_desc * xkb,
784 struct xkb_any_action * action,
785 unsigned field, ExprDef * array_ndx, ExprDef * value)
788 struct xkb_message_action *act;
790 act = (struct xkb_message_action *) action;
794 if (array_ndx != NULL)
795 return ReportActionNotArray(action->type, field);
796 if (!ExprResolveMask(value, &rtrn, evNames))
797 return ReportMismatch(action->type, field, "key event mask");
798 act->flags &= ~(XkbSA_MessageOnPress | XkbSA_MessageOnRelease);
800 rtrn.uval & (XkbSA_MessageOnPress | XkbSA_MessageOnRelease);
803 if (array_ndx != NULL)
804 return ReportActionNotArray(action->type, field);
805 if (!ExprResolveBoolean(value, &rtrn))
806 return ReportMismatch(action->type, field, "boolean");
808 act->flags |= XkbSA_MessageGenKeyEvent;
810 act->flags &= ~XkbSA_MessageGenKeyEvent;
813 if (array_ndx == NULL)
815 if (!ExprResolveString(value, &rtrn))
816 return ReportMismatch(action->type, field, "string");
819 int len = strlen(rtrn.str);
820 if ((len < 1) || (len > 6))
822 WARN("An action message can hold only 6 bytes\n");
823 ACTION("Extra %d bytes ignored\n", len - 6);
825 strncpy((char *) act->message, rtrn.str, 6);
832 if (!ExprResolveInteger(array_ndx, &rtrn))
834 ERROR("Array subscript must be integer\n");
835 ACTION("Illegal subscript ignored\n");
841 ERROR("An action message is at most 6 bytes long\n");
842 ACTION("Attempt to use data[%d] ignored\n", ndx);
845 if (!ExprResolveInteger(value, &rtrn))
846 return ReportMismatch(action->type, field, "integer");
847 if ((rtrn.ival < 0) || (rtrn.ival > 255))
849 ERROR("Message data must be in the range 0..255\n");
850 ACTION("Illegal datum %d ignored\n", rtrn.ival);
853 act->message[ndx] = rtrn.uval;
857 return ReportIllegal(action->type, field);
861 HandleRedirectKey(struct xkb_desc * xkb,
862 struct xkb_any_action * action,
863 unsigned field, ExprDef * array_ndx, ExprDef * value)
866 struct xkb_redirect_key_action *act;
871 if (array_ndx != NULL)
872 return ReportActionNotArray(action->type, field);
874 act = (struct xkb_redirect_key_action *) action;
878 if (!ExprResolveKeyName(value, &rtrn))
879 return ReportMismatch(action->type, field, "key name");
880 tmp = KeyNameToLong(rtrn.keyName.name);
881 if (!FindNamedKey(xkb, tmp, &kc, True, CreateKeyNames(xkb), 0))
883 return ReportNotFound(action->type, field, "Key",
884 XkbcKeyNameText(rtrn.keyName.name));
891 if (CheckModifierField(xkb, action->type, value, &t1, &t2))
893 act->mods_mask |= (t2 & 0xff);
894 if (field == F_Modifiers)
895 act->mods |= (t2 & 0xff);
897 act->mods &= ~(t2 & 0xff);
899 t2 = (t2 >> 8) & 0xffff;
900 act->vmods_mask |= t2;
901 if (field == F_Modifiers)
909 return ReportIllegal(action->type, field);
913 HandleDeviceBtn(struct xkb_desc * xkb,
914 struct xkb_any_action * action,
915 unsigned field, ExprDef * array_ndx, ExprDef * value)
918 struct xkb_device_button_action *act;
920 act = (struct xkb_device_button_action *) action;
921 if (field == F_Button)
923 if (array_ndx != NULL)
924 return ReportActionNotArray(action->type, field);
925 if (!ExprResolveInteger(value, &rtrn))
926 return ReportMismatch(action->type, field,
927 "integer (range 1..255)");
928 if ((rtrn.ival < 0) || (rtrn.ival > 255))
930 ERROR("Button must specify default or be in the range 1..255\n");
931 ACTION("Illegal button value %d ignored\n", rtrn.ival);
934 act->button = rtrn.ival;
937 else if ((action->type == XkbSA_LockDeviceBtn) && (field == F_Affect))
939 if (array_ndx != NULL)
940 return ReportActionNotArray(action->type, field);
941 if (!ExprResolveEnum(value, &rtrn, lockWhich))
942 return ReportMismatch(action->type, field, "lock or unlock");
943 act->flags &= ~(XkbSA_LockNoLock | XkbSA_LockNoUnlock);
944 act->flags |= rtrn.ival;
947 else if (field == F_Count)
949 if (array_ndx != NULL)
950 return ReportActionNotArray(action->type, field);
951 if (!ExprResolveButton(value, &rtrn))
952 return ReportMismatch(action->type, field, "integer");
953 if ((rtrn.ival < 0) || (rtrn.ival > 255))
955 ERROR("The count field must have a value in the range 0..255\n");
956 ACTION("Illegal count %d ignored\n", rtrn.ival);
959 act->count = rtrn.ival;
962 else if (field == F_Device)
964 if (array_ndx != NULL)
965 return ReportActionNotArray(action->type, field);
966 if (!ExprResolveInteger(value, &rtrn))
967 return ReportMismatch(action->type, field,
968 "integer (range 1..255)");
969 if ((rtrn.ival < 0) || (rtrn.ival > 255))
971 ERROR("Device must specify default or be in the range 1..255\n");
972 ACTION("Illegal device value %d ignored\n", rtrn.ival);
975 act->device = rtrn.ival;
978 return ReportIllegal(action->type, field);
982 HandleDeviceValuator(struct xkb_desc * xkb,
983 struct xkb_any_action * action,
984 unsigned field, ExprDef * array_ndx, ExprDef * value)
988 struct xkb_device_valuator_action *act;
990 act = (struct xkb_device_valuator_action *) action;
991 /* XXX - Not yet implemented */
997 HandlePrivate(struct xkb_desc * xkb,
998 struct xkb_any_action * action,
999 unsigned field, ExprDef * array_ndx, ExprDef * value)
1006 if (!ExprResolveInteger(value, &rtrn))
1007 return ReportMismatch(PrivateAction, field, "integer");
1008 if ((rtrn.ival < 0) || (rtrn.ival > 255))
1010 ERROR("Private action type must be in the range 0..255\n");
1011 ACTION("Illegal type %d ignored\n", rtrn.ival);
1014 action->type = rtrn.uval;
1017 if (array_ndx == NULL)
1019 if (!ExprResolveString(value, &rtrn))
1020 return ReportMismatch(action->type, field, "string");
1023 int len = strlen(rtrn.str);
1024 if ((len < 1) || (len > 7))
1026 WARN("A private action has 7 data bytes\n");
1027 ACTION("Extra %d bytes ignored\n", len - 6);
1030 strncpy((char *) action->data, rtrn.str, sizeof action->data);
1038 if (!ExprResolveInteger(array_ndx, &rtrn))
1040 ERROR("Array subscript must be integer\n");
1041 ACTION("Illegal subscript ignored\n");
1045 if (ndx >= sizeof action->data)
1047 ERROR("The data for a private action is 18 bytes long\n");
1048 ACTION("Attempt to use data[%d] ignored\n", ndx);
1051 if (!ExprResolveInteger(value, &rtrn))
1052 return ReportMismatch(action->type, field, "integer");
1053 if ((rtrn.ival < 0) || (rtrn.ival > 255))
1055 ERROR("All data for a private action must be 0..255\n");
1056 ACTION("Illegal datum %d ignored\n", rtrn.ival);
1059 action->data[ndx] = rtrn.uval;
1063 return ReportIllegal(PrivateAction, field);
1066 typedef Bool(*actionHandler) (struct xkb_desc * /* xkb */ ,
1067 struct xkb_any_action * /* action */ ,
1068 unsigned /* field */ ,
1069 ExprDef * /* array_ndx */ ,
1070 ExprDef * /* value */
1073 static const actionHandler handleAction[XkbSA_NumActions + 1] = {
1074 HandleNoAction /* NoAction */ ,
1075 HandleSetLatchMods /* SetMods */ ,
1076 HandleSetLatchMods /* LatchMods */ ,
1077 HandleLockMods /* LockMods */ ,
1078 HandleSetLatchGroup /* SetGroup */ ,
1079 HandleSetLatchGroup /* LatchGroup */ ,
1080 HandleLockGroup /* LockGroup */ ,
1081 HandleMovePtr /* MovePtr */ ,
1082 HandlePtrBtn /* PtrBtn */ ,
1083 HandlePtrBtn /* LockPtrBtn */ ,
1084 HandleSetPtrDflt /* SetPtrDflt */ ,
1085 HandleISOLock /* ISOLock */ ,
1086 HandleNoAction /* Terminate */ ,
1087 HandleSwitchScreen /* SwitchScreen */ ,
1088 HandleSetLockControls /* SetControls */ ,
1089 HandleSetLockControls /* LockControls */ ,
1090 HandleActionMessage /* ActionMessage */ ,
1091 HandleRedirectKey /* RedirectKey */ ,
1092 HandleDeviceBtn /* DeviceBtn */ ,
1093 HandleDeviceBtn /* LockDeviceBtn */ ,
1094 HandleDeviceValuator /* DeviceValuatr */ ,
1095 HandlePrivate /* Private */
1098 /***====================================================================***/
1101 ApplyActionFactoryDefaults(union xkb_action * action)
1103 if (action->type == XkbSA_SetPtrDflt)
1104 { /* increment default button */
1105 action->dflt.affect = XkbSA_AffectDfltBtn;
1106 action->dflt.flags = 0;
1107 action->dflt.value = 1;
1109 else if (action->type == XkbSA_ISOLock)
1111 action->iso.real_mods = LockMask;
1119 HandleActionDef(ExprDef * def,
1120 struct xkb_desc * xkb,
1121 struct xkb_any_action * action, unsigned mergeMode, ActionInfo * info)
1125 unsigned tmp, hndlrType;
1127 if (!actionsInitialized)
1130 if (def->op != ExprActionDecl)
1132 ERROR("Expected an action definition, found %s\n",
1133 exprOpText(def->op));
1136 str = XkbcAtomText(def->value.action.name);
1139 WSGO("Missing name in action definition!!\n");
1142 if (!stringToAction(str, &tmp))
1144 ERROR("Unknown action %s\n", str);
1147 action->type = hndlrType = tmp;
1148 if (action->type != XkbSA_NoAction)
1150 ApplyActionFactoryDefaults((union xkb_action *) action);
1153 if ((info->action == XkbSA_NoAction)
1154 || (info->action == hndlrType))
1156 if (!(*handleAction[hndlrType]) (xkb, action,
1167 for (arg = def->value.action.args; arg != NULL;
1168 arg = (ExprDef *) arg->common.next)
1170 ExprDef *field, *value, *arrayRtrn;
1171 ExprResult elemRtrn, fieldRtrn;
1174 if (arg->op == OpAssign)
1176 field = arg->value.binary.left;
1177 value = arg->value.binary.right;
1181 if ((arg->op == OpNot) || (arg->op == OpInvert))
1183 field = arg->value.child;
1184 value = &constFalse;
1192 if (!ExprResolveLhs(field, &elemRtrn, &fieldRtrn, &arrayRtrn))
1193 return False; /* internal error -- already reported */
1195 if (elemRtrn.str != NULL)
1197 ERROR("Cannot change defaults in an action definition\n");
1198 ACTION("Ignoring attempt to change %s.%s\n", elemRtrn.str,
1201 free(fieldRtrn.str);
1204 if (!stringToField(fieldRtrn.str, &fieldNdx))
1206 ERROR("Unknown field name %s\n", uStringText(fieldRtrn.str));
1208 free(fieldRtrn.str);
1212 free(fieldRtrn.str);
1213 if (!(*handleAction[hndlrType])
1214 (xkb, action, fieldNdx, arrayRtrn, value))
1222 /***====================================================================***/
1225 SetActionField(struct xkb_desc * xkb,
1228 ExprDef * array_ndx, ExprDef * value, ActionInfo ** info_rtrn)
1230 ActionInfo *new, *old;
1232 if (!actionsInitialized)
1235 new = uTypedAlloc(ActionInfo);
1238 WSGO("Couldn't allocate space for action default\n");
1241 if (strcasecmp(elem, "action") == 0)
1242 new->action = XkbSA_NoAction;
1245 if (!stringToAction(elem, &new->action))
1250 if (new->action == XkbSA_NoAction)
1252 ERROR("\"%s\" is not a valid field in a NoAction action\n",
1258 if (!stringToField(field, &new->field))
1260 ERROR("\"%s\" is not a legal field name\n", field);
1264 new->array_ndx = array_ndx;
1268 while ((old) && (old->next))
1277 /***====================================================================***/
1282 if (!actionsInitialized)
1284 memset(&constTrue, 0, sizeof(constTrue));
1285 memset(&constFalse, 0, sizeof(constFalse));
1286 constTrue.common.stmtType = StmtExpr;
1287 constTrue.common.next = NULL;
1288 constTrue.op = ExprIdent;
1289 constTrue.type = TypeBoolean;
1290 constTrue.value.str = xkb_intern_atom("true");
1291 constFalse.common.stmtType = StmtExpr;
1292 constFalse.common.next = NULL;
1293 constFalse.op = ExprIdent;
1294 constFalse.type = TypeBoolean;
1295 constFalse.value.str = xkb_intern_atom("false");
1296 actionsInitialized = 1;