Git init
[framework/uifw/xorg/lib/libxt.git] / src / TMprint.c
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 /*LINTLIBRARY*/
72 #ifdef HAVE_CONFIG_H
73 #include <config.h>
74 #endif
75 #include "IntrinsicI.h"
76 #include <stdio.h>
77
78 typedef struct _TMStringBufRec{
79     String      start;
80     String      current;
81     Cardinal    max;
82 }TMStringBufRec, *TMStringBuf;
83
84
85 #define STR_THRESHOLD 25
86 #define STR_INCAMOUNT 100
87 #define CHECK_STR_OVERFLOW(sb) \
88 if (sb->current - sb->start > (int)sb->max - STR_THRESHOLD)     \
89 { String 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 - nchars) { \
96         String old = sb->start;                                 \
97         sb->start = XtRealloc(old,                              \
98             (Cardinal)(sb->max += STR_INCAMOUNT + 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(
109     TMStringBuf sb,
110     unsigned long mask, unsigned long mod)
111 {
112     Boolean notfirst = False;
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
151 #undef PRINTMOD
152 }
153
154 static void PrintEventType(
155     TMStringBuf sb,
156     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(
204     TMStringBuf sb,
205     unsigned long mask, unsigned long code)
206 {
207     CHECK_STR_OVERFLOW(sb);
208     if (mask != 0) {
209         if (mask != ~0UL)
210             (void) sprintf(sb->current, "0x%lx:0x%lx", mask, code);
211         else (void) sprintf(sb->current, /*"0x%lx"*/ "%d", (unsigned)code);
212         sb->current += strlen(sb->current);
213     }
214 }
215
216 static void PrintKeysym(
217     TMStringBuf sb,
218     KeySym keysym)
219 {
220     String keysymName;
221
222     if (keysym == 0) 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(
236     TMStringBuf sb,
237     Display *dpy,
238     Atom atom)
239 {
240     String atomName;
241
242     if (atom == 0) return;
243
244     atomName = (dpy ? XGetAtomName(dpy, atom) : NULL);
245
246     if (! atomName)
247       PrintCode(sb,~0UL,(unsigned long)atom);
248     else {
249       ExpandToFit( sb, atomName );
250       strcpy(sb->current, atomName);
251       sb->current += strlen(sb->current);
252       XFree(atomName);
253     }
254 }
255
256 static  void PrintLateModifiers(
257     TMStringBuf sb,
258     LateBindingsPtr lateModifiers)
259 {
260     for (; lateModifiers->keysym; lateModifiers++) {
261         CHECK_STR_OVERFLOW(sb);
262         if (lateModifiers->knot) {
263             *sb->current++ = '~';
264         } else {
265             *sb->current++ = ' ';
266         }
267         strcpy(sb->current, XKeysymToString(lateModifiers->keysym));
268         sb->current += strlen(sb->current);
269         if (lateModifiers->pair) {
270             *(sb->current -= 2) = '\0'; /* strip "_L" */
271             lateModifiers++;    /* skip _R keysym */
272         }
273     }
274 }
275
276 static void PrintEvent(
277     TMStringBuf sb,
278     register TMTypeMatch typeMatch,
279     register TMModifierMatch modMatch,
280     Display *dpy)
281 {
282     if (modMatch->standard) *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(
308     TMStringBuf sb,
309     String      *params,
310     Cardinal num_params)
311 {
312     register Cardinal i;
313     for (i = 0; i<num_params; i++) {
314         ExpandToFit( sb, params[i] );
315         if (i != 0) {
316             *sb->current++ = ',';
317             *sb->current++ = ' ';
318         }
319         *sb->current++ = '"';
320         strcpy(sb->current, params[i]);
321         sb->current += strlen(sb->current);
322         *sb->current++ = '"';
323     }
324     *sb->current = '\0';
325 }
326
327 static void PrintActions(
328     TMStringBuf sb,
329     register ActionPtr actions,
330     XrmQuark *quarkTbl,
331     Widget   accelWidget)
332 {
333     while (actions != NULL) {
334         String proc;
335
336         *sb->current++ = ' ';
337
338         if (accelWidget) {
339             /* accelerator */
340             String name = XtName(accelWidget);
341             int nameLen = strlen(name);
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(
360     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             unsigned int type = sTypeMatch->eventType;
400             unsigned int t = typeMatch->eventType;
401             if (   (type == ButtonPress   && t != ButtonRelease)
402                 || (type == ButtonRelease && t != ButtonPress)
403                 || (type == KeyPress      && t != KeyRelease)
404                 || (type == KeyRelease    && t != KeyPress)
405                 || typeMatch->eventCode != sTypeMatch->eventCode
406                 || modMatch->modifiers != sModMatch->modifiers
407                 || modMatch->modifierMask != sModMatch->modifierMask
408                 || modMatch->lateModifiers != sModMatch->lateModifiers
409                 || typeMatch->eventCodeMask != sTypeMatch->eventCodeMask
410                 || typeMatch->matchEvent != sTypeMatch->matchEvent
411                 || modMatch->standard != sModMatch->standard)
412                 /* not inverse of starting event, either */
413                 break;
414         }
415     }
416     *countP = repeatCount;
417     UNLOCK_PROCESS;
418     return isCycle;
419 }
420
421 static void PrintComplexState(
422     TMStringBuf sb,
423     Boolean     includeRHS,
424     StatePtr    state,
425     TMStateTree stateTree,
426     Widget      accelWidget,
427     Display     *dpy)
428 {
429     int                 clickCount = 0;
430     Boolean             cycle;
431     StatePtr            nextLevel = NULL;
432     StatePtr            triggerState = NULL;
433
434     /* print the current state */
435     if (! state) return;
436     LOCK_PROCESS;
437     cycle = LookAheadForCycleOrMulticlick(state, &triggerState, &clickCount,
438                                           &nextLevel);
439
440     PrintEvent(sb, TMGetTypeMatch(triggerState->typeIndex),
441                TMGetModifierMatch(triggerState->modIndex), dpy);
442
443     if (cycle || clickCount) {
444         if (clickCount)
445             sprintf(sb->current, "(%d%s)", clickCount+1, cycle ? "+" : "");
446         else
447             (void) strncpy(sb->current, "(+)", 4);
448         sb->current += strlen(sb->current);
449         if (! state->actions && nextLevel)
450             state = nextLevel;
451         while (! state->actions && ! state->isCycleEnd)
452             state = state->nextLevel;   /* should be trigger state */
453     }
454
455     if (state->actions) {
456         if (includeRHS) {
457             CHECK_STR_OVERFLOW(sb);
458             *sb->current++ = ':';
459             PrintActions(sb,
460                          state->actions,
461                          ((TMSimpleStateTree)stateTree)->quarkTbl,
462                          accelWidget);
463             *sb->current++ = '\n';
464         }
465     }
466     else {
467         if (state->nextLevel && !cycle && !clickCount)
468             *sb->current++ = ',';
469         else {
470             /* no actions are attached to this production */
471             *sb->current++ = ':';
472             *sb->current++ = '\n';
473         }
474     }
475     *sb->current = '\0';
476
477     /* print succeeding states */
478     if (state->nextLevel && !cycle && !clickCount)
479         PrintComplexState(sb, includeRHS, state->nextLevel,
480                           stateTree, accelWidget, dpy);
481     UNLOCK_PROCESS;
482 }
483
484 typedef struct{
485     TMShortCard tIndex;
486     TMShortCard bIndex;
487 }PrintRec, *Print;
488
489 static int FindNextMatch(
490     PrintRec            *printData,
491     TMShortCard         numPrints,
492     XtTranslations      xlations,
493     TMBranchHead        branchHead,
494     StatePtr            nextLevel,
495     TMShortCard         startIndex)
496 {
497     TMShortCard         i;
498     TMComplexStateTree  stateTree;
499     StatePtr            currState, candState;
500     Boolean             noMatch = True;
501     TMBranchHead        prBranchHead;
502
503     for (i = startIndex; noMatch && i < numPrints; i++) {
504         stateTree = (TMComplexStateTree)
505           xlations->stateTreeTbl[printData[i].tIndex];
506         prBranchHead =
507           &(stateTree->branchHeadTbl[printData[i].bIndex]);
508
509         if ((prBranchHead->typeIndex == branchHead->typeIndex) &&
510             (prBranchHead->modIndex == branchHead->modIndex)) {
511             if (prBranchHead->isSimple) {
512                 if (!nextLevel)
513                   return i;
514             }
515             else {
516                 currState = TMComplexBranchHead(stateTree, prBranchHead);
517                 currState = currState->nextLevel;
518                 candState = nextLevel;
519                 for (;
520                      ((currState && !currState->isCycleEnd) &&
521                       (candState && !candState->isCycleEnd));
522                      currState = currState->nextLevel,
523                      candState = candState->nextLevel) {
524                     if ((currState->typeIndex != candState->typeIndex) ||
525                         (currState->modIndex != candState->modIndex))
526                       break;
527                 }
528                 if (candState == currState) {
529                     return i;
530                 }
531             }
532         }
533     }
534     return TM_NO_MATCH;
535 }
536
537 static void ProcessLaterMatches(
538     PrintRec    *printData,
539     XtTranslations xlations,
540     TMShortCard tIndex,
541     int bIndex,
542     TMShortCard *numPrintsRtn)
543 {
544     TMComplexStateTree  stateTree;
545     int                 i, j;
546     TMBranchHead        branchHead, matchBranch = NULL;
547
548     for (i = tIndex; i < (int)xlations->numStateTrees; i++) {
549         stateTree = (TMComplexStateTree)xlations->stateTreeTbl[i];
550         if (i == tIndex) {
551             matchBranch = &stateTree->branchHeadTbl[bIndex];
552             j = bIndex+1;
553         }
554         else j = 0;
555         for (branchHead = &stateTree->branchHeadTbl[j];
556              j < (int)stateTree->numBranchHeads;
557              j++, branchHead++) {
558             if ((branchHead->typeIndex == matchBranch->typeIndex) &&
559                 (branchHead->modIndex == matchBranch->modIndex)) {
560                 StatePtr state;
561                 if (!branchHead->isSimple)
562                   state = TMComplexBranchHead(stateTree, branchHead);
563                 else
564                   state = NULL;
565                 if ((!branchHead->isSimple || branchHead->hasActions) &&
566                     (FindNextMatch(printData,
567                                    *numPrintsRtn,
568                                    xlations,
569                                    branchHead,
570                                    (state ? state->nextLevel : NULL),
571                                    0) == TM_NO_MATCH)) {
572                     printData[*numPrintsRtn].tIndex = i;
573                     printData[*numPrintsRtn].bIndex = j;
574                     (*numPrintsRtn)++;
575                 }
576             }
577         }
578     }
579 }
580
581 static void ProcessStateTree(
582     PrintRec    *printData,
583     XtTranslations xlations,
584     TMShortCard tIndex,
585     TMShortCard *numPrintsRtn)
586 {
587     TMComplexStateTree stateTree;
588     int                 i;
589     TMBranchHead        branchHead;
590
591     stateTree = (TMComplexStateTree)xlations->stateTreeTbl[tIndex];
592
593     for (i = 0, branchHead = stateTree->branchHeadTbl;
594          i < (int)stateTree->numBranchHeads;
595          i++, branchHead++) {
596         StatePtr state;
597         if (!branchHead->isSimple)
598           state = TMComplexBranchHead(stateTree, branchHead);
599         else
600           state = NULL;
601         if (FindNextMatch(printData, *numPrintsRtn, xlations, branchHead,
602                           (state ? state->nextLevel : NULL), 0)
603             == TM_NO_MATCH) {
604             if (!branchHead->isSimple || branchHead->hasActions) {
605                 printData[*numPrintsRtn].tIndex = tIndex;
606                 printData[*numPrintsRtn].bIndex = i;
607                 (*numPrintsRtn)++;
608             }
609             LOCK_PROCESS;
610             if (_XtGlobalTM.newMatchSemantics == False)
611               ProcessLaterMatches(printData,
612                                   xlations,
613                                   tIndex,
614                                   i,
615                                   numPrintsRtn);
616             UNLOCK_PROCESS;
617         }
618     }
619 }
620
621 static void PrintState(
622     TMStringBuf sb,
623     TMStateTree tree,
624     TMBranchHead branchHead,
625     Boolean     includeRHS,
626     Widget      accelWidget,
627     Display     *dpy)
628 {
629     TMComplexStateTree stateTree = (TMComplexStateTree)tree;
630     LOCK_PROCESS;
631     if (branchHead->isSimple) {
632         PrintEvent(sb,
633                    TMGetTypeMatch(branchHead->typeIndex),
634                    TMGetModifierMatch(branchHead->modIndex),
635                    dpy);
636         if (includeRHS) {
637             ActionRec   actRec;
638
639             CHECK_STR_OVERFLOW(sb);
640             *sb->current++ = ':';
641             actRec.idx = TMBranchMore(branchHead);
642             actRec.num_params = 0;
643             actRec.params = NULL;
644             actRec.next = NULL;
645             PrintActions(sb,
646                          &actRec,
647                          stateTree->quarkTbl,
648                          accelWidget);
649             *sb->current++ = '\n';
650         }
651         else
652           *sb->current++ = ',';
653 #ifdef TRACE_TM
654         if (!branchHead->hasActions)
655           printf(" !! no actions !! ");
656 #endif
657     }
658         else { /* it's a complex branchHead */
659             StatePtr state = TMComplexBranchHead(stateTree, branchHead);
660             PrintComplexState(sb,
661                               includeRHS,
662                               state,
663                               tree,
664                               accelWidget,
665                               (Display *)NULL);
666         }
667     *sb->current = '\0';
668     UNLOCK_PROCESS;
669 }
670
671 String _XtPrintXlations(
672     Widget              w,
673     XtTranslations      xlations,
674     Widget              accelWidget,
675     _XtBoolean          includeRHS)
676 {
677     register Cardinal   i;
678 #define STACKPRINTSIZE 250
679     PrintRec            stackPrints[STACKPRINTSIZE];
680     PrintRec            *prints;
681     TMStringBufRec      sbRec, *sb = &sbRec;
682     TMShortCard         numPrints, maxPrints;
683 #ifdef TRACE_TM
684     TMBindData          bindData = (TMBindData)w->core.tm.proc_table;
685     Boolean             hasAccel = (accelWidget ? True : False);
686 #endif /* TRACE_TM */
687     if (xlations == NULL) return NULL;
688
689     sb->current = sb->start = __XtMalloc((Cardinal)1000);
690     sb->max = 1000;
691     maxPrints = 0;
692     for (i = 0; i < xlations->numStateTrees; i++)
693         maxPrints +=
694           ((TMSimpleStateTree)(xlations->stateTreeTbl[i]))->numBranchHeads;
695     prints = (PrintRec *)
696       XtStackAlloc(maxPrints * sizeof(PrintRec), stackPrints);
697
698     numPrints = 0;
699     for (i = 0; i < xlations->numStateTrees; i++)
700       ProcessStateTree(prints, xlations, i, &numPrints);
701
702     for (i = 0; i < numPrints; i++) {
703         TMSimpleStateTree stateTree = (TMSimpleStateTree)
704           xlations->stateTreeTbl[prints[i].tIndex];
705         TMBranchHead branchHead =
706           &stateTree->branchHeadTbl[prints[i].bIndex];
707 #ifdef TRACE_TM
708         TMComplexBindProcs      complexBindProcs;
709
710         if (hasAccel == False) {
711             accelWidget = NULL;
712             if (bindData->simple.isComplex) {
713                 complexBindProcs = TMGetComplexBindEntry(bindData, 0);
714                 accelWidget = complexBindProcs[prints[i].tIndex].widget;
715             }
716         }
717 #endif /* TRACE_TM */
718         PrintState(sb, (TMStateTree)stateTree, branchHead,
719                    includeRHS, accelWidget, XtDisplay(w));
720     }
721     XtStackFree((XtPointer)prints, (XtPointer)stackPrints);
722     return (sb->start);
723 }
724
725
726 #ifndef NO_MIT_HACKS
727 /*ARGSUSED*/
728 void _XtDisplayTranslations(
729     Widget widget,
730     XEvent *event,
731     String *params,
732     Cardinal *num_params)
733 {
734     String      xString;
735
736     xString =  _XtPrintXlations(widget,
737                                 widget->core.tm.translations,
738                                 NULL,
739                                 True);
740     if (xString) {
741         printf("%s\n",xString);
742         XtFree(xString);
743     }
744 }
745
746 /*ARGSUSED*/
747 void _XtDisplayAccelerators(
748     Widget widget,
749     XEvent *event,
750     String *params,
751     Cardinal *num_params)
752 {
753     String      xString;
754
755
756     xString =  _XtPrintXlations(widget,
757                                 widget->core.accelerators,
758                                 NULL,
759                                 True);
760     if (xString) {
761         printf("%s\n",xString);
762         XtFree(xString);
763     }
764 }
765
766 /*ARGSUSED*/
767 void _XtDisplayInstalledAccelerators(
768     Widget widget,
769     XEvent *event,
770     String *params,
771     Cardinal *num_params)
772 {
773     Widget eventWidget
774         = XtWindowToWidget(event->xany.display, event->xany.window);
775     register Cardinal   i;
776     TMStringBufRec      sbRec, *sb = &sbRec;
777     XtTranslations      xlations;
778 #define STACKPRINTSIZE 250
779     PrintRec            stackPrints[STACKPRINTSIZE];
780     PrintRec            *prints;
781     TMShortCard         numPrints, maxPrints;
782     TMBindData  bindData ;
783     TMComplexBindProcs  complexBindProcs;
784
785     if ((eventWidget == NULL) ||
786         (eventWidget->core.tm.translations == NULL) )
787       return;
788
789     xlations = eventWidget->core.tm.translations;
790     bindData = (TMBindData) eventWidget->core.tm.proc_table;
791     if (bindData->simple.isComplex == False)
792       return;
793
794     sb->current = sb->start = __XtMalloc((Cardinal)1000);
795     sb->start[0] = '\0';
796     sb->max = 1000;
797     maxPrints = 0;
798     for (i = 0; i < xlations->numStateTrees; i++)
799         maxPrints +=
800           ((TMSimpleStateTree)xlations->stateTreeTbl[i])->numBranchHeads;
801     prints = (PrintRec *)
802       XtStackAlloc(maxPrints * sizeof(PrintRec), stackPrints);
803
804     numPrints = 0;
805
806     complexBindProcs = TMGetComplexBindEntry(bindData, 0);
807     for (i = 0;
808          i < xlations->numStateTrees;
809          i++, complexBindProcs++) {
810         if (complexBindProcs->widget)
811           {
812               ProcessStateTree(prints, xlations, i, &numPrints);
813           }
814     }
815     for (i = 0; i < numPrints; i++) {
816         TMSimpleStateTree stateTree = (TMSimpleStateTree)
817           xlations->stateTreeTbl[prints[i].tIndex];
818         TMBranchHead branchHead =
819           &stateTree->branchHeadTbl[prints[i].bIndex];
820
821         complexBindProcs = TMGetComplexBindEntry(bindData, 0);
822
823         PrintState(sb, (TMStateTree)stateTree, branchHead, True,
824                    complexBindProcs[prints[i].tIndex].widget,
825                    XtDisplay(widget));
826     }
827     XtStackFree((XtPointer)prints, (XtPointer)stackPrints);
828     printf("%s\n", sb->start);
829     XtFree(sb->start);
830 }
831 #endif /*NO_MIT_HACKS*/
832
833 String _XtPrintActions(
834     register ActionRec *actions,
835     XrmQuark            *quarkTbl)
836 {
837     TMStringBufRec      sbRec, *sb = &sbRec;
838
839     sb->max = 1000;
840     sb->current = sb->start = __XtMalloc((Cardinal)1000);
841     PrintActions(sb,
842                  actions,
843                  quarkTbl,
844                  (Widget)NULL);
845     return sb->start;
846 }
847
848 String _XtPrintState(
849     TMStateTree         stateTree,
850     TMBranchHead        branchHead)
851 {
852     TMStringBufRec      sbRec, *sb = &sbRec;
853
854     sb->current = sb->start = __XtMalloc((Cardinal)1000);
855     sb->max = 1000;
856     PrintState(sb, stateTree, branchHead,
857                True, (Widget)NULL, (Display *)NULL);
858     return sb->start;
859 }
860
861
862 String _XtPrintEventSeq(
863     register EventSeqPtr eventSeq,
864     Display *dpy)
865 {
866     TMStringBufRec      sbRec, *sb = &sbRec;
867     TMTypeMatch         typeMatch;
868     TMModifierMatch     modMatch;
869 #define MAXSEQS 100
870     EventSeqPtr         eventSeqs[MAXSEQS];
871     TMShortCard         i, j;
872     Boolean             cycle = False;
873
874     sb->current = sb->start = __XtMalloc((Cardinal)1000);
875     sb->max = 1000;
876     for (i = 0;
877          i < MAXSEQS && eventSeq != NULL && !cycle;
878          eventSeq = eventSeq->next, i++)
879       {
880           eventSeqs[i] = eventSeq;
881           for (j = 0; j < i && !cycle; j++)
882             if (eventSeqs[j] == eventSeq)
883               cycle = True;
884       }
885     LOCK_PROCESS;
886     for (j = 0; j < i; j++) {
887         typeMatch =
888           TMGetTypeMatch(_XtGetTypeIndex(&eventSeqs[j]->event));
889         modMatch =
890           TMGetModifierMatch(_XtGetModifierIndex(&eventSeqs[j]->event));
891         PrintEvent(sb, typeMatch, modMatch, dpy);
892         if (j < i)
893           *sb->current++ = ',';
894     }
895     UNLOCK_PROCESS;
896     return sb->start;
897 }