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