trace.c revision e39b573c
1e39b573cSmrg/* $XTermId: trace.c,v 1.125 2011/07/12 09:31:05 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));
516e39b573cSmrg	    TRACE(("\tfocus:     %d\n", event->focus));
51720d2c4d2Smrg	    TRACE(("\troot:      %#lx\n", event->root));
51820d2c4d2Smrg	    TRACE(("\tsubwindow: %#lx\n", event->subwindow));
51920d2c4d2Smrg	}
52020d2c4d2Smrg	break;
52120d2c4d2Smrg    }
52220d2c4d2Smrg    while (w != 0) {
52320d2c4d2Smrg	TRACE(("w %p -> %#lx\n", (void *) w, XtWindow(w)));
52420d2c4d2Smrg	w = XtParent(w);
52520d2c4d2Smrg    }
52620d2c4d2Smrg}
52720d2c4d2Smrg
528d522f475Smrgvoid
529d522f475SmrgTraceSizeHints(XSizeHints * hints)
530d522f475Smrg{
531d522f475Smrg    TRACE(("size hints:\n"));
532d522f475Smrg    if (hints->flags & (USPosition | PPosition))
533d522f475Smrg	TRACE(("   position   %d,%d%s%s\n", hints->y, hints->x,
534d522f475Smrg	       hints->flags & USPosition ? " user" : "",
535d522f475Smrg	       hints->flags & PPosition ? " prog" : ""));
536d522f475Smrg    if (hints->flags & (USSize | PSize))
537d522f475Smrg	TRACE(("   size       %d,%d%s%s\n", hints->height, hints->width,
538d522f475Smrg	       hints->flags & USSize ? " user" : "",
539d522f475Smrg	       hints->flags & PSize ? " prog" : ""));
540d522f475Smrg    if (hints->flags & PMinSize)
541d522f475Smrg	TRACE(("   min        %d,%d\n", hints->min_height, hints->min_width));
542d522f475Smrg    if (hints->flags & PMaxSize)
543d522f475Smrg	TRACE(("   max        %d,%d\n", hints->max_height, hints->max_width));
544d522f475Smrg    if (hints->flags & PResizeInc)
545d522f475Smrg	TRACE(("   inc        %d,%d\n", hints->height_inc, hints->width_inc));
5462eaa94a1Schristos    else
5472eaa94a1Schristos	TRACE(("   inc        NONE!\n"));
548d522f475Smrg    if (hints->flags & PAspect)
549d522f475Smrg	TRACE(("   min aspect %d/%d\n", hints->min_aspect.y, hints->min_aspect.y));
550d522f475Smrg    if (hints->flags & PAspect)
551d522f475Smrg	TRACE(("   max aspect %d/%d\n", hints->max_aspect.y, hints->max_aspect.y));
552d522f475Smrg    if (hints->flags & PBaseSize)
553d522f475Smrg	TRACE(("   base       %d,%d\n", hints->base_height, hints->base_width));
554d522f475Smrg    if (hints->flags & PWinGravity)
555d522f475Smrg	TRACE(("   gravity    %d\n", hints->win_gravity));
556d522f475Smrg}
557d522f475Smrg
558d522f475Smrgvoid
559d522f475SmrgTraceWMSizeHints(XtermWidget xw)
560d522f475Smrg{
561d522f475Smrg    XSizeHints sizehints = xw->hints;
562d522f475Smrg
563d522f475Smrg    getXtermSizeHints(xw);
564d522f475Smrg    TraceSizeHints(&xw->hints);
565d522f475Smrg    xw->hints = sizehints;
566d522f475Smrg}
567d522f475Smrg
568d522f475Smrg/*
569d522f475Smrg * Some calls to XGetAtom() will fail, and we don't want to stop.  So we use
570d522f475Smrg * our own error-handler.
571d522f475Smrg */
572a1f3da82Smrg/* ARGSUSED */
573d522f475Smrgstatic int
574d522f475Smrgno_error(Display * dpy GCC_UNUSED, XErrorEvent * event GCC_UNUSED)
575d522f475Smrg{
576d522f475Smrg    return 1;
577d522f475Smrg}
578d522f475Smrg
579d522f475Smrgvoid
580d522f475SmrgTraceTranslations(const char *name, Widget w)
581d522f475Smrg{
582d522f475Smrg    String result;
583d522f475Smrg    XErrorHandler save = XSetErrorHandler(no_error);
584d522f475Smrg    XtTranslations xlations;
585d522f475Smrg    Widget xcelerat;
586d522f475Smrg
58720d2c4d2Smrg    TRACE(("TraceTranslations for %s (widget %#lx) {{\n", name, (long) w));
588d522f475Smrg    if (w) {
589d522f475Smrg	XtVaGetValues(w,
590d522f475Smrg		      XtNtranslations, &xlations,
591d522f475Smrg		      XtNaccelerators, &xcelerat,
592d522f475Smrg		      (XtPointer) 0);
593d522f475Smrg	TRACE(("... xlations %#08lx\n", (long) xlations));
594d522f475Smrg	TRACE(("... xcelerat %#08lx\n", (long) xcelerat));
595d522f475Smrg	result = _XtPrintXlations(w, xlations, xcelerat, True);
59620d2c4d2Smrg	TRACE(("%s\n", NonNull(result)));
597d522f475Smrg	if (result)
59820d2c4d2Smrg	    XFree((char *) result);
599d522f475Smrg    } else {
600d522f475Smrg	TRACE(("none (widget is null)\n"));
601d522f475Smrg    }
60220d2c4d2Smrg    TRACE(("}}\n"));
603d522f475Smrg    XSetErrorHandler(save);
604d522f475Smrg}
605d522f475Smrg
6062eaa94a1Schristosint
6072eaa94a1SchristosTraceResizeRequest(const char *fn, int ln, Widget w,
608e39b573cSmrg		   unsigned reqwide,
609e39b573cSmrg		   unsigned reqhigh,
6102eaa94a1Schristos		   Dimension * gotwide,
6112eaa94a1Schristos		   Dimension * gothigh)
6122eaa94a1Schristos{
6132eaa94a1Schristos    int rc;
6142eaa94a1Schristos
615e39b573cSmrg    TRACE(("%s@%d ResizeRequest %ux%u\n", fn, ln, reqhigh, reqwide));
6162eaa94a1Schristos    rc = XtMakeResizeRequest((Widget) w, reqwide, reqhigh, gotwide, gothigh);
6172eaa94a1Schristos    TRACE(("... ResizeRequest -> "));
6182eaa94a1Schristos    if (gothigh && gotwide)
6192eaa94a1Schristos	TRACE(("%dx%d ", *gothigh, *gotwide));
6202eaa94a1Schristos    TRACE(("(%d)\n", rc));
6212eaa94a1Schristos    return rc;
6222eaa94a1Schristos}
6232eaa94a1Schristos
624d522f475Smrg#define XRES_S(name) Trace(#name " = %s\n", NonNull(resp->name))
625d522f475Smrg#define XRES_B(name) Trace(#name " = %s\n", BtoS(resp->name))
626d522f475Smrg#define XRES_I(name) Trace(#name " = %d\n", resp->name)
627d522f475Smrg
628d522f475Smrgvoid
629d522f475SmrgTraceXtermResources(void)
630d522f475Smrg{
631d522f475Smrg    XTERM_RESOURCE *resp = &resource;
632d522f475Smrg
633d522f475Smrg    Trace("XTERM_RESOURCE settings:\n");
634d522f475Smrg    XRES_S(icon_geometry);
635d522f475Smrg    XRES_S(title);
636d522f475Smrg    XRES_S(icon_name);
637d522f475Smrg    XRES_S(term_name);
638d522f475Smrg    XRES_S(tty_modes);
639e39b573cSmrg    XRES_I(minBufSize);
640e39b573cSmrg    XRES_I(maxBufSize);
641d522f475Smrg    XRES_B(hold_screen);
642d522f475Smrg    XRES_B(utmpInhibit);
643d522f475Smrg    XRES_B(utmpDisplayId);
644d522f475Smrg    XRES_B(messages);
645e39b573cSmrg    XRES_S(menuLocale);
646e39b573cSmrg    XRES_S(omitTranslation);
647e39b573cSmrg    XRES_S(keyboardType);
648e39b573cSmrg#if OPT_PRINT_ON_EXIT
649e39b573cSmrg    XRES_I(printModeNow);
650e39b573cSmrg    XRES_I(printModeOnXError);
651e39b573cSmrg    XRES_I(printOptsNow);
652e39b573cSmrg    XRES_I(printOptsOnXError);
653e39b573cSmrg    XRES_S(printFileNow);
654e39b573cSmrg    XRES_S(printFileOnXError);
655e39b573cSmrg#endif
656d522f475Smrg#if OPT_SUNPC_KBD
657d522f475Smrg    XRES_B(sunKeyboard);
658d522f475Smrg#endif
659d522f475Smrg#if OPT_HP_FUNC_KEYS
660d522f475Smrg    XRES_B(hpFunctionKeys);
661d522f475Smrg#endif
662d522f475Smrg#if OPT_SCO_FUNC_KEYS
663d522f475Smrg    XRES_B(scoFunctionKeys);
664d522f475Smrg#endif
665d522f475Smrg#if OPT_SUN_FUNC_KEYS
666d522f475Smrg    XRES_B(sunFunctionKeys);
667d522f475Smrg#endif
668d522f475Smrg#if OPT_INITIAL_ERASE
669d522f475Smrg    XRES_B(ptyInitialErase);
670d522f475Smrg    XRES_B(backarrow_is_erase);
671d522f475Smrg#endif
672d522f475Smrg    XRES_B(useInsertMode);
673d522f475Smrg#if OPT_ZICONBEEP
674d522f475Smrg    XRES_I(zIconBeep);
675d522f475Smrg#endif
676d522f475Smrg#if OPT_PTY_HANDSHAKE
677d522f475Smrg    XRES_B(wait_for_map);
678d522f475Smrg    XRES_B(ptyHandshake);
679d522f475Smrg    XRES_B(ptySttySize);
680d522f475Smrg#endif
681d522f475Smrg#if OPT_SAME_NAME
682d522f475Smrg    XRES_B(sameName);
683d522f475Smrg#endif
684d522f475Smrg#if OPT_SESSION_MGT
685d522f475Smrg    XRES_B(sessionMgt);
686d522f475Smrg#endif
687a1f3da82Smrg#if OPT_TOOLBAR
688a1f3da82Smrg    XRES_B(toolBar);
689a1f3da82Smrg#endif
690a1f3da82Smrg#if OPT_MAXIMIZE
691a1f3da82Smrg    XRES_B(maximized);
692a1f3da82Smrg    XRES_S(fullscreen_s);
693a1f3da82Smrg#endif
694d522f475Smrg}
695d522f475Smrg
696d522f475Smrgvoid
697d522f475SmrgTraceArgv(const char *tag, char **argv)
698d522f475Smrg{
699d522f475Smrg    int n = 0;
700d522f475Smrg
701d522f475Smrg    TRACE(("%s:\n", tag));
702d522f475Smrg    while (*argv != 0) {
703d522f475Smrg	TRACE(("  %d:%s\n", n++, *argv++));
704d522f475Smrg    }
705d522f475Smrg}
706d522f475Smrg
707d522f475Smrgstatic char *
70820d2c4d2Smrgparse_option(char *dst, String src, int first)
709d522f475Smrg{
710d522f475Smrg    char *s;
711d522f475Smrg
712a1f3da82Smrg    if (!strncmp(src, "-/+", (size_t) 3)) {
713956cc18dSsnj	dst[0] = (char) first;
714d522f475Smrg	strcpy(dst + 1, src + 3);
715d522f475Smrg    } else {
716d522f475Smrg	strcpy(dst, src);
717d522f475Smrg    }
718d522f475Smrg    for (s = dst; *s != '\0'; s++) {
719d522f475Smrg	if (*s == '#' || *s == '%' || *s == 'S') {
720d522f475Smrg	    s[1] = '\0';
721d522f475Smrg	} else if (*s == ' ') {
722d522f475Smrg	    *s = '\0';
723d522f475Smrg	    break;
724d522f475Smrg	}
725d522f475Smrg    }
726d522f475Smrg    return dst;
727d522f475Smrg}
728d522f475Smrg
729d522f475Smrgstatic Bool
730d522f475Smrgsame_option(OptionHelp * opt, XrmOptionDescRec * res)
731d522f475Smrg{
732d522f475Smrg    char temp[BUFSIZ];
733d522f475Smrg    return !strcmp(parse_option(temp, opt->opt, res->option[0]), res->option);
734d522f475Smrg}
735d522f475Smrg
736d522f475Smrgstatic Bool
73720d2c4d2Smrgstandard_option(String opt)
738d522f475Smrg{
739d522f475Smrg    static const char *table[] =
740d522f475Smrg    {
741d522f475Smrg	"+rv",
742d522f475Smrg	"+synchronous",
743d522f475Smrg	"-background",
744d522f475Smrg	"-bd",
745d522f475Smrg	"-bg",
746d522f475Smrg	"-bordercolor",
747d522f475Smrg	"-borderwidth",
748d522f475Smrg	"-bw",
749d522f475Smrg	"-display",
750d522f475Smrg	"-fg",
751d522f475Smrg	"-fn",
752d522f475Smrg	"-font",
753d522f475Smrg	"-foreground",
754d522f475Smrg	"-geometry",
755d522f475Smrg	"-iconic",
756d522f475Smrg	"-name",
757d522f475Smrg	"-reverse",
758d522f475Smrg	"-rv",
759d522f475Smrg	"-selectionTimeout",
760d522f475Smrg	"-synchronous",
761d522f475Smrg	"-title",
762d522f475Smrg	"-xnllanguage",
763d522f475Smrg	"-xrm",
764d522f475Smrg	"-xtsessionID",
765d522f475Smrg    };
766d522f475Smrg    Cardinal n;
767d522f475Smrg    char temp[BUFSIZ];
768d522f475Smrg
769d522f475Smrg    opt = parse_option(temp, opt, '-');
770d522f475Smrg    for (n = 0; n < XtNumber(table); n++) {
771d522f475Smrg	if (!strcmp(opt, table[n]))
772d522f475Smrg	    return True;
773d522f475Smrg    }
774d522f475Smrg    return False;
775d522f475Smrg}
776d522f475Smrg
777d522f475Smrg/*
778d522f475Smrg * Analyse the options/help messages for inconsistencies.
779d522f475Smrg */
780d522f475Smrgvoid
781d522f475SmrgTraceOptions(OptionHelp * options, XrmOptionDescRec * resources, Cardinal res_count)
782d522f475Smrg{
783d522f475Smrg    OptionHelp *opt_array = sortedOpts(options, resources, res_count);
784d522f475Smrg    size_t j, k;
785d522f475Smrg    XrmOptionDescRec *res_array = sortedOptDescs(resources, res_count);
786d522f475Smrg    Bool first, found;
787d522f475Smrg
788d522f475Smrg    TRACE(("Checking options-tables for inconsistencies:\n"));
789d522f475Smrg
790d522f475Smrg#if 0
791d522f475Smrg    TRACE(("Options listed in help-message:\n"));
792d522f475Smrg    for (j = 0; options[j].opt != 0; j++)
793d522f475Smrg	TRACE(("%5d %-28s %s\n", j, opt_array[j].opt, opt_array[j].desc));
794d522f475Smrg    TRACE(("Options listed in resource-table:\n"));
795d522f475Smrg    for (j = 0; j < res_count; j++)
796d522f475Smrg	TRACE(("%5d %-28s %s\n", j, res_array[j].option, res_array[j].specifier));
797d522f475Smrg#endif
798d522f475Smrg
799d522f475Smrg    /* list all options[] not found in resources[] */
800d522f475Smrg    for (j = 0, first = True; options[j].opt != 0; j++) {
801d522f475Smrg	found = False;
802d522f475Smrg	for (k = 0; k < res_count; k++) {
803d522f475Smrg	    if (same_option(&opt_array[j], &res_array[k])) {
804d522f475Smrg		found = True;
805d522f475Smrg		break;
806d522f475Smrg	    }
807d522f475Smrg	}
808d522f475Smrg	if (!found) {
809d522f475Smrg	    if (first) {
810d522f475Smrg		TRACE(("Options listed in help, not found in resource list:\n"));
811d522f475Smrg		first = False;
812d522f475Smrg	    }
813d522f475Smrg	    TRACE(("  %-28s%s\n", opt_array[j].opt,
814d522f475Smrg		   standard_option(opt_array[j].opt) ? " (standard)" : ""));
815d522f475Smrg	}
816d522f475Smrg    }
817d522f475Smrg
818d522f475Smrg    /* list all resources[] not found in options[] */
819d522f475Smrg    for (j = 0, first = True; j < res_count; j++) {
820d522f475Smrg	found = False;
821d522f475Smrg	for (k = 0; options[k].opt != 0; k++) {
822d522f475Smrg	    if (same_option(&opt_array[k], &res_array[j])) {
823d522f475Smrg		found = True;
824d522f475Smrg		break;
825d522f475Smrg	    }
826d522f475Smrg	}
827d522f475Smrg	if (!found) {
828d522f475Smrg	    if (first) {
829d522f475Smrg		TRACE(("Resource list items not found in options-help:\n"));
830d522f475Smrg		first = False;
831d522f475Smrg	    }
832d522f475Smrg	    TRACE(("  %s\n", res_array[j].option));
833d522f475Smrg	}
834d522f475Smrg    }
835d522f475Smrg
836d522f475Smrg    TRACE(("Resource list items that will be ignored by XtOpenApplication:\n"));
837d522f475Smrg    for (j = 0; j < res_count; j++) {
838d522f475Smrg	switch (res_array[j].argKind) {
839d522f475Smrg	case XrmoptionSkipArg:
840d522f475Smrg	    TRACE(("  %-28s {param}\n", res_array[j].option));
841d522f475Smrg	    break;
842d522f475Smrg	case XrmoptionSkipNArgs:
843d522f475Smrg	    TRACE(("  %-28s {%ld params}\n", res_array[j].option, (long)
844d522f475Smrg		   res_array[j].value));
845d522f475Smrg	    break;
846d522f475Smrg	case XrmoptionSkipLine:
847d522f475Smrg	    TRACE(("  %-28s {remainder of line}\n", res_array[j].option));
848d522f475Smrg	    break;
849d522f475Smrg	case XrmoptionIsArg:
850d522f475Smrg	case XrmoptionNoArg:
851d522f475Smrg	case XrmoptionResArg:
852d522f475Smrg	case XrmoptionSepArg:
853d522f475Smrg	case XrmoptionStickyArg:
854d522f475Smrg	default:
855d522f475Smrg	    break;
856d522f475Smrg	}
857d522f475Smrg    }
858d522f475Smrg}
859a1f3da82Smrg#else
860a1f3da82Smrgextern void empty_trace(void);
861a1f3da82Smrgvoid
862a1f3da82Smrgempty_trace(void)
863a1f3da82Smrg{
864a1f3da82Smrg}
865a1f3da82Smrg#endif
866