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(const 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,
329 ERROR("%s named %s not found\n", what, bad);
330 ACTION("Ignoring the %s field of an %s action\n", fieldText(field),
331 XkbcActionTypeText(action));
336 HandleNoAction(struct xkb_desc * xkb,
337 struct xkb_any_action * 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))
357 return ReportMismatch(action, field, "boolean");
361 *flags_inout &= ~tmp;
366 CheckModifierField(struct xkb_desc * xkb,
369 unsigned *flags_inout, unsigned *mods_rtrn)
373 if (value->op == ExprIdent)
376 valStr = XkbcAtomText(value->value.str);
377 if (valStr && ((uStrCaseCmp(valStr, "usemodmapmods") == 0) ||
378 (uStrCaseCmp(valStr, "modmapmods") == 0)))
382 *flags_inout |= XkbSA_UseModMapMods;
386 if (!ExprResolveVModMask(value, &rtrn, xkb))
387 return ReportMismatch(action, F_Modifiers, "modifier mask");
388 *mods_rtrn = rtrn.uval;
389 *flags_inout &= ~XkbSA_UseModMapMods;
394 HandleSetLatchMods(struct xkb_desc * xkb,
395 struct xkb_any_action * action,
396 unsigned field, ExprDef * array_ndx, ExprDef * value)
398 struct xkb_mod_action *act;
402 act = (struct xkb_mod_action *) 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 act->vmods = (t2 >> 8) & 0xffff;
435 return ReportIllegal(action->type, field);
439 HandleLockMods(struct xkb_desc * xkb,
440 struct xkb_any_action * action,
441 unsigned field, ExprDef * array_ndx, ExprDef * value)
443 struct xkb_mod_action *act;
446 act = (struct xkb_mod_action *) 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 act->vmods = (t2 >> 8) & 0xffff;
462 return ReportIllegal(action->type, field);
466 CheckGroupField(unsigned action,
467 ExprDef * value, unsigned *flags_inout, int *grp_rtrn)
472 if ((value->op == OpNegate) || (value->op == OpUnaryPlus))
474 *flags_inout &= ~XkbSA_GroupAbsolute;
475 spec = value->value.child;
479 *flags_inout |= XkbSA_GroupAbsolute;
483 if (!ExprResolveGroup(spec, &rtrn))
484 return ReportMismatch(action, F_Group, "integer (range 1..8)");
485 if (value->op == OpNegate)
486 *grp_rtrn = -rtrn.ival;
487 else if (value->op == OpUnaryPlus)
488 *grp_rtrn = rtrn.ival;
490 *grp_rtrn = rtrn.ival - 1;
495 HandleSetLatchGroup(struct xkb_desc * xkb,
496 struct xkb_any_action * action,
497 unsigned field, ExprDef * array_ndx, ExprDef * value)
499 struct xkb_group_action *act;
504 act = (struct xkb_group_action *) action;
505 if (array_ndx != NULL)
512 return ReportActionNotArray(action->type, field);
520 if (CheckLatchLockFlags(action->type, field, value, &rtrn))
528 if (CheckGroupField(action->type, value, &t1, &t2))
536 return ReportIllegal(action->type, field);
540 HandleLockGroup(struct xkb_desc * xkb,
541 struct xkb_any_action * action,
542 unsigned field, ExprDef * array_ndx, ExprDef * value)
544 struct xkb_group_action *act;
548 act = (struct xkb_group_action *) action;
549 if ((array_ndx != NULL) && (field == F_Group))
550 return ReportActionNotArray(action->type, field);
551 if (field == F_Group)
554 if (CheckGroupField(action->type, value, &t1, &t2))
562 return ReportIllegal(action->type, field);
566 HandleMovePtr(struct xkb_desc * xkb,
567 struct xkb_any_action * action,
568 unsigned field, ExprDef * array_ndx, ExprDef * value)
571 struct xkb_pointer_action *act;
574 act = (struct xkb_pointer_action *) action;
575 if ((array_ndx != NULL) && ((field == F_X) || (field == F_Y)))
576 return ReportActionNotArray(action->type, field);
578 if ((field == F_X) || (field == F_Y))
580 if ((value->op == OpNegate) || (value->op == OpUnaryPlus))
584 if (!ExprResolveInteger(value, &rtrn))
585 return ReportMismatch(action->type, field, "integer");
589 act->flags |= XkbSA_MoveAbsoluteX;
595 act->flags |= XkbSA_MoveAbsoluteY;
600 else if (field == F_Accel)
602 if (!ExprResolveBoolean(value, &rtrn))
603 return ReportMismatch(action->type, field, "boolean");
605 act->flags &= ~XkbSA_NoAcceleration;
607 act->flags |= XkbSA_NoAcceleration;
609 return ReportIllegal(action->type, field);
612 static const LookupEntry lockWhich[] = {
614 {"lock", XkbSA_LockNoUnlock},
615 {"neither", (XkbSA_LockNoLock | XkbSA_LockNoUnlock)},
616 {"unlock", XkbSA_LockNoLock},
621 HandlePtrBtn(struct xkb_desc * xkb,
622 struct xkb_any_action * action,
623 unsigned field, ExprDef * array_ndx, ExprDef * value)
626 struct xkb_pointer_button_action *act;
628 act = (struct xkb_pointer_button_action *) action;
629 if (field == F_Button)
631 if (array_ndx != NULL)
632 return ReportActionNotArray(action->type, field);
633 if (!ExprResolveButton(value, &rtrn))
634 return ReportMismatch(action->type, field,
635 "integer (range 1..5)");
636 if ((rtrn.ival < 0) || (rtrn.ival > 5))
638 ERROR("Button must specify default or be in the range 1..5\n");
639 ACTION("Illegal button value %d ignored\n", rtrn.ival);
642 act->button = rtrn.ival;
645 else if ((action->type == XkbSA_LockPtrBtn) && (field == F_Affect))
647 if (array_ndx != NULL)
648 return ReportActionNotArray(action->type, field);
649 if (!ExprResolveEnum(value, &rtrn, lockWhich))
650 return ReportMismatch(action->type, field, "lock or unlock");
651 act->flags &= ~(XkbSA_LockNoLock | XkbSA_LockNoUnlock);
652 act->flags |= rtrn.ival;
655 else if (field == F_Count)
657 if (array_ndx != NULL)
658 return ReportActionNotArray(action->type, field);
659 if (!ExprResolveButton(value, &rtrn))
660 return ReportMismatch(action->type, field, "integer");
661 if ((rtrn.ival < 0) || (rtrn.ival > 255))
663 ERROR("The count field must have a value in the range 0..255\n");
664 ACTION("Illegal count %d ignored\n", rtrn.ival);
667 act->count = rtrn.ival;
670 return ReportIllegal(action->type, field);
673 static const LookupEntry ptrDflts[] = {
674 {"dfltbtn", XkbSA_AffectDfltBtn},
675 {"defaultbutton", XkbSA_AffectDfltBtn},
676 {"button", XkbSA_AffectDfltBtn},
681 HandleSetPtrDflt(struct xkb_desc * xkb,
682 struct xkb_any_action * action,
683 unsigned field, ExprDef * array_ndx, ExprDef * value)
686 struct xkb_pointer_default_action *act;
688 act = (struct xkb_pointer_default_action *) action;
689 if (field == F_Affect)
691 if (array_ndx != NULL)
692 return ReportActionNotArray(action->type, field);
693 if (!ExprResolveEnum(value, &rtrn, ptrDflts))
694 return ReportMismatch(action->type, field, "pointer component");
695 act->affect = rtrn.uval;
698 else if ((field == F_Button) || (field == F_Value))
701 if (array_ndx != NULL)
702 return ReportActionNotArray(action->type, field);
703 if ((value->op == OpNegate) || (value->op == OpUnaryPlus))
705 act->flags &= ~XkbSA_DfltBtnAbsolute;
706 btn = value->value.child;
710 act->flags |= XkbSA_DfltBtnAbsolute;
714 if (!ExprResolveButton(btn, &rtrn))
715 return ReportMismatch(action->type, field,
716 "integer (range 1..5)");
717 if ((rtrn.ival < 0) || (rtrn.ival > 5))
719 ERROR("New default button value must be in the range 1..5\n");
720 ACTION("Illegal default button value %d ignored\n", rtrn.ival);
725 ERROR("Cannot set default pointer button to \"default\"\n");
726 ACTION("Illegal default button setting ignored\n");
729 if (value->op == OpNegate)
730 act->value = -rtrn.ival;
732 act->value = rtrn.ival;
735 return ReportIllegal(action->type, field);
738 static const LookupEntry isoNames[] = {
739 {"mods", XkbSA_ISONoAffectMods},
740 {"modifiers", XkbSA_ISONoAffectMods},
741 {"group", XkbSA_ISONoAffectGroup},
742 {"groups", XkbSA_ISONoAffectGroup},
743 {"ptr", XkbSA_ISONoAffectPtr},
744 {"pointer", XkbSA_ISONoAffectPtr},
745 {"ctrls", XkbSA_ISONoAffectCtrls},
746 {"controls", XkbSA_ISONoAffectCtrls},
747 {"all", ~((unsigned) 0)},
753 HandleISOLock(struct xkb_desc * xkb,
754 struct xkb_any_action * action,
755 unsigned field, ExprDef * array_ndx, ExprDef * value)
758 struct xkb_iso_action *act;
759 unsigned flags, mods;
762 act = (struct xkb_iso_action *) action;
766 if (array_ndx != NULL)
767 return ReportActionNotArray(action->type, field);
769 if (CheckModifierField(xkb, action->type, value, &flags, &mods))
771 act->flags = flags & (~XkbSA_ISODfltIsGroup);
772 act->real_mods = mods & 0xff;
773 act->vmods = (mods >> 8) & 0xff;
778 if (array_ndx != NULL)
779 return ReportActionNotArray(action->type, field);
781 if (CheckGroupField(action->type, value, &flags, &group))
783 act->flags = flags | XkbSA_ISODfltIsGroup;
789 if (array_ndx != NULL)
790 return ReportActionNotArray(action->type, field);
791 if (!ExprResolveMask(value, &rtrn, isoNames))
792 return ReportMismatch(action->type, field, "keyboard component");
793 act->affect = (~rtrn.uval) & XkbSA_ISOAffectMask;
796 return ReportIllegal(action->type, field);
800 HandleSwitchScreen(struct xkb_desc * xkb,
801 struct xkb_any_action * action,
802 unsigned field, ExprDef * array_ndx, ExprDef * value)
805 struct xkb_switch_screen_action *act;
807 act = (struct xkb_switch_screen_action *) action;
808 if (field == F_Screen)
811 if (array_ndx != NULL)
812 return ReportActionNotArray(action->type, field);
813 if ((value->op == OpNegate) || (value->op == OpUnaryPlus))
815 act->flags &= ~XkbSA_SwitchAbsolute;
816 scrn = value->value.child;
820 act->flags |= XkbSA_SwitchAbsolute;
824 if (!ExprResolveInteger(scrn, &rtrn))
825 return ReportMismatch(action->type, field, "integer (0..255)");
826 if ((rtrn.ival < 0) || (rtrn.ival > 255))
828 ERROR("Screen index must be in the range 1..255\n");
829 ACTION("Illegal screen value %d ignored\n", rtrn.ival);
832 if (value->op == OpNegate)
833 act->screen = -rtrn.ival;
835 act->screen = rtrn.ival;
838 else if (field == F_Same)
840 if (array_ndx != NULL)
841 return ReportActionNotArray(action->type, field);
842 if (!ExprResolveBoolean(value, &rtrn))
843 return ReportMismatch(action->type, field, "boolean");
845 act->flags &= ~XkbSA_SwitchApplication;
847 act->flags |= XkbSA_SwitchApplication;
850 return ReportIllegal(action->type, field);
853 const LookupEntry ctrlNames[] = {
854 {"repeatkeys", XkbRepeatKeysMask},
855 {"repeat", XkbRepeatKeysMask},
856 {"autorepeat", XkbRepeatKeysMask},
857 {"slowkeys", XkbSlowKeysMask},
858 {"bouncekeys", XkbBounceKeysMask},
859 {"stickykeys", XkbStickyKeysMask},
860 {"mousekeys", XkbMouseKeysMask},
861 {"mousekeysaccel", XkbMouseKeysAccelMask},
862 {"accessxkeys", XkbAccessXKeysMask},
863 {"accessxtimeout", XkbAccessXTimeoutMask},
864 {"accessxfeedback", XkbAccessXFeedbackMask},
865 {"audiblebell", XkbAudibleBellMask},
866 {"overlay1", XkbOverlay1Mask},
867 {"overlay2", XkbOverlay2Mask},
868 {"ignoregrouplock", XkbIgnoreGroupLockMask},
869 {"all", XkbAllBooleanCtrlsMask},
875 HandleSetLockControls(struct xkb_desc * xkb,
876 struct xkb_any_action * action,
877 unsigned field, ExprDef * array_ndx, ExprDef * value)
880 struct xkb_controls_action *act;
882 act = (struct xkb_controls_action *) action;
883 if (field == F_Controls)
885 if (array_ndx != NULL)
886 return ReportActionNotArray(action->type, field);
887 if (!ExprResolveMask(value, &rtrn, ctrlNames))
888 return ReportMismatch(action->type, field, "controls mask");
889 act->ctrls = rtrn.uval;
892 return ReportIllegal(action->type, field);
895 static const LookupEntry evNames[] = {
896 {"press", XkbSA_MessageOnPress},
897 {"keypress", XkbSA_MessageOnPress},
898 {"release", XkbSA_MessageOnRelease},
899 {"keyrelease", XkbSA_MessageOnRelease},
900 {"all", XkbSA_MessageOnPress | XkbSA_MessageOnRelease},
906 HandleActionMessage(struct xkb_desc * xkb,
907 struct xkb_any_action * action,
908 unsigned field, ExprDef * array_ndx, ExprDef * value)
911 struct xkb_message_action *act;
913 act = (struct xkb_message_action *) action;
917 if (array_ndx != NULL)
918 return ReportActionNotArray(action->type, field);
919 if (!ExprResolveMask(value, &rtrn, evNames))
920 return ReportMismatch(action->type, field, "key event mask");
921 act->flags &= ~(XkbSA_MessageOnPress | XkbSA_MessageOnRelease);
923 rtrn.uval & (XkbSA_MessageOnPress | XkbSA_MessageOnRelease);
926 if (array_ndx != NULL)
927 return ReportActionNotArray(action->type, field);
928 if (!ExprResolveBoolean(value, &rtrn))
929 return ReportMismatch(action->type, field, "boolean");
931 act->flags |= XkbSA_MessageGenKeyEvent;
933 act->flags &= ~XkbSA_MessageGenKeyEvent;
936 if (array_ndx == NULL)
938 if (!ExprResolveString(value, &rtrn))
939 return ReportMismatch(action->type, field, "string");
942 int len = strlen(rtrn.str);
943 if ((len < 1) || (len > 6))
945 WARN("An action message can hold only 6 bytes\n");
946 ACTION("Extra %d bytes ignored\n", len - 6);
948 strncpy((char *) act->message, rtrn.str, 6);
955 if (!ExprResolveInteger(array_ndx, &rtrn))
957 ERROR("Array subscript must be integer\n");
958 ACTION("Illegal subscript ignored\n");
964 ERROR("An action message is at most 6 bytes long\n");
965 ACTION("Attempt to use data[%d] ignored\n", ndx);
968 if (!ExprResolveInteger(value, &rtrn))
969 return ReportMismatch(action->type, field, "integer");
970 if ((rtrn.ival < 0) || (rtrn.ival > 255))
972 ERROR("Message data must be in the range 0..255\n");
973 ACTION("Illegal datum %d ignored\n", rtrn.ival);
976 act->message[ndx] = rtrn.uval;
980 return ReportIllegal(action->type, field);
984 HandleRedirectKey(struct xkb_desc * xkb,
985 struct xkb_any_action * action,
986 unsigned field, ExprDef * array_ndx, ExprDef * value)
989 struct xkb_redirect_key_action *act;
994 if (array_ndx != NULL)
995 return ReportActionNotArray(action->type, field);
997 act = (struct xkb_redirect_key_action *) action;
1001 if (!ExprResolveKeyName(value, &rtrn))
1002 return ReportMismatch(action->type, field, "key name");
1003 tmp = KeyNameToLong(rtrn.keyName.name);
1004 if (!FindNamedKey(xkb, tmp, &kc, True, CreateKeyNames(xkb), 0))
1006 return ReportNotFound(action->type, field, "Key",
1007 XkbcKeyNameText(rtrn.keyName.name));
1014 if (CheckModifierField(xkb, action->type, value, &t1, &t2))
1016 act->mods_mask |= (t2 & 0xff);
1017 if (field == F_Modifiers)
1018 act->mods |= (t2 & 0xff);
1020 act->mods &= ~(t2 & 0xff);
1022 t2 = (t2 >> 8) & 0xffff;
1023 act->vmods_mask |= t2;
1024 if (field == F_Modifiers)
1032 return ReportIllegal(action->type, field);
1036 HandleDeviceBtn(struct xkb_desc * xkb,
1037 struct xkb_any_action * action,
1038 unsigned field, ExprDef * array_ndx, ExprDef * value)
1041 struct xkb_device_button_action *act;
1043 act = (struct xkb_device_button_action *) action;
1044 if (field == F_Button)
1046 if (array_ndx != NULL)
1047 return ReportActionNotArray(action->type, field);
1048 if (!ExprResolveInteger(value, &rtrn))
1049 return ReportMismatch(action->type, field,
1050 "integer (range 1..255)");
1051 if ((rtrn.ival < 0) || (rtrn.ival > 255))
1053 ERROR("Button must specify default or be in the range 1..255\n");
1054 ACTION("Illegal button value %d ignored\n", rtrn.ival);
1057 act->button = rtrn.ival;
1060 else if ((action->type == XkbSA_LockDeviceBtn) && (field == F_Affect))
1062 if (array_ndx != NULL)
1063 return ReportActionNotArray(action->type, field);
1064 if (!ExprResolveEnum(value, &rtrn, lockWhich))
1065 return ReportMismatch(action->type, field, "lock or unlock");
1066 act->flags &= ~(XkbSA_LockNoLock | XkbSA_LockNoUnlock);
1067 act->flags |= rtrn.ival;
1070 else if (field == F_Count)
1072 if (array_ndx != NULL)
1073 return ReportActionNotArray(action->type, field);
1074 if (!ExprResolveButton(value, &rtrn))
1075 return ReportMismatch(action->type, field, "integer");
1076 if ((rtrn.ival < 0) || (rtrn.ival > 255))
1078 ERROR("The count field must have a value in the range 0..255\n");
1079 ACTION("Illegal count %d ignored\n", rtrn.ival);
1082 act->count = rtrn.ival;
1085 else if (field == F_Device)
1087 if (array_ndx != NULL)
1088 return ReportActionNotArray(action->type, field);
1089 if (!ExprResolveInteger(value, &rtrn))
1090 return ReportMismatch(action->type, field,
1091 "integer (range 1..255)");
1092 if ((rtrn.ival < 0) || (rtrn.ival > 255))
1094 ERROR("Device must specify default or be in the range 1..255\n");
1095 ACTION("Illegal device value %d ignored\n", rtrn.ival);
1098 act->device = rtrn.ival;
1101 return ReportIllegal(action->type, field);
1105 HandleDeviceValuator(struct xkb_desc * xkb,
1106 struct xkb_any_action * action,
1107 unsigned field, ExprDef * array_ndx, ExprDef * value)
1111 struct xkb_device_valuator_action *act;
1113 act = (struct xkb_device_valuator_action *) action;
1114 /* XXX - Not yet implemented */
1120 HandlePrivate(struct xkb_desc * xkb,
1121 struct xkb_any_action * action,
1122 unsigned field, ExprDef * array_ndx, ExprDef * value)
1129 if (!ExprResolveInteger(value, &rtrn))
1130 return ReportMismatch(PrivateAction, field, "integer");
1131 if ((rtrn.ival < 0) || (rtrn.ival > 255))
1133 ERROR("Private action type must be in the range 0..255\n");
1134 ACTION("Illegal type %d ignored\n", rtrn.ival);
1137 action->type = rtrn.uval;
1140 if (array_ndx == NULL)
1142 if (!ExprResolveString(value, &rtrn))
1143 return ReportMismatch(action->type, field, "string");
1146 int len = strlen(rtrn.str);
1147 if ((len < 1) || (len > 7))
1149 WARN("A private action has 7 data bytes\n");
1150 ACTION("Extra %d bytes ignored\n", len - 6);
1153 strncpy((char *) action->data, rtrn.str, sizeof action->data);
1161 if (!ExprResolveInteger(array_ndx, &rtrn))
1163 ERROR("Array subscript must be integer\n");
1164 ACTION("Illegal subscript ignored\n");
1168 if (ndx >= sizeof action->data)
1170 ERROR("The data for a private action is 18 bytes long\n");
1171 ACTION("Attempt to use data[%d] ignored\n", ndx);
1174 if (!ExprResolveInteger(value, &rtrn))
1175 return ReportMismatch(action->type, field, "integer");
1176 if ((rtrn.ival < 0) || (rtrn.ival > 255))
1178 ERROR("All data for a private action must be 0..255\n");
1179 ACTION("Illegal datum %d ignored\n", rtrn.ival);
1182 action->data[ndx] = rtrn.uval;
1186 return ReportIllegal(PrivateAction, field);
1189 typedef Bool(*actionHandler) (struct xkb_desc * /* xkb */ ,
1190 struct xkb_any_action * /* action */ ,
1191 unsigned /* field */ ,
1192 ExprDef * /* array_ndx */ ,
1193 ExprDef * /* value */
1196 static const actionHandler handleAction[XkbSA_NumActions + 1] = {
1197 HandleNoAction /* NoAction */ ,
1198 HandleSetLatchMods /* SetMods */ ,
1199 HandleSetLatchMods /* LatchMods */ ,
1200 HandleLockMods /* LockMods */ ,
1201 HandleSetLatchGroup /* SetGroup */ ,
1202 HandleSetLatchGroup /* LatchGroup */ ,
1203 HandleLockGroup /* LockGroup */ ,
1204 HandleMovePtr /* MovePtr */ ,
1205 HandlePtrBtn /* PtrBtn */ ,
1206 HandlePtrBtn /* LockPtrBtn */ ,
1207 HandleSetPtrDflt /* SetPtrDflt */ ,
1208 HandleISOLock /* ISOLock */ ,
1209 HandleNoAction /* Terminate */ ,
1210 HandleSwitchScreen /* SwitchScreen */ ,
1211 HandleSetLockControls /* SetControls */ ,
1212 HandleSetLockControls /* LockControls */ ,
1213 HandleActionMessage /* ActionMessage */ ,
1214 HandleRedirectKey /* RedirectKey */ ,
1215 HandleDeviceBtn /* DeviceBtn */ ,
1216 HandleDeviceBtn /* LockDeviceBtn */ ,
1217 HandleDeviceValuator /* DeviceValuatr */ ,
1218 HandlePrivate /* Private */
1221 /***====================================================================***/
1224 ApplyActionFactoryDefaults(union xkb_action * action)
1226 if (action->type == XkbSA_SetPtrDflt)
1227 { /* increment default button */
1228 action->dflt.affect = XkbSA_AffectDfltBtn;
1229 action->dflt.flags = 0;
1230 action->dflt.value = 1;
1232 else if (action->type == XkbSA_ISOLock)
1234 action->iso.real_mods = LockMask;
1242 HandleActionDef(ExprDef * def,
1243 struct xkb_desc * xkb,
1244 struct xkb_any_action * action, unsigned mergeMode, ActionInfo * info)
1248 unsigned tmp, hndlrType;
1250 if (!actionsInitialized)
1253 if (def->op != ExprActionDecl)
1255 ERROR("Expected an action definition, found %s\n",
1256 exprOpText(def->op));
1259 str = XkbcAtomText(def->value.action.name);
1262 WSGO("Missing name in action definition!!\n");
1265 if (!stringToAction(str, &tmp))
1267 ERROR("Unknown action %s\n", str);
1270 action->type = hndlrType = tmp;
1271 if (action->type != XkbSA_NoAction)
1273 ApplyActionFactoryDefaults((union xkb_action *) action);
1276 if ((info->action == XkbSA_NoAction)
1277 || (info->action == hndlrType))
1279 if (!(*handleAction[hndlrType]) (xkb, action,
1290 for (arg = def->value.action.args; arg != NULL;
1291 arg = (ExprDef *) arg->common.next)
1293 ExprDef *field, *value, *arrayRtrn;
1294 ExprResult elemRtrn, fieldRtrn;
1297 if (arg->op == OpAssign)
1299 field = arg->value.binary.left;
1300 value = arg->value.binary.right;
1304 if ((arg->op == OpNot) || (arg->op == OpInvert))
1306 field = arg->value.child;
1307 value = &constFalse;
1315 if (!ExprResolveLhs(field, &elemRtrn, &fieldRtrn, &arrayRtrn))
1316 return False; /* internal error -- already reported */
1318 if (elemRtrn.str != NULL)
1320 ERROR("Cannot change defaults in an action definition\n");
1321 ACTION("Ignoring attempt to change %s.%s\n", elemRtrn.str,
1324 free(fieldRtrn.str);
1327 if (!stringToField(fieldRtrn.str, &fieldNdx))
1329 ERROR("Unknown field name %s\n", uStringText(fieldRtrn.str));
1331 free(fieldRtrn.str);
1335 free(fieldRtrn.str);
1336 if (!(*handleAction[hndlrType])
1337 (xkb, action, fieldNdx, arrayRtrn, value))
1345 /***====================================================================***/
1348 SetActionField(struct xkb_desc * xkb,
1351 ExprDef * array_ndx, ExprDef * value, ActionInfo ** info_rtrn)
1353 ActionInfo *new, *old;
1355 if (!actionsInitialized)
1358 new = uTypedAlloc(ActionInfo);
1361 WSGO("Couldn't allocate space for action default\n");
1364 if (uStrCaseCmp(elem, "action") == 0)
1365 new->action = XkbSA_NoAction;
1368 if (!stringToAction(elem, &new->action))
1373 if (new->action == XkbSA_NoAction)
1375 ERROR("\"%s\" is not a valid field in a NoAction action\n",
1381 if (!stringToField(field, &new->field))
1383 ERROR("\"%s\" is not a legal field name\n", field);
1387 new->array_ndx = array_ndx;
1391 while ((old) && (old->next))
1400 /***====================================================================***/
1405 if (!actionsInitialized)
1407 memset(&constTrue, 0, sizeof(constTrue));
1408 memset(&constFalse, 0, sizeof(constFalse));
1409 constTrue.common.stmtType = StmtExpr;
1410 constTrue.common.next = NULL;
1411 constTrue.op = ExprIdent;
1412 constTrue.type = TypeBoolean;
1413 constTrue.value.str = xkb_intern_atom("true");
1414 constFalse.common.stmtType = StmtExpr;
1415 constFalse.common.next = NULL;
1416 constFalse.op = ExprIdent;
1417 constFalse.type = TypeBoolean;
1418 constFalse.value.str = xkb_intern_atom("false");
1419 actionsInitialized = 1;