1 /*************************************<+>*************************************
2  *****************************************************************************
3  **
4  **   File:        MapEvents.c
5  **
6  **   Project:     X Widgets
7  **
8  **   Description: Menu Manager Support Routines
9  **
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.
16  **
17  *****************************************************************************
18  **
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
23  **
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.
32  **
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
39  **   SOFTWARE.
40  **
41  *****************************************************************************
42  *************************************<+>*************************************/
43 
44 
45 
46 #include <X11/Xlib.h>
47 #include <X11/IntrinsicP.h>
48 #include <X11/Xutil.h>
49 #include <X11/StringDefs.h>
50 #include <X11/Xatom.h>
51 
52 
53 static Boolean ParseImmed();
54 static Boolean ParseKeySym();
55 
56 
57 
58 typedef struct {
59    char       * event;
60    XrmQuark     signature;
61    unsigned int eventType;
62    Boolean      (*parseProc)();
63    unsigned int closure;
64 } EventKey;
65 
66 static EventKey modifierStrings[] = {
67 
68   /* Modifier,  Quark,  Mask */
69 
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},
81 };
82 
83 
84 static EventKey buttonEvents[] = {
85 
86 /* Event Name,	  Quark, Event Type,	DetailProc	Closure */
87 
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}};
99 
100 
101 static EventKey keyEvents[] = {
102 
103 /* Event Name,	  Quark, Event Type,	DetailProc	Closure */
104 
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}};
111 
112 
113 static unsigned int buttonModifierMasks[] = {
114     0, Button1Mask, Button2Mask, Button3Mask, Button4Mask, Button5Mask
115 };
116 
117 static initialized = FALSE;
118 
119 
120 
121 /*************************************<->*************************************
122  *
123  *  Numeric convertion routines
124  *
125  *   Description:
126  *   -----------
127  *     xxxxxxxxxxxxxxxxxxxxxxx
128  *
129  *
130  *   Inputs:
131  *   ------
132  *     xxxxxxxxxxxx = xxxxxxxxxxxxx
133  *
134  *   Outputs:
135  *   -------
136  *     xxxxxxxxxxxx = xxxxxxxxxxxxx
137  *
138  *   Procedures Called
139  *   -----------------
140  *
141  *************************************<->***********************************/
142 
StrToHex(str)143 static unsigned int StrToHex(str)
144     String str;
145 {
146     register char   c;
147     register int    val = 0;
148 
149     while (c = *str) {
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;
153 	else return -1;
154 	str++;
155     }
156 
157     return val;
158 }
159 
StrToOct(str)160 static unsigned int StrToOct(str)
161     String str;
162 {
163     register char c;
164     register int  val = 0;
165 
166     while (c = *str) {
167         if ('0' <= c && c <= '7') val = val*8+c-'0'; else return -1;
168 	str++;
169     }
170 
171     return val;
172 }
173 
StrToNum(str)174 static unsigned int StrToNum(str)
175     String str;
176 {
177     register char c;
178     register int val = 0;
179 
180     if (*str == '0') {
181 	str++;
182 	if (*str == 'x' || *str == 'X') return StrToHex(++str);
183 	else return StrToOct(str);
184     }
185 
186     while (c = *str) {
187 	if ('0' <= c && c <= '9') val = val*10+c-'0';
188 	else return -1;
189 	str++;
190     }
191 
192     return val;
193 }
194 
195 
196 /*************************************<->*************************************
197  *
198  *  FillInQuarks (parameters)
199  *
200  *   Description:
201  *   -----------
202  *     Converts each string entry in the modifier/event tables to a
203  *     quark, thus facilitating faster comparisons.
204  *
205  *
206  *   Inputs:
207  *   ------
208  *     xxxxxxxxxxxx = xxxxxxxxxxxxx
209  *
210  *   Outputs:
211  *   -------
212  *     xxxxxxxxxxxx = xxxxxxxxxxxxx
213  *
214  *   Procedures Called
215  *   -----------------
216  *
217  *************************************<->***********************************/
218 
FillInQuarks(table)219 static void FillInQuarks (table)
220 
221     EventKey * table;
222 
223 {
224     register int i;
225 
226     for (i=0; table[i].event; i++)
227         table[i].signature = XrmStringToQuark(table[i].event);
228 }
229 
230 
231 /*************************************<->*************************************
232  *
233  *  LookupModifier (parameters)
234  *
235  *   Description:
236  *   -----------
237  *     Compare the passed in string to the list of valid modifiers.
238  *
239  *
240  *   Inputs:
241  *   ------
242  *     xxxxxxxxxxxx = xxxxxxxxxxxxx
243  *
244  *   Outputs:
245  *   -------
246  *     xxxxxxxxxxxx = xxxxxxxxxxxxx
247  *
248  *   Procedures Called
249  *   -----------------
250  *
251  *************************************<->***********************************/
252 
LookupModifier(name,valueP)253 static Boolean LookupModifier (name, valueP)
254 
255     String name;
256     unsigned int *valueP;
257 
258 {
259     register int i;
260     register XrmQuark signature = XrmStringToQuark(name);
261 
262     for (i=0; modifierStrings[i].event != NULL; i++)
263 	if (modifierStrings[i].signature == signature) {
264 	    *valueP = modifierStrings[i].closure;
265 	    return TRUE;
266 	}
267 
268     return FALSE;
269 }
270 
271 
272 /*************************************<->*************************************
273  *
274  *  ScanAlphanumeric (parameters)
275  *
276  *   Description:
277  *   -----------
278  *     Scan string until a non-alphanumeric character is encountered.
279  *
280  *
281  *   Inputs:
282  *   ------
283  *     xxxxxxxxxxxx = xxxxxxxxxxxxx
284  *
285  *   Outputs:
286  *   -------
287  *     xxxxxxxxxxxx = xxxxxxxxxxxxx
288  *
289  *   Procedures Called
290  *   -----------------
291  *
292  *************************************<->***********************************/
293 
ScanAlphanumeric(str)294 static String ScanAlphanumeric (str)
295 
296     register String str;
297 
298 {
299     while (
300         ('A' <= *str && *str <= 'Z') || ('a' <= *str && *str <= 'z')
301 	|| ('0' <= *str && *str <= '9')) str++;
302     return str;
303 }
304 
305 
306 /*************************************<->*************************************
307  *
308  *  ScanWhitespace (parameters)
309  *
310  *   Description:
311  *   -----------
312  *     Scan the string, skipping over all white space characters.
313  *
314  *
315  *   Inputs:
316  *   ------
317  *     xxxxxxxxxxxx = xxxxxxxxxxxxx
318  *
319  *   Outputs:
320  *   -------
321  *     xxxxxxxxxxxx = xxxxxxxxxxxxx
322  *
323  *   Procedures Called
324  *   -----------------
325  *
326  *************************************<->***********************************/
327 
ScanWhitespace(str)328 static String ScanWhitespace(str)
329     register String str;
330 {
331     while (*str == ' ' || *str == '\t') str++;
332     return str;
333 }
334 
335 
336 /*************************************<->*************************************
337  *
338  *  ParseImmed (parameters)
339  *
340  *   Description:
341  *   -----------
342  *     xxxxxxxxxxxxxxxxxxxxxxx
343  *
344  *
345  *   Inputs:
346  *   ------
347  *     xxxxxxxxxxxx = xxxxxxxxxxxxx
348  *
349  *   Outputs:
350  *   -------
351  *     xxxxxxxxxxxx = xxxxxxxxxxxxx
352  *
353  *   Procedures Called
354  *   -----------------
355  *
356  *************************************<->***********************************/
357 
ParseImmed(str,closure,detail)358 static Boolean ParseImmed (str, closure, detail)
359 
360    String str;
361    unsigned int closure;
362    unsigned int * detail;
363 
364 {
365    *detail = closure;
366    return (TRUE);
367 }
368 
369 
370 /*************************************<->*************************************
371  *
372  *  ParseKeySym (parameters)
373  *
374  *   Description:
375  *   -----------
376  *     xxxxxxxxxxxxxxxxxxxxxxx
377  *
378  *
379  *   Inputs:
380  *   ------
381  *     xxxxxxxxxxxx = xxxxxxxxxxxxx
382  *
383  *   Outputs:
384  *   -------
385  *     xxxxxxxxxxxx = xxxxxxxxxxxxx
386  *
387  *   Procedures Called
388  *   -----------------
389  *
390  *************************************<->***********************************/
391 
ParseKeySym(str,closure,detail)392 static Boolean ParseKeySym (str, closure, detail)
393 
394    String str;
395    unsigned int closure;
396    unsigned int * detail;
397 
398 {
399     char keySymName[100], *start;
400 
401     str = ScanWhitespace(str);
402 
403     if (*str == '\\') {
404 	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 */
411        *detail = NoSymbol;
412        return (FALSE);
413     } else {
414 	start = str;
415 	while (
416 		*str != ','
417 		&& *str != ':'
418 		&& *str != ' '
419 		&& *str != '\t'
420                 && *str != '\n'
421 		&& *str != '\0') str++;
422 	(void) strncpy(keySymName, start, str-start);
423 	keySymName[str-start] = '\0';
424 	*detail = XStringToKeysym(keySymName);
425     }
426 
427     if (*detail == NoSymbol)
428     {
429        if (( '0' <= keySymName[0]) && (keySymName[0] <= '9'))
430        {
431           *detail = StrToNum(keySymName);
432           return (TRUE);
433        }
434        return (FALSE);
435     }
436     else
437        return (TRUE);
438 }
439 
440 
441 /*************************************<->*************************************
442  *
443  *  ParseModifiers (parameters)
444  *
445  *   Description:
446  *   -----------
447  *     Parse the string, extracting all modifier specifications.
448  *
449  *
450  *   Inputs:
451  *   ------
452  *     xxxxxxxxxxxx = xxxxxxxxxxxxx
453  *
454  *   Outputs:
455  *   -------
456  *     xxxxxxxxxxxx = xxxxxxxxxxxxx
457  *
458  *   Procedures Called
459  *   -----------------
460  *
461  *************************************<->***********************************/
462 
ParseModifiers(str,modifiers,status)463 static String ParseModifiers(str, modifiers, status)
464 
465     register String str;
466     unsigned int  * modifiers;
467     Boolean       * status;
468 
469 {
470     register String start;
471     char modStr[100];
472     Boolean notFlag, exclusive;
473     unsigned int maskBit;
474 
475     /* Initially assume all is going to go well */
476     *status = TRUE;
477     *modifiers = 0;
478 
479     /* Attempt to parse the first button modifier */
480     str = ScanWhitespace(str);
481     start = str;
482     str = ScanAlphanumeric(str);
483     if (start != str) {
484          (void) strncpy(modStr, start, str-start);
485           modStr[str-start] = '\0';
486           if (LookupModifier(modStr, &maskBit))
487           {
488 	    if (maskBit== None) {
489 		*modifiers = 0;
490                 str = ScanWhitespace(str);
491 	        return str;
492             }
493          }
494          str = start;
495     }
496 
497 
498     /* Keep parsing modifiers, until the event specifier is encountered */
499     while ((*str != '<') && (*str != '\0')) {
500         if (*str == '~') {
501              notFlag = TRUE;
502              str++;
503           } else
504               notFlag = FALSE;
505 
506 	start = str;
507         str = ScanAlphanumeric(str);
508         if (start == str) {
509            /* ERROR: Modifier or '<' missing */
510            *status = FALSE;
511            return str;
512         }
513         (void) strncpy(modStr, start, str-start);
514         modStr[str-start] = '\0';
515 
516         if (!LookupModifier(modStr, &maskBit))
517         {
518            /* Unknown modifier name */
519            *status = FALSE;
520            return str;
521         }
522 
523 	if (notFlag)
524            *modifiers &= ~maskBit;
525 	else
526            *modifiers |= maskBit;
527         str = ScanWhitespace(str);
528     }
529 
530     return str;
531 }
532 
533 
534 /*************************************<->*************************************
535  *
536  *  ParseEventType (parameters)
537  *
538  *   Description:
539  *   -----------
540  *     xxxxxxxxxxxxxxxxxxxxxxx
541  *
542  *
543  *   Inputs:
544  *   ------
545  *     xxxxxxxxxxxx = xxxxxxxxxxxxx
546  *
547  *   Outputs:
548  *   -------
549  *     xxxxxxxxxxxx = xxxxxxxxxxxxx
550  *
551  *   Procedures Called
552  *   -----------------
553  *
554  *************************************<->***********************************/
555 
ParseEventType(str,table,eventType,index,status)556 static String ParseEventType(str, table, eventType, index, status)
557 
558     register String str;
559     EventKey * table;
560     unsigned int * eventType;
561     Cardinal     * index;
562     Boolean      * status;
563 
564 {
565     String start = str;
566     char eventTypeStr[100];
567     register Cardinal   i;
568     register XrmQuark	signature;
569 
570     /* Parse out the event string */
571     str = ScanAlphanumeric(str);
572     (void) strncpy(eventTypeStr, start, str-start);
573     eventTypeStr[str-start] = '\0';
574 
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)
579         {
580            *index = i;
581            *eventType = table[*index].eventType;
582 
583            *status = TRUE;
584            return str;
585         }
586 
587     /* Unknown event specified */
588     *status = FALSE;
589     return (str);
590 }
591 
592 
593 /*************************************<->*************************************
594  *
595  *  _XwMapEvent (parameters)
596  *
597  *   Description:
598  *   -----------
599  *     xxxxxxxxxxxxxxxxxxxxxxx
600  *
601  *
602  *   Inputs:
603  *   ------
604  *     xxxxxxxxxxxx = xxxxxxxxxxxxx
605  *
606  *   Outputs:
607  *   -------
608  *     xxxxxxxxxxxx = xxxxxxxxxxxxx
609  *
610  *   Procedures Called
611  *   -----------------
612  *
613  *************************************<->***********************************/
614 
615 static Boolean
_XwMapEvent(str,table,eventType,detail,modifiers)616 _XwMapEvent (str, table, eventType, detail, modifiers)
617 
618     register String str;
619     EventKey     * table;
620     unsigned int * eventType;
621     unsigned int * detail;
622     unsigned int * modifiers;
623 
624 {
625     Cardinal index;
626     Boolean  status;
627 
628     /* Initialize, if first time called */
629     if (!initialized)
630     {
631        initialized = TRUE;
632        FillInQuarks (buttonEvents);
633        FillInQuarks (modifierStrings);
634        FillInQuarks (keyEvents);
635     }
636 
637     /* Parse the modifiers */
638     str = ParseModifiers(str, modifiers, &status);
639     if ( status == FALSE || *str != '<')
640        return (FALSE);
641     else
642        str++;
643 
644     /* Parse the event type and detail */
645     str = ParseEventType(str, table, eventType, &index, &status);
646     if (status == FALSE || *str != '>')
647        return (FALSE);
648     else
649        str++;
650 
651     /* Save the detail */
652     return ((*(table[index].parseProc))(str, table[index].closure, detail));
653 }
654 
655 
656 /*************************************<->*************************************
657  *
658  *  _XwMapBtnEvent (parameters)
659  *
660  *   Description:
661  *   -----------
662  *     xxxxxxxxxxxxxxxxxxxxxxx
663  *
664  *
665  *   Inputs:
666  *   ------
667  *     xxxxxxxxxxxx = xxxxxxxxxxxxx
668  *
669  *   Outputs:
670  *   -------
671  *     xxxxxxxxxxxx = xxxxxxxxxxxxx
672  *
673  *   Procedures Called
674  *   -----------------
675  *
676  *************************************<->***********************************/
677 
_XwMapBtnEvent(str,eventType,button,modifiers)678 Boolean _XwMapBtnEvent (str, eventType, button, modifiers)
679 
680     register String str;
681     unsigned int * eventType;
682     unsigned int * button;
683     unsigned int * modifiers;
684 
685 {
686     if (_XwMapEvent (str, buttonEvents, eventType, button, modifiers) == FALSE)
687        return (FALSE);
688 
689     /*
690      * The following is a fix for an X11 deficiency in regards to
691      * modifiers in grabs.
692      */
693     if (*eventType == ButtonRelease)
694     {
695 	/* the button that is going up will always be in the modifiers... */
696 	*modifiers |= buttonModifierMasks[*button];
697     }
698 
699     return (TRUE);
700 }
701 
702 
703 /*************************************<->*************************************
704  *
705  *  _XwMapKeyEvent (parameters)
706  *
707  *   Description:
708  *   -----------
709  *     xxxxxxxxxxxxxxxxxxxxxxx
710  *
711  *
712  *   Inputs:
713  *   ------
714  *     xxxxxxxxxxxx = xxxxxxxxxxxxx
715  *
716  *   Outputs:
717  *   -------
718  *     xxxxxxxxxxxx = xxxxxxxxxxxxx
719  *
720  *   Procedures Called
721  *   -----------------
722  *
723  *************************************<->***********************************/
724 
_XwMapKeyEvent(str,eventType,key,modifiers)725 Boolean _XwMapKeyEvent (str, eventType, key, modifiers)
726 
727     register String str;
728     unsigned int * eventType;
729     unsigned int * key;
730     unsigned int * modifiers;
731 
732 {
733     return (_XwMapEvent (str, keyEvents, eventType, key, modifiers));
734 }
735 
736 
737 /*************************************<->*************************************
738  *
739  *  _XwMatchBtnEvent (parameters)
740  *
741  *   Description:
742  *   -----------
743  *     Compare the passed in event to the event described by the parameter
744  *     list.
745  *
746  *
747  *   Inputs:
748  *   ------
749  *     xxxxxxxxxxxx = xxxxxxxxxxxxx
750  *
751  *   Outputs:
752  *   -------
753  *     xxxxxxxxxxxx = xxxxxxxxxxxxx
754  *
755  *   Procedures Called
756  *   -----------------
757  *
758  *************************************<->***********************************/
759 
_XwMatchBtnEvent(event,eventType,button,modifiers)760 Boolean _XwMatchBtnEvent (event, eventType, button, modifiers)
761 
762    XButtonEvent * event;
763    unsigned int   eventType;
764    unsigned int   button;
765    unsigned int   modifiers;
766 
767 {
768    if ((event->type == eventType) &&
769        (event->button == button) &&
770        (event->state == modifiers))
771       return (TRUE);
772    else
773       return (FALSE);
774 }
775 
776 
777 /*************************************<->*************************************
778  *
779  *  _XwMatchKeyEvent (parameters)
780  *
781  *   Description:
782  *   -----------
783  *     Compare the passed in event to the event described by the parameter
784  *     list.
785  *
786  *
787  *   Inputs:
788  *   ------
789  *     xxxxxxxxxxxx = xxxxxxxxxxxxx
790  *
791  *   Outputs:
792  *   -------
793  *     xxxxxxxxxxxx = xxxxxxxxxxxxx
794  *
795  *   Procedures Called
796  *   -----------------
797  *
798  *************************************<->***********************************/
799 
_XwMatchKeyEvent(event,eventType,key,modifiers)800 Boolean _XwMatchKeyEvent (event, eventType, key, modifiers)
801 
802    XKeyEvent    * event;
803    unsigned int   eventType;
804    unsigned int   key;
805    unsigned int   modifiers;
806 
807 {
808    if ((event->type == eventType) &&
809        (event->keycode == key) &&
810        (event->state == modifiers))
811       return (TRUE);
812    else
813       return (FALSE);
814 }
815 
816 
817 /*************************************<->*************************************
818  *
819  *  _XwValidModifier (parameters)
820  *
821  *   Description:
822  *   -----------
823  *     xxxxxxxxxxxxxxxxxxxxxxx
824  *
825  *
826  *   Inputs:
827  *   ------
828  *     xxxxxxxxxxxx = xxxxxxxxxxxxx
829  *
830  *   Outputs:
831  *   -------
832  *     xxxxxxxxxxxx = xxxxxxxxxxxxx
833  *
834  *   Procedures Called
835  *   -----------------
836  *
837  *************************************<->***********************************/
838 
_XwValidModifier(str)839 Boolean _XwValidModifier (str)
840 
841    register String str;
842 
843 {
844    unsigned int modifiers;
845    Boolean status;
846 
847    /*
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.
851     */
852 
853    if ((str == NULL) || (*str == '\0'))
854       return (TRUE);
855 
856    str = ParseModifiers (str, &modifiers, &status);
857 
858    if (status == TRUE)
859       *str = '\0';
860 
861    return (status);
862 }
863 
864 /*************************************<->*************************************
865  *
866  *  _XwMapToHex (parameters)
867  *
868  *   Description:
869  *   -----------
870  *     xxxxxxxxxxxxxxxxxxxxxxx
871  *
872  *
873  *   Inputs:
874  *   ------
875  *     xxxxxxxxxxxx = xxxxxxxxxxxxx
876  *
877  *   Outputs:
878  *   -------
879  *     xxxxxxxxxxxx = xxxxxxxxxxxxx
880  *
881  *   Procedures Called
882  *   -----------------
883  *
884  *************************************<->***********************************/
885 
_XwMapToHex(menuMgrId)886 String _XwMapToHex (menuMgrId)
887 
888    unsigned long menuMgrId;
889 
890 {
891    static char buffer[(sizeof(Widget) << 1) + 1];
892    int i;
893    char digit;
894 
895    /* Convert the menu manager widget id into a hex string */
896    for (i = (sizeof(Widget) << 1) - 1; i >= 0; i--)
897    {
898       digit = (char) menuMgrId & 0x0F;
899       buffer[i] = (digit < 10) ? (digit + '0') : (digit - 10 + 'A');
900       menuMgrId = menuMgrId >> 4;
901    }
902 
903    buffer[sizeof(Widget) << 1] = '\0';
904    return (buffer);
905 }
906 
907 
908 /*************************************<->*************************************
909  *
910  *  _XwMapFromHex (parameters)
911  *
912  *   Description:
913  *   -----------
914  *     xxxxxxxxxxxxxxxxxxxxxxx
915  *
916  *
917  *   Inputs:
918  *   ------
919  *     xxxxxxxxxxxx = xxxxxxxxxxxxx
920  *
921  *   Outputs:
922  *   -------
923  *     xxxxxxxxxxxx = xxxxxxxxxxxxx
924  *
925  *   Procedures Called
926  *   -----------------
927  *
928  *************************************<->***********************************/
929 
_XwMapFromHex(str)930 unsigned long _XwMapFromHex (str)
931 
932    String str;
933 
934 {
935    unsigned long id = 0;
936    int digit;
937 
938    /* Convert the hex string into a menu manager widget id */
939    while (str && *str)
940    {
941       digit = (int) ((*str >= '0') && (*str <= '9')) ? (*str - '0') :
942                                                        (*str + 10 - 'A');
943       id = (id * 16) + digit;
944       str++;
945    }
946 
947    return (id);
948 }
949