TMprint.c revision 249c3046
1444c061aSmrg/***********************************************************
2249c3046SmrgCopyright (c) 1993, Oracle and/or its affiliates. All rights reserved.
31477040fSmrg
41477040fSmrgPermission is hereby granted, free of charge, to any person obtaining a
51477040fSmrgcopy of this software and associated documentation files (the "Software"),
61477040fSmrgto deal in the Software without restriction, including without limitation
71477040fSmrgthe rights to use, copy, modify, merge, publish, distribute, sublicense,
81477040fSmrgand/or sell copies of the Software, and to permit persons to whom the
91477040fSmrgSoftware is furnished to do so, subject to the following conditions:
101477040fSmrg
111477040fSmrgThe above copyright notice and this permission notice (including the next
121477040fSmrgparagraph) shall be included in all copies or substantial portions of the
131477040fSmrgSoftware.
141477040fSmrg
151477040fSmrgTHE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
161477040fSmrgIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
171477040fSmrgFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
181477040fSmrgTHE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
191477040fSmrgLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
201477040fSmrgFROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
211477040fSmrgDEALINGS IN THE SOFTWARE.
221477040fSmrg
231477040fSmrgCopyright 1987, 1988 by Digital Equipment Corporation, Maynard, Massachusetts.
24444c061aSmrg
25444c061aSmrg                        All Rights Reserved
26444c061aSmrg
27444c061aSmrgPermission to use, copy, modify, and distribute this software and its
28444c061aSmrgdocumentation for any purpose and without fee is hereby granted,
29444c061aSmrgprovided that the above copyright notice appear in all copies and that
30444c061aSmrgboth that copyright notice and this permission notice appear in
311477040fSmrgsupporting documentation, and that the name of Digital not be
32444c061aSmrgused in advertising or publicity pertaining to distribution of the
33444c061aSmrgsoftware without specific, written prior permission.
34444c061aSmrg
35444c061aSmrgDIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
36444c061aSmrgALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
37444c061aSmrgDIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
38444c061aSmrgANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
39444c061aSmrgWHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
40444c061aSmrgARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
41444c061aSmrgSOFTWARE.
42444c061aSmrg
43444c061aSmrg******************************************************************/
44444c061aSmrg
45444c061aSmrg/*
46444c061aSmrg
47444c061aSmrgCopyright 1987, 1988, 1998  The Open Group
48444c061aSmrg
49444c061aSmrgPermission to use, copy, modify, distribute, and sell this software and its
50444c061aSmrgdocumentation for any purpose is hereby granted without fee, provided that
51444c061aSmrgthe above copyright notice appear in all copies and that both that
52444c061aSmrgcopyright notice and this permission notice appear in supporting
53444c061aSmrgdocumentation.
54444c061aSmrg
55444c061aSmrgThe above copyright notice and this permission notice shall be included in
56444c061aSmrgall copies or substantial portions of the Software.
57444c061aSmrg
58444c061aSmrgTHE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
59444c061aSmrgIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
60444c061aSmrgFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
61444c061aSmrgOPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
62444c061aSmrgAN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
63444c061aSmrgCONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
64444c061aSmrg
65444c061aSmrgExcept as contained in this notice, the name of The Open Group shall not be
66444c061aSmrgused in advertising or otherwise to promote the sale, use or other dealings
67444c061aSmrgin this Software without prior written authorization from The Open Group.
68444c061aSmrg
69444c061aSmrg*/
70444c061aSmrg
71444c061aSmrg/*LINTLIBRARY*/
72444c061aSmrg#ifdef HAVE_CONFIG_H
73444c061aSmrg#include <config.h>
74444c061aSmrg#endif
75444c061aSmrg#include "IntrinsicI.h"
76444c061aSmrg#include <stdio.h>
77444c061aSmrg
78444c061aSmrgtypedef struct _TMStringBufRec{
79444c061aSmrg    String	start;
80444c061aSmrg    String	current;
81444c061aSmrg    Cardinal	max;
82444c061aSmrg}TMStringBufRec, *TMStringBuf;
83444c061aSmrg
84444c061aSmrg
85444c061aSmrg#define STR_THRESHOLD 25
86444c061aSmrg#define STR_INCAMOUNT 100
87444c061aSmrg#define CHECK_STR_OVERFLOW(sb) \
88444c061aSmrgif (sb->current - sb->start > (int)sb->max - STR_THRESHOLD) 	\
89444c061aSmrg{ String old = sb->start; \
90444c061aSmrg  sb->start = XtRealloc(old, (Cardinal)(sb->max += STR_INCAMOUNT)); \
91444c061aSmrg  sb->current = sb->current - old + sb->start; \
92444c061aSmrg}
93444c061aSmrg
94444c061aSmrg#define ExpandForChars(sb, nchars ) \
95444c061aSmrg    if ((unsigned)(sb->current - sb->start) > sb->max - STR_THRESHOLD - nchars) { \
96444c061aSmrg	String old = sb->start;					\
97444c061aSmrg	sb->start = XtRealloc(old,				\
98444c061aSmrg	    (Cardinal)(sb->max += STR_INCAMOUNT + nchars));	\
99444c061aSmrg	sb->current = sb->current - old + sb->start;		\
100444c061aSmrg    }
101444c061aSmrg
102444c061aSmrg#define ExpandToFit(sb, more) \
103444c061aSmrg{								\
104444c061aSmrg	size_t l = strlen(more);				\
105444c061aSmrg	ExpandForChars(sb, l);					\
106444c061aSmrg      }
107444c061aSmrg
108444c061aSmrgstatic void PrintModifiers(
109444c061aSmrg    TMStringBuf	sb,
110444c061aSmrg    unsigned long mask, unsigned long mod)
111444c061aSmrg{
112444c061aSmrg    Boolean notfirst = False;
113444c061aSmrg    CHECK_STR_OVERFLOW(sb);
114444c061aSmrg
115444c061aSmrg    if (mask == ~0UL && mod == 0) {
116444c061aSmrg	*sb->current++ = '!';
117444c061aSmrg	*sb->current = '\0';
118444c061aSmrg	return;
119444c061aSmrg    }
120444c061aSmrg
121444c061aSmrg#define PRINTMOD(modmask,modstring) \
122444c061aSmrg    if (mask & modmask) {		 \
123444c061aSmrg	if (! (mod & modmask)) {	 \
124444c061aSmrg	    *sb->current++ = '~';		 \
125444c061aSmrg	    notfirst = True;		 \
126444c061aSmrg	}				 \
127444c061aSmrg	else if (notfirst)		 \
128444c061aSmrg	    *sb->current++ = ' ';		 \
129444c061aSmrg	else notfirst = True;		 \
130444c061aSmrg	strcpy(sb->current, modstring);		 \
131444c061aSmrg	sb->current += strlen(sb->current);		 \
132444c061aSmrg    }
133444c061aSmrg
134444c061aSmrg    PRINTMOD(ShiftMask, "Shift");
135444c061aSmrg    PRINTMOD(ControlMask, "Ctrl");	/* name is not CtrlMask... */
136444c061aSmrg    PRINTMOD(LockMask, "Lock");
137444c061aSmrg    PRINTMOD(Mod1Mask, "Mod1");
138444c061aSmrg    CHECK_STR_OVERFLOW(sb);
139444c061aSmrg    PRINTMOD(Mod2Mask, "Mod2");
140444c061aSmrg    PRINTMOD(Mod3Mask, "Mod3");
141444c061aSmrg    PRINTMOD(Mod4Mask, "Mod4");
142444c061aSmrg    PRINTMOD(Mod5Mask, "Mod5");
143444c061aSmrg    CHECK_STR_OVERFLOW(sb);
144444c061aSmrg    PRINTMOD(Button1Mask, "Button1");
145444c061aSmrg    PRINTMOD(Button2Mask, "Button2");
146444c061aSmrg    PRINTMOD(Button3Mask, "Button3");
147444c061aSmrg    CHECK_STR_OVERFLOW(sb);
148444c061aSmrg    PRINTMOD(Button4Mask, "Button4");
149444c061aSmrg    PRINTMOD(Button5Mask, "Button5");
150444c061aSmrg
151444c061aSmrg#undef PRINTMOD
152444c061aSmrg}
153444c061aSmrg
154444c061aSmrgstatic void PrintEventType(
155444c061aSmrg    TMStringBuf	sb,
156444c061aSmrg    unsigned long event)
157444c061aSmrg{
158444c061aSmrg    CHECK_STR_OVERFLOW(sb);
159444c061aSmrg    switch (event) {
160444c061aSmrg#define PRINTEVENT(event, name) case event: (void) strcpy(sb->current, name); break;
161444c061aSmrg	PRINTEVENT(KeyPress, "<KeyPress>")
162444c061aSmrg	PRINTEVENT(KeyRelease, "<KeyRelease>")
163444c061aSmrg	PRINTEVENT(ButtonPress, "<ButtonPress>")
164444c061aSmrg	PRINTEVENT(ButtonRelease, "<ButtonRelease>")
165444c061aSmrg	PRINTEVENT(MotionNotify, "<MotionNotify>")
166444c061aSmrg	PRINTEVENT(EnterNotify, "<EnterNotify>")
167444c061aSmrg	PRINTEVENT(LeaveNotify, "<LeaveNotify>")
168444c061aSmrg	PRINTEVENT(FocusIn, "<FocusIn>")
169444c061aSmrg	PRINTEVENT(FocusOut, "<FocusOut>")
170444c061aSmrg	PRINTEVENT(KeymapNotify, "<KeymapNotify>")
171444c061aSmrg	PRINTEVENT(Expose, "<Expose>")
172444c061aSmrg	PRINTEVENT(GraphicsExpose, "<GraphicsExpose>")
173444c061aSmrg	PRINTEVENT(NoExpose, "<NoExpose>")
174444c061aSmrg	PRINTEVENT(VisibilityNotify, "<VisibilityNotify>")
175444c061aSmrg	PRINTEVENT(CreateNotify, "<CreateNotify>")
176444c061aSmrg	PRINTEVENT(DestroyNotify, "<DestroyNotify>")
177444c061aSmrg	PRINTEVENT(UnmapNotify, "<UnmapNotify>")
178444c061aSmrg	PRINTEVENT(MapNotify, "<MapNotify>")
179444c061aSmrg	PRINTEVENT(MapRequest, "<MapRequest>")
180444c061aSmrg	PRINTEVENT(ReparentNotify, "<ReparentNotify>")
181444c061aSmrg	PRINTEVENT(ConfigureNotify, "<ConfigureNotify>")
182444c061aSmrg	PRINTEVENT(ConfigureRequest, "<ConfigureRequest>")
183444c061aSmrg	PRINTEVENT(GravityNotify, "<GravityNotify>")
184444c061aSmrg	PRINTEVENT(ResizeRequest, "<ResizeRequest>")
185444c061aSmrg	PRINTEVENT(CirculateNotify, "<CirculateNotify>")
186444c061aSmrg	PRINTEVENT(CirculateRequest, "<CirculateRequest>")
187444c061aSmrg	PRINTEVENT(PropertyNotify, "<PropertyNotify>")
188444c061aSmrg	PRINTEVENT(SelectionClear, "<SelectionClear>")
189444c061aSmrg	PRINTEVENT(SelectionRequest, "<SelectionRequest>")
190444c061aSmrg	PRINTEVENT(SelectionNotify, "<SelectionNotify>")
191444c061aSmrg	PRINTEVENT(ColormapNotify, "<ColormapNotify>")
192444c061aSmrg	PRINTEVENT(ClientMessage, "<ClientMessage>")
193444c061aSmrg	case _XtEventTimerEventType:
194444c061aSmrg	    (void) strcpy(sb->current,"<EventTimer>");
195444c061aSmrg	    break;
196444c061aSmrg	default:
197444c061aSmrg	    (void) sprintf(sb->current, "<0x%x>", (int) event);
198444c061aSmrg#undef PRINTEVENT
199444c061aSmrg    }
200444c061aSmrg    sb->current += strlen(sb->current);
201444c061aSmrg}
202444c061aSmrg
203444c061aSmrgstatic void PrintCode(
204444c061aSmrg    TMStringBuf sb,
205444c061aSmrg    unsigned long mask, unsigned long code)
206444c061aSmrg{
207444c061aSmrg    CHECK_STR_OVERFLOW(sb);
208444c061aSmrg    if (mask != 0) {
209444c061aSmrg	if (mask != ~0UL)
210444c061aSmrg	    (void) sprintf(sb->current, "0x%lx:0x%lx", mask, code);
211444c061aSmrg	else (void) sprintf(sb->current, /*"0x%lx"*/ "%d", (unsigned)code);
212444c061aSmrg	sb->current += strlen(sb->current);
213444c061aSmrg    }
214444c061aSmrg}
215444c061aSmrg
216444c061aSmrgstatic void PrintKeysym(
217444c061aSmrg    TMStringBuf sb,
218444c061aSmrg    KeySym keysym)
219444c061aSmrg{
220444c061aSmrg    String keysymName;
221444c061aSmrg
222444c061aSmrg    if (keysym == 0) return;
223444c061aSmrg
224444c061aSmrg    CHECK_STR_OVERFLOW(sb);
225444c061aSmrg    keysymName = XKeysymToString(keysym);
226444c061aSmrg    if (keysymName == NULL)
227444c061aSmrg      PrintCode(sb,~0UL,(unsigned long)keysym);
228444c061aSmrg    else {
229444c061aSmrg      ExpandToFit(sb, keysymName);
230444c061aSmrg      strcpy(sb->current, keysymName);
231444c061aSmrg      sb->current += strlen(sb->current);
232444c061aSmrg    }
233444c061aSmrg}
234444c061aSmrg
235444c061aSmrgstatic void PrintAtom(
236444c061aSmrg    TMStringBuf sb,
237444c061aSmrg    Display *dpy,
238444c061aSmrg    Atom atom)
239444c061aSmrg{
240444c061aSmrg    String atomName;
241444c061aSmrg
242444c061aSmrg    if (atom == 0) return;
243444c061aSmrg
244444c061aSmrg    atomName = (dpy ? XGetAtomName(dpy, atom) : NULL);
245444c061aSmrg
246444c061aSmrg    if (! atomName)
247444c061aSmrg      PrintCode(sb,~0UL,(unsigned long)atom);
248444c061aSmrg    else {
249444c061aSmrg      ExpandToFit( sb, atomName );
250444c061aSmrg      strcpy(sb->current, atomName);
251444c061aSmrg      sb->current += strlen(sb->current);
252444c061aSmrg      XFree(atomName);
253444c061aSmrg    }
254444c061aSmrg}
255444c061aSmrg
256444c061aSmrgstatic	void PrintLateModifiers(
257444c061aSmrg    TMStringBuf	sb,
258444c061aSmrg    LateBindingsPtr lateModifiers)
259444c061aSmrg{
260444c061aSmrg    for (; lateModifiers->keysym; lateModifiers++) {
261444c061aSmrg	CHECK_STR_OVERFLOW(sb);
262444c061aSmrg	if (lateModifiers->knot) {
263444c061aSmrg	    *sb->current++ = '~';
264444c061aSmrg	} else {
265444c061aSmrg	    *sb->current++ = ' ';
266444c061aSmrg	}
267444c061aSmrg	strcpy(sb->current, XKeysymToString(lateModifiers->keysym));
268444c061aSmrg	sb->current += strlen(sb->current);
269444c061aSmrg	if (lateModifiers->pair) {
270444c061aSmrg	    *(sb->current -= 2) = '\0';	/* strip "_L" */
271444c061aSmrg	    lateModifiers++;	/* skip _R keysym */
272444c061aSmrg	}
273444c061aSmrg    }
274444c061aSmrg}
275444c061aSmrg
276444c061aSmrgstatic void PrintEvent(
277444c061aSmrg    TMStringBuf sb,
278444c061aSmrg    register TMTypeMatch typeMatch,
279444c061aSmrg    register TMModifierMatch modMatch,
280444c061aSmrg    Display *dpy)
281444c061aSmrg{
282444c061aSmrg    if (modMatch->standard) *sb->current++ = ':';
283444c061aSmrg
284444c061aSmrg    PrintModifiers(sb, modMatch->modifierMask, modMatch->modifiers);
285444c061aSmrg    if (modMatch->lateModifiers != NULL)
286444c061aSmrg      PrintLateModifiers(sb, modMatch->lateModifiers);
287444c061aSmrg    PrintEventType(sb, typeMatch->eventType);
288444c061aSmrg    switch (typeMatch->eventType) {
289444c061aSmrg      case KeyPress:
290444c061aSmrg      case KeyRelease:
291444c061aSmrg	PrintKeysym(sb, (KeySym)typeMatch->eventCode);
292444c061aSmrg	break;
293444c061aSmrg
294444c061aSmrg      case PropertyNotify:
295444c061aSmrg      case SelectionClear:
296444c061aSmrg      case SelectionRequest:
297444c061aSmrg      case SelectionNotify:
298444c061aSmrg      case ClientMessage:
299444c061aSmrg	PrintAtom(sb, dpy, (Atom)typeMatch->eventCode);
300444c061aSmrg	break;
301444c061aSmrg
302444c061aSmrg      default:
303444c061aSmrg	PrintCode(sb, typeMatch->eventCodeMask, typeMatch->eventCode);
304444c061aSmrg    }
305444c061aSmrg}
306444c061aSmrg
307444c061aSmrgstatic void PrintParams(
308444c061aSmrg    TMStringBuf	sb,
309444c061aSmrg    String	*params,
310444c061aSmrg    Cardinal num_params)
311444c061aSmrg{
312444c061aSmrg    register Cardinal i;
313444c061aSmrg    for (i = 0; i<num_params; i++) {
314444c061aSmrg	ExpandToFit( sb, params[i] );
315444c061aSmrg	if (i != 0) {
316444c061aSmrg	    *sb->current++ = ',';
317444c061aSmrg	    *sb->current++ = ' ';
318444c061aSmrg	}
319444c061aSmrg	*sb->current++ = '"';
320444c061aSmrg	strcpy(sb->current, params[i]);
321444c061aSmrg	sb->current += strlen(sb->current);
322444c061aSmrg	*sb->current++ = '"';
323444c061aSmrg    }
324444c061aSmrg    *sb->current = '\0';
325444c061aSmrg}
326444c061aSmrg
327444c061aSmrgstatic void PrintActions(
328444c061aSmrg    TMStringBuf	sb,
329444c061aSmrg    register ActionPtr actions,
330444c061aSmrg    XrmQuark *quarkTbl,
331444c061aSmrg    Widget   accelWidget)
332444c061aSmrg{
333444c061aSmrg    while (actions != NULL) {
334444c061aSmrg	String proc;
335444c061aSmrg
336444c061aSmrg	*sb->current++ = ' ';
337444c061aSmrg
338444c061aSmrg	if (accelWidget) {
339444c061aSmrg	    /* accelerator */
340444c061aSmrg	    String name = XtName(accelWidget);
341444c061aSmrg	    int nameLen = strlen(name);
342444c061aSmrg	    ExpandForChars(sb,  nameLen );
343444c061aSmrg	    XtMemmove(sb->current, name, nameLen );
344444c061aSmrg	    sb->current += nameLen;
345444c061aSmrg	    *sb->current++ = '`';
346444c061aSmrg	}
347444c061aSmrg	proc = XrmQuarkToString(quarkTbl[actions->idx]);
348444c061aSmrg	ExpandToFit( sb, proc );
349444c061aSmrg	strcpy(sb->current, proc);
350444c061aSmrg	sb->current += strlen(proc);
351444c061aSmrg	*sb->current++ = '(';
352444c061aSmrg	PrintParams(sb, actions->params, actions->num_params);
353444c061aSmrg	*sb->current++ = ')';
354444c061aSmrg	actions = actions->next;
355444c061aSmrg    }
356444c061aSmrg    *sb->current = '\0';
357444c061aSmrg}
358444c061aSmrg
359444c061aSmrgstatic Boolean LookAheadForCycleOrMulticlick(
360444c061aSmrg    register StatePtr state,
361444c061aSmrg    StatePtr *state_return,	/* state to print, usually startState */
362444c061aSmrg    int *countP,
363444c061aSmrg    StatePtr *nextLevelP)
364444c061aSmrg{
365444c061aSmrg    int repeatCount = 0;
366444c061aSmrg    StatePtr	startState = state;
367444c061aSmrg    Boolean	isCycle = startState->isCycleEnd;
368444c061aSmrg    TMTypeMatch sTypeMatch;
369444c061aSmrg    TMModifierMatch sModMatch;
370444c061aSmrg
371444c061aSmrg    LOCK_PROCESS;
372444c061aSmrg    sTypeMatch = TMGetTypeMatch(startState->typeIndex);
373444c061aSmrg    sModMatch = TMGetModifierMatch(startState->modIndex);
374444c061aSmrg
375444c061aSmrg    *state_return = startState;
376444c061aSmrg
377444c061aSmrg    for (state = state->nextLevel; state != NULL; state = state->nextLevel) {
378444c061aSmrg	TMTypeMatch typeMatch = TMGetTypeMatch(state->typeIndex);
379444c061aSmrg	TMModifierMatch modMatch = TMGetModifierMatch(state->modIndex);
380444c061aSmrg
381444c061aSmrg	/* try to pick up the correct state with actions, to be printed */
382444c061aSmrg	/* This is to accommodate <ButtonUp>(2+), for example */
383444c061aSmrg	if (state->isCycleStart)
384444c061aSmrg	    *state_return = state;
385444c061aSmrg
386444c061aSmrg	if (state->isCycleEnd) {
387444c061aSmrg	    *countP = repeatCount;
388444c061aSmrg	    UNLOCK_PROCESS;
389444c061aSmrg	    return True;
390444c061aSmrg	}
391444c061aSmrg	if ((startState->typeIndex == state->typeIndex) &&
392444c061aSmrg	    (startState->modIndex == state->modIndex)) {
393444c061aSmrg	    repeatCount++;
394444c061aSmrg	    *nextLevelP = state;
395444c061aSmrg	}
396444c061aSmrg	else if (typeMatch->eventType == _XtEventTimerEventType)
397444c061aSmrg	  continue;
398444c061aSmrg	else /* not same event as starting event and not timer */ {
399444c061aSmrg	    unsigned int type = sTypeMatch->eventType;
400444c061aSmrg	    unsigned int t = typeMatch->eventType;
401444c061aSmrg	    if (   (type == ButtonPress	  && t != ButtonRelease)
402444c061aSmrg		|| (type == ButtonRelease && t != ButtonPress)
403444c061aSmrg		|| (type == KeyPress	  && t != KeyRelease)
404444c061aSmrg		|| (type == KeyRelease	  && t != KeyPress)
405444c061aSmrg		|| typeMatch->eventCode != sTypeMatch->eventCode
406444c061aSmrg		|| modMatch->modifiers != sModMatch->modifiers
407444c061aSmrg		|| modMatch->modifierMask != sModMatch->modifierMask
408444c061aSmrg		|| modMatch->lateModifiers != sModMatch->lateModifiers
409444c061aSmrg		|| typeMatch->eventCodeMask != sTypeMatch->eventCodeMask
410444c061aSmrg		|| typeMatch->matchEvent != sTypeMatch->matchEvent
411444c061aSmrg		|| modMatch->standard != sModMatch->standard)
412444c061aSmrg		/* not inverse of starting event, either */
413444c061aSmrg		break;
414444c061aSmrg	}
415444c061aSmrg    }
416444c061aSmrg    *countP = repeatCount;
417444c061aSmrg    UNLOCK_PROCESS;
418444c061aSmrg    return isCycle;
419444c061aSmrg}
420444c061aSmrg
421444c061aSmrgstatic void PrintComplexState(
422444c061aSmrg    TMStringBuf	sb,
423444c061aSmrg    Boolean	includeRHS,
424444c061aSmrg    StatePtr 	state,
425444c061aSmrg    TMStateTree stateTree,
426444c061aSmrg    Widget	accelWidget,
427444c061aSmrg    Display 	*dpy)
428444c061aSmrg{
429444c061aSmrg    int 		clickCount = 0;
430444c061aSmrg    Boolean 		cycle;
431444c061aSmrg    StatePtr 		nextLevel = NULL;
432444c061aSmrg    StatePtr		triggerState = NULL;
433444c061aSmrg
434444c061aSmrg    /* print the current state */
435444c061aSmrg    if (! state) return;
436444c061aSmrg    LOCK_PROCESS;
437444c061aSmrg    cycle = LookAheadForCycleOrMulticlick(state, &triggerState, &clickCount,
438444c061aSmrg					  &nextLevel);
439444c061aSmrg
440444c061aSmrg    PrintEvent(sb, TMGetTypeMatch(triggerState->typeIndex),
441444c061aSmrg	       TMGetModifierMatch(triggerState->modIndex), dpy);
442444c061aSmrg
443444c061aSmrg    if (cycle || clickCount) {
444444c061aSmrg	if (clickCount)
445444c061aSmrg	    sprintf(sb->current, "(%d%s)", clickCount+1, cycle ? "+" : "");
446444c061aSmrg	else
447444c061aSmrg	    (void) strncpy(sb->current, "(+)", 4);
448444c061aSmrg	sb->current += strlen(sb->current);
449444c061aSmrg	if (! state->actions && nextLevel)
450444c061aSmrg	    state = nextLevel;
451444c061aSmrg	while (! state->actions && ! state->isCycleEnd)
452444c061aSmrg	    state = state->nextLevel;	/* should be trigger state */
453444c061aSmrg    }
454444c061aSmrg
455444c061aSmrg    if (state->actions) {
456444c061aSmrg	if (includeRHS) {
457444c061aSmrg	    CHECK_STR_OVERFLOW(sb);
458444c061aSmrg	    *sb->current++ = ':';
459444c061aSmrg	    PrintActions(sb,
460444c061aSmrg			 state->actions,
461444c061aSmrg			 ((TMSimpleStateTree)stateTree)->quarkTbl,
462444c061aSmrg			 accelWidget);
463444c061aSmrg	    *sb->current++ = '\n';
464444c061aSmrg	}
465444c061aSmrg    }
466444c061aSmrg    else {
467444c061aSmrg	if (state->nextLevel && !cycle && !clickCount)
468444c061aSmrg	    *sb->current++ = ',';
469444c061aSmrg	else {
470444c061aSmrg	    /* no actions are attached to this production */
471444c061aSmrg	    *sb->current++ = ':';
472444c061aSmrg	    *sb->current++ = '\n';
473444c061aSmrg	}
474444c061aSmrg    }
475444c061aSmrg    *sb->current = '\0';
476444c061aSmrg
477444c061aSmrg    /* print succeeding states */
478444c061aSmrg    if (state->nextLevel && !cycle && !clickCount)
479444c061aSmrg	PrintComplexState(sb, includeRHS, state->nextLevel,
480444c061aSmrg			  stateTree, accelWidget, dpy);
481444c061aSmrg    UNLOCK_PROCESS;
482444c061aSmrg}
483444c061aSmrg
484444c061aSmrgtypedef struct{
485444c061aSmrg    TMShortCard	tIndex;
486444c061aSmrg    TMShortCard	bIndex;
487444c061aSmrg}PrintRec, *Print;
488444c061aSmrg
489444c061aSmrgstatic int FindNextMatch(
490444c061aSmrg    PrintRec		*printData,
491444c061aSmrg    TMShortCard		numPrints,
492444c061aSmrg    XtTranslations 	xlations,
493444c061aSmrg    TMBranchHead	branchHead,
494444c061aSmrg    StatePtr 		nextLevel,
495444c061aSmrg    TMShortCard		startIndex)
496444c061aSmrg{
497444c061aSmrg    TMShortCard		i;
498444c061aSmrg    TMComplexStateTree 	stateTree;
499444c061aSmrg    StatePtr		currState, candState;
500444c061aSmrg    Boolean		noMatch = True;
501444c061aSmrg    TMBranchHead	prBranchHead;
502444c061aSmrg
503444c061aSmrg    for (i = startIndex; noMatch && i < numPrints; i++) {
504444c061aSmrg	stateTree = (TMComplexStateTree)
505444c061aSmrg	  xlations->stateTreeTbl[printData[i].tIndex];
506444c061aSmrg	prBranchHead =
507444c061aSmrg	  &(stateTree->branchHeadTbl[printData[i].bIndex]);
508444c061aSmrg
509444c061aSmrg	if ((prBranchHead->typeIndex == branchHead->typeIndex) &&
510444c061aSmrg	    (prBranchHead->modIndex == branchHead->modIndex)) {
511444c061aSmrg	    if (prBranchHead->isSimple) {
512444c061aSmrg		if (!nextLevel)
513444c061aSmrg		  return i;
514444c061aSmrg	    }
515444c061aSmrg	    else {
516444c061aSmrg		currState = TMComplexBranchHead(stateTree, prBranchHead);
517444c061aSmrg		currState = currState->nextLevel;
518444c061aSmrg		candState = nextLevel;
519444c061aSmrg		for (;
520444c061aSmrg		     ((currState && !currState->isCycleEnd) &&
521444c061aSmrg		      (candState && !candState->isCycleEnd));
522444c061aSmrg		     currState = currState->nextLevel,
523444c061aSmrg		     candState = candState->nextLevel) {
524444c061aSmrg		    if ((currState->typeIndex != candState->typeIndex) ||
525444c061aSmrg			(currState->modIndex != candState->modIndex))
526444c061aSmrg		      break;
527444c061aSmrg		}
528444c061aSmrg		if (candState == currState) {
529444c061aSmrg		    return i;
530444c061aSmrg		}
531444c061aSmrg	    }
532444c061aSmrg	}
533444c061aSmrg    }
534444c061aSmrg    return TM_NO_MATCH;
535444c061aSmrg}
536444c061aSmrg
537444c061aSmrgstatic void ProcessLaterMatches(
538444c061aSmrg    PrintRec	*printData,
539444c061aSmrg    XtTranslations xlations,
540444c061aSmrg    TMShortCard	tIndex,
541444c061aSmrg    int bIndex,
542444c061aSmrg    TMShortCard	*numPrintsRtn)
543444c061aSmrg{
544444c061aSmrg    TMComplexStateTree 	stateTree;
545444c061aSmrg    int			i, j;
546444c061aSmrg    TMBranchHead	branchHead, matchBranch = NULL;
547444c061aSmrg
548444c061aSmrg    for (i = tIndex; i < (int)xlations->numStateTrees; i++) {
549444c061aSmrg	stateTree = (TMComplexStateTree)xlations->stateTreeTbl[i];
550444c061aSmrg	if (i == tIndex) {
551444c061aSmrg	    matchBranch = &stateTree->branchHeadTbl[bIndex];
552444c061aSmrg	    j = bIndex+1;
553444c061aSmrg	}
554444c061aSmrg	else j = 0;
555444c061aSmrg	for (branchHead = &stateTree->branchHeadTbl[j];
556444c061aSmrg	     j < (int)stateTree->numBranchHeads;
557444c061aSmrg	     j++, branchHead++) {
558444c061aSmrg	    if ((branchHead->typeIndex == matchBranch->typeIndex) &&
559444c061aSmrg		(branchHead->modIndex == matchBranch->modIndex)) {
560444c061aSmrg		StatePtr state;
561444c061aSmrg		if (!branchHead->isSimple)
562444c061aSmrg		  state = TMComplexBranchHead(stateTree, branchHead);
563444c061aSmrg		else
564444c061aSmrg		  state = NULL;
565444c061aSmrg		if ((!branchHead->isSimple || branchHead->hasActions) &&
566444c061aSmrg		    (FindNextMatch(printData,
567444c061aSmrg				   *numPrintsRtn,
568444c061aSmrg				   xlations,
569444c061aSmrg				   branchHead,
570444c061aSmrg				   (state ? state->nextLevel : NULL),
571444c061aSmrg				   0) == TM_NO_MATCH)) {
572444c061aSmrg		    printData[*numPrintsRtn].tIndex = i;
573444c061aSmrg		    printData[*numPrintsRtn].bIndex = j;
574444c061aSmrg		    (*numPrintsRtn)++;
575444c061aSmrg		}
576444c061aSmrg	    }
577444c061aSmrg	}
578444c061aSmrg    }
579444c061aSmrg}
580444c061aSmrg
581444c061aSmrgstatic void ProcessStateTree(
582444c061aSmrg    PrintRec	*printData,
583444c061aSmrg    XtTranslations xlations,
584444c061aSmrg    TMShortCard	tIndex,
585444c061aSmrg    TMShortCard	*numPrintsRtn)
586444c061aSmrg{
587444c061aSmrg    TMComplexStateTree stateTree;
588444c061aSmrg    int			i;
589444c061aSmrg    TMBranchHead	branchHead;
590444c061aSmrg
591444c061aSmrg    stateTree = (TMComplexStateTree)xlations->stateTreeTbl[tIndex];
592444c061aSmrg
593444c061aSmrg    for (i = 0, branchHead = stateTree->branchHeadTbl;
594444c061aSmrg	 i < (int)stateTree->numBranchHeads;
595444c061aSmrg	 i++, branchHead++) {
596444c061aSmrg	StatePtr state;
597444c061aSmrg	if (!branchHead->isSimple)
598444c061aSmrg	  state = TMComplexBranchHead(stateTree, branchHead);
599444c061aSmrg	else
600444c061aSmrg	  state = NULL;
601444c061aSmrg	if (FindNextMatch(printData, *numPrintsRtn, xlations, branchHead,
602444c061aSmrg			  (state ? state->nextLevel : NULL), 0)
603444c061aSmrg	    == TM_NO_MATCH) {
604444c061aSmrg	    if (!branchHead->isSimple || branchHead->hasActions) {
605444c061aSmrg		printData[*numPrintsRtn].tIndex = tIndex;
606444c061aSmrg		printData[*numPrintsRtn].bIndex = i;
607444c061aSmrg		(*numPrintsRtn)++;
608444c061aSmrg	    }
609444c061aSmrg	    LOCK_PROCESS;
610444c061aSmrg	    if (_XtGlobalTM.newMatchSemantics == False)
611444c061aSmrg	      ProcessLaterMatches(printData,
612444c061aSmrg				  xlations,
613444c061aSmrg				  tIndex,
614444c061aSmrg				  i,
615444c061aSmrg				  numPrintsRtn);
616444c061aSmrg	    UNLOCK_PROCESS;
617444c061aSmrg	}
618444c061aSmrg    }
619444c061aSmrg}
620444c061aSmrg
621444c061aSmrgstatic void PrintState(
622444c061aSmrg    TMStringBuf	sb,
623444c061aSmrg    TMStateTree	tree,
624444c061aSmrg    TMBranchHead branchHead,
625444c061aSmrg    Boolean	includeRHS,
626444c061aSmrg    Widget	accelWidget,
627444c061aSmrg    Display 	*dpy)
628444c061aSmrg{
629444c061aSmrg    TMComplexStateTree stateTree = (TMComplexStateTree)tree;
630444c061aSmrg    LOCK_PROCESS;
631444c061aSmrg    if (branchHead->isSimple) {
632444c061aSmrg	PrintEvent(sb,
633444c061aSmrg		   TMGetTypeMatch(branchHead->typeIndex),
634444c061aSmrg		   TMGetModifierMatch(branchHead->modIndex),
635444c061aSmrg		   dpy);
636444c061aSmrg	if (includeRHS) {
637444c061aSmrg	    ActionRec	actRec;
638444c061aSmrg
639444c061aSmrg	    CHECK_STR_OVERFLOW(sb);
640444c061aSmrg	    *sb->current++ = ':';
641444c061aSmrg	    actRec.idx = TMBranchMore(branchHead);
642444c061aSmrg	    actRec.num_params = 0;
643444c061aSmrg	    actRec.params = NULL;
644444c061aSmrg	    actRec.next = NULL;
645444c061aSmrg	    PrintActions(sb,
646444c061aSmrg			 &actRec,
647444c061aSmrg			 stateTree->quarkTbl,
648444c061aSmrg			 accelWidget);
649444c061aSmrg	    *sb->current++ = '\n';
650444c061aSmrg	}
651444c061aSmrg	else
652444c061aSmrg	  *sb->current++ = ',';
653444c061aSmrg#ifdef TRACE_TM
654444c061aSmrg	if (!branchHead->hasActions)
655444c061aSmrg	  printf(" !! no actions !! ");
656444c061aSmrg#endif
657444c061aSmrg    }
658444c061aSmrg	else { /* it's a complex branchHead */
659444c061aSmrg	    StatePtr state = TMComplexBranchHead(stateTree, branchHead);
660444c061aSmrg	    PrintComplexState(sb,
661444c061aSmrg			      includeRHS,
662444c061aSmrg			      state,
663444c061aSmrg			      tree,
664444c061aSmrg			      accelWidget,
665444c061aSmrg			      (Display *)NULL);
666444c061aSmrg	}
667444c061aSmrg    *sb->current = '\0';
668444c061aSmrg    UNLOCK_PROCESS;
669444c061aSmrg}
670444c061aSmrg
671444c061aSmrgString _XtPrintXlations(
672444c061aSmrg    Widget		w,
673444c061aSmrg    XtTranslations 	xlations,
674444c061aSmrg    Widget		accelWidget,
675444c061aSmrg    _XtBoolean		includeRHS)
676444c061aSmrg{
677444c061aSmrg    register Cardinal 	i;
678444c061aSmrg#define STACKPRINTSIZE 250
679444c061aSmrg    PrintRec		stackPrints[STACKPRINTSIZE];
680444c061aSmrg    PrintRec		*prints;
681444c061aSmrg    TMStringBufRec	sbRec, *sb = &sbRec;
682444c061aSmrg    TMShortCard		numPrints, maxPrints;
683444c061aSmrg#ifdef TRACE_TM
684444c061aSmrg    TMBindData		bindData = (TMBindData)w->core.tm.proc_table;
685444c061aSmrg    Boolean		hasAccel = (accelWidget ? True : False);
686444c061aSmrg#endif /* TRACE_TM */
687444c061aSmrg    if (xlations == NULL) return NULL;
688444c061aSmrg
689444c061aSmrg    sb->current = sb->start = __XtMalloc((Cardinal)1000);
690444c061aSmrg    sb->max = 1000;
691444c061aSmrg    maxPrints = 0;
692444c061aSmrg    for (i = 0; i < xlations->numStateTrees; i++)
693444c061aSmrg	maxPrints +=
694444c061aSmrg	  ((TMSimpleStateTree)(xlations->stateTreeTbl[i]))->numBranchHeads;
695444c061aSmrg    prints = (PrintRec *)
696444c061aSmrg      XtStackAlloc(maxPrints * sizeof(PrintRec), stackPrints);
697444c061aSmrg
698444c061aSmrg    numPrints = 0;
699444c061aSmrg    for (i = 0; i < xlations->numStateTrees; i++)
700444c061aSmrg      ProcessStateTree(prints, xlations, i, &numPrints);
701444c061aSmrg
702444c061aSmrg    for (i = 0; i < numPrints; i++) {
703444c061aSmrg	TMSimpleStateTree stateTree = (TMSimpleStateTree)
704444c061aSmrg	  xlations->stateTreeTbl[prints[i].tIndex];
705444c061aSmrg	TMBranchHead branchHead =
706444c061aSmrg	  &stateTree->branchHeadTbl[prints[i].bIndex];
707444c061aSmrg#ifdef TRACE_TM
708444c061aSmrg	TMComplexBindProcs	complexBindProcs;
709444c061aSmrg
710444c061aSmrg	if (hasAccel == False) {
711444c061aSmrg	    accelWidget = NULL;
712444c061aSmrg	    if (bindData->simple.isComplex) {
713444c061aSmrg		complexBindProcs = TMGetComplexBindEntry(bindData, 0);
714444c061aSmrg		accelWidget = complexBindProcs[prints[i].tIndex].widget;
715444c061aSmrg	    }
716444c061aSmrg	}
717444c061aSmrg#endif /* TRACE_TM */
718444c061aSmrg	PrintState(sb, (TMStateTree)stateTree, branchHead,
719444c061aSmrg		   includeRHS, accelWidget, XtDisplay(w));
720444c061aSmrg    }
721444c061aSmrg    XtStackFree((XtPointer)prints, (XtPointer)stackPrints);
722444c061aSmrg    return (sb->start);
723444c061aSmrg}
724444c061aSmrg
725444c061aSmrg
726444c061aSmrg#ifndef NO_MIT_HACKS
727444c061aSmrg/*ARGSUSED*/
728444c061aSmrgvoid _XtDisplayTranslations(
729444c061aSmrg    Widget widget,
730444c061aSmrg    XEvent *event,
731444c061aSmrg    String *params,
732444c061aSmrg    Cardinal *num_params)
733444c061aSmrg{
734444c061aSmrg    String 	xString;
735444c061aSmrg
736444c061aSmrg    xString =  _XtPrintXlations(widget,
737444c061aSmrg				widget->core.tm.translations,
738444c061aSmrg				NULL,
739444c061aSmrg				True);
7402265a131Smrg    if (xString) {
7412265a131Smrg	printf("%s\n",xString);
7422265a131Smrg	XtFree(xString);
7432265a131Smrg    }
744444c061aSmrg}
745444c061aSmrg
746444c061aSmrg/*ARGSUSED*/
747444c061aSmrgvoid _XtDisplayAccelerators(
748444c061aSmrg    Widget widget,
749444c061aSmrg    XEvent *event,
750444c061aSmrg    String *params,
751444c061aSmrg    Cardinal *num_params)
752444c061aSmrg{
753444c061aSmrg    String 	xString;
754444c061aSmrg
755444c061aSmrg
756444c061aSmrg    xString =  _XtPrintXlations(widget,
757444c061aSmrg				widget->core.accelerators,
758444c061aSmrg				NULL,
759444c061aSmrg				True);
7602265a131Smrg    if (xString) {
7612265a131Smrg	printf("%s\n",xString);
7622265a131Smrg	XtFree(xString);
7632265a131Smrg    }
764444c061aSmrg}
765444c061aSmrg
766444c061aSmrg/*ARGSUSED*/
767444c061aSmrgvoid _XtDisplayInstalledAccelerators(
768444c061aSmrg    Widget widget,
769444c061aSmrg    XEvent *event,
770444c061aSmrg    String *params,
771444c061aSmrg    Cardinal *num_params)
772444c061aSmrg{
773444c061aSmrg    Widget eventWidget
774444c061aSmrg	= XtWindowToWidget(event->xany.display, event->xany.window);
775444c061aSmrg    register Cardinal 	i;
776444c061aSmrg    TMStringBufRec	sbRec, *sb = &sbRec;
777444c061aSmrg    XtTranslations	xlations;
778444c061aSmrg#define STACKPRINTSIZE 250
779444c061aSmrg    PrintRec		stackPrints[STACKPRINTSIZE];
780444c061aSmrg    PrintRec		*prints;
781444c061aSmrg    TMShortCard		numPrints, maxPrints;
782249c3046Smrg    TMBindData	bindData ;
783444c061aSmrg    TMComplexBindProcs	complexBindProcs;
784444c061aSmrg
785444c061aSmrg    if ((eventWidget == NULL) ||
786249c3046Smrg	(eventWidget->core.tm.translations == NULL) )
787249c3046Smrg      return;
788249c3046Smrg
789249c3046Smrg    xlations = eventWidget->core.tm.translations;
790249c3046Smrg    bindData = (TMBindData) eventWidget->core.tm.proc_table;
791249c3046Smrg    if (bindData->simple.isComplex == False)
792444c061aSmrg      return;
793444c061aSmrg
794444c061aSmrg    sb->current = sb->start = __XtMalloc((Cardinal)1000);
795444c061aSmrg    sb->start[0] = '\0';
796444c061aSmrg    sb->max = 1000;
797444c061aSmrg    maxPrints = 0;
798444c061aSmrg    for (i = 0; i < xlations->numStateTrees; i++)
799444c061aSmrg	maxPrints +=
800444c061aSmrg	  ((TMSimpleStateTree)xlations->stateTreeTbl[i])->numBranchHeads;
801444c061aSmrg    prints = (PrintRec *)
802444c061aSmrg      XtStackAlloc(maxPrints * sizeof(PrintRec), stackPrints);
803444c061aSmrg
804444c061aSmrg    numPrints = 0;
805444c061aSmrg
806444c061aSmrg    complexBindProcs = TMGetComplexBindEntry(bindData, 0);
807444c061aSmrg    for (i = 0;
808444c061aSmrg	 i < xlations->numStateTrees;
809444c061aSmrg	 i++, complexBindProcs++) {
810444c061aSmrg	if (complexBindProcs->widget)
811444c061aSmrg	  {
812444c061aSmrg	      ProcessStateTree(prints, xlations, i, &numPrints);
813444c061aSmrg	  }
814444c061aSmrg    }
815444c061aSmrg    for (i = 0; i < numPrints; i++) {
816444c061aSmrg	TMSimpleStateTree stateTree = (TMSimpleStateTree)
817444c061aSmrg	  xlations->stateTreeTbl[prints[i].tIndex];
818444c061aSmrg	TMBranchHead branchHead =
819444c061aSmrg	  &stateTree->branchHeadTbl[prints[i].bIndex];
820444c061aSmrg
821444c061aSmrg	complexBindProcs = TMGetComplexBindEntry(bindData, 0);
822444c061aSmrg
823444c061aSmrg	PrintState(sb, (TMStateTree)stateTree, branchHead, True,
824444c061aSmrg		   complexBindProcs[prints[i].tIndex].widget,
825444c061aSmrg		   XtDisplay(widget));
826444c061aSmrg    }
827444c061aSmrg    XtStackFree((XtPointer)prints, (XtPointer)stackPrints);
828444c061aSmrg    printf("%s\n", sb->start);
829444c061aSmrg    XtFree(sb->start);
830444c061aSmrg}
831444c061aSmrg#endif /*NO_MIT_HACKS*/
832444c061aSmrg
833444c061aSmrgString _XtPrintActions(
834444c061aSmrg    register ActionRec *actions,
835444c061aSmrg    XrmQuark		*quarkTbl)
836444c061aSmrg{
837444c061aSmrg    TMStringBufRec	sbRec, *sb = &sbRec;
838444c061aSmrg
839444c061aSmrg    sb->max = 1000;
840444c061aSmrg    sb->current = sb->start = __XtMalloc((Cardinal)1000);
841444c061aSmrg    PrintActions(sb,
842444c061aSmrg		 actions,
843444c061aSmrg		 quarkTbl,
844444c061aSmrg		 (Widget)NULL);
845444c061aSmrg    return sb->start;
846444c061aSmrg}
847444c061aSmrg
848444c061aSmrgString _XtPrintState(
849444c061aSmrg    TMStateTree		stateTree,
850444c061aSmrg    TMBranchHead	branchHead)
851444c061aSmrg{
852444c061aSmrg    TMStringBufRec	sbRec, *sb = &sbRec;
853444c061aSmrg
854444c061aSmrg    sb->current = sb->start = __XtMalloc((Cardinal)1000);
855444c061aSmrg    sb->max = 1000;
856444c061aSmrg    PrintState(sb, stateTree, branchHead,
857444c061aSmrg	       True, (Widget)NULL, (Display *)NULL);
858444c061aSmrg    return sb->start;
859444c061aSmrg}
860444c061aSmrg
861444c061aSmrg
862444c061aSmrgString _XtPrintEventSeq(
863444c061aSmrg    register EventSeqPtr eventSeq,
864444c061aSmrg    Display *dpy)
865444c061aSmrg{
866444c061aSmrg    TMStringBufRec	sbRec, *sb = &sbRec;
867444c061aSmrg    TMTypeMatch		typeMatch;
868444c061aSmrg    TMModifierMatch	modMatch;
869444c061aSmrg#define MAXSEQS 100
870444c061aSmrg    EventSeqPtr		eventSeqs[MAXSEQS];
871444c061aSmrg    TMShortCard		i, j;
872444c061aSmrg    Boolean		cycle = False;
873444c061aSmrg
874444c061aSmrg    sb->current = sb->start = __XtMalloc((Cardinal)1000);
875444c061aSmrg    sb->max = 1000;
876444c061aSmrg    for (i = 0;
877444c061aSmrg	 i < MAXSEQS && eventSeq != NULL && !cycle;
878444c061aSmrg	 eventSeq = eventSeq->next, i++)
879444c061aSmrg      {
880444c061aSmrg	  eventSeqs[i] = eventSeq;
881444c061aSmrg	  for (j = 0; j < i && !cycle; j++)
882444c061aSmrg	    if (eventSeqs[j] == eventSeq)
883444c061aSmrg	      cycle = True;
884444c061aSmrg      }
885444c061aSmrg    LOCK_PROCESS;
886444c061aSmrg    for (j = 0; j < i; j++) {
887444c061aSmrg	typeMatch =
888444c061aSmrg	  TMGetTypeMatch(_XtGetTypeIndex(&eventSeqs[j]->event));
889444c061aSmrg	modMatch =
890444c061aSmrg	  TMGetModifierMatch(_XtGetModifierIndex(&eventSeqs[j]->event));
891444c061aSmrg	PrintEvent(sb, typeMatch, modMatch, dpy);
892444c061aSmrg	if (j < i)
893444c061aSmrg	  *sb->current++ = ',';
894444c061aSmrg    }
895444c061aSmrg    UNLOCK_PROCESS;
896444c061aSmrg    return sb->start;
897444c061aSmrg}
898