|
|
1.1 root 1: #ifndef lint
2: static char rcsid[] = "$Header: TMparse.c,v 1.24 87/09/11 21:24:33 haynes Rel $";
3: #endif lint
4:
5: /*
6: * Copyright 1987 by Digital Equipment Corporation, Maynard, Massachusetts.
7: *
8: * All Rights Reserved
9: *
10: * Permission to use, copy, modify, and distribute this software and its
11: * documentation for any purpose and without fee is hereby granted,
12: * provided that the above copyright notice appear in all copies and that
13: * both that copyright notice and this permission notice appear in
14: * supporting documentation, and that the name of Digital Equipment
15: * Corporation not be used in advertising or publicity pertaining to
16: * distribution of the software without specific, written prior permission.
17: *
18: *
19: * DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
20: * ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
21: * DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
22: * ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
23: * WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
24: * ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
25: * SOFTWARE.
26: */
27: /* TMparse.c -- parse all X events into widget specific actions. */
28:
29: #include <stdio.h>
30: #include "Xlib.h"
31: #include "Xutil.h"
32: #include "Intrinsic.h"
33: #include <strings.h>
34: #include "Atoms.h"
35: #include "TM.h"
36: #include "TMprivate.h"
37:
38: /* Private definitions. */
39: #define LF 0x0a
40: #define BSLASH '\\'
41:
42: #define AtomToAction(atom) ((XtAction)StringToQuark(atom))
43:
44: typedef int EventType;
45: typedef unsigned int XtEventType;
46: typedef unsigned int EventCode;
47: typedef unsigned int Value;
48:
49: typedef void (*ActionProc)();
50:
51: typedef struct _EventKey {
52: char *event;
53: XrmQuark signature;
54: EventMask mask;
55: EventType eventType;
56: int detailType;
57: caddr_t detail;
58: }EventKey, *EventKeys;
59:
60: typedef struct {
61: char *name;
62: XrmQuark signature;
63: Value value;
64: } NameValueRec, *NameValueTable;
65:
66: typedef NameValueRec CompiledAction;
67: typedef NameValueTable CompiledActionTable;
68:
69: NameValueRec modifiers[] = {
70: {"Shift", 0, ShiftMask},
71: {"Lock", 0, LockMask},
72: {"Ctrl", 0, ControlMask},
73: {"Mod1", 0, Mod1Mask},
74: {"Mod2", 0, Mod2Mask},
75: {"Mod3", 0, Mod3Mask},
76: {"Mod4", 0, Mod4Mask},
77: {"Mod5", 0, Mod5Mask},
78: {"Meta", 0, Mod1Mask},
79:
80: {"Button1", 0, Button1Mask},
81: {"Button2", 0, Button2Mask},
82: {"Button3", 0, Button3Mask},
83: {"Button4", 0, Button4Mask},
84: {"Button5", 0, Button5Mask},
85:
86: {"Any", 0, AnyModifier},
87:
88: {NULL, NULL, NULL},
89: };
90:
91: NameValueRec buttonNames[] = {
92: {"Button1", 0, Button1},
93: {"Button2", 0, Button2},
94: {"Button3", 0, Button3},
95: {"Button4", 0, Button4},
96: {"Button5", 0, Button5},
97: {NULL, NULL, NULL},
98: };
99:
100: NameValueRec notifyModes[] = {
101: {"Normal", 0, NotifyNormal},
102: {"Grab", 0, NotifyGrab},
103: {"Ungrab", 0, NotifyUngrab},
104: {"WhileGrabbed", 0, NotifyWhileGrabbed},
105: {NULL, NULL, NULL},
106: };
107:
108: NameValueRec notifyDetail[] = {
109: {"Ancestor", 0, NotifyAncestor},
110: {"Virtual", 0, NotifyVirtual},
111: {"Inferior", 0, NotifyInferior},
112: {"Nonlinear", 0, NotifyNonlinear},
113: {"NonlinearVirtual", 0, NotifyNonlinearVirtual},
114: {"Pointer", 0, NotifyPointer},
115: {"PointerRoot", 0, NotifyPointerRoot},
116: {"DetailNone", 0, NotifyDetailNone},
117: {NULL, NULL, NULL},
118: };
119:
120: NameValueRec visibilityNotify[] = {
121: {"Unobscured", 0, VisibilityUnobscured},
122: {"PartiallyObscured", 0, VisibilityPartiallyObscured},
123: {"FullyObscured", 0, VisibilityFullyObscured},
124: {NULL, NULL, NULL},
125: };
126:
127: NameValueRec circulation[] = {
128: {"OnTop", 0, PlaceOnTop},
129: {"OnBottom", 0, PlaceOnBottom},
130: {NULL, NULL, NULL},
131: };
132:
133: NameValueRec propertyChanged[] = {
134: {"NewValue", 0, PropertyNewValue},
135: {"Delete", 0, PropertyDelete},
136: {NULL, NULL, NULL},
137: };
138:
139: #define NEM NoEventMask
140: #define KPM KeyPressMask
141: #define KRM KeyReleaseMask
142: #define BPM ButtonPressMask
143: #define BRM ButtonReleaseMask
144: #define EWM EnterWindowMask
145: #define LWM LeaveWindowMask
146: #define PMM PointerMotionMask
147: #define PHM PointerMotionHintMask
148: #define B1M Button1MotionMask
149: #define B2M Button2MotionMask
150: #define B3M Button3MotionMask
151: #define B4M Button4MotionMask
152: #define B5M Button5MotionMask
153: #define BMM ButtonMotionMask
154: #define KSM KeymapStateMask
155: #define EXM ExposureMask
156: #define VCM VisibilityChangeMask
157: #define STM StructureNotifyMask
158: #define RRM ResizeRedirectMask
159: #define SSM SubstructureNotifyMask
160: #define SRM SubstructureRedirectMask
161: #define FCM FocusChangeMask
162: #define PCM PropertyChangeMask
163: #define CCM ColormapChangeMask
164: #define OGM OwnerGrabButtonMask
165:
166: #define DetailNone 0
167: #define DetailTable 1
168: #define DetailKeySym 2
169: #define DetailImmed 3
170:
171: EventKey events[] = {
172: {"KeyPress", NULL, KPM, KeyPress, DetailKeySym, NULL},
173: {"KeyRelease", NULL, KRM, KeyRelease, DetailKeySym, NULL},
174: {"ButtonPress", NULL, BPM, ButtonPress, DetailTable,(caddr_t)buttonNames},
175: {"ButtonRelease", NULL, BRM, ButtonRelease,DetailTable,(caddr_t)buttonNames},
176: {"MotionNotify", NULL, PMM, MotionNotify, DetailNone, NULL},
177: {"EnterNotify", NULL, EWM, EnterNotify, DetailTable,(caddr_t)notifyModes},
178: {"LeaveNotify", NULL, LWM, LeaveNotify, DetailTable,(caddr_t)notifyModes},
179: {"FocusIn", NULL, FCM, FocusIn, DetailTable,(caddr_t)notifyModes},
180: {"FocusOut", NULL, FCM, FocusOut, DetailTable,(caddr_t)notifyModes},
181: {"KeymapNotify", NULL, KSM, KeymapNotify, DetailNone, NULL},
182: {"Expose", NULL, EXM, Expose, DetailNone, NULL},
183: {"GraphicsExpose", NULL, EXM, GraphicsExpose, DetailNone, NULL},
184: {"NoExpose", NULL, EXM, NoExpose, DetailNone, NULL},
185: {"VisibilityNotify",NULL, VCM, VisibilityNotify,DetailNone, NULL},
186: {"CreateNotify", NULL, STM, CreateNotify, DetailNone, NULL},
187: {"DestroyNotify", NULL, STM, DestroyNotify, DetailNone, NULL},
188: {"UnmapNotify", NULL, STM, UnmapNotify, DetailNone, NULL},
189: {"MapNotify", NULL, STM, MapNotify, DetailNone, NULL},
190: {"MapRequest", NULL, SRM, MapRequest, DetailNone, NULL},
191: {"ReparentNotify", NULL, STM, ReparentNotify, DetailNone, NULL},
192: {"ConfigureNotify", NULL, STM, ConfigureNotify, DetailNone, NULL},
193: {"ConfigureRequest",NULL, SRM, ConfigureRequest,DetailNone, NULL},
194: {"GravityNotify", NULL, STM, GravityNotify, DetailNone, NULL},
195: {"ResizeRequest", NULL, RRM, ResizeRequest, DetailNone, NULL},
196: {"CirculateNotify", NULL, STM, CirculateNotify, DetailNone, NULL},
197: {"CirculateRequest",NULL, SRM, CirculateRequest,DetailNone, NULL},
198: {"PropertyNotify", NULL, PCM, PropertyNotify, DetailNone, NULL},
199: {"SelectionClear", NULL, SRM, SelectionClear, DetailNone, NULL},
200: {"SelectionRequest",NULL, SRM, SelectionRequest,DetailNone, NULL},
201: {"SelectionNotify", NULL, SRM, SelectionNotify, DetailNone, NULL},
202: {"ColormapNotify", NULL, CCM, ColormapNotify, DetailNone, NULL},
203: {"ClientMessage", NULL, 0, ClientMessage, DetailNone, NULL},
204: {"MappingNotify", NULL, 0, 0/*mapping*/, DetailNone, NULL},
205:
206: {"Key", NULL, KPM, KeyPress, DetailKeySym, NULL},
207: {"BtnDown", NULL, BPM, ButtonPress, DetailTable,(caddr_t)buttonNames},
208: {"BtnUp", NULL, BRM, ButtonRelease,DetailTable,(caddr_t)buttonNames},
209: {"Btn1Down", NULL, BPM, ButtonPress, DetailImmed,(caddr_t)Button1},
210: {"Btn1Up", NULL, BRM, ButtonRelease, DetailImmed,(caddr_t)Button1},
211: {"Btn2Down", NULL, BPM, ButtonPress, DetailImmed,(caddr_t)Button2},
212: {"Btn2Up", NULL, BRM, ButtonRelease, DetailImmed,(caddr_t)Button2},
213: {"Btn3Down", NULL, BPM, ButtonPress, DetailImmed,(caddr_t)Button3},
214: {"Btn3Up", NULL, BRM, ButtonRelease, DetailImmed,(caddr_t)Button3},
215: {"Btn4Down", NULL, BPM, ButtonPress, DetailImmed,(caddr_t)Button4},
216: {"Btn4Up", NULL, BRM, ButtonRelease, DetailImmed,(caddr_t)Button4},
217: {"Btn5Down", NULL, BPM, ButtonPress, DetailImmed,(caddr_t)Button5},
218: {"Btn5Up", NULL, BRM, ButtonRelease, DetailImmed,(caddr_t)Button5},
219: {"PtrMoved", NULL, PMM, MotionNotify, DetailNone, NULL},
220: {"MouseMoved", NULL, PMM, MotionNotify, DetailNone, NULL},
221: {"EnterWindow", NULL, EWM, EnterNotify, DetailTable,(caddr_t)notifyModes},
222: {"LeaveWindow", NULL, LWM, LeaveNotify, DetailTable,(caddr_t)notifyModes},
223:
224: { NULL, NULL, NULL, NULL, NULL, NULL}};
225:
226: static Boolean initialized = FALSE;
227:
228: static void FreeEventSeq(event)
229: EventSeqPtr event;
230: {
231: if (event->next != NULL)
232: FreeEventSeq(event->next);
233: XtFree((char *)event->str);
234: XtFree((char *)event);
235: }
236:
237: static void CompileNameValueTable(table)
238: NameValueTable table;
239: {
240: int i;
241:
242: for (i=0; table[i].name; i++)
243: table[i].signature = StringToQuark(table[i].name);
244: }
245:
246: static void Compile_XtEventTable(table)
247: EventKeys table;
248: {
249: int i;
250:
251: for (i=0; table[i].event; i++)
252: table[i].signature = StringToQuark(table[i].event);
253: }
254:
255: static CompiledActionTable CompileActionTable(actions, count)
256: struct _XtActionsRec *actions;
257: Cardinal count;
258: {
259: int i;
260: CompiledActionTable compiledActionTable;
261:
262: compiledActionTable = (CompiledActionTable) XtCalloc(
263: count+1, (unsigned) sizeof(CompiledAction));
264:
265: for (i=0; i<count; i++) {
266: compiledActionTable[i].name = actions[i].string;
267: compiledActionTable[i].signature = AtomToAction(actions[i].string);
268: compiledActionTable[i].value = (Value) actions[i].value;
269: }
270:
271: compiledActionTable[count].name = NULL;
272: compiledActionTable[count].signature = NULL;
273: compiledActionTable[count].value = NULL;
274:
275: return compiledActionTable;
276: }
277:
278: static void FreeCompiledActionTable(compiledActionTable)
279: CompiledActionTable compiledActionTable;
280: {
281: XtFree((char *)compiledActionTable);
282: }
283:
284: static Syntax(str)
285: char *str;
286: {
287: (void) fprintf(stderr,
288: "Translation table syntax error: %s\n", str);
289: }
290:
291:
292:
293: static XtEventType LookupXtEventType(eventStr)
294: char *eventStr;
295:
296: {
297: int i;
298: XrmQuark signature;
299:
300: signature = StringToQuark(eventStr);
301: for (i = 0; events[i].event != NULL; i++)
302: if (events[i].signature == signature) return i;
303:
304: Syntax("Unknown event type.");
305: return i;
306: }
307:
308: #ifdef notdef
309: /* ||| */
310: {
311: /*** Parse the repetitions, for double click... ***/
312: if (strcmp(repsStr, "") != NULL) {
313: EventSeqPtr tempEvent = curEvent;
314: int reps;
315: if (repsStr[0] >= '0' && repsStr[0] <= '9')
316: reps = StrToNum (repsStr);
317: else
318: reps = 1;
319: for (i=1; i<reps; i++) {
320: curEvent->next = (EventSeqPtr) XtMalloc((unsigned)sizeof(EventSeqRec));
321: curEvent = curEvent->next;
322: curEvent->str = NULL;
323: curEvent->next = NULL;
324: curEvent->eventCode = tempEvent->eventCode;
325: curEvent->eventType = tempEvent->eventType;
326: curEvent->modifiersMask = tempEvent->modifiersMask;
327: }
328: }
329: }
330: #endif
331:
332: /***********************************************************************
333: * LookupTableSym
334: * Given a table and string, it fills in the value if found and returns
335: * status
336: ***********************************************************************/
337:
338: static Boolean LookupTableSym(table, name, valueP)
339: NameValueTable table;
340: char *name;
341: Value *valueP;
342: {
343: /* !!! should implement via hash or something else faster than linear search */
344:
345: int i;
346: XrmQuark signature = StringToQuark(name);
347:
348: for (i=0;table[i].name != NULL;i++)
349: if (table[i].signature == signature) {
350: *valueP = table[i].value;
351: return TRUE;
352: }
353:
354: return FALSE;
355: }
356:
357: /***********************************************************************
358: * InterpretAction
359: * Given an action, it returns a pointer to the appropriate procedure.
360: ***********************************************************************/
361:
362: static ActionProc InterpretAction(compiledActionTable, action)
363: CompiledActionTable compiledActionTable;
364: String action;
365: {
366: Value actionProc;
367:
368: if (LookupTableSym(compiledActionTable, action, &actionProc))
369: return (ActionProc) actionProc;
370:
371: return NULL;
372: }
373:
374: static char * ScanAlphanumeric(str)
375: char *str;
376: {
377: while (
378: ('A' <= *str && *str <= 'Z') || ('a' <= *str && *str <= 'z')
379: || ('0' <= *str && *str <= '9')) str++;
380: return str;
381: }
382:
383: static char * ScanIdent(str)
384: char *str;
385: {
386: str = ScanAlphanumeric(str);
387: while (
388: ('A' <= *str && *str <= 'Z')
389: || ('a' <= *str && *str <= 'z')
390: || ('0' <= *str && *str <= '9')
391: || (*str == '-')
392: || (*str == '_')
393: || (*str == '$')
394: ) str++;
395: return str;
396: }
397:
398: static char * ScanWhitespace(str)
399: char *str;
400: {
401: while (*str == ' ' || *str == '\t') str++;
402: return str;
403: }
404:
405: static char * ParseModifiers(str, modifierMaskP, modifierP)
406: char *str;
407: ModifierMask *modifierMaskP;
408: ModifierMask *modifierP;
409: {
410: char *start;
411: char modStr[100];
412: Boolean notFlag;
413: Value maskBit;
414:
415: while (*str != '<') {
416: str = ScanWhitespace(str);
417: if (*str == '~') { notFlag = TRUE; str++; } else notFlag = FALSE;
418: start = str;
419: str = ScanAlphanumeric(str);
420: if (start == str) {
421: Syntax("Modifier or '<' expected.");
422: return str;
423: }
424: (void) strncpy(modStr, start, str-start);
425: modStr[str-start] = '\0';
426: maskBit = 0;
427: if (!LookupTableSym(modifiers, modStr, &maskBit))
428: Syntax("Unknown modifier name.");
429: *modifierMaskP |= maskBit;
430: if (notFlag) *modifierP &= ~maskBit; else *modifierP |= maskBit;
431: }
432: return str;
433: }
434:
435: static char * ParseXtEventType(str, eventTypeP)
436: char *str;
437: XtEventType *eventTypeP;
438: {
439: char *start = str;
440: char eventTypeStr[100];
441:
442: str = ScanAlphanumeric(str);
443: (void) strncpy(eventTypeStr, start, str-start);
444: eventTypeStr[str-start] = '\0';
445: *eventTypeP = LookupXtEventType(eventTypeStr);
446:
447: return str;
448: }
449:
450: static unsigned int StrToHex(str)
451: char *str;
452: {
453: char c;
454: int val = 0;
455:
456: while (c = *str) {
457: if ('0' <= c && c <= '9') val = val*16+c-'0';
458: else if ('a' <= c && c <= 'z') val = val*16+c-'a'+10;
459: else if ('A' <= c && c <= 'Z') val = val*16+c-'A'+10;
460: else return -1;
461: str++;
462: }
463:
464: return val;
465: }
466:
467: static unsigned int StrToOct(str)
468: char *str;
469: {
470: char c;
471: int val = 0;
472:
473: while (c = *str) {
474: if ('0' <= c && c <= '7') val = val*8+c-'0'; else return -1;
475: str++;
476: }
477:
478: return val;
479: }
480:
481: static unsigned int StrToNum(str)
482: char *str;
483: {
484: char c;
485: int val = 0;
486:
487: if (*str == '0') {
488: str++;
489: if (*str == 'x' || *str == 'X') return StrToHex(++str);
490: else return StrToOct(str);
491: }
492:
493: while (c = *str) {
494: if ('0' <= c && c <= '9') val = val*10+c-'0';
495: else return -1;
496: str++;
497: }
498:
499: return val;
500: }
501:
502: static KeySym XStringToKeySym(str)
503: char *str;
504: {
505:
506: /* ||| replace this with real one when xlib has it... */
507:
508: if (str == NULL) return (KeySym) 0;
509: if ('0' <= *str && *str <= '9') return (KeySym) StrToNum(str);
510: if ('A' <= *str && *str <= 'Z') return (KeySym) *str+'a'-'A';
511: return (KeySym) *str;
512: }
513:
514: static char * ParseKeySym(str, eventCodeMaskP, eventCodeP)
515: char *str;
516: EventCode *eventCodeMaskP;
517: EventCode *eventCodeP;
518: {
519: char keySymName[100], *start;
520:
521: str = ScanWhitespace(str);
522:
523: if (*str == '\\') {
524: str++;
525: keySymName[0] = *str;
526: str++;
527: keySymName[1] = '\0';
528: *eventCodeP = XStringToKeySym(keySymName);
529: *eventCodeMaskP = ~0L;
530: } else if (*str == ',' || *str == ':') {
531: /* no detail */
532: *eventCodeP = 0L;
533: *eventCodeMaskP = 0L;
534: } else {
535: start = str;
536: while (*str != ',' && *str != ':') str++;
537: (void) strncpy(keySymName, start, str-start);
538: keySymName[str-start] = '\0';
539: *eventCodeP = XStringToKeySym(keySymName);
540: *eventCodeMaskP = ~0L;
541: }
542:
543: return str;
544: }
545:
546:
547: static char * ParseTableSym(str, table, eventCodeMaskP, eventCodeP)
548: char *str;
549: NameValueTable table;
550: EventCode *eventCodeMaskP;
551: EventCode *eventCodeP;
552: {
553: char *start = str;
554: char tableSymName[100];
555:
556: *eventCodeP = 0L;
557: str = ScanAlphanumeric(str);
558: if (str == start) {*eventCodeMaskP = 0L; return str; }
559: (void) strncpy(tableSymName, start, str-start);
560: tableSymName[str-start] = '\0';
561: if (! LookupTableSym(table, tableSymName, eventCodeP))
562: Syntax("Unknown Detail Type.");
563: *eventCodeMaskP = ~0L;
564:
565: return str;
566: }
567:
568:
569: static char * ParseDetail(str, eventType, eventCodeMaskP, eventCodeP)
570: char *str;
571: XtEventType eventType;
572: EventCode *eventCodeMaskP;
573: EventCode *eventCodeP;
574: {
575: switch (events[eventType].detailType) {
576:
577: case DetailImmed:
578: *eventCodeMaskP = ~0L;
579: *eventCodeP = (EventCode) events[eventType].detail;
580: return str;
581:
582: case DetailKeySym:
583: str = ParseKeySym(str, eventCodeMaskP, eventCodeP);
584: return str;
585:
586: case DetailTable:
587: str = ParseTableSym(
588: str, (NameValueTable)events[eventType].detail,
589: eventCodeMaskP, eventCodeP);
590: return str;
591:
592: default:
593: *eventCodeMaskP = 0L;
594: *eventCodeP = 0L;
595: return str;
596: }
597: }
598:
599:
600: static char * ParseEvent(str, eventP)
601: char *str;
602: EventSeqPtr eventP;
603: {
604: ModifierMask modifierMask = 0;
605: ModifierMask modifiers = 0;
606: XtEventType eventType = 0;
607: EventCode eventCodeMask = 0L;
608: EventCode eventCode = 0L;
609:
610: str = ParseModifiers(str, &modifierMask, &modifiers);
611: if (*str != '<') Syntax("Missing '<'"); else str++;
612: str = ParseXtEventType(str, &eventType);
613: if (*str != '>') Syntax("Missing '>'"); else str++;
614: str = ParseDetail(str, eventType, &eventCodeMask, &eventCode);
615:
616: eventP->modifierMask = modifierMask;
617: eventP->modifiers = modifiers;
618: eventP->eventType = (EventType)eventType;
619: eventP->eventCodeMask = eventCodeMask;
620: eventP->eventCode = eventCode;
621:
622: return str;
623: }
624:
625: static char * ParseQuotedStringEvent(str, eventP)
626: char *str;
627: EventSeqPtr eventP;
628: {
629: int j;
630:
631: ModifierMask ctrlMask;
632: ModifierMask metaMask;
633: ModifierMask shiftMask;
634: char c;
635: char s[2];
636:
637: (void) LookupTableSym(modifiers, "Ctrl", (Value *) &ctrlMask);
638: (void) LookupTableSym(modifiers, "Meta", (Value *) &metaMask);
639: (void) LookupTableSym(modifiers, "Shift", (Value *) &shiftMask);
640:
641: eventP->modifierMask = ctrlMask | metaMask | shiftMask;
642:
643: for (j=0; j < 2; j++)
644: if (*str=='^' && !(eventP->modifiers | ctrlMask)) {
645: str++;
646: eventP->modifiers |= ctrlMask;
647: } else if (*str == '$' && !(eventP->modifiers | metaMask)) {
648: str++;
649: eventP->modifiers |= metaMask;
650: } else if (*str == '\\') {
651: str++;
652: c = *str;
653: str++;
654: break;
655: } else {
656: c = *str;
657: str++;
658: break;
659: }
660: eventP->eventType = (EventType) LookupXtEventType("Key");
661: if ('A' <= c && c <= 'Z') {
662: eventP->modifiers |= shiftMask;
663: c += 'a' - 'A';
664: }
665: s[0] = c;
666: s[1] = '\0';
667: eventP->eventCode = XStringToKeySym(s);
668:
669: return str;
670: }
671:
672:
673: /***********************************************************************
674: * ParseEventSeq
675: * Parses the left hand side of a translation table production
676: * up to, and consuming the ":".
677: * Takes a pointer to a char* (where to start parsing) and returns an
678: * event seq (in a passed in variable), having updated the char *
679: **********************************************************************/
680:
681: static char *ParseEventSeq(str, eventSeqP)
682: char *str;
683: EventSeqPtr *eventSeqP;
684: {
685: EventSeqPtr *nextEventP = eventSeqP;
686:
687: *eventSeqP = NULL;
688:
689: while (*str != ':') {
690: EventSeqPtr event;
691:
692: event = (EventSeqPtr) XtMalloc((unsigned)sizeof(EventSeqRec));
693: event->str = NULL;
694: event->modifierMask = 0;
695: event->modifiers = 0;
696: event->eventType = 0;
697: event->eventCodeMask = 0L;
698: event->eventCode = 0L;
699: event->next = NULL;
700: event->actions = NULL;
701:
702: if (*str == '"') {
703: str++;
704: while (*str != '"') {
705: str = ParseQuotedStringEvent(str, event);
706: *nextEventP = event;
707: nextEventP = &event->next;
708: }
709: str++;
710: } else {
711: str = ParseEvent(str, event);
712: *nextEventP = event;
713: nextEventP = &event->next;
714: }
715: str = ScanWhitespace(str);
716: if (*str != ':')
717: if (*str != ',') {
718: Syntax("',' expected.");
719: } else str++;
720: }
721: str++;
722:
723: return str;
724: }
725:
726:
727: static char * ParseActionProc(str, actionProcP, actionProcNameP)
728: char *str;
729: ActionProc *actionProcP;
730: char **actionProcNameP;
731: {
732: char *start = str;
733: char procName[100];
734:
735: str = ScanIdent(str);
736: (void) strncpy(procName, start, str-start);
737: procName[str-start] = '\0';
738:
739: /* ||| */
740: /*
741: if (! LookupTableSym(procName, actions, actionProcP))
742: Syntax("Unkown action proc.");
743: */
744: *actionProcP = NULL;
745: *actionProcNameP = strncpy(
746: XtMalloc((unsigned)(str-start+1)), procName, str-start+1);
747: return str;
748: }
749:
750:
751: static char * ParseParamSeq(str, paramSeqP, paramNumP)
752: char *str;
753: char ***paramSeqP;
754: unsigned long *paramNumP;
755: {
756: /* ||| */
757: *paramSeqP = NULL;
758: *paramNumP = 0;
759:
760: return str;
761: }
762:
763: static char * ParseAction(str, actionP)
764: char *str;
765: ActionPtr actionP;
766: {
767: str = ParseActionProc(str, &actionP->proc, &actionP->token);
768: if (*str == '(') {
769: str++;
770: str = ParseParamSeq(str, &actionP->param, &actionP->paramNum);
771: } else { Syntax("Missing '('"); }
772: if (*str == ')') str++; else Syntax("Missing ')'");
773:
774: return str;
775: }
776:
777:
778: static char *ParseActionSeq(str, actionsP)
779: char *str;
780: ActionPtr *actionsP;
781: {
782: ActionPtr *nextActionP = actionsP;
783:
784: *actionsP = NULL;
785:
786: while (*str != '\0') {
787: ActionPtr action;
788:
789: action = (ActionPtr) XtMalloc((unsigned)sizeof(ActionRec));
790: action->token = NULL;
791: action->proc = NULL;
792: action->param = NULL;
793: action->paramNum = 0;
794: action->next = NULL;
795:
796: str = ParseAction(str, action);
797: str = ScanWhitespace(str);
798: *nextActionP = action;
799: nextActionP = &action->next;
800: }
801:
802: return str;
803: }
804:
805:
806: /***********************************************************************
807: * ParseTranslationTableProduction
808: * Parses one line of event bindings.
809: ***********************************************************************/
810:
811: static void ParseTranslationTableProduction(w, compiledActionTable, str)
812: Widget w;
813: CompiledActionTable compiledActionTable;
814: char *str;
815: {
816: EventSeqPtr eventSeq = NULL;
817: ActionPtr actions = NULL;
818:
819: EventSeqPtr esp;
820: ActionPtr ap;
821:
822: str = ParseEventSeq(str, &eventSeq);
823: str = ScanWhitespace(str);
824: str = ParseActionSeq(str, &actions);
825:
826: for (esp=eventSeq; esp!=NULL; esp=esp->next) {
827: XtAddEventHandler(
828: w,
829: events[esp->eventType].mask,
830: (Boolean) (events[esp->eventType].mask == 0),
831: TranslateEvent, (Opaque) NULL);
832: #ifdef ndef
833: /* double click needs to make sure that you have selected on both
834: button down and up. */
835: if (events[esp->eventType].mask & ButtonPressMask)
836: XtAddEventHandler(
837: w, ButtonReleaseMask, FALSE, TranslateEvent, NULL);
838: if (events[esp->eventType].mask & ButtonReleaseMask)
839: XtAddEventHandler(
840: w, ButtonPressMask, FALSE, TranslateEvent, NULL);
841: #endif
842: if (esp->next == NULL) {
843: /* put the action procs in at the end */
844: esp->actions = actions;
845: }
846: /* change translation manager events into real x events */
847: esp->eventType = events[esp->eventType].eventType;
848: /* don't use esp->eventType as an index into event from here on... */
849: w->core.translations->eventObjTbl = EventMapObjectCreate(
850: w->core.translations, esp);
851: }
852:
853: /* run down the action list, binding action names to procs */
854: for (ap=actions; ap!=NULL; ap=ap->next) {
855: ap->proc = InterpretAction(compiledActionTable, ap->token);
856: }
857:
858: /* add the events and actions to the state table */
859: w->core.translations->eventObjTbl = EventMapObjectSet(
860: w->core.translations, eventSeq);
861:
862: FreeEventSeq(eventSeq);
863:
864: }
865:
866: /*
867: * Parses a user's or applications translation table
868: */
869:
870: static void ParseTranslationTable(w, compiledActionTable)
871: Widget w;
872: CompiledActionTable compiledActionTable;
873: {
874: char **translationTableSource = (char **)w->core.translations;
875: int i;
876:
877: w->core.translations =
878: (_XtTranslations) XtMalloc((unsigned) sizeof(TranslationData));
879: w->core.translations->numEvents = 0;
880: w->core.translations->eventTblSize = 0;
881: w->core.translations->eventObjTbl = NULL;
882:
883: /* !!! need some way of setting this !!! */
884: w->core.translations->clickTime = 50;
885:
886: i = 0;
887: while (translationTableSource[i]) {
888: ParseTranslationTableProduction(
889: w, compiledActionTable, translationTableSource[i]);
890: i++;
891: }
892:
893: }
894:
895: /*** public procedures ***/
896:
897: void DefineTranslation(w)
898: Widget w;
899: {
900: /* this procedure assumes that there is a string table in the */
901: /* core.translations field. It compiles it, combines it with */
902: /* the action bindings and puts the resulting internal data */
903: /* structure into the core.translations field. Note that this means */
904: /* that if you call DefineTranslation twice, bad things will happen */
905:
906: CompiledActionTable compiledActionTable;
907:
908: if (w->core.widget_class->core_class.actions == NULL) return;
909:
910: compiledActionTable =
911: CompileActionTable(
912: w->core.widget_class->core_class.actions,
913: w->core.widget_class->core_class.num_actions);
914: ParseTranslationTable(w, compiledActionTable);
915: FreeCompiledActionTable(compiledActionTable);
916:
917:
918: /* double click needs to make sure that you have selected on both
919: button down and up. */
920: #ifdef ndef
921: if (w->core.event_mask & ButtonPressMask ||
922: w->core.event_mask & ButtonReleaseMask)
923: w->core.event_mask |= ButtonPressMask | ButtonReleaseMask;
924: #endif
925: }
926:
927: void TranslateInitialize()
928: {
929: if (initialized) return;
930:
931: initialized = TRUE;
932:
933: Compile_XtEventTable( events );
934: CompileNameValueTable( modifiers );
935: CompileNameValueTable( buttonNames );
936: CompileNameValueTable( notifyModes );
937: CompileNameValueTable( notifyDetail );
938: CompileNameValueTable( visibilityNotify );
939: CompileNameValueTable( circulation );
940: CompileNameValueTable( propertyChanged );
941: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.