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