|
|
1.1 root 1: #ifndef lint
2: static char rcsid[] = "$Header: TMstate.c,v 1.9 87/09/11 21:24:37 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: /* TMstate.c -- maintains the state table of actions for the translation
28: * manager.
29: */
30:
31: #include "Xlib.h"
32: #include "Intrinsic.h"
33: #include "Atoms.h"
34: #include "TM.h"
35: #include "TMprivate.h"
36:
37: extern char *strcpy();
38:
39: static void FreeActionRecs(action)
40: ActionPtr action;
41: {
42: int i;
43: if (action->next != NULL)
44: FreeActionRecs(action->next);
45: if (action->param != NULL)
46: for (i=0; i<action->paramNum; i++)
47: XtFree(action->param[i]);
48: XtFree(action->token);
49: XtFree((char *)action->param);
50: XtFree((char *)action);
51: }
52:
53:
54: static void FreeStateRecs(state)
55: StatePtr state;
56: {
57: if (state->next != NULL)
58: FreeStateRecs(state->next);
59: if (state->nextLevel != NULL)
60: FreeStateRecs(state->nextLevel);
61: if (state->actions != NULL)
62: FreeActionRecs(state->actions);
63: XtFree((char *)state->actions);
64: XtFree((char *)state->next);
65: XtFree((char *)state->nextLevel);
66: }
67:
68: static void PrintModifiers(mask, mod)
69: unsigned long mask, mod;
70: {
71: if (mask & ShiftMask)
72: (void) printf("<%sShift>", ((mod & ShiftMask) ? "" : "~"));
73: if (mask & ControlMask)
74: (void) printf("<%sCtrl>", ((mod & ControlMask) ? "" : "~"));
75: if (mask & LockMask)
76: (void) printf("<%sLock>", ((mod & LockMask) ? "" : "~"));
77: if (mask & Mod1Mask)
78: (void) printf("<%sMeta>", ((mod & Mod1Mask) ? "" : "~"));
79: if (mask & Mod2Mask)
80: (void) printf("<%sMod2>", ((mod & Mod2Mask) ? "" : "~"));
81: if (mask & Mod3Mask)
82: (void) printf("<%sMod3>", ((mod & Mod3Mask) ? "" : "~"));
83: if (mask & Mod4Mask)
84: (void) printf("<%sMod4>", ((mod & Mod4Mask) ? "" : "~"));
85: if (mask & Mod5Mask)
86: (void) printf("<%sMod5>", ((mod & Mod5Mask) ? "" : "~"));
87: }
88:
89: static void PrintEvent(event, endStr)
90: unsigned long event;
91: char * endStr;
92: {
93: (void) strcpy(endStr, "");
94: switch (event) {
95: case KeyPressMask:
96: (void) printf("<Key>");
97: break;
98: case KeyReleaseMask:
99: (void) printf("<Key>");
100: break;
101: case ButtonPressMask:
102: (void) printf("<Btn");
103: (void) strcpy(endStr, "Down>");
104: break;
105: case ButtonReleaseMask:
106: (void) printf("<Btn");
107: (void) strcpy(endStr, "Up>");
108: break;
109: }
110: }
111:
112: static void PrintCode(code)
113: unsigned long code;
114: {
115: char ch;
116: ch = code - 'a' + 'A';
117: if (ch >= 'A' && ch <= 'Z')
118: (void) printf("%c",ch);
119: else
120: (void) printf("%d", code);
121: }
122:
123: static void PrintActions(ev, code, mask, modif, actions, j)
124: unsigned long ev[], mask[], modif[], code[];
125: ActionPtr actions;
126: int j;
127: {
128: char endStr[20];
129: int i;
130: for (i=0; i<j; i++) {
131: PrintModifiers(mask[i], modif[i]);
132: PrintEvent(ev[i], endStr);
133: PrintCode(code[i]);
134: (void) printf("%s ",endStr);
135: }
136: while (actions != NULL && actions->token != NULL) {
137: (void) printf("---------> action = %s\n", actions->token);
138: actions = actions->next;
139: }
140: (void) printf("\n");
141: }
142:
143: /*
144: * there are certain cases where you want to ignore the event and stay
145: * in the same state.
146: */
147: static Boolean SpecialCase(event)
148: EventSeqPtr event;
149: {
150: if (event->eventType == MotionNotify || event->eventType == ButtonPress ||
151: event->eventType == ButtonRelease)
152: return TRUE;
153: else
154: return FALSE;
155: }
156:
157:
158: static int FindEvent(translations, eventSeq)
159: _XtTranslations translations;
160: EventSeqPtr eventSeq;
161: {
162: EventObjPtr eventTbl = translations->eventObjTbl;
163: int i;
164:
165: for (i=0; i < translations->numEvents; i++) {
166: if (
167: (eventTbl[i].eventType == eventSeq->eventType) &&
168: (eventTbl[i].eventCode == eventSeq->eventCode) &&
169: (eventTbl[i].eventCodeMask == eventSeq->eventCodeMask) &&
170: (eventTbl[i].modifiers == eventSeq->modifiers) &&
171: (eventTbl[i].modifierMask == eventSeq->modifierMask)
172: )
173: return(i);
174: }
175: return(-1);
176: }
177:
178:
179: static int MatchEvent(translations, eventSeq)
180: _XtTranslations translations;
181: EventSeqPtr eventSeq;
182: {
183: EventObjPtr eventTbl = translations->eventObjTbl;
184: int i;
185:
186: for (i=0; i < translations->numEvents; i++) {
187: if ((eventTbl[i].eventType == eventSeq->eventType) &&
188: (eventTbl[i].eventCode ==
189: (eventTbl[i].eventCodeMask & eventSeq->eventCode)) &&
190: (eventTbl[i].modifiers ==
191: (eventTbl[i].modifierMask & eventSeq->modifiers))
192: )
193: return(i);
194: }
195: return(-1);
196: }
197:
198:
199: static EventObjPtr CreateStates(translations, index, eventSeq)
200: _XtTranslations translations;
201: int index;
202: EventSeqPtr eventSeq;
203: {
204: EventObjPtr eventObjTbl = translations->eventObjTbl;
205: StatePtr state;
206: Boolean found = FALSE;
207: ActionPtr actions = eventSeq->actions;
208:
209: if (eventObjTbl[index].state == NULL) {
210: eventObjTbl[index].state = (StatePtr) XtMalloc((unsigned)sizeof(StateRec));
211: state = eventObjTbl[index].state;
212: state->index = index;
213: state->nextLevel = NULL;
214: state->next = NULL;
215: state->actions = NULL; ;
216: } else {
217: state = eventObjTbl[index].state;
218: do {
219: found = FALSE;
220: if (eventSeq->next != NULL && state->nextLevel != NULL) {
221: eventSeq = eventSeq->next;
222: index = FindEvent(translations, eventSeq);
223: state = state->nextLevel;
224: if (state->index == index)
225: found = TRUE;
226: while (state->next != NULL && !found) {
227: state = state->next;
228: if (state->index == index)
229: found = TRUE;
230: }
231: if (!found) {
232: state->next = (StatePtr) XtMalloc((unsigned)sizeof(StateRec));
233: state = state->next;
234: state->index = index;
235: state->nextLevel = NULL;
236: state->next = NULL;
237: state->actions = NULL;
238: }
239: }
240: } while (found);
241: }
242: while (eventSeq->next != NULL) {
243: eventSeq = eventSeq->next;
244: index = FindEvent(translations, eventSeq);
245: state->nextLevel = (StatePtr) XtMalloc((unsigned)sizeof(StateRec));
246: state = state->nextLevel;
247: state->index = index;
248: state->nextLevel = NULL;
249: state->next = NULL;
250: state->actions = NULL;
251: }
252: if (state->actions != NULL)
253: FreeActionRecs(state->actions);
254: state->actions = actions;
255:
256: return eventObjTbl;
257: }
258:
259:
260: /*** Public procedures ***/
261: EventObjPtr EventMapObjectCreate(translations, eventSeq)
262: _XtTranslations translations;
263: EventSeqPtr eventSeq;
264: {
265: EventObjPtr new;
266:
267: if (FindEvent(translations, eventSeq) >= 0)
268: return translations->eventObjTbl;
269:
270: if (translations->numEvents == translations->eventTblSize) {
271: translations->eventTblSize += 100;
272: translations->eventObjTbl = (EventObjPtr) XtRealloc(
273: (char *)translations->eventObjTbl,
274: translations->eventTblSize*sizeof(EventObjRec));
275: }
276:
277: new = &translations->eventObjTbl[translations->numEvents];
278:
279: new->eventType = eventSeq->eventType;
280: new->eventCodeMask = eventSeq->eventCodeMask;
281: new->eventCode = eventSeq->eventCode;
282: new->modifierMask = eventSeq->modifierMask;
283: new->modifiers = eventSeq->modifiers;
284: new->state = NULL;
285:
286: translations->numEvents++;
287: return translations->eventObjTbl;
288: }
289:
290:
291: EventObjPtr EventMapObjectGet(translations, eventSeq)
292: _XtTranslations translations;
293: EventSeqPtr eventSeq;
294: {
295: EventObjPtr eventTbl = translations->eventObjTbl;
296: int index;
297: if ((index = FindEvent(translations, eventSeq)) < 0)
298: return NULL;
299: else
300: return &eventTbl[index];
301: }
302:
303:
304: EventObjPtr EventMapObjectSet(translations, eventSeq)
305: _XtTranslations translations;
306: EventSeqPtr eventSeq;
307: {
308: EventObjPtr eventTbl = translations->eventObjTbl;
309: int index;
310: if ((index = FindEvent(translations, eventSeq)) >= 0)
311: eventTbl = CreateStates(translations, index, eventSeq);
312: return eventTbl;
313: }
314:
315:
316: /* ARGSUSED */
317: void TranslateEvent(w, closure, event)
318: Widget w;
319: Opaque closure;
320: register XEvent *event;
321: {
322: static unsigned long upTime=0;
323: static Boolean buttonUp = FALSE;
324: static StatePtr curState = NULL;
325: StatePtr oldState;
326: EventSeqRec curEvent;
327: int index;
328: ActionPtr actions;
329: Boolean specialCase;
330:
331: oldState = 0;
332: specialCase = FALSE;
333: curEvent.eventCodeMask = 0;
334: curEvent.eventCode = 0;
335: curEvent.modifierMask = 0;
336: curEvent.modifiers = 0;
337: curEvent.eventType = event->type;
338: switch (event->type) {
339: case KeyPress:
340: case KeyRelease:
341: buttonUp = FALSE;
342: curEvent.modifiers = event->xkey.state;
343: event->xkey.state = 0;
344: curEvent.eventCode = XLookupKeysym(&event->xkey, 0);
345: event->xkey.state = curEvent.modifiers;
346: break;
347: case ButtonPress:
348: if (buttonUp && curState != NULL)
349: if ((unsigned long)
350: (upTime - event->xbutton.time) >
351: w->core.translations->clickTime)
352: curState = NULL;
353: buttonUp = FALSE;
354: curEvent.eventCode = event->xbutton.button;
355: curEvent.modifiers = event->xbutton.state;
356: break;
357: case ButtonRelease:
358: buttonUp = TRUE;
359: upTime = event->xbutton.time;
360: curEvent.eventCode = event->xbutton.button;
361: curEvent.modifiers = event->xbutton.state;
362: break;
363: case MotionNotify:
364: buttonUp = FALSE;
365: curEvent.modifiers = event->xmotion.state;
366: break;
367: case EnterNotify:
368: case LeaveNotify:
369: buttonUp = FALSE;
370: curEvent.modifiers = event->xcrossing.state;
371: break;
372: default:
373: buttonUp = FALSE;
374: break;
375: }
376: if (curState != NULL) { /* check the current level */
377: index = MatchEvent(w->core.translations, &curEvent);
378: oldState = curState;
379: while (curState != NULL && curState->index != index)
380: curState = curState->next;
381: if (curState == NULL)
382: if (SpecialCase(&curEvent)) {
383: curState = oldState;
384: specialCase = TRUE;
385: } else { /* nothing at level but you performed an action on the
386: last event---> start over with this new event. */
387: if (oldState->actions != NULL) {
388: curState = oldState;
389: index = MatchEvent(w->core.translations, &curEvent);
390: curState = w->core.translations->eventObjTbl[index].state;
391: }
392: }
393: } else {
394: index = MatchEvent(w->core.translations, &curEvent);
395: if (index == -1) return;
396: curState = w->core.translations->eventObjTbl[index].state;
397: }
398: if (curState != NULL && !specialCase) {
399: actions = curState->actions;
400: while (actions != NULL) { /* perform any actions */
401: if (actions->proc != NULL)
402: /*!!!!! should have params here */
403: (*(actions->proc))(w, event);
404: actions = actions->next;
405: }
406: curState = curState->nextLevel;
407: }
408: }
409:
410: void TranslateTableFree(translations)
411: _XtTranslations translations;
412: {
413: EventObjPtr tbl = translations->eventObjTbl;
414: int i;
415:
416: /* !!! ref count this, it may be shared */
417:
418: for (i=0; i<translations->numEvents; i++) {
419: if (tbl[i].state != NULL) FreeStateRecs(tbl[i].state);
420: }
421: XtFree((char *)tbl);
422: XtFree((char *)translations);
423: }
424:
425:
426: void TranslateTablePrint(translations)
427: _XtTranslations translations;
428: {
429: EventObjPtr tbl = translations->eventObjTbl;
430: int i, j;
431: unsigned long ev[100], code[100], mask[100], modif[100];
432: StatePtr stack[100], state;
433:
434: for (i=0; i<translations->numEvents; i++) {
435: j=0;
436: if (tbl[i].state != NULL) {
437: state = tbl[i].state;
438: stack[j] = tbl[i].state;
439: ev[j] = tbl[i].eventType;
440: code[j] = tbl[i].eventCode;
441: mask[j] = tbl[i].modifierMask;
442: modif[j++] = tbl[i].modifiers;
443: if (state->actions != NULL)
444: PrintActions(ev, code, mask, modif, state->actions, j);
445: do {
446: do {
447: while (state->nextLevel != NULL) {
448: state = state->nextLevel;
449: stack[j] = state;
450: ev[j] = tbl[state->index].eventType;
451: code[j] = tbl[state->index].eventCode;
452: mask[j] = tbl[state->index].modifierMask;
453: modif[j++] = tbl[state->index].modifiers;
454: if (state->actions != NULL)
455: PrintActions(
456: ev, code, mask, modif, state->actions, j);
457: }
458: j--;
459: if (state->next != NULL) {
460: state = state->next;
461: stack[j] = state;
462: ev[j] = tbl[state->index].eventType;
463: code[j] = tbl[state->index].eventCode;
464: mask[j] = tbl[state->index].modifierMask;
465: modif[j++] = tbl[state->index].modifiers;
466: if (state->actions != NULL)
467: PrintActions(
468: ev, code, mask, modif, state->actions, j);
469: }
470: } while (state->next != NULL && state->nextLevel != NULL);
471: j--;
472: state = stack[j];
473: if (state->next != NULL) {
474: state = state->next;
475: stack[j] = state;
476: ev[j] = tbl[state->index].eventType;
477: code[j] = tbl[state->index].eventCode;
478: mask[j] = tbl[state->index].modifierMask;
479: modif[j++] = tbl[state->index].modifiers;
480: if (state->actions != NULL)
481: PrintActions(ev, code, mask, modif, state->actions, j);
482: } else
483: j--;
484: } while (j-1>0);
485: }
486: }
487: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.