1 /*************************************<+>*************************************
2 *****************************************************************************
8 ** Description: Menu Manager Support Routines
10 ** This file contains a series of support routines, used by
11 ** the menu manager meta-class and any of its subclasses,
12 ** to convert an event string into an internal format. The
13 ** internal format may then be used to compare against real
14 ** X events. These routines are capable of handling a subset
15 ** of the string formats supported by the translation manager.
17 *****************************************************************************
19 ** Copyright (c) 1988 by Hewlett-Packard Company
20 ** Copyright (c) 1987, 1988 by Digital Equipment Corporation, Maynard,
21 ** Massachusetts, and the Massachusetts Institute of Technology,
22 ** Cambridge, Massachusetts
24 ** Permission to use, copy, modify, and distribute this software
25 ** and its documentation for any purpose and without fee is hereby
26 ** granted, provided that the above copyright notice appear in all
27 ** copies and that both that copyright notice and this permission
28 ** notice appear in supporting documentation, and that the names of
29 ** Hewlett-Packard, Digital or M.I.T. not be used in advertising or
30 ** publicity pertaining to distribution of the software without
31 ** written prior permission.
33 ** DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
34 ** ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
35 ** DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
36 ** ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
37 ** WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
38 ** ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
41 *****************************************************************************
42 *************************************<+>*************************************/
47 #include <X11/IntrinsicP.h>
48 #include <X11/Xutil.h>
49 #include <X11/StringDefs.h>
50 #include <X11/Xatom.h>
53 static Boolean
ParseImmed();
54 static Boolean
ParseKeySym();
61 unsigned int eventType
;
62 Boolean (*parseProc
)();
66 static EventKey modifierStrings
[] = {
68 /* Modifier, Quark, Mask */
70 {"None", NULLQUARK
, 0, NULL
, None
},
71 {"Shift", NULLQUARK
, 0, NULL
, ShiftMask
},
72 {"Lock", NULLQUARK
, 0, NULL
, LockMask
},
73 {"Ctrl", NULLQUARK
, 0, NULL
, ControlMask
},
74 {"Mod1", NULLQUARK
, 0, NULL
, Mod1Mask
},
75 {"Mod2", NULLQUARK
, 0, NULL
, Mod2Mask
},
76 {"Mod3", NULLQUARK
, 0, NULL
, Mod3Mask
},
77 {"Mod4", NULLQUARK
, 0, NULL
, Mod4Mask
},
78 {"Mod5", NULLQUARK
, 0, NULL
, Mod5Mask
},
79 {"Meta", NULLQUARK
, 0, NULL
, Mod1Mask
},
80 {NULL
, NULLQUARK
, 0, NULL
, None
},
84 static EventKey buttonEvents
[] = {
86 /* Event Name, Quark, Event Type, DetailProc Closure */
88 {"Btn1Down", NULLQUARK
, ButtonPress
, ParseImmed
, Button1
},
89 {"Btn2Down", NULLQUARK
, ButtonPress
, ParseImmed
, Button2
},
90 {"Btn3Down", NULLQUARK
, ButtonPress
, ParseImmed
, Button3
},
91 {"Btn4Down", NULLQUARK
, ButtonPress
, ParseImmed
, Button4
},
92 {"Btn5Down", NULLQUARK
, ButtonPress
, ParseImmed
, Button5
},
93 {"Btn1Up", NULLQUARK
, ButtonRelease
, ParseImmed
, Button1
},
94 {"Btn2Up", NULLQUARK
, ButtonRelease
, ParseImmed
, Button2
},
95 {"Btn3Up", NULLQUARK
, ButtonRelease
, ParseImmed
, Button3
},
96 {"Btn4Up", NULLQUARK
, ButtonRelease
, ParseImmed
, Button4
},
97 {"Btn5Up", NULLQUARK
, ButtonRelease
, ParseImmed
, Button5
},
98 { NULL
, NULLQUARK
, 0, NULL
, None
}};
101 static EventKey keyEvents
[] = {
103 /* Event Name, Quark, Event Type, DetailProc Closure */
105 {"KeyPress", NULLQUARK
, KeyPress
, ParseKeySym
, None
},
106 {"Key", NULLQUARK
, KeyPress
, ParseKeySym
, None
},
107 {"KeyDown", NULLQUARK
, KeyPress
, ParseKeySym
, None
},
108 {"KeyUp", NULLQUARK
, KeyRelease
, ParseKeySym
, None
},
109 {"KeyRelease", NULLQUARK
, KeyRelease
, ParseKeySym
, None
},
110 { NULL
, NULLQUARK
, 0, NULL
, None
}};
113 static unsigned int buttonModifierMasks
[] = {
114 0, Button1Mask
, Button2Mask
, Button3Mask
, Button4Mask
, Button5Mask
117 static initialized
= FALSE
;
121 /*************************************<->*************************************
123 * Numeric convertion routines
127 * xxxxxxxxxxxxxxxxxxxxxxx
132 * xxxxxxxxxxxx = xxxxxxxxxxxxx
136 * xxxxxxxxxxxx = xxxxxxxxxxxxx
141 *************************************<->***********************************/
143 static unsigned int StrToHex(str
)
147 register int val
= 0;
150 if ('0' <= c
&& c
<= '9') val
= val
*16+c
-'0';
151 else if ('a' <= c
&& c
<= 'z') val
= val
*16+c
-'a'+10;
152 else if ('A' <= c
&& c
<= 'Z') val
= val
*16+c
-'A'+10;
160 static unsigned int StrToOct(str
)
164 register int val
= 0;
167 if ('0' <= c
&& c
<= '7') val
= val
*8+c
-'0'; else return -1;
174 static unsigned int StrToNum(str
)
178 register int val
= 0;
182 if (*str
== 'x' || *str
== 'X') return StrToHex(++str
);
183 else return StrToOct(str
);
187 if ('0' <= c
&& c
<= '9') val
= val
*10+c
-'0';
196 /*************************************<->*************************************
198 * FillInQuarks (parameters)
202 * Converts each string entry in the modifier/event tables to a
203 * quark, thus facilitating faster comparisons.
208 * xxxxxxxxxxxx = xxxxxxxxxxxxx
212 * xxxxxxxxxxxx = xxxxxxxxxxxxx
217 *************************************<->***********************************/
219 static void FillInQuarks (table
)
226 for (i
=0; table
[i
].event
; i
++)
227 table
[i
].signature
= XrmStringToQuark(table
[i
].event
);
231 /*************************************<->*************************************
233 * LookupModifier (parameters)
237 * Compare the passed in string to the list of valid modifiers.
242 * xxxxxxxxxxxx = xxxxxxxxxxxxx
246 * xxxxxxxxxxxx = xxxxxxxxxxxxx
251 *************************************<->***********************************/
253 static Boolean
LookupModifier (name
, valueP
)
256 unsigned int *valueP
;
260 register XrmQuark signature
= XrmStringToQuark(name
);
262 for (i
=0; modifierStrings
[i
].event
!= NULL
; i
++)
263 if (modifierStrings
[i
].signature
== signature
) {
264 *valueP
= modifierStrings
[i
].closure
;
272 /*************************************<->*************************************
274 * ScanAlphanumeric (parameters)
278 * Scan string until a non-alphanumeric character is encountered.
283 * xxxxxxxxxxxx = xxxxxxxxxxxxx
287 * xxxxxxxxxxxx = xxxxxxxxxxxxx
292 *************************************<->***********************************/
294 static String
ScanAlphanumeric (str
)
300 ('A' <= *str
&& *str
<= 'Z') || ('a' <= *str
&& *str
<= 'z')
301 || ('0' <= *str
&& *str
<= '9')) str
++;
306 /*************************************<->*************************************
308 * ScanWhitespace (parameters)
312 * Scan the string, skipping over all white space characters.
317 * xxxxxxxxxxxx = xxxxxxxxxxxxx
321 * xxxxxxxxxxxx = xxxxxxxxxxxxx
326 *************************************<->***********************************/
328 static String
ScanWhitespace(str
)
331 while (*str
== ' ' || *str
== '\t') str
++;
336 /*************************************<->*************************************
338 * ParseImmed (parameters)
342 * xxxxxxxxxxxxxxxxxxxxxxx
347 * xxxxxxxxxxxx = xxxxxxxxxxxxx
351 * xxxxxxxxxxxx = xxxxxxxxxxxxx
356 *************************************<->***********************************/
358 static Boolean
ParseImmed (str
, closure
, detail
)
361 unsigned int closure
;
362 unsigned int * detail
;
370 /*************************************<->*************************************
372 * ParseKeySym (parameters)
376 * xxxxxxxxxxxxxxxxxxxxxxx
381 * xxxxxxxxxxxx = xxxxxxxxxxxxx
385 * xxxxxxxxxxxx = xxxxxxxxxxxxx
390 *************************************<->***********************************/
392 static Boolean
ParseKeySym (str
, closure
, detail
)
395 unsigned int closure
;
396 unsigned int * detail
;
399 char keySymName
[100], *start
;
401 str
= ScanWhitespace(str
);
405 keySymName
[0] = *str
;
406 if (*str
!= '\0' && *str
!= '\n') str
++;
407 keySymName
[1] = '\0';
408 *detail
= XStringToKeysym(keySymName
);
409 } else if (*str
== ',' || *str
== ':') {
410 /* No detail; return a failure */
421 && *str
!= '\0') str
++;
422 (void) strncpy(keySymName
, start
, str
-start
);
423 keySymName
[str
-start
] = '\0';
424 *detail
= XStringToKeysym(keySymName
);
427 if (*detail
== NoSymbol
)
429 if (( '0' <= keySymName
[0]) && (keySymName
[0] <= '9'))
431 *detail
= StrToNum(keySymName
);
441 /*************************************<->*************************************
443 * ParseModifiers (parameters)
447 * Parse the string, extracting all modifier specifications.
452 * xxxxxxxxxxxx = xxxxxxxxxxxxx
456 * xxxxxxxxxxxx = xxxxxxxxxxxxx
461 *************************************<->***********************************/
463 static String
ParseModifiers(str
, modifiers
, status
)
466 unsigned int * modifiers
;
470 register String start
;
472 Boolean notFlag
, exclusive
;
473 unsigned int maskBit
;
475 /* Initially assume all is going to go well */
479 /* Attempt to parse the first button modifier */
480 str
= ScanWhitespace(str
);
482 str
= ScanAlphanumeric(str
);
484 (void) strncpy(modStr
, start
, str
-start
);
485 modStr
[str
-start
] = '\0';
486 if (LookupModifier(modStr
, &maskBit
))
488 if (maskBit
== None
) {
490 str
= ScanWhitespace(str
);
498 /* Keep parsing modifiers, until the event specifier is encountered */
499 while ((*str
!= '<') && (*str
!= '\0')) {
507 str
= ScanAlphanumeric(str
);
509 /* ERROR: Modifier or '<' missing */
513 (void) strncpy(modStr
, start
, str
-start
);
514 modStr
[str
-start
] = '\0';
516 if (!LookupModifier(modStr
, &maskBit
))
518 /* Unknown modifier name */
524 *modifiers
&= ~maskBit
;
526 *modifiers
|= maskBit
;
527 str
= ScanWhitespace(str
);
534 /*************************************<->*************************************
536 * ParseEventType (parameters)
540 * xxxxxxxxxxxxxxxxxxxxxxx
545 * xxxxxxxxxxxx = xxxxxxxxxxxxx
549 * xxxxxxxxxxxx = xxxxxxxxxxxxx
554 *************************************<->***********************************/
556 static String
ParseEventType(str
, table
, eventType
, index
, status
)
560 unsigned int * eventType
;
566 char eventTypeStr
[100];
568 register XrmQuark signature
;
570 /* Parse out the event string */
571 str
= ScanAlphanumeric(str
);
572 (void) strncpy(eventTypeStr
, start
, str
-start
);
573 eventTypeStr
[str
-start
] = '\0';
575 /* Attempt to match the parsed event against our supported event set */
576 signature
= XrmStringToQuark(eventTypeStr
);
577 for (i
= 0; table
[i
].signature
!= NULLQUARK
; i
++)
578 if (table
[i
].signature
== signature
)
581 *eventType
= table
[*index
].eventType
;
587 /* Unknown event specified */
593 /*************************************<->*************************************
595 * _XwMapEvent (parameters)
599 * xxxxxxxxxxxxxxxxxxxxxxx
604 * xxxxxxxxxxxx = xxxxxxxxxxxxx
608 * xxxxxxxxxxxx = xxxxxxxxxxxxx
613 *************************************<->***********************************/
616 _XwMapEvent (str
, table
, eventType
, detail
, modifiers
)
620 unsigned int * eventType
;
621 unsigned int * detail
;
622 unsigned int * modifiers
;
628 /* Initialize, if first time called */
632 FillInQuarks (buttonEvents
);
633 FillInQuarks (modifierStrings
);
634 FillInQuarks (keyEvents
);
637 /* Parse the modifiers */
638 str
= ParseModifiers(str
, modifiers
, &status
);
639 if ( status
== FALSE
|| *str
!= '<')
644 /* Parse the event type and detail */
645 str
= ParseEventType(str
, table
, eventType
, &index
, &status
);
646 if (status
== FALSE
|| *str
!= '>')
651 /* Save the detail */
652 return ((*(table
[index
].parseProc
))(str
, table
[index
].closure
, detail
));
656 /*************************************<->*************************************
658 * _XwMapBtnEvent (parameters)
662 * xxxxxxxxxxxxxxxxxxxxxxx
667 * xxxxxxxxxxxx = xxxxxxxxxxxxx
671 * xxxxxxxxxxxx = xxxxxxxxxxxxx
676 *************************************<->***********************************/
678 Boolean
_XwMapBtnEvent (str
, eventType
, button
, modifiers
)
681 unsigned int * eventType
;
682 unsigned int * button
;
683 unsigned int * modifiers
;
686 if (_XwMapEvent (str
, buttonEvents
, eventType
, button
, modifiers
) == FALSE
)
690 * The following is a fix for an X11 deficiency in regards to
691 * modifiers in grabs.
693 if (*eventType
== ButtonRelease
)
695 /* the button that is going up will always be in the modifiers... */
696 *modifiers
|= buttonModifierMasks
[*button
];
703 /*************************************<->*************************************
705 * _XwMapKeyEvent (parameters)
709 * xxxxxxxxxxxxxxxxxxxxxxx
714 * xxxxxxxxxxxx = xxxxxxxxxxxxx
718 * xxxxxxxxxxxx = xxxxxxxxxxxxx
723 *************************************<->***********************************/
725 Boolean
_XwMapKeyEvent (str
, eventType
, key
, modifiers
)
728 unsigned int * eventType
;
730 unsigned int * modifiers
;
733 return (_XwMapEvent (str
, keyEvents
, eventType
, key
, modifiers
));
737 /*************************************<->*************************************
739 * _XwMatchBtnEvent (parameters)
743 * Compare the passed in event to the event described by the parameter
749 * xxxxxxxxxxxx = xxxxxxxxxxxxx
753 * xxxxxxxxxxxx = xxxxxxxxxxxxx
758 *************************************<->***********************************/
760 Boolean
_XwMatchBtnEvent (event
, eventType
, button
, modifiers
)
762 XButtonEvent
* event
;
763 unsigned int eventType
;
765 unsigned int modifiers
;
768 if ((event
->type
== eventType
) &&
769 (event
->button
== button
) &&
770 (event
->state
== modifiers
))
777 /*************************************<->*************************************
779 * _XwMatchKeyEvent (parameters)
783 * Compare the passed in event to the event described by the parameter
789 * xxxxxxxxxxxx = xxxxxxxxxxxxx
793 * xxxxxxxxxxxx = xxxxxxxxxxxxx
798 *************************************<->***********************************/
800 Boolean
_XwMatchKeyEvent (event
, eventType
, key
, modifiers
)
803 unsigned int eventType
;
805 unsigned int modifiers
;
808 if ((event
->type
== eventType
) &&
809 (event
->keycode
== key
) &&
810 (event
->state
== modifiers
))
817 /*************************************<->*************************************
819 * _XwValidModifier (parameters)
823 * xxxxxxxxxxxxxxxxxxxxxxx
828 * xxxxxxxxxxxx = xxxxxxxxxxxxx
832 * xxxxxxxxxxxx = xxxxxxxxxxxxx
837 *************************************<->***********************************/
839 Boolean
_XwValidModifier (str
)
844 unsigned int modifiers
;
848 * Scan the string for a valid set of event modifiers; valid includes
849 * a NULL string, an empty string, or all white space. A NULL is
850 * inserted into the string at the end of the modifiers.
853 if ((str
== NULL
) || (*str
== '\0'))
856 str
= ParseModifiers (str
, &modifiers
, &status
);
864 /*************************************<->*************************************
866 * _XwMapToHex (parameters)
870 * xxxxxxxxxxxxxxxxxxxxxxx
875 * xxxxxxxxxxxx = xxxxxxxxxxxxx
879 * xxxxxxxxxxxx = xxxxxxxxxxxxx
884 *************************************<->***********************************/
886 String
_XwMapToHex (menuMgrId
)
888 unsigned long menuMgrId
;
891 static char buffer
[(sizeof(Widget
) << 1) + 1];
895 /* Convert the menu manager widget id into a hex string */
896 for (i
= (sizeof(Widget
) << 1) - 1; i
>= 0; i
--)
898 digit
= (char) menuMgrId
& 0x0F;
899 buffer
[i
] = (digit
< 10) ? (digit
+ '0') : (digit
- 10 + 'A');
900 menuMgrId
= menuMgrId
>> 4;
903 buffer
[sizeof(Widget
) << 1] = '\0';
908 /*************************************<->*************************************
910 * _XwMapFromHex (parameters)
914 * xxxxxxxxxxxxxxxxxxxxxxx
919 * xxxxxxxxxxxx = xxxxxxxxxxxxx
923 * xxxxxxxxxxxx = xxxxxxxxxxxxx
928 *************************************<->***********************************/
930 unsigned long _XwMapFromHex (str
)
935 unsigned long id
= 0;
938 /* Convert the hex string into a menu manager widget id */
941 digit
= (int) ((*str
>= '0') && (*str
<= '9')) ? (*str
- '0') :
943 id
= (id
* 16) + digit
;