15104ee6eSmrg/* $XTermId: trace.c,v 1.244 2024/12/01 20:23:01 tom Exp $ */
2d522f475Smrg
320d2c4d2Smrg/*
45104ee6eSmrg * Copyright 1997-2023,2024 by Thomas E. Dickey
50bd37d32Smrg *
620d2c4d2Smrg *                         All Rights Reserved
70bd37d32Smrg *
820d2c4d2Smrg * Permission is hereby granted, free of charge, to any person obtaining a
920d2c4d2Smrg * copy of this software and associated documentation files (the
1020d2c4d2Smrg * "Software"), to deal in the Software without restriction, including
1120d2c4d2Smrg * without limitation the rights to use, copy, modify, merge, publish,
1220d2c4d2Smrg * distribute, sublicense, and/or sell copies of the Software, and to
1320d2c4d2Smrg * permit persons to whom the Software is furnished to do so, subject to
1420d2c4d2Smrg * the following conditions:
1520d2c4d2Smrg *
1620d2c4d2Smrg * The above copyright notice and this permission notice shall be included
1720d2c4d2Smrg * in all copies or substantial portions of the Software.
1820d2c4d2Smrg *
1920d2c4d2Smrg * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
2020d2c4d2Smrg * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
2120d2c4d2Smrg * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
2220d2c4d2Smrg * IN NO EVENT SHALL THE ABOVE LISTED COPYRIGHT HOLDER(S) BE LIABLE FOR ANY
2320d2c4d2Smrg * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
2420d2c4d2Smrg * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
2520d2c4d2Smrg * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
2620d2c4d2Smrg *
2720d2c4d2Smrg * Except as contained in this notice, the name(s) of the above copyright
2820d2c4d2Smrg * holders shall not be used in advertising or otherwise to promote the
2920d2c4d2Smrg * sale, use or other dealings in this Software without prior written
3020d2c4d2Smrg * authorization.
3120d2c4d2Smrg */
32d522f475Smrg
33d522f475Smrg/*
34d522f475Smrg * debugging support via TRACE macro.
35d522f475Smrg */
36d522f475Smrg
37d522f475Smrg#include <xterm.h>		/* for definition of GCC_UNUSED */
38f2e35a3aSmrg#include <xstrings.h>
39f2e35a3aSmrg#include <wcwidth.h>
400bd37d32Smrg#include <version.h>
41a1f3da82Smrg
42a1f3da82Smrg#if OPT_TRACE
43a1f3da82Smrg
44d522f475Smrg#include <data.h>
45d522f475Smrg#include <trace.h>
46d522f475Smrg
47d522f475Smrg#include <time.h>
48d522f475Smrg#include <stdlib.h>
49d522f475Smrg#include <unistd.h>
50d522f475Smrg#include <sys/types.h>
51894e0ac8Smrg#include <sys/stat.h>
52d522f475Smrg#include <stdio.h>
53d522f475Smrg#include <assert.h>
54d522f475Smrg
55956cc18dSsnj#include <X11/Xatom.h>
56956cc18dSsnj#include <X11/Xmu/Atoms.h>
57f2e35a3aSmrg#include <X11/Xmu/Error.h>
58956cc18dSsnj
59d522f475Smrg#ifdef HAVE_X11_TRANSLATEI_H
602e4f8982Smrg#include <X11/ConvertI.h>
61d522f475Smrg#include <X11/TranslateI.h>
62d522f475Smrg#else
63d522f475Smrg#ifdef __cplusplus
64d522f475Smrgextern "C" {
65d522f475Smrg#endif
66d522f475Smrg
67d522f475Smrg    extern String _XtPrintXlations(Widget w,
68d522f475Smrg				   XtTranslations xlations,
69d522f475Smrg				   Widget accelWidget,
70d522f475Smrg				   _XtBoolean includeRHS);
71d522f475Smrg#ifdef __cplusplus
72d522f475Smrg}
73d522f475Smrg#endif
74d522f475Smrg#endif
7520d2c4d2Smrgconst char *trace_who = "parent";
7620d2c4d2Smrg
7720d2c4d2Smrgstatic FILE *trace_fp;
78d522f475Smrg
79f2e35a3aSmrgstatic FILE *
80f2e35a3aSmrgTraceOpen(void)
81d522f475Smrg{
8220d2c4d2Smrg    static const char *trace_out;
83d522f475Smrg
845104ee6eSmrg    if (trace_fp != NULL
85d522f475Smrg	&& trace_who != trace_out) {
8620d2c4d2Smrg	fclose(trace_fp);
875104ee6eSmrg	trace_fp = NULL;
88d522f475Smrg    }
89d522f475Smrg    trace_out = trace_who;
90d522f475Smrg
9120d2c4d2Smrg    if (!trace_fp) {
92f2e35a3aSmrg	static char dot[] = ".";
93913cc679Smrg	mode_t oldmask = umask(077);
944419d26bSmrg	char *home;
954419d26bSmrg	char *name;
96f2e35a3aSmrg	/*
97f2e35a3aSmrg	 * Put the trace-file in user's home-directory if the current
98f2e35a3aSmrg	 * directory is not writable.
99f2e35a3aSmrg	 */
1004419d26bSmrg	home = ((access(dot, R_OK | W_OK) == 0)
1014419d26bSmrg		? dot
1024419d26bSmrg		: getenv("HOME"));
1034419d26bSmrg	if (home != NULL &&
1044419d26bSmrg	    (name = malloc(strlen(home) + strlen(trace_who) + 50)) != NULL) {
105f2e35a3aSmrg#if OPT_TRACE_UNIQUE		/* usually I do not want unique names */
1064419d26bSmrg	    int unique;
1074419d26bSmrg	    for (unique = 0;; ++unique) {
1084419d26bSmrg		if (unique)
1094419d26bSmrg		    sprintf(name, "%s/Trace-%s.out-%d", home, trace_who, unique);
1104419d26bSmrg		else
1114419d26bSmrg		    sprintf(name, "%s/Trace-%s.out", home, trace_who);
1124419d26bSmrg		if ((trace_fp = fopen(name, "r")) == 0) {
1134419d26bSmrg		    break;
1144419d26bSmrg		}
1154419d26bSmrg		fclose(trace_fp);
116d522f475Smrg	    }
117d522f475Smrg#else
1184419d26bSmrg	    sprintf(name, "%s/Trace-%s.out", home, trace_who);
119d522f475Smrg#endif
1204419d26bSmrg	    trace_fp = fopen(name, "w");
1215104ee6eSmrg	    if (trace_fp != NULL) {
1224419d26bSmrg		fprintf(trace_fp, "%s\n", xtermVersion());
1234419d26bSmrg		TraceIds(NULL, 0);
1244419d26bSmrg	    }
1254419d26bSmrg	    if (!trace_fp) {
1264419d26bSmrg		xtermWarning("Cannot open \"%s\"\n", name);
1274419d26bSmrg		exit(EXIT_FAILURE);
1284419d26bSmrg	    }
1294419d26bSmrg	    (void) umask(oldmask);
1304419d26bSmrg	    free(name);
1310bd37d32Smrg	}
132d522f475Smrg    }
133f2e35a3aSmrg    return trace_fp;
134f2e35a3aSmrg}
135f2e35a3aSmrg
136f2e35a3aSmrgvoid
137f2e35a3aSmrgTrace(const char *fmt, ...)
138f2e35a3aSmrg{
139f2e35a3aSmrg    va_list ap;
140f2e35a3aSmrg    FILE *fp = TraceOpen();
141d522f475Smrg
142d522f475Smrg    va_start(ap, fmt);
143f2e35a3aSmrg    vfprintf(fp, fmt, ap);
144f2e35a3aSmrg    (void) fflush(fp);
14520d2c4d2Smrg    va_end(ap);
14620d2c4d2Smrg}
14720d2c4d2Smrg
148f2e35a3aSmrgvoid
149f2e35a3aSmrgTraceVA(const char *fmt, va_list ap)
150f2e35a3aSmrg{
151f2e35a3aSmrg    FILE *fp = TraceOpen();
152f2e35a3aSmrg
153f2e35a3aSmrg    vfprintf(fp, fmt, ap);
154f2e35a3aSmrg    (void) fflush(fp);
155f2e35a3aSmrg}
156f2e35a3aSmrg
15720d2c4d2Smrgvoid
15820d2c4d2SmrgTraceClose(void)
15920d2c4d2Smrg{
1605104ee6eSmrg    if (trace_fp != NULL) {
16120d2c4d2Smrg	(void) fclose(trace_fp);
162d522f475Smrg	(void) fflush(stdout);
163d522f475Smrg	(void) fflush(stderr);
164956cc18dSsnj	(void) visibleChars(NULL, 0);
165956cc18dSsnj	(void) visibleIChars(NULL, 0);
1665104ee6eSmrg	trace_fp = NULL;
167d522f475Smrg    }
168d522f475Smrg}
169d522f475Smrg
170f2e35a3aSmrgvoid
171f2e35a3aSmrgTraceXError(Display *d, XErrorEvent *ev)
172f2e35a3aSmrg{
173f2e35a3aSmrg    FILE *fp = TraceOpen();
174f2e35a3aSmrg    (void) XmuPrintDefaultErrorMessage(d, ev, fp);
175f2e35a3aSmrg    (void) fflush(fp);
176f2e35a3aSmrg}
177f2e35a3aSmrg
178d522f475Smrgvoid
179d522f475SmrgTraceIds(const char *fname, int lnum)
180d522f475Smrg{
181d522f475Smrg    Trace("process %d ", (int) getpid());
182d522f475Smrg#ifdef HAVE_UNISTD_H
183d522f475Smrg    Trace("real (%u/%u) effective (%u/%u)",
184d522f475Smrg	  (unsigned) getuid(), (unsigned) getgid(),
185d522f475Smrg	  (unsigned) geteuid(), (unsigned) getegid());
186d522f475Smrg#endif
1875104ee6eSmrg    if (fname != NULL) {
188d522f475Smrg	Trace(" (%s@%d)\n", fname, lnum);
189d522f475Smrg    } else {
190d522f475Smrg	time_t now = time((time_t *) 0);
191d522f475Smrg	Trace("-- %s", ctime(&now));
192d522f475Smrg    }
193d522f475Smrg}
194d522f475Smrg
1950bd37d32Smrgvoid
1960bd37d32SmrgTraceTime(const char *fname, int lnum)
1970bd37d32Smrg{
1980bd37d32Smrg    time_t now;
1995104ee6eSmrg    if (fname != NULL) {
2000bd37d32Smrg	Trace("datetime (%s@%d) ", fname, lnum);
2010bd37d32Smrg    }
2020bd37d32Smrg    now = time((time_t *) 0);
2030bd37d32Smrg    Trace("-- %s", ctime(&now));
2040bd37d32Smrg}
2050bd37d32Smrg
206d522f475Smrgstatic void
207d522f475SmrgformatAscii(char *dst, unsigned value)
208d522f475Smrg{
209d522f475Smrg    switch (value) {
210d522f475Smrg    case '\\':
211d522f475Smrg	sprintf(dst, "\\\\");
212d522f475Smrg	break;
213d522f475Smrg    case '\b':
214d522f475Smrg	sprintf(dst, "\\b");
215d522f475Smrg	break;
216d522f475Smrg    case '\n':
217d522f475Smrg	sprintf(dst, "\\n");
218d522f475Smrg	break;
219d522f475Smrg    case '\r':
220d522f475Smrg	sprintf(dst, "\\r");
221d522f475Smrg	break;
222d522f475Smrg    case '\t':
223d522f475Smrg	sprintf(dst, "\\t");
224d522f475Smrg	break;
225d522f475Smrg    default:
2265104ee6eSmrg	if (value < 32 || (value >= 127 && value < 160))
227e0a2b6dfSmrg	    sprintf(dst, "\\%03o", value & 0xff);
228d522f475Smrg	else
229d522f475Smrg	    sprintf(dst, "%c", CharOf(value));
230d522f475Smrg	break;
231d522f475Smrg    }
232d522f475Smrg}
233d522f475Smrg
234d522f475Smrg#if OPT_DEC_CHRSET
235d522f475Smrg
236d522f475Smrgconst char *
237e0a2b6dfSmrgvisibleDblChrset(unsigned chrset)
238d522f475Smrg{
239d522f475Smrg    const char *result = "?";
240d522f475Smrg    switch (chrset) {
241d522f475Smrg    case CSET_SWL:
242d522f475Smrg	result = "CSET_SWL";
243d522f475Smrg	break;
244d522f475Smrg    case CSET_DHL_TOP:
245d522f475Smrg	result = "CSET_DHL_TOP";
246d522f475Smrg	break;
247d522f475Smrg    case CSET_DHL_BOT:
248d522f475Smrg	result = "CSET_DHL_BOT";
249d522f475Smrg	break;
250d522f475Smrg    case CSET_DWL:
251d522f475Smrg	result = "CSET_DWL";
252d522f475Smrg	break;
253d522f475Smrg    }
254d522f475Smrg    return result;
255d522f475Smrg}
256d522f475Smrg#endif
257d522f475Smrg
258e0a2b6dfSmrgconst char *
259f2e35a3aSmrgvisibleScsCode(DECNRCM_codes chrset)
260e0a2b6dfSmrg{
261f2e35a3aSmrg#define MAP(to,from) case from: result = to ":" #from; break
262e0a2b6dfSmrg    const char *result = "<ERR>";
263e0a2b6dfSmrg    switch ((DECNRCM_codes) chrset) {
264e0a2b6dfSmrg	MAP("B", nrc_ASCII);
265e0a2b6dfSmrg	MAP("A", nrc_British);
266e0a2b6dfSmrg	MAP("A", nrc_British_Latin_1);
267f2e35a3aSmrg	MAP("&4", nrc_DEC_Cyrillic);
268e0a2b6dfSmrg	MAP("0", nrc_DEC_Spec_Graphic);
269e0a2b6dfSmrg	MAP("1", nrc_DEC_Alt_Chars);
270e0a2b6dfSmrg	MAP("2", nrc_DEC_Alt_Graphics);
271e0a2b6dfSmrg	MAP("<", nrc_DEC_Supp);
27204b94745Smrg	MAP("<", nrc_DEC_UPSS);
273e0a2b6dfSmrg	MAP("%5", nrc_DEC_Supp_Graphic);
274e0a2b6dfSmrg	MAP(">", nrc_DEC_Technical);
275e0a2b6dfSmrg	MAP("4", nrc_Dutch);
276e0a2b6dfSmrg	MAP("5", nrc_Finnish);
277e0a2b6dfSmrg	MAP("C", nrc_Finnish2);
278e0a2b6dfSmrg	MAP("R", nrc_French);
279e0a2b6dfSmrg	MAP("f", nrc_French2);
280e0a2b6dfSmrg	MAP("Q", nrc_French_Canadian);
281e0a2b6dfSmrg	MAP("9", nrc_French_Canadian2);
282e0a2b6dfSmrg	MAP("K", nrc_German);
283f2e35a3aSmrg	MAP("\"?", nrc_DEC_Greek_Supp);
284f2e35a3aSmrg	MAP("\">", nrc_Greek);
285f2e35a3aSmrg	MAP("F", nrc_ISO_Greek_Supp);
286f2e35a3aSmrg	MAP("\"4", nrc_DEC_Hebrew_Supp);
287f2e35a3aSmrg	MAP("%=", nrc_Hebrew);
288f2e35a3aSmrg	MAP("H", nrc_ISO_Hebrew_Supp);
289e0a2b6dfSmrg	MAP("Y", nrc_Italian);
290f2e35a3aSmrg	MAP("A", nrc_ISO_Latin_1_Supp);
291f2e35a3aSmrg	MAP("B", nrc_ISO_Latin_2_Supp);
2925104ee6eSmrg	MAP("I", nrc_JIS_Katakana);
2935104ee6eSmrg	MAP("J", nrc_JIS_Roman);
294f2e35a3aSmrg	MAP("M", nrc_ISO_Latin_5_Supp);
295f2e35a3aSmrg	MAP("L", nrc_ISO_Latin_Cyrillic);
296e0a2b6dfSmrg	MAP("`", nrc_Norwegian_Danish);
297e0a2b6dfSmrg	MAP("E", nrc_Norwegian_Danish2);
298e0a2b6dfSmrg	MAP("6", nrc_Norwegian_Danish3);
299e0a2b6dfSmrg	MAP("%6", nrc_Portugese);
300e0a2b6dfSmrg	MAP("&5", nrc_Russian);
301e0a2b6dfSmrg	MAP("%3", nrc_SCS_NRCS);
302e0a2b6dfSmrg	MAP("Z", nrc_Spanish);
303e0a2b6dfSmrg	MAP("7", nrc_Swedish);
304e0a2b6dfSmrg	MAP("H", nrc_Swedish2);
305e0a2b6dfSmrg	MAP("=", nrc_Swiss);
306f2e35a3aSmrg	MAP("%2", nrc_Turkish);
307f2e35a3aSmrg	MAP("%0", nrc_DEC_Turkish_Supp);
308e0a2b6dfSmrg	MAP("<UNK>", nrc_Unknown);
309e0a2b6dfSmrg    }
310e0a2b6dfSmrg#undef MAP
311e0a2b6dfSmrg    return result;
312e0a2b6dfSmrg}
313e0a2b6dfSmrg
3142e4f8982Smrgconst char *
3155307cd1aSmrgvisibleChars(const Char *buf, size_t len)
316d522f475Smrg{
317d522f475Smrg    static char *result;
3185307cd1aSmrg    static size_t used;
319d522f475Smrg
3205104ee6eSmrg    if (buf != NULL) {
3215307cd1aSmrg	size_t limit = ((len + 1) * 8) + 1;
322956cc18dSsnj
323956cc18dSsnj	if (limit > used) {
324956cc18dSsnj	    used = limit;
3255307cd1aSmrg	    result = realloc(result, used);
326956cc18dSsnj	}
3275104ee6eSmrg	if (result != NULL) {
3282e4f8982Smrg	    char *dst = result;
32920d2c4d2Smrg	    *dst = '\0';
33020d2c4d2Smrg	    while (len--) {
33120d2c4d2Smrg		unsigned value = *buf++;
33220d2c4d2Smrg		formatAscii(dst, value);
33320d2c4d2Smrg		dst += strlen(dst);
33420d2c4d2Smrg	    }
335956cc18dSsnj	}
336f2e35a3aSmrg    } else {
337f2e35a3aSmrg	FreeAndNull(result);
338956cc18dSsnj	used = 0;
339d522f475Smrg    }
34001037d57Smrg    return NonNull(result);
341956cc18dSsnj}
342956cc18dSsnj
343f2e35a3aSmrgconst char *
344f2e35a3aSmrgvisibleEventMode(EventMode value)
345f2e35a3aSmrg{
346f2e35a3aSmrg    const char *result;
347f2e35a3aSmrg    switch (value) {
348f2e35a3aSmrg    case NORMAL:
349f2e35a3aSmrg	result = "NORMAL";
350f2e35a3aSmrg	break;
351f2e35a3aSmrg    case LEFTEXTENSION:
352f2e35a3aSmrg	result = "LEFTEXTENSION";
353f2e35a3aSmrg	break;
354f2e35a3aSmrg    case RIGHTEXTENSION:
355f2e35a3aSmrg	result = "RIGHTEXTENSION";
356f2e35a3aSmrg	break;
357f2e35a3aSmrg    default:
358f2e35a3aSmrg	result = "?";
359f2e35a3aSmrg	break;
360f2e35a3aSmrg    }
361f2e35a3aSmrg    return result;
362f2e35a3aSmrg}
363f2e35a3aSmrg
3642e4f8982Smrgconst char *
3655307cd1aSmrgvisibleIChars(const IChar *buf, size_t len)
366956cc18dSsnj{
367956cc18dSsnj    static char *result;
3685307cd1aSmrg    static size_t used;
369956cc18dSsnj
3705104ee6eSmrg    if (buf != NULL) {
3715307cd1aSmrg	size_t limit = ((len + 1) * 12) + 1;
372956cc18dSsnj
373956cc18dSsnj	if (limit > used) {
374956cc18dSsnj	    used = limit;
3755307cd1aSmrg	    result = realloc(result, used);
376d522f475Smrg	}
3775104ee6eSmrg	if (result != NULL) {
3782e4f8982Smrg	    char *dst = result;
37920d2c4d2Smrg	    *dst = '\0';
38020d2c4d2Smrg	    while (len--) {
38120d2c4d2Smrg		unsigned value = *buf++;
382956cc18dSsnj#if OPT_WIDE_CHARS
38320d2c4d2Smrg		if (value > 255)
384f2e35a3aSmrg		    sprintf(dst, "\\U+%04X", value);
38520d2c4d2Smrg		else
386d522f475Smrg#endif
38720d2c4d2Smrg		    formatAscii(dst, value);
38820d2c4d2Smrg		dst += strlen(dst);
38920d2c4d2Smrg	    }
390956cc18dSsnj	}
391f2e35a3aSmrg    } else {
392f2e35a3aSmrg	FreeAndNull(result);
393956cc18dSsnj	used = 0;
394d522f475Smrg    }
39501037d57Smrg    return NonNull(result);
396d522f475Smrg}
397d522f475Smrg
3982e4f8982Smrgconst char *
399e0a2b6dfSmrgvisibleUChar(unsigned chr)
400d522f475Smrg{
401e0a2b6dfSmrg    IChar buf[1];
402f2e35a3aSmrg    buf[0] = (IChar) chr;
403e0a2b6dfSmrg    return visibleIChars(buf, 1);
404d522f475Smrg}
405d522f475Smrg
406d522f475Smrgconst char *
407d522f475SmrgvisibleEventType(int type)
408d522f475Smrg{
409d522f475Smrg    const char *result = "?";
410d522f475Smrg    switch (type) {
411d522f475Smrg	CASETYPE(KeyPress);
412d522f475Smrg	CASETYPE(KeyRelease);
413d522f475Smrg	CASETYPE(ButtonPress);
414d522f475Smrg	CASETYPE(ButtonRelease);
415d522f475Smrg	CASETYPE(MotionNotify);
416d522f475Smrg	CASETYPE(EnterNotify);
417d522f475Smrg	CASETYPE(LeaveNotify);
418d522f475Smrg	CASETYPE(FocusIn);
419d522f475Smrg	CASETYPE(FocusOut);
420d522f475Smrg	CASETYPE(KeymapNotify);
421d522f475Smrg	CASETYPE(Expose);
422d522f475Smrg	CASETYPE(GraphicsExpose);
423d522f475Smrg	CASETYPE(NoExpose);
424d522f475Smrg	CASETYPE(VisibilityNotify);
425d522f475Smrg	CASETYPE(CreateNotify);
426d522f475Smrg	CASETYPE(DestroyNotify);
427d522f475Smrg	CASETYPE(UnmapNotify);
428d522f475Smrg	CASETYPE(MapNotify);
429d522f475Smrg	CASETYPE(MapRequest);
430d522f475Smrg	CASETYPE(ReparentNotify);
431d522f475Smrg	CASETYPE(ConfigureNotify);
432d522f475Smrg	CASETYPE(ConfigureRequest);
433d522f475Smrg	CASETYPE(GravityNotify);
434d522f475Smrg	CASETYPE(ResizeRequest);
435d522f475Smrg	CASETYPE(CirculateNotify);
436d522f475Smrg	CASETYPE(CirculateRequest);
437d522f475Smrg	CASETYPE(PropertyNotify);
438d522f475Smrg	CASETYPE(SelectionClear);
439d522f475Smrg	CASETYPE(SelectionRequest);
440d522f475Smrg	CASETYPE(SelectionNotify);
441d522f475Smrg	CASETYPE(ColormapNotify);
442d522f475Smrg	CASETYPE(ClientMessage);
443d522f475Smrg	CASETYPE(MappingNotify);
444d522f475Smrg    }
445d522f475Smrg    return result;
446d522f475Smrg}
447d522f475Smrg
448f2e35a3aSmrgconst char *
449f2e35a3aSmrgvisibleMappingMode(int code)
450f2e35a3aSmrg{
451f2e35a3aSmrg    const char *result = "?";
452f2e35a3aSmrg    switch (code) {
453f2e35a3aSmrg	CASETYPE(MappingModifier);
454f2e35a3aSmrg	CASETYPE(MappingKeyboard);
455f2e35a3aSmrg	CASETYPE(MappingPointer);
456f2e35a3aSmrg    }
457f2e35a3aSmrg    return result;
458f2e35a3aSmrg}
459f2e35a3aSmrg
4600bd37d32Smrgconst char *
4610bd37d32SmrgvisibleNotifyMode(int code)
4620bd37d32Smrg{
4630bd37d32Smrg    const char *result = "?";
4640bd37d32Smrg    switch (code) {
4650bd37d32Smrg	CASETYPE(NotifyNormal);
4660bd37d32Smrg	CASETYPE(NotifyGrab);
4670bd37d32Smrg	CASETYPE(NotifyUngrab);
4680bd37d32Smrg	CASETYPE(NotifyWhileGrabbed);
4690bd37d32Smrg    }
4700bd37d32Smrg    return result;
4710bd37d32Smrg}
4720bd37d32Smrg
47320d2c4d2Smrgconst char *
47420d2c4d2SmrgvisibleNotifyDetail(int code)
47520d2c4d2Smrg{
47620d2c4d2Smrg    const char *result = "?";
47720d2c4d2Smrg    switch (code) {
47820d2c4d2Smrg	CASETYPE(NotifyAncestor);
47920d2c4d2Smrg	CASETYPE(NotifyVirtual);
48020d2c4d2Smrg	CASETYPE(NotifyInferior);
48120d2c4d2Smrg	CASETYPE(NotifyNonlinear);
48220d2c4d2Smrg	CASETYPE(NotifyNonlinearVirtual);
48320d2c4d2Smrg	CASETYPE(NotifyPointer);
48420d2c4d2Smrg	CASETYPE(NotifyPointerRoot);
48520d2c4d2Smrg	CASETYPE(NotifyDetailNone);
48620d2c4d2Smrg    }
48720d2c4d2Smrg    return result;
48820d2c4d2Smrg}
48920d2c4d2Smrg
490956cc18dSsnjconst char *
491e0a2b6dfSmrgvisibleSelectionTarget(Display *d, Atom a)
492956cc18dSsnj{
493956cc18dSsnj    const char *result = "?";
494956cc18dSsnj
495956cc18dSsnj    if (a == XA_STRING) {
496956cc18dSsnj	result = "XA_STRING";
497956cc18dSsnj    } else if (a == XA_TEXT(d)) {
498956cc18dSsnj	result = "XA_TEXT()";
499956cc18dSsnj    } else if (a == XA_COMPOUND_TEXT(d)) {
500956cc18dSsnj	result = "XA_COMPOUND_TEXT()";
501956cc18dSsnj    } else if (a == XA_UTF8_STRING(d)) {
502956cc18dSsnj	result = "XA_UTF8_STRING()";
503956cc18dSsnj    } else if (a == XA_TARGETS(d)) {
504956cc18dSsnj	result = "XA_TARGETS()";
505956cc18dSsnj    }
506956cc18dSsnj
507956cc18dSsnj    return result;
508956cc18dSsnj}
509956cc18dSsnj
5105307cd1aSmrg#if OPT_TEK4014
5112e4f8982Smrgconst char *
5122e4f8982SmrgvisibleTekparse(int code)
5132e4f8982Smrg{
5142e4f8982Smrg    static const struct {
5152e4f8982Smrg	int code;
5162e4f8982Smrg	const char *name;
5172e4f8982Smrg    } table[] = {
5182e4f8982Smrg#include "Tekparse.cin"
5192e4f8982Smrg    };
5202e4f8982Smrg    const char *result = "?";
5212e4f8982Smrg    Cardinal n;
5222e4f8982Smrg    for (n = 0; n < XtNumber(table); ++n) {
5232e4f8982Smrg	if (table[n].code == code) {
5242e4f8982Smrg	    result = table[n].name;
5252e4f8982Smrg	    break;
5262e4f8982Smrg	}
5272e4f8982Smrg    }
5282e4f8982Smrg    return result;
5292e4f8982Smrg}
5305307cd1aSmrg#endif
5312e4f8982Smrg
5322e4f8982Smrgconst char *
5332e4f8982SmrgvisibleVTparse(int code)
5342e4f8982Smrg{
5352e4f8982Smrg    static const struct {
5362e4f8982Smrg	int code;
5372e4f8982Smrg	const char *name;
5382e4f8982Smrg    } table[] = {
5392e4f8982Smrg#include "VTparse.cin"
5402e4f8982Smrg    };
5412e4f8982Smrg    const char *result = "?";
5422e4f8982Smrg    Cardinal n;
5432e4f8982Smrg    for (n = 0; n < XtNumber(table); ++n) {
5442e4f8982Smrg	if (table[n].code == code) {
5452e4f8982Smrg	    result = table[n].name;
5462e4f8982Smrg	    break;
5472e4f8982Smrg	}
5482e4f8982Smrg    }
5492e4f8982Smrg    return result;
5502e4f8982Smrg}
5512e4f8982Smrg
552d522f475Smrgconst char *
553d522f475SmrgvisibleXError(int code)
554d522f475Smrg{
555d522f475Smrg    static char temp[80];
556d522f475Smrg    const char *result = "?";
557d522f475Smrg    switch (code) {
558d522f475Smrg	CASETYPE(Success);
559d522f475Smrg	CASETYPE(BadRequest);
560d522f475Smrg	CASETYPE(BadValue);
561d522f475Smrg	CASETYPE(BadWindow);
562d522f475Smrg	CASETYPE(BadPixmap);
563d522f475Smrg	CASETYPE(BadAtom);
564d522f475Smrg	CASETYPE(BadCursor);
565d522f475Smrg	CASETYPE(BadFont);
566d522f475Smrg	CASETYPE(BadMatch);
567d522f475Smrg	CASETYPE(BadDrawable);
568d522f475Smrg	CASETYPE(BadAccess);
569d522f475Smrg	CASETYPE(BadAlloc);
570d522f475Smrg	CASETYPE(BadColor);
571d522f475Smrg	CASETYPE(BadGC);
572d522f475Smrg	CASETYPE(BadIDChoice);
573d522f475Smrg	CASETYPE(BadName);
574d522f475Smrg	CASETYPE(BadLength);
575d522f475Smrg	CASETYPE(BadImplementation);
576d522f475Smrg    default:
577d522f475Smrg	sprintf(temp, "%d", code);
578d522f475Smrg	result = temp;
579d522f475Smrg	break;
580d522f475Smrg    }
581d522f475Smrg    return result;
582d522f475Smrg}
583d522f475Smrg
584d522f475Smrg#if OPT_TRACE_FLAGS
585d522f475Smrg#define isScrnFlag(flag) ((flag) == LINEWRAPPED)
586d522f475Smrg
587d522f475Smrgstatic char *
588e0a2b6dfSmrgScrnText(LineData *ld)
589d522f475Smrg{
590956cc18dSsnj    return visibleIChars(ld->charData, ld->lineSize);
591d522f475Smrg}
592d522f475Smrg
593956cc18dSsnj#define SHOW_BAD_LINE(name, ld) \
594956cc18dSsnj	Trace("OOPS " #name " bad row\n")
595d522f475Smrg
596d522f475Smrg#define SHOW_SCRN_FLAG(name,code) \
597956cc18dSsnj	Trace(#name " %s:%s\n", \
598d522f475Smrg	      code ? "*" : "", \
599956cc18dSsnj	      ScrnText(ld))
600d522f475Smrg
601d522f475Smrgvoid
602e0a2b6dfSmrgLineClrFlag(LineData *ld, int flag)
603d522f475Smrg{
604956cc18dSsnj    if (ld == 0) {
605956cc18dSsnj	SHOW_BAD_LINE(LineClrFlag, ld);
606d522f475Smrg	assert(0);
607d522f475Smrg    } else if (isScrnFlag(flag)) {
608956cc18dSsnj	SHOW_SCRN_FLAG(LineClrFlag, 0);
609d522f475Smrg    }
610d522f475Smrg
611956cc18dSsnj    LineFlags(ld) &= ~flag;
612d522f475Smrg}
613d522f475Smrg
614d522f475Smrgvoid
615e0a2b6dfSmrgLineSetFlag(LineData *ld, int flag)
616d522f475Smrg{
617956cc18dSsnj    if (ld == 0) {
618956cc18dSsnj	SHOW_BAD_LINE(LineSetFlag, ld);
619d522f475Smrg	assert(0);
620d522f475Smrg    } else if (isScrnFlag(flag)) {
621956cc18dSsnj	SHOW_SCRN_FLAG(LineSetFlag, 1);
622d522f475Smrg    }
623d522f475Smrg
624956cc18dSsnj    LineFlags(ld) |= flag;
625d522f475Smrg}
626d522f475Smrg
627d522f475Smrgint
628956cc18dSsnjLineTstFlag(LineData ld, int flag)
629d522f475Smrg{
630d522f475Smrg    int code = 0;
631956cc18dSsnj    if (ld == 0) {
632956cc18dSsnj	SHOW_BAD_LINE(LineTstFlag, ld);
633d522f475Smrg    } else {
634956cc18dSsnj	code = LineFlags(ld);
635956cc18dSsnj
636956cc18dSsnj	if (isScrnFlag(flag)) {
637956cc18dSsnj	    SHOW_SCRN_FLAG(LineTstFlag, code);
638d522f475Smrg	}
639d522f475Smrg    }
640d522f475Smrg    return code;
641d522f475Smrg}
642d522f475Smrg#endif /* OPT_TRACE_FLAGS */
643d522f475Smrg
644913cc679Smrgconst char *
645913cc679SmrgTraceAtomName(Display *dpy, Atom atom)
646913cc679Smrg{
647913cc679Smrg    static char *result;
648913cc679Smrg    free(result);
649f2e35a3aSmrg    if (atom != 0) {
650f2e35a3aSmrg	result = XGetAtomName(dpy, atom);
651f2e35a3aSmrg    } else {
652f2e35a3aSmrg	result = x_strdup("NONE");
653f2e35a3aSmrg    }
654913cc679Smrg    return result;
655913cc679Smrg}
656913cc679Smrg
6570bd37d32Smrg/*
6580bd37d32Smrg * Trace the normal or alternate screen, showing color values up to 16, e.g.,
6590bd37d32Smrg * for debugging with vttest.
6600bd37d32Smrg */
6610bd37d32Smrgvoid
6620bd37d32SmrgTraceScreen(XtermWidget xw, int whichBuf)
6630bd37d32Smrg{
6640bd37d32Smrg    TScreen *screen = TScreenOf(xw);
6650bd37d32Smrg
6660bd37d32Smrg    if (screen->editBuf_index[whichBuf]) {
6672e4f8982Smrg	int row;
6682e4f8982Smrg
6690bd37d32Smrg	TRACE(("TraceScreen %d:\n", whichBuf));
6704419d26bSmrg	for (row = 0; row <= LastRowNumber(screen); ++row) {
6710bd37d32Smrg	    LineData *ld = getLineData(screen, row);
6722e4f8982Smrg
6730bd37d32Smrg	    TRACE((" %3d:", row));
6745104ee6eSmrg	    if (ld != NULL) {
6752e4f8982Smrg		int col;
6762e4f8982Smrg
6770bd37d32Smrg		for (col = 0; col < ld->lineSize; ++col) {
6780bd37d32Smrg		    int ch = (int) ld->charData[col];
6790bd37d32Smrg		    if (ch < ' ')
6800bd37d32Smrg			ch = ' ';
6810bd37d32Smrg		    if (ch >= 127)
6820bd37d32Smrg			ch = '#';
6830bd37d32Smrg		    TRACE(("%c", ch));
6840bd37d32Smrg		}
6850bd37d32Smrg		TRACE((":\n"));
6860bd37d32Smrg
687f2e35a3aSmrg#if 0
6880bd37d32Smrg		TRACE(("  xx:"));
6890bd37d32Smrg		for (col = 0; col < ld->lineSize; ++col) {
6900bd37d32Smrg		    unsigned attrs = ld->attribs[col];
6910bd37d32Smrg		    char ch;
6920bd37d32Smrg		    if (attrs & PROTECTED) {
6930bd37d32Smrg			ch = '*';
6940bd37d32Smrg		    } else if (attrs & BLINK) {
6950bd37d32Smrg			ch = 'B';
6960bd37d32Smrg		    } else if (attrs & CHARDRAWN) {
6970bd37d32Smrg			ch = '+';
6980bd37d32Smrg		    } else {
6990bd37d32Smrg			ch = ' ';
7000bd37d32Smrg		    }
7010bd37d32Smrg		    TRACE(("%c", ch));
7020bd37d32Smrg		}
7030bd37d32Smrg		TRACE((":\n"));
704f2e35a3aSmrg#endif
7050bd37d32Smrg
7060bd37d32Smrg#if 0
7070bd37d32Smrg		TRACE(("  fg:"));
7080bd37d32Smrg		for (col = 0; col < ld->lineSize; ++col) {
7090bd37d32Smrg		    unsigned fg = extract_fg(xw, ld->color[col], ld->attribs[col]);
7100bd37d32Smrg		    if (fg > 15)
7110bd37d32Smrg			fg = 15;
7120bd37d32Smrg		    TRACE(("%1x", fg));
7130bd37d32Smrg		}
7140bd37d32Smrg		TRACE((":\n"));
7150bd37d32Smrg
7160bd37d32Smrg		TRACE(("  bg:"));
7170bd37d32Smrg		for (col = 0; col < ld->lineSize; ++col) {
7180bd37d32Smrg		    unsigned bg = extract_bg(xw, ld->color[col], ld->attribs[col]);
7190bd37d32Smrg		    if (bg > 15)
7200bd37d32Smrg			bg = 15;
7210bd37d32Smrg		    TRACE(("%1x", bg));
7220bd37d32Smrg		}
7230bd37d32Smrg		TRACE((":\n"));
7240bd37d32Smrg#endif
7250bd37d32Smrg	    } else {
7260bd37d32Smrg		TRACE(("null lineData\n"));
7270bd37d32Smrg	    }
7280bd37d32Smrg	}
7290bd37d32Smrg    } else {
7300bd37d32Smrg	TRACE(("TraceScreen %d is nil\n", whichBuf));
7310bd37d32Smrg    }
7320bd37d32Smrg}
7330bd37d32Smrg
734f2e35a3aSmrgstatic char *
735f2e35a3aSmrgformatEventMask(char *target, unsigned source, Boolean buttons)
736f2e35a3aSmrg{
737f2e35a3aSmrg#define DATA(name) { name ## Mask, #name }
738f2e35a3aSmrg    static struct {
739f2e35a3aSmrg	unsigned mask;
740f2e35a3aSmrg	const char *name;
741f2e35a3aSmrg    } table[] = {
742f2e35a3aSmrg	DATA(Shift),
743f2e35a3aSmrg	    DATA(Lock),
744f2e35a3aSmrg	    DATA(Control),
745f2e35a3aSmrg	    DATA(Mod1),
746f2e35a3aSmrg	    DATA(Mod2),
747f2e35a3aSmrg	    DATA(Mod3),
748f2e35a3aSmrg	    DATA(Mod4),
749f2e35a3aSmrg	    DATA(Mod5),
750f2e35a3aSmrg	    DATA(Button1),
751f2e35a3aSmrg	    DATA(Button2),
752f2e35a3aSmrg	    DATA(Button3),
753f2e35a3aSmrg	    DATA(Button4),
754f2e35a3aSmrg	    DATA(Button5),
755f2e35a3aSmrg    };
756f2e35a3aSmrg#undef DATA
757f2e35a3aSmrg    Cardinal n;
758f2e35a3aSmrg    char marker = L_CURL;
759f2e35a3aSmrg    char *base = target;
760f2e35a3aSmrg
761f2e35a3aSmrg    for (n = 0; n < XtNumber(table); ++n) {
762f2e35a3aSmrg	if (!buttons && (table[n].mask >= Button1Mask))
763f2e35a3aSmrg	    continue;
764f2e35a3aSmrg	if ((table[n].mask & source)) {
765f2e35a3aSmrg	    UIntClr(source, table[n].mask);
766f2e35a3aSmrg	    sprintf(target, "%c%s", marker, table[n].name);
767f2e35a3aSmrg	    target += strlen(target);
768f2e35a3aSmrg	    marker = '|';
769f2e35a3aSmrg	}
770f2e35a3aSmrg    }
771f2e35a3aSmrg
772f2e35a3aSmrg    if (source != 0) {
773f2e35a3aSmrg	sprintf(target, "%c?%#x", marker, source);
774f2e35a3aSmrg	target += strlen(target);
775f2e35a3aSmrg	marker = '|';
776f2e35a3aSmrg    }
777f2e35a3aSmrg
778f2e35a3aSmrg    if (marker == L_CURL)
779f2e35a3aSmrg	*target++ = L_CURL;
780f2e35a3aSmrg    *target++ = R_CURL;
781f2e35a3aSmrg
782f2e35a3aSmrg    *target = '\0';
783f2e35a3aSmrg    return base;
784f2e35a3aSmrg}
785f2e35a3aSmrg
786f2e35a3aSmrgvoid
7875104ee6eSmrgTraceEvent(const char *tag, XEvent *ev, String *params, const Cardinal *num_params)
788f2e35a3aSmrg{
789f2e35a3aSmrg    char mask_buffer[160];
790f2e35a3aSmrg
791f2e35a3aSmrg    TRACE(("Event #%lu %s: %#lx %s",
792f2e35a3aSmrg	   ev->xany.serial,
793f2e35a3aSmrg	   tag,
794f2e35a3aSmrg	   ev->xany.window,
795f2e35a3aSmrg	   visibleEventType(ev->type)));
796f2e35a3aSmrg
797f2e35a3aSmrg    switch (ev->type) {
798f2e35a3aSmrg    case KeyPress:
799f2e35a3aSmrg	/* FALLTHRU */
800f2e35a3aSmrg    case KeyRelease:
801f2e35a3aSmrg	TRACE((" keycode 0x%04X %s",
802f2e35a3aSmrg	       ev->xkey.keycode,
803f2e35a3aSmrg	       formatEventMask(mask_buffer, ev->xkey.state, False)));
804f2e35a3aSmrg	break;
805f2e35a3aSmrg    case ButtonPress:
806f2e35a3aSmrg	/* FALLTHRU */
807f2e35a3aSmrg    case ButtonRelease:
808f2e35a3aSmrg	TRACE((" button %u state %#x %s",
809f2e35a3aSmrg	       ev->xbutton.button,
810f2e35a3aSmrg	       ev->xbutton.state,
811f2e35a3aSmrg	       formatEventMask(mask_buffer, ev->xbutton.state, True)));
812f2e35a3aSmrg	break;
813f2e35a3aSmrg    case MotionNotify:
814f2e35a3aSmrg	TRACE((" (%d,%d) state %#x %s",
815f2e35a3aSmrg	       ev->xmotion.y_root,
816f2e35a3aSmrg	       ev->xmotion.x_root,
817f2e35a3aSmrg	       ev->xmotion.state,
818f2e35a3aSmrg	       formatEventMask(mask_buffer, ev->xmotion.state, True)));
819f2e35a3aSmrg	break;
820f2e35a3aSmrg    case EnterNotify:
821f2e35a3aSmrg    case LeaveNotify:
822f2e35a3aSmrg	TRACE((" at %d,%d root %d,%d %s %s",
823f2e35a3aSmrg	       ev->xcrossing.y,
824f2e35a3aSmrg	       ev->xcrossing.x,
825f2e35a3aSmrg	       ev->xcrossing.y_root,
826f2e35a3aSmrg	       ev->xcrossing.x_root,
827f2e35a3aSmrg	       visibleNotifyMode(ev->xcrossing.mode),
828f2e35a3aSmrg	       visibleNotifyDetail(ev->xcrossing.detail)));
829f2e35a3aSmrg	break;
830f2e35a3aSmrg    case FocusIn:
831f2e35a3aSmrg    case FocusOut:
832f2e35a3aSmrg	TRACE((" %s %s",
833f2e35a3aSmrg	       visibleNotifyMode(ev->xfocus.mode),
834f2e35a3aSmrg	       visibleNotifyDetail(ev->xfocus.detail)));
835f2e35a3aSmrg	break;
836f2e35a3aSmrg    case MapNotify:
837f2e35a3aSmrg	TRACE((" event %#lx %s",
838f2e35a3aSmrg	       ev->xmap.event,
839f2e35a3aSmrg	       ev->xmap.override_redirect ? "override" : ""));
840f2e35a3aSmrg	break;
841f2e35a3aSmrg    case UnmapNotify:
842f2e35a3aSmrg	TRACE((" event %#lx %s",
843f2e35a3aSmrg	       ev->xunmap.event,
844f2e35a3aSmrg	       ev->xunmap.from_configure ? "configure" : ""));
845f2e35a3aSmrg	break;
846f2e35a3aSmrg    case ReparentNotify:
847f2e35a3aSmrg	TRACE((" at %d,%d event %#lx parent %#lx %s",
848f2e35a3aSmrg	       ev->xreparent.y,
849f2e35a3aSmrg	       ev->xreparent.x,
850f2e35a3aSmrg	       ev->xreparent.event,
851f2e35a3aSmrg	       ev->xreparent.parent,
852f2e35a3aSmrg	       ev->xreparent.override_redirect ? "override" : ""));
853f2e35a3aSmrg	break;
854f2e35a3aSmrg    case ConfigureNotify:
855f2e35a3aSmrg	TRACE((" at %d,%d size %dx%d bd %d above %#lx",
856f2e35a3aSmrg	       ev->xconfigure.y,
857f2e35a3aSmrg	       ev->xconfigure.x,
858f2e35a3aSmrg	       ev->xconfigure.height,
859f2e35a3aSmrg	       ev->xconfigure.width,
860f2e35a3aSmrg	       ev->xconfigure.border_width,
861f2e35a3aSmrg	       ev->xconfigure.above));
862f2e35a3aSmrg	break;
863f2e35a3aSmrg    case CreateNotify:
864f2e35a3aSmrg	TRACE((" at %d,%d size %dx%d bd %d",
865f2e35a3aSmrg	       ev->xcreatewindow.y,
866f2e35a3aSmrg	       ev->xcreatewindow.x,
867f2e35a3aSmrg	       ev->xcreatewindow.height,
868f2e35a3aSmrg	       ev->xcreatewindow.width,
869f2e35a3aSmrg	       ev->xcreatewindow.border_width));
870f2e35a3aSmrg	break;
871f2e35a3aSmrg    case ResizeRequest:
872f2e35a3aSmrg	TRACE((" size %dx%d",
873f2e35a3aSmrg	       ev->xresizerequest.height,
874f2e35a3aSmrg	       ev->xresizerequest.width));
875f2e35a3aSmrg	break;
876f2e35a3aSmrg    case PropertyNotify:
877f2e35a3aSmrg	TRACE((" %s %s",
878f2e35a3aSmrg	       TraceAtomName(XtDisplay(toplevel), ev->xproperty.atom),
879f2e35a3aSmrg	       ((ev->xproperty.state == PropertyNewValue)
880f2e35a3aSmrg		? "NewValue"
881f2e35a3aSmrg		: ((ev->xproperty.state == PropertyDelete)
882f2e35a3aSmrg		   ? "Delete"
883f2e35a3aSmrg		   : "?"))));
884f2e35a3aSmrg
885f2e35a3aSmrg	break;
886f2e35a3aSmrg    case Expose:
887f2e35a3aSmrg	TRACE((" at %d,%d size %dx%d count %d",
888f2e35a3aSmrg	       ev->xexpose.y,
889f2e35a3aSmrg	       ev->xexpose.x,
890f2e35a3aSmrg	       ev->xexpose.height,
891f2e35a3aSmrg	       ev->xexpose.width,
892f2e35a3aSmrg	       ev->xexpose.count));
893f2e35a3aSmrg	break;
894f2e35a3aSmrg    case MappingNotify:
895f2e35a3aSmrg	TRACE((" %s first_keycode %d count %d",
896f2e35a3aSmrg	       visibleMappingMode(ev->xmapping.request),
897f2e35a3aSmrg	       ev->xmapping.first_keycode,
898f2e35a3aSmrg	       ev->xmapping.count));
899f2e35a3aSmrg	break;
900f2e35a3aSmrg    case VisibilityNotify:
901f2e35a3aSmrg	TRACE((" state %d",
902f2e35a3aSmrg	       ev->xvisibility.state));
903f2e35a3aSmrg	break;
904f2e35a3aSmrg    case KeymapNotify:
905f2e35a3aSmrg	{
906f2e35a3aSmrg	    Cardinal j;
907f2e35a3aSmrg	    for (j = 0; j < XtNumber(ev->xkeymap.key_vector); ++j) {
908f2e35a3aSmrg		if (ev->xkeymap.key_vector[j] != 0) {
909f2e35a3aSmrg		    Cardinal k;
9105307cd1aSmrg		    for (k = 0; k < CHAR_BIT; ++k) {
911f2e35a3aSmrg			if (ev->xkeymap.key_vector[j] & (1 << k)) {
9125307cd1aSmrg			    TRACE((" key%u", (j * CHAR_BIT) + k));
913f2e35a3aSmrg			}
914f2e35a3aSmrg		    }
915f2e35a3aSmrg		}
916f2e35a3aSmrg	    }
917f2e35a3aSmrg	}
918f2e35a3aSmrg	break;
919f2e35a3aSmrg    case NoExpose:
920f2e35a3aSmrg	TRACE((" send_event:%d display %p major:%d minor:%d",
921f2e35a3aSmrg	       ev->xnoexpose.send_event,
922f2e35a3aSmrg	       (void *) ev->xnoexpose.display,
923f2e35a3aSmrg	       ev->xnoexpose.major_code,
924f2e35a3aSmrg	       ev->xnoexpose.minor_code));
925f2e35a3aSmrg	break;
926a5ae21e4Smrg    case GraphicsExpose:
927a5ae21e4Smrg	TRACE((" send_event:%d display %p major:%d minor:%d",
928a5ae21e4Smrg	       ev->xgraphicsexpose.send_event,
929a5ae21e4Smrg	       (void *) ev->xgraphicsexpose.display,
930a5ae21e4Smrg	       ev->xgraphicsexpose.major_code,
931a5ae21e4Smrg	       ev->xgraphicsexpose.minor_code));
932a5ae21e4Smrg	break;
933f2e35a3aSmrg    case SelectionClear:
934f2e35a3aSmrg	TRACE((" selection:%s",
935f2e35a3aSmrg	       TraceAtomName(ev->xselectionclear.display,
936f2e35a3aSmrg			     ev->xselectionclear.selection)));
937f2e35a3aSmrg	break;
938f2e35a3aSmrg    case SelectionRequest:
939f2e35a3aSmrg	TRACE((" owner:%#lx requestor:%#lx",
940f2e35a3aSmrg	       ev->xselectionrequest.owner,
941f2e35a3aSmrg	       ev->xselectionrequest.requestor));
942f2e35a3aSmrg	TRACE((" selection:%s",
943f2e35a3aSmrg	       TraceAtomName(ev->xselectionrequest.display,
944f2e35a3aSmrg			     ev->xselectionrequest.selection)));
945f2e35a3aSmrg	TRACE((" target:%s",
946f2e35a3aSmrg	       TraceAtomName(ev->xselectionrequest.display,
947f2e35a3aSmrg			     ev->xselectionrequest.target)));
948f2e35a3aSmrg	TRACE((" property:%s",
949f2e35a3aSmrg	       TraceAtomName(ev->xselectionrequest.display,
950f2e35a3aSmrg			     ev->xselectionrequest.property)));
951f2e35a3aSmrg	break;
952f2e35a3aSmrg    default:
953f2e35a3aSmrg	TRACE((":FIXME"));
954f2e35a3aSmrg	break;
955f2e35a3aSmrg    }
956f2e35a3aSmrg    TRACE(("\n"));
9575104ee6eSmrg    if (params != NULL && *num_params != 0) {
958f2e35a3aSmrg	Cardinal n;
959f2e35a3aSmrg	for (n = 0; n < *num_params; ++n) {
960f2e35a3aSmrg	    TRACE(("  param[%d] = %s\n", n, params[n]));
961f2e35a3aSmrg	}
962f2e35a3aSmrg    }
963f2e35a3aSmrg}
964f2e35a3aSmrg
965f2e35a3aSmrg#if OPT_RENDERFONT && OPT_WIDE_CHARS
966f2e35a3aSmrgvoid
967f2e35a3aSmrgTraceFallback(XtermWidget xw, const char *tag, unsigned wc, int n, XftFont *font)
968f2e35a3aSmrg{
969f2e35a3aSmrg    TScreen *screen = TScreenOf(xw);
970f2e35a3aSmrg    XGlyphInfo gi;
971f2e35a3aSmrg    int expect = my_wcwidth((wchar_t) wc);
972f2e35a3aSmrg    int hijack = mk_wcwidth_cjk((wchar_t) wc);
973f2e35a3aSmrg    int actual;
974f2e35a3aSmrg
975f2e35a3aSmrg    XftTextExtents32(screen->display, font, &wc, 1, &gi);
976f2e35a3aSmrg    actual = ((gi.xOff + FontWidth(screen) - 1)
977f2e35a3aSmrg	      / FontWidth(screen));
978f2e35a3aSmrg
979f2e35a3aSmrg    TRACE(("FALLBACK #%d %s U+%04X %d,%d pos,"
980f2e35a3aSmrg	   " %d,%d off," " %dx%d size,"
981f2e35a3aSmrg	   " %d/%d next," " %d vs %d/%d cells%s\n",
982f2e35a3aSmrg	   n + 1, tag, wc,
983f2e35a3aSmrg	   gi.y, gi.x,
984f2e35a3aSmrg	   gi.yOff, gi.xOff,
985f2e35a3aSmrg	   gi.height, gi.width,
986f2e35a3aSmrg	   font->max_advance_width,
987f2e35a3aSmrg	   FontWidth(screen),
988f2e35a3aSmrg	   actual, expect, hijack,
989f2e35a3aSmrg	   ((actual != expect)
990f2e35a3aSmrg	    ? ((actual == hijack)
991f2e35a3aSmrg	       ? " OOPS"
992f2e35a3aSmrg	       : " oops")
993f2e35a3aSmrg	    : "")));
994f2e35a3aSmrg}
995f2e35a3aSmrg#endif /* OPT_RENDERFONT */
996f2e35a3aSmrg
99720d2c4d2Smrgvoid
99801037d57SmrgTraceFocus(Widget w, XEvent *ev)
99920d2c4d2Smrg{
100020d2c4d2Smrg    TRACE(("trace_focus event type %d:%s\n",
100120d2c4d2Smrg	   ev->type, visibleEventType(ev->type)));
100220d2c4d2Smrg    switch (ev->type) {
100320d2c4d2Smrg    case FocusIn:
100420d2c4d2Smrg    case FocusOut:
100520d2c4d2Smrg	{
100620d2c4d2Smrg	    XFocusChangeEvent *event = (XFocusChangeEvent *) ev;
100720d2c4d2Smrg	    TRACE(("\tdetail: %s\n", visibleNotifyDetail(event->detail)));
10080bd37d32Smrg	    TRACE(("\tmode:   %s\n", visibleNotifyMode(event->mode)));
100920d2c4d2Smrg	    TRACE(("\twindow: %#lx\n", event->window));
101020d2c4d2Smrg	}
101120d2c4d2Smrg	break;
101220d2c4d2Smrg    case EnterNotify:
101320d2c4d2Smrg    case LeaveNotify:
101420d2c4d2Smrg	{
101520d2c4d2Smrg	    XCrossingEvent *event = (XCrossingEvent *) ev;
101620d2c4d2Smrg	    TRACE(("\tdetail:    %s\n", visibleNotifyDetail(event->detail)));
10170bd37d32Smrg	    TRACE(("\tmode:      %s\n", visibleNotifyMode(event->mode)));
101820d2c4d2Smrg	    TRACE(("\twindow:    %#lx\n", event->window));
1019e39b573cSmrg	    TRACE(("\tfocus:     %d\n", event->focus));
102020d2c4d2Smrg	    TRACE(("\troot:      %#lx\n", event->root));
102120d2c4d2Smrg	    TRACE(("\tsubwindow: %#lx\n", event->subwindow));
102220d2c4d2Smrg	}
102320d2c4d2Smrg	break;
102420d2c4d2Smrg    }
10255104ee6eSmrg    while (w != NULL) {
102620d2c4d2Smrg	TRACE(("w %p -> %#lx\n", (void *) w, XtWindow(w)));
102720d2c4d2Smrg	w = XtParent(w);
102820d2c4d2Smrg    }
102920d2c4d2Smrg}
103020d2c4d2Smrg
1031d522f475Smrgvoid
1032d522f475SmrgTraceSizeHints(XSizeHints * hints)
1033d522f475Smrg{
1034d522f475Smrg    TRACE(("size hints:\n"));
1035f2e35a3aSmrg    if (hints->flags & (USPosition | PPosition)) {
1036d522f475Smrg	TRACE(("   position   %d,%d%s%s\n", hints->y, hints->x,
10372e4f8982Smrg	       (hints->flags & USPosition) ? " user" : "",
10382e4f8982Smrg	       (hints->flags & PPosition) ? " prog" : ""));
1039f2e35a3aSmrg    }
1040f2e35a3aSmrg    if (hints->flags & (USSize | PSize)) {
1041d522f475Smrg	TRACE(("   size       %d,%d%s%s\n", hints->height, hints->width,
10422e4f8982Smrg	       (hints->flags & USSize) ? " user" : "",
10432e4f8982Smrg	       (hints->flags & PSize) ? " prog" : ""));
1044f2e35a3aSmrg    }
1045f2e35a3aSmrg    if (hints->flags & PMinSize) {
1046d522f475Smrg	TRACE(("   min        %d,%d\n", hints->min_height, hints->min_width));
1047f2e35a3aSmrg    }
1048f2e35a3aSmrg    if (hints->flags & PMaxSize) {
1049d522f475Smrg	TRACE(("   max        %d,%d\n", hints->max_height, hints->max_width));
1050f2e35a3aSmrg    }
1051f2e35a3aSmrg    if (hints->flags & PResizeInc) {
1052d522f475Smrg	TRACE(("   inc        %d,%d\n", hints->height_inc, hints->width_inc));
1053f2e35a3aSmrg    } else {
10542eaa94a1Schristos	TRACE(("   inc        NONE!\n"));
1055f2e35a3aSmrg    }
1056f2e35a3aSmrg    if (hints->flags & PAspect) {
1057d522f475Smrg	TRACE(("   min aspect %d/%d\n", hints->min_aspect.y, hints->min_aspect.y));
1058d522f475Smrg	TRACE(("   max aspect %d/%d\n", hints->max_aspect.y, hints->max_aspect.y));
1059f2e35a3aSmrg    }
1060f2e35a3aSmrg    if (hints->flags & PBaseSize) {
1061d522f475Smrg	TRACE(("   base       %d,%d\n", hints->base_height, hints->base_width));
1062f2e35a3aSmrg    }
1063f2e35a3aSmrg    if (hints->flags & PWinGravity) {
1064d522f475Smrg	TRACE(("   gravity    %d\n", hints->win_gravity));
1065f2e35a3aSmrg    }
1066d522f475Smrg}
1067d522f475Smrg
10680bd37d32Smrgstatic void
10690bd37d32SmrgTraceEventMask(const char *tag, long mask)
10700bd37d32Smrg{
10710bd37d32Smrg#define DATA(name) { name##Mask, #name }
10720bd37d32Smrg    /* *INDENT-OFF* */
10730bd37d32Smrg    static struct {
10740bd37d32Smrg	long mask;
10750bd37d32Smrg	const char *name;
10760bd37d32Smrg    } table[] = {
10770bd37d32Smrg	DATA(KeyPress),
10780bd37d32Smrg	DATA(KeyRelease),
10790bd37d32Smrg	DATA(ButtonPress),
10800bd37d32Smrg	DATA(ButtonRelease),
10810bd37d32Smrg	DATA(EnterWindow),
10820bd37d32Smrg	DATA(LeaveWindow),
10830bd37d32Smrg	DATA(PointerMotion),
10840bd37d32Smrg	DATA(PointerMotionHint),
10850bd37d32Smrg	DATA(Button1Motion),
10860bd37d32Smrg	DATA(Button2Motion),
10870bd37d32Smrg	DATA(Button3Motion),
10880bd37d32Smrg	DATA(Button4Motion),
10890bd37d32Smrg	DATA(Button5Motion),
10900bd37d32Smrg	DATA(ButtonMotion),
10910bd37d32Smrg	DATA(KeymapState),
10920bd37d32Smrg	DATA(Exposure),
10930bd37d32Smrg	DATA(VisibilityChange),
10940bd37d32Smrg	DATA(StructureNotify),
10950bd37d32Smrg	DATA(ResizeRedirect),
10960bd37d32Smrg	DATA(SubstructureNotify),
10970bd37d32Smrg	DATA(SubstructureRedirect),
10980bd37d32Smrg	DATA(FocusChange),
10990bd37d32Smrg	DATA(PropertyChange),
11000bd37d32Smrg	DATA(ColormapChange),
11010bd37d32Smrg	DATA(OwnerGrabButton),
11020bd37d32Smrg    };
11030bd37d32Smrg#undef DATA
11040bd37d32Smrg    Cardinal n;
11050bd37d32Smrg    /* *INDENT-ON* */
11060bd37d32Smrg
11070bd37d32Smrg    for (n = 0; n < XtNumber(table); ++n) {
11080bd37d32Smrg	if (table[n].mask & mask) {
11090bd37d32Smrg	    TRACE(("%s %s\n", tag, table[n].name));
11100bd37d32Smrg	}
11110bd37d32Smrg    }
11120bd37d32Smrg}
11130bd37d32Smrg
11140bd37d32Smrgvoid
11150bd37d32SmrgTraceWindowAttributes(XWindowAttributes * attrs)
11160bd37d32Smrg{
11170bd37d32Smrg    TRACE(("window attributes:\n"));
11180bd37d32Smrg    TRACE(("   position     %d,%d\n", attrs->y, attrs->x));
11190bd37d32Smrg    TRACE(("   size         %dx%d\n", attrs->height, attrs->width));
11200bd37d32Smrg    TRACE(("   border       %d\n", attrs->border_width));
11210bd37d32Smrg    TRACE(("   depth        %d\n", attrs->depth));
11220bd37d32Smrg    TRACE(("   bit_gravity  %d\n", attrs->bit_gravity));
11230bd37d32Smrg    TRACE(("   win_gravity  %d\n", attrs->win_gravity));
11240bd37d32Smrg    TRACE(("   root         %#lx\n", (long) attrs->root));
11250bd37d32Smrg    TRACE(("   class        %s\n", ((attrs->class == InputOutput)
11260bd37d32Smrg				    ? "InputOutput"
11270bd37d32Smrg				    : ((attrs->class == InputOnly)
11280bd37d32Smrg				       ? "InputOnly"
11290bd37d32Smrg				       : "unknown"))));
11300bd37d32Smrg    TRACE(("   map_state    %s\n", ((attrs->map_state == IsUnmapped)
11310bd37d32Smrg				    ? "IsUnmapped"
11320bd37d32Smrg				    : ((attrs->map_state == IsUnviewable)
11330bd37d32Smrg				       ? "IsUnviewable"
11340bd37d32Smrg				       : ((attrs->map_state == IsViewable)
11350bd37d32Smrg					  ? "IsViewable"
11360bd37d32Smrg					  : "unknown")))));
11370bd37d32Smrg    TRACE(("   all_events\n"));
11380bd37d32Smrg    TraceEventMask("        ", attrs->all_event_masks);
11390bd37d32Smrg    TRACE(("   your_events\n"));
11400bd37d32Smrg    TraceEventMask("        ", attrs->your_event_mask);
11410bd37d32Smrg    TRACE(("   no_propagate\n"));
11420bd37d32Smrg    TraceEventMask("        ", attrs->do_not_propagate_mask);
11430bd37d32Smrg}
11440bd37d32Smrg
1145d522f475Smrgvoid
1146d522f475SmrgTraceWMSizeHints(XtermWidget xw)
1147d522f475Smrg{
1148d522f475Smrg    XSizeHints sizehints = xw->hints;
1149d522f475Smrg
1150d522f475Smrg    getXtermSizeHints(xw);
1151d522f475Smrg    TraceSizeHints(&xw->hints);
1152d522f475Smrg    xw->hints = sizehints;
1153d522f475Smrg}
1154d522f475Smrg
11550bd37d32Smrgconst char *
11560bd37d32SmrgModifierName(unsigned modifier)
11570bd37d32Smrg{
11580bd37d32Smrg    const char *s = "";
11590bd37d32Smrg    if (modifier & ShiftMask)
11600bd37d32Smrg	s = " Shift";
11610bd37d32Smrg    else if (modifier & LockMask)
11620bd37d32Smrg	s = " Lock";
11630bd37d32Smrg    else if (modifier & ControlMask)
11640bd37d32Smrg	s = " Control";
11650bd37d32Smrg    else if (modifier & Mod1Mask)
11660bd37d32Smrg	s = " Mod1";
11670bd37d32Smrg    else if (modifier & Mod2Mask)
11680bd37d32Smrg	s = " Mod2";
11690bd37d32Smrg    else if (modifier & Mod3Mask)
11700bd37d32Smrg	s = " Mod3";
11710bd37d32Smrg    else if (modifier & Mod4Mask)
11720bd37d32Smrg	s = " Mod4";
11730bd37d32Smrg    else if (modifier & Mod5Mask)
11740bd37d32Smrg	s = " Mod5";
11750bd37d32Smrg    return s;
11760bd37d32Smrg}
11770bd37d32Smrg
1178d522f475Smrgvoid
1179d522f475SmrgTraceTranslations(const char *name, Widget w)
1180d522f475Smrg{
1181d522f475Smrg    String result;
1182f2e35a3aSmrg    XErrorHandler save = XSetErrorHandler(ignore_x11_error);
1183d522f475Smrg    XtTranslations xlations;
1184d522f475Smrg    Widget xcelerat;
1185d522f475Smrg
1186f2e35a3aSmrg    TRACE(("TraceTranslations for %s (widget %#lx) " TRACE_L "\n",
1187f2e35a3aSmrg	   name, (long) w));
1188d522f475Smrg    if (w) {
1189d522f475Smrg	XtVaGetValues(w,
1190d522f475Smrg		      XtNtranslations, &xlations,
1191d522f475Smrg		      XtNaccelerators, &xcelerat,
1192d522f475Smrg		      (XtPointer) 0);
1193d522f475Smrg	TRACE(("... xlations %#08lx\n", (long) xlations));
1194d522f475Smrg	TRACE(("... xcelerat %#08lx\n", (long) xcelerat));
1195d522f475Smrg	result = _XtPrintXlations(w, xlations, xcelerat, True);
119620d2c4d2Smrg	TRACE(("%s\n", NonNull(result)));
1197d522f475Smrg	if (result)
119820d2c4d2Smrg	    XFree((char *) result);
1199d522f475Smrg    } else {
1200d522f475Smrg	TRACE(("none (widget is null)\n"));
1201d522f475Smrg    }
1202f2e35a3aSmrg    TRACE((TRACE_R "\n"));
1203d522f475Smrg    XSetErrorHandler(save);
1204d522f475Smrg}
1205d522f475Smrg
12060bd37d32SmrgXtGeometryResult
12072eaa94a1SchristosTraceResizeRequest(const char *fn, int ln, Widget w,
1208e39b573cSmrg		   unsigned reqwide,
1209e39b573cSmrg		   unsigned reqhigh,
1210e0a2b6dfSmrg		   Dimension *gotwide,
1211e0a2b6dfSmrg		   Dimension *gothigh)
12122eaa94a1Schristos{
12130bd37d32Smrg    XtGeometryResult rc;
12142eaa94a1Schristos
1215e39b573cSmrg    TRACE(("%s@%d ResizeRequest %ux%u\n", fn, ln, reqhigh, reqwide));
12160bd37d32Smrg    rc = XtMakeResizeRequest((Widget) w,
12170bd37d32Smrg			     (Dimension) reqwide,
12180bd37d32Smrg			     (Dimension) reqhigh,
12190bd37d32Smrg			     gotwide, gothigh);
12202eaa94a1Schristos    TRACE(("... ResizeRequest -> "));
12212eaa94a1Schristos    if (gothigh && gotwide)
12222eaa94a1Schristos	TRACE(("%dx%d ", *gothigh, *gotwide));
12232eaa94a1Schristos    TRACE(("(%d)\n", rc));
12242eaa94a1Schristos    return rc;
12252eaa94a1Schristos}
12262eaa94a1Schristos
1227d522f475Smrg#define XRES_S(name) Trace(#name " = %s\n", NonNull(resp->name))
122801037d57Smrg#define XRES_B(name) Trace(#name " = %s\n", MtoS(resp->name))
1229d522f475Smrg#define XRES_I(name) Trace(#name " = %d\n", resp->name)
1230d522f475Smrg
1231d522f475Smrgvoid
1232d522f475SmrgTraceXtermResources(void)
1233d522f475Smrg{
1234d522f475Smrg    XTERM_RESOURCE *resp = &resource;
1235d522f475Smrg
1236d522f475Smrg    Trace("XTERM_RESOURCE settings:\n");
1237d522f475Smrg    XRES_S(icon_geometry);
1238d522f475Smrg    XRES_S(title);
12390bd37d32Smrg    XRES_S(icon_hint);
1240d522f475Smrg    XRES_S(icon_name);
1241d522f475Smrg    XRES_S(term_name);
1242d522f475Smrg    XRES_S(tty_modes);
1243e39b573cSmrg    XRES_I(minBufSize);
1244e39b573cSmrg    XRES_I(maxBufSize);
1245d522f475Smrg    XRES_B(hold_screen);
1246d522f475Smrg    XRES_B(utmpInhibit);
1247d522f475Smrg    XRES_B(utmpDisplayId);
1248d522f475Smrg    XRES_B(messages);
1249e39b573cSmrg    XRES_S(menuLocale);
1250e39b573cSmrg    XRES_S(omitTranslation);
1251e39b573cSmrg    XRES_S(keyboardType);
1252ad37e533Smrg#ifdef HAVE_LIB_XCURSOR
1253ad37e533Smrg    XRES_S(cursorTheme);
1254ad37e533Smrg#endif
1255e39b573cSmrg#if OPT_PRINT_ON_EXIT
1256e39b573cSmrg    XRES_I(printModeNow);
1257e39b573cSmrg    XRES_I(printModeOnXError);
1258e39b573cSmrg    XRES_I(printOptsNow);
1259e39b573cSmrg    XRES_I(printOptsOnXError);
1260e39b573cSmrg    XRES_S(printFileNow);
1261e39b573cSmrg    XRES_S(printFileOnXError);
1262e39b573cSmrg#endif
1263d522f475Smrg#if OPT_SUNPC_KBD
1264d522f475Smrg    XRES_B(sunKeyboard);
1265d522f475Smrg#endif
1266d522f475Smrg#if OPT_HP_FUNC_KEYS
1267d522f475Smrg    XRES_B(hpFunctionKeys);
1268d522f475Smrg#endif
1269d522f475Smrg#if OPT_SCO_FUNC_KEYS
1270d522f475Smrg    XRES_B(scoFunctionKeys);
1271d522f475Smrg#endif
1272d522f475Smrg#if OPT_SUN_FUNC_KEYS
1273d522f475Smrg    XRES_B(sunFunctionKeys);
1274d522f475Smrg#endif
1275d522f475Smrg#if OPT_INITIAL_ERASE
1276d522f475Smrg    XRES_B(ptyInitialErase);
1277d522f475Smrg    XRES_B(backarrow_is_erase);
1278d522f475Smrg#endif
1279d522f475Smrg    XRES_B(useInsertMode);
1280d522f475Smrg#if OPT_ZICONBEEP
1281d522f475Smrg    XRES_I(zIconBeep);
12820bd37d32Smrg    XRES_S(zIconFormat);
1283d522f475Smrg#endif
1284d522f475Smrg#if OPT_PTY_HANDSHAKE
1285d522f475Smrg    XRES_B(wait_for_map);
1286d522f475Smrg    XRES_B(ptyHandshake);
1287d522f475Smrg    XRES_B(ptySttySize);
1288d522f475Smrg#endif
1289913cc679Smrg#if OPT_REPORT_CCLASS
1290913cc679Smrg    XRES_B(reportCClass);
1291913cc679Smrg#endif
1292e0a2b6dfSmrg#if OPT_REPORT_COLORS
1293e0a2b6dfSmrg    XRES_B(reportColors);
1294e0a2b6dfSmrg#endif
1295e0a2b6dfSmrg#if OPT_REPORT_FONTS
1296e0a2b6dfSmrg    XRES_B(reportFonts);
1297e0a2b6dfSmrg#endif
1298f2e35a3aSmrg#if OPT_REPORT_ICONS
1299f2e35a3aSmrg    XRES_B(reportIcons);
1300f2e35a3aSmrg#endif
1301d522f475Smrg#if OPT_SAME_NAME
1302d522f475Smrg    XRES_B(sameName);
1303d522f475Smrg#endif
1304d522f475Smrg#if OPT_SESSION_MGT
1305d522f475Smrg    XRES_B(sessionMgt);
1306d522f475Smrg#endif
1307a1f3da82Smrg#if OPT_TOOLBAR
1308a1f3da82Smrg    XRES_B(toolBar);
1309a1f3da82Smrg#endif
1310a1f3da82Smrg#if OPT_MAXIMIZE
1311a1f3da82Smrg    XRES_B(maximized);
1312a1f3da82Smrg    XRES_S(fullscreen_s);
1313a1f3da82Smrg#endif
1314f2e35a3aSmrg#if USE_DOUBLE_BUFFER
1315f2e35a3aSmrg    XRES_B(buffered);
1316f2e35a3aSmrg    XRES_I(buffered_fps);
1317f2e35a3aSmrg#endif
1318d522f475Smrg}
1319d522f475Smrg
1320d522f475Smrgvoid
1321d522f475SmrgTraceArgv(const char *tag, char **argv)
1322d522f475Smrg{
1323d522f475Smrg    TRACE(("%s:\n", tag));
13245104ee6eSmrg    if (argv != NULL) {
1325913cc679Smrg	int n = 0;
1326913cc679Smrg
13275104ee6eSmrg	while (*argv != NULL) {
1328913cc679Smrg	    TRACE(("  %d:%s\n", n++, *argv++));
1329913cc679Smrg	}
1330d522f475Smrg    }
1331d522f475Smrg}
1332d522f475Smrg
1333d522f475Smrgstatic char *
133420d2c4d2Smrgparse_option(char *dst, String src, int first)
1335d522f475Smrg{
1336d522f475Smrg    char *s;
1337d522f475Smrg
1338a1f3da82Smrg    if (!strncmp(src, "-/+", (size_t) 3)) {
1339956cc18dSsnj	dst[0] = (char) first;
1340d522f475Smrg	strcpy(dst + 1, src + 3);
1341d522f475Smrg    } else {
1342d522f475Smrg	strcpy(dst, src);
1343d522f475Smrg    }
1344d522f475Smrg    for (s = dst; *s != '\0'; s++) {
1345d522f475Smrg	if (*s == '#' || *s == '%' || *s == 'S') {
1346d522f475Smrg	    s[1] = '\0';
1347d522f475Smrg	} else if (*s == ' ') {
1348d522f475Smrg	    *s = '\0';
1349d522f475Smrg	    break;
1350d522f475Smrg	}
1351d522f475Smrg    }
1352d522f475Smrg    return dst;
1353d522f475Smrg}
1354d522f475Smrg
1355d522f475Smrgstatic Bool
1356d522f475Smrgsame_option(OptionHelp * opt, XrmOptionDescRec * res)
1357d522f475Smrg{
1358d522f475Smrg    char temp[BUFSIZ];
1359d522f475Smrg    return !strcmp(parse_option(temp, opt->opt, res->option[0]), res->option);
1360d522f475Smrg}
1361d522f475Smrg
1362d522f475Smrgstatic Bool
136320d2c4d2Smrgstandard_option(String opt)
1364d522f475Smrg{
1365d522f475Smrg    static const char *table[] =
1366d522f475Smrg    {
1367d522f475Smrg	"+rv",
1368d522f475Smrg	"+synchronous",
1369d522f475Smrg	"-background",
1370d522f475Smrg	"-bd",
1371d522f475Smrg	"-bg",
1372d522f475Smrg	"-bordercolor",
1373d522f475Smrg	"-borderwidth",
1374d522f475Smrg	"-bw",
1375d522f475Smrg	"-display",
1376d522f475Smrg	"-fg",
1377d522f475Smrg	"-fn",
1378d522f475Smrg	"-font",
1379d522f475Smrg	"-foreground",
1380d522f475Smrg	"-geometry",
1381d522f475Smrg	"-iconic",
1382d522f475Smrg	"-name",
1383d522f475Smrg	"-reverse",
1384d522f475Smrg	"-rv",
1385d522f475Smrg	"-selectionTimeout",
1386d522f475Smrg	"-synchronous",
1387d522f475Smrg	"-title",
1388d522f475Smrg	"-xnllanguage",
1389d522f475Smrg	"-xrm",
1390d522f475Smrg	"-xtsessionID",
1391d522f475Smrg    };
1392d522f475Smrg    Cardinal n;
1393d522f475Smrg    char temp[BUFSIZ];
1394d522f475Smrg
1395d522f475Smrg    opt = parse_option(temp, opt, '-');
1396d522f475Smrg    for (n = 0; n < XtNumber(table); n++) {
1397d522f475Smrg	if (!strcmp(opt, table[n]))
1398d522f475Smrg	    return True;
1399d522f475Smrg    }
1400d522f475Smrg    return False;
1401d522f475Smrg}
1402d522f475Smrg
1403d522f475Smrg/*
1404d522f475Smrg * Analyse the options/help messages for inconsistencies.
1405d522f475Smrg */
1406d522f475Smrgvoid
1407d522f475SmrgTraceOptions(OptionHelp * options, XrmOptionDescRec * resources, Cardinal res_count)
1408d522f475Smrg{
1409d522f475Smrg    OptionHelp *opt_array = sortedOpts(options, resources, res_count);
1410d522f475Smrg    size_t j, k;
1411d522f475Smrg    XrmOptionDescRec *res_array = sortedOptDescs(resources, res_count);
1412d522f475Smrg    Bool first, found;
1413d522f475Smrg
1414d522f475Smrg    TRACE(("Checking options-tables for inconsistencies:\n"));
1415d522f475Smrg
1416d522f475Smrg#if 0
1417d522f475Smrg    TRACE(("Options listed in help-message:\n"));
1418d522f475Smrg    for (j = 0; options[j].opt != 0; j++)
1419d522f475Smrg	TRACE(("%5d %-28s %s\n", j, opt_array[j].opt, opt_array[j].desc));
1420d522f475Smrg    TRACE(("Options listed in resource-table:\n"));
1421d522f475Smrg    for (j = 0; j < res_count; j++)
1422d522f475Smrg	TRACE(("%5d %-28s %s\n", j, res_array[j].option, res_array[j].specifier));
1423d522f475Smrg#endif
1424d522f475Smrg
1425d522f475Smrg    /* list all options[] not found in resources[] */
14265104ee6eSmrg    for (j = 0, first = True; options[j].opt != NULL; j++) {
1427d522f475Smrg	found = False;
1428d522f475Smrg	for (k = 0; k < res_count; k++) {
1429d522f475Smrg	    if (same_option(&opt_array[j], &res_array[k])) {
1430d522f475Smrg		found = True;
1431d522f475Smrg		break;
1432d522f475Smrg	    }
1433d522f475Smrg	}
1434d522f475Smrg	if (!found) {
1435d522f475Smrg	    if (first) {
1436d522f475Smrg		TRACE(("Options listed in help, not found in resource list:\n"));
1437d522f475Smrg		first = False;
1438d522f475Smrg	    }
1439d522f475Smrg	    TRACE(("  %-28s%s\n", opt_array[j].opt,
1440d522f475Smrg		   standard_option(opt_array[j].opt) ? " (standard)" : ""));
1441d522f475Smrg	}
1442d522f475Smrg    }
1443d522f475Smrg
1444d522f475Smrg    /* list all resources[] not found in options[] */
1445d522f475Smrg    for (j = 0, first = True; j < res_count; j++) {
1446d522f475Smrg	found = False;
14475104ee6eSmrg	for (k = 0; options[k].opt != NULL; k++) {
1448d522f475Smrg	    if (same_option(&opt_array[k], &res_array[j])) {
1449d522f475Smrg		found = True;
1450d522f475Smrg		break;
1451d522f475Smrg	    }
1452d522f475Smrg	}
1453d522f475Smrg	if (!found) {
1454d522f475Smrg	    if (first) {
1455d522f475Smrg		TRACE(("Resource list items not found in options-help:\n"));
1456d522f475Smrg		first = False;
1457d522f475Smrg	    }
1458d522f475Smrg	    TRACE(("  %s\n", res_array[j].option));
1459d522f475Smrg	}
1460d522f475Smrg    }
1461d522f475Smrg
1462d522f475Smrg    TRACE(("Resource list items that will be ignored by XtOpenApplication:\n"));
1463d522f475Smrg    for (j = 0; j < res_count; j++) {
1464d522f475Smrg	switch (res_array[j].argKind) {
1465d522f475Smrg	case XrmoptionSkipArg:
1466d522f475Smrg	    TRACE(("  %-28s {param}\n", res_array[j].option));
1467d522f475Smrg	    break;
1468d522f475Smrg	case XrmoptionSkipNArgs:
1469d522f475Smrg	    TRACE(("  %-28s {%ld params}\n", res_array[j].option, (long)
1470d522f475Smrg		   res_array[j].value));
1471d522f475Smrg	    break;
1472d522f475Smrg	case XrmoptionSkipLine:
1473d522f475Smrg	    TRACE(("  %-28s {remainder of line}\n", res_array[j].option));
1474d522f475Smrg	    break;
1475d522f475Smrg	case XrmoptionIsArg:
1476d522f475Smrg	case XrmoptionNoArg:
1477d522f475Smrg	case XrmoptionResArg:
1478d522f475Smrg	case XrmoptionSepArg:
1479d522f475Smrg	case XrmoptionStickyArg:
1480d522f475Smrg	default:
1481d522f475Smrg	    break;
1482d522f475Smrg	}
1483d522f475Smrg    }
1484d522f475Smrg}
1485a1f3da82Smrg#else
1486a1f3da82Smrgextern void empty_trace(void);
1487a1f3da82Smrgvoid
1488a1f3da82Smrgempty_trace(void)
1489a1f3da82Smrg{
1490a1f3da82Smrg}
1491a1f3da82Smrg#endif
1492