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 = (XkbcModAction *) 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 act->vmods = (t2 >> 8) & 0xffff;
434 return ReportIllegal(action->type, field);
438 HandleLockMods(XkbcDescPtr xkb,
439 XkbAnyAction * action,
440 unsigned field, ExprDef * array_ndx, ExprDef * value)
445 act = (XkbcModAction *) action;
446 if ((array_ndx != NULL) && (field == F_Modifiers))
447 return ReportActionNotArray(action->type, field);
452 if (CheckModifierField(xkb, action->type, value, &t1, &t2))
455 act->real_mods = act->mask = (t2 & 0xff);
456 act->vmods = (t2 >> 8) & 0xffff;
461 return ReportIllegal(action->type, field);
464 static LookupEntry groupNames[] = {
477 CheckGroupField(unsigned action,
478 ExprDef * value, unsigned *flags_inout, int *grp_rtrn)
483 if ((value->op == OpNegate) || (value->op == OpUnaryPlus))
485 *flags_inout &= ~XkbSA_GroupAbsolute;
486 spec = value->value.child;
490 *flags_inout |= XkbSA_GroupAbsolute;
494 if (!ExprResolveInteger(spec, &rtrn, SimpleLookup, (char *) groupNames))
495 return ReportMismatch(action, F_Group, "integer (range 1..8)");
496 if ((rtrn.ival < 1) || (rtrn.ival > XkbNumKbdGroups))
498 ERROR("Illegal group %d (must be in the range 1..%d)\n", rtrn.ival,
500 ACTION("Action %s definition ignored\n", XkbcActionTypeText(action));
503 if (value->op == OpNegate)
504 *grp_rtrn = -rtrn.ival;
505 else if (value->op == OpUnaryPlus)
506 *grp_rtrn = rtrn.ival;
508 *grp_rtrn = rtrn.ival - 1;
513 HandleSetLatchGroup(XkbcDescPtr xkb,
514 XkbAnyAction * action,
515 unsigned field, ExprDef * array_ndx, ExprDef * value)
522 act = (XkbGroupAction *) action;
523 if (array_ndx != NULL)
530 return ReportActionNotArray(action->type, field);
538 if (CheckLatchLockFlags(action->type, field, value, &rtrn))
546 if (CheckGroupField(action->type, value, &t1, &t2))
549 XkbSASetGroup(act, t2);
554 return ReportIllegal(action->type, field);
558 HandleLockGroup(XkbcDescPtr xkb,
559 XkbAnyAction * action,
560 unsigned field, ExprDef * array_ndx, ExprDef * value)
566 act = (XkbGroupAction *) action;
567 if ((array_ndx != NULL) && (field == F_Group))
568 return ReportActionNotArray(action->type, field);
569 if (field == F_Group)
572 if (CheckGroupField(action->type, value, &t1, &t2))
575 XkbSASetGroup(act, t2);
580 return ReportIllegal(action->type, field);
584 HandleMovePtr(XkbcDescPtr xkb,
585 XkbAnyAction * action,
586 unsigned field, ExprDef * array_ndx, ExprDef * value)
592 act = (XkbcPtrAction *) action;
593 if ((array_ndx != NULL) && ((field == F_X) || (field == F_Y)))
594 return ReportActionNotArray(action->type, field);
596 if ((field == F_X) || (field == F_Y))
598 if ((value->op == OpNegate) || (value->op == OpUnaryPlus))
602 if (!ExprResolveInteger(value, &rtrn, NULL, NULL))
603 return ReportMismatch(action->type, field, "integer");
607 act->flags |= XkbSA_MoveAbsoluteX;
613 act->flags |= XkbSA_MoveAbsoluteY;
618 else if (field == F_Accel)
620 if (!ExprResolveBoolean(value, &rtrn, NULL, NULL))
621 return ReportMismatch(action->type, field, "boolean");
623 act->flags &= ~XkbSA_NoAcceleration;
625 act->flags |= XkbSA_NoAcceleration;
627 return ReportIllegal(action->type, field);
630 static LookupEntry btnNames[] = {
640 static LookupEntry lockWhich[] = {
642 {"lock", XkbSA_LockNoUnlock},
643 {"neither", (XkbSA_LockNoLock | XkbSA_LockNoUnlock)},
644 {"unlock", XkbSA_LockNoLock},
649 HandlePtrBtn(XkbcDescPtr xkb,
650 XkbAnyAction * action,
651 unsigned field, ExprDef * array_ndx, ExprDef * value)
654 XkbPtrBtnAction *act;
656 act = (XkbPtrBtnAction *) action;
657 if (field == F_Button)
659 if (array_ndx != NULL)
660 return ReportActionNotArray(action->type, field);
661 if (!ExprResolveInteger
662 (value, &rtrn, SimpleLookup, (char *) btnNames))
663 return ReportMismatch(action->type, field,
664 "integer (range 1..5)");
665 if ((rtrn.ival < 0) || (rtrn.ival > 5))
667 ERROR("Button must specify default or be in the range 1..5\n");
668 ACTION("Illegal button value %d ignored\n", rtrn.ival);
671 act->button = rtrn.ival;
674 else if ((action->type == XkbSA_LockPtrBtn) && (field == F_Affect))
676 if (array_ndx != NULL)
677 return ReportActionNotArray(action->type, field);
678 if (!ExprResolveEnum(value, &rtrn, lockWhich))
679 return ReportMismatch(action->type, field, "lock or unlock");
680 act->flags &= ~(XkbSA_LockNoLock | XkbSA_LockNoUnlock);
681 act->flags |= rtrn.ival;
684 else if (field == F_Count)
686 if (array_ndx != NULL)
687 return ReportActionNotArray(action->type, field);
688 if (!ExprResolveInteger
689 (value, &rtrn, SimpleLookup, (char *) btnNames))
690 return ReportMismatch(action->type, field, "integer");
691 if ((rtrn.ival < 0) || (rtrn.ival > 255))
693 ERROR("The count field must have a value in the range 0..255\n");
694 ACTION("Illegal count %d ignored\n", rtrn.ival);
697 act->count = rtrn.ival;
700 return ReportIllegal(action->type, field);
703 static LookupEntry ptrDflts[] = {
704 {"dfltbtn", XkbSA_AffectDfltBtn},
705 {"defaultbutton", XkbSA_AffectDfltBtn},
706 {"button", XkbSA_AffectDfltBtn},
711 HandleSetPtrDflt(XkbcDescPtr xkb,
712 XkbAnyAction * action,
713 unsigned field, ExprDef * array_ndx, ExprDef * value)
716 XkbPtrDfltAction *act;
718 act = (XkbPtrDfltAction *) action;
719 if (field == F_Affect)
721 if (array_ndx != NULL)
722 return ReportActionNotArray(action->type, field);
723 if (!ExprResolveEnum(value, &rtrn, ptrDflts))
724 return ReportMismatch(action->type, field, "pointer component");
725 act->affect = rtrn.uval;
728 else if ((field == F_Button) || (field == F_Value))
731 if (array_ndx != NULL)
732 return ReportActionNotArray(action->type, field);
733 if ((value->op == OpNegate) || (value->op == OpUnaryPlus))
735 act->flags &= ~XkbSA_DfltBtnAbsolute;
736 btn = value->value.child;
740 act->flags |= XkbSA_DfltBtnAbsolute;
744 if (!ExprResolveInteger
745 (btn, &rtrn, SimpleLookup, (char *) btnNames))
746 return ReportMismatch(action->type, field,
747 "integer (range 1..5)");
748 if ((rtrn.ival < 0) || (rtrn.ival > 5))
750 ERROR("New default button value must be in the range 1..5\n");
751 ACTION("Illegal default button value %d ignored\n", rtrn.ival);
756 ERROR("Cannot set default pointer button to \"default\"\n");
757 ACTION("Illegal default button setting ignored\n");
760 if (value->op == OpNegate)
761 XkbSASetPtrDfltValue(act, -rtrn.ival);
763 XkbSASetPtrDfltValue(act, rtrn.ival);
766 return ReportIllegal(action->type, field);
769 static LookupEntry isoNames[] = {
770 {"mods", XkbSA_ISONoAffectMods},
771 {"modifiers", XkbSA_ISONoAffectMods},
772 {"group", XkbSA_ISONoAffectGroup},
773 {"groups", XkbSA_ISONoAffectGroup},
774 {"ptr", XkbSA_ISONoAffectPtr},
775 {"pointer", XkbSA_ISONoAffectPtr},
776 {"ctrls", XkbSA_ISONoAffectCtrls},
777 {"controls", XkbSA_ISONoAffectCtrls},
778 {"all", ~((unsigned) 0)},
784 HandleISOLock(XkbcDescPtr xkb,
785 XkbAnyAction * action,
786 unsigned field, ExprDef * array_ndx, ExprDef * value)
790 unsigned flags, mods;
793 act = (XkbcISOAction *) action;
797 if (array_ndx != NULL)
798 return ReportActionNotArray(action->type, field);
800 if (CheckModifierField(xkb, action->type, value, &flags, &mods))
802 act->flags = flags & (~XkbSA_ISODfltIsGroup);
803 act->real_mods = mods & 0xff;
804 act->vmods = (mods >> 8) & 0xff;
809 if (array_ndx != NULL)
810 return ReportActionNotArray(action->type, field);
812 if (CheckGroupField(action->type, value, &flags, &group))
814 act->flags = flags | XkbSA_ISODfltIsGroup;
815 XkbSASetGroup(act, group);
820 if (array_ndx != NULL)
821 return ReportActionNotArray(action->type, field);
822 if (!ExprResolveMask(value, &rtrn, SimpleLookup, (char *) isoNames))
823 return ReportMismatch(action->type, field, "keyboard component");
824 act->affect = (~rtrn.uval) & XkbSA_ISOAffectMask;
827 return ReportIllegal(action->type, field);
831 HandleSwitchScreen(XkbcDescPtr xkb,
832 XkbAnyAction * action,
833 unsigned field, ExprDef * array_ndx, ExprDef * value)
836 XkbSwitchScreenAction *act;
838 act = (XkbSwitchScreenAction *) action;
839 if (field == F_Screen)
842 if (array_ndx != NULL)
843 return ReportActionNotArray(action->type, field);
844 if ((value->op == OpNegate) || (value->op == OpUnaryPlus))
846 act->flags &= ~XkbSA_SwitchAbsolute;
847 scrn = value->value.child;
851 act->flags |= XkbSA_SwitchAbsolute;
855 if (!ExprResolveInteger(scrn, &rtrn, NULL, NULL))
856 return ReportMismatch(action->type, field, "integer (0..255)");
857 if ((rtrn.ival < 0) || (rtrn.ival > 255))
859 ERROR("Screen index must be in the range 1..255\n");
860 ACTION("Illegal screen value %d ignored\n", rtrn.ival);
863 if (value->op == OpNegate)
864 XkbSASetScreen(act, -rtrn.ival);
866 XkbSASetScreen(act, rtrn.ival);
869 else if (field == F_Same)
871 if (array_ndx != NULL)
872 return ReportActionNotArray(action->type, field);
873 if (!ExprResolveBoolean(value, &rtrn, NULL, NULL))
874 return ReportMismatch(action->type, field, "boolean");
876 act->flags &= ~XkbSA_SwitchApplication;
878 act->flags |= XkbSA_SwitchApplication;
881 return ReportIllegal(action->type, field);
884 LookupEntry ctrlNames[] = {
885 {"repeatkeys", XkbRepeatKeysMask}
887 {"repeat", XkbRepeatKeysMask}
889 {"autorepeat", XkbRepeatKeysMask}
891 {"slowkeys", XkbSlowKeysMask}
893 {"bouncekeys", XkbBounceKeysMask}
895 {"stickykeys", XkbStickyKeysMask}
897 {"mousekeys", XkbMouseKeysMask}
899 {"mousekeysaccel", XkbMouseKeysAccelMask}
901 {"accessxkeys", XkbAccessXKeysMask}
903 {"accessxtimeout", XkbAccessXTimeoutMask}
905 {"accessxfeedback", XkbAccessXFeedbackMask}
907 {"audiblebell", XkbAudibleBellMask}
909 {"overlay1", XkbOverlay1Mask}
911 {"overlay2", XkbOverlay2Mask}
913 {"ignoregrouplock", XkbIgnoreGroupLockMask}
915 {"all", XkbAllBooleanCtrlsMask}
923 HandleSetLockControls(XkbcDescPtr xkb,
924 XkbAnyAction * action,
925 unsigned field, ExprDef * array_ndx, ExprDef * value)
928 XkbcCtrlsAction *act;
930 act = (XkbcCtrlsAction *) action;
931 if (field == F_Controls)
933 if (array_ndx != NULL)
934 return ReportActionNotArray(action->type, field);
936 (value, &rtrn, SimpleLookup, (char *) ctrlNames))
937 return ReportMismatch(action->type, field, "controls mask");
938 act->ctrls = rtrn.uval;
941 return ReportIllegal(action->type, field);
944 static LookupEntry evNames[] = {
945 {"press", XkbSA_MessageOnPress},
946 {"keypress", XkbSA_MessageOnPress},
947 {"release", XkbSA_MessageOnRelease},
948 {"keyrelease", XkbSA_MessageOnRelease},
949 {"all", XkbSA_MessageOnPress | XkbSA_MessageOnRelease},
955 HandleActionMessage(XkbcDescPtr xkb,
956 XkbAnyAction * action,
957 unsigned field, ExprDef * array_ndx, ExprDef * value)
960 XkbMessageAction *act;
962 act = (XkbMessageAction *) action;
966 if (array_ndx != NULL)
967 return ReportActionNotArray(action->type, field);
968 if (!ExprResolveMask(value, &rtrn, SimpleLookup, (char *) evNames))
969 return ReportMismatch(action->type, field, "key event mask");
970 act->flags &= ~(XkbSA_MessageOnPress | XkbSA_MessageOnRelease);
972 rtrn.uval & (XkbSA_MessageOnPress | XkbSA_MessageOnRelease);
975 if (array_ndx != NULL)
976 return ReportActionNotArray(action->type, field);
977 if (!ExprResolveBoolean(value, &rtrn, NULL, NULL))
978 return ReportMismatch(action->type, field, "boolean");
980 act->flags |= XkbSA_MessageGenKeyEvent;
982 act->flags &= ~XkbSA_MessageGenKeyEvent;
985 if (array_ndx == NULL)
987 if (!ExprResolveString(value, &rtrn, NULL, NULL))
988 return ReportMismatch(action->type, field, "string");
991 int len = strlen(rtrn.str);
992 if ((len < 1) || (len > 6))
994 WARN("An action message can hold only 6 bytes\n");
995 ACTION("Extra %d bytes ignored\n", len - 6);
997 strncpy((char *) act->message, rtrn.str, 6);
1004 if (!ExprResolveInteger(array_ndx, &rtrn, NULL, NULL))
1006 ERROR("Array subscript must be integer\n");
1007 ACTION("Illegal subscript ignored\n");
1013 ERROR("An action message is at most 6 bytes long\n");
1014 ACTION("Attempt to use data[%d] ignored\n", ndx);
1017 if (!ExprResolveInteger(value, &rtrn, NULL, NULL))
1018 return ReportMismatch(action->type, field, "integer");
1019 if ((rtrn.ival < 0) || (rtrn.ival > 255))
1021 ERROR("Message data must be in the range 0..255\n");
1022 ACTION("Illegal datum %d ignored\n", rtrn.ival);
1025 act->message[ndx] = rtrn.uval;
1029 return ReportIllegal(action->type, field);
1033 HandleRedirectKey(XkbcDescPtr xkb,
1034 XkbAnyAction * action,
1035 unsigned field, ExprDef * array_ndx, ExprDef * value)
1038 XkbcRedirectKeyAction *act;
1042 if (array_ndx != NULL)
1043 return ReportActionNotArray(action->type, field);
1045 act = (XkbcRedirectKeyAction *) action;
1049 if (!ExprResolveKeyName(value, &rtrn, NULL, NULL))
1050 return ReportMismatch(action->type, field, "key name");
1051 tmp = KeyNameToLong(rtrn.keyName.name);
1052 if (!FindNamedKey(xkb, tmp, &t1, True, CreateKeyNames(xkb), 0))
1054 return ReportNotFound(action->type, field, "Key",
1055 XkbcKeyNameText(rtrn.keyName.name));
1062 if (CheckModifierField(xkb, action->type, value, &t1, &t2))
1064 act->mods_mask |= (t2 & 0xff);
1065 if (field == F_Modifiers)
1066 act->mods |= (t2 & 0xff);
1068 act->mods &= ~(t2 & 0xff);
1070 t2 = (t2 >> 8) & 0xffff;
1071 act->vmods_mask |= t2;
1072 if (field == F_Modifiers)
1080 return ReportIllegal(action->type, field);
1084 HandleDeviceBtn(XkbcDescPtr xkb,
1085 XkbAnyAction * action,
1086 unsigned field, ExprDef * array_ndx, ExprDef * value)
1089 XkbDeviceBtnAction *act;
1091 act = (XkbDeviceBtnAction *) action;
1092 if (field == F_Button)
1094 if (array_ndx != NULL)
1095 return ReportActionNotArray(action->type, field);
1096 if (!ExprResolveInteger(value, &rtrn, NULL, NULL))
1097 return ReportMismatch(action->type, field,
1098 "integer (range 1..255)");
1099 if ((rtrn.ival < 0) || (rtrn.ival > 255))
1101 ERROR("Button must specify default or be in the range 1..255\n");
1102 ACTION("Illegal button value %d ignored\n", rtrn.ival);
1105 act->button = rtrn.ival;
1108 else if ((action->type == XkbSA_LockDeviceBtn) && (field == F_Affect))
1110 if (array_ndx != NULL)
1111 return ReportActionNotArray(action->type, field);
1112 if (!ExprResolveEnum(value, &rtrn, lockWhich))
1113 return ReportMismatch(action->type, field, "lock or unlock");
1114 act->flags &= ~(XkbSA_LockNoLock | XkbSA_LockNoUnlock);
1115 act->flags |= rtrn.ival;
1118 else if (field == F_Count)
1120 if (array_ndx != NULL)
1121 return ReportActionNotArray(action->type, field);
1122 if (!ExprResolveInteger
1123 (value, &rtrn, SimpleLookup, (char *) btnNames))
1124 return ReportMismatch(action->type, field, "integer");
1125 if ((rtrn.ival < 0) || (rtrn.ival > 255))
1127 ERROR("The count field must have a value in the range 0..255\n");
1128 ACTION("Illegal count %d ignored\n", rtrn.ival);
1131 act->count = rtrn.ival;
1134 else if (field == F_Device)
1136 if (array_ndx != NULL)
1137 return ReportActionNotArray(action->type, field);
1138 if (!ExprResolveInteger(value, &rtrn, NULL, NULL))
1139 return ReportMismatch(action->type, field,
1140 "integer (range 1..255)");
1141 if ((rtrn.ival < 0) || (rtrn.ival > 255))
1143 ERROR("Device must specify default or be in the range 1..255\n");
1144 ACTION("Illegal device value %d ignored\n", rtrn.ival);
1147 act->device = rtrn.ival;
1150 return ReportIllegal(action->type, field);
1154 HandleDeviceValuator(XkbcDescPtr xkb,
1155 XkbAnyAction * action,
1156 unsigned field, ExprDef * array_ndx, ExprDef * value)
1160 XkbDeviceValuatorAction *act;
1162 act = (XkbDeviceValuatorAction *) action;
1163 /* XXX - Not yet implemented */
1169 HandlePrivate(XkbcDescPtr xkb,
1170 XkbAnyAction * action,
1171 unsigned field, ExprDef * array_ndx, ExprDef * value)
1178 if (!ExprResolveInteger(value, &rtrn, NULL, NULL))
1179 return ReportMismatch(PrivateAction, field, "integer");
1180 if ((rtrn.ival < 0) || (rtrn.ival > 255))
1182 ERROR("Private action type must be in the range 0..255\n");
1183 ACTION("Illegal type %d ignored\n", rtrn.ival);
1186 action->type = rtrn.uval;
1189 if (array_ndx == NULL)
1191 if (!ExprResolveString(value, &rtrn, NULL, NULL))
1192 return ReportMismatch(action->type, field, "string");
1195 int len = strlen(rtrn.str);
1196 if ((len < 1) || (len > 7))
1198 WARN("A private action has 7 data bytes\n");
1199 ACTION("Extra %d bytes ignored\n", len - 6);
1202 strncpy((char *) action->data, rtrn.str, 7);
1209 if (!ExprResolveInteger(array_ndx, &rtrn, NULL, NULL))
1211 ERROR("Array subscript must be integer\n");
1212 ACTION("Illegal subscript ignored\n");
1218 ERROR("The data for a private action is 7 bytes long\n");
1219 ACTION("Attempt to use data[%d] ignored\n", ndx);
1222 if (!ExprResolveInteger(value, &rtrn, NULL, NULL))
1223 return ReportMismatch(action->type, field, "integer");
1224 if ((rtrn.ival < 0) || (rtrn.ival > 255))
1226 ERROR("All data for a private action must be 0..255\n");
1227 ACTION("Illegal datum %d ignored\n", rtrn.ival);
1230 action->data[ndx] = rtrn.uval;
1234 return ReportIllegal(PrivateAction, field);
1237 typedef Bool(*actionHandler) (XkbcDescPtr /* xkb */ ,
1238 XkbAnyAction * /* action */ ,
1239 unsigned /* field */ ,
1240 ExprDef * /* array_ndx */ ,
1241 ExprDef * /* value */
1244 static actionHandler handleAction[XkbSA_NumActions + 1] = {
1245 HandleNoAction /* NoAction */ ,
1246 HandleSetLatchMods /* SetMods */ ,
1247 HandleSetLatchMods /* LatchMods */ ,
1248 HandleLockMods /* LockMods */ ,
1249 HandleSetLatchGroup /* SetGroup */ ,
1250 HandleSetLatchGroup /* LatchGroup */ ,
1251 HandleLockGroup /* LockGroup */ ,
1252 HandleMovePtr /* MovePtr */ ,
1253 HandlePtrBtn /* PtrBtn */ ,
1254 HandlePtrBtn /* LockPtrBtn */ ,
1255 HandleSetPtrDflt /* SetPtrDflt */ ,
1256 HandleISOLock /* ISOLock */ ,
1257 HandleNoAction /* Terminate */ ,
1258 HandleSwitchScreen /* SwitchScreen */ ,
1259 HandleSetLockControls /* SetControls */ ,
1260 HandleSetLockControls /* LockControls */ ,
1261 HandleActionMessage /* ActionMessage */ ,
1262 HandleRedirectKey /* RedirectKey */ ,
1263 HandleDeviceBtn /* DeviceBtn */ ,
1264 HandleDeviceBtn /* LockDeviceBtn */ ,
1265 HandleDeviceValuator /* DeviceValuatr */ ,
1266 HandlePrivate /* Private */
1269 /***====================================================================***/
1272 ApplyActionFactoryDefaults(XkbcAction * action)
1274 if (action->type == XkbSA_SetPtrDflt)
1275 { /* increment default button */
1276 action->dflt.affect = XkbSA_AffectDfltBtn;
1277 action->dflt.flags = 0;
1278 XkbSASetPtrDfltValue(&action->dflt, 1);
1280 else if (action->type == XkbSA_ISOLock)
1282 action->iso.real_mods = LockMask;
1289 HandleActionDef(ExprDef * def,
1291 XkbAnyAction * action, unsigned mergeMode, ActionInfo * info)
1295 unsigned tmp, hndlrType;
1297 if (!actionsInitialized)
1300 if (def->op != ExprActionDecl)
1302 ERROR("Expected an action definition, found %s\n",
1303 exprOpText(def->op));
1306 str = XkbcAtomGetString(def->value.action.name);
1309 WSGO("Missing name in action definition!!\n");
1312 if (!stringToAction(str, &tmp))
1314 ERROR("Unknown action %s\n", str);
1317 action->type = hndlrType = tmp;
1318 if (action->type != XkbSA_NoAction)
1320 ApplyActionFactoryDefaults((XkbcAction *) action);
1323 if ((info->action == XkbSA_NoAction)
1324 || (info->action == hndlrType))
1326 if (!(*handleAction[hndlrType]) (xkb, action,
1337 for (arg = def->value.action.args; arg != NULL;
1338 arg = (ExprDef *) arg->common.next)
1340 ExprDef *field, *value, *arrayRtrn;
1341 ExprResult elemRtrn, fieldRtrn;
1344 if (arg->op == OpAssign)
1346 field = arg->value.binary.left;
1347 value = arg->value.binary.right;
1351 if ((arg->op == OpNot) || (arg->op == OpInvert))
1353 field = arg->value.child;
1354 value = &constFalse;
1362 if (!ExprResolveLhs(field, &elemRtrn, &fieldRtrn, &arrayRtrn))
1363 return False; /* internal error -- already reported */
1365 if (elemRtrn.str != NULL)
1367 ERROR("Cannot change defaults in an action definition\n");
1368 ACTION("Ignoring attempt to change %s.%s\n", elemRtrn.str,
1372 if (!stringToField(fieldRtrn.str, &fieldNdx))
1374 ERROR("Unknown field name %s\n", uStringText(fieldRtrn.str));
1377 if (!(*handleAction[hndlrType])
1378 (xkb, action, fieldNdx, arrayRtrn, value))
1386 /***====================================================================***/
1389 SetActionField(XkbcDescPtr xkb,
1392 ExprDef * array_ndx, ExprDef * value, ActionInfo ** info_rtrn)
1394 ActionInfo *new, *old;
1396 if (!actionsInitialized)
1399 new = uTypedAlloc(ActionInfo);
1402 WSGO("Couldn't allocate space for action default\n");
1405 if (uStrCaseCmp(elem, "action") == 0)
1406 new->action = XkbSA_NoAction;
1409 if (!stringToAction(elem, &new->action))
1411 if (new->action == XkbSA_NoAction)
1413 ERROR("\"%s\" is not a valid field in a NoAction action\n",
1418 if (!stringToField(field, &new->field))
1420 ERROR("\"%s\" is not a legal field name\n", field);
1423 new->array_ndx = array_ndx;
1427 while ((old) && (old->next))
1436 /***====================================================================***/
1441 if (!actionsInitialized)
1443 bzero((char *) &constTrue, sizeof(constTrue));
1444 bzero((char *) &constFalse, sizeof(constFalse));
1445 constTrue.common.stmtType = StmtExpr;
1446 constTrue.common.next = NULL;
1447 constTrue.op = ExprIdent;
1448 constTrue.type = TypeBoolean;
1449 constTrue.value.str = XkbcInternAtom("true", False);
1450 constFalse.common.stmtType = StmtExpr;
1451 constFalse.common.next = NULL;
1452 constFalse.op = ExprIdent;
1453 constFalse.type = TypeBoolean;
1454 constFalse.value.str = XkbcInternAtom("false", False);
1455 actionsInitialized = 1;