trace.c revision a1f3da82
1a1f3da82Smrg/* $XTermId: trace.c,v 1.121 2011/02/17 00:34:47 tom Exp $ */
2d522f475Smrg
320d2c4d2Smrg/*
4a1f3da82Smrg * Copyright 1997-2010,2011 by Thomas E. Dickey
520d2c4d2Smrg *
620d2c4d2Smrg *                         All Rights Reserved
720d2c4d2Smrg *
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 *
3220d2c4d2Smrg */
33d522f475Smrg
34d522f475Smrg/*
35d522f475Smrg * debugging support via TRACE macro.
36d522f475Smrg */
37d522f475Smrg
38d522f475Smrg#include <xterm.h>		/* for definition of GCC_UNUSED */
39a1f3da82Smrg
40a1f3da82Smrg#if OPT_TRACE
41a1f3da82Smrg
42d522f475Smrg#include <data.h>
43d522f475Smrg#include <trace.h>
44d522f475Smrg
45d522f475Smrg#include <time.h>
46d522f475Smrg#include <stdlib.h>
47d522f475Smrg#include <unistd.h>
48d522f475Smrg#include <sys/types.h>
49d522f475Smrg#include <stdio.h>
50d522f475Smrg#include <stdarg.h>
51d522f475Smrg#include <assert.h>
52d522f475Smrg
53956cc18dSsnj#include <X11/Xatom.h>
54956cc18dSsnj#include <X11/Xmu/Atoms.h>
55956cc18dSsnj
56d522f475Smrg#ifdef HAVE_X11_TRANSLATEI_H
57d522f475Smrg#include <X11/TranslateI.h>
58d522f475Smrg#else
59d522f475Smrg#ifdef __cplusplus
60d522f475Smrgextern "C" {
61d522f475Smrg#endif
62d522f475Smrg
63d522f475Smrg    extern String _XtPrintXlations(Widget w,
64d522f475Smrg				   XtTranslations xlations,
65d522f475Smrg				   Widget accelWidget,
66d522f475Smrg				   _XtBoolean includeRHS);
67d522f475Smrg#ifdef __cplusplus
68d522f475Smrg}
69d522f475Smrg#endif
70d522f475Smrg#endif
7120d2c4d2Smrgconst char *trace_who = "parent";
7220d2c4d2Smrg
7320d2c4d2Smrgstatic FILE *trace_fp;
74d522f475Smrg
75d522f475Smrgvoid
76d522f475SmrgTrace(const char *fmt,...)
77d522f475Smrg{
7820d2c4d2Smrg    static const char *trace_out;
79d522f475Smrg    va_list ap;
80d522f475Smrg
8120d2c4d2Smrg    if (trace_fp != 0
82d522f475Smrg	&& trace_who != trace_out) {
8320d2c4d2Smrg	fclose(trace_fp);
8420d2c4d2Smrg	trace_fp = 0;
85d522f475Smrg    }
86d522f475Smrg    trace_out = trace_who;
87d522f475Smrg
8820d2c4d2Smrg    if (!trace_fp) {
89d522f475Smrg	char name[BUFSIZ];
90d522f475Smrg#if 0				/* usually I do not want unique names */
91d522f475Smrg	int unique;
92d522f475Smrg	for (unique = 0;; ++unique) {
93d522f475Smrg	    if (unique)
94d522f475Smrg		sprintf(name, "Trace-%s.out-%d", trace_who, unique);
95d522f475Smrg	    else
96d522f475Smrg		sprintf(name, "Trace-%s.out", trace_who);
9720d2c4d2Smrg	    if ((trace_fp = fopen(name, "r")) == 0) {
98d522f475Smrg		break;
99d522f475Smrg	    }
10020d2c4d2Smrg	    fclose(trace_fp);
101d522f475Smrg	}
102d522f475Smrg#else
103d522f475Smrg	sprintf(name, "Trace-%s.out", trace_who);
104d522f475Smrg#endif
10520d2c4d2Smrg	trace_fp = fopen(name, "w");
10620d2c4d2Smrg	if (trace_fp != 0) {
10720d2c4d2Smrg	    fprintf(trace_fp, "%s\n", xtermVersion());
108d522f475Smrg	    TraceIds(NULL, 0);
109d522f475Smrg	}
110d522f475Smrg    }
11120d2c4d2Smrg    if (!trace_fp)
112d522f475Smrg	abort();
113d522f475Smrg
114d522f475Smrg    va_start(ap, fmt);
11520d2c4d2Smrg    vfprintf(trace_fp, fmt, ap);
11620d2c4d2Smrg    (void) fflush(trace_fp);
11720d2c4d2Smrg    va_end(ap);
11820d2c4d2Smrg}
11920d2c4d2Smrg
12020d2c4d2Smrgvoid
12120d2c4d2SmrgTraceClose(void)
12220d2c4d2Smrg{
12320d2c4d2Smrg    if (trace_fp != 0) {
12420d2c4d2Smrg	(void) fclose(trace_fp);
125d522f475Smrg	(void) fflush(stdout);
126d522f475Smrg	(void) fflush(stderr);
127956cc18dSsnj	(void) visibleChars(NULL, 0);
128956cc18dSsnj	(void) visibleIChars(NULL, 0);
129956cc18dSsnj	(void) visibleIChar(NULL, 0);
13020d2c4d2Smrg	trace_fp = 0;
131d522f475Smrg    }
132d522f475Smrg}
133d522f475Smrg
134d522f475Smrgvoid
135d522f475SmrgTraceIds(const char *fname, int lnum)
136d522f475Smrg{
137d522f475Smrg    Trace("process %d ", (int) getpid());
138d522f475Smrg#ifdef HAVE_UNISTD_H
139d522f475Smrg    Trace("real (%u/%u) effective (%u/%u)",
140d522f475Smrg	  (unsigned) getuid(), (unsigned) getgid(),
141d522f475Smrg	  (unsigned) geteuid(), (unsigned) getegid());
142d522f475Smrg#endif
143d522f475Smrg    if (fname != 0) {
144d522f475Smrg	Trace(" (%s@%d)\n", fname, lnum);
145d522f475Smrg    } else {
146d522f475Smrg	time_t now = time((time_t *) 0);
147d522f475Smrg	Trace("-- %s", ctime(&now));
148d522f475Smrg    }
149d522f475Smrg}
150d522f475Smrg
151d522f475Smrgstatic void
152d522f475SmrgformatAscii(char *dst, unsigned value)
153d522f475Smrg{
154d522f475Smrg    switch (value) {
155d522f475Smrg    case '\\':
156d522f475Smrg	sprintf(dst, "\\\\");
157d522f475Smrg	break;
158d522f475Smrg    case '\b':
159d522f475Smrg	sprintf(dst, "\\b");
160d522f475Smrg	break;
161d522f475Smrg    case '\n':
162d522f475Smrg	sprintf(dst, "\\n");
163d522f475Smrg	break;
164d522f475Smrg    case '\r':
165d522f475Smrg	sprintf(dst, "\\r");
166d522f475Smrg	break;
167d522f475Smrg    case '\t':
168d522f475Smrg	sprintf(dst, "\\t");
169d522f475Smrg	break;
170d522f475Smrg    default:
171d522f475Smrg	if (E2A(value) < 32 || (E2A(value) >= 127 && E2A(value) < 160))
172d522f475Smrg	    sprintf(dst, "\\%03o", value);
173d522f475Smrg	else
174d522f475Smrg	    sprintf(dst, "%c", CharOf(value));
175d522f475Smrg	break;
176d522f475Smrg    }
177d522f475Smrg}
178d522f475Smrg
179d522f475Smrg#if OPT_DEC_CHRSET
180d522f475Smrg
181d522f475Smrgconst char *
182956cc18dSsnjvisibleChrsetName(unsigned chrset)
183d522f475Smrg{
184d522f475Smrg    const char *result = "?";
185d522f475Smrg    switch (chrset) {
186d522f475Smrg    case CSET_SWL:
187d522f475Smrg	result = "CSET_SWL";
188d522f475Smrg	break;
189d522f475Smrg    case CSET_DHL_TOP:
190d522f475Smrg	result = "CSET_DHL_TOP";
191d522f475Smrg	break;
192d522f475Smrg    case CSET_DHL_BOT:
193d522f475Smrg	result = "CSET_DHL_BOT";
194d522f475Smrg	break;
195d522f475Smrg    case CSET_DWL:
196d522f475Smrg	result = "CSET_DWL";
197d522f475Smrg	break;
198d522f475Smrg    }
199d522f475Smrg    return result;
200d522f475Smrg}
201d522f475Smrg#endif
202d522f475Smrg
203d522f475Smrgchar *
20420d2c4d2SmrgvisibleChars(const Char * buf, unsigned len)
205d522f475Smrg{
206d522f475Smrg    static char *result;
207d522f475Smrg    static unsigned used;
208d522f475Smrg
209956cc18dSsnj    if (buf != 0) {
210956cc18dSsnj	unsigned limit = ((len + 1) * 8) + 1;
211956cc18dSsnj	char *dst;
212956cc18dSsnj
213956cc18dSsnj	if (limit > used) {
214956cc18dSsnj	    used = limit;
215956cc18dSsnj	    result = XtRealloc(result, used);
216956cc18dSsnj	}
21720d2c4d2Smrg	if (result != 0) {
21820d2c4d2Smrg	    dst = result;
21920d2c4d2Smrg	    *dst = '\0';
22020d2c4d2Smrg	    while (len--) {
22120d2c4d2Smrg		unsigned value = *buf++;
22220d2c4d2Smrg		formatAscii(dst, value);
22320d2c4d2Smrg		dst += strlen(dst);
22420d2c4d2Smrg	    }
225956cc18dSsnj	}
226956cc18dSsnj    } else if (result != 0) {
227956cc18dSsnj	free(result);
228956cc18dSsnj	result = 0;
229956cc18dSsnj	used = 0;
230d522f475Smrg    }
231956cc18dSsnj    return result;
232956cc18dSsnj}
233956cc18dSsnj
234956cc18dSsnjchar *
235956cc18dSsnjvisibleIChars(IChar * buf, unsigned len)
236956cc18dSsnj{
237956cc18dSsnj    static char *result;
238956cc18dSsnj    static unsigned used;
239956cc18dSsnj
240956cc18dSsnj    if (buf != 0) {
241956cc18dSsnj	unsigned limit = ((len + 1) * 8) + 1;
242956cc18dSsnj	char *dst;
243956cc18dSsnj
244956cc18dSsnj	if (limit > used) {
245956cc18dSsnj	    used = limit;
246956cc18dSsnj	    result = XtRealloc(result, used);
247d522f475Smrg	}
24820d2c4d2Smrg	if (result != 0) {
24920d2c4d2Smrg	    dst = result;
25020d2c4d2Smrg	    *dst = '\0';
25120d2c4d2Smrg	    while (len--) {
25220d2c4d2Smrg		unsigned value = *buf++;
253956cc18dSsnj#if OPT_WIDE_CHARS
25420d2c4d2Smrg		if (value > 255)
25520d2c4d2Smrg		    sprintf(dst, "\\u+%04X", value);
25620d2c4d2Smrg		else
257d522f475Smrg#endif
25820d2c4d2Smrg		    formatAscii(dst, value);
25920d2c4d2Smrg		dst += strlen(dst);
26020d2c4d2Smrg	    }
261956cc18dSsnj	}
262956cc18dSsnj    } else if (result != 0) {
263956cc18dSsnj	free(result);
264956cc18dSsnj	result = 0;
265956cc18dSsnj	used = 0;
266d522f475Smrg    }
267d522f475Smrg    return result;
268d522f475Smrg}
269d522f475Smrg
270d522f475Smrgchar *
271d522f475SmrgvisibleIChar(IChar * buf, unsigned len)
272d522f475Smrg{
273d522f475Smrg    static char *result;
274d522f475Smrg    static unsigned used;
275d522f475Smrg
276956cc18dSsnj    if (buf != 0) {
27720d2c4d2Smrg	unsigned limit = ((len + 1) * 8) + 1;
278956cc18dSsnj	char *dst;
279956cc18dSsnj
280956cc18dSsnj	if (limit > used) {
281956cc18dSsnj	    used = limit;
282956cc18dSsnj	    result = XtRealloc(result, used);
283956cc18dSsnj	}
28420d2c4d2Smrg	if (result != 0) {
28520d2c4d2Smrg	    dst = result;
28620d2c4d2Smrg	    while (len--) {
28720d2c4d2Smrg		unsigned value = *buf++;
288d522f475Smrg#if OPT_WIDE_CHARS
28920d2c4d2Smrg		if (value > 255)
29020d2c4d2Smrg		    sprintf(dst, "\\u+%04X", value);
29120d2c4d2Smrg		else
292d522f475Smrg#endif
29320d2c4d2Smrg		    formatAscii(dst, value);
29420d2c4d2Smrg		dst += strlen(dst);
29520d2c4d2Smrg	    }
296956cc18dSsnj	}
297956cc18dSsnj    } else if (result != 0) {
298956cc18dSsnj	free(result);
299956cc18dSsnj	result = 0;
300956cc18dSsnj	used = 0;
301d522f475Smrg    }
302d522f475Smrg    return result;
303d522f475Smrg}
304d522f475Smrg
305a1f3da82Smrg#define CASETYPE(name) case name: result = #name; break
306d522f475Smrg
307d522f475Smrgconst char *
308d522f475SmrgvisibleKeyboardType(xtermKeyboardType type)
309d522f475Smrg{
310d522f475Smrg    const char *result = "?";
311d522f475Smrg    switch (type) {
312d522f475Smrg	CASETYPE(keyboardIsLegacy);	/* bogus vt220 codes for F1-F4, etc. */
313d522f475Smrg	CASETYPE(keyboardIsDefault);
314d522f475Smrg	CASETYPE(keyboardIsHP);
315d522f475Smrg	CASETYPE(keyboardIsSCO);
316d522f475Smrg	CASETYPE(keyboardIsSun);
317d522f475Smrg	CASETYPE(keyboardIsTermcap);
318d522f475Smrg	CASETYPE(keyboardIsVT220);
319d522f475Smrg    }
320d522f475Smrg    return result;
321d522f475Smrg}
322d522f475Smrg
323d522f475Smrgconst char *
324d522f475SmrgvisibleEventType(int type)
325d522f475Smrg{
326d522f475Smrg    const char *result = "?";
327d522f475Smrg    switch (type) {
328d522f475Smrg	CASETYPE(KeyPress);
329d522f475Smrg	CASETYPE(KeyRelease);
330d522f475Smrg	CASETYPE(ButtonPress);
331d522f475Smrg	CASETYPE(ButtonRelease);
332d522f475Smrg	CASETYPE(MotionNotify);
333d522f475Smrg	CASETYPE(EnterNotify);
334d522f475Smrg	CASETYPE(LeaveNotify);
335d522f475Smrg	CASETYPE(FocusIn);
336d522f475Smrg	CASETYPE(FocusOut);
337d522f475Smrg	CASETYPE(KeymapNotify);
338d522f475Smrg	CASETYPE(Expose);
339d522f475Smrg	CASETYPE(GraphicsExpose);
340d522f475Smrg	CASETYPE(NoExpose);
341d522f475Smrg	CASETYPE(VisibilityNotify);
342d522f475Smrg	CASETYPE(CreateNotify);
343d522f475Smrg	CASETYPE(DestroyNotify);
344d522f475Smrg	CASETYPE(UnmapNotify);
345d522f475Smrg	CASETYPE(MapNotify);
346d522f475Smrg	CASETYPE(MapRequest);
347d522f475Smrg	CASETYPE(ReparentNotify);
348d522f475Smrg	CASETYPE(ConfigureNotify);
349d522f475Smrg	CASETYPE(ConfigureRequest);
350d522f475Smrg	CASETYPE(GravityNotify);
351d522f475Smrg	CASETYPE(ResizeRequest);
352d522f475Smrg	CASETYPE(CirculateNotify);
353d522f475Smrg	CASETYPE(CirculateRequest);
354d522f475Smrg	CASETYPE(PropertyNotify);
355d522f475Smrg	CASETYPE(SelectionClear);
356d522f475Smrg	CASETYPE(SelectionRequest);
357d522f475Smrg	CASETYPE(SelectionNotify);
358d522f475Smrg	CASETYPE(ColormapNotify);
359d522f475Smrg	CASETYPE(ClientMessage);
360d522f475Smrg	CASETYPE(MappingNotify);
361d522f475Smrg    }
362d522f475Smrg    return result;
363d522f475Smrg}
364d522f475Smrg
36520d2c4d2Smrgconst char *
36620d2c4d2SmrgvisibleNotifyDetail(int code)
36720d2c4d2Smrg{
36820d2c4d2Smrg    const char *result = "?";
36920d2c4d2Smrg    switch (code) {
37020d2c4d2Smrg	CASETYPE(NotifyAncestor);
37120d2c4d2Smrg	CASETYPE(NotifyVirtual);
37220d2c4d2Smrg	CASETYPE(NotifyInferior);
37320d2c4d2Smrg	CASETYPE(NotifyNonlinear);
37420d2c4d2Smrg	CASETYPE(NotifyNonlinearVirtual);
37520d2c4d2Smrg	CASETYPE(NotifyPointer);
37620d2c4d2Smrg	CASETYPE(NotifyPointerRoot);
37720d2c4d2Smrg	CASETYPE(NotifyDetailNone);
37820d2c4d2Smrg    }
37920d2c4d2Smrg    return result;
38020d2c4d2Smrg}
38120d2c4d2Smrg
382956cc18dSsnjconst char *
383956cc18dSsnjvisibleSelectionTarget(Display * d, Atom a)
384956cc18dSsnj{
385956cc18dSsnj    const char *result = "?";
386956cc18dSsnj
387956cc18dSsnj    if (a == XA_STRING) {
388956cc18dSsnj	result = "XA_STRING";
389956cc18dSsnj    } else if (a == XA_TEXT(d)) {
390956cc18dSsnj	result = "XA_TEXT()";
391956cc18dSsnj    } else if (a == XA_COMPOUND_TEXT(d)) {
392956cc18dSsnj	result = "XA_COMPOUND_TEXT()";
393956cc18dSsnj    } else if (a == XA_UTF8_STRING(d)) {
394956cc18dSsnj	result = "XA_UTF8_STRING()";
395956cc18dSsnj    } else if (a == XA_TARGETS(d)) {
396956cc18dSsnj	result = "XA_TARGETS()";
397956cc18dSsnj    }
398956cc18dSsnj
399956cc18dSsnj    return result;
400956cc18dSsnj}
401956cc18dSsnj
402d522f475Smrgconst char *
403d522f475SmrgvisibleXError(int code)
404d522f475Smrg{
405d522f475Smrg    static char temp[80];
406d522f475Smrg    const char *result = "?";
407d522f475Smrg    switch (code) {
408d522f475Smrg	CASETYPE(Success);
409d522f475Smrg	CASETYPE(BadRequest);
410d522f475Smrg	CASETYPE(BadValue);
411d522f475Smrg	CASETYPE(BadWindow);
412d522f475Smrg	CASETYPE(BadPixmap);
413d522f475Smrg	CASETYPE(BadAtom);
414d522f475Smrg	CASETYPE(BadCursor);
415d522f475Smrg	CASETYPE(BadFont);
416d522f475Smrg	CASETYPE(BadMatch);
417d522f475Smrg	CASETYPE(BadDrawable);
418d522f475Smrg	CASETYPE(BadAccess);
419d522f475Smrg	CASETYPE(BadAlloc);
420d522f475Smrg	CASETYPE(BadColor);
421d522f475Smrg	CASETYPE(BadGC);
422d522f475Smrg	CASETYPE(BadIDChoice);
423d522f475Smrg	CASETYPE(BadName);
424d522f475Smrg	CASETYPE(BadLength);
425d522f475Smrg	CASETYPE(BadImplementation);
426d522f475Smrg    default:
427d522f475Smrg	sprintf(temp, "%d", code);
428d522f475Smrg	result = temp;
429d522f475Smrg	break;
430d522f475Smrg    }
431d522f475Smrg    return result;
432d522f475Smrg}
433d522f475Smrg
434d522f475Smrg#if OPT_TRACE_FLAGS
435d522f475Smrg#define isScrnFlag(flag) ((flag) == LINEWRAPPED)
436d522f475Smrg
437d522f475Smrgstatic char *
438956cc18dSsnjScrnText(LineData * ld)
439d522f475Smrg{
440956cc18dSsnj    return visibleIChars(ld->charData, ld->lineSize);
441d522f475Smrg}
442d522f475Smrg
443956cc18dSsnj#define SHOW_BAD_LINE(name, ld) \
444956cc18dSsnj	Trace("OOPS " #name " bad row\n")
445d522f475Smrg
446d522f475Smrg#define SHOW_SCRN_FLAG(name,code) \
447956cc18dSsnj	Trace(#name " %s:%s\n", \
448d522f475Smrg	      code ? "*" : "", \
449956cc18dSsnj	      ScrnText(ld))
450d522f475Smrg
451d522f475Smrgvoid
452956cc18dSsnjLineClrFlag(LineData * ld, int flag)
453d522f475Smrg{
454956cc18dSsnj    if (ld == 0) {
455956cc18dSsnj	SHOW_BAD_LINE(LineClrFlag, ld);
456d522f475Smrg	assert(0);
457d522f475Smrg    } else if (isScrnFlag(flag)) {
458956cc18dSsnj	SHOW_SCRN_FLAG(LineClrFlag, 0);
459d522f475Smrg    }
460d522f475Smrg
461956cc18dSsnj    LineFlags(ld) &= ~flag;
462d522f475Smrg}
463d522f475Smrg
464d522f475Smrgvoid
465956cc18dSsnjLineSetFlag(LineData * ld, int flag)
466d522f475Smrg{
467956cc18dSsnj    if (ld == 0) {
468956cc18dSsnj	SHOW_BAD_LINE(LineSetFlag, ld);
469d522f475Smrg	assert(0);
470d522f475Smrg    } else if (isScrnFlag(flag)) {
471956cc18dSsnj	SHOW_SCRN_FLAG(LineSetFlag, 1);
472d522f475Smrg    }
473d522f475Smrg
474956cc18dSsnj    LineFlags(ld) |= flag;
475d522f475Smrg}
476d522f475Smrg
477d522f475Smrgint
478956cc18dSsnjLineTstFlag(LineData ld, int flag)
479d522f475Smrg{
480d522f475Smrg    int code = 0;
481956cc18dSsnj    if (ld == 0) {
482956cc18dSsnj	SHOW_BAD_LINE(LineTstFlag, ld);
483d522f475Smrg    } else {
484956cc18dSsnj	code = LineFlags(ld);
485956cc18dSsnj
486956cc18dSsnj	if (isScrnFlag(flag)) {
487956cc18dSsnj	    SHOW_SCRN_FLAG(LineTstFlag, code);
488d522f475Smrg	}
489d522f475Smrg    }
490d522f475Smrg    return code;
491d522f475Smrg}
492d522f475Smrg#endif /* OPT_TRACE_FLAGS */
493d522f475Smrg
49420d2c4d2Smrgvoid
49520d2c4d2SmrgTraceFocus(Widget w, XEvent * ev)
49620d2c4d2Smrg{
49720d2c4d2Smrg    TRACE(("trace_focus event type %d:%s\n",
49820d2c4d2Smrg	   ev->type, visibleEventType(ev->type)));
49920d2c4d2Smrg    switch (ev->type) {
50020d2c4d2Smrg    case FocusIn:
50120d2c4d2Smrg    case FocusOut:
50220d2c4d2Smrg	{
50320d2c4d2Smrg	    XFocusChangeEvent *event = (XFocusChangeEvent *) ev;
50420d2c4d2Smrg	    TRACE(("\tdetail: %s\n", visibleNotifyDetail(event->detail)));
50520d2c4d2Smrg	    TRACE(("\tmode:   %d\n", event->mode));
50620d2c4d2Smrg	    TRACE(("\twindow: %#lx\n", event->window));
50720d2c4d2Smrg	}
50820d2c4d2Smrg	break;
50920d2c4d2Smrg    case EnterNotify:
51020d2c4d2Smrg    case LeaveNotify:
51120d2c4d2Smrg	{
51220d2c4d2Smrg	    XCrossingEvent *event = (XCrossingEvent *) ev;
51320d2c4d2Smrg	    TRACE(("\tdetail:    %s\n", visibleNotifyDetail(event->detail)));
51420d2c4d2Smrg	    TRACE(("\tmode:      %d\n", event->mode));
51520d2c4d2Smrg	    TRACE(("\twindow:    %#lx\n", event->window));
51620d2c4d2Smrg	    TRACE(("\troot:      %#lx\n", event->root));
51720d2c4d2Smrg	    TRACE(("\tsubwindow: %#lx\n", event->subwindow));
51820d2c4d2Smrg	}
51920d2c4d2Smrg	break;
52020d2c4d2Smrg    }
52120d2c4d2Smrg    while (w != 0) {
52220d2c4d2Smrg	TRACE(("w %p -> %#lx\n", (void *) w, XtWindow(w)));
52320d2c4d2Smrg	w = XtParent(w);
52420d2c4d2Smrg    }
52520d2c4d2Smrg}
52620d2c4d2Smrg
527d522f475Smrgvoid
528d522f475SmrgTraceSizeHints(XSizeHints * hints)
529d522f475Smrg{
530d522f475Smrg    TRACE(("size hints:\n"));
531d522f475Smrg    if (hints->flags & (USPosition | PPosition))
532d522f475Smrg	TRACE(("   position   %d,%d%s%s\n", hints->y, hints->x,
533d522f475Smrg	       hints->flags & USPosition ? " user" : "",
534d522f475Smrg	       hints->flags & PPosition ? " prog" : ""));
535d522f475Smrg    if (hints->flags & (USSize | PSize))
536d522f475Smrg	TRACE(("   size       %d,%d%s%s\n", hints->height, hints->width,
537d522f475Smrg	       hints->flags & USSize ? " user" : "",
538d522f475Smrg	       hints->flags & PSize ? " prog" : ""));
539d522f475Smrg    if (hints->flags & PMinSize)
540d522f475Smrg	TRACE(("   min        %d,%d\n", hints->min_height, hints->min_width));
541d522f475Smrg    if (hints->flags & PMaxSize)
542d522f475Smrg	TRACE(("   max        %d,%d\n", hints->max_height, hints->max_width));
543d522f475Smrg    if (hints->flags & PResizeInc)
544d522f475Smrg	TRACE(("   inc        %d,%d\n", hints->height_inc, hints->width_inc));
5452eaa94a1Schristos    else
5462eaa94a1Schristos	TRACE(("   inc        NONE!\n"));
547d522f475Smrg    if (hints->flags & PAspect)
548d522f475Smrg	TRACE(("   min aspect %d/%d\n", hints->min_aspect.y, hints->min_aspect.y));
549d522f475Smrg    if (hints->flags & PAspect)
550d522f475Smrg	TRACE(("   max aspect %d/%d\n", hints->max_aspect.y, hints->max_aspect.y));
551d522f475Smrg    if (hints->flags & PBaseSize)
552d522f475Smrg	TRACE(("   base       %d,%d\n", hints->base_height, hints->base_width));
553d522f475Smrg    if (hints->flags & PWinGravity)
554d522f475Smrg	TRACE(("   gravity    %d\n", hints->win_gravity));
555d522f475Smrg}
556d522f475Smrg
557d522f475Smrgvoid
558d522f475SmrgTraceWMSizeHints(XtermWidget xw)
559d522f475Smrg{
560d522f475Smrg    XSizeHints sizehints = xw->hints;
561d522f475Smrg
562d522f475Smrg    getXtermSizeHints(xw);
563d522f475Smrg    TraceSizeHints(&xw->hints);
564d522f475Smrg    xw->hints = sizehints;
565d522f475Smrg}
566d522f475Smrg
567d522f475Smrg/*
568d522f475Smrg * Some calls to XGetAtom() will fail, and we don't want to stop.  So we use
569d522f475Smrg * our own error-handler.
570d522f475Smrg */
571a1f3da82Smrg/* ARGSUSED */
572d522f475Smrgstatic int
573d522f475Smrgno_error(Display * dpy GCC_UNUSED, XErrorEvent * event GCC_UNUSED)
574d522f475Smrg{
575d522f475Smrg    return 1;
576d522f475Smrg}
577d522f475Smrg
578d522f475Smrgvoid
579d522f475SmrgTraceTranslations(const char *name, Widget w)
580d522f475Smrg{
581d522f475Smrg    String result;
582d522f475Smrg    XErrorHandler save = XSetErrorHandler(no_error);
583d522f475Smrg    XtTranslations xlations;
584d522f475Smrg    Widget xcelerat;
585d522f475Smrg
58620d2c4d2Smrg    TRACE(("TraceTranslations for %s (widget %#lx) {{\n", name, (long) w));
587d522f475Smrg    if (w) {
588d522f475Smrg	XtVaGetValues(w,
589d522f475Smrg		      XtNtranslations, &xlations,
590d522f475Smrg		      XtNaccelerators, &xcelerat,
591d522f475Smrg		      (XtPointer) 0);
592d522f475Smrg	TRACE(("... xlations %#08lx\n", (long) xlations));
593d522f475Smrg	TRACE(("... xcelerat %#08lx\n", (long) xcelerat));
594d522f475Smrg	result = _XtPrintXlations(w, xlations, xcelerat, True);
59520d2c4d2Smrg	TRACE(("%s\n", NonNull(result)));
596d522f475Smrg	if (result)
59720d2c4d2Smrg	    XFree((char *) result);
598d522f475Smrg    } else {
599d522f475Smrg	TRACE(("none (widget is null)\n"));
600d522f475Smrg    }
60120d2c4d2Smrg    TRACE(("}}\n"));
602d522f475Smrg    XSetErrorHandler(save);
603d522f475Smrg}
604d522f475Smrg
6052eaa94a1Schristosint
6062eaa94a1SchristosTraceResizeRequest(const char *fn, int ln, Widget w,
6072eaa94a1Schristos		   Dimension reqwide,
6082eaa94a1Schristos		   Dimension reqhigh,
6092eaa94a1Schristos		   Dimension * gotwide,
6102eaa94a1Schristos		   Dimension * gothigh)
6112eaa94a1Schristos{
6122eaa94a1Schristos    int rc;
6132eaa94a1Schristos
6142eaa94a1Schristos    TRACE(("%s@%d ResizeRequest %dx%d\n", fn, ln, reqhigh, reqwide));
6152eaa94a1Schristos    rc = XtMakeResizeRequest((Widget) w, reqwide, reqhigh, gotwide, gothigh);
6162eaa94a1Schristos    TRACE(("... ResizeRequest -> "));
6172eaa94a1Schristos    if (gothigh && gotwide)
6182eaa94a1Schristos	TRACE(("%dx%d ", *gothigh, *gotwide));
6192eaa94a1Schristos    TRACE(("(%d)\n", rc));
6202eaa94a1Schristos    return rc;
6212eaa94a1Schristos}
6222eaa94a1Schristos
623d522f475Smrg#define XRES_S(name) Trace(#name " = %s\n", NonNull(resp->name))
624d522f475Smrg#define XRES_B(name) Trace(#name " = %s\n", BtoS(resp->name))
625d522f475Smrg#define XRES_I(name) Trace(#name " = %d\n", resp->name)
626d522f475Smrg
627d522f475Smrgvoid
628d522f475SmrgTraceXtermResources(void)
629d522f475Smrg{
630d522f475Smrg    XTERM_RESOURCE *resp = &resource;
631d522f475Smrg
632d522f475Smrg    Trace("XTERM_RESOURCE settings:\n");
633d522f475Smrg    XRES_S(icon_geometry);
634d522f475Smrg    XRES_S(title);
635d522f475Smrg    XRES_S(icon_name);
636d522f475Smrg    XRES_S(term_name);
637d522f475Smrg    XRES_S(tty_modes);
638d522f475Smrg    XRES_B(hold_screen);
639d522f475Smrg    XRES_B(utmpInhibit);
640d522f475Smrg    XRES_B(utmpDisplayId);
641d522f475Smrg    XRES_B(messages);
642d522f475Smrg#if OPT_SUNPC_KBD
643d522f475Smrg    XRES_B(sunKeyboard);
644d522f475Smrg#endif
645d522f475Smrg#if OPT_HP_FUNC_KEYS
646d522f475Smrg    XRES_B(hpFunctionKeys);
647d522f475Smrg#endif
648d522f475Smrg#if OPT_SCO_FUNC_KEYS
649d522f475Smrg    XRES_B(scoFunctionKeys);
650d522f475Smrg#endif
651d522f475Smrg#if OPT_SUN_FUNC_KEYS
652d522f475Smrg    XRES_B(sunFunctionKeys);
653d522f475Smrg#endif
654d522f475Smrg#if OPT_INITIAL_ERASE
655d522f475Smrg    XRES_B(ptyInitialErase);
656d522f475Smrg    XRES_B(backarrow_is_erase);
657d522f475Smrg#endif
658d522f475Smrg    XRES_B(useInsertMode);
659d522f475Smrg#if OPT_ZICONBEEP
660d522f475Smrg    XRES_I(zIconBeep);
661d522f475Smrg#endif
662d522f475Smrg#if OPT_PTY_HANDSHAKE
663d522f475Smrg    XRES_B(wait_for_map);
664d522f475Smrg    XRES_B(ptyHandshake);
665d522f475Smrg    XRES_B(ptySttySize);
666d522f475Smrg#endif
667d522f475Smrg#if OPT_SAME_NAME
668d522f475Smrg    XRES_B(sameName);
669d522f475Smrg#endif
670d522f475Smrg#if OPT_SESSION_MGT
671d522f475Smrg    XRES_B(sessionMgt);
672d522f475Smrg#endif
673a1f3da82Smrg#if OPT_TOOLBAR
674a1f3da82Smrg    XRES_B(toolBar);
675a1f3da82Smrg#endif
676a1f3da82Smrg#if OPT_MAXIMIZE
677a1f3da82Smrg    XRES_B(maximized);
678a1f3da82Smrg    XRES_S(fullscreen_s);
679a1f3da82Smrg#endif
680d522f475Smrg}
681d522f475Smrg
682d522f475Smrgvoid
683d522f475SmrgTraceArgv(const char *tag, char **argv)
684d522f475Smrg{
685d522f475Smrg    int n = 0;
686d522f475Smrg
687d522f475Smrg    TRACE(("%s:\n", tag));
688d522f475Smrg    while (*argv != 0) {
689d522f475Smrg	TRACE(("  %d:%s\n", n++, *argv++));
690d522f475Smrg    }
691d522f475Smrg}
692d522f475Smrg
693d522f475Smrgstatic char *
69420d2c4d2Smrgparse_option(char *dst, String src, int first)
695d522f475Smrg{
696d522f475Smrg    char *s;
697d522f475Smrg
698a1f3da82Smrg    if (!strncmp(src, "-/+", (size_t) 3)) {
699956cc18dSsnj	dst[0] = (char) first;
700d522f475Smrg	strcpy(dst + 1, src + 3);
701d522f475Smrg    } else {
702d522f475Smrg	strcpy(dst, src);
703d522f475Smrg    }
704d522f475Smrg    for (s = dst; *s != '\0'; s++) {
705d522f475Smrg	if (*s == '#' || *s == '%' || *s == 'S') {
706d522f475Smrg	    s[1] = '\0';
707d522f475Smrg	} else if (*s == ' ') {
708d522f475Smrg	    *s = '\0';
709d522f475Smrg	    break;
710d522f475Smrg	}
711d522f475Smrg    }
712d522f475Smrg    return dst;
713d522f475Smrg}
714d522f475Smrg
715d522f475Smrgstatic Bool
716d522f475Smrgsame_option(OptionHelp * opt, XrmOptionDescRec * res)
717d522f475Smrg{
718d522f475Smrg    char temp[BUFSIZ];
719d522f475Smrg    return !strcmp(parse_option(temp, opt->opt, res->option[0]), res->option);
720d522f475Smrg}
721d522f475Smrg
722d522f475Smrgstatic Bool
72320d2c4d2Smrgstandard_option(String opt)
724d522f475Smrg{
725d522f475Smrg    static const char *table[] =
726d522f475Smrg    {
727d522f475Smrg	"+rv",
728d522f475Smrg	"+synchronous",
729d522f475Smrg	"-background",
730d522f475Smrg	"-bd",
731d522f475Smrg	"-bg",
732d522f475Smrg	"-bordercolor",
733d522f475Smrg	"-borderwidth",
734d522f475Smrg	"-bw",
735d522f475Smrg	"-display",
736d522f475Smrg	"-fg",
737d522f475Smrg	"-fn",
738d522f475Smrg	"-font",
739d522f475Smrg	"-foreground",
740d522f475Smrg	"-geometry",
741d522f475Smrg	"-iconic",
742d522f475Smrg	"-name",
743d522f475Smrg	"-reverse",
744d522f475Smrg	"-rv",
745d522f475Smrg	"-selectionTimeout",
746d522f475Smrg	"-synchronous",
747d522f475Smrg	"-title",
748d522f475Smrg	"-xnllanguage",
749d522f475Smrg	"-xrm",
750d522f475Smrg	"-xtsessionID",
751d522f475Smrg    };
752d522f475Smrg    Cardinal n;
753d522f475Smrg    char temp[BUFSIZ];
754d522f475Smrg
755d522f475Smrg    opt = parse_option(temp, opt, '-');
756d522f475Smrg    for (n = 0; n < XtNumber(table); n++) {
757d522f475Smrg	if (!strcmp(opt, table[n]))
758d522f475Smrg	    return True;
759d522f475Smrg    }
760d522f475Smrg    return False;
761d522f475Smrg}
762d522f475Smrg
763d522f475Smrg/*
764d522f475Smrg * Analyse the options/help messages for inconsistencies.
765d522f475Smrg */
766d522f475Smrgvoid
767d522f475SmrgTraceOptions(OptionHelp * options, XrmOptionDescRec * resources, Cardinal res_count)
768d522f475Smrg{
769d522f475Smrg    OptionHelp *opt_array = sortedOpts(options, resources, res_count);
770d522f475Smrg    size_t j, k;
771d522f475Smrg    XrmOptionDescRec *res_array = sortedOptDescs(resources, res_count);
772d522f475Smrg    Bool first, found;
773d522f475Smrg
774d522f475Smrg    TRACE(("Checking options-tables for inconsistencies:\n"));
775d522f475Smrg
776d522f475Smrg#if 0
777d522f475Smrg    TRACE(("Options listed in help-message:\n"));
778d522f475Smrg    for (j = 0; options[j].opt != 0; j++)
779d522f475Smrg	TRACE(("%5d %-28s %s\n", j, opt_array[j].opt, opt_array[j].desc));
780d522f475Smrg    TRACE(("Options listed in resource-table:\n"));
781d522f475Smrg    for (j = 0; j < res_count; j++)
782d522f475Smrg	TRACE(("%5d %-28s %s\n", j, res_array[j].option, res_array[j].specifier));
783d522f475Smrg#endif
784d522f475Smrg
785d522f475Smrg    /* list all options[] not found in resources[] */
786d522f475Smrg    for (j = 0, first = True; options[j].opt != 0; j++) {
787d522f475Smrg	found = False;
788d522f475Smrg	for (k = 0; k < res_count; k++) {
789d522f475Smrg	    if (same_option(&opt_array[j], &res_array[k])) {
790d522f475Smrg		found = True;
791d522f475Smrg		break;
792d522f475Smrg	    }
793d522f475Smrg	}
794d522f475Smrg	if (!found) {
795d522f475Smrg	    if (first) {
796d522f475Smrg		TRACE(("Options listed in help, not found in resource list:\n"));
797d522f475Smrg		first = False;
798d522f475Smrg	    }
799d522f475Smrg	    TRACE(("  %-28s%s\n", opt_array[j].opt,
800d522f475Smrg		   standard_option(opt_array[j].opt) ? " (standard)" : ""));
801d522f475Smrg	}
802d522f475Smrg    }
803d522f475Smrg
804d522f475Smrg    /* list all resources[] not found in options[] */
805d522f475Smrg    for (j = 0, first = True; j < res_count; j++) {
806d522f475Smrg	found = False;
807d522f475Smrg	for (k = 0; options[k].opt != 0; k++) {
808d522f475Smrg	    if (same_option(&opt_array[k], &res_array[j])) {
809d522f475Smrg		found = True;
810d522f475Smrg		break;
811d522f475Smrg	    }
812d522f475Smrg	}
813d522f475Smrg	if (!found) {
814d522f475Smrg	    if (first) {
815d522f475Smrg		TRACE(("Resource list items not found in options-help:\n"));
816d522f475Smrg		first = False;
817d522f475Smrg	    }
818d522f475Smrg	    TRACE(("  %s\n", res_array[j].option));
819d522f475Smrg	}
820d522f475Smrg    }
821d522f475Smrg
822d522f475Smrg    TRACE(("Resource list items that will be ignored by XtOpenApplication:\n"));
823d522f475Smrg    for (j = 0; j < res_count; j++) {
824d522f475Smrg	switch (res_array[j].argKind) {
825d522f475Smrg	case XrmoptionSkipArg:
826d522f475Smrg	    TRACE(("  %-28s {param}\n", res_array[j].option));
827d522f475Smrg	    break;
828d522f475Smrg	case XrmoptionSkipNArgs:
829d522f475Smrg	    TRACE(("  %-28s {%ld params}\n", res_array[j].option, (long)
830d522f475Smrg		   res_array[j].value));
831d522f475Smrg	    break;
832d522f475Smrg	case XrmoptionSkipLine:
833d522f475Smrg	    TRACE(("  %-28s {remainder of line}\n", res_array[j].option));
834d522f475Smrg	    break;
835d522f475Smrg	case XrmoptionIsArg:
836d522f475Smrg	case XrmoptionNoArg:
837d522f475Smrg	case XrmoptionResArg:
838d522f475Smrg	case XrmoptionSepArg:
839d522f475Smrg	case XrmoptionStickyArg:
840d522f475Smrg	default:
841d522f475Smrg	    break;
842d522f475Smrg	}
843d522f475Smrg    }
844d522f475Smrg}
845a1f3da82Smrg#else
846a1f3da82Smrgextern void empty_trace(void);
847a1f3da82Smrgvoid
848a1f3da82Smrgempty_trace(void)
849a1f3da82Smrg{
850a1f3da82Smrg}
851a1f3da82Smrg#endif
852