TMprint.c revision 0568f49b
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{
790568f49bSmrg    _XtString	start;
800568f49bSmrg    _XtString	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) 	\
890568f49bSmrg{ _XtString 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 ) \
950568f49bSmrg    if ((unsigned)(sb->current - sb->start) > (sb->max - STR_THRESHOLD - (Cardinal) nchars)) { \
960568f49bSmrg	_XtString old = sb->start;				\
97444c061aSmrg	sb->start = XtRealloc(old,				\
980568f49bSmrg	    (Cardinal)(sb->max = (Cardinal)(sb->max + STR_INCAMOUNT + (Cardinal) 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");
1500568f49bSmrg    (void) notfirst;
151444c061aSmrg
152444c061aSmrg#undef PRINTMOD
153444c061aSmrg}
154444c061aSmrg
155444c061aSmrgstatic void PrintEventType(
156444c061aSmrg    TMStringBuf	sb,
157444c061aSmrg    unsigned long event)
158444c061aSmrg{
159444c061aSmrg    CHECK_STR_OVERFLOW(sb);
160444c061aSmrg    switch (event) {
161444c061aSmrg#define PRINTEVENT(event, name) case event: (void) strcpy(sb->current, name); break;
162444c061aSmrg	PRINTEVENT(KeyPress, "<KeyPress>")
163444c061aSmrg	PRINTEVENT(KeyRelease, "<KeyRelease>")
164444c061aSmrg	PRINTEVENT(ButtonPress, "<ButtonPress>")
165444c061aSmrg	PRINTEVENT(ButtonRelease, "<ButtonRelease>")
166444c061aSmrg	PRINTEVENT(MotionNotify, "<MotionNotify>")
167444c061aSmrg	PRINTEVENT(EnterNotify, "<EnterNotify>")
168444c061aSmrg	PRINTEVENT(LeaveNotify, "<LeaveNotify>")
169444c061aSmrg	PRINTEVENT(FocusIn, "<FocusIn>")
170444c061aSmrg	PRINTEVENT(FocusOut, "<FocusOut>")
171444c061aSmrg	PRINTEVENT(KeymapNotify, "<KeymapNotify>")
172444c061aSmrg	PRINTEVENT(Expose, "<Expose>")
173444c061aSmrg	PRINTEVENT(GraphicsExpose, "<GraphicsExpose>")
174444c061aSmrg	PRINTEVENT(NoExpose, "<NoExpose>")
175444c061aSmrg	PRINTEVENT(VisibilityNotify, "<VisibilityNotify>")
176444c061aSmrg	PRINTEVENT(CreateNotify, "<CreateNotify>")
177444c061aSmrg	PRINTEVENT(DestroyNotify, "<DestroyNotify>")
178444c061aSmrg	PRINTEVENT(UnmapNotify, "<UnmapNotify>")
179444c061aSmrg	PRINTEVENT(MapNotify, "<MapNotify>")
180444c061aSmrg	PRINTEVENT(MapRequest, "<MapRequest>")
181444c061aSmrg	PRINTEVENT(ReparentNotify, "<ReparentNotify>")
182444c061aSmrg	PRINTEVENT(ConfigureNotify, "<ConfigureNotify>")
183444c061aSmrg	PRINTEVENT(ConfigureRequest, "<ConfigureRequest>")
184444c061aSmrg	PRINTEVENT(GravityNotify, "<GravityNotify>")
185444c061aSmrg	PRINTEVENT(ResizeRequest, "<ResizeRequest>")
186444c061aSmrg	PRINTEVENT(CirculateNotify, "<CirculateNotify>")
187444c061aSmrg	PRINTEVENT(CirculateRequest, "<CirculateRequest>")
188444c061aSmrg	PRINTEVENT(PropertyNotify, "<PropertyNotify>")
189444c061aSmrg	PRINTEVENT(SelectionClear, "<SelectionClear>")
190444c061aSmrg	PRINTEVENT(SelectionRequest, "<SelectionRequest>")
191444c061aSmrg	PRINTEVENT(SelectionNotify, "<SelectionNotify>")
192444c061aSmrg	PRINTEVENT(ColormapNotify, "<ColormapNotify>")
193444c061aSmrg	PRINTEVENT(ClientMessage, "<ClientMessage>")
194444c061aSmrg	case _XtEventTimerEventType:
195444c061aSmrg	    (void) strcpy(sb->current,"<EventTimer>");
196444c061aSmrg	    break;
197444c061aSmrg	default:
198444c061aSmrg	    (void) sprintf(sb->current, "<0x%x>", (int) event);
199444c061aSmrg#undef PRINTEVENT
200444c061aSmrg    }
201444c061aSmrg    sb->current += strlen(sb->current);
202444c061aSmrg}
203444c061aSmrg
204444c061aSmrgstatic void PrintCode(
205444c061aSmrg    TMStringBuf sb,
206444c061aSmrg    unsigned long mask, unsigned long code)
207444c061aSmrg{
208444c061aSmrg    CHECK_STR_OVERFLOW(sb);
209444c061aSmrg    if (mask != 0) {
210444c061aSmrg	if (mask != ~0UL)
211444c061aSmrg	    (void) sprintf(sb->current, "0x%lx:0x%lx", mask, code);
2120568f49bSmrg	else (void) sprintf(sb->current, /*"0x%lx"*/ "%u", (unsigned)code);
213444c061aSmrg	sb->current += strlen(sb->current);
214444c061aSmrg    }
215444c061aSmrg}
216444c061aSmrg
217444c061aSmrgstatic void PrintKeysym(
218444c061aSmrg    TMStringBuf sb,
219444c061aSmrg    KeySym keysym)
220444c061aSmrg{
221444c061aSmrg    String keysymName;
222444c061aSmrg
223444c061aSmrg    if (keysym == 0) return;
224444c061aSmrg
225444c061aSmrg    CHECK_STR_OVERFLOW(sb);
226444c061aSmrg    keysymName = XKeysymToString(keysym);
227444c061aSmrg    if (keysymName == NULL)
228444c061aSmrg      PrintCode(sb,~0UL,(unsigned long)keysym);
229444c061aSmrg    else {
230444c061aSmrg      ExpandToFit(sb, keysymName);
231444c061aSmrg      strcpy(sb->current, keysymName);
232444c061aSmrg      sb->current += strlen(sb->current);
233444c061aSmrg    }
234444c061aSmrg}
235444c061aSmrg
236444c061aSmrgstatic void PrintAtom(
237444c061aSmrg    TMStringBuf sb,
238444c061aSmrg    Display *dpy,
239444c061aSmrg    Atom atom)
240444c061aSmrg{
2410568f49bSmrg    _XtString atomName;
242444c061aSmrg
243444c061aSmrg    if (atom == 0) return;
244444c061aSmrg
245444c061aSmrg    atomName = (dpy ? XGetAtomName(dpy, atom) : NULL);
246444c061aSmrg
247444c061aSmrg    if (! atomName)
248444c061aSmrg      PrintCode(sb,~0UL,(unsigned long)atom);
249444c061aSmrg    else {
250444c061aSmrg      ExpandToFit( sb, atomName );
251444c061aSmrg      strcpy(sb->current, atomName);
252444c061aSmrg      sb->current += strlen(sb->current);
253444c061aSmrg      XFree(atomName);
254444c061aSmrg    }
255444c061aSmrg}
256444c061aSmrg
257444c061aSmrgstatic	void PrintLateModifiers(
258444c061aSmrg    TMStringBuf	sb,
259444c061aSmrg    LateBindingsPtr lateModifiers)
260444c061aSmrg{
261444c061aSmrg    for (; lateModifiers->keysym; lateModifiers++) {
262444c061aSmrg	CHECK_STR_OVERFLOW(sb);
263444c061aSmrg	if (lateModifiers->knot) {
264444c061aSmrg	    *sb->current++ = '~';
265444c061aSmrg	} else {
266444c061aSmrg	    *sb->current++ = ' ';
267444c061aSmrg	}
268444c061aSmrg	strcpy(sb->current, XKeysymToString(lateModifiers->keysym));
269444c061aSmrg	sb->current += strlen(sb->current);
270444c061aSmrg	if (lateModifiers->pair) {
271444c061aSmrg	    *(sb->current -= 2) = '\0';	/* strip "_L" */
272444c061aSmrg	    lateModifiers++;	/* skip _R keysym */
273444c061aSmrg	}
274444c061aSmrg    }
275444c061aSmrg}
276444c061aSmrg
277444c061aSmrgstatic void PrintEvent(
278444c061aSmrg    TMStringBuf sb,
279444c061aSmrg    register TMTypeMatch typeMatch,
280444c061aSmrg    register TMModifierMatch modMatch,
281444c061aSmrg    Display *dpy)
282444c061aSmrg{
283444c061aSmrg    if (modMatch->standard) *sb->current++ = ':';
284444c061aSmrg
285444c061aSmrg    PrintModifiers(sb, modMatch->modifierMask, modMatch->modifiers);
286444c061aSmrg    if (modMatch->lateModifiers != NULL)
287444c061aSmrg      PrintLateModifiers(sb, modMatch->lateModifiers);
288444c061aSmrg    PrintEventType(sb, typeMatch->eventType);
289444c061aSmrg    switch (typeMatch->eventType) {
290444c061aSmrg      case KeyPress:
291444c061aSmrg      case KeyRelease:
292444c061aSmrg	PrintKeysym(sb, (KeySym)typeMatch->eventCode);
293444c061aSmrg	break;
294444c061aSmrg
295444c061aSmrg      case PropertyNotify:
296444c061aSmrg      case SelectionClear:
297444c061aSmrg      case SelectionRequest:
298444c061aSmrg      case SelectionNotify:
299444c061aSmrg      case ClientMessage:
300444c061aSmrg	PrintAtom(sb, dpy, (Atom)typeMatch->eventCode);
301444c061aSmrg	break;
302444c061aSmrg
303444c061aSmrg      default:
304444c061aSmrg	PrintCode(sb, typeMatch->eventCodeMask, typeMatch->eventCode);
305444c061aSmrg    }
306444c061aSmrg}
307444c061aSmrg
308444c061aSmrgstatic void PrintParams(
309444c061aSmrg    TMStringBuf	sb,
310444c061aSmrg    String	*params,
311444c061aSmrg    Cardinal num_params)
312444c061aSmrg{
313444c061aSmrg    register Cardinal i;
314444c061aSmrg    for (i = 0; i<num_params; i++) {
315444c061aSmrg	ExpandToFit( sb, params[i] );
316444c061aSmrg	if (i != 0) {
317444c061aSmrg	    *sb->current++ = ',';
318444c061aSmrg	    *sb->current++ = ' ';
319444c061aSmrg	}
320444c061aSmrg	*sb->current++ = '"';
321444c061aSmrg	strcpy(sb->current, params[i]);
322444c061aSmrg	sb->current += strlen(sb->current);
323444c061aSmrg	*sb->current++ = '"';
324444c061aSmrg    }
325444c061aSmrg    *sb->current = '\0';
326444c061aSmrg}
327444c061aSmrg
328444c061aSmrgstatic void PrintActions(
329444c061aSmrg    TMStringBuf	sb,
330444c061aSmrg    register ActionPtr actions,
331444c061aSmrg    XrmQuark *quarkTbl,
332444c061aSmrg    Widget   accelWidget)
333444c061aSmrg{
334444c061aSmrg    while (actions != NULL) {
335444c061aSmrg	String proc;
336444c061aSmrg
337444c061aSmrg	*sb->current++ = ' ';
338444c061aSmrg
339444c061aSmrg	if (accelWidget) {
340444c061aSmrg	    /* accelerator */
341444c061aSmrg	    String name = XtName(accelWidget);
3420568f49bSmrg	    int nameLen = (int) strlen(name);
343444c061aSmrg	    ExpandForChars(sb,  nameLen );
344444c061aSmrg	    XtMemmove(sb->current, name, nameLen );
345444c061aSmrg	    sb->current += nameLen;
346444c061aSmrg	    *sb->current++ = '`';
347444c061aSmrg	}
348444c061aSmrg	proc = XrmQuarkToString(quarkTbl[actions->idx]);
349444c061aSmrg	ExpandToFit( sb, proc );
350444c061aSmrg	strcpy(sb->current, proc);
351444c061aSmrg	sb->current += strlen(proc);
352444c061aSmrg	*sb->current++ = '(';
353444c061aSmrg	PrintParams(sb, actions->params, actions->num_params);
354444c061aSmrg	*sb->current++ = ')';
355444c061aSmrg	actions = actions->next;
356444c061aSmrg    }
357444c061aSmrg    *sb->current = '\0';
358444c061aSmrg}
359444c061aSmrg
360444c061aSmrgstatic Boolean LookAheadForCycleOrMulticlick(
361444c061aSmrg    register StatePtr state,
362444c061aSmrg    StatePtr *state_return,	/* state to print, usually startState */
363444c061aSmrg    int *countP,
364444c061aSmrg    StatePtr *nextLevelP)
365444c061aSmrg{
366444c061aSmrg    int repeatCount = 0;
367444c061aSmrg    StatePtr	startState = state;
368444c061aSmrg    Boolean	isCycle = startState->isCycleEnd;
369444c061aSmrg    TMTypeMatch sTypeMatch;
370444c061aSmrg    TMModifierMatch sModMatch;
371444c061aSmrg
372444c061aSmrg    LOCK_PROCESS;
373444c061aSmrg    sTypeMatch = TMGetTypeMatch(startState->typeIndex);
374444c061aSmrg    sModMatch = TMGetModifierMatch(startState->modIndex);
375444c061aSmrg
376444c061aSmrg    *state_return = startState;
377444c061aSmrg
378444c061aSmrg    for (state = state->nextLevel; state != NULL; state = state->nextLevel) {
379444c061aSmrg	TMTypeMatch typeMatch = TMGetTypeMatch(state->typeIndex);
380444c061aSmrg	TMModifierMatch modMatch = TMGetModifierMatch(state->modIndex);
381444c061aSmrg
382444c061aSmrg	/* try to pick up the correct state with actions, to be printed */
383444c061aSmrg	/* This is to accommodate <ButtonUp>(2+), for example */
384444c061aSmrg	if (state->isCycleStart)
385444c061aSmrg	    *state_return = state;
386444c061aSmrg
387444c061aSmrg	if (state->isCycleEnd) {
388444c061aSmrg	    *countP = repeatCount;
389444c061aSmrg	    UNLOCK_PROCESS;
390444c061aSmrg	    return True;
391444c061aSmrg	}
392444c061aSmrg	if ((startState->typeIndex == state->typeIndex) &&
393444c061aSmrg	    (startState->modIndex == state->modIndex)) {
394444c061aSmrg	    repeatCount++;
395444c061aSmrg	    *nextLevelP = state;
396444c061aSmrg	}
397444c061aSmrg	else if (typeMatch->eventType == _XtEventTimerEventType)
398444c061aSmrg	  continue;
399444c061aSmrg	else /* not same event as starting event and not timer */ {
4000568f49bSmrg	    unsigned int type = (unsigned) sTypeMatch->eventType;
4010568f49bSmrg	    unsigned int t = (unsigned) typeMatch->eventType;
402444c061aSmrg	    if (   (type == ButtonPress	  && t != ButtonRelease)
403444c061aSmrg		|| (type == ButtonRelease && t != ButtonPress)
404444c061aSmrg		|| (type == KeyPress	  && t != KeyRelease)
405444c061aSmrg		|| (type == KeyRelease	  && t != KeyPress)
406444c061aSmrg		|| typeMatch->eventCode != sTypeMatch->eventCode
407444c061aSmrg		|| modMatch->modifiers != sModMatch->modifiers
408444c061aSmrg		|| modMatch->modifierMask != sModMatch->modifierMask
409444c061aSmrg		|| modMatch->lateModifiers != sModMatch->lateModifiers
410444c061aSmrg		|| typeMatch->eventCodeMask != sTypeMatch->eventCodeMask
411444c061aSmrg		|| typeMatch->matchEvent != sTypeMatch->matchEvent
412444c061aSmrg		|| modMatch->standard != sModMatch->standard)
413444c061aSmrg		/* not inverse of starting event, either */
414444c061aSmrg		break;
415444c061aSmrg	}
416444c061aSmrg    }
417444c061aSmrg    *countP = repeatCount;
418444c061aSmrg    UNLOCK_PROCESS;
419444c061aSmrg    return isCycle;
420444c061aSmrg}
421444c061aSmrg
422444c061aSmrgstatic void PrintComplexState(
423444c061aSmrg    TMStringBuf	sb,
424444c061aSmrg    Boolean	includeRHS,
425444c061aSmrg    StatePtr 	state,
426444c061aSmrg    TMStateTree stateTree,
427444c061aSmrg    Widget	accelWidget,
428444c061aSmrg    Display 	*dpy)
429444c061aSmrg{
430444c061aSmrg    int 		clickCount = 0;
431444c061aSmrg    Boolean 		cycle;
432444c061aSmrg    StatePtr 		nextLevel = NULL;
433444c061aSmrg    StatePtr		triggerState = NULL;
434444c061aSmrg
435444c061aSmrg    /* print the current state */
436444c061aSmrg    if (! state) return;
437444c061aSmrg    LOCK_PROCESS;
438444c061aSmrg    cycle = LookAheadForCycleOrMulticlick(state, &triggerState, &clickCount,
439444c061aSmrg					  &nextLevel);
440444c061aSmrg
441444c061aSmrg    PrintEvent(sb, TMGetTypeMatch(triggerState->typeIndex),
442444c061aSmrg	       TMGetModifierMatch(triggerState->modIndex), dpy);
443444c061aSmrg
444444c061aSmrg    if (cycle || clickCount) {
445444c061aSmrg	if (clickCount)
446444c061aSmrg	    sprintf(sb->current, "(%d%s)", clickCount+1, cycle ? "+" : "");
447444c061aSmrg	else
448444c061aSmrg	    (void) strncpy(sb->current, "(+)", 4);
449444c061aSmrg	sb->current += strlen(sb->current);
450444c061aSmrg	if (! state->actions && nextLevel)
451444c061aSmrg	    state = nextLevel;
452444c061aSmrg	while (! state->actions && ! state->isCycleEnd)
453444c061aSmrg	    state = state->nextLevel;	/* should be trigger state */
454444c061aSmrg    }
455444c061aSmrg
456444c061aSmrg    if (state->actions) {
457444c061aSmrg	if (includeRHS) {
458444c061aSmrg	    CHECK_STR_OVERFLOW(sb);
459444c061aSmrg	    *sb->current++ = ':';
460444c061aSmrg	    PrintActions(sb,
461444c061aSmrg			 state->actions,
462444c061aSmrg			 ((TMSimpleStateTree)stateTree)->quarkTbl,
463444c061aSmrg			 accelWidget);
464444c061aSmrg	    *sb->current++ = '\n';
465444c061aSmrg	}
466444c061aSmrg    }
467444c061aSmrg    else {
468444c061aSmrg	if (state->nextLevel && !cycle && !clickCount)
469444c061aSmrg	    *sb->current++ = ',';
470444c061aSmrg	else {
471444c061aSmrg	    /* no actions are attached to this production */
472444c061aSmrg	    *sb->current++ = ':';
473444c061aSmrg	    *sb->current++ = '\n';
474444c061aSmrg	}
475444c061aSmrg    }
476444c061aSmrg    *sb->current = '\0';
477444c061aSmrg
478444c061aSmrg    /* print succeeding states */
479444c061aSmrg    if (state->nextLevel && !cycle && !clickCount)
480444c061aSmrg	PrintComplexState(sb, includeRHS, state->nextLevel,
481444c061aSmrg			  stateTree, accelWidget, dpy);
482444c061aSmrg    UNLOCK_PROCESS;
483444c061aSmrg}
484444c061aSmrg
485444c061aSmrgtypedef struct{
486444c061aSmrg    TMShortCard	tIndex;
487444c061aSmrg    TMShortCard	bIndex;
488444c061aSmrg}PrintRec, *Print;
489444c061aSmrg
490444c061aSmrgstatic int FindNextMatch(
491444c061aSmrg    PrintRec		*printData,
492444c061aSmrg    TMShortCard		numPrints,
493444c061aSmrg    XtTranslations 	xlations,
494444c061aSmrg    TMBranchHead	branchHead,
495444c061aSmrg    StatePtr 		nextLevel,
496444c061aSmrg    TMShortCard		startIndex)
497444c061aSmrg{
498444c061aSmrg    TMShortCard		i;
499444c061aSmrg    StatePtr		currState, candState;
500444c061aSmrg    Boolean		noMatch = True;
501444c061aSmrg
502444c061aSmrg    for (i = startIndex; noMatch && i < numPrints; i++) {
5030568f49bSmrg	TMBranchHead prBranchHead;
5040568f49bSmrg	TMComplexStateTree stateTree;
5050568f49bSmrg
506444c061aSmrg	stateTree = (TMComplexStateTree)
507444c061aSmrg	  xlations->stateTreeTbl[printData[i].tIndex];
508444c061aSmrg	prBranchHead =
509444c061aSmrg	  &(stateTree->branchHeadTbl[printData[i].bIndex]);
510444c061aSmrg
511444c061aSmrg	if ((prBranchHead->typeIndex == branchHead->typeIndex) &&
512444c061aSmrg	    (prBranchHead->modIndex == branchHead->modIndex)) {
513444c061aSmrg	    if (prBranchHead->isSimple) {
514444c061aSmrg		if (!nextLevel)
515444c061aSmrg		  return i;
516444c061aSmrg	    }
517444c061aSmrg	    else {
518444c061aSmrg		currState = TMComplexBranchHead(stateTree, prBranchHead);
519444c061aSmrg		currState = currState->nextLevel;
520444c061aSmrg		candState = nextLevel;
521444c061aSmrg		for (;
522444c061aSmrg		     ((currState && !currState->isCycleEnd) &&
523444c061aSmrg		      (candState && !candState->isCycleEnd));
524444c061aSmrg		     currState = currState->nextLevel,
525444c061aSmrg		     candState = candState->nextLevel) {
526444c061aSmrg		    if ((currState->typeIndex != candState->typeIndex) ||
527444c061aSmrg			(currState->modIndex != candState->modIndex))
528444c061aSmrg		      break;
529444c061aSmrg		}
530444c061aSmrg		if (candState == currState) {
531444c061aSmrg		    return i;
532444c061aSmrg		}
533444c061aSmrg	    }
534444c061aSmrg	}
535444c061aSmrg    }
536444c061aSmrg    return TM_NO_MATCH;
537444c061aSmrg}
538444c061aSmrg
539444c061aSmrgstatic void ProcessLaterMatches(
540444c061aSmrg    PrintRec	*printData,
541444c061aSmrg    XtTranslations xlations,
542444c061aSmrg    TMShortCard	tIndex,
543444c061aSmrg    int bIndex,
544444c061aSmrg    TMShortCard	*numPrintsRtn)
545444c061aSmrg{
546444c061aSmrg    TMComplexStateTree 	stateTree;
547444c061aSmrg    int			i, j;
548444c061aSmrg    TMBranchHead	branchHead, matchBranch = NULL;
549444c061aSmrg
550444c061aSmrg    for (i = tIndex; i < (int)xlations->numStateTrees; i++) {
551444c061aSmrg	stateTree = (TMComplexStateTree)xlations->stateTreeTbl[i];
552444c061aSmrg	if (i == tIndex) {
553444c061aSmrg	    matchBranch = &stateTree->branchHeadTbl[bIndex];
554444c061aSmrg	    j = bIndex+1;
555444c061aSmrg	}
556444c061aSmrg	else j = 0;
557444c061aSmrg	for (branchHead = &stateTree->branchHeadTbl[j];
558444c061aSmrg	     j < (int)stateTree->numBranchHeads;
559444c061aSmrg	     j++, branchHead++) {
560444c061aSmrg	    if ((branchHead->typeIndex == matchBranch->typeIndex) &&
561444c061aSmrg		(branchHead->modIndex == matchBranch->modIndex)) {
562444c061aSmrg		StatePtr state;
563444c061aSmrg		if (!branchHead->isSimple)
564444c061aSmrg		  state = TMComplexBranchHead(stateTree, branchHead);
565444c061aSmrg		else
566444c061aSmrg		  state = NULL;
567444c061aSmrg		if ((!branchHead->isSimple || branchHead->hasActions) &&
568444c061aSmrg		    (FindNextMatch(printData,
569444c061aSmrg				   *numPrintsRtn,
570444c061aSmrg				   xlations,
571444c061aSmrg				   branchHead,
572444c061aSmrg				   (state ? state->nextLevel : NULL),
573444c061aSmrg				   0) == TM_NO_MATCH)) {
5740568f49bSmrg		    printData[*numPrintsRtn].tIndex = (TMShortCard) i;
5750568f49bSmrg		    printData[*numPrintsRtn].bIndex = (TMShortCard) j;
576444c061aSmrg		    (*numPrintsRtn)++;
577444c061aSmrg		}
578444c061aSmrg	    }
579444c061aSmrg	}
580444c061aSmrg    }
581444c061aSmrg}
582444c061aSmrg
583444c061aSmrgstatic void ProcessStateTree(
584444c061aSmrg    PrintRec	*printData,
585444c061aSmrg    XtTranslations xlations,
586444c061aSmrg    TMShortCard	tIndex,
587444c061aSmrg    TMShortCard	*numPrintsRtn)
588444c061aSmrg{
589444c061aSmrg    TMComplexStateTree stateTree;
590444c061aSmrg    int			i;
591444c061aSmrg    TMBranchHead	branchHead;
592444c061aSmrg
593444c061aSmrg    stateTree = (TMComplexStateTree)xlations->stateTreeTbl[tIndex];
594444c061aSmrg
595444c061aSmrg    for (i = 0, branchHead = stateTree->branchHeadTbl;
596444c061aSmrg	 i < (int)stateTree->numBranchHeads;
597444c061aSmrg	 i++, branchHead++) {
598444c061aSmrg	StatePtr state;
599444c061aSmrg	if (!branchHead->isSimple)
600444c061aSmrg	  state = TMComplexBranchHead(stateTree, branchHead);
601444c061aSmrg	else
602444c061aSmrg	  state = NULL;
603444c061aSmrg	if (FindNextMatch(printData, *numPrintsRtn, xlations, branchHead,
604444c061aSmrg			  (state ? state->nextLevel : NULL), 0)
605444c061aSmrg	    == TM_NO_MATCH) {
606444c061aSmrg	    if (!branchHead->isSimple || branchHead->hasActions) {
607444c061aSmrg		printData[*numPrintsRtn].tIndex = tIndex;
6080568f49bSmrg		printData[*numPrintsRtn].bIndex = (TMShortCard) i;
609444c061aSmrg		(*numPrintsRtn)++;
610444c061aSmrg	    }
611444c061aSmrg	    LOCK_PROCESS;
612444c061aSmrg	    if (_XtGlobalTM.newMatchSemantics == False)
613444c061aSmrg	      ProcessLaterMatches(printData,
614444c061aSmrg				  xlations,
615444c061aSmrg				  tIndex,
616444c061aSmrg				  i,
617444c061aSmrg				  numPrintsRtn);
618444c061aSmrg	    UNLOCK_PROCESS;
619444c061aSmrg	}
620444c061aSmrg    }
621444c061aSmrg}
622444c061aSmrg
623444c061aSmrgstatic void PrintState(
624444c061aSmrg    TMStringBuf	sb,
625444c061aSmrg    TMStateTree	tree,
626444c061aSmrg    TMBranchHead branchHead,
627444c061aSmrg    Boolean	includeRHS,
628444c061aSmrg    Widget	accelWidget,
629444c061aSmrg    Display 	*dpy)
630444c061aSmrg{
631444c061aSmrg    TMComplexStateTree stateTree = (TMComplexStateTree)tree;
632444c061aSmrg    LOCK_PROCESS;
633444c061aSmrg    if (branchHead->isSimple) {
634444c061aSmrg	PrintEvent(sb,
635444c061aSmrg		   TMGetTypeMatch(branchHead->typeIndex),
636444c061aSmrg		   TMGetModifierMatch(branchHead->modIndex),
637444c061aSmrg		   dpy);
638444c061aSmrg	if (includeRHS) {
639444c061aSmrg	    ActionRec	actRec;
640444c061aSmrg
641444c061aSmrg	    CHECK_STR_OVERFLOW(sb);
642444c061aSmrg	    *sb->current++ = ':';
643444c061aSmrg	    actRec.idx = TMBranchMore(branchHead);
644444c061aSmrg	    actRec.num_params = 0;
645444c061aSmrg	    actRec.params = NULL;
646444c061aSmrg	    actRec.next = NULL;
647444c061aSmrg	    PrintActions(sb,
648444c061aSmrg			 &actRec,
649444c061aSmrg			 stateTree->quarkTbl,
650444c061aSmrg			 accelWidget);
651444c061aSmrg	    *sb->current++ = '\n';
652444c061aSmrg	}
653444c061aSmrg	else
654444c061aSmrg	  *sb->current++ = ',';
655444c061aSmrg#ifdef TRACE_TM
656444c061aSmrg	if (!branchHead->hasActions)
657444c061aSmrg	  printf(" !! no actions !! ");
658444c061aSmrg#endif
659444c061aSmrg    }
660444c061aSmrg	else { /* it's a complex branchHead */
661444c061aSmrg	    StatePtr state = TMComplexBranchHead(stateTree, branchHead);
662444c061aSmrg	    PrintComplexState(sb,
663444c061aSmrg			      includeRHS,
664444c061aSmrg			      state,
665444c061aSmrg			      tree,
666444c061aSmrg			      accelWidget,
667444c061aSmrg			      (Display *)NULL);
668444c061aSmrg	}
669444c061aSmrg    *sb->current = '\0';
670444c061aSmrg    UNLOCK_PROCESS;
671444c061aSmrg}
672444c061aSmrg
6730568f49bSmrg_XtString _XtPrintXlations(
674444c061aSmrg    Widget		w,
675444c061aSmrg    XtTranslations 	xlations,
676444c061aSmrg    Widget		accelWidget,
677444c061aSmrg    _XtBoolean		includeRHS)
678444c061aSmrg{
679444c061aSmrg    register Cardinal 	i;
680444c061aSmrg#define STACKPRINTSIZE 250
681444c061aSmrg    PrintRec		stackPrints[STACKPRINTSIZE];
682444c061aSmrg    PrintRec		*prints;
683444c061aSmrg    TMStringBufRec	sbRec, *sb = &sbRec;
684444c061aSmrg    TMShortCard		numPrints, maxPrints;
685444c061aSmrg#ifdef TRACE_TM
686444c061aSmrg    TMBindData		bindData = (TMBindData)w->core.tm.proc_table;
687444c061aSmrg    Boolean		hasAccel = (accelWidget ? True : False);
688444c061aSmrg#endif /* TRACE_TM */
689444c061aSmrg    if (xlations == NULL) return NULL;
690444c061aSmrg
691444c061aSmrg    sb->current = sb->start = __XtMalloc((Cardinal)1000);
692444c061aSmrg    sb->max = 1000;
693444c061aSmrg    maxPrints = 0;
694444c061aSmrg    for (i = 0; i < xlations->numStateTrees; i++)
6950568f49bSmrg	maxPrints = (TMShortCard) (maxPrints +
6960568f49bSmrg	  ((TMSimpleStateTree)(xlations->stateTreeTbl[i]))->numBranchHeads);
697444c061aSmrg    prints = (PrintRec *)
698444c061aSmrg      XtStackAlloc(maxPrints * sizeof(PrintRec), stackPrints);
699444c061aSmrg
700444c061aSmrg    numPrints = 0;
701444c061aSmrg    for (i = 0; i < xlations->numStateTrees; i++)
7020568f49bSmrg      ProcessStateTree(prints, xlations, (TMShortCard) i, &numPrints);
703444c061aSmrg
704444c061aSmrg    for (i = 0; i < numPrints; i++) {
705444c061aSmrg	TMSimpleStateTree stateTree = (TMSimpleStateTree)
706444c061aSmrg	  xlations->stateTreeTbl[prints[i].tIndex];
707444c061aSmrg	TMBranchHead branchHead =
708444c061aSmrg	  &stateTree->branchHeadTbl[prints[i].bIndex];
709444c061aSmrg#ifdef TRACE_TM
710444c061aSmrg	TMComplexBindProcs	complexBindProcs;
711444c061aSmrg
712444c061aSmrg	if (hasAccel == False) {
713444c061aSmrg	    accelWidget = NULL;
714444c061aSmrg	    if (bindData->simple.isComplex) {
715444c061aSmrg		complexBindProcs = TMGetComplexBindEntry(bindData, 0);
716444c061aSmrg		accelWidget = complexBindProcs[prints[i].tIndex].widget;
717444c061aSmrg	    }
718444c061aSmrg	}
719444c061aSmrg#endif /* TRACE_TM */
720444c061aSmrg	PrintState(sb, (TMStateTree)stateTree, branchHead,
7210568f49bSmrg		   (Boolean) includeRHS, accelWidget, XtDisplay(w));
722444c061aSmrg    }
723444c061aSmrg    XtStackFree((XtPointer)prints, (XtPointer)stackPrints);
724444c061aSmrg    return (sb->start);
725444c061aSmrg}
726444c061aSmrg
727444c061aSmrg
728444c061aSmrg#ifndef NO_MIT_HACKS
729444c061aSmrg/*ARGSUSED*/
730444c061aSmrgvoid _XtDisplayTranslations(
731444c061aSmrg    Widget widget,
732444c061aSmrg    XEvent *event,
733444c061aSmrg    String *params,
734444c061aSmrg    Cardinal *num_params)
735444c061aSmrg{
7360568f49bSmrg    _XtString 	xString;
737444c061aSmrg
738444c061aSmrg    xString =  _XtPrintXlations(widget,
739444c061aSmrg				widget->core.tm.translations,
740444c061aSmrg				NULL,
741444c061aSmrg				True);
7422265a131Smrg    if (xString) {
7432265a131Smrg	printf("%s\n",xString);
7442265a131Smrg	XtFree(xString);
7452265a131Smrg    }
746444c061aSmrg}
747444c061aSmrg
748444c061aSmrg/*ARGSUSED*/
749444c061aSmrgvoid _XtDisplayAccelerators(
750444c061aSmrg    Widget widget,
751444c061aSmrg    XEvent *event,
752444c061aSmrg    String *params,
753444c061aSmrg    Cardinal *num_params)
754444c061aSmrg{
7550568f49bSmrg    _XtString 	xString;
756444c061aSmrg
757444c061aSmrg
758444c061aSmrg    xString =  _XtPrintXlations(widget,
759444c061aSmrg				widget->core.accelerators,
760444c061aSmrg				NULL,
761444c061aSmrg				True);
7622265a131Smrg    if (xString) {
7632265a131Smrg	printf("%s\n",xString);
7642265a131Smrg	XtFree(xString);
7652265a131Smrg    }
766444c061aSmrg}
767444c061aSmrg
768444c061aSmrg/*ARGSUSED*/
769444c061aSmrgvoid _XtDisplayInstalledAccelerators(
770444c061aSmrg    Widget widget,
771444c061aSmrg    XEvent *event,
772444c061aSmrg    String *params,
773444c061aSmrg    Cardinal *num_params)
774444c061aSmrg{
775444c061aSmrg    Widget eventWidget
776444c061aSmrg	= XtWindowToWidget(event->xany.display, event->xany.window);
777444c061aSmrg    register Cardinal 	i;
778444c061aSmrg    TMStringBufRec	sbRec, *sb = &sbRec;
779444c061aSmrg    XtTranslations	xlations;
780444c061aSmrg#define STACKPRINTSIZE 250
781444c061aSmrg    PrintRec		stackPrints[STACKPRINTSIZE];
782444c061aSmrg    PrintRec		*prints;
783444c061aSmrg    TMShortCard		numPrints, maxPrints;
784249c3046Smrg    TMBindData	bindData ;
785444c061aSmrg    TMComplexBindProcs	complexBindProcs;
786444c061aSmrg
787444c061aSmrg    if ((eventWidget == NULL) ||
788249c3046Smrg	(eventWidget->core.tm.translations == NULL) )
789249c3046Smrg      return;
790249c3046Smrg
791249c3046Smrg    xlations = eventWidget->core.tm.translations;
792249c3046Smrg    bindData = (TMBindData) eventWidget->core.tm.proc_table;
793249c3046Smrg    if (bindData->simple.isComplex == False)
794444c061aSmrg      return;
795444c061aSmrg
796444c061aSmrg    sb->current = sb->start = __XtMalloc((Cardinal)1000);
797444c061aSmrg    sb->start[0] = '\0';
798444c061aSmrg    sb->max = 1000;
799444c061aSmrg    maxPrints = 0;
800444c061aSmrg    for (i = 0; i < xlations->numStateTrees; i++)
8010568f49bSmrg	maxPrints = (TMShortCard) (maxPrints +
8020568f49bSmrg	  ((TMSimpleStateTree)xlations->stateTreeTbl[i])->numBranchHeads);
803444c061aSmrg    prints = (PrintRec *)
804444c061aSmrg      XtStackAlloc(maxPrints * sizeof(PrintRec), stackPrints);
805444c061aSmrg
806444c061aSmrg    numPrints = 0;
807444c061aSmrg
808444c061aSmrg    complexBindProcs = TMGetComplexBindEntry(bindData, 0);
809444c061aSmrg    for (i = 0;
810444c061aSmrg	 i < xlations->numStateTrees;
811444c061aSmrg	 i++, complexBindProcs++) {
812444c061aSmrg	if (complexBindProcs->widget)
813444c061aSmrg	  {
8140568f49bSmrg	      ProcessStateTree(prints, xlations, (TMShortCard) i, &numPrints);
815444c061aSmrg	  }
816444c061aSmrg    }
817444c061aSmrg    for (i = 0; i < numPrints; i++) {
818444c061aSmrg	TMSimpleStateTree stateTree = (TMSimpleStateTree)
819444c061aSmrg	  xlations->stateTreeTbl[prints[i].tIndex];
820444c061aSmrg	TMBranchHead branchHead =
821444c061aSmrg	  &stateTree->branchHeadTbl[prints[i].bIndex];
822444c061aSmrg
823444c061aSmrg	complexBindProcs = TMGetComplexBindEntry(bindData, 0);
824444c061aSmrg
825444c061aSmrg	PrintState(sb, (TMStateTree)stateTree, branchHead, True,
826444c061aSmrg		   complexBindProcs[prints[i].tIndex].widget,
827444c061aSmrg		   XtDisplay(widget));
828444c061aSmrg    }
829444c061aSmrg    XtStackFree((XtPointer)prints, (XtPointer)stackPrints);
830444c061aSmrg    printf("%s\n", sb->start);
831444c061aSmrg    XtFree(sb->start);
832444c061aSmrg}
833444c061aSmrg#endif /*NO_MIT_HACKS*/
834444c061aSmrg
835444c061aSmrgString _XtPrintActions(
836444c061aSmrg    register ActionRec *actions,
837444c061aSmrg    XrmQuark		*quarkTbl)
838444c061aSmrg{
839444c061aSmrg    TMStringBufRec	sbRec, *sb = &sbRec;
840444c061aSmrg
841444c061aSmrg    sb->max = 1000;
842444c061aSmrg    sb->current = sb->start = __XtMalloc((Cardinal)1000);
843444c061aSmrg    PrintActions(sb,
844444c061aSmrg		 actions,
845444c061aSmrg		 quarkTbl,
846444c061aSmrg		 (Widget)NULL);
847444c061aSmrg    return sb->start;
848444c061aSmrg}
849444c061aSmrg
850444c061aSmrgString _XtPrintState(
851444c061aSmrg    TMStateTree		stateTree,
852444c061aSmrg    TMBranchHead	branchHead)
853444c061aSmrg{
854444c061aSmrg    TMStringBufRec	sbRec, *sb = &sbRec;
855444c061aSmrg
856444c061aSmrg    sb->current = sb->start = __XtMalloc((Cardinal)1000);
857444c061aSmrg    sb->max = 1000;
858444c061aSmrg    PrintState(sb, stateTree, branchHead,
859444c061aSmrg	       True, (Widget)NULL, (Display *)NULL);
860444c061aSmrg    return sb->start;
861444c061aSmrg}
862444c061aSmrg
863444c061aSmrg
864444c061aSmrgString _XtPrintEventSeq(
865444c061aSmrg    register EventSeqPtr eventSeq,
866444c061aSmrg    Display *dpy)
867444c061aSmrg{
868444c061aSmrg    TMStringBufRec	sbRec, *sb = &sbRec;
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++) {
8870568f49bSmrg	TMTypeMatch typeMatch;
8880568f49bSmrg	TMModifierMatch modMatch;
8890568f49bSmrg
890444c061aSmrg	typeMatch =
891444c061aSmrg	  TMGetTypeMatch(_XtGetTypeIndex(&eventSeqs[j]->event));
892444c061aSmrg	modMatch =
893444c061aSmrg	  TMGetModifierMatch(_XtGetModifierIndex(&eventSeqs[j]->event));
894444c061aSmrg	PrintEvent(sb, typeMatch, modMatch, dpy);
895444c061aSmrg	if (j < i)
896444c061aSmrg	  *sb->current++ = ',';
897444c061aSmrg    }
898444c061aSmrg    UNLOCK_PROCESS;
899444c061aSmrg    return sb->start;
900444c061aSmrg}
901