1 /***********************************************************
2 Copyright (c) 1993, Oracle and/or its affiliates. All rights reserved.
3
4 Permission is hereby granted, free of charge, to any person obtaining a
5 copy of this software and associated documentation files (the "Software"),
6 to deal in the Software without restriction, including without limitation
7 the rights to use, copy, modify, merge, publish, distribute, sublicense,
8 and/or sell copies of the Software, and to permit persons to whom the
9 Software is furnished to do so, subject to the following conditions:
10
11 The above copyright notice and this permission notice (including the next
12 paragraph) shall be included in all copies or substantial portions of the
13 Software.
14
15 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
18 THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20 FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
21 DEALINGS IN THE SOFTWARE.
22
23 Copyright 1987, 1988 by Digital Equipment Corporation, Maynard, Massachusetts.
24
25 All Rights Reserved
26
27 Permission to use, copy, modify, and distribute this software and its
28 documentation for any purpose and without fee is hereby granted,
29 provided that the above copyright notice appear in all copies and that
30 both that copyright notice and this permission notice appear in
31 supporting documentation, and that the name of Digital not be
32 used in advertising or publicity pertaining to distribution of the
33 software without specific, written prior permission.
34
35 DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
36 ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
37 DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
38 ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
39 WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
40 ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
41 SOFTWARE.
42
43 ******************************************************************/
44
45 /*
46
47 Copyright 1987, 1988, 1998 The Open Group
48
49 Permission to use, copy, modify, distribute, and sell this software and its
50 documentation for any purpose is hereby granted without fee, provided that
51 the above copyright notice appear in all copies and that both that
52 copyright notice and this permission notice appear in supporting
53 documentation.
54
55 The above copyright notice and this permission notice shall be included in
56 all copies or substantial portions of the Software.
57
58 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
59 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
60 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
61 OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
62 AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
63 CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
64
65 Except as contained in this notice, the name of The Open Group shall not be
66 used in advertising or otherwise to promote the sale, use or other dealings
67 in this Software without prior written authorization from The Open Group.
68
69 */
70
71 #ifdef HAVE_CONFIG_H
72 #include <config.h>
73 #endif
74 #include "IntrinsicI.h"
75 #include <stdio.h>
76
77 typedef struct _TMStringBufRec {
78 _XtString start;
79 _XtString current;
80 Cardinal max;
81 } TMStringBufRec, *TMStringBuf;
82
83 #define STR_THRESHOLD 25
84 #define STR_INCAMOUNT 100
85
86 #define CHECK_STR_OVERFLOW(sb) \
87 if (sb->current - sb->start > (int)sb->max - STR_THRESHOLD) \
88 { \
89 _XtString old = sb->start; \
90 sb->start = XtRealloc(old, (Cardinal)(sb->max += STR_INCAMOUNT)); \
91 sb->current = sb->current - old + sb->start; \
92 }
93
94 #define ExpandForChars(sb, nchars ) \
95 if ((unsigned)(sb->current - sb->start) > (sb->max - STR_THRESHOLD - (Cardinal) nchars)) { \
96 _XtString old = sb->start; \
97 sb->start = XtRealloc(old, \
98 (Cardinal)(sb->max = (Cardinal)(sb->max + STR_INCAMOUNT + (Cardinal) nchars))); \
99 sb->current = sb->current - old + sb->start; \
100 }
101
102 #define ExpandToFit(sb, more) \
103 { \
104 size_t l = strlen(more); \
105 ExpandForChars(sb, l); \
106 }
107
108 static void
PrintModifiers(TMStringBuf sb,unsigned long mask,unsigned long mod)109 PrintModifiers(TMStringBuf sb, unsigned long mask, unsigned long mod)
110 {
111 Boolean notfirst = False;
112
113 CHECK_STR_OVERFLOW(sb);
114
115 if (mask == ~0UL && mod == 0) {
116 *sb->current++ = '!';
117 *sb->current = '\0';
118 return;
119 }
120
121 #define PRINTMOD(modmask,modstring) \
122 if (mask & modmask) { \
123 if (! (mod & modmask)) { \
124 *sb->current++ = '~'; \
125 notfirst = True; \
126 } \
127 else if (notfirst) \
128 *sb->current++ = ' '; \
129 else notfirst = True; \
130 strcpy(sb->current, modstring); \
131 sb->current += strlen(sb->current); \
132 }
133
134 PRINTMOD(ShiftMask, "Shift");
135 PRINTMOD(ControlMask, "Ctrl"); /* name is not CtrlMask... */
136 PRINTMOD(LockMask, "Lock");
137 PRINTMOD(Mod1Mask, "Mod1");
138 CHECK_STR_OVERFLOW(sb);
139 PRINTMOD(Mod2Mask, "Mod2");
140 PRINTMOD(Mod3Mask, "Mod3");
141 PRINTMOD(Mod4Mask, "Mod4");
142 PRINTMOD(Mod5Mask, "Mod5");
143 CHECK_STR_OVERFLOW(sb);
144 PRINTMOD(Button1Mask, "Button1");
145 PRINTMOD(Button2Mask, "Button2");
146 PRINTMOD(Button3Mask, "Button3");
147 CHECK_STR_OVERFLOW(sb);
148 PRINTMOD(Button4Mask, "Button4");
149 PRINTMOD(Button5Mask, "Button5");
150 (void) notfirst;
151
152 #undef PRINTMOD
153 }
154
155 static void
PrintEventType(TMStringBuf sb,unsigned long event)156 PrintEventType(TMStringBuf sb, unsigned long event)
157 {
158 CHECK_STR_OVERFLOW(sb);
159 switch (event) {
160 #define PRINTEVENT(event, name) case event: (void) strcpy(sb->current, name); break;
161 PRINTEVENT(KeyPress, "<KeyPress>")
162 PRINTEVENT(KeyRelease, "<KeyRelease>")
163 PRINTEVENT(ButtonPress, "<ButtonPress>")
164 PRINTEVENT(ButtonRelease, "<ButtonRelease>")
165 PRINTEVENT(MotionNotify, "<MotionNotify>")
166 PRINTEVENT(EnterNotify, "<EnterNotify>")
167 PRINTEVENT(LeaveNotify, "<LeaveNotify>")
168 PRINTEVENT(FocusIn, "<FocusIn>")
169 PRINTEVENT(FocusOut, "<FocusOut>")
170 PRINTEVENT(KeymapNotify, "<KeymapNotify>")
171 PRINTEVENT(Expose, "<Expose>")
172 PRINTEVENT(GraphicsExpose, "<GraphicsExpose>")
173 PRINTEVENT(NoExpose, "<NoExpose>")
174 PRINTEVENT(VisibilityNotify, "<VisibilityNotify>")
175 PRINTEVENT(CreateNotify, "<CreateNotify>")
176 PRINTEVENT(DestroyNotify, "<DestroyNotify>")
177 PRINTEVENT(UnmapNotify, "<UnmapNotify>")
178 PRINTEVENT(MapNotify, "<MapNotify>")
179 PRINTEVENT(MapRequest, "<MapRequest>")
180 PRINTEVENT(ReparentNotify, "<ReparentNotify>")
181 PRINTEVENT(ConfigureNotify, "<ConfigureNotify>")
182 PRINTEVENT(ConfigureRequest, "<ConfigureRequest>")
183 PRINTEVENT(GravityNotify, "<GravityNotify>")
184 PRINTEVENT(ResizeRequest, "<ResizeRequest>")
185 PRINTEVENT(CirculateNotify, "<CirculateNotify>")
186 PRINTEVENT(CirculateRequest, "<CirculateRequest>")
187 PRINTEVENT(PropertyNotify, "<PropertyNotify>")
188 PRINTEVENT(SelectionClear, "<SelectionClear>")
189 PRINTEVENT(SelectionRequest, "<SelectionRequest>")
190 PRINTEVENT(SelectionNotify, "<SelectionNotify>")
191 PRINTEVENT(ColormapNotify, "<ColormapNotify>")
192 PRINTEVENT(ClientMessage, "<ClientMessage>")
193 case _XtEventTimerEventType:
194 (void) strcpy(sb->current, "<EventTimer>");
195 break;
196 default:
197 (void) sprintf(sb->current, "<0x%x>", (int) event);
198 #undef PRINTEVENT
199 }
200 sb->current += strlen(sb->current);
201 }
202
203 static void
PrintCode(TMStringBuf sb,unsigned long mask,unsigned long code)204 PrintCode(TMStringBuf sb, unsigned long mask, unsigned long code)
205 {
206 CHECK_STR_OVERFLOW(sb);
207 if (mask != 0) {
208 if (mask != ~0UL)
209 (void) sprintf(sb->current, "0x%lx:0x%lx", mask, code);
210 else
211 (void) sprintf(sb->current, /*"0x%lx" */ "%u", (unsigned) code);
212 sb->current += strlen(sb->current);
213 }
214 }
215
216 static void
PrintKeysym(TMStringBuf sb,KeySym keysym)217 PrintKeysym(TMStringBuf sb, KeySym keysym)
218 {
219 String keysymName;
220
221 if (keysym == 0)
222 return;
223
224 CHECK_STR_OVERFLOW(sb);
225 keysymName = XKeysymToString(keysym);
226 if (keysymName == NULL)
227 PrintCode(sb, ~0UL, (unsigned long) keysym);
228 else {
229 ExpandToFit(sb, keysymName);
230 strcpy(sb->current, keysymName);
231 sb->current += strlen(sb->current);
232 }
233 }
234
235 static void
PrintAtom(TMStringBuf sb,Display * dpy,Atom atom)236 PrintAtom(TMStringBuf sb, Display *dpy, Atom atom)
237 {
238 _XtString atomName;
239
240 if (atom == 0)
241 return;
242
243 atomName = (dpy ? XGetAtomName(dpy, atom) : NULL);
244
245 if (!atomName)
246 PrintCode(sb, ~0UL, (unsigned long) atom);
247 else {
248 ExpandToFit(sb, atomName);
249 strcpy(sb->current, atomName);
250 sb->current += strlen(sb->current);
251 XFree(atomName);
252 }
253 }
254
255 static void
PrintLateModifiers(TMStringBuf sb,LateBindingsPtr lateModifiers)256 PrintLateModifiers(TMStringBuf sb, LateBindingsPtr lateModifiers)
257 {
258 for (; lateModifiers->keysym; lateModifiers++) {
259 CHECK_STR_OVERFLOW(sb);
260 if (lateModifiers->knot) {
261 *sb->current++ = '~';
262 }
263 else {
264 *sb->current++ = ' ';
265 }
266 strcpy(sb->current, XKeysymToString(lateModifiers->keysym));
267 sb->current += strlen(sb->current);
268 if (lateModifiers->pair) {
269 *(sb->current -= 2) = '\0'; /* strip "_L" */
270 lateModifiers++; /* skip _R keysym */
271 }
272 }
273 }
274
275 static void
PrintEvent(TMStringBuf sb,register TMTypeMatch typeMatch,register TMModifierMatch modMatch,Display * dpy)276 PrintEvent(TMStringBuf sb,
277 register TMTypeMatch typeMatch,
278 register TMModifierMatch modMatch,
279 Display *dpy)
280 {
281 if (modMatch->standard)
282 *sb->current++ = ':';
283
284 PrintModifiers(sb, modMatch->modifierMask, modMatch->modifiers);
285 if (modMatch->lateModifiers != NULL)
286 PrintLateModifiers(sb, modMatch->lateModifiers);
287 PrintEventType(sb, typeMatch->eventType);
288 switch (typeMatch->eventType) {
289 case KeyPress:
290 case KeyRelease:
291 PrintKeysym(sb, (KeySym) typeMatch->eventCode);
292 break;
293
294 case PropertyNotify:
295 case SelectionClear:
296 case SelectionRequest:
297 case SelectionNotify:
298 case ClientMessage:
299 PrintAtom(sb, dpy, (Atom) typeMatch->eventCode);
300 break;
301
302 default:
303 PrintCode(sb, typeMatch->eventCodeMask, typeMatch->eventCode);
304 }
305 }
306
307 static void
PrintParams(TMStringBuf sb,String * params,Cardinal num_params)308 PrintParams(TMStringBuf sb, String *params, Cardinal num_params)
309 {
310 register Cardinal i;
311
312 for (i = 0; i < num_params; i++) {
313 ExpandToFit(sb, params[i]);
314 if (i != 0) {
315 *sb->current++ = ',';
316 *sb->current++ = ' ';
317 }
318 *sb->current++ = '"';
319 strcpy(sb->current, params[i]);
320 sb->current += strlen(sb->current);
321 *sb->current++ = '"';
322 }
323 *sb->current = '\0';
324 }
325
326 static void
PrintActions(TMStringBuf sb,register ActionPtr actions,XrmQuark * quarkTbl,Widget accelWidget)327 PrintActions(TMStringBuf sb,
328 register ActionPtr actions,
329 XrmQuark *quarkTbl,
330 Widget accelWidget)
331 {
332 while (actions != NULL) {
333 String proc;
334
335 *sb->current++ = ' ';
336
337 if (accelWidget) {
338 /* accelerator */
339 String name = XtName(accelWidget);
340 int nameLen = (int) strlen(name);
341
342 ExpandForChars(sb, nameLen);
343 XtMemmove(sb->current, name, nameLen);
344 sb->current += nameLen;
345 *sb->current++ = '`';
346 }
347 proc = XrmQuarkToString(quarkTbl[actions->idx]);
348 ExpandToFit(sb, proc);
349 strcpy(sb->current, proc);
350 sb->current += strlen(proc);
351 *sb->current++ = '(';
352 PrintParams(sb, actions->params, actions->num_params);
353 *sb->current++ = ')';
354 actions = actions->next;
355 }
356 *sb->current = '\0';
357 }
358
359 static Boolean
LookAheadForCycleOrMulticlick(register StatePtr state,StatePtr * state_return,int * countP,StatePtr * nextLevelP)360 LookAheadForCycleOrMulticlick(register StatePtr state,
361 StatePtr *state_return, /* state to print, usually startState */
362 int *countP,
363 StatePtr *nextLevelP)
364 {
365 int repeatCount = 0;
366 StatePtr startState = state;
367 Boolean isCycle = startState->isCycleEnd;
368 TMTypeMatch sTypeMatch;
369 TMModifierMatch sModMatch;
370
371 LOCK_PROCESS;
372 sTypeMatch = TMGetTypeMatch(startState->typeIndex);
373 sModMatch = TMGetModifierMatch(startState->modIndex);
374
375 *state_return = startState;
376
377 for (state = state->nextLevel; state != NULL; state = state->nextLevel) {
378 TMTypeMatch typeMatch = TMGetTypeMatch(state->typeIndex);
379 TMModifierMatch modMatch = TMGetModifierMatch(state->modIndex);
380
381 /* try to pick up the correct state with actions, to be printed */
382 /* This is to accommodate <ButtonUp>(2+), for example */
383 if (state->isCycleStart)
384 *state_return = state;
385
386 if (state->isCycleEnd) {
387 *countP = repeatCount;
388 UNLOCK_PROCESS;
389 return True;
390 }
391 if ((startState->typeIndex == state->typeIndex) &&
392 (startState->modIndex == state->modIndex)) {
393 repeatCount++;
394 *nextLevelP = state;
395 }
396 else if (typeMatch->eventType == _XtEventTimerEventType)
397 continue;
398 else { /* not same event as starting event and not timer */
399
400 unsigned int type = (unsigned) sTypeMatch->eventType;
401 unsigned int t = (unsigned) typeMatch->eventType;
402
403 if ((type == ButtonPress && t != ButtonRelease)
404 || (type == ButtonRelease && t != ButtonPress)
405 || (type == KeyPress && t != KeyRelease)
406 || (type == KeyRelease && t != KeyPress)
407 || typeMatch->eventCode != sTypeMatch->eventCode
408 || modMatch->modifiers != sModMatch->modifiers
409 || modMatch->modifierMask != sModMatch->modifierMask
410 || modMatch->lateModifiers != sModMatch->lateModifiers
411 || typeMatch->eventCodeMask != sTypeMatch->eventCodeMask
412 || typeMatch->matchEvent != sTypeMatch->matchEvent
413 || modMatch->standard != sModMatch->standard)
414 /* not inverse of starting event, either */
415 break;
416 }
417 }
418 *countP = repeatCount;
419 UNLOCK_PROCESS;
420 return isCycle;
421 }
422
423 static void
PrintComplexState(TMStringBuf sb,Boolean includeRHS,StatePtr state,TMStateTree stateTree,Widget accelWidget,Display * dpy)424 PrintComplexState(TMStringBuf sb,
425 Boolean includeRHS,
426 StatePtr state,
427 TMStateTree stateTree,
428 Widget accelWidget,
429 Display *dpy)
430 {
431 int clickCount = 0;
432 Boolean cycle;
433 StatePtr nextLevel = NULL;
434 StatePtr triggerState = NULL;
435
436 /* print the current state */
437 if (!state)
438 return;
439 LOCK_PROCESS;
440 cycle = LookAheadForCycleOrMulticlick(state, &triggerState, &clickCount,
441 &nextLevel);
442
443 PrintEvent(sb, TMGetTypeMatch(triggerState->typeIndex),
444 TMGetModifierMatch(triggerState->modIndex), dpy);
445
446 if (cycle || clickCount) {
447 if (clickCount)
448 sprintf(sb->current, "(%d%s)", clickCount + 1, cycle ? "+" : "");
449 else
450 (void) strncpy(sb->current, "(+)", 4);
451 sb->current += strlen(sb->current);
452 if (!state->actions && nextLevel)
453 state = nextLevel;
454 while (!state->actions && !state->isCycleEnd)
455 state = state->nextLevel; /* should be trigger state */
456 }
457
458 if (state->actions) {
459 if (includeRHS) {
460 CHECK_STR_OVERFLOW(sb);
461 *sb->current++ = ':';
462 PrintActions(sb,
463 state->actions,
464 ((TMSimpleStateTree) stateTree)->quarkTbl,
465 accelWidget);
466 *sb->current++ = '\n';
467 }
468 }
469 else {
470 if (state->nextLevel && !cycle && !clickCount)
471 *sb->current++ = ',';
472 else {
473 /* no actions are attached to this production */
474 *sb->current++ = ':';
475 *sb->current++ = '\n';
476 }
477 }
478 *sb->current = '\0';
479
480 /* print succeeding states */
481 if (state->nextLevel && !cycle && !clickCount)
482 PrintComplexState(sb, includeRHS, state->nextLevel,
483 stateTree, accelWidget, dpy);
484 UNLOCK_PROCESS;
485 }
486
487 typedef struct {
488 TMShortCard tIndex;
489 TMShortCard bIndex;
490 } PrintRec, *Print;
491
492 static int
FindNextMatch(PrintRec * printData,TMShortCard numPrints,XtTranslations xlations,TMBranchHead branchHead,StatePtr nextLevel,TMShortCard startIndex)493 FindNextMatch(PrintRec *printData,
494 TMShortCard numPrints,
495 XtTranslations xlations,
496 TMBranchHead branchHead,
497 StatePtr nextLevel,
498 TMShortCard startIndex)
499 {
500 TMShortCard i;
501 StatePtr currState, candState;
502 Boolean noMatch = True;
503
504 for (i = startIndex; noMatch && i < numPrints; i++) {
505 TMBranchHead prBranchHead;
506 TMComplexStateTree stateTree;
507
508 stateTree = (TMComplexStateTree)
509 xlations->stateTreeTbl[printData[i].tIndex];
510 prBranchHead = &(stateTree->branchHeadTbl[printData[i].bIndex]);
511
512 if ((prBranchHead->typeIndex == branchHead->typeIndex) &&
513 (prBranchHead->modIndex == branchHead->modIndex)) {
514 if (prBranchHead->isSimple) {
515 if (!nextLevel)
516 return i;
517 }
518 else {
519 currState = TMComplexBranchHead(stateTree, prBranchHead);
520 currState = currState->nextLevel;
521 candState = nextLevel;
522 for (;
523 ((currState && !currState->isCycleEnd) &&
524 (candState && !candState->isCycleEnd));
525 currState = currState->nextLevel,
526 candState = candState->nextLevel) {
527 if ((currState->typeIndex != candState->typeIndex) ||
528 (currState->modIndex != candState->modIndex))
529 break;
530 }
531 if (candState == currState) {
532 return i;
533 }
534 }
535 }
536 }
537 return TM_NO_MATCH;
538 }
539
540 static void
ProcessLaterMatches(PrintRec * printData,XtTranslations xlations,TMShortCard tIndex,int bIndex,TMShortCard * numPrintsRtn)541 ProcessLaterMatches(PrintRec *printData,
542 XtTranslations xlations,
543 TMShortCard tIndex,
544 int bIndex,
545 TMShortCard *numPrintsRtn)
546 {
547 TMComplexStateTree stateTree;
548 int i, j;
549 TMBranchHead branchHead, matchBranch = NULL;
550
551 for (i = tIndex; i < (int) xlations->numStateTrees; i++) {
552 stateTree = (TMComplexStateTree) xlations->stateTreeTbl[i];
553 if (i == tIndex) {
554 matchBranch = &stateTree->branchHeadTbl[bIndex];
555 j = bIndex + 1;
556 }
557 else
558 j = 0;
559 for (branchHead = &stateTree->branchHeadTbl[j];
560 j < (int) stateTree->numBranchHeads; j++, branchHead++) {
561 if ((branchHead->typeIndex == matchBranch->typeIndex) &&
562 (branchHead->modIndex == matchBranch->modIndex)) {
563 StatePtr state;
564
565 if (!branchHead->isSimple)
566 state = TMComplexBranchHead(stateTree, branchHead);
567 else
568 state = NULL;
569 if ((!branchHead->isSimple || branchHead->hasActions) &&
570 (FindNextMatch(printData,
571 *numPrintsRtn,
572 xlations,
573 branchHead,
574 (state ? state->nextLevel : NULL),
575 0) == TM_NO_MATCH)) {
576 printData[*numPrintsRtn].tIndex = (TMShortCard) i;
577 printData[*numPrintsRtn].bIndex = (TMShortCard) j;
578 (*numPrintsRtn)++;
579 }
580 }
581 }
582 }
583 }
584
585 static void
ProcessStateTree(PrintRec * printData,XtTranslations xlations,TMShortCard tIndex,TMShortCard * numPrintsRtn)586 ProcessStateTree(PrintRec *printData,
587 XtTranslations xlations,
588 TMShortCard tIndex,
589 TMShortCard *numPrintsRtn)
590 {
591 TMComplexStateTree stateTree;
592 int i;
593 TMBranchHead branchHead;
594
595 stateTree = (TMComplexStateTree) xlations->stateTreeTbl[tIndex];
596
597 for (i = 0, branchHead = stateTree->branchHeadTbl;
598 i < (int) stateTree->numBranchHeads; i++, branchHead++) {
599 StatePtr state;
600
601 if (!branchHead->isSimple)
602 state = TMComplexBranchHead(stateTree, branchHead);
603 else
604 state = NULL;
605 if (FindNextMatch(printData, *numPrintsRtn, xlations, branchHead,
606 (state ? state->nextLevel : NULL), 0)
607 == TM_NO_MATCH) {
608 if (!branchHead->isSimple || branchHead->hasActions) {
609 printData[*numPrintsRtn].tIndex = tIndex;
610 printData[*numPrintsRtn].bIndex = (TMShortCard) i;
611 (*numPrintsRtn)++;
612 }
613 LOCK_PROCESS;
614 if (_XtGlobalTM.newMatchSemantics == False)
615 ProcessLaterMatches(printData,
616 xlations, tIndex, i, numPrintsRtn);
617 UNLOCK_PROCESS;
618 }
619 }
620 }
621
622 static void
PrintState(TMStringBuf sb,TMStateTree tree,TMBranchHead branchHead,Boolean includeRHS,Widget accelWidget,Display * dpy)623 PrintState(TMStringBuf sb,
624 TMStateTree tree,
625 TMBranchHead branchHead,
626 Boolean includeRHS,
627 Widget accelWidget,
628 Display *dpy)
629 {
630 TMComplexStateTree stateTree = (TMComplexStateTree) tree;
631
632 LOCK_PROCESS;
633 if (branchHead->isSimple) {
634 PrintEvent(sb,
635 TMGetTypeMatch(branchHead->typeIndex),
636 TMGetModifierMatch(branchHead->modIndex), dpy);
637 if (includeRHS) {
638 ActionRec actRec;
639
640 CHECK_STR_OVERFLOW(sb);
641 *sb->current++ = ':';
642 actRec.idx = TMBranchMore(branchHead);
643 actRec.num_params = 0;
644 actRec.params = NULL;
645 actRec.next = NULL;
646 PrintActions(sb, &actRec, stateTree->quarkTbl, accelWidget);
647 *sb->current++ = '\n';
648 }
649 else
650 *sb->current++ = ',';
651 #ifdef TRACE_TM
652 if (!branchHead->hasActions)
653 printf(" !! no actions !! ");
654 #endif
655 }
656 else { /* it's a complex branchHead */
657 StatePtr state = TMComplexBranchHead(stateTree, branchHead);
658
659 PrintComplexState(sb,
660 includeRHS,
661 state, tree, accelWidget, (Display *) NULL);
662 }
663 *sb->current = '\0';
664 UNLOCK_PROCESS;
665 }
666
667 _XtString
_XtPrintXlations(Widget w,XtTranslations xlations,Widget accelWidget,_XtBoolean includeRHS)668 _XtPrintXlations(Widget w,
669 XtTranslations xlations,
670 Widget accelWidget,
671 _XtBoolean includeRHS)
672 {
673 register Cardinal i;
674
675 #define STACKPRINTSIZE 250
676 PrintRec stackPrints[STACKPRINTSIZE];
677 PrintRec *prints;
678 TMStringBufRec sbRec, *sb = &sbRec;
679 TMShortCard numPrints, maxPrints;
680
681 #ifdef TRACE_TM
682 TMBindData bindData = (TMBindData) w->core.tm.proc_table;
683 Boolean hasAccel = (accelWidget ? True : False);
684 #endif /* TRACE_TM */
685 if (xlations == NULL)
686 return NULL;
687
688 sb->current = sb->start = __XtMalloc((Cardinal) 1000);
689 sb->max = 1000;
690 maxPrints = 0;
691 for (i = 0; i < xlations->numStateTrees; i++)
692 maxPrints = (TMShortCard) (maxPrints +
693 ((TMSimpleStateTree)
694 (xlations->stateTreeTbl[i]))->
695 numBranchHeads);
696 prints = (PrintRec *)
697 XtStackAlloc(maxPrints * sizeof(PrintRec), stackPrints);
698
699 numPrints = 0;
700 for (i = 0; i < xlations->numStateTrees; i++)
701 ProcessStateTree(prints, xlations, (TMShortCard) i, &numPrints);
702
703 for (i = 0; i < numPrints; i++) {
704 TMSimpleStateTree stateTree = (TMSimpleStateTree)
705 xlations->stateTreeTbl[prints[i].tIndex];
706 TMBranchHead branchHead = &stateTree->branchHeadTbl[prints[i].bIndex];
707
708 #ifdef TRACE_TM
709 TMComplexBindProcs complexBindProcs;
710
711 if (hasAccel == False) {
712 accelWidget = NULL;
713 if (bindData->simple.isComplex) {
714 complexBindProcs = TMGetComplexBindEntry(bindData, 0);
715 accelWidget = complexBindProcs[prints[i].tIndex].widget;
716 }
717 }
718 #endif /* TRACE_TM */
719 PrintState(sb, (TMStateTree) stateTree, branchHead,
720 (Boolean) includeRHS, accelWidget, XtDisplay(w));
721 }
722 XtStackFree((XtPointer) prints, (XtPointer) stackPrints);
723 return (sb->start);
724 }
725
726 #ifndef NO_MIT_HACKS
727 void
_XtDisplayTranslations(Widget widget,XEvent * event _X_UNUSED,String * params _X_UNUSED,Cardinal * num_params _X_UNUSED)728 _XtDisplayTranslations(Widget widget,
729 XEvent *event _X_UNUSED,
730 String *params _X_UNUSED,
731 Cardinal *num_params _X_UNUSED)
732 {
733 _XtString xString;
734
735 xString = _XtPrintXlations(widget,
736 widget->core.tm.translations, NULL, True);
737 if (xString) {
738 printf("%s\n", xString);
739 XtFree(xString);
740 }
741 }
742
743 void
_XtDisplayAccelerators(Widget widget,XEvent * event _X_UNUSED,String * params _X_UNUSED,Cardinal * num_params _X_UNUSED)744 _XtDisplayAccelerators(Widget widget,
745 XEvent *event _X_UNUSED,
746 String *params _X_UNUSED,
747 Cardinal *num_params _X_UNUSED)
748 {
749 _XtString xString;
750
751 xString = _XtPrintXlations(widget, widget->core.accelerators, NULL, True);
752 if (xString) {
753 printf("%s\n", xString);
754 XtFree(xString);
755 }
756 }
757
758 void
_XtDisplayInstalledAccelerators(Widget widget,XEvent * event,String * params _X_UNUSED,Cardinal * num_params _X_UNUSED)759 _XtDisplayInstalledAccelerators(Widget widget,
760 XEvent *event,
761 String *params _X_UNUSED,
762 Cardinal *num_params _X_UNUSED)
763 {
764 Widget eventWidget
765 = XtWindowToWidget(event->xany.display, event->xany.window);
766 register Cardinal i;
767 TMStringBufRec sbRec, *sb = &sbRec;
768 XtTranslations xlations;
769
770 #define STACKPRINTSIZE 250
771 PrintRec stackPrints[STACKPRINTSIZE];
772 PrintRec *prints;
773 TMShortCard numPrints, maxPrints;
774 TMBindData bindData;
775 TMComplexBindProcs complexBindProcs;
776
777 if ((eventWidget == NULL) || (eventWidget->core.tm.translations == NULL))
778 return;
779
780 xlations = eventWidget->core.tm.translations;
781 bindData = (TMBindData) eventWidget->core.tm.proc_table;
782 if (bindData->simple.isComplex == False)
783 return;
784
785 sb->current = sb->start = __XtMalloc((Cardinal) 1000);
786 sb->start[0] = '\0';
787 sb->max = 1000;
788 maxPrints = 0;
789 for (i = 0; i < xlations->numStateTrees; i++)
790 maxPrints = (TMShortCard) (maxPrints +
791 ((TMSimpleStateTree) xlations->
792 stateTreeTbl[i])->numBranchHeads);
793 prints = (PrintRec *)
794 XtStackAlloc(maxPrints * sizeof(PrintRec), stackPrints);
795
796 numPrints = 0;
797
798 complexBindProcs = TMGetComplexBindEntry(bindData, 0);
799 for (i = 0; i < xlations->numStateTrees; i++, complexBindProcs++) {
800 if (complexBindProcs->widget) {
801 ProcessStateTree(prints, xlations, (TMShortCard) i, &numPrints);
802 }
803 }
804 for (i = 0; i < numPrints; i++) {
805 TMSimpleStateTree stateTree = (TMSimpleStateTree)
806 xlations->stateTreeTbl[prints[i].tIndex];
807 TMBranchHead branchHead = &stateTree->branchHeadTbl[prints[i].bIndex];
808
809 complexBindProcs = TMGetComplexBindEntry(bindData, 0);
810
811 PrintState(sb, (TMStateTree) stateTree, branchHead, True,
812 complexBindProcs[prints[i].tIndex].widget,
813 XtDisplay(widget));
814 }
815 XtStackFree((XtPointer) prints, (XtPointer) stackPrints);
816 printf("%s\n", sb->start);
817 XtFree(sb->start);
818 }
819 #endif /*NO_MIT_HACKS */
820
821 String
_XtPrintActions(register ActionRec * actions,XrmQuark * quarkTbl)822 _XtPrintActions(register ActionRec *actions, XrmQuark *quarkTbl)
823 {
824 TMStringBufRec sbRec, *sb = &sbRec;
825
826 sb->max = 1000;
827 sb->current = sb->start = __XtMalloc((Cardinal) 1000);
828 PrintActions(sb, actions, quarkTbl, (Widget) NULL);
829 return sb->start;
830 }
831
832 String
_XtPrintState(TMStateTree stateTree,TMBranchHead branchHead)833 _XtPrintState(TMStateTree stateTree, TMBranchHead branchHead)
834 {
835 TMStringBufRec sbRec, *sb = &sbRec;
836
837 sb->current = sb->start = __XtMalloc((Cardinal) 1000);
838 sb->max = 1000;
839 PrintState(sb, stateTree, branchHead,
840 True, (Widget) NULL, (Display *) NULL);
841 return sb->start;
842 }
843
844 String
_XtPrintEventSeq(register EventSeqPtr eventSeq,Display * dpy)845 _XtPrintEventSeq(register EventSeqPtr eventSeq, Display *dpy)
846 {
847 TMStringBufRec sbRec, *sb = &sbRec;
848
849 #define MAXSEQS 100
850 EventSeqPtr eventSeqs[MAXSEQS];
851 TMShortCard i, j;
852 Boolean cycle = False;
853
854 sb->current = sb->start = __XtMalloc((Cardinal) 1000);
855 sb->max = 1000;
856 for (i = 0;
857 i < MAXSEQS && eventSeq != NULL && !cycle;
858 eventSeq = eventSeq->next, i++) {
859 eventSeqs[i] = eventSeq;
860 for (j = 0; j < i && !cycle; j++)
861 if (eventSeqs[j] == eventSeq)
862 cycle = True;
863 }
864 LOCK_PROCESS;
865 for (j = 0; j < i; j++) {
866 TMTypeMatch typeMatch;
867 TMModifierMatch modMatch;
868
869 typeMatch = TMGetTypeMatch(_XtGetTypeIndex(&eventSeqs[j]->event));
870 modMatch =
871 TMGetModifierMatch(_XtGetModifierIndex(&eventSeqs[j]->event));
872 PrintEvent(sb, typeMatch, modMatch, dpy);
873 if (j < i)
874 *sb->current++ = ',';
875 }
876 UNLOCK_PROCESS;
877 return sb->start;
878 }
879