trace.c revision e0a2b6df
1e0a2b6dfSmrg/* $XTermId: trace.c,v 1.154 2014/03/02 12:01:26 tom Exp $ */
2d522f475Smrg
320d2c4d2Smrg/*
4e0a2b6dfSmrg * Copyright 1997-2013,2014 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>
49d522f475Smrg#include <stdio.h>
50d522f475Smrg#include <stdarg.h>
51d522f475Smrg#include <assert.h>
52d522f475Smrg
53956cc18dSsnj#include <X11/Xatom.h>
54956cc18dSsnj#include <X11/Xmu/Atoms.h>
55956cc18dSsnj
56d522f475Smrg#ifdef HAVE_X11_TRANSLATEI_H
57d522f475Smrg#include <X11/TranslateI.h>
58d522f475Smrg#else
59d522f475Smrg#ifdef __cplusplus
60d522f475Smrgextern "C" {
61d522f475Smrg#endif
62d522f475Smrg
63d522f475Smrg    extern String _XtPrintXlations(Widget w,
64d522f475Smrg				   XtTranslations xlations,
65d522f475Smrg				   Widget accelWidget,
66d522f475Smrg				   _XtBoolean includeRHS);
67d522f475Smrg#ifdef __cplusplus
68d522f475Smrg}
69d522f475Smrg#endif
70d522f475Smrg#endif
7120d2c4d2Smrgconst char *trace_who = "parent";
7220d2c4d2Smrg
7320d2c4d2Smrgstatic FILE *trace_fp;
74d522f475Smrg
75d522f475Smrgvoid
76d522f475SmrgTrace(const char *fmt,...)
77d522f475Smrg{
7820d2c4d2Smrg    static const char *trace_out;
79d522f475Smrg    va_list ap;
80d522f475Smrg
8120d2c4d2Smrg    if (trace_fp != 0
82d522f475Smrg	&& trace_who != trace_out) {
8320d2c4d2Smrg	fclose(trace_fp);
8420d2c4d2Smrg	trace_fp = 0;
85d522f475Smrg    }
86d522f475Smrg    trace_out = trace_who;
87d522f475Smrg
8820d2c4d2Smrg    if (!trace_fp) {
890bd37d32Smrg	unsigned oldmask = umask(077);
90d522f475Smrg	char name[BUFSIZ];
91d522f475Smrg#if 0				/* usually I do not want unique names */
92d522f475Smrg	int unique;
93d522f475Smrg	for (unique = 0;; ++unique) {
94d522f475Smrg	    if (unique)
95d522f475Smrg		sprintf(name, "Trace-%s.out-%d", trace_who, unique);
96d522f475Smrg	    else
97d522f475Smrg		sprintf(name, "Trace-%s.out", trace_who);
9820d2c4d2Smrg	    if ((trace_fp = fopen(name, "r")) == 0) {
99d522f475Smrg		break;
100d522f475Smrg	    }
10120d2c4d2Smrg	    fclose(trace_fp);
102d522f475Smrg	}
103d522f475Smrg#else
104d522f475Smrg	sprintf(name, "Trace-%s.out", trace_who);
105d522f475Smrg#endif
10620d2c4d2Smrg	trace_fp = fopen(name, "w");
107e0a2b6dfSmrg	/*
108e0a2b6dfSmrg	 * Try to put the trace-file in user's home-directory if the current
109e0a2b6dfSmrg	 * directory is not writable.
110e0a2b6dfSmrg	 */
111e0a2b6dfSmrg	if (trace_fp == 0) {
112e0a2b6dfSmrg	    char *home = getenv("HOME");
113e0a2b6dfSmrg	    if (home != 0) {
114e0a2b6dfSmrg		sprintf(name, "%.*s/Trace-%.8s.out",
115e0a2b6dfSmrg			(BUFSIZ - 21), home,
116e0a2b6dfSmrg			trace_who);
117e0a2b6dfSmrg		trace_fp = fopen(name, "w");
118e0a2b6dfSmrg	    }
119e0a2b6dfSmrg	}
12020d2c4d2Smrg	if (trace_fp != 0) {
12120d2c4d2Smrg	    fprintf(trace_fp, "%s\n", xtermVersion());
122d522f475Smrg	    TraceIds(NULL, 0);
123d522f475Smrg	}
1240bd37d32Smrg	if (!trace_fp) {
1250bd37d32Smrg	    xtermWarning("Cannot open \"%s\"\n", name);
1260bd37d32Smrg	    exit(EXIT_FAILURE);
1270bd37d32Smrg	}
1280bd37d32Smrg	(void) umask(oldmask);
129d522f475Smrg    }
130d522f475Smrg
131d522f475Smrg    va_start(ap, fmt);
13220d2c4d2Smrg    vfprintf(trace_fp, fmt, ap);
13320d2c4d2Smrg    (void) fflush(trace_fp);
13420d2c4d2Smrg    va_end(ap);
13520d2c4d2Smrg}
13620d2c4d2Smrg
13720d2c4d2Smrgvoid
13820d2c4d2SmrgTraceClose(void)
13920d2c4d2Smrg{
14020d2c4d2Smrg    if (trace_fp != 0) {
14120d2c4d2Smrg	(void) fclose(trace_fp);
142d522f475Smrg	(void) fflush(stdout);
143d522f475Smrg	(void) fflush(stderr);
144956cc18dSsnj	(void) visibleChars(NULL, 0);
145956cc18dSsnj	(void) visibleIChars(NULL, 0);
14620d2c4d2Smrg	trace_fp = 0;
147d522f475Smrg    }
148d522f475Smrg}
149d522f475Smrg
150d522f475Smrgvoid
151d522f475SmrgTraceIds(const char *fname, int lnum)
152d522f475Smrg{
153d522f475Smrg    Trace("process %d ", (int) getpid());
154d522f475Smrg#ifdef HAVE_UNISTD_H
155d522f475Smrg    Trace("real (%u/%u) effective (%u/%u)",
156d522f475Smrg	  (unsigned) getuid(), (unsigned) getgid(),
157d522f475Smrg	  (unsigned) geteuid(), (unsigned) getegid());
158d522f475Smrg#endif
159d522f475Smrg    if (fname != 0) {
160d522f475Smrg	Trace(" (%s@%d)\n", fname, lnum);
161d522f475Smrg    } else {
162d522f475Smrg	time_t now = time((time_t *) 0);
163d522f475Smrg	Trace("-- %s", ctime(&now));
164d522f475Smrg    }
165d522f475Smrg}
166d522f475Smrg
1670bd37d32Smrgvoid
1680bd37d32SmrgTraceTime(const char *fname, int lnum)
1690bd37d32Smrg{
1700bd37d32Smrg    time_t now;
1710bd37d32Smrg    if (fname != 0) {
1720bd37d32Smrg	Trace("datetime (%s@%d) ", fname, lnum);
1730bd37d32Smrg    }
1740bd37d32Smrg    now = time((time_t *) 0);
1750bd37d32Smrg    Trace("-- %s", ctime(&now));
1760bd37d32Smrg}
1770bd37d32Smrg
178d522f475Smrgstatic void
179d522f475SmrgformatAscii(char *dst, unsigned value)
180d522f475Smrg{
181d522f475Smrg    switch (value) {
182d522f475Smrg    case '\\':
183d522f475Smrg	sprintf(dst, "\\\\");
184d522f475Smrg	break;
185d522f475Smrg    case '\b':
186d522f475Smrg	sprintf(dst, "\\b");
187d522f475Smrg	break;
188d522f475Smrg    case '\n':
189d522f475Smrg	sprintf(dst, "\\n");
190d522f475Smrg	break;
191d522f475Smrg    case '\r':
192d522f475Smrg	sprintf(dst, "\\r");
193d522f475Smrg	break;
194d522f475Smrg    case '\t':
195d522f475Smrg	sprintf(dst, "\\t");
196d522f475Smrg	break;
197d522f475Smrg    default:
198d522f475Smrg	if (E2A(value) < 32 || (E2A(value) >= 127 && E2A(value) < 160))
199e0a2b6dfSmrg	    sprintf(dst, "\\%03o", value & 0xff);
200d522f475Smrg	else
201d522f475Smrg	    sprintf(dst, "%c", CharOf(value));
202d522f475Smrg	break;
203d522f475Smrg    }
204d522f475Smrg}
205d522f475Smrg
206d522f475Smrg#if OPT_DEC_CHRSET
207d522f475Smrg
208d522f475Smrgconst char *
209e0a2b6dfSmrgvisibleDblChrset(unsigned chrset)
210d522f475Smrg{
211d522f475Smrg    const char *result = "?";
212d522f475Smrg    switch (chrset) {
213d522f475Smrg    case CSET_SWL:
214d522f475Smrg	result = "CSET_SWL";
215d522f475Smrg	break;
216d522f475Smrg    case CSET_DHL_TOP:
217d522f475Smrg	result = "CSET_DHL_TOP";
218d522f475Smrg	break;
219d522f475Smrg    case CSET_DHL_BOT:
220d522f475Smrg	result = "CSET_DHL_BOT";
221d522f475Smrg	break;
222d522f475Smrg    case CSET_DWL:
223d522f475Smrg	result = "CSET_DWL";
224d522f475Smrg	break;
225d522f475Smrg    }
226d522f475Smrg    return result;
227d522f475Smrg}
228d522f475Smrg#endif
229d522f475Smrg
230e0a2b6dfSmrgconst char *
231e0a2b6dfSmrgvisibleScsCode(int chrset)
232e0a2b6dfSmrg{
233e0a2b6dfSmrg#define MAP(to,from) case from: result = to; break
234e0a2b6dfSmrg    const char *result = "<ERR>";
235e0a2b6dfSmrg    switch ((DECNRCM_codes) chrset) {
236e0a2b6dfSmrg	MAP("B", nrc_ASCII);
237e0a2b6dfSmrg	MAP("A", nrc_British);
238e0a2b6dfSmrg	MAP("A", nrc_British_Latin_1);
239e0a2b6dfSmrg	MAP("&4", nrc_Cyrillic);
240e0a2b6dfSmrg	MAP("0", nrc_DEC_Spec_Graphic);
241e0a2b6dfSmrg	MAP("1", nrc_DEC_Alt_Chars);
242e0a2b6dfSmrg	MAP("2", nrc_DEC_Alt_Graphics);
243e0a2b6dfSmrg	MAP("<", nrc_DEC_Supp);
244e0a2b6dfSmrg	MAP("%5", nrc_DEC_Supp_Graphic);
245e0a2b6dfSmrg	MAP(">", nrc_DEC_Technical);
246e0a2b6dfSmrg	MAP("4", nrc_Dutch);
247e0a2b6dfSmrg	MAP("5", nrc_Finnish);
248e0a2b6dfSmrg	MAP("C", nrc_Finnish2);
249e0a2b6dfSmrg	MAP("R", nrc_French);
250e0a2b6dfSmrg	MAP("f", nrc_French2);
251e0a2b6dfSmrg	MAP("Q", nrc_French_Canadian);
252e0a2b6dfSmrg	MAP("9", nrc_French_Canadian2);
253e0a2b6dfSmrg	MAP("K", nrc_German);
254e0a2b6dfSmrg	MAP("\"?", nrc_Greek);
255e0a2b6dfSmrg	MAP("F", nrc_Greek_Supp);
256e0a2b6dfSmrg	MAP("\"4", nrc_Hebrew);
257e0a2b6dfSmrg	MAP("%=", nrc_Hebrew2);
258e0a2b6dfSmrg	MAP("H", nrc_Hebrew_Supp);
259e0a2b6dfSmrg	MAP("Y", nrc_Italian);
260e0a2b6dfSmrg	MAP("M", nrc_Latin_5_Supp);
261e0a2b6dfSmrg	MAP("L", nrc_Latin_Cyrillic);
262e0a2b6dfSmrg	MAP("`", nrc_Norwegian_Danish);
263e0a2b6dfSmrg	MAP("E", nrc_Norwegian_Danish2);
264e0a2b6dfSmrg	MAP("6", nrc_Norwegian_Danish3);
265e0a2b6dfSmrg	MAP("%6", nrc_Portugese);
266e0a2b6dfSmrg	MAP("&5", nrc_Russian);
267e0a2b6dfSmrg	MAP("%3", nrc_SCS_NRCS);
268e0a2b6dfSmrg	MAP("Z", nrc_Spanish);
269e0a2b6dfSmrg	MAP("7", nrc_Swedish);
270e0a2b6dfSmrg	MAP("H", nrc_Swedish2);
271e0a2b6dfSmrg	MAP("=", nrc_Swiss);
272e0a2b6dfSmrg	MAP("%0", nrc_Turkish);
273e0a2b6dfSmrg	MAP("%2", nrc_Turkish2);
274e0a2b6dfSmrg	MAP("<UNK>", nrc_Unknown);
275e0a2b6dfSmrg    }
276e0a2b6dfSmrg#undef MAP
277e0a2b6dfSmrg    return result;
278e0a2b6dfSmrg}
279e0a2b6dfSmrg
280d522f475Smrgchar *
281e0a2b6dfSmrgvisibleChars(const Char *buf, unsigned len)
282d522f475Smrg{
283d522f475Smrg    static char *result;
284d522f475Smrg    static unsigned used;
285d522f475Smrg
286956cc18dSsnj    if (buf != 0) {
287956cc18dSsnj	unsigned limit = ((len + 1) * 8) + 1;
288956cc18dSsnj	char *dst;
289956cc18dSsnj
290956cc18dSsnj	if (limit > used) {
291956cc18dSsnj	    used = limit;
292956cc18dSsnj	    result = XtRealloc(result, used);
293956cc18dSsnj	}
29420d2c4d2Smrg	if (result != 0) {
29520d2c4d2Smrg	    dst = result;
29620d2c4d2Smrg	    *dst = '\0';
29720d2c4d2Smrg	    while (len--) {
29820d2c4d2Smrg		unsigned value = *buf++;
29920d2c4d2Smrg		formatAscii(dst, value);
30020d2c4d2Smrg		dst += strlen(dst);
30120d2c4d2Smrg	    }
302956cc18dSsnj	}
303956cc18dSsnj    } else if (result != 0) {
304956cc18dSsnj	free(result);
305956cc18dSsnj	result = 0;
306956cc18dSsnj	used = 0;
307d522f475Smrg    }
308956cc18dSsnj    return result;
309956cc18dSsnj}
310956cc18dSsnj
311956cc18dSsnjchar *
312e0a2b6dfSmrgvisibleIChars(IChar *buf, unsigned len)
313956cc18dSsnj{
314956cc18dSsnj    static char *result;
315956cc18dSsnj    static unsigned used;
316956cc18dSsnj
317956cc18dSsnj    if (buf != 0) {
318956cc18dSsnj	unsigned limit = ((len + 1) * 8) + 1;
319956cc18dSsnj	char *dst;
320956cc18dSsnj
321956cc18dSsnj	if (limit > used) {
322956cc18dSsnj	    used = limit;
323956cc18dSsnj	    result = XtRealloc(result, used);
324d522f475Smrg	}
32520d2c4d2Smrg	if (result != 0) {
32620d2c4d2Smrg	    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    }
344d522f475Smrg    return result;
345d522f475Smrg}
346d522f475Smrg
347d522f475Smrgchar *
348e0a2b6dfSmrgvisibleUChar(unsigned chr)
349d522f475Smrg{
350e0a2b6dfSmrg    IChar buf[1];
351e0a2b6dfSmrg    buf[0] = chr;
352e0a2b6dfSmrg    return visibleIChars(buf, 1);
353d522f475Smrg}
354d522f475Smrg
355a1f3da82Smrg#define CASETYPE(name) case name: result = #name; break
356d522f475Smrg
357d522f475Smrgconst char *
358d522f475SmrgvisibleKeyboardType(xtermKeyboardType type)
359d522f475Smrg{
360d522f475Smrg    const char *result = "?";
361d522f475Smrg    switch (type) {
362d522f475Smrg	CASETYPE(keyboardIsLegacy);	/* bogus vt220 codes for F1-F4, etc. */
363d522f475Smrg	CASETYPE(keyboardIsDefault);
364d522f475Smrg	CASETYPE(keyboardIsHP);
365d522f475Smrg	CASETYPE(keyboardIsSCO);
366d522f475Smrg	CASETYPE(keyboardIsSun);
367d522f475Smrg	CASETYPE(keyboardIsTermcap);
368d522f475Smrg	CASETYPE(keyboardIsVT220);
369d522f475Smrg    }
370d522f475Smrg    return result;
371d522f475Smrg}
372d522f475Smrg
373d522f475Smrgconst char *
374d522f475SmrgvisibleEventType(int type)
375d522f475Smrg{
376d522f475Smrg    const char *result = "?";
377d522f475Smrg    switch (type) {
378d522f475Smrg	CASETYPE(KeyPress);
379d522f475Smrg	CASETYPE(KeyRelease);
380d522f475Smrg	CASETYPE(ButtonPress);
381d522f475Smrg	CASETYPE(ButtonRelease);
382d522f475Smrg	CASETYPE(MotionNotify);
383d522f475Smrg	CASETYPE(EnterNotify);
384d522f475Smrg	CASETYPE(LeaveNotify);
385d522f475Smrg	CASETYPE(FocusIn);
386d522f475Smrg	CASETYPE(FocusOut);
387d522f475Smrg	CASETYPE(KeymapNotify);
388d522f475Smrg	CASETYPE(Expose);
389d522f475Smrg	CASETYPE(GraphicsExpose);
390d522f475Smrg	CASETYPE(NoExpose);
391d522f475Smrg	CASETYPE(VisibilityNotify);
392d522f475Smrg	CASETYPE(CreateNotify);
393d522f475Smrg	CASETYPE(DestroyNotify);
394d522f475Smrg	CASETYPE(UnmapNotify);
395d522f475Smrg	CASETYPE(MapNotify);
396d522f475Smrg	CASETYPE(MapRequest);
397d522f475Smrg	CASETYPE(ReparentNotify);
398d522f475Smrg	CASETYPE(ConfigureNotify);
399d522f475Smrg	CASETYPE(ConfigureRequest);
400d522f475Smrg	CASETYPE(GravityNotify);
401d522f475Smrg	CASETYPE(ResizeRequest);
402d522f475Smrg	CASETYPE(CirculateNotify);
403d522f475Smrg	CASETYPE(CirculateRequest);
404d522f475Smrg	CASETYPE(PropertyNotify);
405d522f475Smrg	CASETYPE(SelectionClear);
406d522f475Smrg	CASETYPE(SelectionRequest);
407d522f475Smrg	CASETYPE(SelectionNotify);
408d522f475Smrg	CASETYPE(ColormapNotify);
409d522f475Smrg	CASETYPE(ClientMessage);
410d522f475Smrg	CASETYPE(MappingNotify);
411d522f475Smrg    }
412d522f475Smrg    return result;
413d522f475Smrg}
414d522f475Smrg
4150bd37d32Smrgconst char *
4160bd37d32SmrgvisibleNotifyMode(int code)
4170bd37d32Smrg{
4180bd37d32Smrg    const char *result = "?";
4190bd37d32Smrg    switch (code) {
4200bd37d32Smrg	CASETYPE(NotifyNormal);
4210bd37d32Smrg	CASETYPE(NotifyGrab);
4220bd37d32Smrg	CASETYPE(NotifyUngrab);
4230bd37d32Smrg	CASETYPE(NotifyWhileGrabbed);
4240bd37d32Smrg    }
4250bd37d32Smrg    return result;
4260bd37d32Smrg}
4270bd37d32Smrg
42820d2c4d2Smrgconst char *
42920d2c4d2SmrgvisibleNotifyDetail(int code)
43020d2c4d2Smrg{
43120d2c4d2Smrg    const char *result = "?";
43220d2c4d2Smrg    switch (code) {
43320d2c4d2Smrg	CASETYPE(NotifyAncestor);
43420d2c4d2Smrg	CASETYPE(NotifyVirtual);
43520d2c4d2Smrg	CASETYPE(NotifyInferior);
43620d2c4d2Smrg	CASETYPE(NotifyNonlinear);
43720d2c4d2Smrg	CASETYPE(NotifyNonlinearVirtual);
43820d2c4d2Smrg	CASETYPE(NotifyPointer);
43920d2c4d2Smrg	CASETYPE(NotifyPointerRoot);
44020d2c4d2Smrg	CASETYPE(NotifyDetailNone);
44120d2c4d2Smrg    }
44220d2c4d2Smrg    return result;
44320d2c4d2Smrg}
44420d2c4d2Smrg
445956cc18dSsnjconst char *
446e0a2b6dfSmrgvisibleSelectionTarget(Display *d, Atom a)
447956cc18dSsnj{
448956cc18dSsnj    const char *result = "?";
449956cc18dSsnj
450956cc18dSsnj    if (a == XA_STRING) {
451956cc18dSsnj	result = "XA_STRING";
452956cc18dSsnj    } else if (a == XA_TEXT(d)) {
453956cc18dSsnj	result = "XA_TEXT()";
454956cc18dSsnj    } else if (a == XA_COMPOUND_TEXT(d)) {
455956cc18dSsnj	result = "XA_COMPOUND_TEXT()";
456956cc18dSsnj    } else if (a == XA_UTF8_STRING(d)) {
457956cc18dSsnj	result = "XA_UTF8_STRING()";
458956cc18dSsnj    } else if (a == XA_TARGETS(d)) {
459956cc18dSsnj	result = "XA_TARGETS()";
460956cc18dSsnj    }
461956cc18dSsnj
462956cc18dSsnj    return result;
463956cc18dSsnj}
464956cc18dSsnj
465d522f475Smrgconst char *
466d522f475SmrgvisibleXError(int code)
467d522f475Smrg{
468d522f475Smrg    static char temp[80];
469d522f475Smrg    const char *result = "?";
470d522f475Smrg    switch (code) {
471d522f475Smrg	CASETYPE(Success);
472d522f475Smrg	CASETYPE(BadRequest);
473d522f475Smrg	CASETYPE(BadValue);
474d522f475Smrg	CASETYPE(BadWindow);
475d522f475Smrg	CASETYPE(BadPixmap);
476d522f475Smrg	CASETYPE(BadAtom);
477d522f475Smrg	CASETYPE(BadCursor);
478d522f475Smrg	CASETYPE(BadFont);
479d522f475Smrg	CASETYPE(BadMatch);
480d522f475Smrg	CASETYPE(BadDrawable);
481d522f475Smrg	CASETYPE(BadAccess);
482d522f475Smrg	CASETYPE(BadAlloc);
483d522f475Smrg	CASETYPE(BadColor);
484d522f475Smrg	CASETYPE(BadGC);
485d522f475Smrg	CASETYPE(BadIDChoice);
486d522f475Smrg	CASETYPE(BadName);
487d522f475Smrg	CASETYPE(BadLength);
488d522f475Smrg	CASETYPE(BadImplementation);
489d522f475Smrg    default:
490d522f475Smrg	sprintf(temp, "%d", code);
491d522f475Smrg	result = temp;
492d522f475Smrg	break;
493d522f475Smrg    }
494d522f475Smrg    return result;
495d522f475Smrg}
496d522f475Smrg
497d522f475Smrg#if OPT_TRACE_FLAGS
498d522f475Smrg#define isScrnFlag(flag) ((flag) == LINEWRAPPED)
499d522f475Smrg
500d522f475Smrgstatic char *
501e0a2b6dfSmrgScrnText(LineData *ld)
502d522f475Smrg{
503956cc18dSsnj    return visibleIChars(ld->charData, ld->lineSize);
504d522f475Smrg}
505d522f475Smrg
506956cc18dSsnj#define SHOW_BAD_LINE(name, ld) \
507956cc18dSsnj	Trace("OOPS " #name " bad row\n")
508d522f475Smrg
509d522f475Smrg#define SHOW_SCRN_FLAG(name,code) \
510956cc18dSsnj	Trace(#name " %s:%s\n", \
511d522f475Smrg	      code ? "*" : "", \
512956cc18dSsnj	      ScrnText(ld))
513d522f475Smrg
514d522f475Smrgvoid
515e0a2b6dfSmrgLineClrFlag(LineData *ld, int flag)
516d522f475Smrg{
517956cc18dSsnj    if (ld == 0) {
518956cc18dSsnj	SHOW_BAD_LINE(LineClrFlag, ld);
519d522f475Smrg	assert(0);
520d522f475Smrg    } else if (isScrnFlag(flag)) {
521956cc18dSsnj	SHOW_SCRN_FLAG(LineClrFlag, 0);
522d522f475Smrg    }
523d522f475Smrg
524956cc18dSsnj    LineFlags(ld) &= ~flag;
525d522f475Smrg}
526d522f475Smrg
527d522f475Smrgvoid
528e0a2b6dfSmrgLineSetFlag(LineData *ld, int flag)
529d522f475Smrg{
530956cc18dSsnj    if (ld == 0) {
531956cc18dSsnj	SHOW_BAD_LINE(LineSetFlag, ld);
532d522f475Smrg	assert(0);
533d522f475Smrg    } else if (isScrnFlag(flag)) {
534956cc18dSsnj	SHOW_SCRN_FLAG(LineSetFlag, 1);
535d522f475Smrg    }
536d522f475Smrg
537956cc18dSsnj    LineFlags(ld) |= flag;
538d522f475Smrg}
539d522f475Smrg
540d522f475Smrgint
541956cc18dSsnjLineTstFlag(LineData ld, int flag)
542d522f475Smrg{
543d522f475Smrg    int code = 0;
544956cc18dSsnj    if (ld == 0) {
545956cc18dSsnj	SHOW_BAD_LINE(LineTstFlag, ld);
546d522f475Smrg    } else {
547956cc18dSsnj	code = LineFlags(ld);
548956cc18dSsnj
549956cc18dSsnj	if (isScrnFlag(flag)) {
550956cc18dSsnj	    SHOW_SCRN_FLAG(LineTstFlag, code);
551d522f475Smrg	}
552d522f475Smrg    }
553d522f475Smrg    return code;
554d522f475Smrg}
555d522f475Smrg#endif /* OPT_TRACE_FLAGS */
556d522f475Smrg
5570bd37d32Smrg/*
5580bd37d32Smrg * Trace the normal or alternate screen, showing color values up to 16, e.g.,
5590bd37d32Smrg * for debugging with vttest.
5600bd37d32Smrg */
5610bd37d32Smrgvoid
5620bd37d32SmrgTraceScreen(XtermWidget xw, int whichBuf)
5630bd37d32Smrg{
5640bd37d32Smrg    TScreen *screen = TScreenOf(xw);
5650bd37d32Smrg    int row, col;
5660bd37d32Smrg
5670bd37d32Smrg    if (screen->editBuf_index[whichBuf]) {
5680bd37d32Smrg	TRACE(("TraceScreen %d:\n", whichBuf));
5690bd37d32Smrg	for (row = 0; row <= screen->max_row; ++row) {
5700bd37d32Smrg	    LineData *ld = getLineData(screen, row);
5710bd37d32Smrg	    TRACE((" %3d:", row));
5720bd37d32Smrg	    if (ld != 0) {
5730bd37d32Smrg		for (col = 0; col < ld->lineSize; ++col) {
5740bd37d32Smrg		    int ch = (int) ld->charData[col];
5750bd37d32Smrg		    if (ch < ' ')
5760bd37d32Smrg			ch = ' ';
5770bd37d32Smrg		    if (ch >= 127)
5780bd37d32Smrg			ch = '#';
5790bd37d32Smrg		    TRACE(("%c", ch));
5800bd37d32Smrg		}
5810bd37d32Smrg		TRACE((":\n"));
5820bd37d32Smrg
5830bd37d32Smrg		TRACE(("  xx:"));
5840bd37d32Smrg		for (col = 0; col < ld->lineSize; ++col) {
5850bd37d32Smrg		    unsigned attrs = ld->attribs[col];
5860bd37d32Smrg		    char ch;
5870bd37d32Smrg		    if (attrs & PROTECTED) {
5880bd37d32Smrg			ch = '*';
5890bd37d32Smrg		    } else if (attrs & BLINK) {
5900bd37d32Smrg			ch = 'B';
5910bd37d32Smrg		    } else if (attrs & CHARDRAWN) {
5920bd37d32Smrg			ch = '+';
5930bd37d32Smrg		    } else {
5940bd37d32Smrg			ch = ' ';
5950bd37d32Smrg		    }
5960bd37d32Smrg		    TRACE(("%c", ch));
5970bd37d32Smrg		}
5980bd37d32Smrg		TRACE((":\n"));
5990bd37d32Smrg
6000bd37d32Smrg#if 0
6010bd37d32Smrg		TRACE(("  fg:"));
6020bd37d32Smrg		for (col = 0; col < ld->lineSize; ++col) {
6030bd37d32Smrg		    unsigned fg = extract_fg(xw, ld->color[col], ld->attribs[col]);
6040bd37d32Smrg		    if (fg > 15)
6050bd37d32Smrg			fg = 15;
6060bd37d32Smrg		    TRACE(("%1x", fg));
6070bd37d32Smrg		}
6080bd37d32Smrg		TRACE((":\n"));
6090bd37d32Smrg
6100bd37d32Smrg		TRACE(("  bg:"));
6110bd37d32Smrg		for (col = 0; col < ld->lineSize; ++col) {
6120bd37d32Smrg		    unsigned bg = extract_bg(xw, ld->color[col], ld->attribs[col]);
6130bd37d32Smrg		    if (bg > 15)
6140bd37d32Smrg			bg = 15;
6150bd37d32Smrg		    TRACE(("%1x", bg));
6160bd37d32Smrg		}
6170bd37d32Smrg		TRACE((":\n"));
6180bd37d32Smrg#endif
6190bd37d32Smrg	    } else {
6200bd37d32Smrg		TRACE(("null lineData\n"));
6210bd37d32Smrg	    }
6220bd37d32Smrg	}
6230bd37d32Smrg    } else {
6240bd37d32Smrg	TRACE(("TraceScreen %d is nil\n", whichBuf));
6250bd37d32Smrg    }
6260bd37d32Smrg}
6270bd37d32Smrg
62820d2c4d2Smrgvoid
62920d2c4d2SmrgTraceFocus(Widget w, XEvent * ev)
63020d2c4d2Smrg{
63120d2c4d2Smrg    TRACE(("trace_focus event type %d:%s\n",
63220d2c4d2Smrg	   ev->type, visibleEventType(ev->type)));
63320d2c4d2Smrg    switch (ev->type) {
63420d2c4d2Smrg    case FocusIn:
63520d2c4d2Smrg    case FocusOut:
63620d2c4d2Smrg	{
63720d2c4d2Smrg	    XFocusChangeEvent *event = (XFocusChangeEvent *) ev;
63820d2c4d2Smrg	    TRACE(("\tdetail: %s\n", visibleNotifyDetail(event->detail)));
6390bd37d32Smrg	    TRACE(("\tmode:   %s\n", visibleNotifyMode(event->mode)));
64020d2c4d2Smrg	    TRACE(("\twindow: %#lx\n", event->window));
64120d2c4d2Smrg	}
64220d2c4d2Smrg	break;
64320d2c4d2Smrg    case EnterNotify:
64420d2c4d2Smrg    case LeaveNotify:
64520d2c4d2Smrg	{
64620d2c4d2Smrg	    XCrossingEvent *event = (XCrossingEvent *) ev;
64720d2c4d2Smrg	    TRACE(("\tdetail:    %s\n", visibleNotifyDetail(event->detail)));
6480bd37d32Smrg	    TRACE(("\tmode:      %s\n", visibleNotifyMode(event->mode)));
64920d2c4d2Smrg	    TRACE(("\twindow:    %#lx\n", event->window));
650e39b573cSmrg	    TRACE(("\tfocus:     %d\n", event->focus));
65120d2c4d2Smrg	    TRACE(("\troot:      %#lx\n", event->root));
65220d2c4d2Smrg	    TRACE(("\tsubwindow: %#lx\n", event->subwindow));
65320d2c4d2Smrg	}
65420d2c4d2Smrg	break;
65520d2c4d2Smrg    }
65620d2c4d2Smrg    while (w != 0) {
65720d2c4d2Smrg	TRACE(("w %p -> %#lx\n", (void *) w, XtWindow(w)));
65820d2c4d2Smrg	w = XtParent(w);
65920d2c4d2Smrg    }
66020d2c4d2Smrg}
66120d2c4d2Smrg
662d522f475Smrgvoid
663d522f475SmrgTraceSizeHints(XSizeHints * hints)
664d522f475Smrg{
665d522f475Smrg    TRACE(("size hints:\n"));
666d522f475Smrg    if (hints->flags & (USPosition | PPosition))
667d522f475Smrg	TRACE(("   position   %d,%d%s%s\n", hints->y, hints->x,
668d522f475Smrg	       hints->flags & USPosition ? " user" : "",
669d522f475Smrg	       hints->flags & PPosition ? " prog" : ""));
670d522f475Smrg    if (hints->flags & (USSize | PSize))
671d522f475Smrg	TRACE(("   size       %d,%d%s%s\n", hints->height, hints->width,
672d522f475Smrg	       hints->flags & USSize ? " user" : "",
673d522f475Smrg	       hints->flags & PSize ? " prog" : ""));
674d522f475Smrg    if (hints->flags & PMinSize)
675d522f475Smrg	TRACE(("   min        %d,%d\n", hints->min_height, hints->min_width));
676d522f475Smrg    if (hints->flags & PMaxSize)
677d522f475Smrg	TRACE(("   max        %d,%d\n", hints->max_height, hints->max_width));
678d522f475Smrg    if (hints->flags & PResizeInc)
679d522f475Smrg	TRACE(("   inc        %d,%d\n", hints->height_inc, hints->width_inc));
6802eaa94a1Schristos    else
6812eaa94a1Schristos	TRACE(("   inc        NONE!\n"));
682d522f475Smrg    if (hints->flags & PAspect)
683d522f475Smrg	TRACE(("   min aspect %d/%d\n", hints->min_aspect.y, hints->min_aspect.y));
684d522f475Smrg    if (hints->flags & PAspect)
685d522f475Smrg	TRACE(("   max aspect %d/%d\n", hints->max_aspect.y, hints->max_aspect.y));
686d522f475Smrg    if (hints->flags & PBaseSize)
687d522f475Smrg	TRACE(("   base       %d,%d\n", hints->base_height, hints->base_width));
688d522f475Smrg    if (hints->flags & PWinGravity)
689d522f475Smrg	TRACE(("   gravity    %d\n", hints->win_gravity));
690d522f475Smrg}
691d522f475Smrg
6920bd37d32Smrgstatic void
6930bd37d32SmrgTraceEventMask(const char *tag, long mask)
6940bd37d32Smrg{
6950bd37d32Smrg#define DATA(name) { name##Mask, #name }
6960bd37d32Smrg    /* *INDENT-OFF* */
6970bd37d32Smrg    static struct {
6980bd37d32Smrg	long mask;
6990bd37d32Smrg	const char *name;
7000bd37d32Smrg    } table[] = {
7010bd37d32Smrg	DATA(KeyPress),
7020bd37d32Smrg	DATA(KeyRelease),
7030bd37d32Smrg	DATA(ButtonPress),
7040bd37d32Smrg	DATA(ButtonRelease),
7050bd37d32Smrg	DATA(EnterWindow),
7060bd37d32Smrg	DATA(LeaveWindow),
7070bd37d32Smrg	DATA(PointerMotion),
7080bd37d32Smrg	DATA(PointerMotionHint),
7090bd37d32Smrg	DATA(Button1Motion),
7100bd37d32Smrg	DATA(Button2Motion),
7110bd37d32Smrg	DATA(Button3Motion),
7120bd37d32Smrg	DATA(Button4Motion),
7130bd37d32Smrg	DATA(Button5Motion),
7140bd37d32Smrg	DATA(ButtonMotion),
7150bd37d32Smrg	DATA(KeymapState),
7160bd37d32Smrg	DATA(Exposure),
7170bd37d32Smrg	DATA(VisibilityChange),
7180bd37d32Smrg	DATA(StructureNotify),
7190bd37d32Smrg	DATA(ResizeRedirect),
7200bd37d32Smrg	DATA(SubstructureNotify),
7210bd37d32Smrg	DATA(SubstructureRedirect),
7220bd37d32Smrg	DATA(FocusChange),
7230bd37d32Smrg	DATA(PropertyChange),
7240bd37d32Smrg	DATA(ColormapChange),
7250bd37d32Smrg	DATA(OwnerGrabButton),
7260bd37d32Smrg    };
7270bd37d32Smrg#undef DATA
7280bd37d32Smrg    Cardinal n;
7290bd37d32Smrg    /* *INDENT-ON* */
7300bd37d32Smrg
7310bd37d32Smrg    for (n = 0; n < XtNumber(table); ++n) {
7320bd37d32Smrg	if (table[n].mask & mask) {
7330bd37d32Smrg	    TRACE(("%s %s\n", tag, table[n].name));
7340bd37d32Smrg	}
7350bd37d32Smrg    }
7360bd37d32Smrg}
7370bd37d32Smrg
7380bd37d32Smrgvoid
7390bd37d32SmrgTraceWindowAttributes(XWindowAttributes * attrs)
7400bd37d32Smrg{
7410bd37d32Smrg    TRACE(("window attributes:\n"));
7420bd37d32Smrg    TRACE(("   position     %d,%d\n", attrs->y, attrs->x));
7430bd37d32Smrg    TRACE(("   size         %dx%d\n", attrs->height, attrs->width));
7440bd37d32Smrg    TRACE(("   border       %d\n", attrs->border_width));
7450bd37d32Smrg    TRACE(("   depth        %d\n", attrs->depth));
7460bd37d32Smrg    TRACE(("   bit_gravity  %d\n", attrs->bit_gravity));
7470bd37d32Smrg    TRACE(("   win_gravity  %d\n", attrs->win_gravity));
7480bd37d32Smrg    TRACE(("   root         %#lx\n", (long) attrs->root));
7490bd37d32Smrg    TRACE(("   class        %s\n", ((attrs->class == InputOutput)
7500bd37d32Smrg				    ? "InputOutput"
7510bd37d32Smrg				    : ((attrs->class == InputOnly)
7520bd37d32Smrg				       ? "InputOnly"
7530bd37d32Smrg				       : "unknown"))));
7540bd37d32Smrg    TRACE(("   map_state    %s\n", ((attrs->map_state == IsUnmapped)
7550bd37d32Smrg				    ? "IsUnmapped"
7560bd37d32Smrg				    : ((attrs->map_state == IsUnviewable)
7570bd37d32Smrg				       ? "IsUnviewable"
7580bd37d32Smrg				       : ((attrs->map_state == IsViewable)
7590bd37d32Smrg					  ? "IsViewable"
7600bd37d32Smrg					  : "unknown")))));
7610bd37d32Smrg    TRACE(("   all_events\n"));
7620bd37d32Smrg    TraceEventMask("        ", attrs->all_event_masks);
7630bd37d32Smrg    TRACE(("   your_events\n"));
7640bd37d32Smrg    TraceEventMask("        ", attrs->your_event_mask);
7650bd37d32Smrg    TRACE(("   no_propagate\n"));
7660bd37d32Smrg    TraceEventMask("        ", attrs->do_not_propagate_mask);
7670bd37d32Smrg}
7680bd37d32Smrg
769d522f475Smrgvoid
770d522f475SmrgTraceWMSizeHints(XtermWidget xw)
771d522f475Smrg{
772d522f475Smrg    XSizeHints sizehints = xw->hints;
773d522f475Smrg
774d522f475Smrg    getXtermSizeHints(xw);
775d522f475Smrg    TraceSizeHints(&xw->hints);
776d522f475Smrg    xw->hints = sizehints;
777d522f475Smrg}
778d522f475Smrg
779d522f475Smrg/*
780d522f475Smrg * Some calls to XGetAtom() will fail, and we don't want to stop.  So we use
781d522f475Smrg * our own error-handler.
782d522f475Smrg */
783a1f3da82Smrg/* ARGSUSED */
784d522f475Smrgstatic int
785e0a2b6dfSmrgno_error(Display *dpy GCC_UNUSED, XErrorEvent * event GCC_UNUSED)
786d522f475Smrg{
787d522f475Smrg    return 1;
788d522f475Smrg}
789d522f475Smrg
7900bd37d32Smrgconst char *
7910bd37d32SmrgModifierName(unsigned modifier)
7920bd37d32Smrg{
7930bd37d32Smrg    const char *s = "";
7940bd37d32Smrg    if (modifier & ShiftMask)
7950bd37d32Smrg	s = " Shift";
7960bd37d32Smrg    else if (modifier & LockMask)
7970bd37d32Smrg	s = " Lock";
7980bd37d32Smrg    else if (modifier & ControlMask)
7990bd37d32Smrg	s = " Control";
8000bd37d32Smrg    else if (modifier & Mod1Mask)
8010bd37d32Smrg	s = " Mod1";
8020bd37d32Smrg    else if (modifier & Mod2Mask)
8030bd37d32Smrg	s = " Mod2";
8040bd37d32Smrg    else if (modifier & Mod3Mask)
8050bd37d32Smrg	s = " Mod3";
8060bd37d32Smrg    else if (modifier & Mod4Mask)
8070bd37d32Smrg	s = " Mod4";
8080bd37d32Smrg    else if (modifier & Mod5Mask)
8090bd37d32Smrg	s = " Mod5";
8100bd37d32Smrg    return s;
8110bd37d32Smrg}
8120bd37d32Smrg
813d522f475Smrgvoid
814d522f475SmrgTraceTranslations(const char *name, Widget w)
815d522f475Smrg{
816d522f475Smrg    String result;
817d522f475Smrg    XErrorHandler save = XSetErrorHandler(no_error);
818d522f475Smrg    XtTranslations xlations;
819d522f475Smrg    Widget xcelerat;
820d522f475Smrg
82120d2c4d2Smrg    TRACE(("TraceTranslations for %s (widget %#lx) {{\n", name, (long) w));
822d522f475Smrg    if (w) {
823d522f475Smrg	XtVaGetValues(w,
824d522f475Smrg		      XtNtranslations, &xlations,
825d522f475Smrg		      XtNaccelerators, &xcelerat,
826d522f475Smrg		      (XtPointer) 0);
827d522f475Smrg	TRACE(("... xlations %#08lx\n", (long) xlations));
828d522f475Smrg	TRACE(("... xcelerat %#08lx\n", (long) xcelerat));
829d522f475Smrg	result = _XtPrintXlations(w, xlations, xcelerat, True);
83020d2c4d2Smrg	TRACE(("%s\n", NonNull(result)));
831d522f475Smrg	if (result)
83220d2c4d2Smrg	    XFree((char *) result);
833d522f475Smrg    } else {
834d522f475Smrg	TRACE(("none (widget is null)\n"));
835d522f475Smrg    }
83620d2c4d2Smrg    TRACE(("}}\n"));
837d522f475Smrg    XSetErrorHandler(save);
838d522f475Smrg}
839d522f475Smrg
8400bd37d32SmrgXtGeometryResult
8412eaa94a1SchristosTraceResizeRequest(const char *fn, int ln, Widget w,
842e39b573cSmrg		   unsigned reqwide,
843e39b573cSmrg		   unsigned reqhigh,
844e0a2b6dfSmrg		   Dimension *gotwide,
845e0a2b6dfSmrg		   Dimension *gothigh)
8462eaa94a1Schristos{
8470bd37d32Smrg    XtGeometryResult rc;
8482eaa94a1Schristos
849e39b573cSmrg    TRACE(("%s@%d ResizeRequest %ux%u\n", fn, ln, reqhigh, reqwide));
8500bd37d32Smrg    rc = XtMakeResizeRequest((Widget) w,
8510bd37d32Smrg			     (Dimension) reqwide,
8520bd37d32Smrg			     (Dimension) reqhigh,
8530bd37d32Smrg			     gotwide, gothigh);
8542eaa94a1Schristos    TRACE(("... ResizeRequest -> "));
8552eaa94a1Schristos    if (gothigh && gotwide)
8562eaa94a1Schristos	TRACE(("%dx%d ", *gothigh, *gotwide));
8572eaa94a1Schristos    TRACE(("(%d)\n", rc));
8582eaa94a1Schristos    return rc;
8592eaa94a1Schristos}
8602eaa94a1Schristos
861d522f475Smrg#define XRES_S(name) Trace(#name " = %s\n", NonNull(resp->name))
862d522f475Smrg#define XRES_B(name) Trace(#name " = %s\n", BtoS(resp->name))
863d522f475Smrg#define XRES_I(name) Trace(#name " = %d\n", resp->name)
864d522f475Smrg
865d522f475Smrgvoid
866d522f475SmrgTraceXtermResources(void)
867d522f475Smrg{
868d522f475Smrg    XTERM_RESOURCE *resp = &resource;
869d522f475Smrg
870d522f475Smrg    Trace("XTERM_RESOURCE settings:\n");
871d522f475Smrg    XRES_S(icon_geometry);
872d522f475Smrg    XRES_S(title);
8730bd37d32Smrg    XRES_S(icon_hint);
874d522f475Smrg    XRES_S(icon_name);
875d522f475Smrg    XRES_S(term_name);
876d522f475Smrg    XRES_S(tty_modes);
877e39b573cSmrg    XRES_I(minBufSize);
878e39b573cSmrg    XRES_I(maxBufSize);
879d522f475Smrg    XRES_B(hold_screen);
880d522f475Smrg    XRES_B(utmpInhibit);
881d522f475Smrg    XRES_B(utmpDisplayId);
882d522f475Smrg    XRES_B(messages);
883e39b573cSmrg    XRES_S(menuLocale);
884e39b573cSmrg    XRES_S(omitTranslation);
885e39b573cSmrg    XRES_S(keyboardType);
886e39b573cSmrg#if OPT_PRINT_ON_EXIT
887e39b573cSmrg    XRES_I(printModeNow);
888e39b573cSmrg    XRES_I(printModeOnXError);
889e39b573cSmrg    XRES_I(printOptsNow);
890e39b573cSmrg    XRES_I(printOptsOnXError);
891e39b573cSmrg    XRES_S(printFileNow);
892e39b573cSmrg    XRES_S(printFileOnXError);
893e39b573cSmrg#endif
894d522f475Smrg#if OPT_SUNPC_KBD
895d522f475Smrg    XRES_B(sunKeyboard);
896d522f475Smrg#endif
897d522f475Smrg#if OPT_HP_FUNC_KEYS
898d522f475Smrg    XRES_B(hpFunctionKeys);
899d522f475Smrg#endif
900d522f475Smrg#if OPT_SCO_FUNC_KEYS
901d522f475Smrg    XRES_B(scoFunctionKeys);
902d522f475Smrg#endif
903d522f475Smrg#if OPT_SUN_FUNC_KEYS
904d522f475Smrg    XRES_B(sunFunctionKeys);
905d522f475Smrg#endif
906d522f475Smrg#if OPT_INITIAL_ERASE
907d522f475Smrg    XRES_B(ptyInitialErase);
908d522f475Smrg    XRES_B(backarrow_is_erase);
909d522f475Smrg#endif
910d522f475Smrg    XRES_B(useInsertMode);
911d522f475Smrg#if OPT_ZICONBEEP
912d522f475Smrg    XRES_I(zIconBeep);
9130bd37d32Smrg    XRES_S(zIconFormat);
914d522f475Smrg#endif
915d522f475Smrg#if OPT_PTY_HANDSHAKE
916d522f475Smrg    XRES_B(wait_for_map);
917d522f475Smrg    XRES_B(ptyHandshake);
918d522f475Smrg    XRES_B(ptySttySize);
919d522f475Smrg#endif
920e0a2b6dfSmrg#if OPT_REPORT_COLORS
921e0a2b6dfSmrg    XRES_B(reportColors);
922e0a2b6dfSmrg#endif
923e0a2b6dfSmrg#if OPT_REPORT_FONTS
924e0a2b6dfSmrg    XRES_B(reportFonts);
925e0a2b6dfSmrg#endif
926d522f475Smrg#if OPT_SAME_NAME
927d522f475Smrg    XRES_B(sameName);
928d522f475Smrg#endif
929d522f475Smrg#if OPT_SESSION_MGT
930d522f475Smrg    XRES_B(sessionMgt);
931d522f475Smrg#endif
932a1f3da82Smrg#if OPT_TOOLBAR
933a1f3da82Smrg    XRES_B(toolBar);
934a1f3da82Smrg#endif
935a1f3da82Smrg#if OPT_MAXIMIZE
936a1f3da82Smrg    XRES_B(maximized);
937a1f3da82Smrg    XRES_S(fullscreen_s);
938a1f3da82Smrg#endif
939d522f475Smrg}
940d522f475Smrg
941d522f475Smrgvoid
942d522f475SmrgTraceArgv(const char *tag, char **argv)
943d522f475Smrg{
944d522f475Smrg    int n = 0;
945d522f475Smrg
946d522f475Smrg    TRACE(("%s:\n", tag));
947d522f475Smrg    while (*argv != 0) {
948d522f475Smrg	TRACE(("  %d:%s\n", n++, *argv++));
949d522f475Smrg    }
950d522f475Smrg}
951d522f475Smrg
952d522f475Smrgstatic char *
95320d2c4d2Smrgparse_option(char *dst, String src, int first)
954d522f475Smrg{
955d522f475Smrg    char *s;
956d522f475Smrg
957a1f3da82Smrg    if (!strncmp(src, "-/+", (size_t) 3)) {
958956cc18dSsnj	dst[0] = (char) first;
959d522f475Smrg	strcpy(dst + 1, src + 3);
960d522f475Smrg    } else {
961d522f475Smrg	strcpy(dst, src);
962d522f475Smrg    }
963d522f475Smrg    for (s = dst; *s != '\0'; s++) {
964d522f475Smrg	if (*s == '#' || *s == '%' || *s == 'S') {
965d522f475Smrg	    s[1] = '\0';
966d522f475Smrg	} else if (*s == ' ') {
967d522f475Smrg	    *s = '\0';
968d522f475Smrg	    break;
969d522f475Smrg	}
970d522f475Smrg    }
971d522f475Smrg    return dst;
972d522f475Smrg}
973d522f475Smrg
974d522f475Smrgstatic Bool
975d522f475Smrgsame_option(OptionHelp * opt, XrmOptionDescRec * res)
976d522f475Smrg{
977d522f475Smrg    char temp[BUFSIZ];
978d522f475Smrg    return !strcmp(parse_option(temp, opt->opt, res->option[0]), res->option);
979d522f475Smrg}
980d522f475Smrg
981d522f475Smrgstatic Bool
98220d2c4d2Smrgstandard_option(String opt)
983d522f475Smrg{
984d522f475Smrg    static const char *table[] =
985d522f475Smrg    {
986d522f475Smrg	"+rv",
987d522f475Smrg	"+synchronous",
988d522f475Smrg	"-background",
989d522f475Smrg	"-bd",
990d522f475Smrg	"-bg",
991d522f475Smrg	"-bordercolor",
992d522f475Smrg	"-borderwidth",
993d522f475Smrg	"-bw",
994d522f475Smrg	"-display",
995d522f475Smrg	"-fg",
996d522f475Smrg	"-fn",
997d522f475Smrg	"-font",
998d522f475Smrg	"-foreground",
999d522f475Smrg	"-geometry",
1000d522f475Smrg	"-iconic",
1001d522f475Smrg	"-name",
1002d522f475Smrg	"-reverse",
1003d522f475Smrg	"-rv",
1004d522f475Smrg	"-selectionTimeout",
1005d522f475Smrg	"-synchronous",
1006d522f475Smrg	"-title",
1007d522f475Smrg	"-xnllanguage",
1008d522f475Smrg	"-xrm",
1009d522f475Smrg	"-xtsessionID",
1010d522f475Smrg    };
1011d522f475Smrg    Cardinal n;
1012d522f475Smrg    char temp[BUFSIZ];
1013d522f475Smrg
1014d522f475Smrg    opt = parse_option(temp, opt, '-');
1015d522f475Smrg    for (n = 0; n < XtNumber(table); n++) {
1016d522f475Smrg	if (!strcmp(opt, table[n]))
1017d522f475Smrg	    return True;
1018d522f475Smrg    }
1019d522f475Smrg    return False;
1020d522f475Smrg}
1021d522f475Smrg
1022d522f475Smrg/*
1023d522f475Smrg * Analyse the options/help messages for inconsistencies.
1024d522f475Smrg */
1025d522f475Smrgvoid
1026d522f475SmrgTraceOptions(OptionHelp * options, XrmOptionDescRec * resources, Cardinal res_count)
1027d522f475Smrg{
1028d522f475Smrg    OptionHelp *opt_array = sortedOpts(options, resources, res_count);
1029d522f475Smrg    size_t j, k;
1030d522f475Smrg    XrmOptionDescRec *res_array = sortedOptDescs(resources, res_count);
1031d522f475Smrg    Bool first, found;
1032d522f475Smrg
1033d522f475Smrg    TRACE(("Checking options-tables for inconsistencies:\n"));
1034d522f475Smrg
1035d522f475Smrg#if 0
1036d522f475Smrg    TRACE(("Options listed in help-message:\n"));
1037d522f475Smrg    for (j = 0; options[j].opt != 0; j++)
1038d522f475Smrg	TRACE(("%5d %-28s %s\n", j, opt_array[j].opt, opt_array[j].desc));
1039d522f475Smrg    TRACE(("Options listed in resource-table:\n"));
1040d522f475Smrg    for (j = 0; j < res_count; j++)
1041d522f475Smrg	TRACE(("%5d %-28s %s\n", j, res_array[j].option, res_array[j].specifier));
1042d522f475Smrg#endif
1043d522f475Smrg
1044d522f475Smrg    /* list all options[] not found in resources[] */
1045d522f475Smrg    for (j = 0, first = True; options[j].opt != 0; j++) {
1046d522f475Smrg	found = False;
1047d522f475Smrg	for (k = 0; k < res_count; k++) {
1048d522f475Smrg	    if (same_option(&opt_array[j], &res_array[k])) {
1049d522f475Smrg		found = True;
1050d522f475Smrg		break;
1051d522f475Smrg	    }
1052d522f475Smrg	}
1053d522f475Smrg	if (!found) {
1054d522f475Smrg	    if (first) {
1055d522f475Smrg		TRACE(("Options listed in help, not found in resource list:\n"));
1056d522f475Smrg		first = False;
1057d522f475Smrg	    }
1058d522f475Smrg	    TRACE(("  %-28s%s\n", opt_array[j].opt,
1059d522f475Smrg		   standard_option(opt_array[j].opt) ? " (standard)" : ""));
1060d522f475Smrg	}
1061d522f475Smrg    }
1062d522f475Smrg
1063d522f475Smrg    /* list all resources[] not found in options[] */
1064d522f475Smrg    for (j = 0, first = True; j < res_count; j++) {
1065d522f475Smrg	found = False;
1066d522f475Smrg	for (k = 0; options[k].opt != 0; k++) {
1067d522f475Smrg	    if (same_option(&opt_array[k], &res_array[j])) {
1068d522f475Smrg		found = True;
1069d522f475Smrg		break;
1070d522f475Smrg	    }
1071d522f475Smrg	}
1072d522f475Smrg	if (!found) {
1073d522f475Smrg	    if (first) {
1074d522f475Smrg		TRACE(("Resource list items not found in options-help:\n"));
1075d522f475Smrg		first = False;
1076d522f475Smrg	    }
1077d522f475Smrg	    TRACE(("  %s\n", res_array[j].option));
1078d522f475Smrg	}
1079d522f475Smrg    }
1080d522f475Smrg
1081d522f475Smrg    TRACE(("Resource list items that will be ignored by XtOpenApplication:\n"));
1082d522f475Smrg    for (j = 0; j < res_count; j++) {
1083d522f475Smrg	switch (res_array[j].argKind) {
1084d522f475Smrg	case XrmoptionSkipArg:
1085d522f475Smrg	    TRACE(("  %-28s {param}\n", res_array[j].option));
1086d522f475Smrg	    break;
1087d522f475Smrg	case XrmoptionSkipNArgs:
1088d522f475Smrg	    TRACE(("  %-28s {%ld params}\n", res_array[j].option, (long)
1089d522f475Smrg		   res_array[j].value));
1090d522f475Smrg	    break;
1091d522f475Smrg	case XrmoptionSkipLine:
1092d522f475Smrg	    TRACE(("  %-28s {remainder of line}\n", res_array[j].option));
1093d522f475Smrg	    break;
1094d522f475Smrg	case XrmoptionIsArg:
1095d522f475Smrg	case XrmoptionNoArg:
1096d522f475Smrg	case XrmoptionResArg:
1097d522f475Smrg	case XrmoptionSepArg:
1098d522f475Smrg	case XrmoptionStickyArg:
1099d522f475Smrg	default:
1100d522f475Smrg	    break;
1101d522f475Smrg	}
1102d522f475Smrg    }
1103d522f475Smrg}
1104a1f3da82Smrg#else
1105a1f3da82Smrgextern void empty_trace(void);
1106a1f3da82Smrgvoid
1107a1f3da82Smrgempty_trace(void)
1108a1f3da82Smrg{
1109a1f3da82Smrg}
1110a1f3da82Smrg#endif
1111