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",
304 XkbActionTypeText(action, XkbMessage));
309 ReportIllegal(unsigned action, unsigned field)
311 ERROR2("Field %s is not defined for an action of type %s\n",
312 fieldText(field), XkbActionTypeText(action, XkbMessage));
313 ACTION("Action definition ignored\n");
318 ReportActionNotArray(unsigned action, unsigned field)
320 ERROR2("The %s field in the %s action is not an array\n",
321 fieldText(field), XkbActionTypeText(action, XkbMessage));
322 ACTION("Action definition ignored\n");
327 ReportNotFound(unsigned action, unsigned field, const char *what, char *bad)
329 ERROR2("%s named %s not found\n", what, bad);
330 ACTION2("Ignoring the %s field of an %s action\n", fieldText(field),
331 XkbActionTypeText(action, XkbMessage));
336 HandleNoAction(XkbDescPtr xkb,
337 XkbAnyAction * action,
338 unsigned field, ExprDef * array_ndx, ExprDef * value)
340 return ReportIllegal(action->type, field);
344 CheckLatchLockFlags(unsigned action,
345 unsigned field, ExprDef * value, unsigned *flags_inout)
350 if (field == F_ClearLocks)
351 tmp = XkbSA_ClearLocks;
352 else if (field == F_LatchToLock)
353 tmp = XkbSA_LatchToLock;
355 return False; /* WSGO! */
356 if (!ExprResolveBoolean(value, &result, NULL, NULL))
357 return ReportMismatch(action, field, "boolean");
361 *flags_inout &= ~tmp;
366 CheckModifierField(XkbDescPtr xkb,
369 unsigned *flags_inout, unsigned *mods_rtrn)
373 if (value->op == ExprIdent)
375 register char *valStr;
376 valStr = XkbAtomGetString(NULL, value->value.str);
377 if (valStr && ((uStrCaseCmp(valStr, "usemodmapmods") == 0) ||
378 (uStrCaseCmp(valStr, "modmapmods") == 0)))
382 *flags_inout |= XkbSA_UseModMapMods;
386 if (!ExprResolveModMask(value, &rtrn, LookupVModMask, (XPointer) xkb))
387 return ReportMismatch(action, F_Modifiers, "modifier mask");
388 *mods_rtrn = rtrn.uval;
389 *flags_inout &= ~XkbSA_UseModMapMods;
394 HandleSetLatchMods(XkbDescPtr xkb,
395 XkbAnyAction * action,
396 unsigned field, ExprDef * array_ndx, ExprDef * value)
402 act = (XkbModAction *) action;
403 if (array_ndx != NULL)
410 return ReportActionNotArray(action->type, field);
418 if (CheckLatchLockFlags(action->type, field, value, &rtrn))
426 if (CheckModifierField(xkb, action->type, value, &t1, &t2))
429 act->real_mods = act->mask = (t2 & 0xff);
430 t2 = (t2 >> 8) & 0xffff;
431 XkbSetModActionVMods(act, t2);
436 return ReportIllegal(action->type, field);
440 HandleLockMods(XkbDescPtr xkb,
441 XkbAnyAction * action,
442 unsigned field, ExprDef * array_ndx, ExprDef * value)
447 act = (XkbModAction *) action;
448 if ((array_ndx != NULL) && (field == F_Modifiers))
449 return ReportActionNotArray(action->type, field);
454 if (CheckModifierField(xkb, action->type, value, &t1, &t2))
457 act->real_mods = act->mask = (t2 & 0xff);
458 t2 = (t2 >> 8) & 0xffff;
459 XkbSetModActionVMods(act, t2);
464 return ReportIllegal(action->type, field);
467 static LookupEntry groupNames[] = {
480 CheckGroupField(unsigned action,
481 ExprDef * value, unsigned *flags_inout, int *grp_rtrn)
486 if ((value->op == OpNegate) || (value->op == OpUnaryPlus))
488 *flags_inout &= ~XkbSA_GroupAbsolute;
489 spec = value->value.child;
493 *flags_inout |= XkbSA_GroupAbsolute;
497 if (!ExprResolveInteger(spec, &rtrn, SimpleLookup, (XPointer) groupNames))
498 return ReportMismatch(action, F_Group, "integer (range 1..8)");
499 if ((rtrn.ival < 1) || (rtrn.ival > XkbNumKbdGroups))
501 ERROR2("Illegal group %d (must be in the range 1..%d)\n", rtrn.ival,
503 ACTION1("Action %s definition ignored\n",
504 XkbActionTypeText(action, XkbMessage));
507 if (value->op == OpNegate)
508 *grp_rtrn = -rtrn.ival;
509 else if (value->op == OpUnaryPlus)
510 *grp_rtrn = rtrn.ival;
512 *grp_rtrn = rtrn.ival - 1;
517 HandleSetLatchGroup(XkbDescPtr xkb,
518 XkbAnyAction * action,
519 unsigned field, ExprDef * array_ndx, ExprDef * value)
526 act = (XkbGroupAction *) action;
527 if (array_ndx != NULL)
534 return ReportActionNotArray(action->type, field);
542 if (CheckLatchLockFlags(action->type, field, value, &rtrn))
550 if (CheckGroupField(action->type, value, &t1, &t2))
553 XkbSASetGroup(act, t2);
558 return ReportIllegal(action->type, field);
562 HandleLockGroup(XkbDescPtr xkb,
563 XkbAnyAction * action,
564 unsigned field, ExprDef * array_ndx, ExprDef * value)
570 act = (XkbGroupAction *) action;
571 if ((array_ndx != NULL) && (field == F_Group))
572 return ReportActionNotArray(action->type, field);
573 if (field == F_Group)
576 if (CheckGroupField(action->type, value, &t1, &t2))
579 XkbSASetGroup(act, t2);
584 return ReportIllegal(action->type, field);
588 HandleMovePtr(XkbDescPtr xkb,
589 XkbAnyAction * action,
590 unsigned field, ExprDef * array_ndx, ExprDef * value)
596 act = (XkbPtrAction *) action;
597 if ((array_ndx != NULL) && ((field == F_X) || (field == F_Y)))
598 return ReportActionNotArray(action->type, field);
600 if ((field == F_X) || (field == F_Y))
602 if ((value->op == OpNegate) || (value->op == OpUnaryPlus))
606 if (!ExprResolveInteger(value, &rtrn, NULL, NULL))
607 return ReportMismatch(action->type, field, "integer");
611 act->flags |= XkbSA_MoveAbsoluteX;
612 XkbSetPtrActionX(act, rtrn.ival);
617 act->flags |= XkbSA_MoveAbsoluteY;
618 XkbSetPtrActionY(act, rtrn.ival);
622 else if (field == F_Accel)
624 if (!ExprResolveBoolean(value, &rtrn, NULL, NULL))
625 return ReportMismatch(action->type, field, "boolean");
627 act->flags &= ~XkbSA_NoAcceleration;
629 act->flags |= XkbSA_NoAcceleration;
631 return ReportIllegal(action->type, field);
634 static LookupEntry btnNames[] = {
644 static LookupEntry lockWhich[] = {
646 {"lock", XkbSA_LockNoUnlock},
647 {"neither", (XkbSA_LockNoLock | XkbSA_LockNoUnlock)},
648 {"unlock", XkbSA_LockNoLock},
653 HandlePtrBtn(XkbDescPtr xkb,
654 XkbAnyAction * action,
655 unsigned field, ExprDef * array_ndx, ExprDef * value)
658 XkbPtrBtnAction *act;
660 act = (XkbPtrBtnAction *) action;
661 if (field == F_Button)
663 if (array_ndx != NULL)
664 return ReportActionNotArray(action->type, field);
665 if (!ExprResolveInteger
666 (value, &rtrn, SimpleLookup, (XPointer) btnNames))
667 return ReportMismatch(action->type, field,
668 "integer (range 1..5)");
669 if ((rtrn.ival < 0) || (rtrn.ival > 5))
671 ERROR("Button must specify default or be in the range 1..5\n");
672 ACTION1("Illegal button value %d ignored\n", rtrn.ival);
675 act->button = rtrn.ival;
678 else if ((action->type == XkbSA_LockPtrBtn) && (field == F_Affect))
680 if (array_ndx != NULL)
681 return ReportActionNotArray(action->type, field);
682 if (!ExprResolveEnum(value, &rtrn, lockWhich))
683 return ReportMismatch(action->type, field, "lock or unlock");
684 act->flags &= ~(XkbSA_LockNoLock | XkbSA_LockNoUnlock);
685 act->flags |= rtrn.ival;
688 else if (field == F_Count)
690 if (array_ndx != NULL)
691 return ReportActionNotArray(action->type, field);
692 if (!ExprResolveInteger
693 (value, &rtrn, SimpleLookup, (XPointer) btnNames))
694 return ReportMismatch(action->type, field, "integer");
695 if ((rtrn.ival < 0) || (rtrn.ival > 255))
697 ERROR("The count field must have a value in the range 0..255\n");
698 ACTION1("Illegal count %d ignored\n", rtrn.ival);
701 act->count = rtrn.ival;
704 return ReportIllegal(action->type, field);
707 static LookupEntry ptrDflts[] = {
708 {"dfltbtn", XkbSA_AffectDfltBtn},
709 {"defaultbutton", XkbSA_AffectDfltBtn},
710 {"button", XkbSA_AffectDfltBtn},
715 HandleSetPtrDflt(XkbDescPtr xkb,
716 XkbAnyAction * action,
717 unsigned field, ExprDef * array_ndx, ExprDef * value)
720 XkbPtrDfltAction *act;
722 act = (XkbPtrDfltAction *) action;
723 if (field == F_Affect)
725 if (array_ndx != NULL)
726 return ReportActionNotArray(action->type, field);
727 if (!ExprResolveEnum(value, &rtrn, ptrDflts))
728 return ReportMismatch(action->type, field, "pointer component");
729 act->affect = rtrn.uval;
732 else if ((field == F_Button) || (field == F_Value))
735 if (array_ndx != NULL)
736 return ReportActionNotArray(action->type, field);
737 if ((value->op == OpNegate) || (value->op == OpUnaryPlus))
739 act->flags &= ~XkbSA_DfltBtnAbsolute;
740 btn = value->value.child;
744 act->flags |= XkbSA_DfltBtnAbsolute;
748 if (!ExprResolveInteger
749 (btn, &rtrn, SimpleLookup, (XPointer) btnNames))
750 return ReportMismatch(action->type, field,
751 "integer (range 1..5)");
752 if ((rtrn.ival < 0) || (rtrn.ival > 5))
754 ERROR("New default button value must be in the range 1..5\n");
755 ACTION1("Illegal default button value %d ignored\n", rtrn.ival);
760 ERROR("Cannot set default pointer button to \"default\"\n");
761 ACTION("Illegal default button setting ignored\n");
764 if (value->op == OpNegate)
765 XkbSASetPtrDfltValue(act, -rtrn.ival);
767 XkbSASetPtrDfltValue(act, rtrn.ival);
770 return ReportIllegal(action->type, field);
773 static LookupEntry isoNames[] = {
774 {"mods", XkbSA_ISONoAffectMods},
775 {"modifiers", XkbSA_ISONoAffectMods},
776 {"group", XkbSA_ISONoAffectGroup},
777 {"groups", XkbSA_ISONoAffectGroup},
778 {"ptr", XkbSA_ISONoAffectPtr},
779 {"pointer", XkbSA_ISONoAffectPtr},
780 {"ctrls", XkbSA_ISONoAffectCtrls},
781 {"controls", XkbSA_ISONoAffectCtrls},
782 {"all", ~((unsigned) 0)},
788 HandleISOLock(XkbDescPtr xkb,
789 XkbAnyAction * action,
790 unsigned field, ExprDef * array_ndx, ExprDef * value)
794 unsigned flags, mods;
797 act = (XkbISOAction *) action;
801 if (array_ndx != NULL)
802 return ReportActionNotArray(action->type, field);
804 if (CheckModifierField(xkb, action->type, value, &flags, &mods))
806 act->flags = flags & (~XkbSA_ISODfltIsGroup);
807 act->real_mods = mods & 0xff;
808 mods = (mods >> 8) & 0xff;
809 XkbSetModActionVMods(act, mods);
814 if (array_ndx != NULL)
815 return ReportActionNotArray(action->type, field);
817 if (CheckGroupField(action->type, value, &flags, &group))
819 act->flags = flags | XkbSA_ISODfltIsGroup;
820 XkbSASetGroup(act, group);
825 if (array_ndx != NULL)
826 return ReportActionNotArray(action->type, field);
827 if (!ExprResolveMask(value, &rtrn, SimpleLookup, (XPointer) isoNames))
828 return ReportMismatch(action->type, field, "keyboard component");
829 act->affect = (~rtrn.uval) & XkbSA_ISOAffectMask;
832 return ReportIllegal(action->type, field);
836 HandleSwitchScreen(XkbDescPtr xkb,
837 XkbAnyAction * action,
838 unsigned field, ExprDef * array_ndx, ExprDef * value)
841 XkbSwitchScreenAction *act;
843 act = (XkbSwitchScreenAction *) action;
844 if (field == F_Screen)
847 if (array_ndx != NULL)
848 return ReportActionNotArray(action->type, field);
849 if ((value->op == OpNegate) || (value->op == OpUnaryPlus))
851 act->flags &= ~XkbSA_SwitchAbsolute;
852 scrn = value->value.child;
856 act->flags |= XkbSA_SwitchAbsolute;
860 if (!ExprResolveInteger(scrn, &rtrn, NULL, NULL))
861 return ReportMismatch(action->type, field, "integer (0..255)");
862 if ((rtrn.ival < 0) || (rtrn.ival > 255))
864 ERROR("Screen index must be in the range 1..255\n");
865 ACTION1("Illegal screen value %d ignored\n", rtrn.ival);
868 if (value->op == OpNegate)
869 XkbSASetScreen(act, -rtrn.ival);
871 XkbSASetScreen(act, rtrn.ival);
874 else if (field == F_Same)
876 if (array_ndx != NULL)
877 return ReportActionNotArray(action->type, field);
878 if (!ExprResolveBoolean(value, &rtrn, NULL, NULL))
879 return ReportMismatch(action->type, field, "boolean");
881 act->flags &= ~XkbSA_SwitchApplication;
883 act->flags |= XkbSA_SwitchApplication;
886 return ReportIllegal(action->type, field);
889 LookupEntry ctrlNames[] = {
890 {"repeatkeys", XkbRepeatKeysMask}
892 {"repeat", XkbRepeatKeysMask}
894 {"autorepeat", XkbRepeatKeysMask}
896 {"slowkeys", XkbSlowKeysMask}
898 {"bouncekeys", XkbBounceKeysMask}
900 {"stickykeys", XkbStickyKeysMask}
902 {"mousekeys", XkbMouseKeysMask}
904 {"mousekeysaccel", XkbMouseKeysAccelMask}
906 {"accessxkeys", XkbAccessXKeysMask}
908 {"accessxtimeout", XkbAccessXTimeoutMask}
910 {"accessxfeedback", XkbAccessXFeedbackMask}
912 {"audiblebell", XkbAudibleBellMask}
914 {"overlay1", XkbOverlay1Mask}
916 {"overlay2", XkbOverlay2Mask}
918 {"ignoregrouplock", XkbIgnoreGroupLockMask}
920 {"all", XkbAllBooleanCtrlsMask}
928 HandleSetLockControls(XkbDescPtr xkb,
929 XkbAnyAction * action,
930 unsigned field, ExprDef * array_ndx, ExprDef * value)
935 act = (XkbCtrlsAction *) action;
936 if (field == F_Controls)
938 if (array_ndx != NULL)
939 return ReportActionNotArray(action->type, field);
941 (value, &rtrn, SimpleLookup, (XPointer) ctrlNames))
942 return ReportMismatch(action->type, field, "controls mask");
943 XkbActionSetCtrls(act, rtrn.uval);
946 return ReportIllegal(action->type, field);
949 static LookupEntry evNames[] = {
950 {"press", XkbSA_MessageOnPress},
951 {"keypress", XkbSA_MessageOnPress},
952 {"release", XkbSA_MessageOnRelease},
953 {"keyrelease", XkbSA_MessageOnRelease},
954 {"all", XkbSA_MessageOnPress | XkbSA_MessageOnRelease},
960 HandleActionMessage(XkbDescPtr xkb,
961 XkbAnyAction * action,
962 unsigned field, ExprDef * array_ndx, ExprDef * value)
965 XkbMessageAction *act;
967 act = (XkbMessageAction *) action;
971 if (array_ndx != NULL)
972 return ReportActionNotArray(action->type, field);
973 if (!ExprResolveMask(value, &rtrn, SimpleLookup, (XPointer) evNames))
974 return ReportMismatch(action->type, field, "key event mask");
975 act->flags &= ~(XkbSA_MessageOnPress | XkbSA_MessageOnRelease);
977 rtrn.uval & (XkbSA_MessageOnPress | XkbSA_MessageOnRelease);
980 if (array_ndx != NULL)
981 return ReportActionNotArray(action->type, field);
982 if (!ExprResolveBoolean(value, &rtrn, NULL, NULL))
983 return ReportMismatch(action->type, field, "boolean");
985 act->flags |= XkbSA_MessageGenKeyEvent;
987 act->flags &= ~XkbSA_MessageGenKeyEvent;
990 if (array_ndx == NULL)
992 if (!ExprResolveString(value, &rtrn, NULL, NULL))
993 return ReportMismatch(action->type, field, "string");
996 int len = strlen(rtrn.str);
997 if ((len < 1) || (len > 6))
999 WARN("An action message can hold only 6 bytes\n");
1000 ACTION1("Extra %d bytes ignored\n", len - 6);
1002 strncpy((char *) act->message, rtrn.str, 6);
1009 if (!ExprResolveInteger(array_ndx, &rtrn, NULL, NULL))
1011 ERROR("Array subscript must be integer\n");
1012 ACTION("Illegal subscript ignored\n");
1018 ERROR("An action message is at most 6 bytes long\n");
1019 ACTION1("Attempt to use data[%d] ignored\n", ndx);
1022 if (!ExprResolveInteger(value, &rtrn, NULL, NULL))
1023 return ReportMismatch(action->type, field, "integer");
1024 if ((rtrn.ival < 0) || (rtrn.ival > 255))
1026 ERROR("Message data must be in the range 0..255\n");
1027 ACTION1("Illegal datum %d ignored\n", rtrn.ival);
1030 act->message[ndx] = rtrn.uval;
1034 return ReportIllegal(action->type, field);
1038 HandleRedirectKey(XkbDescPtr xkb,
1039 XkbAnyAction * action,
1040 unsigned field, ExprDef * array_ndx, ExprDef * value)
1043 XkbRedirectKeyAction *act;
1044 unsigned t1, t2, vmods, vmask;
1047 if (array_ndx != NULL)
1048 return ReportActionNotArray(action->type, field);
1050 act = (XkbRedirectKeyAction *) action;
1054 if (!ExprResolveKeyName(value, &rtrn, NULL, NULL))
1055 return ReportMismatch(action->type, field, "key name");
1056 tmp = KeyNameToLong(rtrn.keyName.name);
1057 if (!FindNamedKey(xkb, tmp, &t1, True, CreateKeyNames(xkb), 0))
1059 return ReportNotFound(action->type, field, "Key",
1060 XkbKeyNameText(rtrn.keyName.name,
1068 if (CheckModifierField(xkb, action->type, value, &t1, &t2))
1070 act->mods_mask |= (t2 & 0xff);
1071 if (field == F_Modifiers)
1072 act->mods |= (t2 & 0xff);
1074 act->mods &= ~(t2 & 0xff);
1076 t2 = (t2 >> 8) & 0xffff;
1077 vmods = XkbSARedirectVMods(act);
1078 vmask = XkbSARedirectVModsMask(act);
1080 if (field == F_Modifiers)
1084 XkbSARedirectSetVMods(act, vmods);
1085 XkbSARedirectSetVModsMask(act, vmask);
1090 return ReportIllegal(action->type, field);
1094 HandleDeviceBtn(XkbDescPtr xkb,
1095 XkbAnyAction * action,
1096 unsigned field, ExprDef * array_ndx, ExprDef * value)
1099 XkbDeviceBtnAction *act;
1101 act = (XkbDeviceBtnAction *) action;
1102 if (field == F_Button)
1104 if (array_ndx != NULL)
1105 return ReportActionNotArray(action->type, field);
1106 if (!ExprResolveInteger(value, &rtrn, NULL, NULL))
1107 return ReportMismatch(action->type, field,
1108 "integer (range 1..255)");
1109 if ((rtrn.ival < 0) || (rtrn.ival > 255))
1111 ERROR("Button must specify default or be in the range 1..255\n");
1112 ACTION1("Illegal button value %d ignored\n", rtrn.ival);
1115 act->button = rtrn.ival;
1118 else if ((action->type == XkbSA_LockDeviceBtn) && (field == F_Affect))
1120 if (array_ndx != NULL)
1121 return ReportActionNotArray(action->type, field);
1122 if (!ExprResolveEnum(value, &rtrn, lockWhich))
1123 return ReportMismatch(action->type, field, "lock or unlock");
1124 act->flags &= ~(XkbSA_LockNoLock | XkbSA_LockNoUnlock);
1125 act->flags |= rtrn.ival;
1128 else if (field == F_Count)
1130 if (array_ndx != NULL)
1131 return ReportActionNotArray(action->type, field);
1132 if (!ExprResolveInteger
1133 (value, &rtrn, SimpleLookup, (XPointer) btnNames))
1134 return ReportMismatch(action->type, field, "integer");
1135 if ((rtrn.ival < 0) || (rtrn.ival > 255))
1137 ERROR("The count field must have a value in the range 0..255\n");
1138 ACTION1("Illegal count %d ignored\n", rtrn.ival);
1141 act->count = rtrn.ival;
1144 else if (field == F_Device)
1146 if (array_ndx != NULL)
1147 return ReportActionNotArray(action->type, field);
1148 if (!ExprResolveInteger(value, &rtrn, NULL, NULL))
1149 return ReportMismatch(action->type, field,
1150 "integer (range 1..255)");
1151 if ((rtrn.ival < 0) || (rtrn.ival > 255))
1153 ERROR("Device must specify default or be in the range 1..255\n");
1154 ACTION1("Illegal device value %d ignored\n", rtrn.ival);
1157 act->device = rtrn.ival;
1160 return ReportIllegal(action->type, field);
1164 HandleDeviceValuator(XkbDescPtr xkb,
1165 XkbAnyAction * action,
1166 unsigned field, ExprDef * array_ndx, ExprDef * value)
1170 XkbDeviceValuatorAction *act;
1172 act = (XkbDeviceValuatorAction *) action;
1173 /* XXX - Not yet implemented */
1179 HandlePrivate(XkbDescPtr xkb,
1180 XkbAnyAction * action,
1181 unsigned field, ExprDef * array_ndx, ExprDef * value)
1188 if (!ExprResolveInteger(value, &rtrn, NULL, NULL))
1189 return ReportMismatch(PrivateAction, field, "integer");
1190 if ((rtrn.ival < 0) || (rtrn.ival > 255))
1192 ERROR("Private action type must be in the range 0..255\n");
1193 ACTION1("Illegal type %d ignored\n", rtrn.ival);
1196 action->type = rtrn.uval;
1199 if (array_ndx == NULL)
1201 if (!ExprResolveString(value, &rtrn, NULL, NULL))
1202 return ReportMismatch(action->type, field, "string");
1205 int len = strlen(rtrn.str);
1206 if ((len < 1) || (len > 7))
1208 WARN("A private action has 7 data bytes\n");
1209 ACTION1("Extra %d bytes ignored\n", len - 6);
1212 strncpy((char *) action->data, rtrn.str, 7);
1219 if (!ExprResolveInteger(array_ndx, &rtrn, NULL, NULL))
1221 ERROR("Array subscript must be integer\n");
1222 ACTION("Illegal subscript ignored\n");
1228 ERROR("The data for a private action is 7 bytes long\n");
1229 ACTION1("Attempt to use data[%d] ignored\n", ndx);
1232 if (!ExprResolveInteger(value, &rtrn, NULL, NULL))
1233 return ReportMismatch(action->type, field, "integer");
1234 if ((rtrn.ival < 0) || (rtrn.ival > 255))
1236 ERROR("All data for a private action must be 0..255\n");
1237 ACTION1("Illegal datum %d ignored\n", rtrn.ival);
1240 action->data[ndx] = rtrn.uval;
1244 return ReportIllegal(PrivateAction, field);
1247 typedef Bool(*actionHandler) (XkbDescPtr /* xkb */ ,
1248 XkbAnyAction * /* action */ ,
1249 unsigned /* field */ ,
1250 ExprDef * /* array_ndx */ ,
1251 ExprDef * /* value */
1254 static actionHandler handleAction[XkbSA_NumActions + 1] = {
1255 HandleNoAction /* NoAction */ ,
1256 HandleSetLatchMods /* SetMods */ ,
1257 HandleSetLatchMods /* LatchMods */ ,
1258 HandleLockMods /* LockMods */ ,
1259 HandleSetLatchGroup /* SetGroup */ ,
1260 HandleSetLatchGroup /* LatchGroup */ ,
1261 HandleLockGroup /* LockGroup */ ,
1262 HandleMovePtr /* MovePtr */ ,
1263 HandlePtrBtn /* PtrBtn */ ,
1264 HandlePtrBtn /* LockPtrBtn */ ,
1265 HandleSetPtrDflt /* SetPtrDflt */ ,
1266 HandleISOLock /* ISOLock */ ,
1267 HandleNoAction /* Terminate */ ,
1268 HandleSwitchScreen /* SwitchScreen */ ,
1269 HandleSetLockControls /* SetControls */ ,
1270 HandleSetLockControls /* LockControls */ ,
1271 HandleActionMessage /* ActionMessage */ ,
1272 HandleRedirectKey /* RedirectKey */ ,
1273 HandleDeviceBtn /* DeviceBtn */ ,
1274 HandleDeviceBtn /* LockDeviceBtn */ ,
1275 HandleDeviceValuator /* DeviceValuatr */ ,
1276 HandlePrivate /* Private */
1279 /***====================================================================***/
1282 ApplyActionFactoryDefaults(XkbAction * action)
1284 if (action->type == XkbSA_SetPtrDflt)
1285 { /* increment default button */
1286 action->dflt.affect = XkbSA_AffectDfltBtn;
1287 action->dflt.flags = 0;
1288 XkbSASetPtrDfltValue(&action->dflt, 1);
1290 else if (action->type == XkbSA_ISOLock)
1292 action->iso.real_mods = LockMask;
1299 HandleActionDef(ExprDef * def,
1301 XkbAnyAction * action, unsigned mergeMode, ActionInfo * info)
1305 unsigned tmp, hndlrType;
1307 if (!actionsInitialized)
1310 if (def->op != ExprActionDecl)
1312 ERROR1("Expected an action definition, found %s\n",
1313 exprOpText(def->op));
1316 str = XkbAtomGetString(NULL, def->value.action.name);
1319 WSGO("Missing name in action definition!!\n");
1322 if (!stringToAction(str, &tmp))
1324 ERROR1("Unknown action %s\n", str);
1327 action->type = hndlrType = tmp;
1328 if (action->type != XkbSA_NoAction)
1330 ApplyActionFactoryDefaults((XkbAction *) action);
1333 if ((info->action == XkbSA_NoAction)
1334 || (info->action == hndlrType))
1336 if (!(*handleAction[hndlrType]) (xkb, action,
1347 for (arg = def->value.action.args; arg != NULL;
1348 arg = (ExprDef *) arg->common.next)
1350 ExprDef *field, *value, *arrayRtrn;
1351 ExprResult elemRtrn, fieldRtrn;
1354 if (arg->op == OpAssign)
1356 field = arg->value.binary.left;
1357 value = arg->value.binary.right;
1361 if ((arg->op == OpNot) || (arg->op == OpInvert))
1363 field = arg->value.child;
1364 value = &constFalse;
1372 if (!ExprResolveLhs(field, &elemRtrn, &fieldRtrn, &arrayRtrn))
1373 return False; /* internal error -- already reported */
1375 if (elemRtrn.str != NULL)
1377 ERROR("Cannot change defaults in an action definition\n");
1378 ACTION2("Ignoring attempt to change %s.%s\n", elemRtrn.str,
1382 if (!stringToField(fieldRtrn.str, &fieldNdx))
1384 ERROR1("Unknown field name %s\n", uStringText(fieldRtrn.str));
1387 if (!(*handleAction[hndlrType])
1388 (xkb, action, fieldNdx, arrayRtrn, value))
1396 /***====================================================================***/
1399 SetActionField(XkbDescPtr xkb,
1402 ExprDef * array_ndx, ExprDef * value, ActionInfo ** info_rtrn)
1404 ActionInfo *new, *old;
1406 if (!actionsInitialized)
1409 new = uTypedAlloc(ActionInfo);
1412 WSGO("Couldn't allocate space for action default\n");
1415 if (uStrCaseCmp(elem, "action") == 0)
1416 new->action = XkbSA_NoAction;
1419 if (!stringToAction(elem, &new->action))
1421 if (new->action == XkbSA_NoAction)
1423 ERROR1("\"%s\" is not a valid field in a NoAction action\n",
1428 if (!stringToField(field, &new->field))
1430 ERROR1("\"%s\" is not a legal field name\n", field);
1433 new->array_ndx = array_ndx;
1437 while ((old) && (old->next))
1446 /***====================================================================***/
1451 if (!actionsInitialized)
1453 bzero((char *) &constTrue, sizeof(constTrue));
1454 bzero((char *) &constFalse, sizeof(constFalse));
1455 constTrue.common.stmtType = StmtExpr;
1456 constTrue.common.next = NULL;
1457 constTrue.op = ExprIdent;
1458 constTrue.type = TypeBoolean;
1459 constTrue.value.str = XkbInternAtom(NULL, "true", False);
1460 constFalse.common.stmtType = StmtExpr;
1461 constFalse.common.next = NULL;
1462 constFalse.op = ExprIdent;
1463 constFalse.type = TypeBoolean;
1464 constFalse.value.str = XkbInternAtom(NULL, "false", False);
1465 actionsInitialized = 1;