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 ********************************************************/
30 static bool actionsInitialized;
31 static ExprDef constTrue;
32 static ExprDef constFalse;
34 /***====================================================================***/
36 static const LookupEntry actionStrings[] = {
37 { "noaction", XkbSA_NoAction },
38 { "setmods", XkbSA_SetMods },
39 { "latchmods", XkbSA_LatchMods },
40 { "lockmods", XkbSA_LockMods },
41 { "setgroup", XkbSA_SetGroup },
42 { "latchgroup", XkbSA_LatchGroup },
43 { "lockgroup", XkbSA_LockGroup },
44 { "moveptr", XkbSA_MovePtr },
45 { "movepointer", XkbSA_MovePtr },
46 { "ptrbtn", XkbSA_PtrBtn },
47 { "pointerbutton", XkbSA_PtrBtn },
48 { "lockptrbtn", XkbSA_LockPtrBtn },
49 { "lockpointerbutton", XkbSA_LockPtrBtn },
50 { "lockptrbutton", XkbSA_LockPtrBtn },
51 { "lockpointerbtn", XkbSA_LockPtrBtn },
52 { "setptrdflt", XkbSA_SetPtrDflt },
53 { "setpointerdefault", XkbSA_SetPtrDflt },
54 { "isolock", XkbSA_ISOLock },
55 { "terminate", XkbSA_Terminate },
56 { "terminateserver", XkbSA_Terminate },
57 { "switchscreen", XkbSA_SwitchScreen },
58 { "setcontrols", XkbSA_SetControls },
59 { "lockcontrols", XkbSA_LockControls },
60 { "actionmessage", XkbSA_ActionMessage },
61 { "messageaction", XkbSA_ActionMessage },
62 { "message", XkbSA_ActionMessage },
63 { "redirect", XkbSA_RedirectKey },
64 { "redirectkey", XkbSA_RedirectKey },
65 { "devbtn", XkbSA_DeviceBtn },
66 { "devicebtn", XkbSA_DeviceBtn },
67 { "devbutton", XkbSA_DeviceBtn },
68 { "devicebutton", XkbSA_DeviceBtn },
69 { "lockdevbtn", XkbSA_DeviceBtn },
70 { "lockdevicebtn", XkbSA_LockDeviceBtn },
71 { "lockdevbutton", XkbSA_LockDeviceBtn },
72 { "lockdevicebutton", XkbSA_LockDeviceBtn },
73 { "devval", XkbSA_DeviceValuator },
74 { "deviceval", XkbSA_DeviceValuator },
75 { "devvaluator", XkbSA_DeviceValuator },
76 { "devicevaluator", XkbSA_DeviceValuator },
77 { "private", PrivateAction },
81 static const LookupEntry fieldStrings[] = {
82 { "clearLocks", F_ClearLocks },
83 { "latchToLock", F_LatchToLock },
84 { "genKeyEvent", F_GenKeyEvent },
85 { "generateKeyEvent", F_GenKeyEvent },
86 { "report", F_Report },
87 { "default", F_Default },
88 { "affect", F_Affect },
89 { "increment", F_Increment },
90 { "modifiers", F_Modifiers },
91 { "mods", F_Modifiers },
96 { "accelerate", F_Accel },
97 { "repeat", F_Accel },
98 { "button", F_Button },
100 { "controls", F_Controls },
101 { "ctrls", F_Controls },
103 { "count", F_Count },
104 { "screen", F_Screen },
106 { "sameServer", F_Same },
108 { "device", F_Device },
110 { "key", F_Keycode },
111 { "keycode", F_Keycode },
113 { "clearmods", F_ModsToClear },
114 { "clearmodifiers", F_ModsToClear },
119 stringToValue(const LookupEntry tab[], const char *string,
120 unsigned *value_rtrn)
122 const LookupEntry *entry;
127 for (entry = tab; entry->name != NULL; entry++) {
128 if (strcasecmp(entry->name, string) == 0) {
129 *value_rtrn = entry->result;
138 valueToString(const LookupEntry tab[], unsigned value)
140 const LookupEntry *entry;
142 for (entry = tab; entry->name != NULL; entry++)
143 if (entry->result == value)
150 stringToAction(const char *str, unsigned *type_rtrn)
152 return stringToValue(actionStrings, str, type_rtrn);
156 stringToField(const char *str, unsigned *field_rtrn)
158 return stringToValue(fieldStrings, str, field_rtrn);
162 fieldText(unsigned field)
164 return valueToString(fieldStrings, field);
167 /***====================================================================***/
170 ReportMismatch(unsigned action, unsigned field, const char *type)
172 ERROR("Value of %s field must be of type %s\n", fieldText(field), type);
173 ACTION("Action %s definition ignored\n", XkbcActionTypeText(action));
178 ReportIllegal(unsigned action, unsigned field)
180 ERROR("Field %s is not defined for an action of type %s\n",
181 fieldText(field), XkbcActionTypeText(action));
182 ACTION("Action definition ignored\n");
187 ReportActionNotArray(unsigned action, unsigned field)
189 ERROR("The %s field in the %s action is not an array\n",
190 fieldText(field), XkbcActionTypeText(action));
191 ACTION("Action definition ignored\n");
196 ReportNotFound(unsigned action, unsigned field, const char *what,
199 ERROR("%s named %s not found\n", what, bad);
200 ACTION("Ignoring the %s field of an %s action\n", fieldText(field),
201 XkbcActionTypeText(action));
206 HandleNoAction(struct xkb_keymap *keymap, struct xkb_any_action *action,
207 unsigned field, ExprDef *array_ndx, ExprDef *value)
209 return ReportIllegal(action->type, field);
213 CheckLatchLockFlags(struct xkb_keymap *keymap, unsigned action,
214 unsigned field, ExprDef * value, unsigned *flags_inout)
219 if (field == F_ClearLocks)
220 tmp = XkbSA_ClearLocks;
221 else if (field == F_LatchToLock)
222 tmp = XkbSA_LatchToLock;
224 return false; /* WSGO! */
225 if (!ExprResolveBoolean(keymap->ctx, value, &result))
226 return ReportMismatch(action, field, "boolean");
230 *flags_inout &= ~tmp;
235 CheckModifierField(struct xkb_keymap *keymap, unsigned action, ExprDef *value,
236 unsigned *flags_inout, unsigned *mods_rtrn)
240 if (value->op == ExprIdent) {
242 valStr = xkb_atom_text(keymap->ctx, value->value.str);
243 if (valStr && ((strcasecmp(valStr, "usemodmapmods") == 0) ||
244 (strcasecmp(valStr, "modmapmods") == 0))) {
247 *flags_inout |= XkbSA_UseModMapMods;
251 if (!ExprResolveVModMask(value, &rtrn, keymap))
252 return ReportMismatch(action, F_Modifiers, "modifier mask");
253 *mods_rtrn = rtrn.uval;
254 *flags_inout &= ~XkbSA_UseModMapMods;
259 HandleSetLatchMods(struct xkb_keymap *keymap, struct xkb_any_action *action,
260 unsigned field, ExprDef *array_ndx, ExprDef *value)
262 struct xkb_mod_action *act;
266 act = (struct xkb_mod_action *) action;
267 if (array_ndx != NULL) {
272 return ReportActionNotArray(action->type, field);
279 if (CheckLatchLockFlags(keymap, action->type, field, value, &rtrn)) {
287 if (CheckModifierField(keymap, action->type, value, &t1, &t2)) {
289 act->real_mods = act->mask = (t2 & 0xff);
290 act->vmods = (t2 >> 8) & 0xffff;
295 return ReportIllegal(action->type, field);
299 HandleLockMods(struct xkb_keymap *keymap, struct xkb_any_action *action,
300 unsigned field, ExprDef *array_ndx, ExprDef *value)
302 struct xkb_mod_action *act;
305 act = (struct xkb_mod_action *) action;
306 if ((array_ndx != NULL) && (field == F_Modifiers))
307 return ReportActionNotArray(action->type, field);
311 if (CheckModifierField(keymap, action->type, value, &t1, &t2)) {
313 act->real_mods = act->mask = (t2 & 0xff);
314 act->vmods = (t2 >> 8) & 0xffff;
319 return ReportIllegal(action->type, field);
323 CheckGroupField(struct xkb_keymap *keymap, unsigned action,
324 ExprDef * value, unsigned *flags_inout, int *grp_rtrn)
329 if ((value->op == OpNegate) || (value->op == OpUnaryPlus)) {
330 *flags_inout &= ~XkbSA_GroupAbsolute;
331 spec = value->value.child;
334 *flags_inout |= XkbSA_GroupAbsolute;
338 if (!ExprResolveGroup(keymap->ctx, spec, &rtrn))
339 return ReportMismatch(action, F_Group, "integer (range 1..8)");
340 if (value->op == OpNegate)
341 *grp_rtrn = -rtrn.ival;
342 else if (value->op == OpUnaryPlus)
343 *grp_rtrn = rtrn.ival;
345 *grp_rtrn = rtrn.ival - 1;
350 HandleSetLatchGroup(struct xkb_keymap *keymap, struct xkb_any_action *action,
351 unsigned field, ExprDef *array_ndx, ExprDef *value)
353 struct xkb_group_action *act;
358 act = (struct xkb_group_action *) action;
359 if (array_ndx != NULL) {
364 return ReportActionNotArray(action->type, field);
371 if (CheckLatchLockFlags(keymap, action->type, field, value, &rtrn)) {
379 if (CheckGroupField(keymap, action->type, value, &t1, &t2)) {
386 return ReportIllegal(action->type, field);
390 HandleLockGroup(struct xkb_keymap *keymap, struct xkb_any_action *action,
391 unsigned field, ExprDef *array_ndx, ExprDef *value)
393 struct xkb_group_action *act;
397 act = (struct xkb_group_action *) action;
398 if ((array_ndx != NULL) && (field == F_Group))
399 return ReportActionNotArray(action->type, field);
400 if (field == F_Group) {
402 if (CheckGroupField(keymap, action->type, value, &t1, &t2)) {
409 return ReportIllegal(action->type, field);
413 HandleMovePtr(struct xkb_keymap *keymap, struct xkb_any_action *action,
414 unsigned field, ExprDef *array_ndx, ExprDef *value)
417 struct xkb_pointer_action *act;
420 act = (struct xkb_pointer_action *) action;
421 if ((array_ndx != NULL) && ((field == F_X) || (field == F_Y)))
422 return ReportActionNotArray(action->type, field);
424 if ((field == F_X) || (field == F_Y)) {
425 if ((value->op == OpNegate) || (value->op == OpUnaryPlus))
429 if (!ExprResolveInteger(keymap->ctx, value, &rtrn))
430 return ReportMismatch(action->type, field, "integer");
433 act->flags |= XkbSA_MoveAbsoluteX;
438 act->flags |= XkbSA_MoveAbsoluteY;
443 else if (field == F_Accel) {
444 if (!ExprResolveBoolean(keymap->ctx, value, &rtrn))
445 return ReportMismatch(action->type, field, "boolean");
447 act->flags &= ~XkbSA_NoAcceleration;
449 act->flags |= XkbSA_NoAcceleration;
451 return ReportIllegal(action->type, field);
454 static const LookupEntry lockWhich[] = {
456 { "lock", XkbSA_LockNoUnlock },
457 { "neither", (XkbSA_LockNoLock | XkbSA_LockNoUnlock) },
458 { "unlock", XkbSA_LockNoLock },
463 HandlePtrBtn(struct xkb_keymap *keymap, struct xkb_any_action *action,
464 unsigned field, ExprDef *array_ndx, ExprDef *value)
467 struct xkb_pointer_button_action *act;
469 act = (struct xkb_pointer_button_action *) action;
470 if (field == F_Button) {
471 if (array_ndx != NULL)
472 return ReportActionNotArray(action->type, field);
473 if (!ExprResolveButton(keymap->ctx, value, &rtrn))
474 return ReportMismatch(action->type, field,
475 "integer (range 1..5)");
476 if ((rtrn.ival < 0) || (rtrn.ival > 5)) {
477 ERROR("Button must specify default or be in the range 1..5\n");
478 ACTION("Illegal button value %d ignored\n", rtrn.ival);
481 act->button = rtrn.ival;
484 else if ((action->type == XkbSA_LockPtrBtn) && (field == F_Affect)) {
485 if (array_ndx != NULL)
486 return ReportActionNotArray(action->type, field);
487 if (!ExprResolveEnum(keymap->ctx, value, &rtrn, lockWhich))
488 return ReportMismatch(action->type, field, "lock or unlock");
489 act->flags &= ~(XkbSA_LockNoLock | XkbSA_LockNoUnlock);
490 act->flags |= rtrn.ival;
493 else if (field == F_Count) {
494 if (array_ndx != NULL)
495 return ReportActionNotArray(action->type, field);
496 if (!ExprResolveButton(keymap->ctx, value, &rtrn))
497 return ReportMismatch(action->type, field, "integer");
498 if ((rtrn.ival < 0) || (rtrn.ival > 255)) {
499 ERROR("The count field must have a value in the range 0..255\n");
500 ACTION("Illegal count %d ignored\n", rtrn.ival);
503 act->count = rtrn.ival;
506 return ReportIllegal(action->type, field);
509 static const LookupEntry ptrDflts[] = {
510 { "dfltbtn", XkbSA_AffectDfltBtn },
511 { "defaultbutton", XkbSA_AffectDfltBtn },
512 { "button", XkbSA_AffectDfltBtn },
517 HandleSetPtrDflt(struct xkb_keymap *keymap, struct xkb_any_action *action,
518 unsigned field, ExprDef *array_ndx, ExprDef *value)
521 struct xkb_pointer_default_action *act;
523 act = (struct xkb_pointer_default_action *) action;
524 if (field == F_Affect) {
525 if (array_ndx != NULL)
526 return ReportActionNotArray(action->type, field);
527 if (!ExprResolveEnum(keymap->ctx, value, &rtrn, ptrDflts))
528 return ReportMismatch(action->type, field, "pointer component");
529 act->affect = rtrn.uval;
532 else if ((field == F_Button) || (field == F_Value)) {
534 if (array_ndx != NULL)
535 return ReportActionNotArray(action->type, field);
536 if ((value->op == OpNegate) || (value->op == OpUnaryPlus)) {
537 act->flags &= ~XkbSA_DfltBtnAbsolute;
538 btn = value->value.child;
541 act->flags |= XkbSA_DfltBtnAbsolute;
545 if (!ExprResolveButton(keymap->ctx, btn, &rtrn))
546 return ReportMismatch(action->type, field,
547 "integer (range 1..5)");
548 if ((rtrn.ival < 0) || (rtrn.ival > 5)) {
549 ERROR("New default button value must be in the range 1..5\n");
550 ACTION("Illegal default button value %d ignored\n", rtrn.ival);
553 if (rtrn.ival == 0) {
554 ERROR("Cannot set default pointer button to \"default\"\n");
555 ACTION("Illegal default button setting ignored\n");
558 if (value->op == OpNegate)
559 act->value = -rtrn.ival;
561 act->value = rtrn.ival;
564 return ReportIllegal(action->type, field);
567 static const LookupEntry isoNames[] = {
568 { "mods", XkbSA_ISONoAffectMods },
569 { "modifiers", XkbSA_ISONoAffectMods },
570 { "group", XkbSA_ISONoAffectGroup },
571 { "groups", XkbSA_ISONoAffectGroup },
572 { "ptr", XkbSA_ISONoAffectPtr },
573 { "pointer", XkbSA_ISONoAffectPtr },
574 { "ctrls", XkbSA_ISONoAffectCtrls },
575 { "controls", XkbSA_ISONoAffectCtrls },
576 { "all", ~((unsigned) 0) },
582 HandleISOLock(struct xkb_keymap *keymap, struct xkb_any_action *action,
583 unsigned field, ExprDef *array_ndx, ExprDef *value)
586 struct xkb_iso_action *act;
587 unsigned flags, mods;
590 act = (struct xkb_iso_action *) action;
593 if (array_ndx != NULL)
594 return ReportActionNotArray(action->type, field);
596 if (CheckModifierField(keymap, action->type, value, &flags, &mods)) {
597 act->flags = flags & (~XkbSA_ISODfltIsGroup);
598 act->real_mods = mods & 0xff;
599 act->vmods = (mods >> 8) & 0xff;
605 if (array_ndx != NULL)
606 return ReportActionNotArray(action->type, field);
608 if (CheckGroupField(keymap, action->type, value, &flags, &group)) {
609 act->flags = flags | XkbSA_ISODfltIsGroup;
616 if (array_ndx != NULL)
617 return ReportActionNotArray(action->type, field);
618 if (!ExprResolveMask(keymap->ctx, value, &rtrn, isoNames))
619 return ReportMismatch(action->type, field, "keyboard component");
620 act->affect = (~rtrn.uval) & XkbSA_ISOAffectMask;
623 return ReportIllegal(action->type, field);
627 HandleSwitchScreen(struct xkb_keymap *keymap, struct xkb_any_action *action,
628 unsigned field, ExprDef *array_ndx, ExprDef *value)
631 struct xkb_switch_screen_action *act;
633 act = (struct xkb_switch_screen_action *) action;
634 if (field == F_Screen) {
636 if (array_ndx != NULL)
637 return ReportActionNotArray(action->type, field);
638 if ((value->op == OpNegate) || (value->op == OpUnaryPlus)) {
639 act->flags &= ~XkbSA_SwitchAbsolute;
640 scrn = value->value.child;
643 act->flags |= XkbSA_SwitchAbsolute;
647 if (!ExprResolveInteger(keymap->ctx, scrn, &rtrn))
648 return ReportMismatch(action->type, field, "integer (0..255)");
649 if ((rtrn.ival < 0) || (rtrn.ival > 255)) {
650 ERROR("Screen index must be in the range 1..255\n");
651 ACTION("Illegal screen value %d ignored\n", rtrn.ival);
654 if (value->op == OpNegate)
655 act->screen = -rtrn.ival;
657 act->screen = rtrn.ival;
660 else if (field == F_Same) {
661 if (array_ndx != NULL)
662 return ReportActionNotArray(action->type, field);
663 if (!ExprResolveBoolean(keymap->ctx, value, &rtrn))
664 return ReportMismatch(action->type, field, "boolean");
666 act->flags &= ~XkbSA_SwitchApplication;
668 act->flags |= XkbSA_SwitchApplication;
671 return ReportIllegal(action->type, field);
674 const LookupEntry ctrlNames[] = {
675 { "repeatkeys", XkbRepeatKeysMask },
676 { "repeat", XkbRepeatKeysMask },
677 { "autorepeat", XkbRepeatKeysMask },
678 { "slowkeys", XkbSlowKeysMask },
679 { "bouncekeys", XkbBounceKeysMask },
680 { "stickykeys", XkbStickyKeysMask },
681 { "mousekeys", XkbMouseKeysMask },
682 { "mousekeysaccel", XkbMouseKeysAccelMask },
683 { "accessxkeys", XkbAccessXKeysMask },
684 { "accessxtimeout", XkbAccessXTimeoutMask },
685 { "accessxfeedback", XkbAccessXFeedbackMask },
686 { "audiblebell", XkbAudibleBellMask },
687 { "ignoregrouplock", XkbIgnoreGroupLockMask },
688 { "all", XkbAllBooleanCtrlsMask },
696 HandleSetLockControls(struct xkb_keymap *keymap,
697 struct xkb_any_action *action,
698 unsigned field, ExprDef *array_ndx,
702 struct xkb_controls_action *act;
704 act = (struct xkb_controls_action *) action;
705 if (field == F_Controls) {
706 if (array_ndx != NULL)
707 return ReportActionNotArray(action->type, field);
708 if (!ExprResolveMask(keymap->ctx, value, &rtrn, ctrlNames))
709 return ReportMismatch(action->type, field, "controls mask");
710 act->ctrls = rtrn.uval;
713 return ReportIllegal(action->type, field);
716 static const LookupEntry evNames[] = {
717 { "press", XkbSA_MessageOnPress },
718 { "keypress", XkbSA_MessageOnPress },
719 { "release", XkbSA_MessageOnRelease },
720 { "keyrelease", XkbSA_MessageOnRelease },
721 { "all", XkbSA_MessageOnPress | XkbSA_MessageOnRelease },
727 HandleActionMessage(struct xkb_keymap *keymap, struct xkb_any_action *action,
728 unsigned field, ExprDef *array_ndx, ExprDef *value)
731 struct xkb_message_action *act;
733 act = (struct xkb_message_action *) action;
736 if (array_ndx != NULL)
737 return ReportActionNotArray(action->type, field);
738 if (!ExprResolveMask(keymap->ctx, value, &rtrn, evNames))
739 return ReportMismatch(action->type, field, "key event mask");
740 act->flags &= ~(XkbSA_MessageOnPress | XkbSA_MessageOnRelease);
742 rtrn.uval & (XkbSA_MessageOnPress | XkbSA_MessageOnRelease);
746 if (array_ndx != NULL)
747 return ReportActionNotArray(action->type, field);
748 if (!ExprResolveBoolean(keymap->ctx, value, &rtrn))
749 return ReportMismatch(action->type, field, "boolean");
751 act->flags |= XkbSA_MessageGenKeyEvent;
753 act->flags &= ~XkbSA_MessageGenKeyEvent;
757 if (array_ndx == NULL) {
758 if (!ExprResolveString(keymap->ctx, value, &rtrn))
759 return ReportMismatch(action->type, field, "string");
761 int len = strlen(rtrn.str);
762 if ((len < 1) || (len > 6)) {
763 WARN("An action message can hold only 6 bytes\n");
764 ACTION("Extra %d bytes ignored\n", len - 6);
766 strncpy((char *) act->message, rtrn.str, 6);
772 if (!ExprResolveInteger(keymap->ctx, array_ndx, &rtrn)) {
773 ERROR("Array subscript must be integer\n");
774 ACTION("Illegal subscript ignored\n");
779 ERROR("An action message is at most 6 bytes long\n");
780 ACTION("Attempt to use data[%d] ignored\n", ndx);
783 if (!ExprResolveInteger(keymap->ctx, value, &rtrn))
784 return ReportMismatch(action->type, field, "integer");
785 if ((rtrn.ival < 0) || (rtrn.ival > 255)) {
786 ERROR("Message data must be in the range 0..255\n");
787 ACTION("Illegal datum %d ignored\n", rtrn.ival);
790 act->message[ndx] = rtrn.uval;
794 return ReportIllegal(action->type, field);
798 HandleRedirectKey(struct xkb_keymap *keymap, struct xkb_any_action *action,
799 unsigned field, ExprDef *array_ndx, ExprDef *value)
803 struct xkb_redirect_key_action *act;
807 if (array_ndx != NULL)
808 return ReportActionNotArray(action->type, field);
810 act = (struct xkb_redirect_key_action *) action;
813 if (!ExprResolveKeyName(keymap->ctx, value, &rtrn))
814 return ReportMismatch(action->type, field, "key name");
816 tmp = KeyNameToLong(rtrn.name);
817 key = FindNamedKey(keymap, tmp, true, CreateKeyNames(keymap), 0);
819 return ReportNotFound(action->type, field, "Key",
820 XkbcKeyNameText(rtrn.name));
821 act->new_kc = XkbKeyGetKeycode(keymap, key);
827 if (CheckModifierField(keymap, action->type, value, &t1, &t2)) {
828 act->mods_mask |= (t2 & 0xff);
829 if (field == F_Modifiers)
830 act->mods |= (t2 & 0xff);
832 act->mods &= ~(t2 & 0xff);
834 t2 = (t2 >> 8) & 0xffff;
835 act->vmods_mask |= t2;
836 if (field == F_Modifiers)
844 return ReportIllegal(action->type, field);
848 HandleDeviceBtn(struct xkb_keymap *keymap, struct xkb_any_action *action,
849 unsigned field, ExprDef *array_ndx, ExprDef *value)
852 struct xkb_device_button_action *act;
854 act = (struct xkb_device_button_action *) action;
855 if (field == F_Button) {
856 if (array_ndx != NULL)
857 return ReportActionNotArray(action->type, field);
858 if (!ExprResolveInteger(keymap->ctx, value, &rtrn))
859 return ReportMismatch(action->type, field,
860 "integer (range 1..255)");
861 if ((rtrn.ival < 0) || (rtrn.ival > 255)) {
862 ERROR("Button must specify default or be in the range 1..255\n");
863 ACTION("Illegal button value %d ignored\n", rtrn.ival);
866 act->button = rtrn.ival;
869 else if ((action->type == XkbSA_LockDeviceBtn) && (field == F_Affect)) {
870 if (array_ndx != NULL)
871 return ReportActionNotArray(action->type, field);
872 if (!ExprResolveEnum(keymap->ctx, value, &rtrn, lockWhich))
873 return ReportMismatch(action->type, field, "lock or unlock");
874 act->flags &= ~(XkbSA_LockNoLock | XkbSA_LockNoUnlock);
875 act->flags |= rtrn.ival;
878 else if (field == F_Count) {
879 if (array_ndx != NULL)
880 return ReportActionNotArray(action->type, field);
881 if (!ExprResolveButton(keymap->ctx, value, &rtrn))
882 return ReportMismatch(action->type, field, "integer");
883 if ((rtrn.ival < 0) || (rtrn.ival > 255)) {
884 ERROR("The count field must have a value in the range 0..255\n");
885 ACTION("Illegal count %d ignored\n", rtrn.ival);
888 act->count = rtrn.ival;
891 else if (field == F_Device) {
892 if (array_ndx != NULL)
893 return ReportActionNotArray(action->type, field);
894 if (!ExprResolveInteger(keymap->ctx, value, &rtrn))
895 return ReportMismatch(action->type, field,
896 "integer (range 1..255)");
897 if ((rtrn.ival < 0) || (rtrn.ival > 255)) {
898 ERROR("Device must specify default or be in the range 1..255\n");
899 ACTION("Illegal device value %d ignored\n", rtrn.ival);
902 act->device = rtrn.ival;
905 return ReportIllegal(action->type, field);
909 HandleDeviceValuator(struct xkb_keymap *keymap, struct xkb_any_action *action,
910 unsigned field, ExprDef *array_ndx, ExprDef *value)
914 struct xkb_device_valuator_action *act;
916 act = (struct xkb_device_valuator_action *) action;
917 /* XXX - Not yet implemented */
923 HandlePrivate(struct xkb_keymap *keymap, struct xkb_any_action *action,
924 unsigned field, ExprDef *array_ndx, ExprDef *value)
930 if (!ExprResolveInteger(keymap->ctx, value, &rtrn))
931 return ReportMismatch(PrivateAction, field, "integer");
932 if ((rtrn.ival < 0) || (rtrn.ival > 255)) {
933 ERROR("Private action type must be in the range 0..255\n");
934 ACTION("Illegal type %d ignored\n", rtrn.ival);
937 action->type = rtrn.uval;
941 if (array_ndx == NULL) {
942 if (!ExprResolveString(keymap->ctx, value, &rtrn))
943 return ReportMismatch(action->type, field, "string");
945 int len = strlen(rtrn.str);
946 if ((len < 1) || (len > 7)) {
947 WARN("A private action has 7 data bytes\n");
948 ACTION("Extra %d bytes ignored\n", len - 6);
951 strncpy((char *) action->data, rtrn.str, sizeof action->data);
958 if (!ExprResolveInteger(keymap->ctx, array_ndx, &rtrn)) {
959 ERROR("Array subscript must be integer\n");
960 ACTION("Illegal subscript ignored\n");
964 if (ndx >= sizeof action->data) {
965 ERROR("The data for a private action is 18 bytes long\n");
966 ACTION("Attempt to use data[%d] ignored\n", ndx);
969 if (!ExprResolveInteger(keymap->ctx, value, &rtrn))
970 return ReportMismatch(action->type, field, "integer");
971 if ((rtrn.ival < 0) || (rtrn.ival > 255)) {
972 ERROR("All data for a private action must be 0..255\n");
973 ACTION("Illegal datum %d ignored\n", rtrn.ival);
976 action->data[ndx] = rtrn.uval;
980 return ReportIllegal(PrivateAction, field);
983 typedef bool (*actionHandler)(struct xkb_keymap *keymap,
984 struct xkb_any_action *action, unsigned field,
985 ExprDef *array_ndx, ExprDef *value);
987 static const actionHandler handleAction[XkbSA_NumActions + 1] = {
988 [XkbSA_NoAction] = HandleNoAction,
989 [XkbSA_SetMods] = HandleSetLatchMods,
990 [XkbSA_LatchMods] = HandleSetLatchMods,
991 [XkbSA_LockMods] = HandleLockMods,
992 [XkbSA_SetGroup] = HandleSetLatchGroup,
993 [XkbSA_LatchGroup] = HandleSetLatchGroup,
994 [XkbSA_LockGroup] = HandleLockGroup,
995 [XkbSA_MovePtr] = HandleMovePtr,
996 [XkbSA_PtrBtn] = HandlePtrBtn,
997 [XkbSA_LockPtrBtn] = HandlePtrBtn,
998 [XkbSA_SetPtrDflt] = HandleSetPtrDflt,
999 [XkbSA_ISOLock] = HandleISOLock,
1000 [XkbSA_Terminate] = HandleNoAction,
1001 [XkbSA_SwitchScreen] = HandleSwitchScreen,
1002 [XkbSA_SetControls] = HandleSetLockControls,
1003 [XkbSA_LockControls] = HandleSetLockControls,
1004 [XkbSA_ActionMessage] = HandleActionMessage,
1005 [XkbSA_RedirectKey] = HandleRedirectKey,
1006 [XkbSA_DeviceBtn] = HandleDeviceBtn,
1007 [XkbSA_LockDeviceBtn] = HandleDeviceBtn,
1008 [XkbSA_DeviceValuator] = HandleDeviceValuator,
1009 [PrivateAction] = HandlePrivate,
1012 /***====================================================================***/
1015 ApplyActionFactoryDefaults(union xkb_action * action)
1017 if (action->type == XkbSA_SetPtrDflt) { /* increment default button */
1018 action->dflt.affect = XkbSA_AffectDfltBtn;
1019 action->dflt.flags = 0;
1020 action->dflt.value = 1;
1022 else if (action->type == XkbSA_ISOLock) {
1023 action->iso.real_mods = LockMask;
1028 ActionsInit(struct xkb_context *ctx);
1031 HandleActionDef(ExprDef * def,
1032 struct xkb_keymap *keymap,
1033 struct xkb_any_action *action, ActionInfo *info)
1037 unsigned tmp, hndlrType;
1039 if (!actionsInitialized)
1040 ActionsInit(keymap->ctx);
1042 if (def->op != ExprActionDecl) {
1043 ERROR("Expected an action definition, found %s\n",
1044 exprOpText(def->op));
1047 str = xkb_atom_text(keymap->ctx, def->value.action.name);
1049 WSGO("Missing name in action definition!!\n");
1052 if (!stringToAction(str, &tmp)) {
1053 ERROR("Unknown action %s\n", str);
1056 action->type = hndlrType = tmp;
1057 if (action->type != XkbSA_NoAction) {
1058 ApplyActionFactoryDefaults((union xkb_action *) action);
1061 if ((info->action == XkbSA_NoAction)
1062 || (info->action == hndlrType)) {
1063 if (!(*handleAction[hndlrType])(keymap, action,
1073 for (arg = def->value.action.args; arg != NULL;
1074 arg = (ExprDef *) arg->common.next) {
1075 ExprDef *field, *value, *arrayRtrn;
1076 ExprResult elemRtrn, fieldRtrn;
1079 if (arg->op == OpAssign) {
1080 field = arg->value.binary.left;
1081 value = arg->value.binary.right;
1084 if ((arg->op == OpNot) || (arg->op == OpInvert)) {
1085 field = arg->value.child;
1086 constFalse.value.str = xkb_atom_intern(keymap->ctx, "false");
1087 value = &constFalse;
1091 constTrue.value.str = xkb_atom_intern(keymap->ctx, "true");
1095 if (!ExprResolveLhs(keymap, field, &elemRtrn, &fieldRtrn, &arrayRtrn))
1096 return false; /* internal error -- already reported */
1098 if (elemRtrn.str != NULL) {
1099 ERROR("Cannot change defaults in an action definition\n");
1100 ACTION("Ignoring attempt to change %s.%s\n", elemRtrn.str,
1103 free(fieldRtrn.str);
1106 if (!stringToField(fieldRtrn.str, &fieldNdx)) {
1107 ERROR("Unknown field name %s\n", uStringText(fieldRtrn.str));
1109 free(fieldRtrn.str);
1113 free(fieldRtrn.str);
1114 if (!(*handleAction[hndlrType])(keymap, action, fieldNdx, arrayRtrn,
1121 /***====================================================================***/
1124 SetActionField(struct xkb_keymap *keymap,
1127 ExprDef * array_ndx, ExprDef * value, ActionInfo ** info_rtrn)
1129 ActionInfo *new, *old;
1131 if (!actionsInitialized)
1132 ActionsInit(keymap->ctx);
1134 new = uTypedAlloc(ActionInfo);
1136 WSGO("Couldn't allocate space for action default\n");
1139 if (strcasecmp(elem, "action") == 0)
1140 new->action = XkbSA_NoAction;
1142 if (!stringToAction(elem, &new->action)) {
1146 if (new->action == XkbSA_NoAction) {
1147 ERROR("\"%s\" is not a valid field in a NoAction action\n",
1153 if (!stringToField(field, &new->field)) {
1154 ERROR("\"%s\" is not a legal field name\n", field);
1158 new->array_ndx = array_ndx;
1162 while ((old) && (old->next))
1171 /***====================================================================***/
1174 ActionsInit(struct xkb_context *ctx)
1176 if (!actionsInitialized) {
1177 memset(&constTrue, 0, sizeof(constTrue));
1178 memset(&constFalse, 0, sizeof(constFalse));
1179 constTrue.common.stmtType = StmtExpr;
1180 constTrue.common.next = NULL;
1181 constTrue.op = ExprIdent;
1182 constTrue.type = TypeBoolean;
1183 constTrue.value.str = xkb_atom_intern(ctx, "true");
1184 constFalse.common.stmtType = StmtExpr;
1185 constFalse.common.next = NULL;
1186 constFalse.op = ExprIdent;
1187 constFalse.type = TypeBoolean;
1188 constFalse.value.str = xkb_atom_intern(ctx, "false");
1189 actionsInitialized = 1;