trace.c revision 2e4f8982
12e4f8982Smrg/* $XTermId: trace.c,v 1.166 2016/10/05 09:16:01 tom Exp $ */
2d522f475Smrg
320d2c4d2Smrg/*
42e4f8982Smrg * Copyright 1997-2015,2016 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 */
380bd37d32Smrg#include <version.h>
39a1f3da82Smrg
40a1f3da82Smrg#if OPT_TRACE
41a1f3da82Smrg
42d522f475Smrg#include <data.h>
43d522f475Smrg#include <trace.h>
44d522f475Smrg
45d522f475Smrg#include <time.h>
46d522f475Smrg#include <stdlib.h>
47d522f475Smrg#include <unistd.h>
48d522f475Smrg#include <sys/types.h>
49894e0ac8Smrg#include <sys/stat.h>
50d522f475Smrg#include <stdio.h>
51d522f475Smrg#include <stdarg.h>
52d522f475Smrg#include <assert.h>
53d522f475Smrg
54956cc18dSsnj#include <X11/Xatom.h>
55956cc18dSsnj#include <X11/Xmu/Atoms.h>
56956cc18dSsnj
57d522f475Smrg#ifdef HAVE_X11_TRANSLATEI_H
582e4f8982Smrg#include <X11/ConvertI.h>
59d522f475Smrg#include <X11/TranslateI.h>
60d522f475Smrg#else
61d522f475Smrg#ifdef __cplusplus
62d522f475Smrgextern "C" {
63d522f475Smrg#endif
64d522f475Smrg
65d522f475Smrg    extern String _XtPrintXlations(Widget w,
66d522f475Smrg				   XtTranslations xlations,
67d522f475Smrg				   Widget accelWidget,
68d522f475Smrg				   _XtBoolean includeRHS);
69d522f475Smrg#ifdef __cplusplus
70d522f475Smrg}
71d522f475Smrg#endif
72d522f475Smrg#endif
7320d2c4d2Smrgconst char *trace_who = "parent";
7420d2c4d2Smrg
7520d2c4d2Smrgstatic FILE *trace_fp;
76d522f475Smrg
77d522f475Smrgvoid
78d522f475SmrgTrace(const char *fmt,...)
79d522f475Smrg{
8020d2c4d2Smrg    static const char *trace_out;
81d522f475Smrg    va_list ap;
82d522f475Smrg
8320d2c4d2Smrg    if (trace_fp != 0
84d522f475Smrg	&& trace_who != trace_out) {
8520d2c4d2Smrg	fclose(trace_fp);
8620d2c4d2Smrg	trace_fp = 0;
87d522f475Smrg    }
88d522f475Smrg    trace_out = trace_who;
89d522f475Smrg
9020d2c4d2Smrg    if (!trace_fp) {
91894e0ac8Smrg	unsigned oldmask = (unsigned) umask(077);
92d522f475Smrg	char name[BUFSIZ];
93d522f475Smrg#if 0				/* usually I do not want unique names */
94d522f475Smrg	int unique;
95d522f475Smrg	for (unique = 0;; ++unique) {
96d522f475Smrg	    if (unique)
97d522f475Smrg		sprintf(name, "Trace-%s.out-%d", trace_who, unique);
98d522f475Smrg	    else
99d522f475Smrg		sprintf(name, "Trace-%s.out", trace_who);
10020d2c4d2Smrg	    if ((trace_fp = fopen(name, "r")) == 0) {
101d522f475Smrg		break;
102d522f475Smrg	    }
10320d2c4d2Smrg	    fclose(trace_fp);
104d522f475Smrg	}
105d522f475Smrg#else
106d522f475Smrg	sprintf(name, "Trace-%s.out", trace_who);
107d522f475Smrg#endif
10820d2c4d2Smrg	trace_fp = fopen(name, "w");
109e0a2b6dfSmrg	/*
110e0a2b6dfSmrg	 * Try to put the trace-file in user's home-directory if the current
111e0a2b6dfSmrg	 * directory is not writable.
112e0a2b6dfSmrg	 */
113e0a2b6dfSmrg	if (trace_fp == 0) {
114e0a2b6dfSmrg	    char *home = getenv("HOME");
115e0a2b6dfSmrg	    if (home != 0) {
116e0a2b6dfSmrg		sprintf(name, "%.*s/Trace-%.8s.out",
117e0a2b6dfSmrg			(BUFSIZ - 21), home,
118e0a2b6dfSmrg			trace_who);
119e0a2b6dfSmrg		trace_fp = fopen(name, "w");
120e0a2b6dfSmrg	    }
121e0a2b6dfSmrg	}
12220d2c4d2Smrg	if (trace_fp != 0) {
12320d2c4d2Smrg	    fprintf(trace_fp, "%s\n", xtermVersion());
124d522f475Smrg	    TraceIds(NULL, 0);
125d522f475Smrg	}
1260bd37d32Smrg	if (!trace_fp) {
1270bd37d32Smrg	    xtermWarning("Cannot open \"%s\"\n", name);
1280bd37d32Smrg	    exit(EXIT_FAILURE);
1290bd37d32Smrg	}
1300bd37d32Smrg	(void) umask(oldmask);
131d522f475Smrg    }
132d522f475Smrg
133d522f475Smrg    va_start(ap, fmt);
13420d2c4d2Smrg    vfprintf(trace_fp, fmt, ap);
13520d2c4d2Smrg    (void) fflush(trace_fp);
13620d2c4d2Smrg    va_end(ap);
13720d2c4d2Smrg}
13820d2c4d2Smrg
13920d2c4d2Smrgvoid
14020d2c4d2SmrgTraceClose(void)
14120d2c4d2Smrg{
14220d2c4d2Smrg    if (trace_fp != 0) {
14320d2c4d2Smrg	(void) fclose(trace_fp);
144d522f475Smrg	(void) fflush(stdout);
145d522f475Smrg	(void) fflush(stderr);
146956cc18dSsnj	(void) visibleChars(NULL, 0);
147956cc18dSsnj	(void) visibleIChars(NULL, 0);
14820d2c4d2Smrg	trace_fp = 0;
149d522f475Smrg    }
150d522f475Smrg}
151d522f475Smrg
152d522f475Smrgvoid
153d522f475SmrgTraceIds(const char *fname, int lnum)
154d522f475Smrg{
155d522f475Smrg    Trace("process %d ", (int) getpid());
156d522f475Smrg#ifdef HAVE_UNISTD_H
157d522f475Smrg    Trace("real (%u/%u) effective (%u/%u)",
158d522f475Smrg	  (unsigned) getuid(), (unsigned) getgid(),
159d522f475Smrg	  (unsigned) geteuid(), (unsigned) getegid());
160d522f475Smrg#endif
161d522f475Smrg    if (fname != 0) {
162d522f475Smrg	Trace(" (%s@%d)\n", fname, lnum);
163d522f475Smrg    } else {
164d522f475Smrg	time_t now = time((time_t *) 0);
165d522f475Smrg	Trace("-- %s", ctime(&now));
166d522f475Smrg    }
167d522f475Smrg}
168d522f475Smrg
1690bd37d32Smrgvoid
1700bd37d32SmrgTraceTime(const char *fname, int lnum)
1710bd37d32Smrg{
1720bd37d32Smrg    time_t now;
1730bd37d32Smrg    if (fname != 0) {
1740bd37d32Smrg	Trace("datetime (%s@%d) ", fname, lnum);
1750bd37d32Smrg    }
1760bd37d32Smrg    now = time((time_t *) 0);
1770bd37d32Smrg    Trace("-- %s", ctime(&now));
1780bd37d32Smrg}
1790bd37d32Smrg
180d522f475Smrgstatic void
181d522f475SmrgformatAscii(char *dst, unsigned value)
182d522f475Smrg{
183d522f475Smrg    switch (value) {
184d522f475Smrg    case '\\':
185d522f475Smrg	sprintf(dst, "\\\\");
186d522f475Smrg	break;
187d522f475Smrg    case '\b':
188d522f475Smrg	sprintf(dst, "\\b");
189d522f475Smrg	break;
190d522f475Smrg    case '\n':
191d522f475Smrg	sprintf(dst, "\\n");
192d522f475Smrg	break;
193d522f475Smrg    case '\r':
194d522f475Smrg	sprintf(dst, "\\r");
195d522f475Smrg	break;
196d522f475Smrg    case '\t':
197d522f475Smrg	sprintf(dst, "\\t");
198d522f475Smrg	break;
199d522f475Smrg    default:
200d522f475Smrg	if (E2A(value) < 32 || (E2A(value) >= 127 && E2A(value) < 160))
201e0a2b6dfSmrg	    sprintf(dst, "\\%03o", value & 0xff);
202d522f475Smrg	else
203d522f475Smrg	    sprintf(dst, "%c", CharOf(value));
204d522f475Smrg	break;
205d522f475Smrg    }
206d522f475Smrg}
207d522f475Smrg
208d522f475Smrg#if OPT_DEC_CHRSET
209d522f475Smrg
210d522f475Smrgconst char *
211e0a2b6dfSmrgvisibleDblChrset(unsigned chrset)
212d522f475Smrg{
213d522f475Smrg    const char *result = "?";
214d522f475Smrg    switch (chrset) {
215d522f475Smrg    case CSET_SWL:
216d522f475Smrg	result = "CSET_SWL";
217d522f475Smrg	break;
218d522f475Smrg    case CSET_DHL_TOP:
219d522f475Smrg	result = "CSET_DHL_TOP";
220d522f475Smrg	break;
221d522f475Smrg    case CSET_DHL_BOT:
222d522f475Smrg	result = "CSET_DHL_BOT";
223d522f475Smrg	break;
224d522f475Smrg    case CSET_DWL:
225d522f475Smrg	result = "CSET_DWL";
226d522f475Smrg	break;
227d522f475Smrg    }
228d522f475Smrg    return result;
229d522f475Smrg}
230d522f475Smrg#endif
231d522f475Smrg
232e0a2b6dfSmrgconst char *
233e0a2b6dfSmrgvisibleScsCode(int chrset)
234e0a2b6dfSmrg{
235e0a2b6dfSmrg#define MAP(to,from) case from: result = to; break
236e0a2b6dfSmrg    const char *result = "<ERR>";
237e0a2b6dfSmrg    switch ((DECNRCM_codes) chrset) {
238e0a2b6dfSmrg	MAP("B", nrc_ASCII);
239e0a2b6dfSmrg	MAP("A", nrc_British);
240e0a2b6dfSmrg	MAP("A", nrc_British_Latin_1);
241e0a2b6dfSmrg	MAP("&4", nrc_Cyrillic);
242e0a2b6dfSmrg	MAP("0", nrc_DEC_Spec_Graphic);
243e0a2b6dfSmrg	MAP("1", nrc_DEC_Alt_Chars);
244e0a2b6dfSmrg	MAP("2", nrc_DEC_Alt_Graphics);
245e0a2b6dfSmrg	MAP("<", nrc_DEC_Supp);
246e0a2b6dfSmrg	MAP("%5", nrc_DEC_Supp_Graphic);
247e0a2b6dfSmrg	MAP(">", nrc_DEC_Technical);
248e0a2b6dfSmrg	MAP("4", nrc_Dutch);
249e0a2b6dfSmrg	MAP("5", nrc_Finnish);
250e0a2b6dfSmrg	MAP("C", nrc_Finnish2);
251e0a2b6dfSmrg	MAP("R", nrc_French);
252e0a2b6dfSmrg	MAP("f", nrc_French2);
253e0a2b6dfSmrg	MAP("Q", nrc_French_Canadian);
254e0a2b6dfSmrg	MAP("9", nrc_French_Canadian2);
255e0a2b6dfSmrg	MAP("K", nrc_German);
256e0a2b6dfSmrg	MAP("\"?", nrc_Greek);
257e0a2b6dfSmrg	MAP("F", nrc_Greek_Supp);
258e0a2b6dfSmrg	MAP("\"4", nrc_Hebrew);
259e0a2b6dfSmrg	MAP("%=", nrc_Hebrew2);
260e0a2b6dfSmrg	MAP("H", nrc_Hebrew_Supp);
261e0a2b6dfSmrg	MAP("Y", nrc_Italian);
262e0a2b6dfSmrg	MAP("M", nrc_Latin_5_Supp);
263e0a2b6dfSmrg	MAP("L", nrc_Latin_Cyrillic);
264e0a2b6dfSmrg	MAP("`", nrc_Norwegian_Danish);
265e0a2b6dfSmrg	MAP("E", nrc_Norwegian_Danish2);
266e0a2b6dfSmrg	MAP("6", nrc_Norwegian_Danish3);
267e0a2b6dfSmrg	MAP("%6", nrc_Portugese);
268e0a2b6dfSmrg	MAP("&5", nrc_Russian);
269e0a2b6dfSmrg	MAP("%3", nrc_SCS_NRCS);
270e0a2b6dfSmrg	MAP("Z", nrc_Spanish);
271e0a2b6dfSmrg	MAP("7", nrc_Swedish);
272e0a2b6dfSmrg	MAP("H", nrc_Swedish2);
273e0a2b6dfSmrg	MAP("=", nrc_Swiss);
274e0a2b6dfSmrg	MAP("%0", nrc_Turkish);
275e0a2b6dfSmrg	MAP("%2", nrc_Turkish2);
276e0a2b6dfSmrg	MAP("<UNK>", nrc_Unknown);
277e0a2b6dfSmrg    }
278e0a2b6dfSmrg#undef MAP
279e0a2b6dfSmrg    return result;
280e0a2b6dfSmrg}
281e0a2b6dfSmrg
2822e4f8982Smrgconst char *
283e0a2b6dfSmrgvisibleChars(const Char *buf, unsigned len)
284d522f475Smrg{
285d522f475Smrg    static char *result;
286d522f475Smrg    static unsigned used;
287d522f475Smrg
288956cc18dSsnj    if (buf != 0) {
289956cc18dSsnj	unsigned limit = ((len + 1) * 8) + 1;
290956cc18dSsnj
291956cc18dSsnj	if (limit > used) {
292956cc18dSsnj	    used = limit;
293956cc18dSsnj	    result = XtRealloc(result, used);
294956cc18dSsnj	}
29520d2c4d2Smrg	if (result != 0) {
2962e4f8982Smrg	    char *dst = result;
29720d2c4d2Smrg	    *dst = '\0';
29820d2c4d2Smrg	    while (len--) {
29920d2c4d2Smrg		unsigned value = *buf++;
30020d2c4d2Smrg		formatAscii(dst, value);
30120d2c4d2Smrg		dst += strlen(dst);
30220d2c4d2Smrg	    }
303956cc18dSsnj	}
304956cc18dSsnj    } else if (result != 0) {
305956cc18dSsnj	free(result);
306956cc18dSsnj	result = 0;
307956cc18dSsnj	used = 0;
308d522f475Smrg    }
30901037d57Smrg    return NonNull(result);
310956cc18dSsnj}
311956cc18dSsnj
3122e4f8982Smrgconst char *
31301037d57SmrgvisibleIChars(const IChar *buf, unsigned len)
314956cc18dSsnj{
315956cc18dSsnj    static char *result;
316956cc18dSsnj    static unsigned used;
317956cc18dSsnj
318956cc18dSsnj    if (buf != 0) {
319956cc18dSsnj	unsigned limit = ((len + 1) * 8) + 1;
320956cc18dSsnj
321956cc18dSsnj	if (limit > used) {
322956cc18dSsnj	    used = limit;
323956cc18dSsnj	    result = XtRealloc(result, used);
324d522f475Smrg	}
32520d2c4d2Smrg	if (result != 0) {
3262e4f8982Smrg	    char *dst = result;
32720d2c4d2Smrg	    *dst = '\0';
32820d2c4d2Smrg	    while (len--) {
32920d2c4d2Smrg		unsigned value = *buf++;
330956cc18dSsnj#if OPT_WIDE_CHARS
33120d2c4d2Smrg		if (value > 255)
33220d2c4d2Smrg		    sprintf(dst, "\\u+%04X", value);
33320d2c4d2Smrg		else
334d522f475Smrg#endif
33520d2c4d2Smrg		    formatAscii(dst, value);
33620d2c4d2Smrg		dst += strlen(dst);
33720d2c4d2Smrg	    }
338956cc18dSsnj	}
339956cc18dSsnj    } else if (result != 0) {
340956cc18dSsnj	free(result);
341956cc18dSsnj	result = 0;
342956cc18dSsnj	used = 0;
343d522f475Smrg    }
34401037d57Smrg    return NonNull(result);
345d522f475Smrg}
346d522f475Smrg
3472e4f8982Smrgconst char *
348e0a2b6dfSmrgvisibleUChar(unsigned chr)
349d522f475Smrg{
350e0a2b6dfSmrg    IChar buf[1];
351e0a2b6dfSmrg    buf[0] = chr;
352e0a2b6dfSmrg    return visibleIChars(buf, 1);
353d522f475Smrg}
354d522f475Smrg
355d522f475Smrgconst char *
356d522f475SmrgvisibleEventType(int type)
357d522f475Smrg{
358d522f475Smrg    const char *result = "?";
359d522f475Smrg    switch (type) {
360d522f475Smrg	CASETYPE(KeyPress);
361d522f475Smrg	CASETYPE(KeyRelease);
362d522f475Smrg	CASETYPE(ButtonPress);
363d522f475Smrg	CASETYPE(ButtonRelease);
364d522f475Smrg	CASETYPE(MotionNotify);
365d522f475Smrg	CASETYPE(EnterNotify);
366d522f475Smrg	CASETYPE(LeaveNotify);
367d522f475Smrg	CASETYPE(FocusIn);
368d522f475Smrg	CASETYPE(FocusOut);
369d522f475Smrg	CASETYPE(KeymapNotify);
370d522f475Smrg	CASETYPE(Expose);
371d522f475Smrg	CASETYPE(GraphicsExpose);
372d522f475Smrg	CASETYPE(NoExpose);
373d522f475Smrg	CASETYPE(VisibilityNotify);
374d522f475Smrg	CASETYPE(CreateNotify);
375d522f475Smrg	CASETYPE(DestroyNotify);
376d522f475Smrg	CASETYPE(UnmapNotify);
377d522f475Smrg	CASETYPE(MapNotify);
378d522f475Smrg	CASETYPE(MapRequest);
379d522f475Smrg	CASETYPE(ReparentNotify);
380d522f475Smrg	CASETYPE(ConfigureNotify);
381d522f475Smrg	CASETYPE(ConfigureRequest);
382d522f475Smrg	CASETYPE(GravityNotify);
383d522f475Smrg	CASETYPE(ResizeRequest);
384d522f475Smrg	CASETYPE(CirculateNotify);
385d522f475Smrg	CASETYPE(CirculateRequest);
386d522f475Smrg	CASETYPE(PropertyNotify);
387d522f475Smrg	CASETYPE(SelectionClear);
388d522f475Smrg	CASETYPE(SelectionRequest);
389d522f475Smrg	CASETYPE(SelectionNotify);
390d522f475Smrg	CASETYPE(ColormapNotify);
391d522f475Smrg	CASETYPE(ClientMessage);
392d522f475Smrg	CASETYPE(MappingNotify);
393d522f475Smrg    }
394d522f475Smrg    return result;
395d522f475Smrg}
396d522f475Smrg
3970bd37d32Smrgconst char *
3980bd37d32SmrgvisibleNotifyMode(int code)
3990bd37d32Smrg{
4000bd37d32Smrg    const char *result = "?";
4010bd37d32Smrg    switch (code) {
4020bd37d32Smrg	CASETYPE(NotifyNormal);
4030bd37d32Smrg	CASETYPE(NotifyGrab);
4040bd37d32Smrg	CASETYPE(NotifyUngrab);
4050bd37d32Smrg	CASETYPE(NotifyWhileGrabbed);
4060bd37d32Smrg    }
4070bd37d32Smrg    return result;
4080bd37d32Smrg}
4090bd37d32Smrg
41020d2c4d2Smrgconst char *
41120d2c4d2SmrgvisibleNotifyDetail(int code)
41220d2c4d2Smrg{
41320d2c4d2Smrg    const char *result = "?";
41420d2c4d2Smrg    switch (code) {
41520d2c4d2Smrg	CASETYPE(NotifyAncestor);
41620d2c4d2Smrg	CASETYPE(NotifyVirtual);
41720d2c4d2Smrg	CASETYPE(NotifyInferior);
41820d2c4d2Smrg	CASETYPE(NotifyNonlinear);
41920d2c4d2Smrg	CASETYPE(NotifyNonlinearVirtual);
42020d2c4d2Smrg	CASETYPE(NotifyPointer);
42120d2c4d2Smrg	CASETYPE(NotifyPointerRoot);
42220d2c4d2Smrg	CASETYPE(NotifyDetailNone);
42320d2c4d2Smrg    }
42420d2c4d2Smrg    return result;
42520d2c4d2Smrg}
42620d2c4d2Smrg
427956cc18dSsnjconst char *
428e0a2b6dfSmrgvisibleSelectionTarget(Display *d, Atom a)
429956cc18dSsnj{
430956cc18dSsnj    const char *result = "?";
431956cc18dSsnj
432956cc18dSsnj    if (a == XA_STRING) {
433956cc18dSsnj	result = "XA_STRING";
434956cc18dSsnj    } else if (a == XA_TEXT(d)) {
435956cc18dSsnj	result = "XA_TEXT()";
436956cc18dSsnj    } else if (a == XA_COMPOUND_TEXT(d)) {
437956cc18dSsnj	result = "XA_COMPOUND_TEXT()";
438956cc18dSsnj    } else if (a == XA_UTF8_STRING(d)) {
439956cc18dSsnj	result = "XA_UTF8_STRING()";
440956cc18dSsnj    } else if (a == XA_TARGETS(d)) {
441956cc18dSsnj	result = "XA_TARGETS()";
442956cc18dSsnj    }
443956cc18dSsnj
444956cc18dSsnj    return result;
445956cc18dSsnj}
446956cc18dSsnj
4472e4f8982Smrgconst char *
4482e4f8982SmrgvisibleTekparse(int code)
4492e4f8982Smrg{
4502e4f8982Smrg    static const struct {
4512e4f8982Smrg	int code;
4522e4f8982Smrg	const char *name;
4532e4f8982Smrg    } table[] = {
4542e4f8982Smrg#include "Tekparse.cin"
4552e4f8982Smrg    };
4562e4f8982Smrg    const char *result = "?";
4572e4f8982Smrg    Cardinal n;
4582e4f8982Smrg    for (n = 0; n < XtNumber(table); ++n) {
4592e4f8982Smrg	if (table[n].code == code) {
4602e4f8982Smrg	    result = table[n].name;
4612e4f8982Smrg	    break;
4622e4f8982Smrg	}
4632e4f8982Smrg    }
4642e4f8982Smrg    return result;
4652e4f8982Smrg}
4662e4f8982Smrg
4672e4f8982Smrgconst char *
4682e4f8982SmrgvisibleVTparse(int code)
4692e4f8982Smrg{
4702e4f8982Smrg    static const struct {
4712e4f8982Smrg	int code;
4722e4f8982Smrg	const char *name;
4732e4f8982Smrg    } table[] = {
4742e4f8982Smrg#include "VTparse.cin"
4752e4f8982Smrg    };
4762e4f8982Smrg    const char *result = "?";
4772e4f8982Smrg    Cardinal n;
4782e4f8982Smrg    for (n = 0; n < XtNumber(table); ++n) {
4792e4f8982Smrg	if (table[n].code == code) {
4802e4f8982Smrg	    result = table[n].name;
4812e4f8982Smrg	    break;
4822e4f8982Smrg	}
4832e4f8982Smrg    }
4842e4f8982Smrg    return result;
4852e4f8982Smrg}
4862e4f8982Smrg
487d522f475Smrgconst char *
488d522f475SmrgvisibleXError(int code)
489d522f475Smrg{
490d522f475Smrg    static char temp[80];
491d522f475Smrg    const char *result = "?";
492d522f475Smrg    switch (code) {
493d522f475Smrg	CASETYPE(Success);
494d522f475Smrg	CASETYPE(BadRequest);
495d522f475Smrg	CASETYPE(BadValue);
496d522f475Smrg	CASETYPE(BadWindow);
497d522f475Smrg	CASETYPE(BadPixmap);
498d522f475Smrg	CASETYPE(BadAtom);
499d522f475Smrg	CASETYPE(BadCursor);
500d522f475Smrg	CASETYPE(BadFont);
501d522f475Smrg	CASETYPE(BadMatch);
502d522f475Smrg	CASETYPE(BadDrawable);
503d522f475Smrg	CASETYPE(BadAccess);
504d522f475Smrg	CASETYPE(BadAlloc);
505d522f475Smrg	CASETYPE(BadColor);
506d522f475Smrg	CASETYPE(BadGC);
507d522f475Smrg	CASETYPE(BadIDChoice);
508d522f475Smrg	CASETYPE(BadName);
509d522f475Smrg	CASETYPE(BadLength);
510d522f475Smrg	CASETYPE(BadImplementation);
511d522f475Smrg    default:
512d522f475Smrg	sprintf(temp, "%d", code);
513d522f475Smrg	result = temp;
514d522f475Smrg	break;
515d522f475Smrg    }
516d522f475Smrg    return result;
517d522f475Smrg}
518d522f475Smrg
519d522f475Smrg#if OPT_TRACE_FLAGS
520d522f475Smrg#define isScrnFlag(flag) ((flag) == LINEWRAPPED)
521d522f475Smrg
522d522f475Smrgstatic char *
523e0a2b6dfSmrgScrnText(LineData *ld)
524d522f475Smrg{
525956cc18dSsnj    return visibleIChars(ld->charData, ld->lineSize);
526d522f475Smrg}
527d522f475Smrg
528956cc18dSsnj#define SHOW_BAD_LINE(name, ld) \
529956cc18dSsnj	Trace("OOPS " #name " bad row\n")
530d522f475Smrg
531d522f475Smrg#define SHOW_SCRN_FLAG(name,code) \
532956cc18dSsnj	Trace(#name " %s:%s\n", \
533d522f475Smrg	      code ? "*" : "", \
534956cc18dSsnj	      ScrnText(ld))
535d522f475Smrg
536d522f475Smrgvoid
537e0a2b6dfSmrgLineClrFlag(LineData *ld, int flag)
538d522f475Smrg{
539956cc18dSsnj    if (ld == 0) {
540956cc18dSsnj	SHOW_BAD_LINE(LineClrFlag, ld);
541d522f475Smrg	assert(0);
542d522f475Smrg    } else if (isScrnFlag(flag)) {
543956cc18dSsnj	SHOW_SCRN_FLAG(LineClrFlag, 0);
544d522f475Smrg    }
545d522f475Smrg
546956cc18dSsnj    LineFlags(ld) &= ~flag;
547d522f475Smrg}
548d522f475Smrg
549d522f475Smrgvoid
550e0a2b6dfSmrgLineSetFlag(LineData *ld, int flag)
551d522f475Smrg{
552956cc18dSsnj    if (ld == 0) {
553956cc18dSsnj	SHOW_BAD_LINE(LineSetFlag, ld);
554d522f475Smrg	assert(0);
555d522f475Smrg    } else if (isScrnFlag(flag)) {
556956cc18dSsnj	SHOW_SCRN_FLAG(LineSetFlag, 1);
557d522f475Smrg    }
558d522f475Smrg
559956cc18dSsnj    LineFlags(ld) |= flag;
560d522f475Smrg}
561d522f475Smrg
562d522f475Smrgint
563956cc18dSsnjLineTstFlag(LineData ld, int flag)
564d522f475Smrg{
565d522f475Smrg    int code = 0;
566956cc18dSsnj    if (ld == 0) {
567956cc18dSsnj	SHOW_BAD_LINE(LineTstFlag, ld);
568d522f475Smrg    } else {
569956cc18dSsnj	code = LineFlags(ld);
570956cc18dSsnj
571956cc18dSsnj	if (isScrnFlag(flag)) {
572956cc18dSsnj	    SHOW_SCRN_FLAG(LineTstFlag, code);
573d522f475Smrg	}
574d522f475Smrg    }
575d522f475Smrg    return code;
576d522f475Smrg}
577d522f475Smrg#endif /* OPT_TRACE_FLAGS */
578d522f475Smrg
5790bd37d32Smrg/*
5800bd37d32Smrg * Trace the normal or alternate screen, showing color values up to 16, e.g.,
5810bd37d32Smrg * for debugging with vttest.
5820bd37d32Smrg */
5830bd37d32Smrgvoid
5840bd37d32SmrgTraceScreen(XtermWidget xw, int whichBuf)
5850bd37d32Smrg{
5860bd37d32Smrg    TScreen *screen = TScreenOf(xw);
5870bd37d32Smrg
5880bd37d32Smrg    if (screen->editBuf_index[whichBuf]) {
5892e4f8982Smrg	int row;
5902e4f8982Smrg
5910bd37d32Smrg	TRACE(("TraceScreen %d:\n", whichBuf));
5920bd37d32Smrg	for (row = 0; row <= screen->max_row; ++row) {
5930bd37d32Smrg	    LineData *ld = getLineData(screen, row);
5942e4f8982Smrg
5950bd37d32Smrg	    TRACE((" %3d:", row));
5960bd37d32Smrg	    if (ld != 0) {
5972e4f8982Smrg		int col;
5982e4f8982Smrg
5990bd37d32Smrg		for (col = 0; col < ld->lineSize; ++col) {
6000bd37d32Smrg		    int ch = (int) ld->charData[col];
6010bd37d32Smrg		    if (ch < ' ')
6020bd37d32Smrg			ch = ' ';
6030bd37d32Smrg		    if (ch >= 127)
6040bd37d32Smrg			ch = '#';
6050bd37d32Smrg		    TRACE(("%c", ch));
6060bd37d32Smrg		}
6070bd37d32Smrg		TRACE((":\n"));
6080bd37d32Smrg
6090bd37d32Smrg		TRACE(("  xx:"));
6100bd37d32Smrg		for (col = 0; col < ld->lineSize; ++col) {
6110bd37d32Smrg		    unsigned attrs = ld->attribs[col];
6120bd37d32Smrg		    char ch;
6130bd37d32Smrg		    if (attrs & PROTECTED) {
6140bd37d32Smrg			ch = '*';
6150bd37d32Smrg		    } else if (attrs & BLINK) {
6160bd37d32Smrg			ch = 'B';
6170bd37d32Smrg		    } else if (attrs & CHARDRAWN) {
6180bd37d32Smrg			ch = '+';
6190bd37d32Smrg		    } else {
6200bd37d32Smrg			ch = ' ';
6210bd37d32Smrg		    }
6220bd37d32Smrg		    TRACE(("%c", ch));
6230bd37d32Smrg		}
6240bd37d32Smrg		TRACE((":\n"));
6250bd37d32Smrg
6260bd37d32Smrg#if 0
6270bd37d32Smrg		TRACE(("  fg:"));
6280bd37d32Smrg		for (col = 0; col < ld->lineSize; ++col) {
6290bd37d32Smrg		    unsigned fg = extract_fg(xw, ld->color[col], ld->attribs[col]);
6300bd37d32Smrg		    if (fg > 15)
6310bd37d32Smrg			fg = 15;
6320bd37d32Smrg		    TRACE(("%1x", fg));
6330bd37d32Smrg		}
6340bd37d32Smrg		TRACE((":\n"));
6350bd37d32Smrg
6360bd37d32Smrg		TRACE(("  bg:"));
6370bd37d32Smrg		for (col = 0; col < ld->lineSize; ++col) {
6380bd37d32Smrg		    unsigned bg = extract_bg(xw, ld->color[col], ld->attribs[col]);
6390bd37d32Smrg		    if (bg > 15)
6400bd37d32Smrg			bg = 15;
6410bd37d32Smrg		    TRACE(("%1x", bg));
6420bd37d32Smrg		}
6430bd37d32Smrg		TRACE((":\n"));
6440bd37d32Smrg#endif
6450bd37d32Smrg	    } else {
6460bd37d32Smrg		TRACE(("null lineData\n"));
6470bd37d32Smrg	    }
6480bd37d32Smrg	}
6490bd37d32Smrg    } else {
6500bd37d32Smrg	TRACE(("TraceScreen %d is nil\n", whichBuf));
6510bd37d32Smrg    }
6520bd37d32Smrg}
6530bd37d32Smrg
65420d2c4d2Smrgvoid
65501037d57SmrgTraceFocus(Widget w, XEvent *ev)
65620d2c4d2Smrg{
65720d2c4d2Smrg    TRACE(("trace_focus event type %d:%s\n",
65820d2c4d2Smrg	   ev->type, visibleEventType(ev->type)));
65920d2c4d2Smrg    switch (ev->type) {
66020d2c4d2Smrg    case FocusIn:
66120d2c4d2Smrg    case FocusOut:
66220d2c4d2Smrg	{
66320d2c4d2Smrg	    XFocusChangeEvent *event = (XFocusChangeEvent *) ev;
66420d2c4d2Smrg	    TRACE(("\tdetail: %s\n", visibleNotifyDetail(event->detail)));
6650bd37d32Smrg	    TRACE(("\tmode:   %s\n", visibleNotifyMode(event->mode)));
66620d2c4d2Smrg	    TRACE(("\twindow: %#lx\n", event->window));
66720d2c4d2Smrg	}
66820d2c4d2Smrg	break;
66920d2c4d2Smrg    case EnterNotify:
67020d2c4d2Smrg    case LeaveNotify:
67120d2c4d2Smrg	{
67220d2c4d2Smrg	    XCrossingEvent *event = (XCrossingEvent *) ev;
67320d2c4d2Smrg	    TRACE(("\tdetail:    %s\n", visibleNotifyDetail(event->detail)));
6740bd37d32Smrg	    TRACE(("\tmode:      %s\n", visibleNotifyMode(event->mode)));
67520d2c4d2Smrg	    TRACE(("\twindow:    %#lx\n", event->window));
676e39b573cSmrg	    TRACE(("\tfocus:     %d\n", event->focus));
67720d2c4d2Smrg	    TRACE(("\troot:      %#lx\n", event->root));
67820d2c4d2Smrg	    TRACE(("\tsubwindow: %#lx\n", event->subwindow));
67920d2c4d2Smrg	}
68020d2c4d2Smrg	break;
68120d2c4d2Smrg    }
68220d2c4d2Smrg    while (w != 0) {
68320d2c4d2Smrg	TRACE(("w %p -> %#lx\n", (void *) w, XtWindow(w)));
68420d2c4d2Smrg	w = XtParent(w);
68520d2c4d2Smrg    }
68620d2c4d2Smrg}
68720d2c4d2Smrg
688d522f475Smrgvoid
689d522f475SmrgTraceSizeHints(XSizeHints * hints)
690d522f475Smrg{
691d522f475Smrg    TRACE(("size hints:\n"));
692d522f475Smrg    if (hints->flags & (USPosition | PPosition))
693d522f475Smrg	TRACE(("   position   %d,%d%s%s\n", hints->y, hints->x,
6942e4f8982Smrg	       (hints->flags & USPosition) ? " user" : "",
6952e4f8982Smrg	       (hints->flags & PPosition) ? " prog" : ""));
696d522f475Smrg    if (hints->flags & (USSize | PSize))
697d522f475Smrg	TRACE(("   size       %d,%d%s%s\n", hints->height, hints->width,
6982e4f8982Smrg	       (hints->flags & USSize) ? " user" : "",
6992e4f8982Smrg	       (hints->flags & PSize) ? " prog" : ""));
700d522f475Smrg    if (hints->flags & PMinSize)
701d522f475Smrg	TRACE(("   min        %d,%d\n", hints->min_height, hints->min_width));
702d522f475Smrg    if (hints->flags & PMaxSize)
703d522f475Smrg	TRACE(("   max        %d,%d\n", hints->max_height, hints->max_width));
704d522f475Smrg    if (hints->flags & PResizeInc)
705d522f475Smrg	TRACE(("   inc        %d,%d\n", hints->height_inc, hints->width_inc));
7062eaa94a1Schristos    else
7072eaa94a1Schristos	TRACE(("   inc        NONE!\n"));
708d522f475Smrg    if (hints->flags & PAspect)
709d522f475Smrg	TRACE(("   min aspect %d/%d\n", hints->min_aspect.y, hints->min_aspect.y));
710d522f475Smrg    if (hints->flags & PAspect)
711d522f475Smrg	TRACE(("   max aspect %d/%d\n", hints->max_aspect.y, hints->max_aspect.y));
712d522f475Smrg    if (hints->flags & PBaseSize)
713d522f475Smrg	TRACE(("   base       %d,%d\n", hints->base_height, hints->base_width));
714d522f475Smrg    if (hints->flags & PWinGravity)
715d522f475Smrg	TRACE(("   gravity    %d\n", hints->win_gravity));
716d522f475Smrg}
717d522f475Smrg
7180bd37d32Smrgstatic void
7190bd37d32SmrgTraceEventMask(const char *tag, long mask)
7200bd37d32Smrg{
7210bd37d32Smrg#define DATA(name) { name##Mask, #name }
7220bd37d32Smrg    /* *INDENT-OFF* */
7230bd37d32Smrg    static struct {
7240bd37d32Smrg	long mask;
7250bd37d32Smrg	const char *name;
7260bd37d32Smrg    } table[] = {
7270bd37d32Smrg	DATA(KeyPress),
7280bd37d32Smrg	DATA(KeyRelease),
7290bd37d32Smrg	DATA(ButtonPress),
7300bd37d32Smrg	DATA(ButtonRelease),
7310bd37d32Smrg	DATA(EnterWindow),
7320bd37d32Smrg	DATA(LeaveWindow),
7330bd37d32Smrg	DATA(PointerMotion),
7340bd37d32Smrg	DATA(PointerMotionHint),
7350bd37d32Smrg	DATA(Button1Motion),
7360bd37d32Smrg	DATA(Button2Motion),
7370bd37d32Smrg	DATA(Button3Motion),
7380bd37d32Smrg	DATA(Button4Motion),
7390bd37d32Smrg	DATA(Button5Motion),
7400bd37d32Smrg	DATA(ButtonMotion),
7410bd37d32Smrg	DATA(KeymapState),
7420bd37d32Smrg	DATA(Exposure),
7430bd37d32Smrg	DATA(VisibilityChange),
7440bd37d32Smrg	DATA(StructureNotify),
7450bd37d32Smrg	DATA(ResizeRedirect),
7460bd37d32Smrg	DATA(SubstructureNotify),
7470bd37d32Smrg	DATA(SubstructureRedirect),
7480bd37d32Smrg	DATA(FocusChange),
7490bd37d32Smrg	DATA(PropertyChange),
7500bd37d32Smrg	DATA(ColormapChange),
7510bd37d32Smrg	DATA(OwnerGrabButton),
7520bd37d32Smrg    };
7530bd37d32Smrg#undef DATA
7540bd37d32Smrg    Cardinal n;
7550bd37d32Smrg    /* *INDENT-ON* */
7560bd37d32Smrg
7570bd37d32Smrg    for (n = 0; n < XtNumber(table); ++n) {
7580bd37d32Smrg	if (table[n].mask & mask) {
7590bd37d32Smrg	    TRACE(("%s %s\n", tag, table[n].name));
7600bd37d32Smrg	}
7610bd37d32Smrg    }
7620bd37d32Smrg}
7630bd37d32Smrg
7640bd37d32Smrgvoid
7650bd37d32SmrgTraceWindowAttributes(XWindowAttributes * attrs)
7660bd37d32Smrg{
7670bd37d32Smrg    TRACE(("window attributes:\n"));
7680bd37d32Smrg    TRACE(("   position     %d,%d\n", attrs->y, attrs->x));
7690bd37d32Smrg    TRACE(("   size         %dx%d\n", attrs->height, attrs->width));
7700bd37d32Smrg    TRACE(("   border       %d\n", attrs->border_width));
7710bd37d32Smrg    TRACE(("   depth        %d\n", attrs->depth));
7720bd37d32Smrg    TRACE(("   bit_gravity  %d\n", attrs->bit_gravity));
7730bd37d32Smrg    TRACE(("   win_gravity  %d\n", attrs->win_gravity));
7740bd37d32Smrg    TRACE(("   root         %#lx\n", (long) attrs->root));
7750bd37d32Smrg    TRACE(("   class        %s\n", ((attrs->class == InputOutput)
7760bd37d32Smrg				    ? "InputOutput"
7770bd37d32Smrg				    : ((attrs->class == InputOnly)
7780bd37d32Smrg				       ? "InputOnly"
7790bd37d32Smrg				       : "unknown"))));
7800bd37d32Smrg    TRACE(("   map_state    %s\n", ((attrs->map_state == IsUnmapped)
7810bd37d32Smrg				    ? "IsUnmapped"
7820bd37d32Smrg				    : ((attrs->map_state == IsUnviewable)
7830bd37d32Smrg				       ? "IsUnviewable"
7840bd37d32Smrg				       : ((attrs->map_state == IsViewable)
7850bd37d32Smrg					  ? "IsViewable"
7860bd37d32Smrg					  : "unknown")))));
7870bd37d32Smrg    TRACE(("   all_events\n"));
7880bd37d32Smrg    TraceEventMask("        ", attrs->all_event_masks);
7890bd37d32Smrg    TRACE(("   your_events\n"));
7900bd37d32Smrg    TraceEventMask("        ", attrs->your_event_mask);
7910bd37d32Smrg    TRACE(("   no_propagate\n"));
7920bd37d32Smrg    TraceEventMask("        ", attrs->do_not_propagate_mask);
7930bd37d32Smrg}
7940bd37d32Smrg
795d522f475Smrgvoid
796d522f475SmrgTraceWMSizeHints(XtermWidget xw)
797d522f475Smrg{
798d522f475Smrg    XSizeHints sizehints = xw->hints;
799d522f475Smrg
800d522f475Smrg    getXtermSizeHints(xw);
801d522f475Smrg    TraceSizeHints(&xw->hints);
802d522f475Smrg    xw->hints = sizehints;
803d522f475Smrg}
804d522f475Smrg
805d522f475Smrg/*
806d522f475Smrg * Some calls to XGetAtom() will fail, and we don't want to stop.  So we use
807d522f475Smrg * our own error-handler.
808d522f475Smrg */
809a1f3da82Smrg/* ARGSUSED */
810d522f475Smrgstatic int
81101037d57Smrgno_error(Display *dpy GCC_UNUSED, XErrorEvent *event GCC_UNUSED)
812d522f475Smrg{
813d522f475Smrg    return 1;
814d522f475Smrg}
815d522f475Smrg
8160bd37d32Smrgconst char *
8170bd37d32SmrgModifierName(unsigned modifier)
8180bd37d32Smrg{
8190bd37d32Smrg    const char *s = "";
8200bd37d32Smrg    if (modifier & ShiftMask)
8210bd37d32Smrg	s = " Shift";
8220bd37d32Smrg    else if (modifier & LockMask)
8230bd37d32Smrg	s = " Lock";
8240bd37d32Smrg    else if (modifier & ControlMask)
8250bd37d32Smrg	s = " Control";
8260bd37d32Smrg    else if (modifier & Mod1Mask)
8270bd37d32Smrg	s = " Mod1";
8280bd37d32Smrg    else if (modifier & Mod2Mask)
8290bd37d32Smrg	s = " Mod2";
8300bd37d32Smrg    else if (modifier & Mod3Mask)
8310bd37d32Smrg	s = " Mod3";
8320bd37d32Smrg    else if (modifier & Mod4Mask)
8330bd37d32Smrg	s = " Mod4";
8340bd37d32Smrg    else if (modifier & Mod5Mask)
8350bd37d32Smrg	s = " Mod5";
8360bd37d32Smrg    return s;
8370bd37d32Smrg}
8380bd37d32Smrg
839d522f475Smrgvoid
840d522f475SmrgTraceTranslations(const char *name, Widget w)
841d522f475Smrg{
842d522f475Smrg    String result;
843d522f475Smrg    XErrorHandler save = XSetErrorHandler(no_error);
844d522f475Smrg    XtTranslations xlations;
845d522f475Smrg    Widget xcelerat;
846d522f475Smrg
84720d2c4d2Smrg    TRACE(("TraceTranslations for %s (widget %#lx) {{\n", name, (long) w));
848d522f475Smrg    if (w) {
849d522f475Smrg	XtVaGetValues(w,
850d522f475Smrg		      XtNtranslations, &xlations,
851d522f475Smrg		      XtNaccelerators, &xcelerat,
852d522f475Smrg		      (XtPointer) 0);
853d522f475Smrg	TRACE(("... xlations %#08lx\n", (long) xlations));
854d522f475Smrg	TRACE(("... xcelerat %#08lx\n", (long) xcelerat));
855d522f475Smrg	result = _XtPrintXlations(w, xlations, xcelerat, True);
85620d2c4d2Smrg	TRACE(("%s\n", NonNull(result)));
857d522f475Smrg	if (result)
85820d2c4d2Smrg	    XFree((char *) result);
859d522f475Smrg    } else {
860d522f475Smrg	TRACE(("none (widget is null)\n"));
861d522f475Smrg    }
86220d2c4d2Smrg    TRACE(("}}\n"));
863d522f475Smrg    XSetErrorHandler(save);
864d522f475Smrg}
865d522f475Smrg
8660bd37d32SmrgXtGeometryResult
8672eaa94a1SchristosTraceResizeRequest(const char *fn, int ln, Widget w,
868e39b573cSmrg		   unsigned reqwide,
869e39b573cSmrg		   unsigned reqhigh,
870e0a2b6dfSmrg		   Dimension *gotwide,
871e0a2b6dfSmrg		   Dimension *gothigh)
8722eaa94a1Schristos{
8730bd37d32Smrg    XtGeometryResult rc;
8742eaa94a1Schristos
875e39b573cSmrg    TRACE(("%s@%d ResizeRequest %ux%u\n", fn, ln, reqhigh, reqwide));
8760bd37d32Smrg    rc = XtMakeResizeRequest((Widget) w,
8770bd37d32Smrg			     (Dimension) reqwide,
8780bd37d32Smrg			     (Dimension) reqhigh,
8790bd37d32Smrg			     gotwide, gothigh);
8802eaa94a1Schristos    TRACE(("... ResizeRequest -> "));
8812eaa94a1Schristos    if (gothigh && gotwide)
8822eaa94a1Schristos	TRACE(("%dx%d ", *gothigh, *gotwide));
8832eaa94a1Schristos    TRACE(("(%d)\n", rc));
8842eaa94a1Schristos    return rc;
8852eaa94a1Schristos}
8862eaa94a1Schristos
887d522f475Smrg#define XRES_S(name) Trace(#name " = %s\n", NonNull(resp->name))
88801037d57Smrg#define XRES_B(name) Trace(#name " = %s\n", MtoS(resp->name))
889d522f475Smrg#define XRES_I(name) Trace(#name " = %d\n", resp->name)
890d522f475Smrg
891d522f475Smrgvoid
892d522f475SmrgTraceXtermResources(void)
893d522f475Smrg{
894d522f475Smrg    XTERM_RESOURCE *resp = &resource;
895d522f475Smrg
896d522f475Smrg    Trace("XTERM_RESOURCE settings:\n");
897d522f475Smrg    XRES_S(icon_geometry);
898d522f475Smrg    XRES_S(title);
8990bd37d32Smrg    XRES_S(icon_hint);
900d522f475Smrg    XRES_S(icon_name);
901d522f475Smrg    XRES_S(term_name);
902d522f475Smrg    XRES_S(tty_modes);
903e39b573cSmrg    XRES_I(minBufSize);
904e39b573cSmrg    XRES_I(maxBufSize);
905d522f475Smrg    XRES_B(hold_screen);
906d522f475Smrg    XRES_B(utmpInhibit);
907d522f475Smrg    XRES_B(utmpDisplayId);
908d522f475Smrg    XRES_B(messages);
909e39b573cSmrg    XRES_S(menuLocale);
910e39b573cSmrg    XRES_S(omitTranslation);
911e39b573cSmrg    XRES_S(keyboardType);
912e39b573cSmrg#if OPT_PRINT_ON_EXIT
913e39b573cSmrg    XRES_I(printModeNow);
914e39b573cSmrg    XRES_I(printModeOnXError);
915e39b573cSmrg    XRES_I(printOptsNow);
916e39b573cSmrg    XRES_I(printOptsOnXError);
917e39b573cSmrg    XRES_S(printFileNow);
918e39b573cSmrg    XRES_S(printFileOnXError);
919e39b573cSmrg#endif
920d522f475Smrg#if OPT_SUNPC_KBD
921d522f475Smrg    XRES_B(sunKeyboard);
922d522f475Smrg#endif
923d522f475Smrg#if OPT_HP_FUNC_KEYS
924d522f475Smrg    XRES_B(hpFunctionKeys);
925d522f475Smrg#endif
926d522f475Smrg#if OPT_SCO_FUNC_KEYS
927d522f475Smrg    XRES_B(scoFunctionKeys);
928d522f475Smrg#endif
929d522f475Smrg#if OPT_SUN_FUNC_KEYS
930d522f475Smrg    XRES_B(sunFunctionKeys);
931d522f475Smrg#endif
932d522f475Smrg#if OPT_INITIAL_ERASE
933d522f475Smrg    XRES_B(ptyInitialErase);
934d522f475Smrg    XRES_B(backarrow_is_erase);
935d522f475Smrg#endif
936d522f475Smrg    XRES_B(useInsertMode);
937d522f475Smrg#if OPT_ZICONBEEP
938d522f475Smrg    XRES_I(zIconBeep);
9390bd37d32Smrg    XRES_S(zIconFormat);
940d522f475Smrg#endif
941d522f475Smrg#if OPT_PTY_HANDSHAKE
942d522f475Smrg    XRES_B(wait_for_map);
943d522f475Smrg    XRES_B(ptyHandshake);
944d522f475Smrg    XRES_B(ptySttySize);
945d522f475Smrg#endif
946e0a2b6dfSmrg#if OPT_REPORT_COLORS
947e0a2b6dfSmrg    XRES_B(reportColors);
948e0a2b6dfSmrg#endif
949e0a2b6dfSmrg#if OPT_REPORT_FONTS
950e0a2b6dfSmrg    XRES_B(reportFonts);
951e0a2b6dfSmrg#endif
952d522f475Smrg#if OPT_SAME_NAME
953d522f475Smrg    XRES_B(sameName);
954d522f475Smrg#endif
955d522f475Smrg#if OPT_SESSION_MGT
956d522f475Smrg    XRES_B(sessionMgt);
957d522f475Smrg#endif
958a1f3da82Smrg#if OPT_TOOLBAR
959a1f3da82Smrg    XRES_B(toolBar);
960a1f3da82Smrg#endif
961a1f3da82Smrg#if OPT_MAXIMIZE
962a1f3da82Smrg    XRES_B(maximized);
963a1f3da82Smrg    XRES_S(fullscreen_s);
964a1f3da82Smrg#endif
965d522f475Smrg}
966d522f475Smrg
967d522f475Smrgvoid
968d522f475SmrgTraceArgv(const char *tag, char **argv)
969d522f475Smrg{
970d522f475Smrg    int n = 0;
971d522f475Smrg
972d522f475Smrg    TRACE(("%s:\n", tag));
973d522f475Smrg    while (*argv != 0) {
974d522f475Smrg	TRACE(("  %d:%s\n", n++, *argv++));
975d522f475Smrg    }
976d522f475Smrg}
977d522f475Smrg
978d522f475Smrgstatic char *
97920d2c4d2Smrgparse_option(char *dst, String src, int first)
980d522f475Smrg{
981d522f475Smrg    char *s;
982d522f475Smrg
983a1f3da82Smrg    if (!strncmp(src, "-/+", (size_t) 3)) {
984956cc18dSsnj	dst[0] = (char) first;
985d522f475Smrg	strcpy(dst + 1, src + 3);
986d522f475Smrg    } else {
987d522f475Smrg	strcpy(dst, src);
988d522f475Smrg    }
989d522f475Smrg    for (s = dst; *s != '\0'; s++) {
990d522f475Smrg	if (*s == '#' || *s == '%' || *s == 'S') {
991d522f475Smrg	    s[1] = '\0';
992d522f475Smrg	} else if (*s == ' ') {
993d522f475Smrg	    *s = '\0';
994d522f475Smrg	    break;
995d522f475Smrg	}
996d522f475Smrg    }
997d522f475Smrg    return dst;
998d522f475Smrg}
999d522f475Smrg
1000d522f475Smrgstatic Bool
1001d522f475Smrgsame_option(OptionHelp * opt, XrmOptionDescRec * res)
1002d522f475Smrg{
1003d522f475Smrg    char temp[BUFSIZ];
1004d522f475Smrg    return !strcmp(parse_option(temp, opt->opt, res->option[0]), res->option);
1005d522f475Smrg}
1006d522f475Smrg
1007d522f475Smrgstatic Bool
100820d2c4d2Smrgstandard_option(String opt)
1009d522f475Smrg{
1010d522f475Smrg    static const char *table[] =
1011d522f475Smrg    {
1012d522f475Smrg	"+rv",
1013d522f475Smrg	"+synchronous",
1014d522f475Smrg	"-background",
1015d522f475Smrg	"-bd",
1016d522f475Smrg	"-bg",
1017d522f475Smrg	"-bordercolor",
1018d522f475Smrg	"-borderwidth",
1019d522f475Smrg	"-bw",
1020d522f475Smrg	"-display",
1021d522f475Smrg	"-fg",
1022d522f475Smrg	"-fn",
1023d522f475Smrg	"-font",
1024d522f475Smrg	"-foreground",
1025d522f475Smrg	"-geometry",
1026d522f475Smrg	"-iconic",
1027d522f475Smrg	"-name",
1028d522f475Smrg	"-reverse",
1029d522f475Smrg	"-rv",
1030d522f475Smrg	"-selectionTimeout",
1031d522f475Smrg	"-synchronous",
1032d522f475Smrg	"-title",
1033d522f475Smrg	"-xnllanguage",
1034d522f475Smrg	"-xrm",
1035d522f475Smrg	"-xtsessionID",
1036d522f475Smrg    };
1037d522f475Smrg    Cardinal n;
1038d522f475Smrg    char temp[BUFSIZ];
1039d522f475Smrg
1040d522f475Smrg    opt = parse_option(temp, opt, '-');
1041d522f475Smrg    for (n = 0; n < XtNumber(table); n++) {
1042d522f475Smrg	if (!strcmp(opt, table[n]))
1043d522f475Smrg	    return True;
1044d522f475Smrg    }
1045d522f475Smrg    return False;
1046d522f475Smrg}
1047d522f475Smrg
1048d522f475Smrg/*
1049d522f475Smrg * Analyse the options/help messages for inconsistencies.
1050d522f475Smrg */
1051d522f475Smrgvoid
1052d522f475SmrgTraceOptions(OptionHelp * options, XrmOptionDescRec * resources, Cardinal res_count)
1053d522f475Smrg{
1054d522f475Smrg    OptionHelp *opt_array = sortedOpts(options, resources, res_count);
1055d522f475Smrg    size_t j, k;
1056d522f475Smrg    XrmOptionDescRec *res_array = sortedOptDescs(resources, res_count);
1057d522f475Smrg    Bool first, found;
1058d522f475Smrg
1059d522f475Smrg    TRACE(("Checking options-tables for inconsistencies:\n"));
1060d522f475Smrg
1061d522f475Smrg#if 0
1062d522f475Smrg    TRACE(("Options listed in help-message:\n"));
1063d522f475Smrg    for (j = 0; options[j].opt != 0; j++)
1064d522f475Smrg	TRACE(("%5d %-28s %s\n", j, opt_array[j].opt, opt_array[j].desc));
1065d522f475Smrg    TRACE(("Options listed in resource-table:\n"));
1066d522f475Smrg    for (j = 0; j < res_count; j++)
1067d522f475Smrg	TRACE(("%5d %-28s %s\n", j, res_array[j].option, res_array[j].specifier));
1068d522f475Smrg#endif
1069d522f475Smrg
1070d522f475Smrg    /* list all options[] not found in resources[] */
1071d522f475Smrg    for (j = 0, first = True; options[j].opt != 0; j++) {
1072d522f475Smrg	found = False;
1073d522f475Smrg	for (k = 0; k < res_count; k++) {
1074d522f475Smrg	    if (same_option(&opt_array[j], &res_array[k])) {
1075d522f475Smrg		found = True;
1076d522f475Smrg		break;
1077d522f475Smrg	    }
1078d522f475Smrg	}
1079d522f475Smrg	if (!found) {
1080d522f475Smrg	    if (first) {
1081d522f475Smrg		TRACE(("Options listed in help, not found in resource list:\n"));
1082d522f475Smrg		first = False;
1083d522f475Smrg	    }
1084d522f475Smrg	    TRACE(("  %-28s%s\n", opt_array[j].opt,
1085d522f475Smrg		   standard_option(opt_array[j].opt) ? " (standard)" : ""));
1086d522f475Smrg	}
1087d522f475Smrg    }
1088d522f475Smrg
1089d522f475Smrg    /* list all resources[] not found in options[] */
1090d522f475Smrg    for (j = 0, first = True; j < res_count; j++) {
1091d522f475Smrg	found = False;
1092d522f475Smrg	for (k = 0; options[k].opt != 0; k++) {
1093d522f475Smrg	    if (same_option(&opt_array[k], &res_array[j])) {
1094d522f475Smrg		found = True;
1095d522f475Smrg		break;
1096d522f475Smrg	    }
1097d522f475Smrg	}
1098d522f475Smrg	if (!found) {
1099d522f475Smrg	    if (first) {
1100d522f475Smrg		TRACE(("Resource list items not found in options-help:\n"));
1101d522f475Smrg		first = False;
1102d522f475Smrg	    }
1103d522f475Smrg	    TRACE(("  %s\n", res_array[j].option));
1104d522f475Smrg	}
1105d522f475Smrg    }
1106d522f475Smrg
1107d522f475Smrg    TRACE(("Resource list items that will be ignored by XtOpenApplication:\n"));
1108d522f475Smrg    for (j = 0; j < res_count; j++) {
1109d522f475Smrg	switch (res_array[j].argKind) {
1110d522f475Smrg	case XrmoptionSkipArg:
1111d522f475Smrg	    TRACE(("  %-28s {param}\n", res_array[j].option));
1112d522f475Smrg	    break;
1113d522f475Smrg	case XrmoptionSkipNArgs:
1114d522f475Smrg	    TRACE(("  %-28s {%ld params}\n", res_array[j].option, (long)
1115d522f475Smrg		   res_array[j].value));
1116d522f475Smrg	    break;
1117d522f475Smrg	case XrmoptionSkipLine:
1118d522f475Smrg	    TRACE(("  %-28s {remainder of line}\n", res_array[j].option));
1119d522f475Smrg	    break;
1120d522f475Smrg	case XrmoptionIsArg:
1121d522f475Smrg	case XrmoptionNoArg:
1122d522f475Smrg	case XrmoptionResArg:
1123d522f475Smrg	case XrmoptionSepArg:
1124d522f475Smrg	case XrmoptionStickyArg:
1125d522f475Smrg	default:
1126d522f475Smrg	    break;
1127d522f475Smrg	}
1128d522f475Smrg    }
1129d522f475Smrg}
1130a1f3da82Smrg#else
1131a1f3da82Smrgextern void empty_trace(void);
1132a1f3da82Smrgvoid
1133a1f3da82Smrgempty_trace(void)
1134a1f3da82Smrg{
1135a1f3da82Smrg}
1136a1f3da82Smrg#endif
1137