"Fossies" - the Fresh Open Source Software Archive 
Member "xterm-379/trace.c" (6 Oct 2022, 33783 Bytes) of package /linux/misc/xterm-379.tgz:
As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style:
standard) with prefixed line numbers and
code folding option.
Alternatively you can here
view or
download the uninterpreted source code file.
For more information about "trace.c" see the
Fossies "Dox" file reference documentation and the last
Fossies "Diffs" side-by-side code changes report:
373_vs_374.
1 /* $XTermId: trace.c,v 1.239 2022/10/06 20:43:02 tom Exp $ */
2
3 /*
4 * Copyright 1997-2021,2022 by Thomas E. Dickey
5 *
6 * All Rights Reserved
7 *
8 * Permission is hereby granted, free of charge, to any person obtaining a
9 * copy of this software and associated documentation files (the
10 * "Software"), to deal in the Software without restriction, including
11 * without limitation the rights to use, copy, modify, merge, publish,
12 * distribute, sublicense, and/or sell copies of the Software, and to
13 * permit persons to whom the Software is furnished to do so, subject to
14 * the following conditions:
15 *
16 * The above copyright notice and this permission notice shall be included
17 * in all copies or substantial portions of the Software.
18 *
19 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
20 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
21 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
22 * IN NO EVENT SHALL THE ABOVE LISTED COPYRIGHT HOLDER(S) BE LIABLE FOR ANY
23 * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
24 * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
25 * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
26 *
27 * Except as contained in this notice, the name(s) of the above copyright
28 * holders shall not be used in advertising or otherwise to promote the
29 * sale, use or other dealings in this Software without prior written
30 * authorization.
31 */
32
33 /*
34 * debugging support via TRACE macro.
35 */
36
37 #include <xterm.h> /* for definition of GCC_UNUSED */
38 #include <xstrings.h>
39 #include <wcwidth.h>
40 #include <version.h>
41
42 #if OPT_TRACE
43
44 #include <data.h>
45 #include <trace.h>
46
47 #include <time.h>
48 #include <stdlib.h>
49 #include <unistd.h>
50 #include <sys/types.h>
51 #include <sys/stat.h>
52 #include <stdio.h>
53 #include <assert.h>
54
55 #include <X11/Xatom.h>
56 #include <X11/Xmu/Atoms.h>
57 #include <X11/Xmu/Error.h>
58
59 #ifdef HAVE_X11_TRANSLATEI_H
60 #include <X11/ConvertI.h>
61 #include <X11/TranslateI.h>
62 #else
63 #ifdef __cplusplus
64 extern "C" {
65 #endif
66
67 extern String _XtPrintXlations(Widget w,
68 XtTranslations xlations,
69 Widget accelWidget,
70 _XtBoolean includeRHS);
71 #ifdef __cplusplus
72 }
73 #endif
74 #endif
75 const char *trace_who = "parent";
76
77 static FILE *trace_fp;
78
79 static FILE *
80 TraceOpen(void)
81 {
82 static const char *trace_out;
83
84 if (trace_fp != 0
85 && trace_who != trace_out) {
86 fclose(trace_fp);
87 trace_fp = 0;
88 }
89 trace_out = trace_who;
90
91 if (!trace_fp) {
92 static char dot[] = ".";
93 mode_t oldmask = umask(077);
94 char *home;
95 char *name;
96 /*
97 * Put the trace-file in user's home-directory if the current
98 * directory is not writable.
99 */
100 home = ((access(dot, R_OK | W_OK) == 0)
101 ? dot
102 : getenv("HOME"));
103 if (home != NULL &&
104 (name = malloc(strlen(home) + strlen(trace_who) + 50)) != NULL) {
105 #if OPT_TRACE_UNIQUE /* usually I do not want unique names */
106 int unique;
107 for (unique = 0;; ++unique) {
108 if (unique)
109 sprintf(name, "%s/Trace-%s.out-%d", home, trace_who, unique);
110 else
111 sprintf(name, "%s/Trace-%s.out", home, trace_who);
112 if ((trace_fp = fopen(name, "r")) == 0) {
113 break;
114 }
115 fclose(trace_fp);
116 }
117 #else
118 sprintf(name, "%s/Trace-%s.out", home, trace_who);
119 #endif
120 trace_fp = fopen(name, "w");
121 if (trace_fp != 0) {
122 fprintf(trace_fp, "%s\n", xtermVersion());
123 TraceIds(NULL, 0);
124 }
125 if (!trace_fp) {
126 xtermWarning("Cannot open \"%s\"\n", name);
127 exit(EXIT_FAILURE);
128 }
129 (void) umask(oldmask);
130 free(name);
131 }
132 }
133 return trace_fp;
134 }
135
136 void
137 Trace(const char *fmt, ...)
138 {
139 va_list ap;
140 FILE *fp = TraceOpen();
141
142 va_start(ap, fmt);
143 vfprintf(fp, fmt, ap);
144 (void) fflush(fp);
145 va_end(ap);
146 }
147
148 void
149 TraceVA(const char *fmt, va_list ap)
150 {
151 FILE *fp = TraceOpen();
152
153 vfprintf(fp, fmt, ap);
154 (void) fflush(fp);
155 }
156
157 void
158 TraceClose(void)
159 {
160 if (trace_fp != 0) {
161 (void) fclose(trace_fp);
162 (void) fflush(stdout);
163 (void) fflush(stderr);
164 (void) visibleChars(NULL, 0);
165 (void) visibleIChars(NULL, 0);
166 trace_fp = 0;
167 }
168 }
169
170 void
171 TraceXError(Display *d, XErrorEvent *ev)
172 {
173 FILE *fp = TraceOpen();
174 (void) XmuPrintDefaultErrorMessage(d, ev, fp);
175 (void) fflush(fp);
176 }
177
178 void
179 TraceIds(const char *fname, int lnum)
180 {
181 Trace("process %d ", (int) getpid());
182 #ifdef HAVE_UNISTD_H
183 Trace("real (%u/%u) effective (%u/%u)",
184 (unsigned) getuid(), (unsigned) getgid(),
185 (unsigned) geteuid(), (unsigned) getegid());
186 #endif
187 if (fname != 0) {
188 Trace(" (%s@%d)\n", fname, lnum);
189 } else {
190 time_t now = time((time_t *) 0);
191 Trace("-- %s", ctime(&now));
192 }
193 }
194
195 void
196 TraceTime(const char *fname, int lnum)
197 {
198 time_t now;
199 if (fname != 0) {
200 Trace("datetime (%s@%d) ", fname, lnum);
201 }
202 now = time((time_t *) 0);
203 Trace("-- %s", ctime(&now));
204 }
205
206 static void
207 formatAscii(char *dst, unsigned value)
208 {
209 switch (value) {
210 case '\\':
211 sprintf(dst, "\\\\");
212 break;
213 case '\b':
214 sprintf(dst, "\\b");
215 break;
216 case '\n':
217 sprintf(dst, "\\n");
218 break;
219 case '\r':
220 sprintf(dst, "\\r");
221 break;
222 case '\t':
223 sprintf(dst, "\\t");
224 break;
225 default:
226 if (E2A(value) < 32 || (E2A(value) >= 127 && E2A(value) < 160))
227 sprintf(dst, "\\%03o", value & 0xff);
228 else
229 sprintf(dst, "%c", CharOf(value));
230 break;
231 }
232 }
233
234 #if OPT_DEC_CHRSET
235
236 const char *
237 visibleDblChrset(unsigned chrset)
238 {
239 const char *result = "?";
240 switch (chrset) {
241 case CSET_SWL:
242 result = "CSET_SWL";
243 break;
244 case CSET_DHL_TOP:
245 result = "CSET_DHL_TOP";
246 break;
247 case CSET_DHL_BOT:
248 result = "CSET_DHL_BOT";
249 break;
250 case CSET_DWL:
251 result = "CSET_DWL";
252 break;
253 }
254 return result;
255 }
256 #endif
257
258 const char *
259 visibleScsCode(DECNRCM_codes chrset)
260 {
261 #define MAP(to,from) case from: result = to ":" #from; break
262 const char *result = "<ERR>";
263 switch ((DECNRCM_codes) chrset) {
264 MAP("B", nrc_ASCII);
265 MAP("A", nrc_British);
266 MAP("A", nrc_British_Latin_1);
267 MAP("&4", nrc_DEC_Cyrillic);
268 MAP("0", nrc_DEC_Spec_Graphic);
269 MAP("1", nrc_DEC_Alt_Chars);
270 MAP("2", nrc_DEC_Alt_Graphics);
271 MAP("<", nrc_DEC_Supp);
272 MAP("%5", nrc_DEC_Supp_Graphic);
273 MAP(">", nrc_DEC_Technical);
274 MAP("4", nrc_Dutch);
275 MAP("5", nrc_Finnish);
276 MAP("C", nrc_Finnish2);
277 MAP("R", nrc_French);
278 MAP("f", nrc_French2);
279 MAP("Q", nrc_French_Canadian);
280 MAP("9", nrc_French_Canadian2);
281 MAP("K", nrc_German);
282 MAP("\"?", nrc_DEC_Greek_Supp);
283 MAP("\">", nrc_Greek);
284 MAP("F", nrc_ISO_Greek_Supp);
285 MAP("\"4", nrc_DEC_Hebrew_Supp);
286 MAP("%=", nrc_Hebrew);
287 MAP("H", nrc_ISO_Hebrew_Supp);
288 MAP("Y", nrc_Italian);
289 MAP("A", nrc_ISO_Latin_1_Supp);
290 MAP("B", nrc_ISO_Latin_2_Supp);
291 MAP("M", nrc_ISO_Latin_5_Supp);
292 MAP("L", nrc_ISO_Latin_Cyrillic);
293 MAP("`", nrc_Norwegian_Danish);
294 MAP("E", nrc_Norwegian_Danish2);
295 MAP("6", nrc_Norwegian_Danish3);
296 MAP("%6", nrc_Portugese);
297 MAP("&5", nrc_Russian);
298 MAP("%3", nrc_SCS_NRCS);
299 MAP("Z", nrc_Spanish);
300 MAP("7", nrc_Swedish);
301 MAP("H", nrc_Swedish2);
302 MAP("=", nrc_Swiss);
303 MAP("%2", nrc_Turkish);
304 MAP("%0", nrc_DEC_Turkish_Supp);
305 MAP("<UNK>", nrc_Unknown);
306 }
307 #undef MAP
308 return result;
309 }
310
311 const char *
312 visibleChars(const Char *buf, size_t len)
313 {
314 static char *result;
315 static size_t used;
316
317 if (buf != 0) {
318 size_t limit = ((len + 1) * 8) + 1;
319
320 if (limit > used) {
321 used = limit;
322 result = realloc(result, used);
323 }
324 if (result != 0) {
325 char *dst = result;
326 *dst = '\0';
327 while (len--) {
328 unsigned value = *buf++;
329 formatAscii(dst, value);
330 dst += strlen(dst);
331 }
332 }
333 } else {
334 FreeAndNull(result);
335 used = 0;
336 }
337 return NonNull(result);
338 }
339
340 const char *
341 visibleEventMode(EventMode value)
342 {
343 const char *result;
344 switch (value) {
345 case NORMAL:
346 result = "NORMAL";
347 break;
348 case LEFTEXTENSION:
349 result = "LEFTEXTENSION";
350 break;
351 case RIGHTEXTENSION:
352 result = "RIGHTEXTENSION";
353 break;
354 default:
355 result = "?";
356 break;
357 }
358 return result;
359 }
360
361 const char *
362 visibleIChars(const IChar *buf, size_t len)
363 {
364 static char *result;
365 static size_t used;
366
367 if (buf != 0) {
368 size_t limit = ((len + 1) * 12) + 1;
369
370 if (limit > used) {
371 used = limit;
372 result = realloc(result, used);
373 }
374 if (result != 0) {
375 char *dst = result;
376 *dst = '\0';
377 while (len--) {
378 unsigned value = *buf++;
379 #if OPT_WIDE_CHARS
380 if (value > 255)
381 sprintf(dst, "\\U+%04X", value);
382 else
383 #endif
384 formatAscii(dst, value);
385 dst += strlen(dst);
386 }
387 }
388 } else {
389 FreeAndNull(result);
390 used = 0;
391 }
392 return NonNull(result);
393 }
394
395 const char *
396 visibleUChar(unsigned chr)
397 {
398 IChar buf[1];
399 buf[0] = (IChar) chr;
400 return visibleIChars(buf, 1);
401 }
402
403 const char *
404 visibleEventType(int type)
405 {
406 const char *result = "?";
407 switch (type) {
408 CASETYPE(KeyPress);
409 CASETYPE(KeyRelease);
410 CASETYPE(ButtonPress);
411 CASETYPE(ButtonRelease);
412 CASETYPE(MotionNotify);
413 CASETYPE(EnterNotify);
414 CASETYPE(LeaveNotify);
415 CASETYPE(FocusIn);
416 CASETYPE(FocusOut);
417 CASETYPE(KeymapNotify);
418 CASETYPE(Expose);
419 CASETYPE(GraphicsExpose);
420 CASETYPE(NoExpose);
421 CASETYPE(VisibilityNotify);
422 CASETYPE(CreateNotify);
423 CASETYPE(DestroyNotify);
424 CASETYPE(UnmapNotify);
425 CASETYPE(MapNotify);
426 CASETYPE(MapRequest);
427 CASETYPE(ReparentNotify);
428 CASETYPE(ConfigureNotify);
429 CASETYPE(ConfigureRequest);
430 CASETYPE(GravityNotify);
431 CASETYPE(ResizeRequest);
432 CASETYPE(CirculateNotify);
433 CASETYPE(CirculateRequest);
434 CASETYPE(PropertyNotify);
435 CASETYPE(SelectionClear);
436 CASETYPE(SelectionRequest);
437 CASETYPE(SelectionNotify);
438 CASETYPE(ColormapNotify);
439 CASETYPE(ClientMessage);
440 CASETYPE(MappingNotify);
441 }
442 return result;
443 }
444
445 const char *
446 visibleMappingMode(int code)
447 {
448 const char *result = "?";
449 switch (code) {
450 CASETYPE(MappingModifier);
451 CASETYPE(MappingKeyboard);
452 CASETYPE(MappingPointer);
453 }
454 return result;
455 }
456
457 const char *
458 visibleNotifyMode(int code)
459 {
460 const char *result = "?";
461 switch (code) {
462 CASETYPE(NotifyNormal);
463 CASETYPE(NotifyGrab);
464 CASETYPE(NotifyUngrab);
465 CASETYPE(NotifyWhileGrabbed);
466 }
467 return result;
468 }
469
470 const char *
471 visibleNotifyDetail(int code)
472 {
473 const char *result = "?";
474 switch (code) {
475 CASETYPE(NotifyAncestor);
476 CASETYPE(NotifyVirtual);
477 CASETYPE(NotifyInferior);
478 CASETYPE(NotifyNonlinear);
479 CASETYPE(NotifyNonlinearVirtual);
480 CASETYPE(NotifyPointer);
481 CASETYPE(NotifyPointerRoot);
482 CASETYPE(NotifyDetailNone);
483 }
484 return result;
485 }
486
487 const char *
488 visibleSelectionTarget(Display *d, Atom a)
489 {
490 const char *result = "?";
491
492 if (a == XA_STRING) {
493 result = "XA_STRING";
494 } else if (a == XA_TEXT(d)) {
495 result = "XA_TEXT()";
496 } else if (a == XA_COMPOUND_TEXT(d)) {
497 result = "XA_COMPOUND_TEXT()";
498 } else if (a == XA_UTF8_STRING(d)) {
499 result = "XA_UTF8_STRING()";
500 } else if (a == XA_TARGETS(d)) {
501 result = "XA_TARGETS()";
502 }
503
504 return result;
505 }
506
507 #if OPT_TEK4014
508 const char *
509 visibleTekparse(int code)
510 {
511 static const struct {
512 int code;
513 const char *name;
514 } table[] = {
515 #include "Tekparse.cin"
516 };
517 const char *result = "?";
518 Cardinal n;
519 for (n = 0; n < XtNumber(table); ++n) {
520 if (table[n].code == code) {
521 result = table[n].name;
522 break;
523 }
524 }
525 return result;
526 }
527 #endif
528
529 const char *
530 visibleVTparse(int code)
531 {
532 static const struct {
533 int code;
534 const char *name;
535 } table[] = {
536 #include "VTparse.cin"
537 };
538 const char *result = "?";
539 Cardinal n;
540 for (n = 0; n < XtNumber(table); ++n) {
541 if (table[n].code == code) {
542 result = table[n].name;
543 break;
544 }
545 }
546 return result;
547 }
548
549 const char *
550 visibleXError(int code)
551 {
552 static char temp[80];
553 const char *result = "?";
554 switch (code) {
555 CASETYPE(Success);
556 CASETYPE(BadRequest);
557 CASETYPE(BadValue);
558 CASETYPE(BadWindow);
559 CASETYPE(BadPixmap);
560 CASETYPE(BadAtom);
561 CASETYPE(BadCursor);
562 CASETYPE(BadFont);
563 CASETYPE(BadMatch);
564 CASETYPE(BadDrawable);
565 CASETYPE(BadAccess);
566 CASETYPE(BadAlloc);
567 CASETYPE(BadColor);
568 CASETYPE(BadGC);
569 CASETYPE(BadIDChoice);
570 CASETYPE(BadName);
571 CASETYPE(BadLength);
572 CASETYPE(BadImplementation);
573 default:
574 sprintf(temp, "%d", code);
575 result = temp;
576 break;
577 }
578 return result;
579 }
580
581 #if OPT_TRACE_FLAGS
582 #define isScrnFlag(flag) ((flag) == LINEWRAPPED)
583
584 static char *
585 ScrnText(LineData *ld)
586 {
587 return visibleIChars(ld->charData, ld->lineSize);
588 }
589
590 #define SHOW_BAD_LINE(name, ld) \
591 Trace("OOPS " #name " bad row\n")
592
593 #define SHOW_SCRN_FLAG(name,code) \
594 Trace(#name " %s:%s\n", \
595 code ? "*" : "", \
596 ScrnText(ld))
597
598 void
599 LineClrFlag(LineData *ld, int flag)
600 {
601 if (ld == 0) {
602 SHOW_BAD_LINE(LineClrFlag, ld);
603 assert(0);
604 } else if (isScrnFlag(flag)) {
605 SHOW_SCRN_FLAG(LineClrFlag, 0);
606 }
607
608 LineFlags(ld) &= ~flag;
609 }
610
611 void
612 LineSetFlag(LineData *ld, int flag)
613 {
614 if (ld == 0) {
615 SHOW_BAD_LINE(LineSetFlag, ld);
616 assert(0);
617 } else if (isScrnFlag(flag)) {
618 SHOW_SCRN_FLAG(LineSetFlag, 1);
619 }
620
621 LineFlags(ld) |= flag;
622 }
623
624 int
625 LineTstFlag(LineData ld, int flag)
626 {
627 int code = 0;
628 if (ld == 0) {
629 SHOW_BAD_LINE(LineTstFlag, ld);
630 } else {
631 code = LineFlags(ld);
632
633 if (isScrnFlag(flag)) {
634 SHOW_SCRN_FLAG(LineTstFlag, code);
635 }
636 }
637 return code;
638 }
639 #endif /* OPT_TRACE_FLAGS */
640
641 const char *
642 TraceAtomName(Display *dpy, Atom atom)
643 {
644 static char *result;
645 free(result);
646 if (atom != 0) {
647 result = XGetAtomName(dpy, atom);
648 } else {
649 result = x_strdup("NONE");
650 }
651 return result;
652 }
653
654 /*
655 * Trace the normal or alternate screen, showing color values up to 16, e.g.,
656 * for debugging with vttest.
657 */
658 void
659 TraceScreen(XtermWidget xw, int whichBuf)
660 {
661 TScreen *screen = TScreenOf(xw);
662
663 if (screen->editBuf_index[whichBuf]) {
664 int row;
665
666 TRACE(("TraceScreen %d:\n", whichBuf));
667 for (row = 0; row <= LastRowNumber(screen); ++row) {
668 LineData *ld = getLineData(screen, row);
669
670 TRACE((" %3d:", row));
671 if (ld != 0) {
672 int col;
673
674 for (col = 0; col < ld->lineSize; ++col) {
675 int ch = (int) ld->charData[col];
676 if (ch < ' ')
677 ch = ' ';
678 if (ch >= 127)
679 ch = '#';
680 TRACE(("%c", ch));
681 }
682 TRACE((":\n"));
683
684 #if 0
685 TRACE((" xx:"));
686 for (col = 0; col < ld->lineSize; ++col) {
687 unsigned attrs = ld->attribs[col];
688 char ch;
689 if (attrs & PROTECTED) {
690 ch = '*';
691 } else if (attrs & BLINK) {
692 ch = 'B';
693 } else if (attrs & CHARDRAWN) {
694 ch = '+';
695 } else {
696 ch = ' ';
697 }
698 TRACE(("%c", ch));
699 }
700 TRACE((":\n"));
701 #endif
702
703 #if 0
704 TRACE((" fg:"));
705 for (col = 0; col < ld->lineSize; ++col) {
706 unsigned fg = extract_fg(xw, ld->color[col], ld->attribs[col]);
707 if (fg > 15)
708 fg = 15;
709 TRACE(("%1x", fg));
710 }
711 TRACE((":\n"));
712
713 TRACE((" bg:"));
714 for (col = 0; col < ld->lineSize; ++col) {
715 unsigned bg = extract_bg(xw, ld->color[col], ld->attribs[col]);
716 if (bg > 15)
717 bg = 15;
718 TRACE(("%1x", bg));
719 }
720 TRACE((":\n"));
721 #endif
722 } else {
723 TRACE(("null lineData\n"));
724 }
725 }
726 } else {
727 TRACE(("TraceScreen %d is nil\n", whichBuf));
728 }
729 }
730
731 static char *
732 formatEventMask(char *target, unsigned source, Boolean buttons)
733 {
734 #define DATA(name) { name ## Mask, #name }
735 static struct {
736 unsigned mask;
737 const char *name;
738 } table[] = {
739 DATA(Shift),
740 DATA(Lock),
741 DATA(Control),
742 DATA(Mod1),
743 DATA(Mod2),
744 DATA(Mod3),
745 DATA(Mod4),
746 DATA(Mod5),
747 DATA(Button1),
748 DATA(Button2),
749 DATA(Button3),
750 DATA(Button4),
751 DATA(Button5),
752 };
753 #undef DATA
754 Cardinal n;
755 char marker = L_CURL;
756 char *base = target;
757
758 for (n = 0; n < XtNumber(table); ++n) {
759 if (!buttons && (table[n].mask >= Button1Mask))
760 continue;
761 if ((table[n].mask & source)) {
762 UIntClr(source, table[n].mask);
763 sprintf(target, "%c%s", marker, table[n].name);
764 target += strlen(target);
765 marker = '|';
766 }
767 }
768
769 if (source != 0) {
770 sprintf(target, "%c?%#x", marker, source);
771 target += strlen(target);
772 marker = '|';
773 }
774
775 if (marker == L_CURL)
776 *target++ = L_CURL;
777 *target++ = R_CURL;
778
779 *target = '\0';
780 return base;
781 }
782
783 void
784 TraceEvent(const char *tag, XEvent *ev, String *params, Cardinal *num_params)
785 {
786 char mask_buffer[160];
787
788 TRACE(("Event #%lu %s: %#lx %s",
789 ev->xany.serial,
790 tag,
791 ev->xany.window,
792 visibleEventType(ev->type)));
793
794 switch (ev->type) {
795 case KeyPress:
796 /* FALLTHRU */
797 case KeyRelease:
798 TRACE((" keycode 0x%04X %s",
799 ev->xkey.keycode,
800 formatEventMask(mask_buffer, ev->xkey.state, False)));
801 break;
802 case ButtonPress:
803 /* FALLTHRU */
804 case ButtonRelease:
805 TRACE((" button %u state %#x %s",
806 ev->xbutton.button,
807 ev->xbutton.state,
808 formatEventMask(mask_buffer, ev->xbutton.state, True)));
809 break;
810 case MotionNotify:
811 TRACE((" (%d,%d) state %#x %s",
812 ev->xmotion.y_root,
813 ev->xmotion.x_root,
814 ev->xmotion.state,
815 formatEventMask(mask_buffer, ev->xmotion.state, True)));
816 break;
817 case EnterNotify:
818 case LeaveNotify:
819 TRACE((" at %d,%d root %d,%d %s %s",
820 ev->xcrossing.y,
821 ev->xcrossing.x,
822 ev->xcrossing.y_root,
823 ev->xcrossing.x_root,
824 visibleNotifyMode(ev->xcrossing.mode),
825 visibleNotifyDetail(ev->xcrossing.detail)));
826 break;
827 case FocusIn:
828 case FocusOut:
829 TRACE((" %s %s",
830 visibleNotifyMode(ev->xfocus.mode),
831 visibleNotifyDetail(ev->xfocus.detail)));
832 break;
833 case MapNotify:
834 TRACE((" event %#lx %s",
835 ev->xmap.event,
836 ev->xmap.override_redirect ? "override" : ""));
837 break;
838 case UnmapNotify:
839 TRACE((" event %#lx %s",
840 ev->xunmap.event,
841 ev->xunmap.from_configure ? "configure" : ""));
842 break;
843 case ReparentNotify:
844 TRACE((" at %d,%d event %#lx parent %#lx %s",
845 ev->xreparent.y,
846 ev->xreparent.x,
847 ev->xreparent.event,
848 ev->xreparent.parent,
849 ev->xreparent.override_redirect ? "override" : ""));
850 break;
851 case ConfigureNotify:
852 TRACE((" at %d,%d size %dx%d bd %d above %#lx",
853 ev->xconfigure.y,
854 ev->xconfigure.x,
855 ev->xconfigure.height,
856 ev->xconfigure.width,
857 ev->xconfigure.border_width,
858 ev->xconfigure.above));
859 break;
860 case CreateNotify:
861 TRACE((" at %d,%d size %dx%d bd %d",
862 ev->xcreatewindow.y,
863 ev->xcreatewindow.x,
864 ev->xcreatewindow.height,
865 ev->xcreatewindow.width,
866 ev->xcreatewindow.border_width));
867 break;
868 case ResizeRequest:
869 TRACE((" size %dx%d",
870 ev->xresizerequest.height,
871 ev->xresizerequest.width));
872 break;
873 case PropertyNotify:
874 TRACE((" %s %s",
875 TraceAtomName(XtDisplay(toplevel), ev->xproperty.atom),
876 ((ev->xproperty.state == PropertyNewValue)
877 ? "NewValue"
878 : ((ev->xproperty.state == PropertyDelete)
879 ? "Delete"
880 : "?"))));
881
882 break;
883 case Expose:
884 TRACE((" at %d,%d size %dx%d count %d",
885 ev->xexpose.y,
886 ev->xexpose.x,
887 ev->xexpose.height,
888 ev->xexpose.width,
889 ev->xexpose.count));
890 break;
891 case MappingNotify:
892 TRACE((" %s first_keycode %d count %d",
893 visibleMappingMode(ev->xmapping.request),
894 ev->xmapping.first_keycode,
895 ev->xmapping.count));
896 break;
897 case VisibilityNotify:
898 TRACE((" state %d",
899 ev->xvisibility.state));
900 break;
901 case KeymapNotify:
902 {
903 Cardinal j;
904 for (j = 0; j < XtNumber(ev->xkeymap.key_vector); ++j) {
905 if (ev->xkeymap.key_vector[j] != 0) {
906 Cardinal k;
907 for (k = 0; k < CHAR_BIT; ++k) {
908 if (ev->xkeymap.key_vector[j] & (1 << k)) {
909 TRACE((" key%u", (j * CHAR_BIT) + k));
910 }
911 }
912 }
913 }
914 }
915 break;
916 case NoExpose:
917 TRACE((" send_event:%d display %p major:%d minor:%d",
918 ev->xnoexpose.send_event,
919 (void *) ev->xnoexpose.display,
920 ev->xnoexpose.major_code,
921 ev->xnoexpose.minor_code));
922 break;
923 case GraphicsExpose:
924 TRACE((" send_event:%d display %p major:%d minor:%d",
925 ev->xgraphicsexpose.send_event,
926 (void *) ev->xgraphicsexpose.display,
927 ev->xgraphicsexpose.major_code,
928 ev->xgraphicsexpose.minor_code));
929 break;
930 case SelectionClear:
931 TRACE((" selection:%s",
932 TraceAtomName(ev->xselectionclear.display,
933 ev->xselectionclear.selection)));
934 break;
935 case SelectionRequest:
936 TRACE((" owner:%#lx requestor:%#lx",
937 ev->xselectionrequest.owner,
938 ev->xselectionrequest.requestor));
939 TRACE((" selection:%s",
940 TraceAtomName(ev->xselectionrequest.display,
941 ev->xselectionrequest.selection)));
942 TRACE((" target:%s",
943 TraceAtomName(ev->xselectionrequest.display,
944 ev->xselectionrequest.target)));
945 TRACE((" property:%s",
946 TraceAtomName(ev->xselectionrequest.display,
947 ev->xselectionrequest.property)));
948 break;
949 default:
950 TRACE((":FIXME"));
951 break;
952 }
953 TRACE(("\n"));
954 if (params != 0 && *num_params != 0) {
955 Cardinal n;
956 for (n = 0; n < *num_params; ++n) {
957 TRACE((" param[%d] = %s\n", n, params[n]));
958 }
959 }
960 }
961
962 #if OPT_RENDERFONT && OPT_WIDE_CHARS
963 void
964 TraceFallback(XtermWidget xw, const char *tag, unsigned wc, int n, XftFont *font)
965 {
966 TScreen *screen = TScreenOf(xw);
967 XGlyphInfo gi;
968 int expect = my_wcwidth((wchar_t) wc);
969 int hijack = mk_wcwidth_cjk((wchar_t) wc);
970 int actual;
971
972 XftTextExtents32(screen->display, font, &wc, 1, &gi);
973 actual = ((gi.xOff + FontWidth(screen) - 1)
974 / FontWidth(screen));
975
976 TRACE(("FALLBACK #%d %s U+%04X %d,%d pos,"
977 " %d,%d off," " %dx%d size,"
978 " %d/%d next," " %d vs %d/%d cells%s\n",
979 n + 1, tag, wc,
980 gi.y, gi.x,
981 gi.yOff, gi.xOff,
982 gi.height, gi.width,
983 font->max_advance_width,
984 FontWidth(screen),
985 actual, expect, hijack,
986 ((actual != expect)
987 ? ((actual == hijack)
988 ? " OOPS"
989 : " oops")
990 : "")));
991 }
992 #endif /* OPT_RENDERFONT */
993
994 void
995 TraceFocus(Widget w, XEvent *ev)
996 {
997 TRACE(("trace_focus event type %d:%s\n",
998 ev->type, visibleEventType(ev->type)));
999 switch (ev->type) {
1000 case FocusIn:
1001 case FocusOut:
1002 {
1003 XFocusChangeEvent *event = (XFocusChangeEvent *) ev;
1004 TRACE(("\tdetail: %s\n", visibleNotifyDetail(event->detail)));
1005 TRACE(("\tmode: %s\n", visibleNotifyMode(event->mode)));
1006 TRACE(("\twindow: %#lx\n", event->window));
1007 }
1008 break;
1009 case EnterNotify:
1010 case LeaveNotify:
1011 {
1012 XCrossingEvent *event = (XCrossingEvent *) ev;
1013 TRACE(("\tdetail: %s\n", visibleNotifyDetail(event->detail)));
1014 TRACE(("\tmode: %s\n", visibleNotifyMode(event->mode)));
1015 TRACE(("\twindow: %#lx\n", event->window));
1016 TRACE(("\tfocus: %d\n", event->focus));
1017 TRACE(("\troot: %#lx\n", event->root));
1018 TRACE(("\tsubwindow: %#lx\n", event->subwindow));
1019 }
1020 break;
1021 }
1022 while (w != 0) {
1023 TRACE(("w %p -> %#lx\n", (void *) w, XtWindow(w)));
1024 w = XtParent(w);
1025 }
1026 }
1027
1028 void
1029 TraceSizeHints(XSizeHints * hints)
1030 {
1031 TRACE(("size hints:\n"));
1032 if (hints->flags & (USPosition | PPosition)) {
1033 TRACE((" position %d,%d%s%s\n", hints->y, hints->x,
1034 (hints->flags & USPosition) ? " user" : "",
1035 (hints->flags & PPosition) ? " prog" : ""));
1036 }
1037 if (hints->flags & (USSize | PSize)) {
1038 TRACE((" size %d,%d%s%s\n", hints->height, hints->width,
1039 (hints->flags & USSize) ? " user" : "",
1040 (hints->flags & PSize) ? " prog" : ""));
1041 }
1042 if (hints->flags & PMinSize) {
1043 TRACE((" min %d,%d\n", hints->min_height, hints->min_width));
1044 }
1045 if (hints->flags & PMaxSize) {
1046 TRACE((" max %d,%d\n", hints->max_height, hints->max_width));
1047 }
1048 if (hints->flags & PResizeInc) {
1049 TRACE((" inc %d,%d\n", hints->height_inc, hints->width_inc));
1050 } else {
1051 TRACE((" inc NONE!\n"));
1052 }
1053 if (hints->flags & PAspect) {
1054 TRACE((" min aspect %d/%d\n", hints->min_aspect.y, hints->min_aspect.y));
1055 TRACE((" max aspect %d/%d\n", hints->max_aspect.y, hints->max_aspect.y));
1056 }
1057 if (hints->flags & PBaseSize) {
1058 TRACE((" base %d,%d\n", hints->base_height, hints->base_width));
1059 }
1060 if (hints->flags & PWinGravity) {
1061 TRACE((" gravity %d\n", hints->win_gravity));
1062 }
1063 }
1064
1065 static void
1066 TraceEventMask(const char *tag, long mask)
1067 {
1068 #define DATA(name) { name##Mask, #name }
1069 /* *INDENT-OFF* */
1070 static struct {
1071 long mask;
1072 const char *name;
1073 } table[] = {
1074 DATA(KeyPress),
1075 DATA(KeyRelease),
1076 DATA(ButtonPress),
1077 DATA(ButtonRelease),
1078 DATA(EnterWindow),
1079 DATA(LeaveWindow),
1080 DATA(PointerMotion),
1081 DATA(PointerMotionHint),
1082 DATA(Button1Motion),
1083 DATA(Button2Motion),
1084 DATA(Button3Motion),
1085 DATA(Button4Motion),
1086 DATA(Button5Motion),
1087 DATA(ButtonMotion),
1088 DATA(KeymapState),
1089 DATA(Exposure),
1090 DATA(VisibilityChange),
1091 DATA(StructureNotify),
1092 DATA(ResizeRedirect),
1093 DATA(SubstructureNotify),
1094 DATA(SubstructureRedirect),
1095 DATA(FocusChange),
1096 DATA(PropertyChange),
1097 DATA(ColormapChange),
1098 DATA(OwnerGrabButton),
1099 };
1100 #undef DATA
1101 Cardinal n;
1102 /* *INDENT-ON* */
1103
1104 for (n = 0; n < XtNumber(table); ++n) {
1105 if (table[n].mask & mask) {
1106 TRACE(("%s %s\n", tag, table[n].name));
1107 }
1108 }
1109 }
1110
1111 void
1112 TraceWindowAttributes(XWindowAttributes * attrs)
1113 {
1114 TRACE(("window attributes:\n"));
1115 TRACE((" position %d,%d\n", attrs->y, attrs->x));
1116 TRACE((" size %dx%d\n", attrs->height, attrs->width));
1117 TRACE((" border %d\n", attrs->border_width));
1118 TRACE((" depth %d\n", attrs->depth));
1119 TRACE((" bit_gravity %d\n", attrs->bit_gravity));
1120 TRACE((" win_gravity %d\n", attrs->win_gravity));
1121 TRACE((" root %#lx\n", (long) attrs->root));
1122 TRACE((" class %s\n", ((attrs->class == InputOutput)
1123 ? "InputOutput"
1124 : ((attrs->class == InputOnly)
1125 ? "InputOnly"
1126 : "unknown"))));
1127 TRACE((" map_state %s\n", ((attrs->map_state == IsUnmapped)
1128 ? "IsUnmapped"
1129 : ((attrs->map_state == IsUnviewable)
1130 ? "IsUnviewable"
1131 : ((attrs->map_state == IsViewable)
1132 ? "IsViewable"
1133 : "unknown")))));
1134 TRACE((" all_events\n"));
1135 TraceEventMask(" ", attrs->all_event_masks);
1136 TRACE((" your_events\n"));
1137 TraceEventMask(" ", attrs->your_event_mask);
1138 TRACE((" no_propagate\n"));
1139 TraceEventMask(" ", attrs->do_not_propagate_mask);
1140 }
1141
1142 void
1143 TraceWMSizeHints(XtermWidget xw)
1144 {
1145 XSizeHints sizehints = xw->hints;
1146
1147 getXtermSizeHints(xw);
1148 TraceSizeHints(&xw->hints);
1149 xw->hints = sizehints;
1150 }
1151
1152 const char *
1153 ModifierName(unsigned modifier)
1154 {
1155 const char *s = "";
1156 if (modifier & ShiftMask)
1157 s = " Shift";
1158 else if (modifier & LockMask)
1159 s = " Lock";
1160 else if (modifier & ControlMask)
1161 s = " Control";
1162 else if (modifier & Mod1Mask)
1163 s = " Mod1";
1164 else if (modifier & Mod2Mask)
1165 s = " Mod2";
1166 else if (modifier & Mod3Mask)
1167 s = " Mod3";
1168 else if (modifier & Mod4Mask)
1169 s = " Mod4";
1170 else if (modifier & Mod5Mask)
1171 s = " Mod5";
1172 return s;
1173 }
1174
1175 void
1176 TraceTranslations(const char *name, Widget w)
1177 {
1178 String result;
1179 XErrorHandler save = XSetErrorHandler(ignore_x11_error);
1180 XtTranslations xlations;
1181 Widget xcelerat;
1182
1183 TRACE(("TraceTranslations for %s (widget %#lx) " TRACE_L "\n",
1184 name, (long) w));
1185 if (w) {
1186 XtVaGetValues(w,
1187 XtNtranslations, &xlations,
1188 XtNaccelerators, &xcelerat,
1189 (XtPointer) 0);
1190 TRACE(("... xlations %#08lx\n", (long) xlations));
1191 TRACE(("... xcelerat %#08lx\n", (long) xcelerat));
1192 result = _XtPrintXlations(w, xlations, xcelerat, True);
1193 TRACE(("%s\n", NonNull(result)));
1194 if (result)
1195 XFree((char *) result);
1196 } else {
1197 TRACE(("none (widget is null)\n"));
1198 }
1199 TRACE((TRACE_R "\n"));
1200 XSetErrorHandler(save);
1201 }
1202
1203 XtGeometryResult
1204 TraceResizeRequest(const char *fn, int ln, Widget w,
1205 unsigned reqwide,
1206 unsigned reqhigh,
1207 Dimension *gotwide,
1208 Dimension *gothigh)
1209 {
1210 XtGeometryResult rc;
1211
1212 TRACE(("%s@%d ResizeRequest %ux%u\n", fn, ln, reqhigh, reqwide));
1213 rc = XtMakeResizeRequest((Widget) w,
1214 (Dimension) reqwide,
1215 (Dimension) reqhigh,
1216 gotwide, gothigh);
1217 TRACE(("... ResizeRequest -> "));
1218 if (gothigh && gotwide)
1219 TRACE(("%dx%d ", *gothigh, *gotwide));
1220 TRACE(("(%d)\n", rc));
1221 return rc;
1222 }
1223
1224 #define XRES_S(name) Trace(#name " = %s\n", NonNull(resp->name))
1225 #define XRES_B(name) Trace(#name " = %s\n", MtoS(resp->name))
1226 #define XRES_I(name) Trace(#name " = %d\n", resp->name)
1227
1228 void
1229 TraceXtermResources(void)
1230 {
1231 XTERM_RESOURCE *resp = &resource;
1232
1233 Trace("XTERM_RESOURCE settings:\n");
1234 XRES_S(icon_geometry);
1235 XRES_S(title);
1236 XRES_S(icon_hint);
1237 XRES_S(icon_name);
1238 XRES_S(term_name);
1239 XRES_S(tty_modes);
1240 XRES_I(minBufSize);
1241 XRES_I(maxBufSize);
1242 XRES_B(hold_screen);
1243 XRES_B(utmpInhibit);
1244 XRES_B(utmpDisplayId);
1245 XRES_B(messages);
1246 XRES_S(menuLocale);
1247 XRES_S(omitTranslation);
1248 XRES_S(keyboardType);
1249 #ifdef HAVE_LIB_XCURSOR
1250 XRES_S(cursorTheme);
1251 #endif
1252 #if OPT_PRINT_ON_EXIT
1253 XRES_I(printModeNow);
1254 XRES_I(printModeOnXError);
1255 XRES_I(printOptsNow);
1256 XRES_I(printOptsOnXError);
1257 XRES_S(printFileNow);
1258 XRES_S(printFileOnXError);
1259 #endif
1260 #if OPT_SUNPC_KBD
1261 XRES_B(sunKeyboard);
1262 #endif
1263 #if OPT_HP_FUNC_KEYS
1264 XRES_B(hpFunctionKeys);
1265 #endif
1266 #if OPT_SCO_FUNC_KEYS
1267 XRES_B(scoFunctionKeys);
1268 #endif
1269 #if OPT_SUN_FUNC_KEYS
1270 XRES_B(sunFunctionKeys);
1271 #endif
1272 #if OPT_INITIAL_ERASE
1273 XRES_B(ptyInitialErase);
1274 XRES_B(backarrow_is_erase);
1275 #endif
1276 XRES_B(useInsertMode);
1277 #if OPT_ZICONBEEP
1278 XRES_I(zIconBeep);
1279 XRES_S(zIconFormat);
1280 #endif
1281 #if OPT_PTY_HANDSHAKE
1282 XRES_B(wait_for_map);
1283 XRES_B(ptyHandshake);
1284 XRES_B(ptySttySize);
1285 #endif
1286 #if OPT_REPORT_CCLASS
1287 XRES_B(reportCClass);
1288 #endif
1289 #if OPT_REPORT_COLORS
1290 XRES_B(reportColors);
1291 #endif
1292 #if OPT_REPORT_FONTS
1293 XRES_B(reportFonts);
1294 #endif
1295 #if OPT_REPORT_ICONS
1296 XRES_B(reportIcons);
1297 #endif
1298 #if OPT_SAME_NAME
1299 XRES_B(sameName);
1300 #endif
1301 #if OPT_SESSION_MGT
1302 XRES_B(sessionMgt);
1303 #endif
1304 #if OPT_TOOLBAR
1305 XRES_B(toolBar);
1306 #endif
1307 #if OPT_MAXIMIZE
1308 XRES_B(maximized);
1309 XRES_S(fullscreen_s);
1310 #endif
1311 #if USE_DOUBLE_BUFFER
1312 XRES_B(buffered);
1313 XRES_I(buffered_fps);
1314 #endif
1315 }
1316
1317 void
1318 TraceArgv(const char *tag, char **argv)
1319 {
1320 TRACE(("%s:\n", tag));
1321 if (argv != 0) {
1322 int n = 0;
1323
1324 while (*argv != 0) {
1325 TRACE((" %d:%s\n", n++, *argv++));
1326 }
1327 }
1328 }
1329
1330 static char *
1331 parse_option(char *dst, String src, int first)
1332 {
1333 char *s;
1334
1335 if (!strncmp(src, "-/+", (size_t) 3)) {
1336 dst[0] = (char) first;
1337 strcpy(dst + 1, src + 3);
1338 } else {
1339 strcpy(dst, src);
1340 }
1341 for (s = dst; *s != '\0'; s++) {
1342 if (*s == '#' || *s == '%' || *s == 'S') {
1343 s[1] = '\0';
1344 } else if (*s == ' ') {
1345 *s = '\0';
1346 break;
1347 }
1348 }
1349 return dst;
1350 }
1351
1352 static Bool
1353 same_option(OptionHelp * opt, XrmOptionDescRec * res)
1354 {
1355 char temp[BUFSIZ];
1356 return !strcmp(parse_option(temp, opt->opt, res->option[0]), res->option);
1357 }
1358
1359 static Bool
1360 standard_option(String opt)
1361 {
1362 static const char *table[] =
1363 {
1364 "+rv",
1365 "+synchronous",
1366 "-background",
1367 "-bd",
1368 "-bg",
1369 "-bordercolor",
1370 "-borderwidth",
1371 "-bw",
1372 "-display",
1373 "-fg",
1374 "-fn",
1375 "-font",
1376 "-foreground",
1377 "-geometry",
1378 "-iconic",
1379 "-name",
1380 "-reverse",
1381 "-rv",
1382 "-selectionTimeout",
1383 "-synchronous",
1384 "-title",
1385 "-xnllanguage",
1386 "-xrm",
1387 "-xtsessionID",
1388 };
1389 Cardinal n;
1390 char temp[BUFSIZ];
1391
1392 opt = parse_option(temp, opt, '-');
1393 for (n = 0; n < XtNumber(table); n++) {
1394 if (!strcmp(opt, table[n]))
1395 return True;
1396 }
1397 return False;
1398 }
1399
1400 /*
1401 * Analyse the options/help messages for inconsistencies.
1402 */
1403 void
1404 TraceOptions(OptionHelp * options, XrmOptionDescRec * resources, Cardinal res_count)
1405 {
1406 OptionHelp *opt_array = sortedOpts(options, resources, res_count);
1407 size_t j, k;
1408 XrmOptionDescRec *res_array = sortedOptDescs(resources, res_count);
1409 Bool first, found;
1410
1411 TRACE(("Checking options-tables for inconsistencies:\n"));
1412
1413 #if 0
1414 TRACE(("Options listed in help-message:\n"));
1415 for (j = 0; options[j].opt != 0; j++)
1416 TRACE(("%5d %-28s %s\n", j, opt_array[j].opt, opt_array[j].desc));
1417 TRACE(("Options listed in resource-table:\n"));
1418 for (j = 0; j < res_count; j++)
1419 TRACE(("%5d %-28s %s\n", j, res_array[j].option, res_array[j].specifier));
1420 #endif
1421
1422 /* list all options[] not found in resources[] */
1423 for (j = 0, first = True; options[j].opt != 0; j++) {
1424 found = False;
1425 for (k = 0; k < res_count; k++) {
1426 if (same_option(&opt_array[j], &res_array[k])) {
1427 found = True;
1428 break;
1429 }
1430 }
1431 if (!found) {
1432 if (first) {
1433 TRACE(("Options listed in help, not found in resource list:\n"));
1434 first = False;
1435 }
1436 TRACE((" %-28s%s\n", opt_array[j].opt,
1437 standard_option(opt_array[j].opt) ? " (standard)" : ""));
1438 }
1439 }
1440
1441 /* list all resources[] not found in options[] */
1442 for (j = 0, first = True; j < res_count; j++) {
1443 found = False;
1444 for (k = 0; options[k].opt != 0; k++) {
1445 if (same_option(&opt_array[k], &res_array[j])) {
1446 found = True;
1447 break;
1448 }
1449 }
1450 if (!found) {
1451 if (first) {
1452 TRACE(("Resource list items not found in options-help:\n"));
1453 first = False;
1454 }
1455 TRACE((" %s\n", res_array[j].option));
1456 }
1457 }
1458
1459 TRACE(("Resource list items that will be ignored by XtOpenApplication:\n"));
1460 for (j = 0; j < res_count; j++) {
1461 switch (res_array[j].argKind) {
1462 case XrmoptionSkipArg:
1463 TRACE((" %-28s {param}\n", res_array[j].option));
1464 break;
1465 case XrmoptionSkipNArgs:
1466 TRACE((" %-28s {%ld params}\n", res_array[j].option, (long)
1467 res_array[j].value));
1468 break;
1469 case XrmoptionSkipLine:
1470 TRACE((" %-28s {remainder of line}\n", res_array[j].option));
1471 break;
1472 case XrmoptionIsArg:
1473 case XrmoptionNoArg:
1474 case XrmoptionResArg:
1475 case XrmoptionSepArg:
1476 case XrmoptionStickyArg:
1477 default:
1478 break;
1479 }
1480 }
1481 }
1482 #else
1483 extern void empty_trace(void);
1484 void
1485 empty_trace(void)
1486 {
1487 }
1488 #endif