trace.c revision a5ae21e4
1a5ae21e4Smrg/* $XTermId: trace.c,v 1.234 2021/09/14 20:09:56 tom Exp $ */
2d522f475Smrg
320d2c4d2Smrg/*
4f2e35a3aSmrg * Copyright 1997-2020,2021 by Thomas E. Dickey
50bd37d32Smrg *
620d2c4d2Smrg *                         All Rights Reserved
70bd37d32Smrg *
820d2c4d2Smrg * Permission is hereby granted, free of charge, to any person obtaining a
920d2c4d2Smrg * copy of this software and associated documentation files (the
1020d2c4d2Smrg * "Software"), to deal in the Software without restriction, including
1120d2c4d2Smrg * without limitation the rights to use, copy, modify, merge, publish,
1220d2c4d2Smrg * distribute, sublicense, and/or sell copies of the Software, and to
1320d2c4d2Smrg * permit persons to whom the Software is furnished to do so, subject to
1420d2c4d2Smrg * the following conditions:
1520d2c4d2Smrg *
1620d2c4d2Smrg * The above copyright notice and this permission notice shall be included
1720d2c4d2Smrg * in all copies or substantial portions of the Software.
1820d2c4d2Smrg *
1920d2c4d2Smrg * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
2020d2c4d2Smrg * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
2120d2c4d2Smrg * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
2220d2c4d2Smrg * IN NO EVENT SHALL THE ABOVE LISTED COPYRIGHT HOLDER(S) BE LIABLE FOR ANY
2320d2c4d2Smrg * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
2420d2c4d2Smrg * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
2520d2c4d2Smrg * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
2620d2c4d2Smrg *
2720d2c4d2Smrg * Except as contained in this notice, the name(s) of the above copyright
2820d2c4d2Smrg * holders shall not be used in advertising or otherwise to promote the
2920d2c4d2Smrg * sale, use or other dealings in this Software without prior written
3020d2c4d2Smrg * authorization.
3120d2c4d2Smrg */
32d522f475Smrg
33d522f475Smrg/*
34d522f475Smrg * debugging support via TRACE macro.
35d522f475Smrg */
36d522f475Smrg
37d522f475Smrg#include <xterm.h>		/* for definition of GCC_UNUSED */
38f2e35a3aSmrg#include <xstrings.h>
39f2e35a3aSmrg#include <wcwidth.h>
400bd37d32Smrg#include <version.h>
41a1f3da82Smrg
42a1f3da82Smrg#if OPT_TRACE
43a1f3da82Smrg
44d522f475Smrg#include <data.h>
45d522f475Smrg#include <trace.h>
46d522f475Smrg
47d522f475Smrg#include <time.h>
48d522f475Smrg#include <stdlib.h>
49d522f475Smrg#include <unistd.h>
50d522f475Smrg#include <sys/types.h>
51894e0ac8Smrg#include <sys/stat.h>
52d522f475Smrg#include <stdio.h>
53d522f475Smrg#include <assert.h>
54d522f475Smrg
55956cc18dSsnj#include <X11/Xatom.h>
56956cc18dSsnj#include <X11/Xmu/Atoms.h>
57f2e35a3aSmrg#include <X11/Xmu/Error.h>
58956cc18dSsnj
59d522f475Smrg#ifdef HAVE_X11_TRANSLATEI_H
602e4f8982Smrg#include <X11/ConvertI.h>
61d522f475Smrg#include <X11/TranslateI.h>
62d522f475Smrg#else
63d522f475Smrg#ifdef __cplusplus
64d522f475Smrgextern "C" {
65d522f475Smrg#endif
66d522f475Smrg
67d522f475Smrg    extern String _XtPrintXlations(Widget w,
68d522f475Smrg				   XtTranslations xlations,
69d522f475Smrg				   Widget accelWidget,
70d522f475Smrg				   _XtBoolean includeRHS);
71d522f475Smrg#ifdef __cplusplus
72d522f475Smrg}
73d522f475Smrg#endif
74d522f475Smrg#endif
7520d2c4d2Smrgconst char *trace_who = "parent";
7620d2c4d2Smrg
7720d2c4d2Smrgstatic FILE *trace_fp;
78d522f475Smrg
79f2e35a3aSmrgstatic FILE *
80f2e35a3aSmrgTraceOpen(void)
81d522f475Smrg{
8220d2c4d2Smrg    static const char *trace_out;
83d522f475Smrg
8420d2c4d2Smrg    if (trace_fp != 0
85d522f475Smrg	&& trace_who != trace_out) {
8620d2c4d2Smrg	fclose(trace_fp);
8720d2c4d2Smrg	trace_fp = 0;
88d522f475Smrg    }
89d522f475Smrg    trace_out = trace_who;
90d522f475Smrg
9120d2c4d2Smrg    if (!trace_fp) {
92f2e35a3aSmrg	static char dot[] = ".";
93913cc679Smrg	mode_t oldmask = umask(077);
94f2e35a3aSmrg	/*
95f2e35a3aSmrg	 * Put the trace-file in user's home-directory if the current
96f2e35a3aSmrg	 * directory is not writable.
97f2e35a3aSmrg	 */
98f2e35a3aSmrg	char *home = (access(dot, R_OK | W_OK) == 0) ? dot : getenv("HOME");
99f2e35a3aSmrg	char *name = malloc(strlen(home) + strlen(trace_who) + 50);
100f2e35a3aSmrg#if OPT_TRACE_UNIQUE		/* usually I do not want unique names */
101d522f475Smrg	int unique;
102d522f475Smrg	for (unique = 0;; ++unique) {
103d522f475Smrg	    if (unique)
104f2e35a3aSmrg		sprintf(name, "%s/Trace-%s.out-%d", home, trace_who, unique);
105d522f475Smrg	    else
106f2e35a3aSmrg		sprintf(name, "%s/Trace-%s.out", home, trace_who);
10720d2c4d2Smrg	    if ((trace_fp = fopen(name, "r")) == 0) {
108d522f475Smrg		break;
109d522f475Smrg	    }
11020d2c4d2Smrg	    fclose(trace_fp);
111d522f475Smrg	}
112d522f475Smrg#else
113f2e35a3aSmrg	sprintf(name, "%s/Trace-%s.out", home, trace_who);
114d522f475Smrg#endif
11520d2c4d2Smrg	trace_fp = fopen(name, "w");
11620d2c4d2Smrg	if (trace_fp != 0) {
11720d2c4d2Smrg	    fprintf(trace_fp, "%s\n", xtermVersion());
118d522f475Smrg	    TraceIds(NULL, 0);
119d522f475Smrg	}
1200bd37d32Smrg	if (!trace_fp) {
1210bd37d32Smrg	    xtermWarning("Cannot open \"%s\"\n", name);
1220bd37d32Smrg	    exit(EXIT_FAILURE);
1230bd37d32Smrg	}
1240bd37d32Smrg	(void) umask(oldmask);
125f2e35a3aSmrg	free(name);
126d522f475Smrg    }
127f2e35a3aSmrg    return trace_fp;
128f2e35a3aSmrg}
129f2e35a3aSmrg
130f2e35a3aSmrgvoid
131f2e35a3aSmrgTrace(const char *fmt, ...)
132f2e35a3aSmrg{
133f2e35a3aSmrg    va_list ap;
134f2e35a3aSmrg    FILE *fp = TraceOpen();
135d522f475Smrg
136d522f475Smrg    va_start(ap, fmt);
137f2e35a3aSmrg    vfprintf(fp, fmt, ap);
138f2e35a3aSmrg    (void) fflush(fp);
13920d2c4d2Smrg    va_end(ap);
14020d2c4d2Smrg}
14120d2c4d2Smrg
142f2e35a3aSmrgvoid
143f2e35a3aSmrgTraceVA(const char *fmt, va_list ap)
144f2e35a3aSmrg{
145f2e35a3aSmrg    FILE *fp = TraceOpen();
146f2e35a3aSmrg
147f2e35a3aSmrg    vfprintf(fp, fmt, ap);
148f2e35a3aSmrg    (void) fflush(fp);
149f2e35a3aSmrg}
150f2e35a3aSmrg
15120d2c4d2Smrgvoid
15220d2c4d2SmrgTraceClose(void)
15320d2c4d2Smrg{
15420d2c4d2Smrg    if (trace_fp != 0) {
15520d2c4d2Smrg	(void) fclose(trace_fp);
156d522f475Smrg	(void) fflush(stdout);
157d522f475Smrg	(void) fflush(stderr);
158956cc18dSsnj	(void) visibleChars(NULL, 0);
159956cc18dSsnj	(void) visibleIChars(NULL, 0);
16020d2c4d2Smrg	trace_fp = 0;
161d522f475Smrg    }
162d522f475Smrg}
163d522f475Smrg
164f2e35a3aSmrgvoid
165f2e35a3aSmrgTraceXError(Display *d, XErrorEvent *ev)
166f2e35a3aSmrg{
167f2e35a3aSmrg    FILE *fp = TraceOpen();
168f2e35a3aSmrg    (void) XmuPrintDefaultErrorMessage(d, ev, fp);
169f2e35a3aSmrg    (void) fflush(fp);
170f2e35a3aSmrg}
171f2e35a3aSmrg
172d522f475Smrgvoid
173d522f475SmrgTraceIds(const char *fname, int lnum)
174d522f475Smrg{
175d522f475Smrg    Trace("process %d ", (int) getpid());
176d522f475Smrg#ifdef HAVE_UNISTD_H
177d522f475Smrg    Trace("real (%u/%u) effective (%u/%u)",
178d522f475Smrg	  (unsigned) getuid(), (unsigned) getgid(),
179d522f475Smrg	  (unsigned) geteuid(), (unsigned) getegid());
180d522f475Smrg#endif
181d522f475Smrg    if (fname != 0) {
182d522f475Smrg	Trace(" (%s@%d)\n", fname, lnum);
183d522f475Smrg    } else {
184d522f475Smrg	time_t now = time((time_t *) 0);
185d522f475Smrg	Trace("-- %s", ctime(&now));
186d522f475Smrg    }
187d522f475Smrg}
188d522f475Smrg
1890bd37d32Smrgvoid
1900bd37d32SmrgTraceTime(const char *fname, int lnum)
1910bd37d32Smrg{
1920bd37d32Smrg    time_t now;
1930bd37d32Smrg    if (fname != 0) {
1940bd37d32Smrg	Trace("datetime (%s@%d) ", fname, lnum);
1950bd37d32Smrg    }
1960bd37d32Smrg    now = time((time_t *) 0);
1970bd37d32Smrg    Trace("-- %s", ctime(&now));
1980bd37d32Smrg}
1990bd37d32Smrg
200d522f475Smrgstatic void
201d522f475SmrgformatAscii(char *dst, unsigned value)
202d522f475Smrg{
203d522f475Smrg    switch (value) {
204d522f475Smrg    case '\\':
205d522f475Smrg	sprintf(dst, "\\\\");
206d522f475Smrg	break;
207d522f475Smrg    case '\b':
208d522f475Smrg	sprintf(dst, "\\b");
209d522f475Smrg	break;
210d522f475Smrg    case '\n':
211d522f475Smrg	sprintf(dst, "\\n");
212d522f475Smrg	break;
213d522f475Smrg    case '\r':
214d522f475Smrg	sprintf(dst, "\\r");
215d522f475Smrg	break;
216d522f475Smrg    case '\t':
217d522f475Smrg	sprintf(dst, "\\t");
218d522f475Smrg	break;
219d522f475Smrg    default:
220d522f475Smrg	if (E2A(value) < 32 || (E2A(value) >= 127 && E2A(value) < 160))
221e0a2b6dfSmrg	    sprintf(dst, "\\%03o", value & 0xff);
222d522f475Smrg	else
223d522f475Smrg	    sprintf(dst, "%c", CharOf(value));
224d522f475Smrg	break;
225d522f475Smrg    }
226d522f475Smrg}
227d522f475Smrg
228d522f475Smrg#if OPT_DEC_CHRSET
229d522f475Smrg
230d522f475Smrgconst char *
231e0a2b6dfSmrgvisibleDblChrset(unsigned chrset)
232d522f475Smrg{
233d522f475Smrg    const char *result = "?";
234d522f475Smrg    switch (chrset) {
235d522f475Smrg    case CSET_SWL:
236d522f475Smrg	result = "CSET_SWL";
237d522f475Smrg	break;
238d522f475Smrg    case CSET_DHL_TOP:
239d522f475Smrg	result = "CSET_DHL_TOP";
240d522f475Smrg	break;
241d522f475Smrg    case CSET_DHL_BOT:
242d522f475Smrg	result = "CSET_DHL_BOT";
243d522f475Smrg	break;
244d522f475Smrg    case CSET_DWL:
245d522f475Smrg	result = "CSET_DWL";
246d522f475Smrg	break;
247d522f475Smrg    }
248d522f475Smrg    return result;
249d522f475Smrg}
250d522f475Smrg#endif
251d522f475Smrg
252e0a2b6dfSmrgconst char *
253f2e35a3aSmrgvisibleScsCode(DECNRCM_codes chrset)
254e0a2b6dfSmrg{
255f2e35a3aSmrg#define MAP(to,from) case from: result = to ":" #from; break
256e0a2b6dfSmrg    const char *result = "<ERR>";
257e0a2b6dfSmrg    switch ((DECNRCM_codes) chrset) {
258e0a2b6dfSmrg	MAP("B", nrc_ASCII);
259e0a2b6dfSmrg	MAP("A", nrc_British);
260e0a2b6dfSmrg	MAP("A", nrc_British_Latin_1);
261f2e35a3aSmrg	MAP("&4", nrc_DEC_Cyrillic);
262e0a2b6dfSmrg	MAP("0", nrc_DEC_Spec_Graphic);
263e0a2b6dfSmrg	MAP("1", nrc_DEC_Alt_Chars);
264e0a2b6dfSmrg	MAP("2", nrc_DEC_Alt_Graphics);
265e0a2b6dfSmrg	MAP("<", nrc_DEC_Supp);
266e0a2b6dfSmrg	MAP("%5", nrc_DEC_Supp_Graphic);
267e0a2b6dfSmrg	MAP(">", nrc_DEC_Technical);
268e0a2b6dfSmrg	MAP("4", nrc_Dutch);
269e0a2b6dfSmrg	MAP("5", nrc_Finnish);
270e0a2b6dfSmrg	MAP("C", nrc_Finnish2);
271e0a2b6dfSmrg	MAP("R", nrc_French);
272e0a2b6dfSmrg	MAP("f", nrc_French2);
273e0a2b6dfSmrg	MAP("Q", nrc_French_Canadian);
274e0a2b6dfSmrg	MAP("9", nrc_French_Canadian2);
275e0a2b6dfSmrg	MAP("K", nrc_German);
276f2e35a3aSmrg	MAP("\"?", nrc_DEC_Greek_Supp);
277f2e35a3aSmrg	MAP("\">", nrc_Greek);
278f2e35a3aSmrg	MAP("F", nrc_ISO_Greek_Supp);
279f2e35a3aSmrg	MAP("\"4", nrc_DEC_Hebrew_Supp);
280f2e35a3aSmrg	MAP("%=", nrc_Hebrew);
281f2e35a3aSmrg	MAP("H", nrc_ISO_Hebrew_Supp);
282e0a2b6dfSmrg	MAP("Y", nrc_Italian);
283f2e35a3aSmrg	MAP("A", nrc_ISO_Latin_1_Supp);
284f2e35a3aSmrg	MAP("B", nrc_ISO_Latin_2_Supp);
285f2e35a3aSmrg	MAP("M", nrc_ISO_Latin_5_Supp);
286f2e35a3aSmrg	MAP("L", nrc_ISO_Latin_Cyrillic);
287e0a2b6dfSmrg	MAP("`", nrc_Norwegian_Danish);
288e0a2b6dfSmrg	MAP("E", nrc_Norwegian_Danish2);
289e0a2b6dfSmrg	MAP("6", nrc_Norwegian_Danish3);
290e0a2b6dfSmrg	MAP("%6", nrc_Portugese);
291e0a2b6dfSmrg	MAP("&5", nrc_Russian);
292e0a2b6dfSmrg	MAP("%3", nrc_SCS_NRCS);
293e0a2b6dfSmrg	MAP("Z", nrc_Spanish);
294e0a2b6dfSmrg	MAP("7", nrc_Swedish);
295e0a2b6dfSmrg	MAP("H", nrc_Swedish2);
296e0a2b6dfSmrg	MAP("=", nrc_Swiss);
297f2e35a3aSmrg	MAP("%2", nrc_Turkish);
298f2e35a3aSmrg	MAP("%0", nrc_DEC_Turkish_Supp);
299e0a2b6dfSmrg	MAP("<UNK>", nrc_Unknown);
300e0a2b6dfSmrg    }
301e0a2b6dfSmrg#undef MAP
302e0a2b6dfSmrg    return result;
303e0a2b6dfSmrg}
304e0a2b6dfSmrg
3052e4f8982Smrgconst char *
306e0a2b6dfSmrgvisibleChars(const Char *buf, unsigned len)
307d522f475Smrg{
308d522f475Smrg    static char *result;
309d522f475Smrg    static unsigned used;
310d522f475Smrg
311956cc18dSsnj    if (buf != 0) {
312956cc18dSsnj	unsigned limit = ((len + 1) * 8) + 1;
313956cc18dSsnj
314956cc18dSsnj	if (limit > used) {
315956cc18dSsnj	    used = limit;
316956cc18dSsnj	    result = XtRealloc(result, used);
317956cc18dSsnj	}
31820d2c4d2Smrg	if (result != 0) {
3192e4f8982Smrg	    char *dst = result;
32020d2c4d2Smrg	    *dst = '\0';
32120d2c4d2Smrg	    while (len--) {
32220d2c4d2Smrg		unsigned value = *buf++;
32320d2c4d2Smrg		formatAscii(dst, value);
32420d2c4d2Smrg		dst += strlen(dst);
32520d2c4d2Smrg	    }
326956cc18dSsnj	}
327f2e35a3aSmrg    } else {
328f2e35a3aSmrg	FreeAndNull(result);
329956cc18dSsnj	used = 0;
330d522f475Smrg    }
33101037d57Smrg    return NonNull(result);
332956cc18dSsnj}
333956cc18dSsnj
334f2e35a3aSmrgconst char *
335f2e35a3aSmrgvisibleEventMode(EventMode value)
336f2e35a3aSmrg{
337f2e35a3aSmrg    const char *result;
338f2e35a3aSmrg    switch (value) {
339f2e35a3aSmrg    case NORMAL:
340f2e35a3aSmrg	result = "NORMAL";
341f2e35a3aSmrg	break;
342f2e35a3aSmrg    case LEFTEXTENSION:
343f2e35a3aSmrg	result = "LEFTEXTENSION";
344f2e35a3aSmrg	break;
345f2e35a3aSmrg    case RIGHTEXTENSION:
346f2e35a3aSmrg	result = "RIGHTEXTENSION";
347f2e35a3aSmrg	break;
348f2e35a3aSmrg    default:
349f2e35a3aSmrg	result = "?";
350f2e35a3aSmrg	break;
351f2e35a3aSmrg    }
352f2e35a3aSmrg    return result;
353f2e35a3aSmrg}
354f2e35a3aSmrg
3552e4f8982Smrgconst char *
35601037d57SmrgvisibleIChars(const IChar *buf, unsigned len)
357956cc18dSsnj{
358956cc18dSsnj    static char *result;
359956cc18dSsnj    static unsigned used;
360956cc18dSsnj
361956cc18dSsnj    if (buf != 0) {
362f2e35a3aSmrg	unsigned limit = ((len + 1) * 12) + 1;
363956cc18dSsnj
364956cc18dSsnj	if (limit > used) {
365956cc18dSsnj	    used = limit;
366956cc18dSsnj	    result = XtRealloc(result, used);
367d522f475Smrg	}
36820d2c4d2Smrg	if (result != 0) {
3692e4f8982Smrg	    char *dst = result;
37020d2c4d2Smrg	    *dst = '\0';
37120d2c4d2Smrg	    while (len--) {
37220d2c4d2Smrg		unsigned value = *buf++;
373956cc18dSsnj#if OPT_WIDE_CHARS
37420d2c4d2Smrg		if (value > 255)
375f2e35a3aSmrg		    sprintf(dst, "\\U+%04X", value);
37620d2c4d2Smrg		else
377d522f475Smrg#endif
37820d2c4d2Smrg		    formatAscii(dst, value);
37920d2c4d2Smrg		dst += strlen(dst);
38020d2c4d2Smrg	    }
381956cc18dSsnj	}
382f2e35a3aSmrg    } else {
383f2e35a3aSmrg	FreeAndNull(result);
384956cc18dSsnj	used = 0;
385d522f475Smrg    }
38601037d57Smrg    return NonNull(result);
387d522f475Smrg}
388d522f475Smrg
3892e4f8982Smrgconst char *
390e0a2b6dfSmrgvisibleUChar(unsigned chr)
391d522f475Smrg{
392e0a2b6dfSmrg    IChar buf[1];
393f2e35a3aSmrg    buf[0] = (IChar) chr;
394e0a2b6dfSmrg    return visibleIChars(buf, 1);
395d522f475Smrg}
396d522f475Smrg
397d522f475Smrgconst char *
398d522f475SmrgvisibleEventType(int type)
399d522f475Smrg{
400d522f475Smrg    const char *result = "?";
401d522f475Smrg    switch (type) {
402d522f475Smrg	CASETYPE(KeyPress);
403d522f475Smrg	CASETYPE(KeyRelease);
404d522f475Smrg	CASETYPE(ButtonPress);
405d522f475Smrg	CASETYPE(ButtonRelease);
406d522f475Smrg	CASETYPE(MotionNotify);
407d522f475Smrg	CASETYPE(EnterNotify);
408d522f475Smrg	CASETYPE(LeaveNotify);
409d522f475Smrg	CASETYPE(FocusIn);
410d522f475Smrg	CASETYPE(FocusOut);
411d522f475Smrg	CASETYPE(KeymapNotify);
412d522f475Smrg	CASETYPE(Expose);
413d522f475Smrg	CASETYPE(GraphicsExpose);
414d522f475Smrg	CASETYPE(NoExpose);
415d522f475Smrg	CASETYPE(VisibilityNotify);
416d522f475Smrg	CASETYPE(CreateNotify);
417d522f475Smrg	CASETYPE(DestroyNotify);
418d522f475Smrg	CASETYPE(UnmapNotify);
419d522f475Smrg	CASETYPE(MapNotify);
420d522f475Smrg	CASETYPE(MapRequest);
421d522f475Smrg	CASETYPE(ReparentNotify);
422d522f475Smrg	CASETYPE(ConfigureNotify);
423d522f475Smrg	CASETYPE(ConfigureRequest);
424d522f475Smrg	CASETYPE(GravityNotify);
425d522f475Smrg	CASETYPE(ResizeRequest);
426d522f475Smrg	CASETYPE(CirculateNotify);
427d522f475Smrg	CASETYPE(CirculateRequest);
428d522f475Smrg	CASETYPE(PropertyNotify);
429d522f475Smrg	CASETYPE(SelectionClear);
430d522f475Smrg	CASETYPE(SelectionRequest);
431d522f475Smrg	CASETYPE(SelectionNotify);
432d522f475Smrg	CASETYPE(ColormapNotify);
433d522f475Smrg	CASETYPE(ClientMessage);
434d522f475Smrg	CASETYPE(MappingNotify);
435d522f475Smrg    }
436d522f475Smrg    return result;
437d522f475Smrg}
438d522f475Smrg
439f2e35a3aSmrgconst char *
440f2e35a3aSmrgvisibleMappingMode(int code)
441f2e35a3aSmrg{
442f2e35a3aSmrg    const char *result = "?";
443f2e35a3aSmrg    switch (code) {
444f2e35a3aSmrg	CASETYPE(MappingModifier);
445f2e35a3aSmrg	CASETYPE(MappingKeyboard);
446f2e35a3aSmrg	CASETYPE(MappingPointer);
447f2e35a3aSmrg    }
448f2e35a3aSmrg    return result;
449f2e35a3aSmrg}
450f2e35a3aSmrg
4510bd37d32Smrgconst char *
4520bd37d32SmrgvisibleNotifyMode(int code)
4530bd37d32Smrg{
4540bd37d32Smrg    const char *result = "?";
4550bd37d32Smrg    switch (code) {
4560bd37d32Smrg	CASETYPE(NotifyNormal);
4570bd37d32Smrg	CASETYPE(NotifyGrab);
4580bd37d32Smrg	CASETYPE(NotifyUngrab);
4590bd37d32Smrg	CASETYPE(NotifyWhileGrabbed);
4600bd37d32Smrg    }
4610bd37d32Smrg    return result;
4620bd37d32Smrg}
4630bd37d32Smrg
46420d2c4d2Smrgconst char *
46520d2c4d2SmrgvisibleNotifyDetail(int code)
46620d2c4d2Smrg{
46720d2c4d2Smrg    const char *result = "?";
46820d2c4d2Smrg    switch (code) {
46920d2c4d2Smrg	CASETYPE(NotifyAncestor);
47020d2c4d2Smrg	CASETYPE(NotifyVirtual);
47120d2c4d2Smrg	CASETYPE(NotifyInferior);
47220d2c4d2Smrg	CASETYPE(NotifyNonlinear);
47320d2c4d2Smrg	CASETYPE(NotifyNonlinearVirtual);
47420d2c4d2Smrg	CASETYPE(NotifyPointer);
47520d2c4d2Smrg	CASETYPE(NotifyPointerRoot);
47620d2c4d2Smrg	CASETYPE(NotifyDetailNone);
47720d2c4d2Smrg    }
47820d2c4d2Smrg    return result;
47920d2c4d2Smrg}
48020d2c4d2Smrg
481956cc18dSsnjconst char *
482e0a2b6dfSmrgvisibleSelectionTarget(Display *d, Atom a)
483956cc18dSsnj{
484956cc18dSsnj    const char *result = "?";
485956cc18dSsnj
486956cc18dSsnj    if (a == XA_STRING) {
487956cc18dSsnj	result = "XA_STRING";
488956cc18dSsnj    } else if (a == XA_TEXT(d)) {
489956cc18dSsnj	result = "XA_TEXT()";
490956cc18dSsnj    } else if (a == XA_COMPOUND_TEXT(d)) {
491956cc18dSsnj	result = "XA_COMPOUND_TEXT()";
492956cc18dSsnj    } else if (a == XA_UTF8_STRING(d)) {
493956cc18dSsnj	result = "XA_UTF8_STRING()";
494956cc18dSsnj    } else if (a == XA_TARGETS(d)) {
495956cc18dSsnj	result = "XA_TARGETS()";
496956cc18dSsnj    }
497956cc18dSsnj
498956cc18dSsnj    return result;
499956cc18dSsnj}
500956cc18dSsnj
5012e4f8982Smrgconst char *
5022e4f8982SmrgvisibleTekparse(int code)
5032e4f8982Smrg{
5042e4f8982Smrg    static const struct {
5052e4f8982Smrg	int code;
5062e4f8982Smrg	const char *name;
5072e4f8982Smrg    } table[] = {
5082e4f8982Smrg#include "Tekparse.cin"
5092e4f8982Smrg    };
5102e4f8982Smrg    const char *result = "?";
5112e4f8982Smrg    Cardinal n;
5122e4f8982Smrg    for (n = 0; n < XtNumber(table); ++n) {
5132e4f8982Smrg	if (table[n].code == code) {
5142e4f8982Smrg	    result = table[n].name;
5152e4f8982Smrg	    break;
5162e4f8982Smrg	}
5172e4f8982Smrg    }
5182e4f8982Smrg    return result;
5192e4f8982Smrg}
5202e4f8982Smrg
5212e4f8982Smrgconst char *
5222e4f8982SmrgvisibleVTparse(int code)
5232e4f8982Smrg{
5242e4f8982Smrg    static const struct {
5252e4f8982Smrg	int code;
5262e4f8982Smrg	const char *name;
5272e4f8982Smrg    } table[] = {
5282e4f8982Smrg#include "VTparse.cin"
5292e4f8982Smrg    };
5302e4f8982Smrg    const char *result = "?";
5312e4f8982Smrg    Cardinal n;
5322e4f8982Smrg    for (n = 0; n < XtNumber(table); ++n) {
5332e4f8982Smrg	if (table[n].code == code) {
5342e4f8982Smrg	    result = table[n].name;
5352e4f8982Smrg	    break;
5362e4f8982Smrg	}
5372e4f8982Smrg    }
5382e4f8982Smrg    return result;
5392e4f8982Smrg}
5402e4f8982Smrg
541d522f475Smrgconst char *
542d522f475SmrgvisibleXError(int code)
543d522f475Smrg{
544d522f475Smrg    static char temp[80];
545d522f475Smrg    const char *result = "?";
546d522f475Smrg    switch (code) {
547d522f475Smrg	CASETYPE(Success);
548d522f475Smrg	CASETYPE(BadRequest);
549d522f475Smrg	CASETYPE(BadValue);
550d522f475Smrg	CASETYPE(BadWindow);
551d522f475Smrg	CASETYPE(BadPixmap);
552d522f475Smrg	CASETYPE(BadAtom);
553d522f475Smrg	CASETYPE(BadCursor);
554d522f475Smrg	CASETYPE(BadFont);
555d522f475Smrg	CASETYPE(BadMatch);
556d522f475Smrg	CASETYPE(BadDrawable);
557d522f475Smrg	CASETYPE(BadAccess);
558d522f475Smrg	CASETYPE(BadAlloc);
559d522f475Smrg	CASETYPE(BadColor);
560d522f475Smrg	CASETYPE(BadGC);
561d522f475Smrg	CASETYPE(BadIDChoice);
562d522f475Smrg	CASETYPE(BadName);
563d522f475Smrg	CASETYPE(BadLength);
564d522f475Smrg	CASETYPE(BadImplementation);
565d522f475Smrg    default:
566d522f475Smrg	sprintf(temp, "%d", code);
567d522f475Smrg	result = temp;
568d522f475Smrg	break;
569d522f475Smrg    }
570d522f475Smrg    return result;
571d522f475Smrg}
572d522f475Smrg
573d522f475Smrg#if OPT_TRACE_FLAGS
574d522f475Smrg#define isScrnFlag(flag) ((flag) == LINEWRAPPED)
575d522f475Smrg
576d522f475Smrgstatic char *
577e0a2b6dfSmrgScrnText(LineData *ld)
578d522f475Smrg{
579956cc18dSsnj    return visibleIChars(ld->charData, ld->lineSize);
580d522f475Smrg}
581d522f475Smrg
582956cc18dSsnj#define SHOW_BAD_LINE(name, ld) \
583956cc18dSsnj	Trace("OOPS " #name " bad row\n")
584d522f475Smrg
585d522f475Smrg#define SHOW_SCRN_FLAG(name,code) \
586956cc18dSsnj	Trace(#name " %s:%s\n", \
587d522f475Smrg	      code ? "*" : "", \
588956cc18dSsnj	      ScrnText(ld))
589d522f475Smrg
590d522f475Smrgvoid
591e0a2b6dfSmrgLineClrFlag(LineData *ld, int flag)
592d522f475Smrg{
593956cc18dSsnj    if (ld == 0) {
594956cc18dSsnj	SHOW_BAD_LINE(LineClrFlag, ld);
595d522f475Smrg	assert(0);
596d522f475Smrg    } else if (isScrnFlag(flag)) {
597956cc18dSsnj	SHOW_SCRN_FLAG(LineClrFlag, 0);
598d522f475Smrg    }
599d522f475Smrg
600956cc18dSsnj    LineFlags(ld) &= ~flag;
601d522f475Smrg}
602d522f475Smrg
603d522f475Smrgvoid
604e0a2b6dfSmrgLineSetFlag(LineData *ld, int flag)
605d522f475Smrg{
606956cc18dSsnj    if (ld == 0) {
607956cc18dSsnj	SHOW_BAD_LINE(LineSetFlag, ld);
608d522f475Smrg	assert(0);
609d522f475Smrg    } else if (isScrnFlag(flag)) {
610956cc18dSsnj	SHOW_SCRN_FLAG(LineSetFlag, 1);
611d522f475Smrg    }
612d522f475Smrg
613956cc18dSsnj    LineFlags(ld) |= flag;
614d522f475Smrg}
615d522f475Smrg
616d522f475Smrgint
617956cc18dSsnjLineTstFlag(LineData ld, int flag)
618d522f475Smrg{
619d522f475Smrg    int code = 0;
620956cc18dSsnj    if (ld == 0) {
621956cc18dSsnj	SHOW_BAD_LINE(LineTstFlag, ld);
622d522f475Smrg    } else {
623956cc18dSsnj	code = LineFlags(ld);
624956cc18dSsnj
625956cc18dSsnj	if (isScrnFlag(flag)) {
626956cc18dSsnj	    SHOW_SCRN_FLAG(LineTstFlag, code);
627d522f475Smrg	}
628d522f475Smrg    }
629d522f475Smrg    return code;
630d522f475Smrg}
631d522f475Smrg#endif /* OPT_TRACE_FLAGS */
632d522f475Smrg
633913cc679Smrgconst char *
634913cc679SmrgTraceAtomName(Display *dpy, Atom atom)
635913cc679Smrg{
636913cc679Smrg    static char *result;
637913cc679Smrg    free(result);
638f2e35a3aSmrg    if (atom != 0) {
639f2e35a3aSmrg	result = XGetAtomName(dpy, atom);
640f2e35a3aSmrg    } else {
641f2e35a3aSmrg	result = x_strdup("NONE");
642f2e35a3aSmrg    }
643913cc679Smrg    return result;
644913cc679Smrg}
645913cc679Smrg
6460bd37d32Smrg/*
6470bd37d32Smrg * Trace the normal or alternate screen, showing color values up to 16, e.g.,
6480bd37d32Smrg * for debugging with vttest.
6490bd37d32Smrg */
6500bd37d32Smrgvoid
6510bd37d32SmrgTraceScreen(XtermWidget xw, int whichBuf)
6520bd37d32Smrg{
6530bd37d32Smrg    TScreen *screen = TScreenOf(xw);
6540bd37d32Smrg
6550bd37d32Smrg    if (screen->editBuf_index[whichBuf]) {
6562e4f8982Smrg	int row;
6572e4f8982Smrg
6580bd37d32Smrg	TRACE(("TraceScreen %d:\n", whichBuf));
6590bd37d32Smrg	for (row = 0; row <= screen->max_row; ++row) {
6600bd37d32Smrg	    LineData *ld = getLineData(screen, row);
6612e4f8982Smrg
6620bd37d32Smrg	    TRACE((" %3d:", row));
6630bd37d32Smrg	    if (ld != 0) {
6642e4f8982Smrg		int col;
6652e4f8982Smrg
6660bd37d32Smrg		for (col = 0; col < ld->lineSize; ++col) {
6670bd37d32Smrg		    int ch = (int) ld->charData[col];
6680bd37d32Smrg		    if (ch < ' ')
6690bd37d32Smrg			ch = ' ';
6700bd37d32Smrg		    if (ch >= 127)
6710bd37d32Smrg			ch = '#';
6720bd37d32Smrg		    TRACE(("%c", ch));
6730bd37d32Smrg		}
6740bd37d32Smrg		TRACE((":\n"));
6750bd37d32Smrg
676f2e35a3aSmrg#if 0
6770bd37d32Smrg		TRACE(("  xx:"));
6780bd37d32Smrg		for (col = 0; col < ld->lineSize; ++col) {
6790bd37d32Smrg		    unsigned attrs = ld->attribs[col];
6800bd37d32Smrg		    char ch;
6810bd37d32Smrg		    if (attrs & PROTECTED) {
6820bd37d32Smrg			ch = '*';
6830bd37d32Smrg		    } else if (attrs & BLINK) {
6840bd37d32Smrg			ch = 'B';
6850bd37d32Smrg		    } else if (attrs & CHARDRAWN) {
6860bd37d32Smrg			ch = '+';
6870bd37d32Smrg		    } else {
6880bd37d32Smrg			ch = ' ';
6890bd37d32Smrg		    }
6900bd37d32Smrg		    TRACE(("%c", ch));
6910bd37d32Smrg		}
6920bd37d32Smrg		TRACE((":\n"));
693f2e35a3aSmrg#endif
6940bd37d32Smrg
6950bd37d32Smrg#if 0
6960bd37d32Smrg		TRACE(("  fg:"));
6970bd37d32Smrg		for (col = 0; col < ld->lineSize; ++col) {
6980bd37d32Smrg		    unsigned fg = extract_fg(xw, ld->color[col], ld->attribs[col]);
6990bd37d32Smrg		    if (fg > 15)
7000bd37d32Smrg			fg = 15;
7010bd37d32Smrg		    TRACE(("%1x", fg));
7020bd37d32Smrg		}
7030bd37d32Smrg		TRACE((":\n"));
7040bd37d32Smrg
7050bd37d32Smrg		TRACE(("  bg:"));
7060bd37d32Smrg		for (col = 0; col < ld->lineSize; ++col) {
7070bd37d32Smrg		    unsigned bg = extract_bg(xw, ld->color[col], ld->attribs[col]);
7080bd37d32Smrg		    if (bg > 15)
7090bd37d32Smrg			bg = 15;
7100bd37d32Smrg		    TRACE(("%1x", bg));
7110bd37d32Smrg		}
7120bd37d32Smrg		TRACE((":\n"));
7130bd37d32Smrg#endif
7140bd37d32Smrg	    } else {
7150bd37d32Smrg		TRACE(("null lineData\n"));
7160bd37d32Smrg	    }
7170bd37d32Smrg	}
7180bd37d32Smrg    } else {
7190bd37d32Smrg	TRACE(("TraceScreen %d is nil\n", whichBuf));
7200bd37d32Smrg    }
7210bd37d32Smrg}
7220bd37d32Smrg
723f2e35a3aSmrgstatic char *
724f2e35a3aSmrgformatEventMask(char *target, unsigned source, Boolean buttons)
725f2e35a3aSmrg{
726f2e35a3aSmrg#define DATA(name) { name ## Mask, #name }
727f2e35a3aSmrg    static struct {
728f2e35a3aSmrg	unsigned mask;
729f2e35a3aSmrg	const char *name;
730f2e35a3aSmrg    } table[] = {
731f2e35a3aSmrg	DATA(Shift),
732f2e35a3aSmrg	    DATA(Lock),
733f2e35a3aSmrg	    DATA(Control),
734f2e35a3aSmrg	    DATA(Mod1),
735f2e35a3aSmrg	    DATA(Mod2),
736f2e35a3aSmrg	    DATA(Mod3),
737f2e35a3aSmrg	    DATA(Mod4),
738f2e35a3aSmrg	    DATA(Mod5),
739f2e35a3aSmrg	    DATA(Button1),
740f2e35a3aSmrg	    DATA(Button2),
741f2e35a3aSmrg	    DATA(Button3),
742f2e35a3aSmrg	    DATA(Button4),
743f2e35a3aSmrg	    DATA(Button5),
744f2e35a3aSmrg    };
745f2e35a3aSmrg#undef DATA
746f2e35a3aSmrg    Cardinal n;
747f2e35a3aSmrg    char marker = L_CURL;
748f2e35a3aSmrg    char *base = target;
749f2e35a3aSmrg
750f2e35a3aSmrg    for (n = 0; n < XtNumber(table); ++n) {
751f2e35a3aSmrg	if (!buttons && (table[n].mask >= Button1Mask))
752f2e35a3aSmrg	    continue;
753f2e35a3aSmrg	if ((table[n].mask & source)) {
754f2e35a3aSmrg	    UIntClr(source, table[n].mask);
755f2e35a3aSmrg	    sprintf(target, "%c%s", marker, table[n].name);
756f2e35a3aSmrg	    target += strlen(target);
757f2e35a3aSmrg	    marker = '|';
758f2e35a3aSmrg	}
759f2e35a3aSmrg    }
760f2e35a3aSmrg
761f2e35a3aSmrg    if (source != 0) {
762f2e35a3aSmrg	sprintf(target, "%c?%#x", marker, source);
763f2e35a3aSmrg	target += strlen(target);
764f2e35a3aSmrg	marker = '|';
765f2e35a3aSmrg    }
766f2e35a3aSmrg
767f2e35a3aSmrg    if (marker == L_CURL)
768f2e35a3aSmrg	*target++ = L_CURL;
769f2e35a3aSmrg    *target++ = R_CURL;
770f2e35a3aSmrg
771f2e35a3aSmrg    *target = '\0';
772f2e35a3aSmrg    return base;
773f2e35a3aSmrg}
774f2e35a3aSmrg
775f2e35a3aSmrgvoid
776f2e35a3aSmrgTraceEvent(const char *tag, XEvent *ev, String *params, Cardinal *num_params)
777f2e35a3aSmrg{
778f2e35a3aSmrg    char mask_buffer[160];
779f2e35a3aSmrg
780f2e35a3aSmrg    TRACE(("Event #%lu %s: %#lx %s",
781f2e35a3aSmrg	   ev->xany.serial,
782f2e35a3aSmrg	   tag,
783f2e35a3aSmrg	   ev->xany.window,
784f2e35a3aSmrg	   visibleEventType(ev->type)));
785f2e35a3aSmrg
786f2e35a3aSmrg    switch (ev->type) {
787f2e35a3aSmrg    case KeyPress:
788f2e35a3aSmrg	/* FALLTHRU */
789f2e35a3aSmrg    case KeyRelease:
790f2e35a3aSmrg	TRACE((" keycode 0x%04X %s",
791f2e35a3aSmrg	       ev->xkey.keycode,
792f2e35a3aSmrg	       formatEventMask(mask_buffer, ev->xkey.state, False)));
793f2e35a3aSmrg	break;
794f2e35a3aSmrg    case ButtonPress:
795f2e35a3aSmrg	/* FALLTHRU */
796f2e35a3aSmrg    case ButtonRelease:
797f2e35a3aSmrg	TRACE((" button %u state %#x %s",
798f2e35a3aSmrg	       ev->xbutton.button,
799f2e35a3aSmrg	       ev->xbutton.state,
800f2e35a3aSmrg	       formatEventMask(mask_buffer, ev->xbutton.state, True)));
801f2e35a3aSmrg	break;
802f2e35a3aSmrg    case MotionNotify:
803f2e35a3aSmrg	TRACE((" (%d,%d) state %#x %s",
804f2e35a3aSmrg	       ev->xmotion.y_root,
805f2e35a3aSmrg	       ev->xmotion.x_root,
806f2e35a3aSmrg	       ev->xmotion.state,
807f2e35a3aSmrg	       formatEventMask(mask_buffer, ev->xmotion.state, True)));
808f2e35a3aSmrg	break;
809f2e35a3aSmrg    case EnterNotify:
810f2e35a3aSmrg    case LeaveNotify:
811f2e35a3aSmrg	TRACE((" at %d,%d root %d,%d %s %s",
812f2e35a3aSmrg	       ev->xcrossing.y,
813f2e35a3aSmrg	       ev->xcrossing.x,
814f2e35a3aSmrg	       ev->xcrossing.y_root,
815f2e35a3aSmrg	       ev->xcrossing.x_root,
816f2e35a3aSmrg	       visibleNotifyMode(ev->xcrossing.mode),
817f2e35a3aSmrg	       visibleNotifyDetail(ev->xcrossing.detail)));
818f2e35a3aSmrg	break;
819f2e35a3aSmrg    case FocusIn:
820f2e35a3aSmrg    case FocusOut:
821f2e35a3aSmrg	TRACE((" %s %s",
822f2e35a3aSmrg	       visibleNotifyMode(ev->xfocus.mode),
823f2e35a3aSmrg	       visibleNotifyDetail(ev->xfocus.detail)));
824f2e35a3aSmrg	break;
825f2e35a3aSmrg    case MapNotify:
826f2e35a3aSmrg	TRACE((" event %#lx %s",
827f2e35a3aSmrg	       ev->xmap.event,
828f2e35a3aSmrg	       ev->xmap.override_redirect ? "override" : ""));
829f2e35a3aSmrg	break;
830f2e35a3aSmrg    case UnmapNotify:
831f2e35a3aSmrg	TRACE((" event %#lx %s",
832f2e35a3aSmrg	       ev->xunmap.event,
833f2e35a3aSmrg	       ev->xunmap.from_configure ? "configure" : ""));
834f2e35a3aSmrg	break;
835f2e35a3aSmrg    case ReparentNotify:
836f2e35a3aSmrg	TRACE((" at %d,%d event %#lx parent %#lx %s",
837f2e35a3aSmrg	       ev->xreparent.y,
838f2e35a3aSmrg	       ev->xreparent.x,
839f2e35a3aSmrg	       ev->xreparent.event,
840f2e35a3aSmrg	       ev->xreparent.parent,
841f2e35a3aSmrg	       ev->xreparent.override_redirect ? "override" : ""));
842f2e35a3aSmrg	break;
843f2e35a3aSmrg    case ConfigureNotify:
844f2e35a3aSmrg	TRACE((" at %d,%d size %dx%d bd %d above %#lx",
845f2e35a3aSmrg	       ev->xconfigure.y,
846f2e35a3aSmrg	       ev->xconfigure.x,
847f2e35a3aSmrg	       ev->xconfigure.height,
848f2e35a3aSmrg	       ev->xconfigure.width,
849f2e35a3aSmrg	       ev->xconfigure.border_width,
850f2e35a3aSmrg	       ev->xconfigure.above));
851f2e35a3aSmrg	break;
852f2e35a3aSmrg    case CreateNotify:
853f2e35a3aSmrg	TRACE((" at %d,%d size %dx%d bd %d",
854f2e35a3aSmrg	       ev->xcreatewindow.y,
855f2e35a3aSmrg	       ev->xcreatewindow.x,
856f2e35a3aSmrg	       ev->xcreatewindow.height,
857f2e35a3aSmrg	       ev->xcreatewindow.width,
858f2e35a3aSmrg	       ev->xcreatewindow.border_width));
859f2e35a3aSmrg	break;
860f2e35a3aSmrg    case ResizeRequest:
861f2e35a3aSmrg	TRACE((" size %dx%d",
862f2e35a3aSmrg	       ev->xresizerequest.height,
863f2e35a3aSmrg	       ev->xresizerequest.width));
864f2e35a3aSmrg	break;
865f2e35a3aSmrg    case PropertyNotify:
866f2e35a3aSmrg	TRACE((" %s %s",
867f2e35a3aSmrg	       TraceAtomName(XtDisplay(toplevel), ev->xproperty.atom),
868f2e35a3aSmrg	       ((ev->xproperty.state == PropertyNewValue)
869f2e35a3aSmrg		? "NewValue"
870f2e35a3aSmrg		: ((ev->xproperty.state == PropertyDelete)
871f2e35a3aSmrg		   ? "Delete"
872f2e35a3aSmrg		   : "?"))));
873f2e35a3aSmrg
874f2e35a3aSmrg	break;
875f2e35a3aSmrg    case Expose:
876f2e35a3aSmrg	TRACE((" at %d,%d size %dx%d count %d",
877f2e35a3aSmrg	       ev->xexpose.y,
878f2e35a3aSmrg	       ev->xexpose.x,
879f2e35a3aSmrg	       ev->xexpose.height,
880f2e35a3aSmrg	       ev->xexpose.width,
881f2e35a3aSmrg	       ev->xexpose.count));
882f2e35a3aSmrg	break;
883f2e35a3aSmrg    case MappingNotify:
884f2e35a3aSmrg	TRACE((" %s first_keycode %d count %d",
885f2e35a3aSmrg	       visibleMappingMode(ev->xmapping.request),
886f2e35a3aSmrg	       ev->xmapping.first_keycode,
887f2e35a3aSmrg	       ev->xmapping.count));
888f2e35a3aSmrg	break;
889f2e35a3aSmrg    case VisibilityNotify:
890f2e35a3aSmrg	TRACE((" state %d",
891f2e35a3aSmrg	       ev->xvisibility.state));
892f2e35a3aSmrg	break;
893f2e35a3aSmrg    case KeymapNotify:
894f2e35a3aSmrg	{
895f2e35a3aSmrg	    Cardinal j;
896f2e35a3aSmrg	    for (j = 0; j < XtNumber(ev->xkeymap.key_vector); ++j) {
897f2e35a3aSmrg		if (ev->xkeymap.key_vector[j] != 0) {
898f2e35a3aSmrg		    Cardinal k;
899f2e35a3aSmrg		    for (k = 0; k < 8; ++k) {
900f2e35a3aSmrg			if (ev->xkeymap.key_vector[j] & (1 << k)) {
901f2e35a3aSmrg			    TRACE((" key%u", (j * 8) + k));
902f2e35a3aSmrg			}
903f2e35a3aSmrg		    }
904f2e35a3aSmrg		}
905f2e35a3aSmrg	    }
906f2e35a3aSmrg	}
907f2e35a3aSmrg	break;
908f2e35a3aSmrg    case NoExpose:
909f2e35a3aSmrg	TRACE((" send_event:%d display %p major:%d minor:%d",
910f2e35a3aSmrg	       ev->xnoexpose.send_event,
911f2e35a3aSmrg	       (void *) ev->xnoexpose.display,
912f2e35a3aSmrg	       ev->xnoexpose.major_code,
913f2e35a3aSmrg	       ev->xnoexpose.minor_code));
914f2e35a3aSmrg	break;
915a5ae21e4Smrg    case GraphicsExpose:
916a5ae21e4Smrg	TRACE((" send_event:%d display %p major:%d minor:%d",
917a5ae21e4Smrg	       ev->xgraphicsexpose.send_event,
918a5ae21e4Smrg	       (void *) ev->xgraphicsexpose.display,
919a5ae21e4Smrg	       ev->xgraphicsexpose.major_code,
920a5ae21e4Smrg	       ev->xgraphicsexpose.minor_code));
921a5ae21e4Smrg	break;
922f2e35a3aSmrg    case SelectionClear:
923f2e35a3aSmrg	TRACE((" selection:%s",
924f2e35a3aSmrg	       TraceAtomName(ev->xselectionclear.display,
925f2e35a3aSmrg			     ev->xselectionclear.selection)));
926f2e35a3aSmrg	break;
927f2e35a3aSmrg    case SelectionRequest:
928f2e35a3aSmrg	TRACE((" owner:%#lx requestor:%#lx",
929f2e35a3aSmrg	       ev->xselectionrequest.owner,
930f2e35a3aSmrg	       ev->xselectionrequest.requestor));
931f2e35a3aSmrg	TRACE((" selection:%s",
932f2e35a3aSmrg	       TraceAtomName(ev->xselectionrequest.display,
933f2e35a3aSmrg			     ev->xselectionrequest.selection)));
934f2e35a3aSmrg	TRACE((" target:%s",
935f2e35a3aSmrg	       TraceAtomName(ev->xselectionrequest.display,
936f2e35a3aSmrg			     ev->xselectionrequest.target)));
937f2e35a3aSmrg	TRACE((" property:%s",
938f2e35a3aSmrg	       TraceAtomName(ev->xselectionrequest.display,
939f2e35a3aSmrg			     ev->xselectionrequest.property)));
940f2e35a3aSmrg	break;
941f2e35a3aSmrg    default:
942f2e35a3aSmrg	TRACE((":FIXME"));
943f2e35a3aSmrg	break;
944f2e35a3aSmrg    }
945f2e35a3aSmrg    TRACE(("\n"));
946f2e35a3aSmrg    if (params != 0 && *num_params != 0) {
947f2e35a3aSmrg	Cardinal n;
948f2e35a3aSmrg	for (n = 0; n < *num_params; ++n) {
949f2e35a3aSmrg	    TRACE(("  param[%d] = %s\n", n, params[n]));
950f2e35a3aSmrg	}
951f2e35a3aSmrg    }
952f2e35a3aSmrg}
953f2e35a3aSmrg
954f2e35a3aSmrg#if OPT_RENDERFONT && OPT_WIDE_CHARS
955f2e35a3aSmrgvoid
956f2e35a3aSmrgTraceFallback(XtermWidget xw, const char *tag, unsigned wc, int n, XftFont *font)
957f2e35a3aSmrg{
958f2e35a3aSmrg    TScreen *screen = TScreenOf(xw);
959f2e35a3aSmrg    XGlyphInfo gi;
960f2e35a3aSmrg    int expect = my_wcwidth((wchar_t) wc);
961f2e35a3aSmrg    int hijack = mk_wcwidth_cjk((wchar_t) wc);
962f2e35a3aSmrg    int actual;
963f2e35a3aSmrg
964f2e35a3aSmrg    XftTextExtents32(screen->display, font, &wc, 1, &gi);
965f2e35a3aSmrg    actual = ((gi.xOff + FontWidth(screen) - 1)
966f2e35a3aSmrg	      / FontWidth(screen));
967f2e35a3aSmrg
968f2e35a3aSmrg    TRACE(("FALLBACK #%d %s U+%04X %d,%d pos,"
969f2e35a3aSmrg	   " %d,%d off," " %dx%d size,"
970f2e35a3aSmrg	   " %d/%d next," " %d vs %d/%d cells%s\n",
971f2e35a3aSmrg	   n + 1, tag, wc,
972f2e35a3aSmrg	   gi.y, gi.x,
973f2e35a3aSmrg	   gi.yOff, gi.xOff,
974f2e35a3aSmrg	   gi.height, gi.width,
975f2e35a3aSmrg	   font->max_advance_width,
976f2e35a3aSmrg	   FontWidth(screen),
977f2e35a3aSmrg	   actual, expect, hijack,
978f2e35a3aSmrg	   ((actual != expect)
979f2e35a3aSmrg	    ? ((actual == hijack)
980f2e35a3aSmrg	       ? " OOPS"
981f2e35a3aSmrg	       : " oops")
982f2e35a3aSmrg	    : "")));
983f2e35a3aSmrg}
984f2e35a3aSmrg#endif /* OPT_RENDERFONT */
985f2e35a3aSmrg
98620d2c4d2Smrgvoid
98701037d57SmrgTraceFocus(Widget w, XEvent *ev)
98820d2c4d2Smrg{
98920d2c4d2Smrg    TRACE(("trace_focus event type %d:%s\n",
99020d2c4d2Smrg	   ev->type, visibleEventType(ev->type)));
99120d2c4d2Smrg    switch (ev->type) {
99220d2c4d2Smrg    case FocusIn:
99320d2c4d2Smrg    case FocusOut:
99420d2c4d2Smrg	{
99520d2c4d2Smrg	    XFocusChangeEvent *event = (XFocusChangeEvent *) ev;
99620d2c4d2Smrg	    TRACE(("\tdetail: %s\n", visibleNotifyDetail(event->detail)));
9970bd37d32Smrg	    TRACE(("\tmode:   %s\n", visibleNotifyMode(event->mode)));
99820d2c4d2Smrg	    TRACE(("\twindow: %#lx\n", event->window));
99920d2c4d2Smrg	}
100020d2c4d2Smrg	break;
100120d2c4d2Smrg    case EnterNotify:
100220d2c4d2Smrg    case LeaveNotify:
100320d2c4d2Smrg	{
100420d2c4d2Smrg	    XCrossingEvent *event = (XCrossingEvent *) ev;
100520d2c4d2Smrg	    TRACE(("\tdetail:    %s\n", visibleNotifyDetail(event->detail)));
10060bd37d32Smrg	    TRACE(("\tmode:      %s\n", visibleNotifyMode(event->mode)));
100720d2c4d2Smrg	    TRACE(("\twindow:    %#lx\n", event->window));
1008e39b573cSmrg	    TRACE(("\tfocus:     %d\n", event->focus));
100920d2c4d2Smrg	    TRACE(("\troot:      %#lx\n", event->root));
101020d2c4d2Smrg	    TRACE(("\tsubwindow: %#lx\n", event->subwindow));
101120d2c4d2Smrg	}
101220d2c4d2Smrg	break;
101320d2c4d2Smrg    }
101420d2c4d2Smrg    while (w != 0) {
101520d2c4d2Smrg	TRACE(("w %p -> %#lx\n", (void *) w, XtWindow(w)));
101620d2c4d2Smrg	w = XtParent(w);
101720d2c4d2Smrg    }
101820d2c4d2Smrg}
101920d2c4d2Smrg
1020d522f475Smrgvoid
1021d522f475SmrgTraceSizeHints(XSizeHints * hints)
1022d522f475Smrg{
1023d522f475Smrg    TRACE(("size hints:\n"));
1024f2e35a3aSmrg    if (hints->flags & (USPosition | PPosition)) {
1025d522f475Smrg	TRACE(("   position   %d,%d%s%s\n", hints->y, hints->x,
10262e4f8982Smrg	       (hints->flags & USPosition) ? " user" : "",
10272e4f8982Smrg	       (hints->flags & PPosition) ? " prog" : ""));
1028f2e35a3aSmrg    }
1029f2e35a3aSmrg    if (hints->flags & (USSize | PSize)) {
1030d522f475Smrg	TRACE(("   size       %d,%d%s%s\n", hints->height, hints->width,
10312e4f8982Smrg	       (hints->flags & USSize) ? " user" : "",
10322e4f8982Smrg	       (hints->flags & PSize) ? " prog" : ""));
1033f2e35a3aSmrg    }
1034f2e35a3aSmrg    if (hints->flags & PMinSize) {
1035d522f475Smrg	TRACE(("   min        %d,%d\n", hints->min_height, hints->min_width));
1036f2e35a3aSmrg    }
1037f2e35a3aSmrg    if (hints->flags & PMaxSize) {
1038d522f475Smrg	TRACE(("   max        %d,%d\n", hints->max_height, hints->max_width));
1039f2e35a3aSmrg    }
1040f2e35a3aSmrg    if (hints->flags & PResizeInc) {
1041d522f475Smrg	TRACE(("   inc        %d,%d\n", hints->height_inc, hints->width_inc));
1042f2e35a3aSmrg    } else {
10432eaa94a1Schristos	TRACE(("   inc        NONE!\n"));
1044f2e35a3aSmrg    }
1045f2e35a3aSmrg    if (hints->flags & PAspect) {
1046d522f475Smrg	TRACE(("   min aspect %d/%d\n", hints->min_aspect.y, hints->min_aspect.y));
1047d522f475Smrg	TRACE(("   max aspect %d/%d\n", hints->max_aspect.y, hints->max_aspect.y));
1048f2e35a3aSmrg    }
1049f2e35a3aSmrg    if (hints->flags & PBaseSize) {
1050d522f475Smrg	TRACE(("   base       %d,%d\n", hints->base_height, hints->base_width));
1051f2e35a3aSmrg    }
1052f2e35a3aSmrg    if (hints->flags & PWinGravity) {
1053d522f475Smrg	TRACE(("   gravity    %d\n", hints->win_gravity));
1054f2e35a3aSmrg    }
1055d522f475Smrg}
1056d522f475Smrg
10570bd37d32Smrgstatic void
10580bd37d32SmrgTraceEventMask(const char *tag, long mask)
10590bd37d32Smrg{
10600bd37d32Smrg#define DATA(name) { name##Mask, #name }
10610bd37d32Smrg    /* *INDENT-OFF* */
10620bd37d32Smrg    static struct {
10630bd37d32Smrg	long mask;
10640bd37d32Smrg	const char *name;
10650bd37d32Smrg    } table[] = {
10660bd37d32Smrg	DATA(KeyPress),
10670bd37d32Smrg	DATA(KeyRelease),
10680bd37d32Smrg	DATA(ButtonPress),
10690bd37d32Smrg	DATA(ButtonRelease),
10700bd37d32Smrg	DATA(EnterWindow),
10710bd37d32Smrg	DATA(LeaveWindow),
10720bd37d32Smrg	DATA(PointerMotion),
10730bd37d32Smrg	DATA(PointerMotionHint),
10740bd37d32Smrg	DATA(Button1Motion),
10750bd37d32Smrg	DATA(Button2Motion),
10760bd37d32Smrg	DATA(Button3Motion),
10770bd37d32Smrg	DATA(Button4Motion),
10780bd37d32Smrg	DATA(Button5Motion),
10790bd37d32Smrg	DATA(ButtonMotion),
10800bd37d32Smrg	DATA(KeymapState),
10810bd37d32Smrg	DATA(Exposure),
10820bd37d32Smrg	DATA(VisibilityChange),
10830bd37d32Smrg	DATA(StructureNotify),
10840bd37d32Smrg	DATA(ResizeRedirect),
10850bd37d32Smrg	DATA(SubstructureNotify),
10860bd37d32Smrg	DATA(SubstructureRedirect),
10870bd37d32Smrg	DATA(FocusChange),
10880bd37d32Smrg	DATA(PropertyChange),
10890bd37d32Smrg	DATA(ColormapChange),
10900bd37d32Smrg	DATA(OwnerGrabButton),
10910bd37d32Smrg    };
10920bd37d32Smrg#undef DATA
10930bd37d32Smrg    Cardinal n;
10940bd37d32Smrg    /* *INDENT-ON* */
10950bd37d32Smrg
10960bd37d32Smrg    for (n = 0; n < XtNumber(table); ++n) {
10970bd37d32Smrg	if (table[n].mask & mask) {
10980bd37d32Smrg	    TRACE(("%s %s\n", tag, table[n].name));
10990bd37d32Smrg	}
11000bd37d32Smrg    }
11010bd37d32Smrg}
11020bd37d32Smrg
11030bd37d32Smrgvoid
11040bd37d32SmrgTraceWindowAttributes(XWindowAttributes * attrs)
11050bd37d32Smrg{
11060bd37d32Smrg    TRACE(("window attributes:\n"));
11070bd37d32Smrg    TRACE(("   position     %d,%d\n", attrs->y, attrs->x));
11080bd37d32Smrg    TRACE(("   size         %dx%d\n", attrs->height, attrs->width));
11090bd37d32Smrg    TRACE(("   border       %d\n", attrs->border_width));
11100bd37d32Smrg    TRACE(("   depth        %d\n", attrs->depth));
11110bd37d32Smrg    TRACE(("   bit_gravity  %d\n", attrs->bit_gravity));
11120bd37d32Smrg    TRACE(("   win_gravity  %d\n", attrs->win_gravity));
11130bd37d32Smrg    TRACE(("   root         %#lx\n", (long) attrs->root));
11140bd37d32Smrg    TRACE(("   class        %s\n", ((attrs->class == InputOutput)
11150bd37d32Smrg				    ? "InputOutput"
11160bd37d32Smrg				    : ((attrs->class == InputOnly)
11170bd37d32Smrg				       ? "InputOnly"
11180bd37d32Smrg				       : "unknown"))));
11190bd37d32Smrg    TRACE(("   map_state    %s\n", ((attrs->map_state == IsUnmapped)
11200bd37d32Smrg				    ? "IsUnmapped"
11210bd37d32Smrg				    : ((attrs->map_state == IsUnviewable)
11220bd37d32Smrg				       ? "IsUnviewable"
11230bd37d32Smrg				       : ((attrs->map_state == IsViewable)
11240bd37d32Smrg					  ? "IsViewable"
11250bd37d32Smrg					  : "unknown")))));
11260bd37d32Smrg    TRACE(("   all_events\n"));
11270bd37d32Smrg    TraceEventMask("        ", attrs->all_event_masks);
11280bd37d32Smrg    TRACE(("   your_events\n"));
11290bd37d32Smrg    TraceEventMask("        ", attrs->your_event_mask);
11300bd37d32Smrg    TRACE(("   no_propagate\n"));
11310bd37d32Smrg    TraceEventMask("        ", attrs->do_not_propagate_mask);
11320bd37d32Smrg}
11330bd37d32Smrg
1134d522f475Smrgvoid
1135d522f475SmrgTraceWMSizeHints(XtermWidget xw)
1136d522f475Smrg{
1137d522f475Smrg    XSizeHints sizehints = xw->hints;
1138d522f475Smrg
1139d522f475Smrg    getXtermSizeHints(xw);
1140d522f475Smrg    TraceSizeHints(&xw->hints);
1141d522f475Smrg    xw->hints = sizehints;
1142d522f475Smrg}
1143d522f475Smrg
11440bd37d32Smrgconst char *
11450bd37d32SmrgModifierName(unsigned modifier)
11460bd37d32Smrg{
11470bd37d32Smrg    const char *s = "";
11480bd37d32Smrg    if (modifier & ShiftMask)
11490bd37d32Smrg	s = " Shift";
11500bd37d32Smrg    else if (modifier & LockMask)
11510bd37d32Smrg	s = " Lock";
11520bd37d32Smrg    else if (modifier & ControlMask)
11530bd37d32Smrg	s = " Control";
11540bd37d32Smrg    else if (modifier & Mod1Mask)
11550bd37d32Smrg	s = " Mod1";
11560bd37d32Smrg    else if (modifier & Mod2Mask)
11570bd37d32Smrg	s = " Mod2";
11580bd37d32Smrg    else if (modifier & Mod3Mask)
11590bd37d32Smrg	s = " Mod3";
11600bd37d32Smrg    else if (modifier & Mod4Mask)
11610bd37d32Smrg	s = " Mod4";
11620bd37d32Smrg    else if (modifier & Mod5Mask)
11630bd37d32Smrg	s = " Mod5";
11640bd37d32Smrg    return s;
11650bd37d32Smrg}
11660bd37d32Smrg
1167d522f475Smrgvoid
1168d522f475SmrgTraceTranslations(const char *name, Widget w)
1169d522f475Smrg{
1170d522f475Smrg    String result;
1171f2e35a3aSmrg    XErrorHandler save = XSetErrorHandler(ignore_x11_error);
1172d522f475Smrg    XtTranslations xlations;
1173d522f475Smrg    Widget xcelerat;
1174d522f475Smrg
1175f2e35a3aSmrg    TRACE(("TraceTranslations for %s (widget %#lx) " TRACE_L "\n",
1176f2e35a3aSmrg	   name, (long) w));
1177d522f475Smrg    if (w) {
1178d522f475Smrg	XtVaGetValues(w,
1179d522f475Smrg		      XtNtranslations, &xlations,
1180d522f475Smrg		      XtNaccelerators, &xcelerat,
1181d522f475Smrg		      (XtPointer) 0);
1182d522f475Smrg	TRACE(("... xlations %#08lx\n", (long) xlations));
1183d522f475Smrg	TRACE(("... xcelerat %#08lx\n", (long) xcelerat));
1184d522f475Smrg	result = _XtPrintXlations(w, xlations, xcelerat, True);
118520d2c4d2Smrg	TRACE(("%s\n", NonNull(result)));
1186d522f475Smrg	if (result)
118720d2c4d2Smrg	    XFree((char *) result);
1188d522f475Smrg    } else {
1189d522f475Smrg	TRACE(("none (widget is null)\n"));
1190d522f475Smrg    }
1191f2e35a3aSmrg    TRACE((TRACE_R "\n"));
1192d522f475Smrg    XSetErrorHandler(save);
1193d522f475Smrg}
1194d522f475Smrg
11950bd37d32SmrgXtGeometryResult
11962eaa94a1SchristosTraceResizeRequest(const char *fn, int ln, Widget w,
1197e39b573cSmrg		   unsigned reqwide,
1198e39b573cSmrg		   unsigned reqhigh,
1199e0a2b6dfSmrg		   Dimension *gotwide,
1200e0a2b6dfSmrg		   Dimension *gothigh)
12012eaa94a1Schristos{
12020bd37d32Smrg    XtGeometryResult rc;
12032eaa94a1Schristos
1204e39b573cSmrg    TRACE(("%s@%d ResizeRequest %ux%u\n", fn, ln, reqhigh, reqwide));
12050bd37d32Smrg    rc = XtMakeResizeRequest((Widget) w,
12060bd37d32Smrg			     (Dimension) reqwide,
12070bd37d32Smrg			     (Dimension) reqhigh,
12080bd37d32Smrg			     gotwide, gothigh);
12092eaa94a1Schristos    TRACE(("... ResizeRequest -> "));
12102eaa94a1Schristos    if (gothigh && gotwide)
12112eaa94a1Schristos	TRACE(("%dx%d ", *gothigh, *gotwide));
12122eaa94a1Schristos    TRACE(("(%d)\n", rc));
12132eaa94a1Schristos    return rc;
12142eaa94a1Schristos}
12152eaa94a1Schristos
1216d522f475Smrg#define XRES_S(name) Trace(#name " = %s\n", NonNull(resp->name))
121701037d57Smrg#define XRES_B(name) Trace(#name " = %s\n", MtoS(resp->name))
1218d522f475Smrg#define XRES_I(name) Trace(#name " = %d\n", resp->name)
1219d522f475Smrg
1220d522f475Smrgvoid
1221d522f475SmrgTraceXtermResources(void)
1222d522f475Smrg{
1223d522f475Smrg    XTERM_RESOURCE *resp = &resource;
1224d522f475Smrg
1225d522f475Smrg    Trace("XTERM_RESOURCE settings:\n");
1226d522f475Smrg    XRES_S(icon_geometry);
1227d522f475Smrg    XRES_S(title);
12280bd37d32Smrg    XRES_S(icon_hint);
1229d522f475Smrg    XRES_S(icon_name);
1230d522f475Smrg    XRES_S(term_name);
1231d522f475Smrg    XRES_S(tty_modes);
1232e39b573cSmrg    XRES_I(minBufSize);
1233e39b573cSmrg    XRES_I(maxBufSize);
1234d522f475Smrg    XRES_B(hold_screen);
1235d522f475Smrg    XRES_B(utmpInhibit);
1236d522f475Smrg    XRES_B(utmpDisplayId);
1237d522f475Smrg    XRES_B(messages);
1238e39b573cSmrg    XRES_S(menuLocale);
1239e39b573cSmrg    XRES_S(omitTranslation);
1240e39b573cSmrg    XRES_S(keyboardType);
1241ad37e533Smrg#ifdef HAVE_LIB_XCURSOR
1242ad37e533Smrg    XRES_S(cursorTheme);
1243ad37e533Smrg#endif
1244e39b573cSmrg#if OPT_PRINT_ON_EXIT
1245e39b573cSmrg    XRES_I(printModeNow);
1246e39b573cSmrg    XRES_I(printModeOnXError);
1247e39b573cSmrg    XRES_I(printOptsNow);
1248e39b573cSmrg    XRES_I(printOptsOnXError);
1249e39b573cSmrg    XRES_S(printFileNow);
1250e39b573cSmrg    XRES_S(printFileOnXError);
1251e39b573cSmrg#endif
1252d522f475Smrg#if OPT_SUNPC_KBD
1253d522f475Smrg    XRES_B(sunKeyboard);
1254d522f475Smrg#endif
1255d522f475Smrg#if OPT_HP_FUNC_KEYS
1256d522f475Smrg    XRES_B(hpFunctionKeys);
1257d522f475Smrg#endif
1258d522f475Smrg#if OPT_SCO_FUNC_KEYS
1259d522f475Smrg    XRES_B(scoFunctionKeys);
1260d522f475Smrg#endif
1261d522f475Smrg#if OPT_SUN_FUNC_KEYS
1262d522f475Smrg    XRES_B(sunFunctionKeys);
1263d522f475Smrg#endif
1264d522f475Smrg#if OPT_INITIAL_ERASE
1265d522f475Smrg    XRES_B(ptyInitialErase);
1266d522f475Smrg    XRES_B(backarrow_is_erase);
1267d522f475Smrg#endif
1268d522f475Smrg    XRES_B(useInsertMode);
1269d522f475Smrg#if OPT_ZICONBEEP
1270d522f475Smrg    XRES_I(zIconBeep);
12710bd37d32Smrg    XRES_S(zIconFormat);
1272d522f475Smrg#endif
1273d522f475Smrg#if OPT_PTY_HANDSHAKE
1274d522f475Smrg    XRES_B(wait_for_map);
1275d522f475Smrg    XRES_B(ptyHandshake);
1276d522f475Smrg    XRES_B(ptySttySize);
1277d522f475Smrg#endif
1278913cc679Smrg#if OPT_REPORT_CCLASS
1279913cc679Smrg    XRES_B(reportCClass);
1280913cc679Smrg#endif
1281e0a2b6dfSmrg#if OPT_REPORT_COLORS
1282e0a2b6dfSmrg    XRES_B(reportColors);
1283e0a2b6dfSmrg#endif
1284e0a2b6dfSmrg#if OPT_REPORT_FONTS
1285e0a2b6dfSmrg    XRES_B(reportFonts);
1286e0a2b6dfSmrg#endif
1287f2e35a3aSmrg#if OPT_REPORT_ICONS
1288f2e35a3aSmrg    XRES_B(reportIcons);
1289f2e35a3aSmrg#endif
1290d522f475Smrg#if OPT_SAME_NAME
1291d522f475Smrg    XRES_B(sameName);
1292d522f475Smrg#endif
1293d522f475Smrg#if OPT_SESSION_MGT
1294d522f475Smrg    XRES_B(sessionMgt);
1295d522f475Smrg#endif
1296a1f3da82Smrg#if OPT_TOOLBAR
1297a1f3da82Smrg    XRES_B(toolBar);
1298a1f3da82Smrg#endif
1299a1f3da82Smrg#if OPT_MAXIMIZE
1300a1f3da82Smrg    XRES_B(maximized);
1301a1f3da82Smrg    XRES_S(fullscreen_s);
1302a1f3da82Smrg#endif
1303f2e35a3aSmrg#if USE_DOUBLE_BUFFER
1304f2e35a3aSmrg    XRES_B(buffered);
1305f2e35a3aSmrg    XRES_I(buffered_fps);
1306f2e35a3aSmrg#endif
1307d522f475Smrg}
1308d522f475Smrg
1309d522f475Smrgvoid
1310d522f475SmrgTraceArgv(const char *tag, char **argv)
1311d522f475Smrg{
1312d522f475Smrg    TRACE(("%s:\n", tag));
1313913cc679Smrg    if (argv != 0) {
1314913cc679Smrg	int n = 0;
1315913cc679Smrg
1316913cc679Smrg	while (*argv != 0) {
1317913cc679Smrg	    TRACE(("  %d:%s\n", n++, *argv++));
1318913cc679Smrg	}
1319d522f475Smrg    }
1320d522f475Smrg}
1321d522f475Smrg
1322d522f475Smrgstatic char *
132320d2c4d2Smrgparse_option(char *dst, String src, int first)
1324d522f475Smrg{
1325d522f475Smrg    char *s;
1326d522f475Smrg
1327a1f3da82Smrg    if (!strncmp(src, "-/+", (size_t) 3)) {
1328956cc18dSsnj	dst[0] = (char) first;
1329d522f475Smrg	strcpy(dst + 1, src + 3);
1330d522f475Smrg    } else {
1331d522f475Smrg	strcpy(dst, src);
1332d522f475Smrg    }
1333d522f475Smrg    for (s = dst; *s != '\0'; s++) {
1334d522f475Smrg	if (*s == '#' || *s == '%' || *s == 'S') {
1335d522f475Smrg	    s[1] = '\0';
1336d522f475Smrg	} else if (*s == ' ') {
1337d522f475Smrg	    *s = '\0';
1338d522f475Smrg	    break;
1339d522f475Smrg	}
1340d522f475Smrg    }
1341d522f475Smrg    return dst;
1342d522f475Smrg}
1343d522f475Smrg
1344d522f475Smrgstatic Bool
1345d522f475Smrgsame_option(OptionHelp * opt, XrmOptionDescRec * res)
1346d522f475Smrg{
1347d522f475Smrg    char temp[BUFSIZ];
1348d522f475Smrg    return !strcmp(parse_option(temp, opt->opt, res->option[0]), res->option);
1349d522f475Smrg}
1350d522f475Smrg
1351d522f475Smrgstatic Bool
135220d2c4d2Smrgstandard_option(String opt)
1353d522f475Smrg{
1354d522f475Smrg    static const char *table[] =
1355d522f475Smrg    {
1356d522f475Smrg	"+rv",
1357d522f475Smrg	"+synchronous",
1358d522f475Smrg	"-background",
1359d522f475Smrg	"-bd",
1360d522f475Smrg	"-bg",
1361d522f475Smrg	"-bordercolor",
1362d522f475Smrg	"-borderwidth",
1363d522f475Smrg	"-bw",
1364d522f475Smrg	"-display",
1365d522f475Smrg	"-fg",
1366d522f475Smrg	"-fn",
1367d522f475Smrg	"-font",
1368d522f475Smrg	"-foreground",
1369d522f475Smrg	"-geometry",
1370d522f475Smrg	"-iconic",
1371d522f475Smrg	"-name",
1372d522f475Smrg	"-reverse",
1373d522f475Smrg	"-rv",
1374d522f475Smrg	"-selectionTimeout",
1375d522f475Smrg	"-synchronous",
1376d522f475Smrg	"-title",
1377d522f475Smrg	"-xnllanguage",
1378d522f475Smrg	"-xrm",
1379d522f475Smrg	"-xtsessionID",
1380d522f475Smrg    };
1381d522f475Smrg    Cardinal n;
1382d522f475Smrg    char temp[BUFSIZ];
1383d522f475Smrg
1384d522f475Smrg    opt = parse_option(temp, opt, '-');
1385d522f475Smrg    for (n = 0; n < XtNumber(table); n++) {
1386d522f475Smrg	if (!strcmp(opt, table[n]))
1387d522f475Smrg	    return True;
1388d522f475Smrg    }
1389d522f475Smrg    return False;
1390d522f475Smrg}
1391d522f475Smrg
1392d522f475Smrg/*
1393d522f475Smrg * Analyse the options/help messages for inconsistencies.
1394d522f475Smrg */
1395d522f475Smrgvoid
1396d522f475SmrgTraceOptions(OptionHelp * options, XrmOptionDescRec * resources, Cardinal res_count)
1397d522f475Smrg{
1398d522f475Smrg    OptionHelp *opt_array = sortedOpts(options, resources, res_count);
1399d522f475Smrg    size_t j, k;
1400d522f475Smrg    XrmOptionDescRec *res_array = sortedOptDescs(resources, res_count);
1401d522f475Smrg    Bool first, found;
1402d522f475Smrg
1403d522f475Smrg    TRACE(("Checking options-tables for inconsistencies:\n"));
1404d522f475Smrg
1405d522f475Smrg#if 0
1406d522f475Smrg    TRACE(("Options listed in help-message:\n"));
1407d522f475Smrg    for (j = 0; options[j].opt != 0; j++)
1408d522f475Smrg	TRACE(("%5d %-28s %s\n", j, opt_array[j].opt, opt_array[j].desc));
1409d522f475Smrg    TRACE(("Options listed in resource-table:\n"));
1410d522f475Smrg    for (j = 0; j < res_count; j++)
1411d522f475Smrg	TRACE(("%5d %-28s %s\n", j, res_array[j].option, res_array[j].specifier));
1412d522f475Smrg#endif
1413d522f475Smrg
1414d522f475Smrg    /* list all options[] not found in resources[] */
1415d522f475Smrg    for (j = 0, first = True; options[j].opt != 0; j++) {
1416d522f475Smrg	found = False;
1417d522f475Smrg	for (k = 0; k < res_count; k++) {
1418d522f475Smrg	    if (same_option(&opt_array[j], &res_array[k])) {
1419d522f475Smrg		found = True;
1420d522f475Smrg		break;
1421d522f475Smrg	    }
1422d522f475Smrg	}
1423d522f475Smrg	if (!found) {
1424d522f475Smrg	    if (first) {
1425d522f475Smrg		TRACE(("Options listed in help, not found in resource list:\n"));
1426d522f475Smrg		first = False;
1427d522f475Smrg	    }
1428d522f475Smrg	    TRACE(("  %-28s%s\n", opt_array[j].opt,
1429d522f475Smrg		   standard_option(opt_array[j].opt) ? " (standard)" : ""));
1430d522f475Smrg	}
1431d522f475Smrg    }
1432d522f475Smrg
1433d522f475Smrg    /* list all resources[] not found in options[] */
1434d522f475Smrg    for (j = 0, first = True; j < res_count; j++) {
1435d522f475Smrg	found = False;
1436d522f475Smrg	for (k = 0; options[k].opt != 0; k++) {
1437d522f475Smrg	    if (same_option(&opt_array[k], &res_array[j])) {
1438d522f475Smrg		found = True;
1439d522f475Smrg		break;
1440d522f475Smrg	    }
1441d522f475Smrg	}
1442d522f475Smrg	if (!found) {
1443d522f475Smrg	    if (first) {
1444d522f475Smrg		TRACE(("Resource list items not found in options-help:\n"));
1445d522f475Smrg		first = False;
1446d522f475Smrg	    }
1447d522f475Smrg	    TRACE(("  %s\n", res_array[j].option));
1448d522f475Smrg	}
1449d522f475Smrg    }
1450d522f475Smrg
1451d522f475Smrg    TRACE(("Resource list items that will be ignored by XtOpenApplication:\n"));
1452d522f475Smrg    for (j = 0; j < res_count; j++) {
1453d522f475Smrg	switch (res_array[j].argKind) {
1454d522f475Smrg	case XrmoptionSkipArg:
1455d522f475Smrg	    TRACE(("  %-28s {param}\n", res_array[j].option));
1456d522f475Smrg	    break;
1457d522f475Smrg	case XrmoptionSkipNArgs:
1458d522f475Smrg	    TRACE(("  %-28s {%ld params}\n", res_array[j].option, (long)
1459d522f475Smrg		   res_array[j].value));
1460d522f475Smrg	    break;
1461d522f475Smrg	case XrmoptionSkipLine:
1462d522f475Smrg	    TRACE(("  %-28s {remainder of line}\n", res_array[j].option));
1463d522f475Smrg	    break;
1464d522f475Smrg	case XrmoptionIsArg:
1465d522f475Smrg	case XrmoptionNoArg:
1466d522f475Smrg	case XrmoptionResArg:
1467d522f475Smrg	case XrmoptionSepArg:
1468d522f475Smrg	case XrmoptionStickyArg:
1469d522f475Smrg	default:
1470d522f475Smrg	    break;
1471d522f475Smrg	}
1472d522f475Smrg    }
1473d522f475Smrg}
1474a1f3da82Smrg#else
1475a1f3da82Smrgextern void empty_trace(void);
1476a1f3da82Smrgvoid
1477a1f3da82Smrgempty_trace(void)
1478a1f3da82Smrg{
1479a1f3da82Smrg}
1480a1f3da82Smrg#endif
1481