trace.c revision 2e4f8982
1/* $XTermId: trace.c,v 1.166 2016/10/05 09:16:01 tom Exp $ */ 2 3/* 4 * Copyright 1997-2015,2016 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 <version.h> 39 40#if OPT_TRACE 41 42#include <data.h> 43#include <trace.h> 44 45#include <time.h> 46#include <stdlib.h> 47#include <unistd.h> 48#include <sys/types.h> 49#include <sys/stat.h> 50#include <stdio.h> 51#include <stdarg.h> 52#include <assert.h> 53 54#include <X11/Xatom.h> 55#include <X11/Xmu/Atoms.h> 56 57#ifdef HAVE_X11_TRANSLATEI_H 58#include <X11/ConvertI.h> 59#include <X11/TranslateI.h> 60#else 61#ifdef __cplusplus 62extern "C" { 63#endif 64 65 extern String _XtPrintXlations(Widget w, 66 XtTranslations xlations, 67 Widget accelWidget, 68 _XtBoolean includeRHS); 69#ifdef __cplusplus 70} 71#endif 72#endif 73const char *trace_who = "parent"; 74 75static FILE *trace_fp; 76 77void 78Trace(const char *fmt,...) 79{ 80 static const char *trace_out; 81 va_list ap; 82 83 if (trace_fp != 0 84 && trace_who != trace_out) { 85 fclose(trace_fp); 86 trace_fp = 0; 87 } 88 trace_out = trace_who; 89 90 if (!trace_fp) { 91 unsigned oldmask = (unsigned) umask(077); 92 char name[BUFSIZ]; 93#if 0 /* usually I do not want unique names */ 94 int unique; 95 for (unique = 0;; ++unique) { 96 if (unique) 97 sprintf(name, "Trace-%s.out-%d", trace_who, unique); 98 else 99 sprintf(name, "Trace-%s.out", trace_who); 100 if ((trace_fp = fopen(name, "r")) == 0) { 101 break; 102 } 103 fclose(trace_fp); 104 } 105#else 106 sprintf(name, "Trace-%s.out", trace_who); 107#endif 108 trace_fp = fopen(name, "w"); 109 /* 110 * Try to put the trace-file in user's home-directory if the current 111 * directory is not writable. 112 */ 113 if (trace_fp == 0) { 114 char *home = getenv("HOME"); 115 if (home != 0) { 116 sprintf(name, "%.*s/Trace-%.8s.out", 117 (BUFSIZ - 21), home, 118 trace_who); 119 trace_fp = fopen(name, "w"); 120 } 121 } 122 if (trace_fp != 0) { 123 fprintf(trace_fp, "%s\n", xtermVersion()); 124 TraceIds(NULL, 0); 125 } 126 if (!trace_fp) { 127 xtermWarning("Cannot open \"%s\"\n", name); 128 exit(EXIT_FAILURE); 129 } 130 (void) umask(oldmask); 131 } 132 133 va_start(ap, fmt); 134 vfprintf(trace_fp, fmt, ap); 135 (void) fflush(trace_fp); 136 va_end(ap); 137} 138 139void 140TraceClose(void) 141{ 142 if (trace_fp != 0) { 143 (void) fclose(trace_fp); 144 (void) fflush(stdout); 145 (void) fflush(stderr); 146 (void) visibleChars(NULL, 0); 147 (void) visibleIChars(NULL, 0); 148 trace_fp = 0; 149 } 150} 151 152void 153TraceIds(const char *fname, int lnum) 154{ 155 Trace("process %d ", (int) getpid()); 156#ifdef HAVE_UNISTD_H 157 Trace("real (%u/%u) effective (%u/%u)", 158 (unsigned) getuid(), (unsigned) getgid(), 159 (unsigned) geteuid(), (unsigned) getegid()); 160#endif 161 if (fname != 0) { 162 Trace(" (%s@%d)\n", fname, lnum); 163 } else { 164 time_t now = time((time_t *) 0); 165 Trace("-- %s", ctime(&now)); 166 } 167} 168 169void 170TraceTime(const char *fname, int lnum) 171{ 172 time_t now; 173 if (fname != 0) { 174 Trace("datetime (%s@%d) ", fname, lnum); 175 } 176 now = time((time_t *) 0); 177 Trace("-- %s", ctime(&now)); 178} 179 180static void 181formatAscii(char *dst, unsigned value) 182{ 183 switch (value) { 184 case '\\': 185 sprintf(dst, "\\\\"); 186 break; 187 case '\b': 188 sprintf(dst, "\\b"); 189 break; 190 case '\n': 191 sprintf(dst, "\\n"); 192 break; 193 case '\r': 194 sprintf(dst, "\\r"); 195 break; 196 case '\t': 197 sprintf(dst, "\\t"); 198 break; 199 default: 200 if (E2A(value) < 32 || (E2A(value) >= 127 && E2A(value) < 160)) 201 sprintf(dst, "\\%03o", value & 0xff); 202 else 203 sprintf(dst, "%c", CharOf(value)); 204 break; 205 } 206} 207 208#if OPT_DEC_CHRSET 209 210const char * 211visibleDblChrset(unsigned chrset) 212{ 213 const char *result = "?"; 214 switch (chrset) { 215 case CSET_SWL: 216 result = "CSET_SWL"; 217 break; 218 case CSET_DHL_TOP: 219 result = "CSET_DHL_TOP"; 220 break; 221 case CSET_DHL_BOT: 222 result = "CSET_DHL_BOT"; 223 break; 224 case CSET_DWL: 225 result = "CSET_DWL"; 226 break; 227 } 228 return result; 229} 230#endif 231 232const char * 233visibleScsCode(int chrset) 234{ 235#define MAP(to,from) case from: result = to; break 236 const char *result = "<ERR>"; 237 switch ((DECNRCM_codes) chrset) { 238 MAP("B", nrc_ASCII); 239 MAP("A", nrc_British); 240 MAP("A", nrc_British_Latin_1); 241 MAP("&4", nrc_Cyrillic); 242 MAP("0", nrc_DEC_Spec_Graphic); 243 MAP("1", nrc_DEC_Alt_Chars); 244 MAP("2", nrc_DEC_Alt_Graphics); 245 MAP("<", nrc_DEC_Supp); 246 MAP("%5", nrc_DEC_Supp_Graphic); 247 MAP(">", nrc_DEC_Technical); 248 MAP("4", nrc_Dutch); 249 MAP("5", nrc_Finnish); 250 MAP("C", nrc_Finnish2); 251 MAP("R", nrc_French); 252 MAP("f", nrc_French2); 253 MAP("Q", nrc_French_Canadian); 254 MAP("9", nrc_French_Canadian2); 255 MAP("K", nrc_German); 256 MAP("\"?", nrc_Greek); 257 MAP("F", nrc_Greek_Supp); 258 MAP("\"4", nrc_Hebrew); 259 MAP("%=", nrc_Hebrew2); 260 MAP("H", nrc_Hebrew_Supp); 261 MAP("Y", nrc_Italian); 262 MAP("M", nrc_Latin_5_Supp); 263 MAP("L", nrc_Latin_Cyrillic); 264 MAP("`", nrc_Norwegian_Danish); 265 MAP("E", nrc_Norwegian_Danish2); 266 MAP("6", nrc_Norwegian_Danish3); 267 MAP("%6", nrc_Portugese); 268 MAP("&5", nrc_Russian); 269 MAP("%3", nrc_SCS_NRCS); 270 MAP("Z", nrc_Spanish); 271 MAP("7", nrc_Swedish); 272 MAP("H", nrc_Swedish2); 273 MAP("=", nrc_Swiss); 274 MAP("%0", nrc_Turkish); 275 MAP("%2", nrc_Turkish2); 276 MAP("<UNK>", nrc_Unknown); 277 } 278#undef MAP 279 return result; 280} 281 282const char * 283visibleChars(const Char *buf, unsigned len) 284{ 285 static char *result; 286 static unsigned used; 287 288 if (buf != 0) { 289 unsigned limit = ((len + 1) * 8) + 1; 290 291 if (limit > used) { 292 used = limit; 293 result = XtRealloc(result, used); 294 } 295 if (result != 0) { 296 char *dst = result; 297 *dst = '\0'; 298 while (len--) { 299 unsigned value = *buf++; 300 formatAscii(dst, value); 301 dst += strlen(dst); 302 } 303 } 304 } else if (result != 0) { 305 free(result); 306 result = 0; 307 used = 0; 308 } 309 return NonNull(result); 310} 311 312const char * 313visibleIChars(const IChar *buf, unsigned len) 314{ 315 static char *result; 316 static unsigned used; 317 318 if (buf != 0) { 319 unsigned limit = ((len + 1) * 8) + 1; 320 321 if (limit > used) { 322 used = limit; 323 result = XtRealloc(result, used); 324 } 325 if (result != 0) { 326 char *dst = result; 327 *dst = '\0'; 328 while (len--) { 329 unsigned value = *buf++; 330#if OPT_WIDE_CHARS 331 if (value > 255) 332 sprintf(dst, "\\u+%04X", value); 333 else 334#endif 335 formatAscii(dst, value); 336 dst += strlen(dst); 337 } 338 } 339 } else if (result != 0) { 340 free(result); 341 result = 0; 342 used = 0; 343 } 344 return NonNull(result); 345} 346 347const char * 348visibleUChar(unsigned chr) 349{ 350 IChar buf[1]; 351 buf[0] = chr; 352 return visibleIChars(buf, 1); 353} 354 355const char * 356visibleEventType(int type) 357{ 358 const char *result = "?"; 359 switch (type) { 360 CASETYPE(KeyPress); 361 CASETYPE(KeyRelease); 362 CASETYPE(ButtonPress); 363 CASETYPE(ButtonRelease); 364 CASETYPE(MotionNotify); 365 CASETYPE(EnterNotify); 366 CASETYPE(LeaveNotify); 367 CASETYPE(FocusIn); 368 CASETYPE(FocusOut); 369 CASETYPE(KeymapNotify); 370 CASETYPE(Expose); 371 CASETYPE(GraphicsExpose); 372 CASETYPE(NoExpose); 373 CASETYPE(VisibilityNotify); 374 CASETYPE(CreateNotify); 375 CASETYPE(DestroyNotify); 376 CASETYPE(UnmapNotify); 377 CASETYPE(MapNotify); 378 CASETYPE(MapRequest); 379 CASETYPE(ReparentNotify); 380 CASETYPE(ConfigureNotify); 381 CASETYPE(ConfigureRequest); 382 CASETYPE(GravityNotify); 383 CASETYPE(ResizeRequest); 384 CASETYPE(CirculateNotify); 385 CASETYPE(CirculateRequest); 386 CASETYPE(PropertyNotify); 387 CASETYPE(SelectionClear); 388 CASETYPE(SelectionRequest); 389 CASETYPE(SelectionNotify); 390 CASETYPE(ColormapNotify); 391 CASETYPE(ClientMessage); 392 CASETYPE(MappingNotify); 393 } 394 return result; 395} 396 397const char * 398visibleNotifyMode(int code) 399{ 400 const char *result = "?"; 401 switch (code) { 402 CASETYPE(NotifyNormal); 403 CASETYPE(NotifyGrab); 404 CASETYPE(NotifyUngrab); 405 CASETYPE(NotifyWhileGrabbed); 406 } 407 return result; 408} 409 410const char * 411visibleNotifyDetail(int code) 412{ 413 const char *result = "?"; 414 switch (code) { 415 CASETYPE(NotifyAncestor); 416 CASETYPE(NotifyVirtual); 417 CASETYPE(NotifyInferior); 418 CASETYPE(NotifyNonlinear); 419 CASETYPE(NotifyNonlinearVirtual); 420 CASETYPE(NotifyPointer); 421 CASETYPE(NotifyPointerRoot); 422 CASETYPE(NotifyDetailNone); 423 } 424 return result; 425} 426 427const char * 428visibleSelectionTarget(Display *d, Atom a) 429{ 430 const char *result = "?"; 431 432 if (a == XA_STRING) { 433 result = "XA_STRING"; 434 } else if (a == XA_TEXT(d)) { 435 result = "XA_TEXT()"; 436 } else if (a == XA_COMPOUND_TEXT(d)) { 437 result = "XA_COMPOUND_TEXT()"; 438 } else if (a == XA_UTF8_STRING(d)) { 439 result = "XA_UTF8_STRING()"; 440 } else if (a == XA_TARGETS(d)) { 441 result = "XA_TARGETS()"; 442 } 443 444 return result; 445} 446 447const char * 448visibleTekparse(int code) 449{ 450 static const struct { 451 int code; 452 const char *name; 453 } table[] = { 454#include "Tekparse.cin" 455 }; 456 const char *result = "?"; 457 Cardinal n; 458 for (n = 0; n < XtNumber(table); ++n) { 459 if (table[n].code == code) { 460 result = table[n].name; 461 break; 462 } 463 } 464 return result; 465} 466 467const char * 468visibleVTparse(int code) 469{ 470 static const struct { 471 int code; 472 const char *name; 473 } table[] = { 474#include "VTparse.cin" 475 }; 476 const char *result = "?"; 477 Cardinal n; 478 for (n = 0; n < XtNumber(table); ++n) { 479 if (table[n].code == code) { 480 result = table[n].name; 481 break; 482 } 483 } 484 return result; 485} 486 487const char * 488visibleXError(int code) 489{ 490 static char temp[80]; 491 const char *result = "?"; 492 switch (code) { 493 CASETYPE(Success); 494 CASETYPE(BadRequest); 495 CASETYPE(BadValue); 496 CASETYPE(BadWindow); 497 CASETYPE(BadPixmap); 498 CASETYPE(BadAtom); 499 CASETYPE(BadCursor); 500 CASETYPE(BadFont); 501 CASETYPE(BadMatch); 502 CASETYPE(BadDrawable); 503 CASETYPE(BadAccess); 504 CASETYPE(BadAlloc); 505 CASETYPE(BadColor); 506 CASETYPE(BadGC); 507 CASETYPE(BadIDChoice); 508 CASETYPE(BadName); 509 CASETYPE(BadLength); 510 CASETYPE(BadImplementation); 511 default: 512 sprintf(temp, "%d", code); 513 result = temp; 514 break; 515 } 516 return result; 517} 518 519#if OPT_TRACE_FLAGS 520#define isScrnFlag(flag) ((flag) == LINEWRAPPED) 521 522static char * 523ScrnText(LineData *ld) 524{ 525 return visibleIChars(ld->charData, ld->lineSize); 526} 527 528#define SHOW_BAD_LINE(name, ld) \ 529 Trace("OOPS " #name " bad row\n") 530 531#define SHOW_SCRN_FLAG(name,code) \ 532 Trace(#name " %s:%s\n", \ 533 code ? "*" : "", \ 534 ScrnText(ld)) 535 536void 537LineClrFlag(LineData *ld, int flag) 538{ 539 if (ld == 0) { 540 SHOW_BAD_LINE(LineClrFlag, ld); 541 assert(0); 542 } else if (isScrnFlag(flag)) { 543 SHOW_SCRN_FLAG(LineClrFlag, 0); 544 } 545 546 LineFlags(ld) &= ~flag; 547} 548 549void 550LineSetFlag(LineData *ld, int flag) 551{ 552 if (ld == 0) { 553 SHOW_BAD_LINE(LineSetFlag, ld); 554 assert(0); 555 } else if (isScrnFlag(flag)) { 556 SHOW_SCRN_FLAG(LineSetFlag, 1); 557 } 558 559 LineFlags(ld) |= flag; 560} 561 562int 563LineTstFlag(LineData ld, int flag) 564{ 565 int code = 0; 566 if (ld == 0) { 567 SHOW_BAD_LINE(LineTstFlag, ld); 568 } else { 569 code = LineFlags(ld); 570 571 if (isScrnFlag(flag)) { 572 SHOW_SCRN_FLAG(LineTstFlag, code); 573 } 574 } 575 return code; 576} 577#endif /* OPT_TRACE_FLAGS */ 578 579/* 580 * Trace the normal or alternate screen, showing color values up to 16, e.g., 581 * for debugging with vttest. 582 */ 583void 584TraceScreen(XtermWidget xw, int whichBuf) 585{ 586 TScreen *screen = TScreenOf(xw); 587 588 if (screen->editBuf_index[whichBuf]) { 589 int row; 590 591 TRACE(("TraceScreen %d:\n", whichBuf)); 592 for (row = 0; row <= screen->max_row; ++row) { 593 LineData *ld = getLineData(screen, row); 594 595 TRACE((" %3d:", row)); 596 if (ld != 0) { 597 int col; 598 599 for (col = 0; col < ld->lineSize; ++col) { 600 int ch = (int) ld->charData[col]; 601 if (ch < ' ') 602 ch = ' '; 603 if (ch >= 127) 604 ch = '#'; 605 TRACE(("%c", ch)); 606 } 607 TRACE((":\n")); 608 609 TRACE((" xx:")); 610 for (col = 0; col < ld->lineSize; ++col) { 611 unsigned attrs = ld->attribs[col]; 612 char ch; 613 if (attrs & PROTECTED) { 614 ch = '*'; 615 } else if (attrs & BLINK) { 616 ch = 'B'; 617 } else if (attrs & CHARDRAWN) { 618 ch = '+'; 619 } else { 620 ch = ' '; 621 } 622 TRACE(("%c", ch)); 623 } 624 TRACE((":\n")); 625 626#if 0 627 TRACE((" fg:")); 628 for (col = 0; col < ld->lineSize; ++col) { 629 unsigned fg = extract_fg(xw, ld->color[col], ld->attribs[col]); 630 if (fg > 15) 631 fg = 15; 632 TRACE(("%1x", fg)); 633 } 634 TRACE((":\n")); 635 636 TRACE((" bg:")); 637 for (col = 0; col < ld->lineSize; ++col) { 638 unsigned bg = extract_bg(xw, ld->color[col], ld->attribs[col]); 639 if (bg > 15) 640 bg = 15; 641 TRACE(("%1x", bg)); 642 } 643 TRACE((":\n")); 644#endif 645 } else { 646 TRACE(("null lineData\n")); 647 } 648 } 649 } else { 650 TRACE(("TraceScreen %d is nil\n", whichBuf)); 651 } 652} 653 654void 655TraceFocus(Widget w, XEvent *ev) 656{ 657 TRACE(("trace_focus event type %d:%s\n", 658 ev->type, visibleEventType(ev->type))); 659 switch (ev->type) { 660 case FocusIn: 661 case FocusOut: 662 { 663 XFocusChangeEvent *event = (XFocusChangeEvent *) ev; 664 TRACE(("\tdetail: %s\n", visibleNotifyDetail(event->detail))); 665 TRACE(("\tmode: %s\n", visibleNotifyMode(event->mode))); 666 TRACE(("\twindow: %#lx\n", event->window)); 667 } 668 break; 669 case EnterNotify: 670 case LeaveNotify: 671 { 672 XCrossingEvent *event = (XCrossingEvent *) ev; 673 TRACE(("\tdetail: %s\n", visibleNotifyDetail(event->detail))); 674 TRACE(("\tmode: %s\n", visibleNotifyMode(event->mode))); 675 TRACE(("\twindow: %#lx\n", event->window)); 676 TRACE(("\tfocus: %d\n", event->focus)); 677 TRACE(("\troot: %#lx\n", event->root)); 678 TRACE(("\tsubwindow: %#lx\n", event->subwindow)); 679 } 680 break; 681 } 682 while (w != 0) { 683 TRACE(("w %p -> %#lx\n", (void *) w, XtWindow(w))); 684 w = XtParent(w); 685 } 686} 687 688void 689TraceSizeHints(XSizeHints * hints) 690{ 691 TRACE(("size hints:\n")); 692 if (hints->flags & (USPosition | PPosition)) 693 TRACE((" position %d,%d%s%s\n", hints->y, hints->x, 694 (hints->flags & USPosition) ? " user" : "", 695 (hints->flags & PPosition) ? " prog" : "")); 696 if (hints->flags & (USSize | PSize)) 697 TRACE((" size %d,%d%s%s\n", hints->height, hints->width, 698 (hints->flags & USSize) ? " user" : "", 699 (hints->flags & PSize) ? " prog" : "")); 700 if (hints->flags & PMinSize) 701 TRACE((" min %d,%d\n", hints->min_height, hints->min_width)); 702 if (hints->flags & PMaxSize) 703 TRACE((" max %d,%d\n", hints->max_height, hints->max_width)); 704 if (hints->flags & PResizeInc) 705 TRACE((" inc %d,%d\n", hints->height_inc, hints->width_inc)); 706 else 707 TRACE((" inc NONE!\n")); 708 if (hints->flags & PAspect) 709 TRACE((" min aspect %d/%d\n", hints->min_aspect.y, hints->min_aspect.y)); 710 if (hints->flags & PAspect) 711 TRACE((" max aspect %d/%d\n", hints->max_aspect.y, hints->max_aspect.y)); 712 if (hints->flags & PBaseSize) 713 TRACE((" base %d,%d\n", hints->base_height, hints->base_width)); 714 if (hints->flags & PWinGravity) 715 TRACE((" gravity %d\n", hints->win_gravity)); 716} 717 718static void 719TraceEventMask(const char *tag, long mask) 720{ 721#define DATA(name) { name##Mask, #name } 722 /* *INDENT-OFF* */ 723 static struct { 724 long mask; 725 const char *name; 726 } table[] = { 727 DATA(KeyPress), 728 DATA(KeyRelease), 729 DATA(ButtonPress), 730 DATA(ButtonRelease), 731 DATA(EnterWindow), 732 DATA(LeaveWindow), 733 DATA(PointerMotion), 734 DATA(PointerMotionHint), 735 DATA(Button1Motion), 736 DATA(Button2Motion), 737 DATA(Button3Motion), 738 DATA(Button4Motion), 739 DATA(Button5Motion), 740 DATA(ButtonMotion), 741 DATA(KeymapState), 742 DATA(Exposure), 743 DATA(VisibilityChange), 744 DATA(StructureNotify), 745 DATA(ResizeRedirect), 746 DATA(SubstructureNotify), 747 DATA(SubstructureRedirect), 748 DATA(FocusChange), 749 DATA(PropertyChange), 750 DATA(ColormapChange), 751 DATA(OwnerGrabButton), 752 }; 753#undef DATA 754 Cardinal n; 755 /* *INDENT-ON* */ 756 757 for (n = 0; n < XtNumber(table); ++n) { 758 if (table[n].mask & mask) { 759 TRACE(("%s %s\n", tag, table[n].name)); 760 } 761 } 762} 763 764void 765TraceWindowAttributes(XWindowAttributes * attrs) 766{ 767 TRACE(("window attributes:\n")); 768 TRACE((" position %d,%d\n", attrs->y, attrs->x)); 769 TRACE((" size %dx%d\n", attrs->height, attrs->width)); 770 TRACE((" border %d\n", attrs->border_width)); 771 TRACE((" depth %d\n", attrs->depth)); 772 TRACE((" bit_gravity %d\n", attrs->bit_gravity)); 773 TRACE((" win_gravity %d\n", attrs->win_gravity)); 774 TRACE((" root %#lx\n", (long) attrs->root)); 775 TRACE((" class %s\n", ((attrs->class == InputOutput) 776 ? "InputOutput" 777 : ((attrs->class == InputOnly) 778 ? "InputOnly" 779 : "unknown")))); 780 TRACE((" map_state %s\n", ((attrs->map_state == IsUnmapped) 781 ? "IsUnmapped" 782 : ((attrs->map_state == IsUnviewable) 783 ? "IsUnviewable" 784 : ((attrs->map_state == IsViewable) 785 ? "IsViewable" 786 : "unknown"))))); 787 TRACE((" all_events\n")); 788 TraceEventMask(" ", attrs->all_event_masks); 789 TRACE((" your_events\n")); 790 TraceEventMask(" ", attrs->your_event_mask); 791 TRACE((" no_propagate\n")); 792 TraceEventMask(" ", attrs->do_not_propagate_mask); 793} 794 795void 796TraceWMSizeHints(XtermWidget xw) 797{ 798 XSizeHints sizehints = xw->hints; 799 800 getXtermSizeHints(xw); 801 TraceSizeHints(&xw->hints); 802 xw->hints = sizehints; 803} 804 805/* 806 * Some calls to XGetAtom() will fail, and we don't want to stop. So we use 807 * our own error-handler. 808 */ 809/* ARGSUSED */ 810static int 811no_error(Display *dpy GCC_UNUSED, XErrorEvent *event GCC_UNUSED) 812{ 813 return 1; 814} 815 816const char * 817ModifierName(unsigned modifier) 818{ 819 const char *s = ""; 820 if (modifier & ShiftMask) 821 s = " Shift"; 822 else if (modifier & LockMask) 823 s = " Lock"; 824 else if (modifier & ControlMask) 825 s = " Control"; 826 else if (modifier & Mod1Mask) 827 s = " Mod1"; 828 else if (modifier & Mod2Mask) 829 s = " Mod2"; 830 else if (modifier & Mod3Mask) 831 s = " Mod3"; 832 else if (modifier & Mod4Mask) 833 s = " Mod4"; 834 else if (modifier & Mod5Mask) 835 s = " Mod5"; 836 return s; 837} 838 839void 840TraceTranslations(const char *name, Widget w) 841{ 842 String result; 843 XErrorHandler save = XSetErrorHandler(no_error); 844 XtTranslations xlations; 845 Widget xcelerat; 846 847 TRACE(("TraceTranslations for %s (widget %#lx) {{\n", name, (long) w)); 848 if (w) { 849 XtVaGetValues(w, 850 XtNtranslations, &xlations, 851 XtNaccelerators, &xcelerat, 852 (XtPointer) 0); 853 TRACE(("... xlations %#08lx\n", (long) xlations)); 854 TRACE(("... xcelerat %#08lx\n", (long) xcelerat)); 855 result = _XtPrintXlations(w, xlations, xcelerat, True); 856 TRACE(("%s\n", NonNull(result))); 857 if (result) 858 XFree((char *) result); 859 } else { 860 TRACE(("none (widget is null)\n")); 861 } 862 TRACE(("}}\n")); 863 XSetErrorHandler(save); 864} 865 866XtGeometryResult 867TraceResizeRequest(const char *fn, int ln, Widget w, 868 unsigned reqwide, 869 unsigned reqhigh, 870 Dimension *gotwide, 871 Dimension *gothigh) 872{ 873 XtGeometryResult rc; 874 875 TRACE(("%s@%d ResizeRequest %ux%u\n", fn, ln, reqhigh, reqwide)); 876 rc = XtMakeResizeRequest((Widget) w, 877 (Dimension) reqwide, 878 (Dimension) reqhigh, 879 gotwide, gothigh); 880 TRACE(("... ResizeRequest -> ")); 881 if (gothigh && gotwide) 882 TRACE(("%dx%d ", *gothigh, *gotwide)); 883 TRACE(("(%d)\n", rc)); 884 return rc; 885} 886 887#define XRES_S(name) Trace(#name " = %s\n", NonNull(resp->name)) 888#define XRES_B(name) Trace(#name " = %s\n", MtoS(resp->name)) 889#define XRES_I(name) Trace(#name " = %d\n", resp->name) 890 891void 892TraceXtermResources(void) 893{ 894 XTERM_RESOURCE *resp = &resource; 895 896 Trace("XTERM_RESOURCE settings:\n"); 897 XRES_S(icon_geometry); 898 XRES_S(title); 899 XRES_S(icon_hint); 900 XRES_S(icon_name); 901 XRES_S(term_name); 902 XRES_S(tty_modes); 903 XRES_I(minBufSize); 904 XRES_I(maxBufSize); 905 XRES_B(hold_screen); 906 XRES_B(utmpInhibit); 907 XRES_B(utmpDisplayId); 908 XRES_B(messages); 909 XRES_S(menuLocale); 910 XRES_S(omitTranslation); 911 XRES_S(keyboardType); 912#if OPT_PRINT_ON_EXIT 913 XRES_I(printModeNow); 914 XRES_I(printModeOnXError); 915 XRES_I(printOptsNow); 916 XRES_I(printOptsOnXError); 917 XRES_S(printFileNow); 918 XRES_S(printFileOnXError); 919#endif 920#if OPT_SUNPC_KBD 921 XRES_B(sunKeyboard); 922#endif 923#if OPT_HP_FUNC_KEYS 924 XRES_B(hpFunctionKeys); 925#endif 926#if OPT_SCO_FUNC_KEYS 927 XRES_B(scoFunctionKeys); 928#endif 929#if OPT_SUN_FUNC_KEYS 930 XRES_B(sunFunctionKeys); 931#endif 932#if OPT_INITIAL_ERASE 933 XRES_B(ptyInitialErase); 934 XRES_B(backarrow_is_erase); 935#endif 936 XRES_B(useInsertMode); 937#if OPT_ZICONBEEP 938 XRES_I(zIconBeep); 939 XRES_S(zIconFormat); 940#endif 941#if OPT_PTY_HANDSHAKE 942 XRES_B(wait_for_map); 943 XRES_B(ptyHandshake); 944 XRES_B(ptySttySize); 945#endif 946#if OPT_REPORT_COLORS 947 XRES_B(reportColors); 948#endif 949#if OPT_REPORT_FONTS 950 XRES_B(reportFonts); 951#endif 952#if OPT_SAME_NAME 953 XRES_B(sameName); 954#endif 955#if OPT_SESSION_MGT 956 XRES_B(sessionMgt); 957#endif 958#if OPT_TOOLBAR 959 XRES_B(toolBar); 960#endif 961#if OPT_MAXIMIZE 962 XRES_B(maximized); 963 XRES_S(fullscreen_s); 964#endif 965} 966 967void 968TraceArgv(const char *tag, char **argv) 969{ 970 int n = 0; 971 972 TRACE(("%s:\n", tag)); 973 while (*argv != 0) { 974 TRACE((" %d:%s\n", n++, *argv++)); 975 } 976} 977 978static char * 979parse_option(char *dst, String src, int first) 980{ 981 char *s; 982 983 if (!strncmp(src, "-/+", (size_t) 3)) { 984 dst[0] = (char) first; 985 strcpy(dst + 1, src + 3); 986 } else { 987 strcpy(dst, src); 988 } 989 for (s = dst; *s != '\0'; s++) { 990 if (*s == '#' || *s == '%' || *s == 'S') { 991 s[1] = '\0'; 992 } else if (*s == ' ') { 993 *s = '\0'; 994 break; 995 } 996 } 997 return dst; 998} 999 1000static Bool 1001same_option(OptionHelp * opt, XrmOptionDescRec * res) 1002{ 1003 char temp[BUFSIZ]; 1004 return !strcmp(parse_option(temp, opt->opt, res->option[0]), res->option); 1005} 1006 1007static Bool 1008standard_option(String opt) 1009{ 1010 static const char *table[] = 1011 { 1012 "+rv", 1013 "+synchronous", 1014 "-background", 1015 "-bd", 1016 "-bg", 1017 "-bordercolor", 1018 "-borderwidth", 1019 "-bw", 1020 "-display", 1021 "-fg", 1022 "-fn", 1023 "-font", 1024 "-foreground", 1025 "-geometry", 1026 "-iconic", 1027 "-name", 1028 "-reverse", 1029 "-rv", 1030 "-selectionTimeout", 1031 "-synchronous", 1032 "-title", 1033 "-xnllanguage", 1034 "-xrm", 1035 "-xtsessionID", 1036 }; 1037 Cardinal n; 1038 char temp[BUFSIZ]; 1039 1040 opt = parse_option(temp, opt, '-'); 1041 for (n = 0; n < XtNumber(table); n++) { 1042 if (!strcmp(opt, table[n])) 1043 return True; 1044 } 1045 return False; 1046} 1047 1048/* 1049 * Analyse the options/help messages for inconsistencies. 1050 */ 1051void 1052TraceOptions(OptionHelp * options, XrmOptionDescRec * resources, Cardinal res_count) 1053{ 1054 OptionHelp *opt_array = sortedOpts(options, resources, res_count); 1055 size_t j, k; 1056 XrmOptionDescRec *res_array = sortedOptDescs(resources, res_count); 1057 Bool first, found; 1058 1059 TRACE(("Checking options-tables for inconsistencies:\n")); 1060 1061#if 0 1062 TRACE(("Options listed in help-message:\n")); 1063 for (j = 0; options[j].opt != 0; j++) 1064 TRACE(("%5d %-28s %s\n", j, opt_array[j].opt, opt_array[j].desc)); 1065 TRACE(("Options listed in resource-table:\n")); 1066 for (j = 0; j < res_count; j++) 1067 TRACE(("%5d %-28s %s\n", j, res_array[j].option, res_array[j].specifier)); 1068#endif 1069 1070 /* list all options[] not found in resources[] */ 1071 for (j = 0, first = True; options[j].opt != 0; j++) { 1072 found = False; 1073 for (k = 0; k < res_count; k++) { 1074 if (same_option(&opt_array[j], &res_array[k])) { 1075 found = True; 1076 break; 1077 } 1078 } 1079 if (!found) { 1080 if (first) { 1081 TRACE(("Options listed in help, not found in resource list:\n")); 1082 first = False; 1083 } 1084 TRACE((" %-28s%s\n", opt_array[j].opt, 1085 standard_option(opt_array[j].opt) ? " (standard)" : "")); 1086 } 1087 } 1088 1089 /* list all resources[] not found in options[] */ 1090 for (j = 0, first = True; j < res_count; j++) { 1091 found = False; 1092 for (k = 0; options[k].opt != 0; k++) { 1093 if (same_option(&opt_array[k], &res_array[j])) { 1094 found = True; 1095 break; 1096 } 1097 } 1098 if (!found) { 1099 if (first) { 1100 TRACE(("Resource list items not found in options-help:\n")); 1101 first = False; 1102 } 1103 TRACE((" %s\n", res_array[j].option)); 1104 } 1105 } 1106 1107 TRACE(("Resource list items that will be ignored by XtOpenApplication:\n")); 1108 for (j = 0; j < res_count; j++) { 1109 switch (res_array[j].argKind) { 1110 case XrmoptionSkipArg: 1111 TRACE((" %-28s {param}\n", res_array[j].option)); 1112 break; 1113 case XrmoptionSkipNArgs: 1114 TRACE((" %-28s {%ld params}\n", res_array[j].option, (long) 1115 res_array[j].value)); 1116 break; 1117 case XrmoptionSkipLine: 1118 TRACE((" %-28s {remainder of line}\n", res_array[j].option)); 1119 break; 1120 case XrmoptionIsArg: 1121 case XrmoptionNoArg: 1122 case XrmoptionResArg: 1123 case XrmoptionSepArg: 1124 case XrmoptionStickyArg: 1125 default: 1126 break; 1127 } 1128 } 1129} 1130#else 1131extern void empty_trace(void); 1132void 1133empty_trace(void) 1134{ 1135} 1136#endif 1137