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 /***====================================================================***/
44 stringToAction(char *str, unsigned *type_rtrn)
49 if (uStrCaseCmp(str, "noaction") == 0)
50 *type_rtrn = XkbSA_NoAction;
51 else if (uStrCaseCmp(str, "setmods") == 0)
52 *type_rtrn = XkbSA_SetMods;
53 else if (uStrCaseCmp(str, "latchmods") == 0)
54 *type_rtrn = XkbSA_LatchMods;
55 else if (uStrCaseCmp(str, "lockmods") == 0)
56 *type_rtrn = XkbSA_LockMods;
57 else if (uStrCaseCmp(str, "setgroup") == 0)
58 *type_rtrn = XkbSA_SetGroup;
59 else if (uStrCaseCmp(str, "latchgroup") == 0)
60 *type_rtrn = XkbSA_LatchGroup;
61 else if (uStrCaseCmp(str, "lockgroup") == 0)
62 *type_rtrn = XkbSA_LockGroup;
63 else if (uStrCaseCmp(str, "moveptr") == 0)
64 *type_rtrn = XkbSA_MovePtr;
65 else if (uStrCaseCmp(str, "movepointer") == 0)
66 *type_rtrn = XkbSA_MovePtr;
67 else if (uStrCaseCmp(str, "ptrbtn") == 0)
68 *type_rtrn = XkbSA_PtrBtn;
69 else if (uStrCaseCmp(str, "pointerbutton") == 0)
70 *type_rtrn = XkbSA_PtrBtn;
71 else if (uStrCaseCmp(str, "lockptrbtn") == 0)
72 *type_rtrn = XkbSA_LockPtrBtn;
73 else if (uStrCaseCmp(str, "lockpointerbutton") == 0)
74 *type_rtrn = XkbSA_LockPtrBtn;
75 else if (uStrCaseCmp(str, "lockptrbutton") == 0)
76 *type_rtrn = XkbSA_LockPtrBtn;
77 else if (uStrCaseCmp(str, "lockpointerbtn") == 0)
78 *type_rtrn = XkbSA_LockPtrBtn;
79 else if (uStrCaseCmp(str, "setptrdflt") == 0)
80 *type_rtrn = XkbSA_SetPtrDflt;
81 else if (uStrCaseCmp(str, "setpointerdefault") == 0)
82 *type_rtrn = XkbSA_SetPtrDflt;
83 else if (uStrCaseCmp(str, "isolock") == 0)
84 *type_rtrn = XkbSA_ISOLock;
85 else if (uStrCaseCmp(str, "terminate") == 0)
86 *type_rtrn = XkbSA_Terminate;
87 else if (uStrCaseCmp(str, "terminateserver") == 0)
88 *type_rtrn = XkbSA_Terminate;
89 else if (uStrCaseCmp(str, "switchscreen") == 0)
90 *type_rtrn = XkbSA_SwitchScreen;
91 else if (uStrCaseCmp(str, "setcontrols") == 0)
92 *type_rtrn = XkbSA_SetControls;
93 else if (uStrCaseCmp(str, "lockcontrols") == 0)
94 *type_rtrn = XkbSA_LockControls;
95 else if (uStrCaseCmp(str, "actionmessage") == 0)
96 *type_rtrn = XkbSA_ActionMessage;
97 else if (uStrCaseCmp(str, "messageaction") == 0)
98 *type_rtrn = XkbSA_ActionMessage;
99 else if (uStrCaseCmp(str, "message") == 0)
100 *type_rtrn = XkbSA_ActionMessage;
101 else if (uStrCaseCmp(str, "redirect") == 0)
102 *type_rtrn = XkbSA_RedirectKey;
103 else if (uStrCaseCmp(str, "redirectkey") == 0)
104 *type_rtrn = XkbSA_RedirectKey;
105 else if (uStrCaseCmp(str, "devbtn") == 0)
106 *type_rtrn = XkbSA_DeviceBtn;
107 else if (uStrCaseCmp(str, "devicebtn") == 0)
108 *type_rtrn = XkbSA_DeviceBtn;
109 else if (uStrCaseCmp(str, "devbutton") == 0)
110 *type_rtrn = XkbSA_DeviceBtn;
111 else if (uStrCaseCmp(str, "devicebutton") == 0)
112 *type_rtrn = XkbSA_DeviceBtn;
113 else if (uStrCaseCmp(str, "lockdevbtn") == 0)
114 *type_rtrn = XkbSA_DeviceBtn;
115 else if (uStrCaseCmp(str, "lockdevicebtn") == 0)
116 *type_rtrn = XkbSA_LockDeviceBtn;
117 else if (uStrCaseCmp(str, "lockdevbutton") == 0)
118 *type_rtrn = XkbSA_LockDeviceBtn;
119 else if (uStrCaseCmp(str, "lockdevicebutton") == 0)
120 *type_rtrn = XkbSA_LockDeviceBtn;
121 else if (uStrCaseCmp(str, "devval") == 0)
122 *type_rtrn = XkbSA_DeviceValuator;
123 else if (uStrCaseCmp(str, "deviceval") == 0)
124 *type_rtrn = XkbSA_DeviceValuator;
125 else if (uStrCaseCmp(str, "devvaluator") == 0)
126 *type_rtrn = XkbSA_DeviceValuator;
127 else if (uStrCaseCmp(str, "devicevaluator") == 0)
128 *type_rtrn = XkbSA_DeviceValuator;
129 else if (uStrCaseCmp(str, "private") == 0)
130 *type_rtrn = PrivateAction;
137 stringToField(char *str, unsigned *field_rtrn)
143 if (uStrCaseCmp(str, "clearlocks") == 0)
144 *field_rtrn = F_ClearLocks;
145 else if (uStrCaseCmp(str, "latchtolock") == 0)
146 *field_rtrn = F_LatchToLock;
147 else if (uStrCaseCmp(str, "genkeyevent") == 0)
148 *field_rtrn = F_GenKeyEvent;
149 else if (uStrCaseCmp(str, "generatekeyevent") == 0)
150 *field_rtrn = F_GenKeyEvent;
151 else if (uStrCaseCmp(str, "report") == 0)
152 *field_rtrn = F_Report;
153 else if (uStrCaseCmp(str, "default") == 0)
154 *field_rtrn = F_Default;
155 else if (uStrCaseCmp(str, "affect") == 0)
156 *field_rtrn = F_Affect;
157 else if (uStrCaseCmp(str, "increment") == 0)
158 *field_rtrn = F_Increment;
159 else if (uStrCaseCmp(str, "mods") == 0)
160 *field_rtrn = F_Modifiers;
161 else if (uStrCaseCmp(str, "modifiers") == 0)
162 *field_rtrn = F_Modifiers;
163 else if (uStrCaseCmp(str, "group") == 0)
164 *field_rtrn = F_Group;
165 else if (uStrCaseCmp(str, "x") == 0)
167 else if (uStrCaseCmp(str, "y") == 0)
169 else if (uStrCaseCmp(str, "accel") == 0)
170 *field_rtrn = F_Accel;
171 else if (uStrCaseCmp(str, "accelerate") == 0)
172 *field_rtrn = F_Accel;
173 else if (uStrCaseCmp(str, "repeat") == 0)
174 *field_rtrn = F_Accel;
175 else if (uStrCaseCmp(str, "button") == 0)
176 *field_rtrn = F_Button;
177 else if (uStrCaseCmp(str, "value") == 0)
178 *field_rtrn = F_Value;
179 else if (uStrCaseCmp(str, "controls") == 0)
180 *field_rtrn = F_Controls;
181 else if (uStrCaseCmp(str, "ctrls") == 0)
182 *field_rtrn = F_Controls;
183 else if (uStrCaseCmp(str, "type") == 0)
184 *field_rtrn = F_Type;
185 else if (uStrCaseCmp(str, "count") == 0)
186 *field_rtrn = F_Count;
187 else if (uStrCaseCmp(str, "screen") == 0)
188 *field_rtrn = F_Screen;
189 else if (uStrCaseCmp(str, "same") == 0)
190 *field_rtrn = F_Same;
191 else if (uStrCaseCmp(str, "sameserver") == 0)
192 *field_rtrn = F_Same;
193 else if (uStrCaseCmp(str, "data") == 0)
194 *field_rtrn = F_Data;
195 else if (uStrCaseCmp(str, "device") == 0)
196 *field_rtrn = F_Device;
197 else if (uStrCaseCmp(str, "dev") == 0)
198 *field_rtrn = F_Device;
199 else if (uStrCaseCmp(str, "key") == 0)
200 *field_rtrn = F_Keycode;
201 else if (uStrCaseCmp(str, "keycode") == 0)
202 *field_rtrn = F_Keycode;
203 else if (uStrCaseCmp(str, "kc") == 0)
204 *field_rtrn = F_Keycode;
205 else if (uStrCaseCmp(str, "clearmods") == 0)
206 *field_rtrn = F_ModsToClear;
207 else if (uStrCaseCmp(str, "clearmodifiers") == 0)
208 *field_rtrn = F_ModsToClear;
215 fieldText(unsigned field)
222 strcpy(buf, "clearLocks");
225 strcpy(buf, "latchToLock");
228 strcpy(buf, "genKeyEvent");
231 strcpy(buf, "report");
234 strcpy(buf, "default");
237 strcpy(buf, "affect");
240 strcpy(buf, "increment");
243 strcpy(buf, "modifiers");
246 strcpy(buf, "group");
255 strcpy(buf, "accel");
258 strcpy(buf, "button");
261 strcpy(buf, "value");
264 strcpy(buf, "controls");
270 strcpy(buf, "count");
273 strcpy(buf, "screen");
276 strcpy(buf, "sameServer");
282 strcpy(buf, "device");
285 strcpy(buf, "keycode");
288 strcpy(buf, "clearmods");
291 strcpy(buf, "unknown");
297 /***====================================================================***/
300 ReportMismatch(unsigned action, unsigned field, const char *type)
302 ERROR2("Value of %s field must be of type %s\n", fieldText(field), type);
303 ACTION1("Action %s definition ignored\n", XkbActionTypeText(action));
308 ReportIllegal(unsigned action, unsigned field)
310 ERROR2("Field %s is not defined for an action of type %s\n",
311 fieldText(field), XkbActionTypeText(action));
312 ACTION("Action definition ignored\n");
317 ReportActionNotArray(unsigned action, unsigned field)
319 ERROR2("The %s field in the %s action is not an array\n",
320 fieldText(field), XkbActionTypeText(action));
321 ACTION("Action definition ignored\n");
326 ReportNotFound(unsigned action, unsigned field, const char *what, char *bad)
328 ERROR2("%s named %s not found\n", what, bad);
329 ACTION2("Ignoring the %s field of an %s action\n", fieldText(field),
330 XkbActionTypeText(action));
335 HandleNoAction(XkbcDescPtr xkb,
336 XkbAnyAction * action,
337 unsigned field, ExprDef * array_ndx, ExprDef * value)
339 return ReportIllegal(action->type, field);
343 CheckLatchLockFlags(unsigned action,
344 unsigned field, ExprDef * value, unsigned *flags_inout)
349 if (field == F_ClearLocks)
350 tmp = XkbSA_ClearLocks;
351 else if (field == F_LatchToLock)
352 tmp = XkbSA_LatchToLock;
354 return False; /* WSGO! */
355 if (!ExprResolveBoolean(value, &result, NULL, NULL))
356 return ReportMismatch(action, field, "boolean");
360 *flags_inout &= ~tmp;
365 CheckModifierField(XkbcDescPtr xkb,
368 unsigned *flags_inout, unsigned *mods_rtrn)
372 if (value->op == ExprIdent)
374 register char *valStr;
375 valStr = XkbcAtomGetString(value->value.str);
376 if (valStr && ((uStrCaseCmp(valStr, "usemodmapmods") == 0) ||
377 (uStrCaseCmp(valStr, "modmapmods") == 0)))
381 *flags_inout |= XkbSA_UseModMapMods;
385 if (!ExprResolveModMask(value, &rtrn, LookupVModMask, (char *) xkb))
386 return ReportMismatch(action, F_Modifiers, "modifier mask");
387 *mods_rtrn = rtrn.uval;
388 *flags_inout &= ~XkbSA_UseModMapMods;
393 HandleSetLatchMods(XkbcDescPtr xkb,
394 XkbAnyAction * action,
395 unsigned field, ExprDef * array_ndx, ExprDef * value)
401 act = (XkbModAction *) action;
402 if (array_ndx != NULL)
409 return ReportActionNotArray(action->type, field);
417 if (CheckLatchLockFlags(action->type, field, value, &rtrn))
425 if (CheckModifierField(xkb, action->type, value, &t1, &t2))
428 act->real_mods = act->mask = (t2 & 0xff);
429 t2 = (t2 >> 8) & 0xffff;
430 XkbSetModActionVMods(act, t2);
435 return ReportIllegal(action->type, field);
439 HandleLockMods(XkbcDescPtr xkb,
440 XkbAnyAction * action,
441 unsigned field, ExprDef * array_ndx, ExprDef * value)
446 act = (XkbModAction *) action;
447 if ((array_ndx != NULL) && (field == F_Modifiers))
448 return ReportActionNotArray(action->type, field);
453 if (CheckModifierField(xkb, action->type, value, &t1, &t2))
456 act->real_mods = act->mask = (t2 & 0xff);
457 t2 = (t2 >> 8) & 0xffff;
458 XkbSetModActionVMods(act, t2);
463 return ReportIllegal(action->type, field);
466 static LookupEntry groupNames[] = {
479 CheckGroupField(unsigned action,
480 ExprDef * value, unsigned *flags_inout, int *grp_rtrn)
485 if ((value->op == OpNegate) || (value->op == OpUnaryPlus))
487 *flags_inout &= ~XkbSA_GroupAbsolute;
488 spec = value->value.child;
492 *flags_inout |= XkbSA_GroupAbsolute;
496 if (!ExprResolveInteger(spec, &rtrn, SimpleLookup, (char *) groupNames))
497 return ReportMismatch(action, F_Group, "integer (range 1..8)");
498 if ((rtrn.ival < 1) || (rtrn.ival > XkbNumKbdGroups))
500 ERROR2("Illegal group %d (must be in the range 1..%d)\n", rtrn.ival,
502 ACTION1("Action %s definition ignored\n", XkbActionTypeText(action));
505 if (value->op == OpNegate)
506 *grp_rtrn = -rtrn.ival;
507 else if (value->op == OpUnaryPlus)
508 *grp_rtrn = rtrn.ival;
510 *grp_rtrn = rtrn.ival - 1;
515 HandleSetLatchGroup(XkbcDescPtr xkb,
516 XkbAnyAction * action,
517 unsigned field, ExprDef * array_ndx, ExprDef * value)
524 act = (XkbGroupAction *) action;
525 if (array_ndx != NULL)
532 return ReportActionNotArray(action->type, field);
540 if (CheckLatchLockFlags(action->type, field, value, &rtrn))
548 if (CheckGroupField(action->type, value, &t1, &t2))
551 XkbSASetGroup(act, t2);
556 return ReportIllegal(action->type, field);
560 HandleLockGroup(XkbcDescPtr xkb,
561 XkbAnyAction * action,
562 unsigned field, ExprDef * array_ndx, ExprDef * value)
568 act = (XkbGroupAction *) action;
569 if ((array_ndx != NULL) && (field == F_Group))
570 return ReportActionNotArray(action->type, field);
571 if (field == F_Group)
574 if (CheckGroupField(action->type, value, &t1, &t2))
577 XkbSASetGroup(act, t2);
582 return ReportIllegal(action->type, field);
586 HandleMovePtr(XkbcDescPtr xkb,
587 XkbAnyAction * action,
588 unsigned field, ExprDef * array_ndx, ExprDef * value)
594 act = (XkbPtrAction *) action;
595 if ((array_ndx != NULL) && ((field == F_X) || (field == F_Y)))
596 return ReportActionNotArray(action->type, field);
598 if ((field == F_X) || (field == F_Y))
600 if ((value->op == OpNegate) || (value->op == OpUnaryPlus))
604 if (!ExprResolveInteger(value, &rtrn, NULL, NULL))
605 return ReportMismatch(action->type, field, "integer");
609 act->flags |= XkbSA_MoveAbsoluteX;
610 XkbSetPtrActionX(act, rtrn.ival);
615 act->flags |= XkbSA_MoveAbsoluteY;
616 XkbSetPtrActionY(act, rtrn.ival);
620 else if (field == F_Accel)
622 if (!ExprResolveBoolean(value, &rtrn, NULL, NULL))
623 return ReportMismatch(action->type, field, "boolean");
625 act->flags &= ~XkbSA_NoAcceleration;
627 act->flags |= XkbSA_NoAcceleration;
629 return ReportIllegal(action->type, field);
632 static LookupEntry btnNames[] = {
642 static LookupEntry lockWhich[] = {
644 {"lock", XkbSA_LockNoUnlock},
645 {"neither", (XkbSA_LockNoLock | XkbSA_LockNoUnlock)},
646 {"unlock", XkbSA_LockNoLock},
651 HandlePtrBtn(XkbcDescPtr xkb,
652 XkbAnyAction * action,
653 unsigned field, ExprDef * array_ndx, ExprDef * value)
656 XkbPtrBtnAction *act;
658 act = (XkbPtrBtnAction *) action;
659 if (field == F_Button)
661 if (array_ndx != NULL)
662 return ReportActionNotArray(action->type, field);
663 if (!ExprResolveInteger
664 (value, &rtrn, SimpleLookup, (char *) btnNames))
665 return ReportMismatch(action->type, field,
666 "integer (range 1..5)");
667 if ((rtrn.ival < 0) || (rtrn.ival > 5))
669 ERROR("Button must specify default or be in the range 1..5\n");
670 ACTION1("Illegal button value %d ignored\n", rtrn.ival);
673 act->button = rtrn.ival;
676 else if ((action->type == XkbSA_LockPtrBtn) && (field == F_Affect))
678 if (array_ndx != NULL)
679 return ReportActionNotArray(action->type, field);
680 if (!ExprResolveEnum(value, &rtrn, lockWhich))
681 return ReportMismatch(action->type, field, "lock or unlock");
682 act->flags &= ~(XkbSA_LockNoLock | XkbSA_LockNoUnlock);
683 act->flags |= rtrn.ival;
686 else if (field == F_Count)
688 if (array_ndx != NULL)
689 return ReportActionNotArray(action->type, field);
690 if (!ExprResolveInteger
691 (value, &rtrn, SimpleLookup, (char *) btnNames))
692 return ReportMismatch(action->type, field, "integer");
693 if ((rtrn.ival < 0) || (rtrn.ival > 255))
695 ERROR("The count field must have a value in the range 0..255\n");
696 ACTION1("Illegal count %d ignored\n", rtrn.ival);
699 act->count = rtrn.ival;
702 return ReportIllegal(action->type, field);
705 static LookupEntry ptrDflts[] = {
706 {"dfltbtn", XkbSA_AffectDfltBtn},
707 {"defaultbutton", XkbSA_AffectDfltBtn},
708 {"button", XkbSA_AffectDfltBtn},
713 HandleSetPtrDflt(XkbcDescPtr xkb,
714 XkbAnyAction * action,
715 unsigned field, ExprDef * array_ndx, ExprDef * value)
718 XkbPtrDfltAction *act;
720 act = (XkbPtrDfltAction *) action;
721 if (field == F_Affect)
723 if (array_ndx != NULL)
724 return ReportActionNotArray(action->type, field);
725 if (!ExprResolveEnum(value, &rtrn, ptrDflts))
726 return ReportMismatch(action->type, field, "pointer component");
727 act->affect = rtrn.uval;
730 else if ((field == F_Button) || (field == F_Value))
733 if (array_ndx != NULL)
734 return ReportActionNotArray(action->type, field);
735 if ((value->op == OpNegate) || (value->op == OpUnaryPlus))
737 act->flags &= ~XkbSA_DfltBtnAbsolute;
738 btn = value->value.child;
742 act->flags |= XkbSA_DfltBtnAbsolute;
746 if (!ExprResolveInteger
747 (btn, &rtrn, SimpleLookup, (char *) btnNames))
748 return ReportMismatch(action->type, field,
749 "integer (range 1..5)");
750 if ((rtrn.ival < 0) || (rtrn.ival > 5))
752 ERROR("New default button value must be in the range 1..5\n");
753 ACTION1("Illegal default button value %d ignored\n", rtrn.ival);
758 ERROR("Cannot set default pointer button to \"default\"\n");
759 ACTION("Illegal default button setting ignored\n");
762 if (value->op == OpNegate)
763 XkbSASetPtrDfltValue(act, -rtrn.ival);
765 XkbSASetPtrDfltValue(act, rtrn.ival);
768 return ReportIllegal(action->type, field);
771 static LookupEntry isoNames[] = {
772 {"mods", XkbSA_ISONoAffectMods},
773 {"modifiers", XkbSA_ISONoAffectMods},
774 {"group", XkbSA_ISONoAffectGroup},
775 {"groups", XkbSA_ISONoAffectGroup},
776 {"ptr", XkbSA_ISONoAffectPtr},
777 {"pointer", XkbSA_ISONoAffectPtr},
778 {"ctrls", XkbSA_ISONoAffectCtrls},
779 {"controls", XkbSA_ISONoAffectCtrls},
780 {"all", ~((unsigned) 0)},
786 HandleISOLock(XkbcDescPtr xkb,
787 XkbAnyAction * action,
788 unsigned field, ExprDef * array_ndx, ExprDef * value)
792 unsigned flags, mods;
795 act = (XkbISOAction *) action;
799 if (array_ndx != NULL)
800 return ReportActionNotArray(action->type, field);
802 if (CheckModifierField(xkb, action->type, value, &flags, &mods))
804 act->flags = flags & (~XkbSA_ISODfltIsGroup);
805 act->real_mods = mods & 0xff;
806 mods = (mods >> 8) & 0xff;
807 XkbSetModActionVMods(act, mods);
812 if (array_ndx != NULL)
813 return ReportActionNotArray(action->type, field);
815 if (CheckGroupField(action->type, value, &flags, &group))
817 act->flags = flags | XkbSA_ISODfltIsGroup;
818 XkbSASetGroup(act, group);
823 if (array_ndx != NULL)
824 return ReportActionNotArray(action->type, field);
825 if (!ExprResolveMask(value, &rtrn, SimpleLookup, (char *) isoNames))
826 return ReportMismatch(action->type, field, "keyboard component");
827 act->affect = (~rtrn.uval) & XkbSA_ISOAffectMask;
830 return ReportIllegal(action->type, field);
834 HandleSwitchScreen(XkbcDescPtr xkb,
835 XkbAnyAction * action,
836 unsigned field, ExprDef * array_ndx, ExprDef * value)
839 XkbSwitchScreenAction *act;
841 act = (XkbSwitchScreenAction *) action;
842 if (field == F_Screen)
845 if (array_ndx != NULL)
846 return ReportActionNotArray(action->type, field);
847 if ((value->op == OpNegate) || (value->op == OpUnaryPlus))
849 act->flags &= ~XkbSA_SwitchAbsolute;
850 scrn = value->value.child;
854 act->flags |= XkbSA_SwitchAbsolute;
858 if (!ExprResolveInteger(scrn, &rtrn, NULL, NULL))
859 return ReportMismatch(action->type, field, "integer (0..255)");
860 if ((rtrn.ival < 0) || (rtrn.ival > 255))
862 ERROR("Screen index must be in the range 1..255\n");
863 ACTION1("Illegal screen value %d ignored\n", rtrn.ival);
866 if (value->op == OpNegate)
867 XkbSASetScreen(act, -rtrn.ival);
869 XkbSASetScreen(act, rtrn.ival);
872 else if (field == F_Same)
874 if (array_ndx != NULL)
875 return ReportActionNotArray(action->type, field);
876 if (!ExprResolveBoolean(value, &rtrn, NULL, NULL))
877 return ReportMismatch(action->type, field, "boolean");
879 act->flags &= ~XkbSA_SwitchApplication;
881 act->flags |= XkbSA_SwitchApplication;
884 return ReportIllegal(action->type, field);
887 LookupEntry ctrlNames[] = {
888 {"repeatkeys", XkbRepeatKeysMask}
890 {"repeat", XkbRepeatKeysMask}
892 {"autorepeat", XkbRepeatKeysMask}
894 {"slowkeys", XkbSlowKeysMask}
896 {"bouncekeys", XkbBounceKeysMask}
898 {"stickykeys", XkbStickyKeysMask}
900 {"mousekeys", XkbMouseKeysMask}
902 {"mousekeysaccel", XkbMouseKeysAccelMask}
904 {"accessxkeys", XkbAccessXKeysMask}
906 {"accessxtimeout", XkbAccessXTimeoutMask}
908 {"accessxfeedback", XkbAccessXFeedbackMask}
910 {"audiblebell", XkbAudibleBellMask}
912 {"overlay1", XkbOverlay1Mask}
914 {"overlay2", XkbOverlay2Mask}
916 {"ignoregrouplock", XkbIgnoreGroupLockMask}
918 {"all", XkbAllBooleanCtrlsMask}
926 HandleSetLockControls(XkbcDescPtr xkb,
927 XkbAnyAction * action,
928 unsigned field, ExprDef * array_ndx, ExprDef * value)
933 act = (XkbCtrlsAction *) action;
934 if (field == F_Controls)
936 if (array_ndx != NULL)
937 return ReportActionNotArray(action->type, field);
939 (value, &rtrn, SimpleLookup, (char *) ctrlNames))
940 return ReportMismatch(action->type, field, "controls mask");
941 XkbActionSetCtrls(act, rtrn.uval);
944 return ReportIllegal(action->type, field);
947 static LookupEntry evNames[] = {
948 {"press", XkbSA_MessageOnPress},
949 {"keypress", XkbSA_MessageOnPress},
950 {"release", XkbSA_MessageOnRelease},
951 {"keyrelease", XkbSA_MessageOnRelease},
952 {"all", XkbSA_MessageOnPress | XkbSA_MessageOnRelease},
958 HandleActionMessage(XkbcDescPtr xkb,
959 XkbAnyAction * action,
960 unsigned field, ExprDef * array_ndx, ExprDef * value)
963 XkbMessageAction *act;
965 act = (XkbMessageAction *) action;
969 if (array_ndx != NULL)
970 return ReportActionNotArray(action->type, field);
971 if (!ExprResolveMask(value, &rtrn, SimpleLookup, (char *) evNames))
972 return ReportMismatch(action->type, field, "key event mask");
973 act->flags &= ~(XkbSA_MessageOnPress | XkbSA_MessageOnRelease);
975 rtrn.uval & (XkbSA_MessageOnPress | XkbSA_MessageOnRelease);
978 if (array_ndx != NULL)
979 return ReportActionNotArray(action->type, field);
980 if (!ExprResolveBoolean(value, &rtrn, NULL, NULL))
981 return ReportMismatch(action->type, field, "boolean");
983 act->flags |= XkbSA_MessageGenKeyEvent;
985 act->flags &= ~XkbSA_MessageGenKeyEvent;
988 if (array_ndx == NULL)
990 if (!ExprResolveString(value, &rtrn, NULL, NULL))
991 return ReportMismatch(action->type, field, "string");
994 int len = strlen(rtrn.str);
995 if ((len < 1) || (len > 6))
997 WARN("An action message can hold only 6 bytes\n");
998 ACTION1("Extra %d bytes ignored\n", len - 6);
1000 strncpy((char *) act->message, rtrn.str, 6);
1007 if (!ExprResolveInteger(array_ndx, &rtrn, NULL, NULL))
1009 ERROR("Array subscript must be integer\n");
1010 ACTION("Illegal subscript ignored\n");
1016 ERROR("An action message is at most 6 bytes long\n");
1017 ACTION1("Attempt to use data[%d] ignored\n", ndx);
1020 if (!ExprResolveInteger(value, &rtrn, NULL, NULL))
1021 return ReportMismatch(action->type, field, "integer");
1022 if ((rtrn.ival < 0) || (rtrn.ival > 255))
1024 ERROR("Message data must be in the range 0..255\n");
1025 ACTION1("Illegal datum %d ignored\n", rtrn.ival);
1028 act->message[ndx] = rtrn.uval;
1032 return ReportIllegal(action->type, field);
1036 HandleRedirectKey(XkbcDescPtr xkb,
1037 XkbAnyAction * action,
1038 unsigned field, ExprDef * array_ndx, ExprDef * value)
1041 XkbRedirectKeyAction *act;
1042 unsigned t1, t2, vmods, vmask;
1045 if (array_ndx != NULL)
1046 return ReportActionNotArray(action->type, field);
1048 act = (XkbRedirectKeyAction *) action;
1052 if (!ExprResolveKeyName(value, &rtrn, NULL, NULL))
1053 return ReportMismatch(action->type, field, "key name");
1054 tmp = KeyNameToLong(rtrn.keyName.name);
1055 if (!FindNamedKey(xkb, tmp, &t1, True, CreateKeyNames(xkb), 0))
1057 return ReportNotFound(action->type, field, "Key",
1058 XkbKeyNameText(rtrn.keyName.name,
1066 if (CheckModifierField(xkb, action->type, value, &t1, &t2))
1068 act->mods_mask |= (t2 & 0xff);
1069 if (field == F_Modifiers)
1070 act->mods |= (t2 & 0xff);
1072 act->mods &= ~(t2 & 0xff);
1074 t2 = (t2 >> 8) & 0xffff;
1075 vmods = XkbSARedirectVMods(act);
1076 vmask = XkbSARedirectVModsMask(act);
1078 if (field == F_Modifiers)
1082 XkbSARedirectSetVMods(act, vmods);
1083 XkbSARedirectSetVModsMask(act, vmask);
1088 return ReportIllegal(action->type, field);
1092 HandleDeviceBtn(XkbcDescPtr xkb,
1093 XkbAnyAction * action,
1094 unsigned field, ExprDef * array_ndx, ExprDef * value)
1097 XkbDeviceBtnAction *act;
1099 act = (XkbDeviceBtnAction *) action;
1100 if (field == F_Button)
1102 if (array_ndx != NULL)
1103 return ReportActionNotArray(action->type, field);
1104 if (!ExprResolveInteger(value, &rtrn, NULL, NULL))
1105 return ReportMismatch(action->type, field,
1106 "integer (range 1..255)");
1107 if ((rtrn.ival < 0) || (rtrn.ival > 255))
1109 ERROR("Button must specify default or be in the range 1..255\n");
1110 ACTION1("Illegal button value %d ignored\n", rtrn.ival);
1113 act->button = rtrn.ival;
1116 else if ((action->type == XkbSA_LockDeviceBtn) && (field == F_Affect))
1118 if (array_ndx != NULL)
1119 return ReportActionNotArray(action->type, field);
1120 if (!ExprResolveEnum(value, &rtrn, lockWhich))
1121 return ReportMismatch(action->type, field, "lock or unlock");
1122 act->flags &= ~(XkbSA_LockNoLock | XkbSA_LockNoUnlock);
1123 act->flags |= rtrn.ival;
1126 else if (field == F_Count)
1128 if (array_ndx != NULL)
1129 return ReportActionNotArray(action->type, field);
1130 if (!ExprResolveInteger
1131 (value, &rtrn, SimpleLookup, (char *) btnNames))
1132 return ReportMismatch(action->type, field, "integer");
1133 if ((rtrn.ival < 0) || (rtrn.ival > 255))
1135 ERROR("The count field must have a value in the range 0..255\n");
1136 ACTION1("Illegal count %d ignored\n", rtrn.ival);
1139 act->count = rtrn.ival;
1142 else if (field == F_Device)
1144 if (array_ndx != NULL)
1145 return ReportActionNotArray(action->type, field);
1146 if (!ExprResolveInteger(value, &rtrn, NULL, NULL))
1147 return ReportMismatch(action->type, field,
1148 "integer (range 1..255)");
1149 if ((rtrn.ival < 0) || (rtrn.ival > 255))
1151 ERROR("Device must specify default or be in the range 1..255\n");
1152 ACTION1("Illegal device value %d ignored\n", rtrn.ival);
1155 act->device = rtrn.ival;
1158 return ReportIllegal(action->type, field);
1162 HandleDeviceValuator(XkbcDescPtr xkb,
1163 XkbAnyAction * action,
1164 unsigned field, ExprDef * array_ndx, ExprDef * value)
1168 XkbDeviceValuatorAction *act;
1170 act = (XkbDeviceValuatorAction *) action;
1171 /* XXX - Not yet implemented */
1177 HandlePrivate(XkbcDescPtr xkb,
1178 XkbAnyAction * action,
1179 unsigned field, ExprDef * array_ndx, ExprDef * value)
1186 if (!ExprResolveInteger(value, &rtrn, NULL, NULL))
1187 return ReportMismatch(PrivateAction, field, "integer");
1188 if ((rtrn.ival < 0) || (rtrn.ival > 255))
1190 ERROR("Private action type must be in the range 0..255\n");
1191 ACTION1("Illegal type %d ignored\n", rtrn.ival);
1194 action->type = rtrn.uval;
1197 if (array_ndx == NULL)
1199 if (!ExprResolveString(value, &rtrn, NULL, NULL))
1200 return ReportMismatch(action->type, field, "string");
1203 int len = strlen(rtrn.str);
1204 if ((len < 1) || (len > 7))
1206 WARN("A private action has 7 data bytes\n");
1207 ACTION1("Extra %d bytes ignored\n", len - 6);
1210 strncpy((char *) action->data, rtrn.str, 7);
1217 if (!ExprResolveInteger(array_ndx, &rtrn, NULL, NULL))
1219 ERROR("Array subscript must be integer\n");
1220 ACTION("Illegal subscript ignored\n");
1226 ERROR("The data for a private action is 7 bytes long\n");
1227 ACTION1("Attempt to use data[%d] ignored\n", ndx);
1230 if (!ExprResolveInteger(value, &rtrn, NULL, NULL))
1231 return ReportMismatch(action->type, field, "integer");
1232 if ((rtrn.ival < 0) || (rtrn.ival > 255))
1234 ERROR("All data for a private action must be 0..255\n");
1235 ACTION1("Illegal datum %d ignored\n", rtrn.ival);
1238 action->data[ndx] = rtrn.uval;
1242 return ReportIllegal(PrivateAction, field);
1245 typedef Bool(*actionHandler) (XkbcDescPtr /* xkb */ ,
1246 XkbAnyAction * /* action */ ,
1247 unsigned /* field */ ,
1248 ExprDef * /* array_ndx */ ,
1249 ExprDef * /* value */
1252 static actionHandler handleAction[XkbSA_NumActions + 1] = {
1253 HandleNoAction /* NoAction */ ,
1254 HandleSetLatchMods /* SetMods */ ,
1255 HandleSetLatchMods /* LatchMods */ ,
1256 HandleLockMods /* LockMods */ ,
1257 HandleSetLatchGroup /* SetGroup */ ,
1258 HandleSetLatchGroup /* LatchGroup */ ,
1259 HandleLockGroup /* LockGroup */ ,
1260 HandleMovePtr /* MovePtr */ ,
1261 HandlePtrBtn /* PtrBtn */ ,
1262 HandlePtrBtn /* LockPtrBtn */ ,
1263 HandleSetPtrDflt /* SetPtrDflt */ ,
1264 HandleISOLock /* ISOLock */ ,
1265 HandleNoAction /* Terminate */ ,
1266 HandleSwitchScreen /* SwitchScreen */ ,
1267 HandleSetLockControls /* SetControls */ ,
1268 HandleSetLockControls /* LockControls */ ,
1269 HandleActionMessage /* ActionMessage */ ,
1270 HandleRedirectKey /* RedirectKey */ ,
1271 HandleDeviceBtn /* DeviceBtn */ ,
1272 HandleDeviceBtn /* LockDeviceBtn */ ,
1273 HandleDeviceValuator /* DeviceValuatr */ ,
1274 HandlePrivate /* Private */
1277 /***====================================================================***/
1280 ApplyActionFactoryDefaults(XkbAction * action)
1282 if (action->type == XkbSA_SetPtrDflt)
1283 { /* increment default button */
1284 action->dflt.affect = XkbSA_AffectDfltBtn;
1285 action->dflt.flags = 0;
1286 XkbSASetPtrDfltValue(&action->dflt, 1);
1288 else if (action->type == XkbSA_ISOLock)
1290 action->iso.real_mods = LockMask;
1297 HandleActionDef(ExprDef * def,
1299 XkbAnyAction * action, unsigned mergeMode, ActionInfo * info)
1303 unsigned tmp, hndlrType;
1305 if (!actionsInitialized)
1308 if (def->op != ExprActionDecl)
1310 ERROR1("Expected an action definition, found %s\n",
1311 exprOpText(def->op));
1314 str = XkbcAtomGetString(def->value.action.name);
1317 WSGO("Missing name in action definition!!\n");
1320 if (!stringToAction(str, &tmp))
1322 ERROR1("Unknown action %s\n", str);
1325 action->type = hndlrType = tmp;
1326 if (action->type != XkbSA_NoAction)
1328 ApplyActionFactoryDefaults((XkbAction *) action);
1331 if ((info->action == XkbSA_NoAction)
1332 || (info->action == hndlrType))
1334 if (!(*handleAction[hndlrType]) (xkb, action,
1345 for (arg = def->value.action.args; arg != NULL;
1346 arg = (ExprDef *) arg->common.next)
1348 ExprDef *field, *value, *arrayRtrn;
1349 ExprResult elemRtrn, fieldRtrn;
1352 if (arg->op == OpAssign)
1354 field = arg->value.binary.left;
1355 value = arg->value.binary.right;
1359 if ((arg->op == OpNot) || (arg->op == OpInvert))
1361 field = arg->value.child;
1362 value = &constFalse;
1370 if (!ExprResolveLhs(field, &elemRtrn, &fieldRtrn, &arrayRtrn))
1371 return False; /* internal error -- already reported */
1373 if (elemRtrn.str != NULL)
1375 ERROR("Cannot change defaults in an action definition\n");
1376 ACTION2("Ignoring attempt to change %s.%s\n", elemRtrn.str,
1380 if (!stringToField(fieldRtrn.str, &fieldNdx))
1382 ERROR1("Unknown field name %s\n", uStringText(fieldRtrn.str));
1385 if (!(*handleAction[hndlrType])
1386 (xkb, action, fieldNdx, arrayRtrn, value))
1394 /***====================================================================***/
1397 SetActionField(XkbcDescPtr xkb,
1400 ExprDef * array_ndx, ExprDef * value, ActionInfo ** info_rtrn)
1402 ActionInfo *new, *old;
1404 if (!actionsInitialized)
1407 new = uTypedAlloc(ActionInfo);
1410 WSGO("Couldn't allocate space for action default\n");
1413 if (uStrCaseCmp(elem, "action") == 0)
1414 new->action = XkbSA_NoAction;
1417 if (!stringToAction(elem, &new->action))
1419 if (new->action == XkbSA_NoAction)
1421 ERROR1("\"%s\" is not a valid field in a NoAction action\n",
1426 if (!stringToField(field, &new->field))
1428 ERROR1("\"%s\" is not a legal field name\n", field);
1431 new->array_ndx = array_ndx;
1435 while ((old) && (old->next))
1444 /***====================================================================***/
1449 if (!actionsInitialized)
1451 bzero((char *) &constTrue, sizeof(constTrue));
1452 bzero((char *) &constFalse, sizeof(constFalse));
1453 constTrue.common.stmtType = StmtExpr;
1454 constTrue.common.next = NULL;
1455 constTrue.op = ExprIdent;
1456 constTrue.type = TypeBoolean;
1457 constTrue.value.str = XkbcInternAtom("true", False);
1458 constFalse.common.stmtType = StmtExpr;
1459 constFalse.common.next = NULL;
1460 constFalse.op = ExprIdent;
1461 constFalse.type = TypeBoolean;
1462 constFalse.value.str = XkbcInternAtom("false", False);
1463 actionsInitialized = 1;