Initial commit at Tue Apr 25 08:36:02 EDT 2017 by tim on stravinsky
[xcircuit.git] / Xw / MapEvents.c
blobe0347a8a500f86dae794b02b5f9deb9d2cc7e3b1
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 *************************************<+>*************************************/
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>
53 static Boolean ParseImmed();
54 static Boolean ParseKeySym();
58 typedef struct {
59 char * event;
60 XrmQuark signature;
61 unsigned int eventType;
62 Boolean (*parseProc)();
63 unsigned int closure;
64 } EventKey;
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
125 * Description:
126 * -----------
127 * xxxxxxxxxxxxxxxxxxxxxxx
130 * Inputs:
131 * ------
132 * xxxxxxxxxxxx = xxxxxxxxxxxxx
134 * Outputs:
135 * -------
136 * xxxxxxxxxxxx = xxxxxxxxxxxxx
138 * Procedures Called
139 * -----------------
141 *************************************<->***********************************/
143 static unsigned int StrToHex(str)
144 String str;
146 register char c;
147 register int val = 0;
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++;
157 return val;
160 static unsigned int StrToOct(str)
161 String str;
163 register char c;
164 register int val = 0;
166 while (c = *str) {
167 if ('0' <= c && c <= '7') val = val*8+c-'0'; else return -1;
168 str++;
171 return val;
174 static unsigned int StrToNum(str)
175 String str;
177 register char c;
178 register int val = 0;
180 if (*str == '0') {
181 str++;
182 if (*str == 'x' || *str == 'X') return StrToHex(++str);
183 else return StrToOct(str);
186 while (c = *str) {
187 if ('0' <= c && c <= '9') val = val*10+c-'0';
188 else return -1;
189 str++;
192 return val;
196 /*************************************<->*************************************
198 * FillInQuarks (parameters)
200 * Description:
201 * -----------
202 * Converts each string entry in the modifier/event tables to a
203 * quark, thus facilitating faster comparisons.
206 * Inputs:
207 * ------
208 * xxxxxxxxxxxx = xxxxxxxxxxxxx
210 * Outputs:
211 * -------
212 * xxxxxxxxxxxx = xxxxxxxxxxxxx
214 * Procedures Called
215 * -----------------
217 *************************************<->***********************************/
219 static void FillInQuarks (table)
221 EventKey * table;
224 register int i;
226 for (i=0; table[i].event; i++)
227 table[i].signature = XrmStringToQuark(table[i].event);
231 /*************************************<->*************************************
233 * LookupModifier (parameters)
235 * Description:
236 * -----------
237 * Compare the passed in string to the list of valid modifiers.
240 * Inputs:
241 * ------
242 * xxxxxxxxxxxx = xxxxxxxxxxxxx
244 * Outputs:
245 * -------
246 * xxxxxxxxxxxx = xxxxxxxxxxxxx
248 * Procedures Called
249 * -----------------
251 *************************************<->***********************************/
253 static Boolean LookupModifier (name, valueP)
255 String name;
256 unsigned int *valueP;
259 register int i;
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;
265 return TRUE;
268 return FALSE;
272 /*************************************<->*************************************
274 * ScanAlphanumeric (parameters)
276 * Description:
277 * -----------
278 * Scan string until a non-alphanumeric character is encountered.
281 * Inputs:
282 * ------
283 * xxxxxxxxxxxx = xxxxxxxxxxxxx
285 * Outputs:
286 * -------
287 * xxxxxxxxxxxx = xxxxxxxxxxxxx
289 * Procedures Called
290 * -----------------
292 *************************************<->***********************************/
294 static String ScanAlphanumeric (str)
296 register String str;
299 while (
300 ('A' <= *str && *str <= 'Z') || ('a' <= *str && *str <= 'z')
301 || ('0' <= *str && *str <= '9')) str++;
302 return str;
306 /*************************************<->*************************************
308 * ScanWhitespace (parameters)
310 * Description:
311 * -----------
312 * Scan the string, skipping over all white space characters.
315 * Inputs:
316 * ------
317 * xxxxxxxxxxxx = xxxxxxxxxxxxx
319 * Outputs:
320 * -------
321 * xxxxxxxxxxxx = xxxxxxxxxxxxx
323 * Procedures Called
324 * -----------------
326 *************************************<->***********************************/
328 static String ScanWhitespace(str)
329 register String str;
331 while (*str == ' ' || *str == '\t') str++;
332 return str;
336 /*************************************<->*************************************
338 * ParseImmed (parameters)
340 * Description:
341 * -----------
342 * xxxxxxxxxxxxxxxxxxxxxxx
345 * Inputs:
346 * ------
347 * xxxxxxxxxxxx = xxxxxxxxxxxxx
349 * Outputs:
350 * -------
351 * xxxxxxxxxxxx = xxxxxxxxxxxxx
353 * Procedures Called
354 * -----------------
356 *************************************<->***********************************/
358 static Boolean ParseImmed (str, closure, detail)
360 String str;
361 unsigned int closure;
362 unsigned int * detail;
365 *detail = closure;
366 return (TRUE);
370 /*************************************<->*************************************
372 * ParseKeySym (parameters)
374 * Description:
375 * -----------
376 * xxxxxxxxxxxxxxxxxxxxxxx
379 * Inputs:
380 * ------
381 * xxxxxxxxxxxx = xxxxxxxxxxxxx
383 * Outputs:
384 * -------
385 * xxxxxxxxxxxx = xxxxxxxxxxxxx
387 * Procedures Called
388 * -----------------
390 *************************************<->***********************************/
392 static Boolean ParseKeySym (str, closure, detail)
394 String str;
395 unsigned int closure;
396 unsigned int * detail;
399 char keySymName[100], *start;
401 str = ScanWhitespace(str);
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);
427 if (*detail == NoSymbol)
429 if (( '0' <= keySymName[0]) && (keySymName[0] <= '9'))
431 *detail = StrToNum(keySymName);
432 return (TRUE);
434 return (FALSE);
436 else
437 return (TRUE);
441 /*************************************<->*************************************
443 * ParseModifiers (parameters)
445 * Description:
446 * -----------
447 * Parse the string, extracting all modifier specifications.
450 * Inputs:
451 * ------
452 * xxxxxxxxxxxx = xxxxxxxxxxxxx
454 * Outputs:
455 * -------
456 * xxxxxxxxxxxx = xxxxxxxxxxxxx
458 * Procedures Called
459 * -----------------
461 *************************************<->***********************************/
463 static String ParseModifiers(str, modifiers, status)
465 register String str;
466 unsigned int * modifiers;
467 Boolean * status;
470 register String start;
471 char modStr[100];
472 Boolean notFlag, exclusive;
473 unsigned int maskBit;
475 /* Initially assume all is going to go well */
476 *status = TRUE;
477 *modifiers = 0;
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))
488 if (maskBit== None) {
489 *modifiers = 0;
490 str = ScanWhitespace(str);
491 return str;
494 str = start;
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;
506 start = str;
507 str = ScanAlphanumeric(str);
508 if (start == str) {
509 /* ERROR: Modifier or '<' missing */
510 *status = FALSE;
511 return str;
513 (void) strncpy(modStr, start, str-start);
514 modStr[str-start] = '\0';
516 if (!LookupModifier(modStr, &maskBit))
518 /* Unknown modifier name */
519 *status = FALSE;
520 return str;
523 if (notFlag)
524 *modifiers &= ~maskBit;
525 else
526 *modifiers |= maskBit;
527 str = ScanWhitespace(str);
530 return str;
534 /*************************************<->*************************************
536 * ParseEventType (parameters)
538 * Description:
539 * -----------
540 * xxxxxxxxxxxxxxxxxxxxxxx
543 * Inputs:
544 * ------
545 * xxxxxxxxxxxx = xxxxxxxxxxxxx
547 * Outputs:
548 * -------
549 * xxxxxxxxxxxx = xxxxxxxxxxxxx
551 * Procedures Called
552 * -----------------
554 *************************************<->***********************************/
556 static String ParseEventType(str, table, eventType, index, status)
558 register String str;
559 EventKey * table;
560 unsigned int * eventType;
561 Cardinal * index;
562 Boolean * status;
565 String start = str;
566 char eventTypeStr[100];
567 register Cardinal i;
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)
580 *index = i;
581 *eventType = table[*index].eventType;
583 *status = TRUE;
584 return str;
587 /* Unknown event specified */
588 *status = FALSE;
589 return (str);
593 /*************************************<->*************************************
595 * _XwMapEvent (parameters)
597 * Description:
598 * -----------
599 * xxxxxxxxxxxxxxxxxxxxxxx
602 * Inputs:
603 * ------
604 * xxxxxxxxxxxx = xxxxxxxxxxxxx
606 * Outputs:
607 * -------
608 * xxxxxxxxxxxx = xxxxxxxxxxxxx
610 * Procedures Called
611 * -----------------
613 *************************************<->***********************************/
615 static Boolean
616 _XwMapEvent (str, table, eventType, detail, modifiers)
618 register String str;
619 EventKey * table;
620 unsigned int * eventType;
621 unsigned int * detail;
622 unsigned int * modifiers;
625 Cardinal index;
626 Boolean status;
628 /* Initialize, if first time called */
629 if (!initialized)
631 initialized = TRUE;
632 FillInQuarks (buttonEvents);
633 FillInQuarks (modifierStrings);
634 FillInQuarks (keyEvents);
637 /* Parse the modifiers */
638 str = ParseModifiers(str, modifiers, &status);
639 if ( status == FALSE || *str != '<')
640 return (FALSE);
641 else
642 str++;
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++;
651 /* Save the detail */
652 return ((*(table[index].parseProc))(str, table[index].closure, detail));
656 /*************************************<->*************************************
658 * _XwMapBtnEvent (parameters)
660 * Description:
661 * -----------
662 * xxxxxxxxxxxxxxxxxxxxxxx
665 * Inputs:
666 * ------
667 * xxxxxxxxxxxx = xxxxxxxxxxxxx
669 * Outputs:
670 * -------
671 * xxxxxxxxxxxx = xxxxxxxxxxxxx
673 * Procedures Called
674 * -----------------
676 *************************************<->***********************************/
678 Boolean _XwMapBtnEvent (str, eventType, button, modifiers)
680 register String str;
681 unsigned int * eventType;
682 unsigned int * button;
683 unsigned int * modifiers;
686 if (_XwMapEvent (str, buttonEvents, eventType, button, modifiers) == FALSE)
687 return (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];
699 return (TRUE);
703 /*************************************<->*************************************
705 * _XwMapKeyEvent (parameters)
707 * Description:
708 * -----------
709 * xxxxxxxxxxxxxxxxxxxxxxx
712 * Inputs:
713 * ------
714 * xxxxxxxxxxxx = xxxxxxxxxxxxx
716 * Outputs:
717 * -------
718 * xxxxxxxxxxxx = xxxxxxxxxxxxx
720 * Procedures Called
721 * -----------------
723 *************************************<->***********************************/
725 Boolean _XwMapKeyEvent (str, eventType, key, modifiers)
727 register String str;
728 unsigned int * eventType;
729 unsigned int * key;
730 unsigned int * modifiers;
733 return (_XwMapEvent (str, keyEvents, eventType, key, modifiers));
737 /*************************************<->*************************************
739 * _XwMatchBtnEvent (parameters)
741 * Description:
742 * -----------
743 * Compare the passed in event to the event described by the parameter
744 * list.
747 * Inputs:
748 * ------
749 * xxxxxxxxxxxx = xxxxxxxxxxxxx
751 * Outputs:
752 * -------
753 * xxxxxxxxxxxx = xxxxxxxxxxxxx
755 * Procedures Called
756 * -----------------
758 *************************************<->***********************************/
760 Boolean _XwMatchBtnEvent (event, eventType, button, modifiers)
762 XButtonEvent * event;
763 unsigned int eventType;
764 unsigned int button;
765 unsigned int modifiers;
768 if ((event->type == eventType) &&
769 (event->button == button) &&
770 (event->state == modifiers))
771 return (TRUE);
772 else
773 return (FALSE);
777 /*************************************<->*************************************
779 * _XwMatchKeyEvent (parameters)
781 * Description:
782 * -----------
783 * Compare the passed in event to the event described by the parameter
784 * list.
787 * Inputs:
788 * ------
789 * xxxxxxxxxxxx = xxxxxxxxxxxxx
791 * Outputs:
792 * -------
793 * xxxxxxxxxxxx = xxxxxxxxxxxxx
795 * Procedures Called
796 * -----------------
798 *************************************<->***********************************/
800 Boolean _XwMatchKeyEvent (event, eventType, key, modifiers)
802 XKeyEvent * event;
803 unsigned int eventType;
804 unsigned int key;
805 unsigned int modifiers;
808 if ((event->type == eventType) &&
809 (event->keycode == key) &&
810 (event->state == modifiers))
811 return (TRUE);
812 else
813 return (FALSE);
817 /*************************************<->*************************************
819 * _XwValidModifier (parameters)
821 * Description:
822 * -----------
823 * xxxxxxxxxxxxxxxxxxxxxxx
826 * Inputs:
827 * ------
828 * xxxxxxxxxxxx = xxxxxxxxxxxxx
830 * Outputs:
831 * -------
832 * xxxxxxxxxxxx = xxxxxxxxxxxxx
834 * Procedures Called
835 * -----------------
837 *************************************<->***********************************/
839 Boolean _XwValidModifier (str)
841 register String str;
844 unsigned int modifiers;
845 Boolean status;
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'))
854 return (TRUE);
856 str = ParseModifiers (str, &modifiers, &status);
858 if (status == TRUE)
859 *str = '\0';
861 return (status);
864 /*************************************<->*************************************
866 * _XwMapToHex (parameters)
868 * Description:
869 * -----------
870 * xxxxxxxxxxxxxxxxxxxxxxx
873 * Inputs:
874 * ------
875 * xxxxxxxxxxxx = xxxxxxxxxxxxx
877 * Outputs:
878 * -------
879 * xxxxxxxxxxxx = xxxxxxxxxxxxx
881 * Procedures Called
882 * -----------------
884 *************************************<->***********************************/
886 String _XwMapToHex (menuMgrId)
888 unsigned long menuMgrId;
891 static char buffer[(sizeof(Widget) << 1) + 1];
892 int i;
893 char digit;
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';
904 return (buffer);
908 /*************************************<->*************************************
910 * _XwMapFromHex (parameters)
912 * Description:
913 * -----------
914 * xxxxxxxxxxxxxxxxxxxxxxx
917 * Inputs:
918 * ------
919 * xxxxxxxxxxxx = xxxxxxxxxxxxx
921 * Outputs:
922 * -------
923 * xxxxxxxxxxxx = xxxxxxxxxxxxx
925 * Procedures Called
926 * -----------------
928 *************************************<->***********************************/
930 unsigned long _XwMapFromHex (str)
932 String str;
935 unsigned long id = 0;
936 int digit;
938 /* Convert the hex string into a menu manager widget id */
939 while (str && *str)
941 digit = (int) ((*str >= '0') && (*str <= '9')) ? (*str - '0') :
942 (*str + 10 - 'A');
943 id = (id * 16) + digit;
944 str++;
947 return (id);