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 ERROR("Value of %s field must be of type %s\n", fieldText(field), type);
303 ACTION("Action %s definition ignored\n", XkbcActionTypeText(action));
308 ReportIllegal(unsigned action, unsigned field)
310 ERROR("Field %s is not defined for an action of type %s\n",
311 fieldText(field), XkbcActionTypeText(action));
312 ACTION("Action definition ignored\n");
317 ReportActionNotArray(unsigned action, unsigned field)
319 ERROR("The %s field in the %s action is not an array\n",
320 fieldText(field), XkbcActionTypeText(action));
321 ACTION("Action definition ignored\n");
326 ReportNotFound(unsigned action, unsigned field, const char *what, char *bad)
328 ERROR("%s named %s not found\n", what, bad);
329 ACTION("Ignoring the %s field of an %s action\n", fieldText(field),
330 XkbcActionTypeText(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 ERROR("Illegal group %d (must be in the range 1..%d)\n", rtrn.ival,
502 ACTION("Action %s definition ignored\n", XkbcActionTypeText(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 ACTION("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 ACTION("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 ACTION("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 ACTION("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 ACTION("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 ACTION("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 ACTION("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 XkbcKeyNameText(rtrn.keyName.name));
1065 if (CheckModifierField(xkb, action->type, value, &t1, &t2))
1067 act->mods_mask |= (t2 & 0xff);
1068 if (field == F_Modifiers)
1069 act->mods |= (t2 & 0xff);
1071 act->mods &= ~(t2 & 0xff);
1073 t2 = (t2 >> 8) & 0xffff;
1074 vmods = XkbSARedirectVMods(act);
1075 vmask = XkbSARedirectVModsMask(act);
1077 if (field == F_Modifiers)
1081 XkbSARedirectSetVMods(act, vmods);
1082 XkbSARedirectSetVModsMask(act, vmask);
1087 return ReportIllegal(action->type, field);
1091 HandleDeviceBtn(XkbcDescPtr xkb,
1092 XkbAnyAction * action,
1093 unsigned field, ExprDef * array_ndx, ExprDef * value)
1096 XkbDeviceBtnAction *act;
1098 act = (XkbDeviceBtnAction *) action;
1099 if (field == F_Button)
1101 if (array_ndx != NULL)
1102 return ReportActionNotArray(action->type, field);
1103 if (!ExprResolveInteger(value, &rtrn, NULL, NULL))
1104 return ReportMismatch(action->type, field,
1105 "integer (range 1..255)");
1106 if ((rtrn.ival < 0) || (rtrn.ival > 255))
1108 ERROR("Button must specify default or be in the range 1..255\n");
1109 ACTION("Illegal button value %d ignored\n", rtrn.ival);
1112 act->button = rtrn.ival;
1115 else if ((action->type == XkbSA_LockDeviceBtn) && (field == F_Affect))
1117 if (array_ndx != NULL)
1118 return ReportActionNotArray(action->type, field);
1119 if (!ExprResolveEnum(value, &rtrn, lockWhich))
1120 return ReportMismatch(action->type, field, "lock or unlock");
1121 act->flags &= ~(XkbSA_LockNoLock | XkbSA_LockNoUnlock);
1122 act->flags |= rtrn.ival;
1125 else if (field == F_Count)
1127 if (array_ndx != NULL)
1128 return ReportActionNotArray(action->type, field);
1129 if (!ExprResolveInteger
1130 (value, &rtrn, SimpleLookup, (char *) btnNames))
1131 return ReportMismatch(action->type, field, "integer");
1132 if ((rtrn.ival < 0) || (rtrn.ival > 255))
1134 ERROR("The count field must have a value in the range 0..255\n");
1135 ACTION("Illegal count %d ignored\n", rtrn.ival);
1138 act->count = rtrn.ival;
1141 else if (field == F_Device)
1143 if (array_ndx != NULL)
1144 return ReportActionNotArray(action->type, field);
1145 if (!ExprResolveInteger(value, &rtrn, NULL, NULL))
1146 return ReportMismatch(action->type, field,
1147 "integer (range 1..255)");
1148 if ((rtrn.ival < 0) || (rtrn.ival > 255))
1150 ERROR("Device must specify default or be in the range 1..255\n");
1151 ACTION("Illegal device value %d ignored\n", rtrn.ival);
1154 act->device = rtrn.ival;
1157 return ReportIllegal(action->type, field);
1161 HandleDeviceValuator(XkbcDescPtr xkb,
1162 XkbAnyAction * action,
1163 unsigned field, ExprDef * array_ndx, ExprDef * value)
1167 XkbDeviceValuatorAction *act;
1169 act = (XkbDeviceValuatorAction *) action;
1170 /* XXX - Not yet implemented */
1176 HandlePrivate(XkbcDescPtr xkb,
1177 XkbAnyAction * action,
1178 unsigned field, ExprDef * array_ndx, ExprDef * value)
1185 if (!ExprResolveInteger(value, &rtrn, NULL, NULL))
1186 return ReportMismatch(PrivateAction, field, "integer");
1187 if ((rtrn.ival < 0) || (rtrn.ival > 255))
1189 ERROR("Private action type must be in the range 0..255\n");
1190 ACTION("Illegal type %d ignored\n", rtrn.ival);
1193 action->type = rtrn.uval;
1196 if (array_ndx == NULL)
1198 if (!ExprResolveString(value, &rtrn, NULL, NULL))
1199 return ReportMismatch(action->type, field, "string");
1202 int len = strlen(rtrn.str);
1203 if ((len < 1) || (len > 7))
1205 WARN("A private action has 7 data bytes\n");
1206 ACTION("Extra %d bytes ignored\n", len - 6);
1209 strncpy((char *) action->data, rtrn.str, 7);
1216 if (!ExprResolveInteger(array_ndx, &rtrn, NULL, NULL))
1218 ERROR("Array subscript must be integer\n");
1219 ACTION("Illegal subscript ignored\n");
1225 ERROR("The data for a private action is 7 bytes long\n");
1226 ACTION("Attempt to use data[%d] ignored\n", ndx);
1229 if (!ExprResolveInteger(value, &rtrn, NULL, NULL))
1230 return ReportMismatch(action->type, field, "integer");
1231 if ((rtrn.ival < 0) || (rtrn.ival > 255))
1233 ERROR("All data for a private action must be 0..255\n");
1234 ACTION("Illegal datum %d ignored\n", rtrn.ival);
1237 action->data[ndx] = rtrn.uval;
1241 return ReportIllegal(PrivateAction, field);
1244 typedef Bool(*actionHandler) (XkbcDescPtr /* xkb */ ,
1245 XkbAnyAction * /* action */ ,
1246 unsigned /* field */ ,
1247 ExprDef * /* array_ndx */ ,
1248 ExprDef * /* value */
1251 static actionHandler handleAction[XkbSA_NumActions + 1] = {
1252 HandleNoAction /* NoAction */ ,
1253 HandleSetLatchMods /* SetMods */ ,
1254 HandleSetLatchMods /* LatchMods */ ,
1255 HandleLockMods /* LockMods */ ,
1256 HandleSetLatchGroup /* SetGroup */ ,
1257 HandleSetLatchGroup /* LatchGroup */ ,
1258 HandleLockGroup /* LockGroup */ ,
1259 HandleMovePtr /* MovePtr */ ,
1260 HandlePtrBtn /* PtrBtn */ ,
1261 HandlePtrBtn /* LockPtrBtn */ ,
1262 HandleSetPtrDflt /* SetPtrDflt */ ,
1263 HandleISOLock /* ISOLock */ ,
1264 HandleNoAction /* Terminate */ ,
1265 HandleSwitchScreen /* SwitchScreen */ ,
1266 HandleSetLockControls /* SetControls */ ,
1267 HandleSetLockControls /* LockControls */ ,
1268 HandleActionMessage /* ActionMessage */ ,
1269 HandleRedirectKey /* RedirectKey */ ,
1270 HandleDeviceBtn /* DeviceBtn */ ,
1271 HandleDeviceBtn /* LockDeviceBtn */ ,
1272 HandleDeviceValuator /* DeviceValuatr */ ,
1273 HandlePrivate /* Private */
1276 /***====================================================================***/
1279 ApplyActionFactoryDefaults(XkbAction * action)
1281 if (action->type == XkbSA_SetPtrDflt)
1282 { /* increment default button */
1283 action->dflt.affect = XkbSA_AffectDfltBtn;
1284 action->dflt.flags = 0;
1285 XkbSASetPtrDfltValue(&action->dflt, 1);
1287 else if (action->type == XkbSA_ISOLock)
1289 action->iso.real_mods = LockMask;
1296 HandleActionDef(ExprDef * def,
1298 XkbAnyAction * action, unsigned mergeMode, ActionInfo * info)
1302 unsigned tmp, hndlrType;
1304 if (!actionsInitialized)
1307 if (def->op != ExprActionDecl)
1309 ERROR("Expected an action definition, found %s\n",
1310 exprOpText(def->op));
1313 str = XkbcAtomGetString(def->value.action.name);
1316 WSGO("Missing name in action definition!!\n");
1319 if (!stringToAction(str, &tmp))
1321 ERROR("Unknown action %s\n", str);
1324 action->type = hndlrType = tmp;
1325 if (action->type != XkbSA_NoAction)
1327 ApplyActionFactoryDefaults((XkbAction *) action);
1330 if ((info->action == XkbSA_NoAction)
1331 || (info->action == hndlrType))
1333 if (!(*handleAction[hndlrType]) (xkb, action,
1344 for (arg = def->value.action.args; arg != NULL;
1345 arg = (ExprDef *) arg->common.next)
1347 ExprDef *field, *value, *arrayRtrn;
1348 ExprResult elemRtrn, fieldRtrn;
1351 if (arg->op == OpAssign)
1353 field = arg->value.binary.left;
1354 value = arg->value.binary.right;
1358 if ((arg->op == OpNot) || (arg->op == OpInvert))
1360 field = arg->value.child;
1361 value = &constFalse;
1369 if (!ExprResolveLhs(field, &elemRtrn, &fieldRtrn, &arrayRtrn))
1370 return False; /* internal error -- already reported */
1372 if (elemRtrn.str != NULL)
1374 ERROR("Cannot change defaults in an action definition\n");
1375 ACTION("Ignoring attempt to change %s.%s\n", elemRtrn.str,
1379 if (!stringToField(fieldRtrn.str, &fieldNdx))
1381 ERROR("Unknown field name %s\n", uStringText(fieldRtrn.str));
1384 if (!(*handleAction[hndlrType])
1385 (xkb, action, fieldNdx, arrayRtrn, value))
1393 /***====================================================================***/
1396 SetActionField(XkbcDescPtr xkb,
1399 ExprDef * array_ndx, ExprDef * value, ActionInfo ** info_rtrn)
1401 ActionInfo *new, *old;
1403 if (!actionsInitialized)
1406 new = uTypedAlloc(ActionInfo);
1409 WSGO("Couldn't allocate space for action default\n");
1412 if (uStrCaseCmp(elem, "action") == 0)
1413 new->action = XkbSA_NoAction;
1416 if (!stringToAction(elem, &new->action))
1418 if (new->action == XkbSA_NoAction)
1420 ERROR("\"%s\" is not a valid field in a NoAction action\n",
1425 if (!stringToField(field, &new->field))
1427 ERROR("\"%s\" is not a legal field name\n", field);
1430 new->array_ndx = array_ndx;
1434 while ((old) && (old->next))
1443 /***====================================================================***/
1448 if (!actionsInitialized)
1450 bzero((char *) &constTrue, sizeof(constTrue));
1451 bzero((char *) &constFalse, sizeof(constFalse));
1452 constTrue.common.stmtType = StmtExpr;
1453 constTrue.common.next = NULL;
1454 constTrue.op = ExprIdent;
1455 constTrue.type = TypeBoolean;
1456 constTrue.value.str = XkbcInternAtom("true", False);
1457 constFalse.common.stmtType = StmtExpr;
1458 constFalse.common.next = NULL;
1459 constFalse.op = ExprIdent;
1460 constFalse.type = TypeBoolean;
1461 constFalse.value.str = XkbcInternAtom("false", False);
1462 actionsInitialized = 1;