trace.c revision 5307cd1a
15307cd1aSmrg/* $XTermId: trace.c,v 1.238 2022/09/06 23:55:46 tom Exp $ */
2d522f475Smrg
320d2c4d2Smrg/*
44419d26bSmrg * Copyright 1997-2021,2022 by Thomas E. Dickey
50bd37d32Smrg *
620d2c4d2Smrg *                         All Rights Reserved
70bd37d32Smrg *
820d2c4d2Smrg * Permission is hereby granted, free of charge, to any person obtaining a
920d2c4d2Smrg * copy of this software and associated documentation files (the
1020d2c4d2Smrg * "Software"), to deal in the Software without restriction, including
1120d2c4d2Smrg * without limitation the rights to use, copy, modify, merge, publish,
1220d2c4d2Smrg * distribute, sublicense, and/or sell copies of the Software, and to
1320d2c4d2Smrg * permit persons to whom the Software is furnished to do so, subject to
1420d2c4d2Smrg * the following conditions:
1520d2c4d2Smrg *
1620d2c4d2Smrg * The above copyright notice and this permission notice shall be included
1720d2c4d2Smrg * in all copies or substantial portions of the Software.
1820d2c4d2Smrg *
1920d2c4d2Smrg * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
2020d2c4d2Smrg * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
2120d2c4d2Smrg * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
2220d2c4d2Smrg * IN NO EVENT SHALL THE ABOVE LISTED COPYRIGHT HOLDER(S) BE LIABLE FOR ANY
2320d2c4d2Smrg * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
2420d2c4d2Smrg * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
2520d2c4d2Smrg * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
2620d2c4d2Smrg *
2720d2c4d2Smrg * Except as contained in this notice, the name(s) of the above copyright
2820d2c4d2Smrg * holders shall not be used in advertising or otherwise to promote the
2920d2c4d2Smrg * sale, use or other dealings in this Software without prior written
3020d2c4d2Smrg * authorization.
3120d2c4d2Smrg */
32d522f475Smrg
33d522f475Smrg/*
34d522f475Smrg * debugging support via TRACE macro.
35d522f475Smrg */
36d522f475Smrg
37d522f475Smrg#include <xterm.h>		/* for definition of GCC_UNUSED */
38f2e35a3aSmrg#include <xstrings.h>
39f2e35a3aSmrg#include <wcwidth.h>
400bd37d32Smrg#include <version.h>
41a1f3da82Smrg
42a1f3da82Smrg#if OPT_TRACE
43a1f3da82Smrg
44d522f475Smrg#include <data.h>
45d522f475Smrg#include <trace.h>
46d522f475Smrg
47d522f475Smrg#include <time.h>
48d522f475Smrg#include <stdlib.h>
49d522f475Smrg#include <unistd.h>
50d522f475Smrg#include <sys/types.h>
51894e0ac8Smrg#include <sys/stat.h>
52d522f475Smrg#include <stdio.h>
53d522f475Smrg#include <assert.h>
54d522f475Smrg
55956cc18dSsnj#include <X11/Xatom.h>
56956cc18dSsnj#include <X11/Xmu/Atoms.h>
57f2e35a3aSmrg#include <X11/Xmu/Error.h>
58956cc18dSsnj
59d522f475Smrg#ifdef HAVE_X11_TRANSLATEI_H
602e4f8982Smrg#include <X11/ConvertI.h>
61d522f475Smrg#include <X11/TranslateI.h>
62d522f475Smrg#else
63d522f475Smrg#ifdef __cplusplus
64d522f475Smrgextern "C" {
65d522f475Smrg#endif
66d522f475Smrg
67d522f475Smrg    extern String _XtPrintXlations(Widget w,
68d522f475Smrg				   XtTranslations xlations,
69d522f475Smrg				   Widget accelWidget,
70d522f475Smrg				   _XtBoolean includeRHS);
71d522f475Smrg#ifdef __cplusplus
72d522f475Smrg}
73d522f475Smrg#endif
74d522f475Smrg#endif
7520d2c4d2Smrgconst char *trace_who = "parent";
7620d2c4d2Smrg
7720d2c4d2Smrgstatic FILE *trace_fp;
78d522f475Smrg
79f2e35a3aSmrgstatic FILE *
80f2e35a3aSmrgTraceOpen(void)
81d522f475Smrg{
8220d2c4d2Smrg    static const char *trace_out;
83d522f475Smrg
8420d2c4d2Smrg    if (trace_fp != 0
85d522f475Smrg	&& trace_who != trace_out) {
8620d2c4d2Smrg	fclose(trace_fp);
8720d2c4d2Smrg	trace_fp = 0;
88d522f475Smrg    }
89d522f475Smrg    trace_out = trace_who;
90d522f475Smrg
9120d2c4d2Smrg    if (!trace_fp) {
92f2e35a3aSmrg	static char dot[] = ".";
93913cc679Smrg	mode_t oldmask = umask(077);
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");
1214419d26bSmrg	    if (trace_fp != 0) {
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{
16020d2c4d2Smrg    if (trace_fp != 0) {
16120d2c4d2Smrg	(void) fclose(trace_fp);
162d522f475Smrg	(void) fflush(stdout);
163d522f475Smrg	(void) fflush(stderr);
164956cc18dSsnj	(void) visibleChars(NULL, 0);
165956cc18dSsnj	(void) visibleIChars(NULL, 0);
16620d2c4d2Smrg	trace_fp = 0;
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
187d522f475Smrg    if (fname != 0) {
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;
1990bd37d32Smrg    if (fname != 0) {
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:
226d522f475Smrg	if (E2A(value) < 32 || (E2A(value) >= 127 && E2A(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);
272e0a2b6dfSmrg	MAP("%5", nrc_DEC_Supp_Graphic);
273e0a2b6dfSmrg	MAP(">", nrc_DEC_Technical);
274e0a2b6dfSmrg	MAP("4", nrc_Dutch);
275e0a2b6dfSmrg	MAP("5", nrc_Finnish);
276e0a2b6dfSmrg	MAP("C", nrc_Finnish2);
277e0a2b6dfSmrg	MAP("R", nrc_French);
278e0a2b6dfSmrg	MAP("f", nrc_French2);
279e0a2b6dfSmrg	MAP("Q", nrc_French_Canadian);
280e0a2b6dfSmrg	MAP("9", nrc_French_Canadian2);
281e0a2b6dfSmrg	MAP("K", nrc_German);
282f2e35a3aSmrg	MAP("\"?", nrc_DEC_Greek_Supp);
283f2e35a3aSmrg	MAP("\">", nrc_Greek);
284f2e35a3aSmrg	MAP("F", nrc_ISO_Greek_Supp);
285f2e35a3aSmrg	MAP("\"4", nrc_DEC_Hebrew_Supp);
286f2e35a3aSmrg	MAP("%=", nrc_Hebrew);
287f2e35a3aSmrg	MAP("H", nrc_ISO_Hebrew_Supp);
288e0a2b6dfSmrg	MAP("Y", nrc_Italian);
289f2e35a3aSmrg	MAP("A", nrc_ISO_Latin_1_Supp);
290f2e35a3aSmrg	MAP("B", nrc_ISO_Latin_2_Supp);
291f2e35a3aSmrg	MAP("M", nrc_ISO_Latin_5_Supp);
292f2e35a3aSmrg	MAP("L", nrc_ISO_Latin_Cyrillic);
293e0a2b6dfSmrg	MAP("`", nrc_Norwegian_Danish);
294e0a2b6dfSmrg	MAP("E", nrc_Norwegian_Danish2);
295e0a2b6dfSmrg	MAP("6", nrc_Norwegian_Danish3);
296e0a2b6dfSmrg	MAP("%6", nrc_Portugese);
297e0a2b6dfSmrg	MAP("&5", nrc_Russian);
298e0a2b6dfSmrg	MAP("%3", nrc_SCS_NRCS);
299e0a2b6dfSmrg	MAP("Z", nrc_Spanish);
300e0a2b6dfSmrg	MAP("7", nrc_Swedish);
301e0a2b6dfSmrg	MAP("H", nrc_Swedish2);
302e0a2b6dfSmrg	MAP("=", nrc_Swiss);
303f2e35a3aSmrg	MAP("%2", nrc_Turkish);
304f2e35a3aSmrg	MAP("%0", nrc_DEC_Turkish_Supp);
305e0a2b6dfSmrg	MAP("<UNK>", nrc_Unknown);
306e0a2b6dfSmrg    }
307e0a2b6dfSmrg#undef MAP
308e0a2b6dfSmrg    return result;
309e0a2b6dfSmrg}
310e0a2b6dfSmrg
3112e4f8982Smrgconst char *
3125307cd1aSmrgvisibleChars(const Char *buf, size_t len)
313d522f475Smrg{
314d522f475Smrg    static char *result;
3155307cd1aSmrg    static size_t used;
316d522f475Smrg
317956cc18dSsnj    if (buf != 0) {
3185307cd1aSmrg	size_t limit = ((len + 1) * 8) + 1;
319956cc18dSsnj
320956cc18dSsnj	if (limit > used) {
321956cc18dSsnj	    used = limit;
3225307cd1aSmrg	    result = realloc(result, used);
323956cc18dSsnj	}
32420d2c4d2Smrg	if (result != 0) {
3252e4f8982Smrg	    char *dst = result;
32620d2c4d2Smrg	    *dst = '\0';
32720d2c4d2Smrg	    while (len--) {
32820d2c4d2Smrg		unsigned value = *buf++;
32920d2c4d2Smrg		formatAscii(dst, value);
33020d2c4d2Smrg		dst += strlen(dst);
33120d2c4d2Smrg	    }
332956cc18dSsnj	}
333f2e35a3aSmrg    } else {
334f2e35a3aSmrg	FreeAndNull(result);
335956cc18dSsnj	used = 0;
336d522f475Smrg    }
33701037d57Smrg    return NonNull(result);
338956cc18dSsnj}
339956cc18dSsnj
340f2e35a3aSmrgconst char *
341f2e35a3aSmrgvisibleEventMode(EventMode value)
342f2e35a3aSmrg{
343f2e35a3aSmrg    const char *result;
344f2e35a3aSmrg    switch (value) {
345f2e35a3aSmrg    case NORMAL:
346f2e35a3aSmrg	result = "NORMAL";
347f2e35a3aSmrg	break;
348f2e35a3aSmrg    case LEFTEXTENSION:
349f2e35a3aSmrg	result = "LEFTEXTENSION";
350f2e35a3aSmrg	break;
351f2e35a3aSmrg    case RIGHTEXTENSION:
352f2e35a3aSmrg	result = "RIGHTEXTENSION";
353f2e35a3aSmrg	break;
354f2e35a3aSmrg    default:
355f2e35a3aSmrg	result = "?";
356f2e35a3aSmrg	break;
357f2e35a3aSmrg    }
358f2e35a3aSmrg    return result;
359f2e35a3aSmrg}
360f2e35a3aSmrg
3612e4f8982Smrgconst char *
3625307cd1aSmrgvisibleIChars(const IChar *buf, size_t len)
363956cc18dSsnj{
364956cc18dSsnj    static char *result;
3655307cd1aSmrg    static size_t used;
366956cc18dSsnj
367956cc18dSsnj    if (buf != 0) {
3685307cd1aSmrg	size_t limit = ((len + 1) * 12) + 1;
369956cc18dSsnj
370956cc18dSsnj	if (limit > used) {
371956cc18dSsnj	    used = limit;
3725307cd1aSmrg	    result = realloc(result, used);
373d522f475Smrg	}
37420d2c4d2Smrg	if (result != 0) {
3752e4f8982Smrg	    char *dst = result;
37620d2c4d2Smrg	    *dst = '\0';
37720d2c4d2Smrg	    while (len--) {
37820d2c4d2Smrg		unsigned value = *buf++;
379956cc18dSsnj#if OPT_WIDE_CHARS
38020d2c4d2Smrg		if (value > 255)
381f2e35a3aSmrg		    sprintf(dst, "\\U+%04X", value);
38220d2c4d2Smrg		else
383d522f475Smrg#endif
38420d2c4d2Smrg		    formatAscii(dst, value);
38520d2c4d2Smrg		dst += strlen(dst);
38620d2c4d2Smrg	    }
387956cc18dSsnj	}
388f2e35a3aSmrg    } else {
389f2e35a3aSmrg	FreeAndNull(result);
390956cc18dSsnj	used = 0;
391d522f475Smrg    }
39201037d57Smrg    return NonNull(result);
393d522f475Smrg}
394d522f475Smrg
3952e4f8982Smrgconst char *
396e0a2b6dfSmrgvisibleUChar(unsigned chr)
397d522f475Smrg{
398e0a2b6dfSmrg    IChar buf[1];
399f2e35a3aSmrg    buf[0] = (IChar) chr;
400e0a2b6dfSmrg    return visibleIChars(buf, 1);
401d522f475Smrg}
402d522f475Smrg
403d522f475Smrgconst char *
404d522f475SmrgvisibleEventType(int type)
405d522f475Smrg{
406d522f475Smrg    const char *result = "?";
407d522f475Smrg    switch (type) {
408d522f475Smrg	CASETYPE(KeyPress);
409d522f475Smrg	CASETYPE(KeyRelease);
410d522f475Smrg	CASETYPE(ButtonPress);
411d522f475Smrg	CASETYPE(ButtonRelease);
412d522f475Smrg	CASETYPE(MotionNotify);
413d522f475Smrg	CASETYPE(EnterNotify);
414d522f475Smrg	CASETYPE(LeaveNotify);
415d522f475Smrg	CASETYPE(FocusIn);
416d522f475Smrg	CASETYPE(FocusOut);
417d522f475Smrg	CASETYPE(KeymapNotify);
418d522f475Smrg	CASETYPE(Expose);
419d522f475Smrg	CASETYPE(GraphicsExpose);
420d522f475Smrg	CASETYPE(NoExpose);
421d522f475Smrg	CASETYPE(VisibilityNotify);
422d522f475Smrg	CASETYPE(CreateNotify);
423d522f475Smrg	CASETYPE(DestroyNotify);
424d522f475Smrg	CASETYPE(UnmapNotify);
425d522f475Smrg	CASETYPE(MapNotify);
426d522f475Smrg	CASETYPE(MapRequest);
427d522f475Smrg	CASETYPE(ReparentNotify);
428d522f475Smrg	CASETYPE(ConfigureNotify);
429d522f475Smrg	CASETYPE(ConfigureRequest);
430d522f475Smrg	CASETYPE(GravityNotify);
431d522f475Smrg	CASETYPE(ResizeRequest);
432d522f475Smrg	CASETYPE(CirculateNotify);
433d522f475Smrg	CASETYPE(CirculateRequest);
434d522f475Smrg	CASETYPE(PropertyNotify);
435d522f475Smrg	CASETYPE(SelectionClear);
436d522f475Smrg	CASETYPE(SelectionRequest);
437d522f475Smrg	CASETYPE(SelectionNotify);
438d522f475Smrg	CASETYPE(ColormapNotify);
439d522f475Smrg	CASETYPE(ClientMessage);
440d522f475Smrg	CASETYPE(MappingNotify);
441d522f475Smrg    }
442d522f475Smrg    return result;
443d522f475Smrg}
444d522f475Smrg
445f2e35a3aSmrgconst char *
446f2e35a3aSmrgvisibleMappingMode(int code)
447f2e35a3aSmrg{
448f2e35a3aSmrg    const char *result = "?";
449f2e35a3aSmrg    switch (code) {
450f2e35a3aSmrg	CASETYPE(MappingModifier);
451f2e35a3aSmrg	CASETYPE(MappingKeyboard);
452f2e35a3aSmrg	CASETYPE(MappingPointer);
453f2e35a3aSmrg    }
454f2e35a3aSmrg    return result;
455f2e35a3aSmrg}
456f2e35a3aSmrg
4570bd37d32Smrgconst char *
4580bd37d32SmrgvisibleNotifyMode(int code)
4590bd37d32Smrg{
4600bd37d32Smrg    const char *result = "?";
4610bd37d32Smrg    switch (code) {
4620bd37d32Smrg	CASETYPE(NotifyNormal);
4630bd37d32Smrg	CASETYPE(NotifyGrab);
4640bd37d32Smrg	CASETYPE(NotifyUngrab);
4650bd37d32Smrg	CASETYPE(NotifyWhileGrabbed);
4660bd37d32Smrg    }
4670bd37d32Smrg    return result;
4680bd37d32Smrg}
4690bd37d32Smrg
47020d2c4d2Smrgconst char *
47120d2c4d2SmrgvisibleNotifyDetail(int code)
47220d2c4d2Smrg{
47320d2c4d2Smrg    const char *result = "?";
47420d2c4d2Smrg    switch (code) {
47520d2c4d2Smrg	CASETYPE(NotifyAncestor);
47620d2c4d2Smrg	CASETYPE(NotifyVirtual);
47720d2c4d2Smrg	CASETYPE(NotifyInferior);
47820d2c4d2Smrg	CASETYPE(NotifyNonlinear);
47920d2c4d2Smrg	CASETYPE(NotifyNonlinearVirtual);
48020d2c4d2Smrg	CASETYPE(NotifyPointer);
48120d2c4d2Smrg	CASETYPE(NotifyPointerRoot);
48220d2c4d2Smrg	CASETYPE(NotifyDetailNone);
48320d2c4d2Smrg    }
48420d2c4d2Smrg    return result;
48520d2c4d2Smrg}
48620d2c4d2Smrg
487956cc18dSsnjconst char *
488e0a2b6dfSmrgvisibleSelectionTarget(Display *d, Atom a)
489956cc18dSsnj{
490956cc18dSsnj    const char *result = "?";
491956cc18dSsnj
492956cc18dSsnj    if (a == XA_STRING) {
493956cc18dSsnj	result = "XA_STRING";
494956cc18dSsnj    } else if (a == XA_TEXT(d)) {
495956cc18dSsnj	result = "XA_TEXT()";
496956cc18dSsnj    } else if (a == XA_COMPOUND_TEXT(d)) {
497956cc18dSsnj	result = "XA_COMPOUND_TEXT()";
498956cc18dSsnj    } else if (a == XA_UTF8_STRING(d)) {
499956cc18dSsnj	result = "XA_UTF8_STRING()";
500956cc18dSsnj    } else if (a == XA_TARGETS(d)) {
501956cc18dSsnj	result = "XA_TARGETS()";
502956cc18dSsnj    }
503956cc18dSsnj
504956cc18dSsnj    return result;
505956cc18dSsnj}
506956cc18dSsnj
5075307cd1aSmrg#if OPT_TEK4014
5082e4f8982Smrgconst char *
5092e4f8982SmrgvisibleTekparse(int code)
5102e4f8982Smrg{
5112e4f8982Smrg    static const struct {
5122e4f8982Smrg	int code;
5132e4f8982Smrg	const char *name;
5142e4f8982Smrg    } table[] = {
5152e4f8982Smrg#include "Tekparse.cin"
5162e4f8982Smrg    };
5172e4f8982Smrg    const char *result = "?";
5182e4f8982Smrg    Cardinal n;
5192e4f8982Smrg    for (n = 0; n < XtNumber(table); ++n) {
5202e4f8982Smrg	if (table[n].code == code) {
5212e4f8982Smrg	    result = table[n].name;
5222e4f8982Smrg	    break;
5232e4f8982Smrg	}
5242e4f8982Smrg    }
5252e4f8982Smrg    return result;
5262e4f8982Smrg}
5275307cd1aSmrg#endif
5282e4f8982Smrg
5292e4f8982Smrgconst char *
5302e4f8982SmrgvisibleVTparse(int code)
5312e4f8982Smrg{
5322e4f8982Smrg    static const struct {
5332e4f8982Smrg	int code;
5342e4f8982Smrg	const char *name;
5352e4f8982Smrg    } table[] = {
5362e4f8982Smrg#include "VTparse.cin"
5372e4f8982Smrg    };
5382e4f8982Smrg    const char *result = "?";
5392e4f8982Smrg    Cardinal n;
5402e4f8982Smrg    for (n = 0; n < XtNumber(table); ++n) {
5412e4f8982Smrg	if (table[n].code == code) {
5422e4f8982Smrg	    result = table[n].name;
5432e4f8982Smrg	    break;
5442e4f8982Smrg	}
5452e4f8982Smrg    }
5462e4f8982Smrg    return result;
5472e4f8982Smrg}
5482e4f8982Smrg
549d522f475Smrgconst char *
550d522f475SmrgvisibleXError(int code)
551d522f475Smrg{
552d522f475Smrg    static char temp[80];
553d522f475Smrg    const char *result = "?";
554d522f475Smrg    switch (code) {
555d522f475Smrg	CASETYPE(Success);
556d522f475Smrg	CASETYPE(BadRequest);
557d522f475Smrg	CASETYPE(BadValue);
558d522f475Smrg	CASETYPE(BadWindow);
559d522f475Smrg	CASETYPE(BadPixmap);
560d522f475Smrg	CASETYPE(BadAtom);
561d522f475Smrg	CASETYPE(BadCursor);
562d522f475Smrg	CASETYPE(BadFont);
563d522f475Smrg	CASETYPE(BadMatch);
564d522f475Smrg	CASETYPE(BadDrawable);
565d522f475Smrg	CASETYPE(BadAccess);
566d522f475Smrg	CASETYPE(BadAlloc);
567d522f475Smrg	CASETYPE(BadColor);
568d522f475Smrg	CASETYPE(BadGC);
569d522f475Smrg	CASETYPE(BadIDChoice);
570d522f475Smrg	CASETYPE(BadName);
571d522f475Smrg	CASETYPE(BadLength);
572d522f475Smrg	CASETYPE(BadImplementation);
573d522f475Smrg    default:
574d522f475Smrg	sprintf(temp, "%d", code);
575d522f475Smrg	result = temp;
576d522f475Smrg	break;
577d522f475Smrg    }
578d522f475Smrg    return result;
579d522f475Smrg}
580d522f475Smrg
581d522f475Smrg#if OPT_TRACE_FLAGS
582d522f475Smrg#define isScrnFlag(flag) ((flag) == LINEWRAPPED)
583d522f475Smrg
584d522f475Smrgstatic char *
585e0a2b6dfSmrgScrnText(LineData *ld)
586d522f475Smrg{
587956cc18dSsnj    return visibleIChars(ld->charData, ld->lineSize);
588d522f475Smrg}
589d522f475Smrg
590956cc18dSsnj#define SHOW_BAD_LINE(name, ld) \
591956cc18dSsnj	Trace("OOPS " #name " bad row\n")
592d522f475Smrg
593d522f475Smrg#define SHOW_SCRN_FLAG(name,code) \
594956cc18dSsnj	Trace(#name " %s:%s\n", \
595d522f475Smrg	      code ? "*" : "", \
596956cc18dSsnj	      ScrnText(ld))
597d522f475Smrg
598d522f475Smrgvoid
599e0a2b6dfSmrgLineClrFlag(LineData *ld, int flag)
600d522f475Smrg{
601956cc18dSsnj    if (ld == 0) {
602956cc18dSsnj	SHOW_BAD_LINE(LineClrFlag, ld);
603d522f475Smrg	assert(0);
604d522f475Smrg    } else if (isScrnFlag(flag)) {
605956cc18dSsnj	SHOW_SCRN_FLAG(LineClrFlag, 0);
606d522f475Smrg    }
607d522f475Smrg
608956cc18dSsnj    LineFlags(ld) &= ~flag;
609d522f475Smrg}
610d522f475Smrg
611d522f475Smrgvoid
612e0a2b6dfSmrgLineSetFlag(LineData *ld, int flag)
613d522f475Smrg{
614956cc18dSsnj    if (ld == 0) {
615956cc18dSsnj	SHOW_BAD_LINE(LineSetFlag, ld);
616d522f475Smrg	assert(0);
617d522f475Smrg    } else if (isScrnFlag(flag)) {
618956cc18dSsnj	SHOW_SCRN_FLAG(LineSetFlag, 1);
619d522f475Smrg    }
620d522f475Smrg
621956cc18dSsnj    LineFlags(ld) |= flag;
622d522f475Smrg}
623d522f475Smrg
624d522f475Smrgint
625956cc18dSsnjLineTstFlag(LineData ld, int flag)
626d522f475Smrg{
627d522f475Smrg    int code = 0;
628956cc18dSsnj    if (ld == 0) {
629956cc18dSsnj	SHOW_BAD_LINE(LineTstFlag, ld);
630d522f475Smrg    } else {
631956cc18dSsnj	code = LineFlags(ld);
632956cc18dSsnj
633956cc18dSsnj	if (isScrnFlag(flag)) {
634956cc18dSsnj	    SHOW_SCRN_FLAG(LineTstFlag, code);
635d522f475Smrg	}
636d522f475Smrg    }
637d522f475Smrg    return code;
638d522f475Smrg}
639d522f475Smrg#endif /* OPT_TRACE_FLAGS */
640d522f475Smrg
641913cc679Smrgconst char *
642913cc679SmrgTraceAtomName(Display *dpy, Atom atom)
643913cc679Smrg{
644913cc679Smrg    static char *result;
645913cc679Smrg    free(result);
646f2e35a3aSmrg    if (atom != 0) {
647f2e35a3aSmrg	result = XGetAtomName(dpy, atom);
648f2e35a3aSmrg    } else {
649f2e35a3aSmrg	result = x_strdup("NONE");
650f2e35a3aSmrg    }
651913cc679Smrg    return result;
652913cc679Smrg}
653913cc679Smrg
6540bd37d32Smrg/*
6550bd37d32Smrg * Trace the normal or alternate screen, showing color values up to 16, e.g.,
6560bd37d32Smrg * for debugging with vttest.
6570bd37d32Smrg */
6580bd37d32Smrgvoid
6590bd37d32SmrgTraceScreen(XtermWidget xw, int whichBuf)
6600bd37d32Smrg{
6610bd37d32Smrg    TScreen *screen = TScreenOf(xw);
6620bd37d32Smrg
6630bd37d32Smrg    if (screen->editBuf_index[whichBuf]) {
6642e4f8982Smrg	int row;
6652e4f8982Smrg
6660bd37d32Smrg	TRACE(("TraceScreen %d:\n", whichBuf));
6674419d26bSmrg	for (row = 0; row <= LastRowNumber(screen); ++row) {
6680bd37d32Smrg	    LineData *ld = getLineData(screen, row);
6692e4f8982Smrg
6700bd37d32Smrg	    TRACE((" %3d:", row));
6710bd37d32Smrg	    if (ld != 0) {
6722e4f8982Smrg		int col;
6732e4f8982Smrg
6740bd37d32Smrg		for (col = 0; col < ld->lineSize; ++col) {
6750bd37d32Smrg		    int ch = (int) ld->charData[col];
6760bd37d32Smrg		    if (ch < ' ')
6770bd37d32Smrg			ch = ' ';
6780bd37d32Smrg		    if (ch >= 127)
6790bd37d32Smrg			ch = '#';
6800bd37d32Smrg		    TRACE(("%c", ch));
6810bd37d32Smrg		}
6820bd37d32Smrg		TRACE((":\n"));
6830bd37d32Smrg
684f2e35a3aSmrg#if 0
6850bd37d32Smrg		TRACE(("  xx:"));
6860bd37d32Smrg		for (col = 0; col < ld->lineSize; ++col) {
6870bd37d32Smrg		    unsigned attrs = ld->attribs[col];
6880bd37d32Smrg		    char ch;
6890bd37d32Smrg		    if (attrs & PROTECTED) {
6900bd37d32Smrg			ch = '*';
6910bd37d32Smrg		    } else if (attrs & BLINK) {
6920bd37d32Smrg			ch = 'B';
6930bd37d32Smrg		    } else if (attrs & CHARDRAWN) {
6940bd37d32Smrg			ch = '+';
6950bd37d32Smrg		    } else {
6960bd37d32Smrg			ch = ' ';
6970bd37d32Smrg		    }
6980bd37d32Smrg		    TRACE(("%c", ch));
6990bd37d32Smrg		}
7000bd37d32Smrg		TRACE((":\n"));
701f2e35a3aSmrg#endif
7020bd37d32Smrg
7030bd37d32Smrg#if 0
7040bd37d32Smrg		TRACE(("  fg:"));
7050bd37d32Smrg		for (col = 0; col < ld->lineSize; ++col) {
7060bd37d32Smrg		    unsigned fg = extract_fg(xw, ld->color[col], ld->attribs[col]);
7070bd37d32Smrg		    if (fg > 15)
7080bd37d32Smrg			fg = 15;
7090bd37d32Smrg		    TRACE(("%1x", fg));
7100bd37d32Smrg		}
7110bd37d32Smrg		TRACE((":\n"));
7120bd37d32Smrg
7130bd37d32Smrg		TRACE(("  bg:"));
7140bd37d32Smrg		for (col = 0; col < ld->lineSize; ++col) {
7150bd37d32Smrg		    unsigned bg = extract_bg(xw, ld->color[col], ld->attribs[col]);
7160bd37d32Smrg		    if (bg > 15)
7170bd37d32Smrg			bg = 15;
7180bd37d32Smrg		    TRACE(("%1x", bg));
7190bd37d32Smrg		}
7200bd37d32Smrg		TRACE((":\n"));
7210bd37d32Smrg#endif
7220bd37d32Smrg	    } else {
7230bd37d32Smrg		TRACE(("null lineData\n"));
7240bd37d32Smrg	    }
7250bd37d32Smrg	}
7260bd37d32Smrg    } else {
7270bd37d32Smrg	TRACE(("TraceScreen %d is nil\n", whichBuf));
7280bd37d32Smrg    }
7290bd37d32Smrg}
7300bd37d32Smrg
731f2e35a3aSmrgstatic char *
732f2e35a3aSmrgformatEventMask(char *target, unsigned source, Boolean buttons)
733f2e35a3aSmrg{
734f2e35a3aSmrg#define DATA(name) { name ## Mask, #name }
735f2e35a3aSmrg    static struct {
736f2e35a3aSmrg	unsigned mask;
737f2e35a3aSmrg	const char *name;
738f2e35a3aSmrg    } table[] = {
739f2e35a3aSmrg	DATA(Shift),
740f2e35a3aSmrg	    DATA(Lock),
741f2e35a3aSmrg	    DATA(Control),
742f2e35a3aSmrg	    DATA(Mod1),
743f2e35a3aSmrg	    DATA(Mod2),
744f2e35a3aSmrg	    DATA(Mod3),
745f2e35a3aSmrg	    DATA(Mod4),
746f2e35a3aSmrg	    DATA(Mod5),
747f2e35a3aSmrg	    DATA(Button1),
748f2e35a3aSmrg	    DATA(Button2),
749f2e35a3aSmrg	    DATA(Button3),
750f2e35a3aSmrg	    DATA(Button4),
751f2e35a3aSmrg	    DATA(Button5),
752f2e35a3aSmrg    };
753f2e35a3aSmrg#undef DATA
754f2e35a3aSmrg    Cardinal n;
755f2e35a3aSmrg    char marker = L_CURL;
756f2e35a3aSmrg    char *base = target;
757f2e35a3aSmrg
758f2e35a3aSmrg    for (n = 0; n < XtNumber(table); ++n) {
759f2e35a3aSmrg	if (!buttons && (table[n].mask >= Button1Mask))
760f2e35a3aSmrg	    continue;
761f2e35a3aSmrg	if ((table[n].mask & source)) {
762f2e35a3aSmrg	    UIntClr(source, table[n].mask);
763f2e35a3aSmrg	    sprintf(target, "%c%s", marker, table[n].name);
764f2e35a3aSmrg	    target += strlen(target);
765f2e35a3aSmrg	    marker = '|';
766f2e35a3aSmrg	}
767f2e35a3aSmrg    }
768f2e35a3aSmrg
769f2e35a3aSmrg    if (source != 0) {
770f2e35a3aSmrg	sprintf(target, "%c?%#x", marker, source);
771f2e35a3aSmrg	target += strlen(target);
772f2e35a3aSmrg	marker = '|';
773f2e35a3aSmrg    }
774f2e35a3aSmrg
775f2e35a3aSmrg    if (marker == L_CURL)
776f2e35a3aSmrg	*target++ = L_CURL;
777f2e35a3aSmrg    *target++ = R_CURL;
778f2e35a3aSmrg
779f2e35a3aSmrg    *target = '\0';
780f2e35a3aSmrg    return base;
781f2e35a3aSmrg}
782f2e35a3aSmrg
783f2e35a3aSmrgvoid
784f2e35a3aSmrgTraceEvent(const char *tag, XEvent *ev, String *params, Cardinal *num_params)
785f2e35a3aSmrg{
786f2e35a3aSmrg    char mask_buffer[160];
787f2e35a3aSmrg
788f2e35a3aSmrg    TRACE(("Event #%lu %s: %#lx %s",
789f2e35a3aSmrg	   ev->xany.serial,
790f2e35a3aSmrg	   tag,
791f2e35a3aSmrg	   ev->xany.window,
792f2e35a3aSmrg	   visibleEventType(ev->type)));
793f2e35a3aSmrg
794f2e35a3aSmrg    switch (ev->type) {
795f2e35a3aSmrg    case KeyPress:
796f2e35a3aSmrg	/* FALLTHRU */
797f2e35a3aSmrg    case KeyRelease:
798f2e35a3aSmrg	TRACE((" keycode 0x%04X %s",
799f2e35a3aSmrg	       ev->xkey.keycode,
800f2e35a3aSmrg	       formatEventMask(mask_buffer, ev->xkey.state, False)));
801f2e35a3aSmrg	break;
802f2e35a3aSmrg    case ButtonPress:
803f2e35a3aSmrg	/* FALLTHRU */
804f2e35a3aSmrg    case ButtonRelease:
805f2e35a3aSmrg	TRACE((" button %u state %#x %s",
806f2e35a3aSmrg	       ev->xbutton.button,
807f2e35a3aSmrg	       ev->xbutton.state,
808f2e35a3aSmrg	       formatEventMask(mask_buffer, ev->xbutton.state, True)));
809f2e35a3aSmrg	break;
810f2e35a3aSmrg    case MotionNotify:
811f2e35a3aSmrg	TRACE((" (%d,%d) state %#x %s",
812f2e35a3aSmrg	       ev->xmotion.y_root,
813f2e35a3aSmrg	       ev->xmotion.x_root,
814f2e35a3aSmrg	       ev->xmotion.state,
815f2e35a3aSmrg	       formatEventMask(mask_buffer, ev->xmotion.state, True)));
816f2e35a3aSmrg	break;
817f2e35a3aSmrg    case EnterNotify:
818f2e35a3aSmrg    case LeaveNotify:
819f2e35a3aSmrg	TRACE((" at %d,%d root %d,%d %s %s",
820f2e35a3aSmrg	       ev->xcrossing.y,
821f2e35a3aSmrg	       ev->xcrossing.x,
822f2e35a3aSmrg	       ev->xcrossing.y_root,
823f2e35a3aSmrg	       ev->xcrossing.x_root,
824f2e35a3aSmrg	       visibleNotifyMode(ev->xcrossing.mode),
825f2e35a3aSmrg	       visibleNotifyDetail(ev->xcrossing.detail)));
826f2e35a3aSmrg	break;
827f2e35a3aSmrg    case FocusIn:
828f2e35a3aSmrg    case FocusOut:
829f2e35a3aSmrg	TRACE((" %s %s",
830f2e35a3aSmrg	       visibleNotifyMode(ev->xfocus.mode),
831f2e35a3aSmrg	       visibleNotifyDetail(ev->xfocus.detail)));
832f2e35a3aSmrg	break;
833f2e35a3aSmrg    case MapNotify:
834f2e35a3aSmrg	TRACE((" event %#lx %s",
835f2e35a3aSmrg	       ev->xmap.event,
836f2e35a3aSmrg	       ev->xmap.override_redirect ? "override" : ""));
837f2e35a3aSmrg	break;
838f2e35a3aSmrg    case UnmapNotify:
839f2e35a3aSmrg	TRACE((" event %#lx %s",
840f2e35a3aSmrg	       ev->xunmap.event,
841f2e35a3aSmrg	       ev->xunmap.from_configure ? "configure" : ""));
842f2e35a3aSmrg	break;
843f2e35a3aSmrg    case ReparentNotify:
844f2e35a3aSmrg	TRACE((" at %d,%d event %#lx parent %#lx %s",
845f2e35a3aSmrg	       ev->xreparent.y,
846f2e35a3aSmrg	       ev->xreparent.x,
847f2e35a3aSmrg	       ev->xreparent.event,
848f2e35a3aSmrg	       ev->xreparent.parent,
849f2e35a3aSmrg	       ev->xreparent.override_redirect ? "override" : ""));
850f2e35a3aSmrg	break;
851f2e35a3aSmrg    case ConfigureNotify:
852f2e35a3aSmrg	TRACE((" at %d,%d size %dx%d bd %d above %#lx",
853f2e35a3aSmrg	       ev->xconfigure.y,
854f2e35a3aSmrg	       ev->xconfigure.x,
855f2e35a3aSmrg	       ev->xconfigure.height,
856f2e35a3aSmrg	       ev->xconfigure.width,
857f2e35a3aSmrg	       ev->xconfigure.border_width,
858f2e35a3aSmrg	       ev->xconfigure.above));
859f2e35a3aSmrg	break;
860f2e35a3aSmrg    case CreateNotify:
861f2e35a3aSmrg	TRACE((" at %d,%d size %dx%d bd %d",
862f2e35a3aSmrg	       ev->xcreatewindow.y,
863f2e35a3aSmrg	       ev->xcreatewindow.x,
864f2e35a3aSmrg	       ev->xcreatewindow.height,
865f2e35a3aSmrg	       ev->xcreatewindow.width,
866f2e35a3aSmrg	       ev->xcreatewindow.border_width));
867f2e35a3aSmrg	break;
868f2e35a3aSmrg    case ResizeRequest:
869f2e35a3aSmrg	TRACE((" size %dx%d",
870f2e35a3aSmrg	       ev->xresizerequest.height,
871f2e35a3aSmrg	       ev->xresizerequest.width));
872f2e35a3aSmrg	break;
873f2e35a3aSmrg    case PropertyNotify:
874f2e35a3aSmrg	TRACE((" %s %s",
875f2e35a3aSmrg	       TraceAtomName(XtDisplay(toplevel), ev->xproperty.atom),
876f2e35a3aSmrg	       ((ev->xproperty.state == PropertyNewValue)
877f2e35a3aSmrg		? "NewValue"
878f2e35a3aSmrg		: ((ev->xproperty.state == PropertyDelete)
879f2e35a3aSmrg		   ? "Delete"
880f2e35a3aSmrg		   : "?"))));
881f2e35a3aSmrg
882f2e35a3aSmrg	break;
883f2e35a3aSmrg    case Expose:
884f2e35a3aSmrg	TRACE((" at %d,%d size %dx%d count %d",
885f2e35a3aSmrg	       ev->xexpose.y,
886f2e35a3aSmrg	       ev->xexpose.x,
887f2e35a3aSmrg	       ev->xexpose.height,
888f2e35a3aSmrg	       ev->xexpose.width,
889f2e35a3aSmrg	       ev->xexpose.count));
890f2e35a3aSmrg	break;
891f2e35a3aSmrg    case MappingNotify:
892f2e35a3aSmrg	TRACE((" %s first_keycode %d count %d",
893f2e35a3aSmrg	       visibleMappingMode(ev->xmapping.request),
894f2e35a3aSmrg	       ev->xmapping.first_keycode,
895f2e35a3aSmrg	       ev->xmapping.count));
896f2e35a3aSmrg	break;
897f2e35a3aSmrg    case VisibilityNotify:
898f2e35a3aSmrg	TRACE((" state %d",
899f2e35a3aSmrg	       ev->xvisibility.state));
900f2e35a3aSmrg	break;
901f2e35a3aSmrg    case KeymapNotify:
902f2e35a3aSmrg	{
903f2e35a3aSmrg	    Cardinal j;
904f2e35a3aSmrg	    for (j = 0; j < XtNumber(ev->xkeymap.key_vector); ++j) {
905f2e35a3aSmrg		if (ev->xkeymap.key_vector[j] != 0) {
906f2e35a3aSmrg		    Cardinal k;
9075307cd1aSmrg		    for (k = 0; k < CHAR_BIT; ++k) {
908f2e35a3aSmrg			if (ev->xkeymap.key_vector[j] & (1 << k)) {
9095307cd1aSmrg			    TRACE((" key%u", (j * CHAR_BIT) + k));
910f2e35a3aSmrg			}
911f2e35a3aSmrg		    }
912f2e35a3aSmrg		}
913f2e35a3aSmrg	    }
914f2e35a3aSmrg	}
915f2e35a3aSmrg	break;
916f2e35a3aSmrg    case NoExpose:
917f2e35a3aSmrg	TRACE((" send_event:%d display %p major:%d minor:%d",
918f2e35a3aSmrg	       ev->xnoexpose.send_event,
919f2e35a3aSmrg	       (void *) ev->xnoexpose.display,
920f2e35a3aSmrg	       ev->xnoexpose.major_code,
921f2e35a3aSmrg	       ev->xnoexpose.minor_code));
922f2e35a3aSmrg	break;
923a5ae21e4Smrg    case GraphicsExpose:
924a5ae21e4Smrg	TRACE((" send_event:%d display %p major:%d minor:%d",
925a5ae21e4Smrg	       ev->xgraphicsexpose.send_event,
926a5ae21e4Smrg	       (void *) ev->xgraphicsexpose.display,
927a5ae21e4Smrg	       ev->xgraphicsexpose.major_code,
928a5ae21e4Smrg	       ev->xgraphicsexpose.minor_code));
929a5ae21e4Smrg	break;
930f2e35a3aSmrg    case SelectionClear:
931f2e35a3aSmrg	TRACE((" selection:%s",
932f2e35a3aSmrg	       TraceAtomName(ev->xselectionclear.display,
933f2e35a3aSmrg			     ev->xselectionclear.selection)));
934f2e35a3aSmrg	break;
935f2e35a3aSmrg    case SelectionRequest:
936f2e35a3aSmrg	TRACE((" owner:%#lx requestor:%#lx",
937f2e35a3aSmrg	       ev->xselectionrequest.owner,
938f2e35a3aSmrg	       ev->xselectionrequest.requestor));
939f2e35a3aSmrg	TRACE((" selection:%s",
940f2e35a3aSmrg	       TraceAtomName(ev->xselectionrequest.display,
941f2e35a3aSmrg			     ev->xselectionrequest.selection)));
942f2e35a3aSmrg	TRACE((" target:%s",
943f2e35a3aSmrg	       TraceAtomName(ev->xselectionrequest.display,
944f2e35a3aSmrg			     ev->xselectionrequest.target)));
945f2e35a3aSmrg	TRACE((" property:%s",
946f2e35a3aSmrg	       TraceAtomName(ev->xselectionrequest.display,
947f2e35a3aSmrg			     ev->xselectionrequest.property)));
948f2e35a3aSmrg	break;
949f2e35a3aSmrg    default:
950f2e35a3aSmrg	TRACE((":FIXME"));
951f2e35a3aSmrg	break;
952f2e35a3aSmrg    }
953f2e35a3aSmrg    TRACE(("\n"));
954f2e35a3aSmrg    if (params != 0 && *num_params != 0) {
955f2e35a3aSmrg	Cardinal n;
956f2e35a3aSmrg	for (n = 0; n < *num_params; ++n) {
957f2e35a3aSmrg	    TRACE(("  param[%d] = %s\n", n, params[n]));
958f2e35a3aSmrg	}
959f2e35a3aSmrg    }
960f2e35a3aSmrg}
961f2e35a3aSmrg
962f2e35a3aSmrg#if OPT_RENDERFONT && OPT_WIDE_CHARS
963f2e35a3aSmrgvoid
964f2e35a3aSmrgTraceFallback(XtermWidget xw, const char *tag, unsigned wc, int n, XftFont *font)
965f2e35a3aSmrg{
966f2e35a3aSmrg    TScreen *screen = TScreenOf(xw);
967f2e35a3aSmrg    XGlyphInfo gi;
968f2e35a3aSmrg    int expect = my_wcwidth((wchar_t) wc);
969f2e35a3aSmrg    int hijack = mk_wcwidth_cjk((wchar_t) wc);
970f2e35a3aSmrg    int actual;
971f2e35a3aSmrg
972f2e35a3aSmrg    XftTextExtents32(screen->display, font, &wc, 1, &gi);
973f2e35a3aSmrg    actual = ((gi.xOff + FontWidth(screen) - 1)
974f2e35a3aSmrg	      / FontWidth(screen));
975f2e35a3aSmrg
976f2e35a3aSmrg    TRACE(("FALLBACK #%d %s U+%04X %d,%d pos,"
977f2e35a3aSmrg	   " %d,%d off," " %dx%d size,"
978f2e35a3aSmrg	   " %d/%d next," " %d vs %d/%d cells%s\n",
979f2e35a3aSmrg	   n + 1, tag, wc,
980f2e35a3aSmrg	   gi.y, gi.x,
981f2e35a3aSmrg	   gi.yOff, gi.xOff,
982f2e35a3aSmrg	   gi.height, gi.width,
983f2e35a3aSmrg	   font->max_advance_width,
984f2e35a3aSmrg	   FontWidth(screen),
985f2e35a3aSmrg	   actual, expect, hijack,
986f2e35a3aSmrg	   ((actual != expect)
987f2e35a3aSmrg	    ? ((actual == hijack)
988f2e35a3aSmrg	       ? " OOPS"
989f2e35a3aSmrg	       : " oops")
990f2e35a3aSmrg	    : "")));
991f2e35a3aSmrg}
992f2e35a3aSmrg#endif /* OPT_RENDERFONT */
993f2e35a3aSmrg
99420d2c4d2Smrgvoid
99501037d57SmrgTraceFocus(Widget w, XEvent *ev)
99620d2c4d2Smrg{
99720d2c4d2Smrg    TRACE(("trace_focus event type %d:%s\n",
99820d2c4d2Smrg	   ev->type, visibleEventType(ev->type)));
99920d2c4d2Smrg    switch (ev->type) {
100020d2c4d2Smrg    case FocusIn:
100120d2c4d2Smrg    case FocusOut:
100220d2c4d2Smrg	{
100320d2c4d2Smrg	    XFocusChangeEvent *event = (XFocusChangeEvent *) ev;
100420d2c4d2Smrg	    TRACE(("\tdetail: %s\n", visibleNotifyDetail(event->detail)));
10050bd37d32Smrg	    TRACE(("\tmode:   %s\n", visibleNotifyMode(event->mode)));
100620d2c4d2Smrg	    TRACE(("\twindow: %#lx\n", event->window));
100720d2c4d2Smrg	}
100820d2c4d2Smrg	break;
100920d2c4d2Smrg    case EnterNotify:
101020d2c4d2Smrg    case LeaveNotify:
101120d2c4d2Smrg	{
101220d2c4d2Smrg	    XCrossingEvent *event = (XCrossingEvent *) ev;
101320d2c4d2Smrg	    TRACE(("\tdetail:    %s\n", visibleNotifyDetail(event->detail)));
10140bd37d32Smrg	    TRACE(("\tmode:      %s\n", visibleNotifyMode(event->mode)));
101520d2c4d2Smrg	    TRACE(("\twindow:    %#lx\n", event->window));
1016e39b573cSmrg	    TRACE(("\tfocus:     %d\n", event->focus));
101720d2c4d2Smrg	    TRACE(("\troot:      %#lx\n", event->root));
101820d2c4d2Smrg	    TRACE(("\tsubwindow: %#lx\n", event->subwindow));
101920d2c4d2Smrg	}
102020d2c4d2Smrg	break;
102120d2c4d2Smrg    }
102220d2c4d2Smrg    while (w != 0) {
102320d2c4d2Smrg	TRACE(("w %p -> %#lx\n", (void *) w, XtWindow(w)));
102420d2c4d2Smrg	w = XtParent(w);
102520d2c4d2Smrg    }
102620d2c4d2Smrg}
102720d2c4d2Smrg
1028d522f475Smrgvoid
1029d522f475SmrgTraceSizeHints(XSizeHints * hints)
1030d522f475Smrg{
1031d522f475Smrg    TRACE(("size hints:\n"));
1032f2e35a3aSmrg    if (hints->flags & (USPosition | PPosition)) {
1033d522f475Smrg	TRACE(("   position   %d,%d%s%s\n", hints->y, hints->x,
10342e4f8982Smrg	       (hints->flags & USPosition) ? " user" : "",
10352e4f8982Smrg	       (hints->flags & PPosition) ? " prog" : ""));
1036f2e35a3aSmrg    }
1037f2e35a3aSmrg    if (hints->flags & (USSize | PSize)) {
1038d522f475Smrg	TRACE(("   size       %d,%d%s%s\n", hints->height, hints->width,
10392e4f8982Smrg	       (hints->flags & USSize) ? " user" : "",
10402e4f8982Smrg	       (hints->flags & PSize) ? " prog" : ""));
1041f2e35a3aSmrg    }
1042f2e35a3aSmrg    if (hints->flags & PMinSize) {
1043d522f475Smrg	TRACE(("   min        %d,%d\n", hints->min_height, hints->min_width));
1044f2e35a3aSmrg    }
1045f2e35a3aSmrg    if (hints->flags & PMaxSize) {
1046d522f475Smrg	TRACE(("   max        %d,%d\n", hints->max_height, hints->max_width));
1047f2e35a3aSmrg    }
1048f2e35a3aSmrg    if (hints->flags & PResizeInc) {
1049d522f475Smrg	TRACE(("   inc        %d,%d\n", hints->height_inc, hints->width_inc));
1050f2e35a3aSmrg    } else {
10512eaa94a1Schristos	TRACE(("   inc        NONE!\n"));
1052f2e35a3aSmrg    }
1053f2e35a3aSmrg    if (hints->flags & PAspect) {
1054d522f475Smrg	TRACE(("   min aspect %d/%d\n", hints->min_aspect.y, hints->min_aspect.y));
1055d522f475Smrg	TRACE(("   max aspect %d/%d\n", hints->max_aspect.y, hints->max_aspect.y));
1056f2e35a3aSmrg    }
1057f2e35a3aSmrg    if (hints->flags & PBaseSize) {
1058d522f475Smrg	TRACE(("   base       %d,%d\n", hints->base_height, hints->base_width));
1059f2e35a3aSmrg    }
1060f2e35a3aSmrg    if (hints->flags & PWinGravity) {
1061d522f475Smrg	TRACE(("   gravity    %d\n", hints->win_gravity));
1062f2e35a3aSmrg    }
1063d522f475Smrg}
1064d522f475Smrg
10650bd37d32Smrgstatic void
10660bd37d32SmrgTraceEventMask(const char *tag, long mask)
10670bd37d32Smrg{
10680bd37d32Smrg#define DATA(name) { name##Mask, #name }
10690bd37d32Smrg    /* *INDENT-OFF* */
10700bd37d32Smrg    static struct {
10710bd37d32Smrg	long mask;
10720bd37d32Smrg	const char *name;
10730bd37d32Smrg    } table[] = {
10740bd37d32Smrg	DATA(KeyPress),
10750bd37d32Smrg	DATA(KeyRelease),
10760bd37d32Smrg	DATA(ButtonPress),
10770bd37d32Smrg	DATA(ButtonRelease),
10780bd37d32Smrg	DATA(EnterWindow),
10790bd37d32Smrg	DATA(LeaveWindow),
10800bd37d32Smrg	DATA(PointerMotion),
10810bd37d32Smrg	DATA(PointerMotionHint),
10820bd37d32Smrg	DATA(Button1Motion),
10830bd37d32Smrg	DATA(Button2Motion),
10840bd37d32Smrg	DATA(Button3Motion),
10850bd37d32Smrg	DATA(Button4Motion),
10860bd37d32Smrg	DATA(Button5Motion),
10870bd37d32Smrg	DATA(ButtonMotion),
10880bd37d32Smrg	DATA(KeymapState),
10890bd37d32Smrg	DATA(Exposure),
10900bd37d32Smrg	DATA(VisibilityChange),
10910bd37d32Smrg	DATA(StructureNotify),
10920bd37d32Smrg	DATA(ResizeRedirect),
10930bd37d32Smrg	DATA(SubstructureNotify),
10940bd37d32Smrg	DATA(SubstructureRedirect),
10950bd37d32Smrg	DATA(FocusChange),
10960bd37d32Smrg	DATA(PropertyChange),
10970bd37d32Smrg	DATA(ColormapChange),
10980bd37d32Smrg	DATA(OwnerGrabButton),
10990bd37d32Smrg    };
11000bd37d32Smrg#undef DATA
11010bd37d32Smrg    Cardinal n;
11020bd37d32Smrg    /* *INDENT-ON* */
11030bd37d32Smrg
11040bd37d32Smrg    for (n = 0; n < XtNumber(table); ++n) {
11050bd37d32Smrg	if (table[n].mask & mask) {
11060bd37d32Smrg	    TRACE(("%s %s\n", tag, table[n].name));
11070bd37d32Smrg	}
11080bd37d32Smrg    }
11090bd37d32Smrg}
11100bd37d32Smrg
11110bd37d32Smrgvoid
11120bd37d32SmrgTraceWindowAttributes(XWindowAttributes * attrs)
11130bd37d32Smrg{
11140bd37d32Smrg    TRACE(("window attributes:\n"));
11150bd37d32Smrg    TRACE(("   position     %d,%d\n", attrs->y, attrs->x));
11160bd37d32Smrg    TRACE(("   size         %dx%d\n", attrs->height, attrs->width));
11170bd37d32Smrg    TRACE(("   border       %d\n", attrs->border_width));
11180bd37d32Smrg    TRACE(("   depth        %d\n", attrs->depth));
11190bd37d32Smrg    TRACE(("   bit_gravity  %d\n", attrs->bit_gravity));
11200bd37d32Smrg    TRACE(("   win_gravity  %d\n", attrs->win_gravity));
11210bd37d32Smrg    TRACE(("   root         %#lx\n", (long) attrs->root));
11220bd37d32Smrg    TRACE(("   class        %s\n", ((attrs->class == InputOutput)
11230bd37d32Smrg				    ? "InputOutput"
11240bd37d32Smrg				    : ((attrs->class == InputOnly)
11250bd37d32Smrg				       ? "InputOnly"
11260bd37d32Smrg				       : "unknown"))));
11270bd37d32Smrg    TRACE(("   map_state    %s\n", ((attrs->map_state == IsUnmapped)
11280bd37d32Smrg				    ? "IsUnmapped"
11290bd37d32Smrg				    : ((attrs->map_state == IsUnviewable)
11300bd37d32Smrg				       ? "IsUnviewable"
11310bd37d32Smrg				       : ((attrs->map_state == IsViewable)
11320bd37d32Smrg					  ? "IsViewable"
11330bd37d32Smrg					  : "unknown")))));
11340bd37d32Smrg    TRACE(("   all_events\n"));
11350bd37d32Smrg    TraceEventMask("        ", attrs->all_event_masks);
11360bd37d32Smrg    TRACE(("   your_events\n"));
11370bd37d32Smrg    TraceEventMask("        ", attrs->your_event_mask);
11380bd37d32Smrg    TRACE(("   no_propagate\n"));
11390bd37d32Smrg    TraceEventMask("        ", attrs->do_not_propagate_mask);
11400bd37d32Smrg}
11410bd37d32Smrg
1142d522f475Smrgvoid
1143d522f475SmrgTraceWMSizeHints(XtermWidget xw)
1144d522f475Smrg{
1145d522f475Smrg    XSizeHints sizehints = xw->hints;
1146d522f475Smrg
1147d522f475Smrg    getXtermSizeHints(xw);
1148d522f475Smrg    TraceSizeHints(&xw->hints);
1149d522f475Smrg    xw->hints = sizehints;
1150d522f475Smrg}
1151d522f475Smrg
11520bd37d32Smrgconst char *
11530bd37d32SmrgModifierName(unsigned modifier)
11540bd37d32Smrg{
11550bd37d32Smrg    const char *s = "";
11560bd37d32Smrg    if (modifier & ShiftMask)
11570bd37d32Smrg	s = " Shift";
11580bd37d32Smrg    else if (modifier & LockMask)
11590bd37d32Smrg	s = " Lock";
11600bd37d32Smrg    else if (modifier & ControlMask)
11610bd37d32Smrg	s = " Control";
11620bd37d32Smrg    else if (modifier & Mod1Mask)
11630bd37d32Smrg	s = " Mod1";
11640bd37d32Smrg    else if (modifier & Mod2Mask)
11650bd37d32Smrg	s = " Mod2";
11660bd37d32Smrg    else if (modifier & Mod3Mask)
11670bd37d32Smrg	s = " Mod3";
11680bd37d32Smrg    else if (modifier & Mod4Mask)
11690bd37d32Smrg	s = " Mod4";
11700bd37d32Smrg    else if (modifier & Mod5Mask)
11710bd37d32Smrg	s = " Mod5";
11720bd37d32Smrg    return s;
11730bd37d32Smrg}
11740bd37d32Smrg
1175d522f475Smrgvoid
1176d522f475SmrgTraceTranslations(const char *name, Widget w)
1177d522f475Smrg{
1178d522f475Smrg    String result;
1179f2e35a3aSmrg    XErrorHandler save = XSetErrorHandler(ignore_x11_error);
1180d522f475Smrg    XtTranslations xlations;
1181d522f475Smrg    Widget xcelerat;
1182d522f475Smrg
1183f2e35a3aSmrg    TRACE(("TraceTranslations for %s (widget %#lx) " TRACE_L "\n",
1184f2e35a3aSmrg	   name, (long) w));
1185d522f475Smrg    if (w) {
1186d522f475Smrg	XtVaGetValues(w,
1187d522f475Smrg		      XtNtranslations, &xlations,
1188d522f475Smrg		      XtNaccelerators, &xcelerat,
1189d522f475Smrg		      (XtPointer) 0);
1190d522f475Smrg	TRACE(("... xlations %#08lx\n", (long) xlations));
1191d522f475Smrg	TRACE(("... xcelerat %#08lx\n", (long) xcelerat));
1192d522f475Smrg	result = _XtPrintXlations(w, xlations, xcelerat, True);
119320d2c4d2Smrg	TRACE(("%s\n", NonNull(result)));
1194d522f475Smrg	if (result)
119520d2c4d2Smrg	    XFree((char *) result);
1196d522f475Smrg    } else {
1197d522f475Smrg	TRACE(("none (widget is null)\n"));
1198d522f475Smrg    }
1199f2e35a3aSmrg    TRACE((TRACE_R "\n"));
1200d522f475Smrg    XSetErrorHandler(save);
1201d522f475Smrg}
1202d522f475Smrg
12030bd37d32SmrgXtGeometryResult
12042eaa94a1SchristosTraceResizeRequest(const char *fn, int ln, Widget w,
1205e39b573cSmrg		   unsigned reqwide,
1206e39b573cSmrg		   unsigned reqhigh,
1207e0a2b6dfSmrg		   Dimension *gotwide,
1208e0a2b6dfSmrg		   Dimension *gothigh)
12092eaa94a1Schristos{
12100bd37d32Smrg    XtGeometryResult rc;
12112eaa94a1Schristos
1212e39b573cSmrg    TRACE(("%s@%d ResizeRequest %ux%u\n", fn, ln, reqhigh, reqwide));
12130bd37d32Smrg    rc = XtMakeResizeRequest((Widget) w,
12140bd37d32Smrg			     (Dimension) reqwide,
12150bd37d32Smrg			     (Dimension) reqhigh,
12160bd37d32Smrg			     gotwide, gothigh);
12172eaa94a1Schristos    TRACE(("... ResizeRequest -> "));
12182eaa94a1Schristos    if (gothigh && gotwide)
12192eaa94a1Schristos	TRACE(("%dx%d ", *gothigh, *gotwide));
12202eaa94a1Schristos    TRACE(("(%d)\n", rc));
12212eaa94a1Schristos    return rc;
12222eaa94a1Schristos}
12232eaa94a1Schristos
1224d522f475Smrg#define XRES_S(name) Trace(#name " = %s\n", NonNull(resp->name))
122501037d57Smrg#define XRES_B(name) Trace(#name " = %s\n", MtoS(resp->name))
1226d522f475Smrg#define XRES_I(name) Trace(#name " = %d\n", resp->name)
1227d522f475Smrg
1228d522f475Smrgvoid
1229d522f475SmrgTraceXtermResources(void)
1230d522f475Smrg{
1231d522f475Smrg    XTERM_RESOURCE *resp = &resource;
1232d522f475Smrg
1233d522f475Smrg    Trace("XTERM_RESOURCE settings:\n");
1234d522f475Smrg    XRES_S(icon_geometry);
1235d522f475Smrg    XRES_S(title);
12360bd37d32Smrg    XRES_S(icon_hint);
1237d522f475Smrg    XRES_S(icon_name);
1238d522f475Smrg    XRES_S(term_name);
1239d522f475Smrg    XRES_S(tty_modes);
1240e39b573cSmrg    XRES_I(minBufSize);
1241e39b573cSmrg    XRES_I(maxBufSize);
1242d522f475Smrg    XRES_B(hold_screen);
1243d522f475Smrg    XRES_B(utmpInhibit);
1244d522f475Smrg    XRES_B(utmpDisplayId);
1245d522f475Smrg    XRES_B(messages);
1246e39b573cSmrg    XRES_S(menuLocale);
1247e39b573cSmrg    XRES_S(omitTranslation);
1248e39b573cSmrg    XRES_S(keyboardType);
1249ad37e533Smrg#ifdef HAVE_LIB_XCURSOR
1250ad37e533Smrg    XRES_S(cursorTheme);
1251ad37e533Smrg#endif
1252e39b573cSmrg#if OPT_PRINT_ON_EXIT
1253e39b573cSmrg    XRES_I(printModeNow);
1254e39b573cSmrg    XRES_I(printModeOnXError);
1255e39b573cSmrg    XRES_I(printOptsNow);
1256e39b573cSmrg    XRES_I(printOptsOnXError);
1257e39b573cSmrg    XRES_S(printFileNow);
1258e39b573cSmrg    XRES_S(printFileOnXError);
1259e39b573cSmrg#endif
1260d522f475Smrg#if OPT_SUNPC_KBD
1261d522f475Smrg    XRES_B(sunKeyboard);
1262d522f475Smrg#endif
1263d522f475Smrg#if OPT_HP_FUNC_KEYS
1264d522f475Smrg    XRES_B(hpFunctionKeys);
1265d522f475Smrg#endif
1266d522f475Smrg#if OPT_SCO_FUNC_KEYS
1267d522f475Smrg    XRES_B(scoFunctionKeys);
1268d522f475Smrg#endif
1269d522f475Smrg#if OPT_SUN_FUNC_KEYS
1270d522f475Smrg    XRES_B(sunFunctionKeys);
1271d522f475Smrg#endif
1272d522f475Smrg#if OPT_INITIAL_ERASE
1273d522f475Smrg    XRES_B(ptyInitialErase);
1274d522f475Smrg    XRES_B(backarrow_is_erase);
1275d522f475Smrg#endif
1276d522f475Smrg    XRES_B(useInsertMode);
1277d522f475Smrg#if OPT_ZICONBEEP
1278d522f475Smrg    XRES_I(zIconBeep);
12790bd37d32Smrg    XRES_S(zIconFormat);
1280d522f475Smrg#endif
1281d522f475Smrg#if OPT_PTY_HANDSHAKE
1282d522f475Smrg    XRES_B(wait_for_map);
1283d522f475Smrg    XRES_B(ptyHandshake);
1284d522f475Smrg    XRES_B(ptySttySize);
1285d522f475Smrg#endif
1286913cc679Smrg#if OPT_REPORT_CCLASS
1287913cc679Smrg    XRES_B(reportCClass);
1288913cc679Smrg#endif
1289e0a2b6dfSmrg#if OPT_REPORT_COLORS
1290e0a2b6dfSmrg    XRES_B(reportColors);
1291e0a2b6dfSmrg#endif
1292e0a2b6dfSmrg#if OPT_REPORT_FONTS
1293e0a2b6dfSmrg    XRES_B(reportFonts);
1294e0a2b6dfSmrg#endif
1295f2e35a3aSmrg#if OPT_REPORT_ICONS
1296f2e35a3aSmrg    XRES_B(reportIcons);
1297f2e35a3aSmrg#endif
1298d522f475Smrg#if OPT_SAME_NAME
1299d522f475Smrg    XRES_B(sameName);
1300d522f475Smrg#endif
1301d522f475Smrg#if OPT_SESSION_MGT
1302d522f475Smrg    XRES_B(sessionMgt);
1303d522f475Smrg#endif
1304a1f3da82Smrg#if OPT_TOOLBAR
1305a1f3da82Smrg    XRES_B(toolBar);
1306a1f3da82Smrg#endif
1307a1f3da82Smrg#if OPT_MAXIMIZE
1308a1f3da82Smrg    XRES_B(maximized);
1309a1f3da82Smrg    XRES_S(fullscreen_s);
1310a1f3da82Smrg#endif
1311f2e35a3aSmrg#if USE_DOUBLE_BUFFER
1312f2e35a3aSmrg    XRES_B(buffered);
1313f2e35a3aSmrg    XRES_I(buffered_fps);
1314f2e35a3aSmrg#endif
1315d522f475Smrg}
1316d522f475Smrg
1317d522f475Smrgvoid
1318d522f475SmrgTraceArgv(const char *tag, char **argv)
1319d522f475Smrg{
1320d522f475Smrg    TRACE(("%s:\n", tag));
1321913cc679Smrg    if (argv != 0) {
1322913cc679Smrg	int n = 0;
1323913cc679Smrg
1324913cc679Smrg	while (*argv != 0) {
1325913cc679Smrg	    TRACE(("  %d:%s\n", n++, *argv++));
1326913cc679Smrg	}
1327d522f475Smrg    }
1328d522f475Smrg}
1329d522f475Smrg
1330d522f475Smrgstatic char *
133120d2c4d2Smrgparse_option(char *dst, String src, int first)
1332d522f475Smrg{
1333d522f475Smrg    char *s;
1334d522f475Smrg
1335a1f3da82Smrg    if (!strncmp(src, "-/+", (size_t) 3)) {
1336956cc18dSsnj	dst[0] = (char) first;
1337d522f475Smrg	strcpy(dst + 1, src + 3);
1338d522f475Smrg    } else {
1339d522f475Smrg	strcpy(dst, src);
1340d522f475Smrg    }
1341d522f475Smrg    for (s = dst; *s != '\0'; s++) {
1342d522f475Smrg	if (*s == '#' || *s == '%' || *s == 'S') {
1343d522f475Smrg	    s[1] = '\0';
1344d522f475Smrg	} else if (*s == ' ') {
1345d522f475Smrg	    *s = '\0';
1346d522f475Smrg	    break;
1347d522f475Smrg	}
1348d522f475Smrg    }
1349d522f475Smrg    return dst;
1350d522f475Smrg}
1351d522f475Smrg
1352d522f475Smrgstatic Bool
1353d522f475Smrgsame_option(OptionHelp * opt, XrmOptionDescRec * res)
1354d522f475Smrg{
1355d522f475Smrg    char temp[BUFSIZ];
1356d522f475Smrg    return !strcmp(parse_option(temp, opt->opt, res->option[0]), res->option);
1357d522f475Smrg}
1358d522f475Smrg
1359d522f475Smrgstatic Bool
136020d2c4d2Smrgstandard_option(String opt)
1361d522f475Smrg{
1362d522f475Smrg    static const char *table[] =
1363d522f475Smrg    {
1364d522f475Smrg	"+rv",
1365d522f475Smrg	"+synchronous",
1366d522f475Smrg	"-background",
1367d522f475Smrg	"-bd",
1368d522f475Smrg	"-bg",
1369d522f475Smrg	"-bordercolor",
1370d522f475Smrg	"-borderwidth",
1371d522f475Smrg	"-bw",
1372d522f475Smrg	"-display",
1373d522f475Smrg	"-fg",
1374d522f475Smrg	"-fn",
1375d522f475Smrg	"-font",
1376d522f475Smrg	"-foreground",
1377d522f475Smrg	"-geometry",
1378d522f475Smrg	"-iconic",
1379d522f475Smrg	"-name",
1380d522f475Smrg	"-reverse",
1381d522f475Smrg	"-rv",
1382d522f475Smrg	"-selectionTimeout",
1383d522f475Smrg	"-synchronous",
1384d522f475Smrg	"-title",
1385d522f475Smrg	"-xnllanguage",
1386d522f475Smrg	"-xrm",
1387d522f475Smrg	"-xtsessionID",
1388d522f475Smrg    };
1389d522f475Smrg    Cardinal n;
1390d522f475Smrg    char temp[BUFSIZ];
1391d522f475Smrg
1392d522f475Smrg    opt = parse_option(temp, opt, '-');
1393d522f475Smrg    for (n = 0; n < XtNumber(table); n++) {
1394d522f475Smrg	if (!strcmp(opt, table[n]))
1395d522f475Smrg	    return True;
1396d522f475Smrg    }
1397d522f475Smrg    return False;
1398d522f475Smrg}
1399d522f475Smrg
1400d522f475Smrg/*
1401d522f475Smrg * Analyse the options/help messages for inconsistencies.
1402d522f475Smrg */
1403d522f475Smrgvoid
1404d522f475SmrgTraceOptions(OptionHelp * options, XrmOptionDescRec * resources, Cardinal res_count)
1405d522f475Smrg{
1406d522f475Smrg    OptionHelp *opt_array = sortedOpts(options, resources, res_count);
1407d522f475Smrg    size_t j, k;
1408d522f475Smrg    XrmOptionDescRec *res_array = sortedOptDescs(resources, res_count);
1409d522f475Smrg    Bool first, found;
1410d522f475Smrg
1411d522f475Smrg    TRACE(("Checking options-tables for inconsistencies:\n"));
1412d522f475Smrg
1413d522f475Smrg#if 0
1414d522f475Smrg    TRACE(("Options listed in help-message:\n"));
1415d522f475Smrg    for (j = 0; options[j].opt != 0; j++)
1416d522f475Smrg	TRACE(("%5d %-28s %s\n", j, opt_array[j].opt, opt_array[j].desc));
1417d522f475Smrg    TRACE(("Options listed in resource-table:\n"));
1418d522f475Smrg    for (j = 0; j < res_count; j++)
1419d522f475Smrg	TRACE(("%5d %-28s %s\n", j, res_array[j].option, res_array[j].specifier));
1420d522f475Smrg#endif
1421d522f475Smrg
1422d522f475Smrg    /* list all options[] not found in resources[] */
1423d522f475Smrg    for (j = 0, first = True; options[j].opt != 0; j++) {
1424d522f475Smrg	found = False;
1425d522f475Smrg	for (k = 0; k < res_count; k++) {
1426d522f475Smrg	    if (same_option(&opt_array[j], &res_array[k])) {
1427d522f475Smrg		found = True;
1428d522f475Smrg		break;
1429d522f475Smrg	    }
1430d522f475Smrg	}
1431d522f475Smrg	if (!found) {
1432d522f475Smrg	    if (first) {
1433d522f475Smrg		TRACE(("Options listed in help, not found in resource list:\n"));
1434d522f475Smrg		first = False;
1435d522f475Smrg	    }
1436d522f475Smrg	    TRACE(("  %-28s%s\n", opt_array[j].opt,
1437d522f475Smrg		   standard_option(opt_array[j].opt) ? " (standard)" : ""));
1438d522f475Smrg	}
1439d522f475Smrg    }
1440d522f475Smrg
1441d522f475Smrg    /* list all resources[] not found in options[] */
1442d522f475Smrg    for (j = 0, first = True; j < res_count; j++) {
1443d522f475Smrg	found = False;
1444d522f475Smrg	for (k = 0; options[k].opt != 0; k++) {
1445d522f475Smrg	    if (same_option(&opt_array[k], &res_array[j])) {
1446d522f475Smrg		found = True;
1447d522f475Smrg		break;
1448d522f475Smrg	    }
1449d522f475Smrg	}
1450d522f475Smrg	if (!found) {
1451d522f475Smrg	    if (first) {
1452d522f475Smrg		TRACE(("Resource list items not found in options-help:\n"));
1453d522f475Smrg		first = False;
1454d522f475Smrg	    }
1455d522f475Smrg	    TRACE(("  %s\n", res_array[j].option));
1456d522f475Smrg	}
1457d522f475Smrg    }
1458d522f475Smrg
1459d522f475Smrg    TRACE(("Resource list items that will be ignored by XtOpenApplication:\n"));
1460d522f475Smrg    for (j = 0; j < res_count; j++) {
1461d522f475Smrg	switch (res_array[j].argKind) {
1462d522f475Smrg	case XrmoptionSkipArg:
1463d522f475Smrg	    TRACE(("  %-28s {param}\n", res_array[j].option));
1464d522f475Smrg	    break;
1465d522f475Smrg	case XrmoptionSkipNArgs:
1466d522f475Smrg	    TRACE(("  %-28s {%ld params}\n", res_array[j].option, (long)
1467d522f475Smrg		   res_array[j].value));
1468d522f475Smrg	    break;
1469d522f475Smrg	case XrmoptionSkipLine:
1470d522f475Smrg	    TRACE(("  %-28s {remainder of line}\n", res_array[j].option));
1471d522f475Smrg	    break;
1472d522f475Smrg	case XrmoptionIsArg:
1473d522f475Smrg	case XrmoptionNoArg:
1474d522f475Smrg	case XrmoptionResArg:
1475d522f475Smrg	case XrmoptionSepArg:
1476d522f475Smrg	case XrmoptionStickyArg:
1477d522f475Smrg	default:
1478d522f475Smrg	    break;
1479d522f475Smrg	}
1480d522f475Smrg    }
1481d522f475Smrg}
1482a1f3da82Smrg#else
1483a1f3da82Smrgextern void empty_trace(void);
1484a1f3da82Smrgvoid
1485a1f3da82Smrgempty_trace(void)
1486a1f3da82Smrg{
1487a1f3da82Smrg}
1488a1f3da82Smrg#endif
1489