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