|
|
1.1 root 1: /* $Header: Actions.c,v 1.1 87/09/11 07:57:01 toddb Exp $ */
2: #ifndef lint
3: static char *sccsid = "@(#)Actions.c 1.12 2/25/87";
4: #endif lint
5:
6: /*
7: * Copyright 1987 by Digital Equipment Corporation, Maynard, Massachusetts.
8: *
9: * All Rights Reserved
10: *
11: * Permission to use, copy, modify, and distribute this software and its
12: * documentation for any purpose and without fee is hereby granted,
13: * provided that the above copyright notice appear in all copies and that
14: * both that copyright notice and this permission notice appear in
15: * supporting documentation, and that the name of Digital Equipment
16: * Corporation not be used in advertising or publicity pertaining to
17: * distribution of the software without specific, written prior permission.
18: *
19: *
20: * DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
21: * ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
22: * DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
23: * ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
24: * WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
25: * ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
26: * SOFTWARE.
27: */
28:
29: /* Actions.c -- parse all X events into widget specific actions. */
30:
31: #include <stdio.h>
32: #include "Xlib.h"
33: #include "Xutil.h"
34: #include "Intrinsic.h"
35: #include <strings.h>
36: #include "Atoms.h"
37:
38: /* Private definitions. */
39:
40: #define NUMBUTTONS 3
41: #define NUMKEYS 256
42: #define HASH(x) (((unsigned long)(x)) % NUMKEYS)
43: #define LF 0x0a
44: #define BSLASH '\\'
45:
46: /* X10 Compatibility sillyness stuff (that should go away ...) */
47:
48: #define MetaMask Mod1Mask
49:
50: typedef enum UpDown {down, up};
51:
52: typedef struct _EventSeqRec {
53: unsigned long eventCode;
54: unsigned long eventType;
55: short modeBits, modeMask;
56: XtActionTokenPtr token;
57: struct _EventSeqRec *next;
58: } EventSeqRec, *EventSeqPtr;
59:
60: typedef struct _TranslationRec {
61: XContext context;
62: EventSeqPtr *eventTable;
63: XtActionsPtr actionTable;
64: } TranslationRec;
65:
66: typedef struct {
67: char *event;
68: XContext context;
69: short mode;
70: unsigned long eventType;
71: }EventKey, *EventKeys;
72:
73: EventKey events[] = {
74: {"Key", NULL, 0, KeyPress},
75: {"Ctrl", NULL, ControlMask, KeyPress},
76: {"Meta", NULL, MetaMask, KeyPress},
77: {"Shift", NULL, ShiftMask, KeyPress},
78: {"BtnDown", NULL, 0, ButtonPress},
79: {"BtnUp", NULL, 0, ButtonRelease},
80: {"PtrMoved", NULL, 0, MotionNotify},
81: {"KeyPress", NULL, 0, KeyPress},
82: {"KeyRelease", NULL, 0, KeyRelease},
83: {"ButtonPress", NULL, 0, ButtonPress},
84: {"ButtonRelease", NULL, 0, ButtonRelease},
85: {"MouseMoved", NULL, 0, MotionNotify},
86: {"MotionNotify", NULL, 0, MotionNotify},
87: {"EnterWindow", NULL, 0, EnterNotify},
88: {"LeaveWindow", NULL, 0, LeaveNotify},
89: {"FocusIn", NULL, 0, FocusIn},
90: {"FocusOut", NULL, 0, FocusOut},
91: {"KeymapNotify", NULL, 0, KeymapNotify},
92: {"Expose", NULL, 0, Expose},
93: {"GraphicsExpose", NULL, 0, GraphicsExpose},
94: {"NoExpose", NULL, 0, NoExpose},
95: {"VisibilityNotify",NULL, 0, VisibilityNotify},
96: {"CreateNotify", NULL, 0, CreateNotify},
97: {"DestroyNotify", NULL, 0, DestroyNotify},
98: {"UnmapNotify", NULL, 0, UnmapNotify},
99: {"MapNotify", NULL, 0, MapNotify},
100: {"MapRequest", NULL, 0, MapRequest},
101: {"ReparentNotify", NULL, 0, ReparentNotify},
102: {"ConfigureNotify", NULL, 0, ConfigureNotify},
103: {"ConfigureRequest",NULL, 0, ConfigureRequest},
104: {"GravityNotify", NULL, 0, GravityNotify},
105: {"ResizeRequest", NULL, 0, ResizeRequest},
106: {"CirculateNotify", NULL, 0, CirculateNotify},
107: {"CirculateRequest",NULL, 0, CirculateRequest},
108: {"PropertyNotify", NULL, 0, PropertyNotify},
109: {"SelectionClear", NULL, 0, SelectionClear},
110: {"SelectionRequest",NULL, 0, SelectionRequest},
111: {"SelectionNotify", NULL, 0, SelectionNotify},
112: {"ColormapNotify", NULL, 0, ColormapNotify},
113: {"ClientMessage", NULL, 0, ClientMessage},
114: { NULL, NULL, NULL, NULL}
115: };
116:
117: static Boolean initialized = FALSE;
118: static Boolean parseError;
119:
120: void ActionsInitialize()
121: {
122: int i;
123: void CvtStringToEventBindings();
124:
125: if (initialized)
126: return;
127: initialized = TRUE;
128:
129: for (i = 0; events[i].event != NULL; i++)
130: events[i].context = XAtomToContext(events[i].event);
131: XrmRegisterTypeConverter(XrmRString, XtREventBindings,
132: CvtStringToEventBindings);
133: }
134:
135: static int StrToNum(s)
136: char *s;
137: {
138: int base = 10;
139: register int val = 0;
140: register int c;
141: if (*s == '0') {
142: s++;
143: if (*s == 'x' || *s == 'X') {
144: base = 16;
145: s++;
146: } else
147: base = 8;
148: }
149: while (*s)
150: switch (c = *s++) {
151: case '0':
152: case '1':
153: case '2':
154: case '3':
155: case '4':
156: case '5':
157: case '6':
158: case '7':
159: val = (val * base) + (c - '0');
160: break;
161: case '8':
162: case '9':
163: if (base < 10)
164: return -1;
165: val = (val * base) + (c - '0');
166: break;
167: case 'a':
168: case 'b':
169: case 'c':
170: case 'd':
171: case 'e':
172: case 'f':
173: if (base != 16)
174: return -1;
175: val = (val * base) + (c - 'a' + 10);
176: break;
177: case 'A':
178: case 'B':
179: case 'C':
180: case 'D':
181: case 'E':
182: case 'F':
183: if (base != 16)
184: return -1;
185: val = (val * base) + (c - 'A' + 10);
186: break;
187: default:
188: return -1;
189: }
190: return val;
191: }
192:
193: static Syntax(str)
194: char *str;
195: {
196: (void) fprintf(stderr,
197: "Event Sequence description error (ignored): %s\n", str);
198: }
199:
200: static EventSeqPtr *NewEventTable()
201: {
202: EventSeqPtr *eventTable;
203: int i;
204:
205: eventTable = (EventSeqPtr *) XtMalloc(sizeof(EventSeqPtr)* NUMKEYS);
206: for (i = 0; i < NUMKEYS; i++)
207: eventTable[i] = (EventSeqPtr) NULL;
208: return eventTable;
209: }
210:
211: static XtActionTokenPtr FindAction(list, modeBits, eventCode, eventType)
212: EventSeqPtr list;
213: short modeBits;
214: register int eventCode, eventType;
215: {
216: register EventSeqPtr ptr;
217:
218: for (ptr = list; ptr != NULL; ptr = ptr->next) {
219: if ((ptr->eventCode == eventCode) &&
220: (ptr->eventType == eventType) &&
221: (ptr->modeBits == (modeBits & ptr->modeMask)))
222: return ptr->token;
223: }
224: return NULL;
225: }
226:
227: static MakeKeyOrButtonEntry(list, modeBits, modeMask, eventCode, eventType, token)
228: EventSeqPtr *list;
229: short modeBits, modeMask;
230: unsigned long eventCode, eventType;
231: XtActionTokenPtr token;
232: {
233: register EventSeqPtr ptr;
234:
235: ptr = (EventSeqPtr) XtMalloc(sizeof(EventSeqRec));
236: ptr->eventCode = eventCode;
237: ptr->eventType = eventType;
238: ptr->modeBits = modeBits;
239: ptr->modeMask = modeMask;
240: ptr->token = token;
241: ptr->next = *list;
242: *list = ptr;
243: }
244:
245: static int ButtonMaskFromString(str)
246: char *str;
247: {
248: switch (StrToNum(str)) {
249: case 1:
250: return Button1Mask;
251: case 2:
252: return Button2Mask;
253: case 3:
254: return Button3Mask;
255: case 4:
256: return Button4Mask;
257: case 5:
258: return Button5Mask;
259: }
260: if (strcmp(str, "left") == 0) return Button1Mask;
261: if (strcmp(str, "middle") == 0) return Button2Mask;
262: if (strcmp(str, "right") == 0) return Button3Mask;
263:
264: return 0;
265: }
266:
267: static int ButtonFromString(str)
268: char *str;
269: {
270: switch (ButtonMaskFromString(str)) {
271: case Button1Mask:
272: return Button1;
273: case Button2Mask:
274: return Button2;
275: case Button3Mask:
276: return Button3;
277: case Button4Mask:
278: return Button4;
279: case Button5Mask:
280: return Button5;
281: }
282:
283: parseError = TRUE;
284: return 0;
285: }
286:
287: /*
288: static StringToToken(table, str, token)
289: XtActionsPtr table;
290: char *str;
291: int *token;
292: {
293: register XtActionsPtr tab = table;
294: while (tab->string) {
295: if (strcmp(tab->string, str) == 0) {
296: *token = tab->value;
297: return TRUE;
298: }
299: tab++;
300: }
301: return FALSE;
302: }
303: */
304:
305: static Boolean ParseChar(s, c)
306: char **s;
307: char *c;
308: {
309: Boolean result = FALSE;
310: register char *ptr;
311:
312: ptr = *s;
313: *c = *ptr++;
314: if (*c == '\\') {
315: result = TRUE;
316: *c = *ptr++;
317: switch (*c) {
318: case 't': *c = '\t'; break;
319: case 'n': *c = '\n'; break;
320: case 'r': *c = '\r'; break;
321: case 'e': *c = '\033'; break;
322: }
323: if (*c >= '0' && *c <= '9') {
324: *c = (*c - '0') * 64 + (ptr[0] - '0') * 8 + ptr[1] - '0';
325: ptr += 2;
326: }
327: }
328: *s = ptr;
329: return result;
330: }
331:
332:
333: static ParseEventSequenceBinding(str, tbl)
334: char *str;
335: EventSeqPtr *tbl;
336: {
337: char str2[500], modeStr[50], typeStr[50], detailStr[50];
338: char *ptr, *ptr2, c;
339: Boolean backSlash;
340: int modeBits, modeMask, i, code;
341: Boolean notFlag, done;
342: XtActionTokenPtr tok, lasttok, firsttok;
343: unsigned long eventType;
344: XContext eventContext;
345:
346: ptr = str;
347: modeStr[0] = 0;
348: typeStr[0] = 0;
349: detailStr[0] = 0;
350: parseError = FALSE;
351: ptr2 = modeStr;
352: while (*ptr != ':') { /* find end of lhs and collect pieces */
353: switch (*ptr) {
354: case 0:
355: case LF:
356: Syntax(str);
357: return;
358:
359: case BSLASH:
360: ptr++;
361: *ptr2++ = *ptr++;
362: break;
363: case '<':
364: *ptr2 = 0;
365: ptr2 = typeStr;
366: ptr++;
367: break;
368: case '>':
369: *ptr2 = 0;
370: ptr2 = detailStr;
371: ptr++;
372: break;
373: default:
374: *ptr2++ = *ptr++;
375: }
376: }
377: *ptr2 = 0;
378: ptr++; /* step over ':' */
379: /* process mode flags */
380: ptr2 = modeStr;
381: notFlag = FALSE;
382: code = 0;
383: modeBits = 0;
384: modeMask = 0;
385: while (*(ptr2)) {
386: switch (*ptr2) {
387: case '~':
388: notFlag = TRUE;
389: break;
390: case 'c':
391: modeMask |= ControlMask;
392: if (notFlag)
393: modeBits &= ~ControlMask;
394: else
395: modeBits |= ControlMask;
396: notFlag = FALSE;
397: break;
398: case 'm':
399: modeMask |= MetaMask;
400: if (notFlag)
401: modeBits &= ~MetaMask;
402: else
403: modeBits |= MetaMask;
404: notFlag = FALSE;
405: break;
406: case 's':
407: modeMask |= ShiftMask;
408: if (notFlag)
409: modeBits &= ~ShiftMask;
410: else
411: modeBits |= ShiftMask;
412: notFlag = FALSE;
413: break;
414: case 'l':
415: modeMask |= LockMask;
416: if (notFlag)
417: modeBits &= ~LockMask;
418: else
419: modeBits |= LockMask;
420: notFlag = FALSE;
421: break;
422: case '1':
423: case '2':
424: case '3':
425: case '4':
426: case '5':
427: str2[0] = *ptr2;
428: str2[1] = '\0';
429: i = ButtonMaskFromString(str2);
430: modeMask |= i;
431: if (notFlag)
432: modeBits &= ~i;
433: else
434: modeBits |= i;
435: break;
436:
437: default:
438: Syntax (str);
439: return;
440:
441: }
442: ptr2++;
443: }
444: if (detailStr[0] >= '0' && detailStr[0] <= '9')
445: code = StrToNum (detailStr);
446: /* check for valid event type and set detail */
447: eventType = 0;
448: eventContext = XAtomToContext(typeStr);
449: for (i = 0; events[i].event != NULL; i++) {
450: if (events[i].context == eventContext) {
451: modeBits |= events[i].mode;
452: modeMask |= events[i].mode;
453: eventType = events[i].eventType;
454: break;
455: }
456: }
457: switch (eventType) {
458: case KeyPress:
459: case KeyRelease:
460: if (detailStr[0] >= '0' && detailStr[0] <= '9')
461: code = StrToNum (detailStr);
462: else code = (detailStr[0] >= 'A' && detailStr[0] <= 'Z') ?
463: (detailStr[0] + 'a' - 'A') : detailStr[0];
464: break;
465: case ButtonPress:
466: code = ButtonFromString (detailStr);
467: break;
468: case ButtonRelease:
469: code = ButtonFromString (detailStr);
470: break;
471: case MotionNotify:
472: code = 0;
473: modeBits |= ButtonMaskFromString(detailStr);
474: modeMask |= ButtonMaskFromString(detailStr);
475: break;
476: case 0:
477: Syntax(str);
478: return;
479: }
480: done = FALSE;
481: lasttok = NULL;
482: firsttok = NULL;
483: /* now process rhs */
484: while (*ptr) {
485: tok = (XtActionTokenPtr) XtMalloc (sizeof (XtActionTokenRec));
486: tok->next = NULL;
487: while (*ptr == ' ' || *ptr == '\t')
488: ptr++;
489: switch (*ptr) {
490: case '\n':
491: case '#':
492: case 0:
493: done = TRUE;
494: XtFree ((char *) tok);
495: break;
496: case '\'':
497: ptr++;
498: (void) ParseChar (&ptr, &c);
499: if (*ptr != '\'') {
500: Syntax (str);
501: return;
502: }
503: tok->type = XttokenChar;
504: tok->value.c = c;
505: ptr++;
506: break;
507: case '"':
508: ptr++;
509: ptr2 = str2;
510: while (1) {
511: backSlash = ParseChar (&ptr, ptr2);
512: if (!backSlash && *ptr2 == '"')
513: break;
514: if (!backSlash && *ptr2 == '\n') {
515: Syntax (str);
516: return;
517: }
518: ptr2++;
519: }
520: *ptr2 = 0;
521: tok->type = XttokenString;
522: tok->value.str =
523: strcpy (XtMalloc ((unsigned) strlen (str2) + 1), str2);
524: break;
525: default:
526: ptr2 = str2;
527: do {
528: (void) ParseChar (&ptr, ptr2);
529: c = *ptr2++;
530: } while (c != ' ' && c != '\t' && c != '\n' && c != 0);
531: *--ptr2 = 0;
532: tok->type = XttokenAction;
533: tok->value.action = XtAtomToAction (str2);
534: }
535: if (!done && tok) {
536: if (lasttok)
537: lasttok->next = tok;
538: else
539: firsttok = tok;
540: lasttok = tok;
541: }
542: }
543: /* set action based on eventType */
544: if (parseError)
545: Syntax(str);
546: else
547: MakeKeyOrButtonEntry (&tbl[HASH(code)], modeBits, modeMask,
548: code, eventType, firsttok);
549:
550: }
551:
552: /*ARGSUSED*/
553: void CvtStringToEventBindings(dpy, fromVal, toVal)
554: Display *dpy;
555: XrmValue fromVal;
556: XrmValue *toVal;
557: {
558: FILE *fid;
559: char str[1024];
560: static EventSeqPtr *eventTable; /* ||| STATIC */
561: extern char *getenv();
562:
563: (void) sprintf (str, "%s/%s", getenv ("HOME"), (char *) fromVal.addr);
564: fid = fopen (str, "r");
565: if (fid == NULL) {
566: (void) strcpy (str, LIBDIR);
567: (void) strcat (str, (char *) fromVal.addr);
568: fid = fopen (str, "r");
569: if (fid == NULL) {
570: (void) fprintf (stderr,
571: " Can't find Event Bindings file: %s, using defaults\n",
572: fromVal.addr);
573: return;
574: }
575: }
576: eventTable = NewEventTable();
577: while (!feof (fid)) {
578: (void) fgets (str, 1020, fid);
579: if (str[0] != '#')
580: ParseEventSequenceBinding(str, eventTable);
581: }
582: (void) fclose(fid);
583: (*toVal).size = sizeof(caddr_t);
584: (*toVal).addr = (caddr_t) &eventTable;
585: }
586:
587: /* Public routines. */
588:
589: XtEventsPtr XtParseEventBindings(stringTable)
590: register char **stringTable;
591: {
592: register int i = 0;
593: register EventSeqPtr *eventTable;
594:
595: eventTable = NewEventTable();
596: while (stringTable[i]) {
597: ParseEventSequenceBinding(stringTable[i], eventTable);
598: i++;
599: }
600: return (XtEventsPtr)eventTable;
601: }
602:
603: caddr_t XtSetActionBindings(dpy, eventTable, actionTable, defaultValue)
604: Display *dpy;
605: XtEventsPtr eventTable;
606: register XtActionsPtr actionTable;
607: caddr_t defaultValue;
608: {
609: register XContext context;
610: register TranslationPtr state;
611:
612: state = (TranslationPtr)XtMalloc(sizeof(TranslationRec));
613: context = XUniqueContext();
614: state->actionTable = actionTable;
615: state->eventTable = (EventSeqPtr *) eventTable;
616: while (actionTable->string) {
617: (void) XSaveContext (
618: dpy, (Window) XtAtomToAction (actionTable->string),
619: context, (caddr_t) actionTable->value);
620: actionTable++;
621: }
622: (void) XSaveContext (dpy, (Window) NULL, context, defaultValue);
623: state->context = context;
624: return (caddr_t) state;
625: }
626:
627: XtActionTokenPtr XtTranslateEvent(event, state)
628: register XEvent *event;
629: TranslationPtr state;
630: {
631: register XtActionTokenPtr result;
632: static XtActionTokenRec temp;
633: static char str[1024]; /* !!! STATIC ||| */
634: register int code;
635: register int modeBits;
636: int n;
637:
638: result = NULL;
639: code = 0;
640: modeBits = 0;
641: switch (event->type) {
642: case KeyPress:
643: case KeyRelease:
644: code = XLookupKeysym(&event->xkey, 0);
645: modeBits = event->xkey.state;
646: break;
647: case ButtonPress:
648: case ButtonRelease:
649: code = event->xbutton.button;
650: modeBits = event->xbutton.state;
651: break;
652: case MotionNotify:
653: modeBits = event->xmotion.state;
654: break;
655: case EnterNotify:
656: case LeaveNotify:
657: modeBits = event->xcrossing.state;
658: break;
659: }
660: result = FindAction (state->eventTable[HASH(code)], modeBits, code, event->type);
661: if (result == NULL &&
662: (event->type == KeyPress || event->type == KeyRelease)) {
663: n = XLookupString((XKeyEvent *)event, str, sizeof(str),
664: (KeySym *)NULL, (XComposeStatus *)NULL);
665: if (n == 0)
666: result = NULL;
667: else {
668: str[n] = 0;
669: temp.value.str = str;
670: temp.type = XttokenString;
671: temp.next = NULL;
672: result = &temp;
673: }
674: }
675: return result;
676: }
677:
678:
679: caddr_t XtInterpretAction(dpy, state, action)
680: Display *dpy;
681: TranslationPtr state;
682: XtAction action;
683: {
684: caddr_t result;
685: if (XFindContext(
686: dpy, (Window) action, state->context, (caddr_t *) &result))
687: (void) XFindContext(dpy, (Window) NULL, state->context,
688: (caddr_t *) &result);
689: return result;
690: }
691:
692:
693: XtAddAction(dpy, context, string, action)
694: Display *dpy;
695: XContext context;
696: char *string;
697: int action;
698: {
699: (void) XSaveContext(dpy, (Window) XAtomToContext(string),
700: context, (caddr_t) action);
701: }
702:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.