trace.c revision 20d2c4d2
120d2c4d2Smrg/* $XTermId: trace.c,v 1.115 2010/06/15 22:40:28 tom Exp $ */ 2d522f475Smrg 320d2c4d2Smrg/* 420d2c4d2Smrg * 520d2c4d2Smrg * Copyright 1997-2009,2010 by Thomas E. Dickey 620d2c4d2Smrg * 720d2c4d2Smrg * All Rights Reserved 820d2c4d2Smrg * 920d2c4d2Smrg * Permission is hereby granted, free of charge, to any person obtaining a 1020d2c4d2Smrg * copy of this software and associated documentation files (the 1120d2c4d2Smrg * "Software"), to deal in the Software without restriction, including 1220d2c4d2Smrg * without limitation the rights to use, copy, modify, merge, publish, 1320d2c4d2Smrg * distribute, sublicense, and/or sell copies of the Software, and to 1420d2c4d2Smrg * permit persons to whom the Software is furnished to do so, subject to 1520d2c4d2Smrg * the following conditions: 1620d2c4d2Smrg * 1720d2c4d2Smrg * The above copyright notice and this permission notice shall be included 1820d2c4d2Smrg * in all copies or substantial portions of the Software. 1920d2c4d2Smrg * 2020d2c4d2Smrg * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 2120d2c4d2Smrg * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 2220d2c4d2Smrg * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 2320d2c4d2Smrg * IN NO EVENT SHALL THE ABOVE LISTED COPYRIGHT HOLDER(S) BE LIABLE FOR ANY 2420d2c4d2Smrg * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 2520d2c4d2Smrg * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 2620d2c4d2Smrg * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 2720d2c4d2Smrg * 2820d2c4d2Smrg * Except as contained in this notice, the name(s) of the above copyright 2920d2c4d2Smrg * holders shall not be used in advertising or otherwise to promote the 3020d2c4d2Smrg * sale, use or other dealings in this Software without prior written 3120d2c4d2Smrg * authorization. 3220d2c4d2Smrg * 3320d2c4d2Smrg */ 34d522f475Smrg 35d522f475Smrg/* 36d522f475Smrg * debugging support via TRACE macro. 37d522f475Smrg */ 38d522f475Smrg 39d522f475Smrg#include <xterm.h> /* for definition of GCC_UNUSED */ 40d522f475Smrg#include <data.h> 41d522f475Smrg#include <trace.h> 42d522f475Smrg 43d522f475Smrg#include <time.h> 44d522f475Smrg#include <stdlib.h> 45d522f475Smrg#include <unistd.h> 46d522f475Smrg#include <sys/types.h> 47d522f475Smrg#include <stdio.h> 48d522f475Smrg#include <stdarg.h> 49d522f475Smrg#include <assert.h> 50d522f475Smrg 51956cc18dSsnj#include <X11/Xatom.h> 52956cc18dSsnj#include <X11/Xmu/Atoms.h> 53956cc18dSsnj 54d522f475Smrg#ifdef HAVE_X11_TRANSLATEI_H 55d522f475Smrg#include <X11/TranslateI.h> 56d522f475Smrg#else 57d522f475Smrg#ifdef __cplusplus 58d522f475Smrgextern "C" { 59d522f475Smrg#endif 60d522f475Smrg 61d522f475Smrg extern String _XtPrintXlations(Widget w, 62d522f475Smrg XtTranslations xlations, 63d522f475Smrg Widget accelWidget, 64d522f475Smrg _XtBoolean includeRHS); 65d522f475Smrg#ifdef __cplusplus 66d522f475Smrg} 67d522f475Smrg#endif 68d522f475Smrg#endif 6920d2c4d2Smrgconst char *trace_who = "parent"; 7020d2c4d2Smrg 7120d2c4d2Smrgstatic FILE *trace_fp; 72d522f475Smrg 73d522f475Smrgvoid 74d522f475SmrgTrace(const char *fmt,...) 75d522f475Smrg{ 7620d2c4d2Smrg static const char *trace_out; 77d522f475Smrg va_list ap; 78d522f475Smrg 7920d2c4d2Smrg if (trace_fp != 0 80d522f475Smrg && trace_who != trace_out) { 8120d2c4d2Smrg fclose(trace_fp); 8220d2c4d2Smrg trace_fp = 0; 83d522f475Smrg } 84d522f475Smrg trace_out = trace_who; 85d522f475Smrg 8620d2c4d2Smrg if (!trace_fp) { 87d522f475Smrg char name[BUFSIZ]; 88d522f475Smrg#if 0 /* usually I do not want unique names */ 89d522f475Smrg int unique; 90d522f475Smrg for (unique = 0;; ++unique) { 91d522f475Smrg if (unique) 92d522f475Smrg sprintf(name, "Trace-%s.out-%d", trace_who, unique); 93d522f475Smrg else 94d522f475Smrg sprintf(name, "Trace-%s.out", trace_who); 9520d2c4d2Smrg if ((trace_fp = fopen(name, "r")) == 0) { 96d522f475Smrg break; 97d522f475Smrg } 9820d2c4d2Smrg fclose(trace_fp); 99d522f475Smrg } 100d522f475Smrg#else 101d522f475Smrg sprintf(name, "Trace-%s.out", trace_who); 102d522f475Smrg#endif 10320d2c4d2Smrg trace_fp = fopen(name, "w"); 10420d2c4d2Smrg if (trace_fp != 0) { 10520d2c4d2Smrg fprintf(trace_fp, "%s\n", xtermVersion()); 106d522f475Smrg TraceIds(NULL, 0); 107d522f475Smrg } 108d522f475Smrg } 10920d2c4d2Smrg if (!trace_fp) 110d522f475Smrg abort(); 111d522f475Smrg 112d522f475Smrg va_start(ap, fmt); 11320d2c4d2Smrg vfprintf(trace_fp, fmt, ap); 11420d2c4d2Smrg (void) fflush(trace_fp); 11520d2c4d2Smrg va_end(ap); 11620d2c4d2Smrg} 11720d2c4d2Smrg 11820d2c4d2Smrgvoid 11920d2c4d2SmrgTraceClose(void) 12020d2c4d2Smrg{ 12120d2c4d2Smrg if (trace_fp != 0) { 12220d2c4d2Smrg (void) fclose(trace_fp); 123d522f475Smrg (void) fflush(stdout); 124d522f475Smrg (void) fflush(stderr); 125956cc18dSsnj (void) visibleChars(NULL, 0); 126956cc18dSsnj (void) visibleIChars(NULL, 0); 127956cc18dSsnj (void) visibleIChar(NULL, 0); 12820d2c4d2Smrg trace_fp = 0; 129d522f475Smrg } 130d522f475Smrg} 131d522f475Smrg 132d522f475Smrgvoid 133d522f475SmrgTraceIds(const char *fname, int lnum) 134d522f475Smrg{ 135d522f475Smrg Trace("process %d ", (int) getpid()); 136d522f475Smrg#ifdef HAVE_UNISTD_H 137d522f475Smrg Trace("real (%u/%u) effective (%u/%u)", 138d522f475Smrg (unsigned) getuid(), (unsigned) getgid(), 139d522f475Smrg (unsigned) geteuid(), (unsigned) getegid()); 140d522f475Smrg#endif 141d522f475Smrg if (fname != 0) { 142d522f475Smrg Trace(" (%s@%d)\n", fname, lnum); 143d522f475Smrg } else { 144d522f475Smrg time_t now = time((time_t *) 0); 145d522f475Smrg Trace("-- %s", ctime(&now)); 146d522f475Smrg } 147d522f475Smrg} 148d522f475Smrg 149d522f475Smrgstatic void 150d522f475SmrgformatAscii(char *dst, unsigned value) 151d522f475Smrg{ 152d522f475Smrg switch (value) { 153d522f475Smrg case '\\': 154d522f475Smrg sprintf(dst, "\\\\"); 155d522f475Smrg break; 156d522f475Smrg case '\b': 157d522f475Smrg sprintf(dst, "\\b"); 158d522f475Smrg break; 159d522f475Smrg case '\n': 160d522f475Smrg sprintf(dst, "\\n"); 161d522f475Smrg break; 162d522f475Smrg case '\r': 163d522f475Smrg sprintf(dst, "\\r"); 164d522f475Smrg break; 165d522f475Smrg case '\t': 166d522f475Smrg sprintf(dst, "\\t"); 167d522f475Smrg break; 168d522f475Smrg default: 169d522f475Smrg if (E2A(value) < 32 || (E2A(value) >= 127 && E2A(value) < 160)) 170d522f475Smrg sprintf(dst, "\\%03o", value); 171d522f475Smrg else 172d522f475Smrg sprintf(dst, "%c", CharOf(value)); 173d522f475Smrg break; 174d522f475Smrg } 175d522f475Smrg} 176d522f475Smrg 177d522f475Smrg#if OPT_DEC_CHRSET 178d522f475Smrg 179d522f475Smrgconst char * 180956cc18dSsnjvisibleChrsetName(unsigned chrset) 181d522f475Smrg{ 182d522f475Smrg const char *result = "?"; 183d522f475Smrg switch (chrset) { 184d522f475Smrg case CSET_SWL: 185d522f475Smrg result = "CSET_SWL"; 186d522f475Smrg break; 187d522f475Smrg case CSET_DHL_TOP: 188d522f475Smrg result = "CSET_DHL_TOP"; 189d522f475Smrg break; 190d522f475Smrg case CSET_DHL_BOT: 191d522f475Smrg result = "CSET_DHL_BOT"; 192d522f475Smrg break; 193d522f475Smrg case CSET_DWL: 194d522f475Smrg result = "CSET_DWL"; 195d522f475Smrg break; 196d522f475Smrg } 197d522f475Smrg return result; 198d522f475Smrg} 199d522f475Smrg#endif 200d522f475Smrg 201d522f475Smrgchar * 20220d2c4d2SmrgvisibleChars(const Char * buf, unsigned len) 203d522f475Smrg{ 204d522f475Smrg static char *result; 205d522f475Smrg static unsigned used; 206d522f475Smrg 207956cc18dSsnj if (buf != 0) { 208956cc18dSsnj unsigned limit = ((len + 1) * 8) + 1; 209956cc18dSsnj char *dst; 210956cc18dSsnj 211956cc18dSsnj if (limit > used) { 212956cc18dSsnj used = limit; 213956cc18dSsnj result = XtRealloc(result, used); 214956cc18dSsnj } 21520d2c4d2Smrg if (result != 0) { 21620d2c4d2Smrg dst = result; 21720d2c4d2Smrg *dst = '\0'; 21820d2c4d2Smrg while (len--) { 21920d2c4d2Smrg unsigned value = *buf++; 22020d2c4d2Smrg formatAscii(dst, value); 22120d2c4d2Smrg dst += strlen(dst); 22220d2c4d2Smrg } 223956cc18dSsnj } 224956cc18dSsnj } else if (result != 0) { 225956cc18dSsnj free(result); 226956cc18dSsnj result = 0; 227956cc18dSsnj used = 0; 228d522f475Smrg } 229956cc18dSsnj return result; 230956cc18dSsnj} 231956cc18dSsnj 232956cc18dSsnjchar * 233956cc18dSsnjvisibleIChars(IChar * buf, unsigned len) 234956cc18dSsnj{ 235956cc18dSsnj static char *result; 236956cc18dSsnj static unsigned used; 237956cc18dSsnj 238956cc18dSsnj if (buf != 0) { 239956cc18dSsnj unsigned limit = ((len + 1) * 8) + 1; 240956cc18dSsnj char *dst; 241956cc18dSsnj 242956cc18dSsnj if (limit > used) { 243956cc18dSsnj used = limit; 244956cc18dSsnj result = XtRealloc(result, used); 245d522f475Smrg } 24620d2c4d2Smrg if (result != 0) { 24720d2c4d2Smrg dst = result; 24820d2c4d2Smrg *dst = '\0'; 24920d2c4d2Smrg while (len--) { 25020d2c4d2Smrg unsigned value = *buf++; 251956cc18dSsnj#if OPT_WIDE_CHARS 25220d2c4d2Smrg if (value > 255) 25320d2c4d2Smrg sprintf(dst, "\\u+%04X", value); 25420d2c4d2Smrg else 255d522f475Smrg#endif 25620d2c4d2Smrg formatAscii(dst, value); 25720d2c4d2Smrg dst += strlen(dst); 25820d2c4d2Smrg } 259956cc18dSsnj } 260956cc18dSsnj } else if (result != 0) { 261956cc18dSsnj free(result); 262956cc18dSsnj result = 0; 263956cc18dSsnj used = 0; 264d522f475Smrg } 265d522f475Smrg return result; 266d522f475Smrg} 267d522f475Smrg 268d522f475Smrgchar * 269d522f475SmrgvisibleIChar(IChar * buf, unsigned len) 270d522f475Smrg{ 271d522f475Smrg static char *result; 272d522f475Smrg static unsigned used; 273d522f475Smrg 274956cc18dSsnj if (buf != 0) { 27520d2c4d2Smrg unsigned limit = ((len + 1) * 8) + 1; 276956cc18dSsnj char *dst; 277956cc18dSsnj 278956cc18dSsnj if (limit > used) { 279956cc18dSsnj used = limit; 280956cc18dSsnj result = XtRealloc(result, used); 281956cc18dSsnj } 28220d2c4d2Smrg if (result != 0) { 28320d2c4d2Smrg dst = result; 28420d2c4d2Smrg while (len--) { 28520d2c4d2Smrg unsigned value = *buf++; 286d522f475Smrg#if OPT_WIDE_CHARS 28720d2c4d2Smrg if (value > 255) 28820d2c4d2Smrg sprintf(dst, "\\u+%04X", value); 28920d2c4d2Smrg else 290d522f475Smrg#endif 29120d2c4d2Smrg formatAscii(dst, value); 29220d2c4d2Smrg dst += strlen(dst); 29320d2c4d2Smrg } 294956cc18dSsnj } 295956cc18dSsnj } else if (result != 0) { 296956cc18dSsnj free(result); 297956cc18dSsnj result = 0; 298956cc18dSsnj used = 0; 299d522f475Smrg } 300d522f475Smrg return result; 301d522f475Smrg} 302d522f475Smrg 303d522f475Smrg#define CASETYPE(name) case name: result = #name; break; 304d522f475Smrg 305d522f475Smrgconst char * 306d522f475SmrgvisibleKeyboardType(xtermKeyboardType type) 307d522f475Smrg{ 308d522f475Smrg const char *result = "?"; 309d522f475Smrg switch (type) { 310d522f475Smrg CASETYPE(keyboardIsLegacy); /* bogus vt220 codes for F1-F4, etc. */ 311d522f475Smrg CASETYPE(keyboardIsDefault); 312d522f475Smrg CASETYPE(keyboardIsHP); 313d522f475Smrg CASETYPE(keyboardIsSCO); 314d522f475Smrg CASETYPE(keyboardIsSun); 315d522f475Smrg CASETYPE(keyboardIsTermcap); 316d522f475Smrg CASETYPE(keyboardIsVT220); 317d522f475Smrg } 318d522f475Smrg return result; 319d522f475Smrg} 320d522f475Smrg 321d522f475Smrgconst char * 322d522f475SmrgvisibleEventType(int type) 323d522f475Smrg{ 324d522f475Smrg const char *result = "?"; 325d522f475Smrg switch (type) { 326d522f475Smrg CASETYPE(KeyPress); 327d522f475Smrg CASETYPE(KeyRelease); 328d522f475Smrg CASETYPE(ButtonPress); 329d522f475Smrg CASETYPE(ButtonRelease); 330d522f475Smrg CASETYPE(MotionNotify); 331d522f475Smrg CASETYPE(EnterNotify); 332d522f475Smrg CASETYPE(LeaveNotify); 333d522f475Smrg CASETYPE(FocusIn); 334d522f475Smrg CASETYPE(FocusOut); 335d522f475Smrg CASETYPE(KeymapNotify); 336d522f475Smrg CASETYPE(Expose); 337d522f475Smrg CASETYPE(GraphicsExpose); 338d522f475Smrg CASETYPE(NoExpose); 339d522f475Smrg CASETYPE(VisibilityNotify); 340d522f475Smrg CASETYPE(CreateNotify); 341d522f475Smrg CASETYPE(DestroyNotify); 342d522f475Smrg CASETYPE(UnmapNotify); 343d522f475Smrg CASETYPE(MapNotify); 344d522f475Smrg CASETYPE(MapRequest); 345d522f475Smrg CASETYPE(ReparentNotify); 346d522f475Smrg CASETYPE(ConfigureNotify); 347d522f475Smrg CASETYPE(ConfigureRequest); 348d522f475Smrg CASETYPE(GravityNotify); 349d522f475Smrg CASETYPE(ResizeRequest); 350d522f475Smrg CASETYPE(CirculateNotify); 351d522f475Smrg CASETYPE(CirculateRequest); 352d522f475Smrg CASETYPE(PropertyNotify); 353d522f475Smrg CASETYPE(SelectionClear); 354d522f475Smrg CASETYPE(SelectionRequest); 355d522f475Smrg CASETYPE(SelectionNotify); 356d522f475Smrg CASETYPE(ColormapNotify); 357d522f475Smrg CASETYPE(ClientMessage); 358d522f475Smrg CASETYPE(MappingNotify); 359d522f475Smrg } 360d522f475Smrg return result; 361d522f475Smrg} 362d522f475Smrg 36320d2c4d2Smrgconst char * 36420d2c4d2SmrgvisibleNotifyDetail(int code) 36520d2c4d2Smrg{ 36620d2c4d2Smrg const char *result = "?"; 36720d2c4d2Smrg switch (code) { 36820d2c4d2Smrg CASETYPE(NotifyAncestor); 36920d2c4d2Smrg CASETYPE(NotifyVirtual); 37020d2c4d2Smrg CASETYPE(NotifyInferior); 37120d2c4d2Smrg CASETYPE(NotifyNonlinear); 37220d2c4d2Smrg CASETYPE(NotifyNonlinearVirtual); 37320d2c4d2Smrg CASETYPE(NotifyPointer); 37420d2c4d2Smrg CASETYPE(NotifyPointerRoot); 37520d2c4d2Smrg CASETYPE(NotifyDetailNone); 37620d2c4d2Smrg } 37720d2c4d2Smrg return result; 37820d2c4d2Smrg} 37920d2c4d2Smrg 380956cc18dSsnjconst char * 381956cc18dSsnjvisibleSelectionTarget(Display * d, Atom a) 382956cc18dSsnj{ 383956cc18dSsnj const char *result = "?"; 384956cc18dSsnj 385956cc18dSsnj if (a == XA_STRING) { 386956cc18dSsnj result = "XA_STRING"; 387956cc18dSsnj } else if (a == XA_TEXT(d)) { 388956cc18dSsnj result = "XA_TEXT()"; 389956cc18dSsnj } else if (a == XA_COMPOUND_TEXT(d)) { 390956cc18dSsnj result = "XA_COMPOUND_TEXT()"; 391956cc18dSsnj } else if (a == XA_UTF8_STRING(d)) { 392956cc18dSsnj result = "XA_UTF8_STRING()"; 393956cc18dSsnj } else if (a == XA_TARGETS(d)) { 394956cc18dSsnj result = "XA_TARGETS()"; 395956cc18dSsnj } 396956cc18dSsnj 397956cc18dSsnj return result; 398956cc18dSsnj} 399956cc18dSsnj 400d522f475Smrgconst char * 401d522f475SmrgvisibleXError(int code) 402d522f475Smrg{ 403d522f475Smrg static char temp[80]; 404d522f475Smrg const char *result = "?"; 405d522f475Smrg switch (code) { 406d522f475Smrg CASETYPE(Success); 407d522f475Smrg CASETYPE(BadRequest); 408d522f475Smrg CASETYPE(BadValue); 409d522f475Smrg CASETYPE(BadWindow); 410d522f475Smrg CASETYPE(BadPixmap); 411d522f475Smrg CASETYPE(BadAtom); 412d522f475Smrg CASETYPE(BadCursor); 413d522f475Smrg CASETYPE(BadFont); 414d522f475Smrg CASETYPE(BadMatch); 415d522f475Smrg CASETYPE(BadDrawable); 416d522f475Smrg CASETYPE(BadAccess); 417d522f475Smrg CASETYPE(BadAlloc); 418d522f475Smrg CASETYPE(BadColor); 419d522f475Smrg CASETYPE(BadGC); 420d522f475Smrg CASETYPE(BadIDChoice); 421d522f475Smrg CASETYPE(BadName); 422d522f475Smrg CASETYPE(BadLength); 423d522f475Smrg CASETYPE(BadImplementation); 424d522f475Smrg default: 425d522f475Smrg sprintf(temp, "%d", code); 426d522f475Smrg result = temp; 427d522f475Smrg break; 428d522f475Smrg } 429d522f475Smrg return result; 430d522f475Smrg} 431d522f475Smrg 432d522f475Smrg#if OPT_TRACE_FLAGS 433d522f475Smrg#define isScrnFlag(flag) ((flag) == LINEWRAPPED) 434d522f475Smrg 435d522f475Smrgstatic char * 436956cc18dSsnjScrnText(LineData * ld) 437d522f475Smrg{ 438956cc18dSsnj return visibleIChars(ld->charData, ld->lineSize); 439d522f475Smrg} 440d522f475Smrg 441956cc18dSsnj#define SHOW_BAD_LINE(name, ld) \ 442956cc18dSsnj Trace("OOPS " #name " bad row\n") 443d522f475Smrg 444d522f475Smrg#define SHOW_SCRN_FLAG(name,code) \ 445956cc18dSsnj Trace(#name " %s:%s\n", \ 446d522f475Smrg code ? "*" : "", \ 447956cc18dSsnj ScrnText(ld)) 448d522f475Smrg 449d522f475Smrgvoid 450956cc18dSsnjLineClrFlag(LineData * ld, int flag) 451d522f475Smrg{ 452956cc18dSsnj if (ld == 0) { 453956cc18dSsnj SHOW_BAD_LINE(LineClrFlag, ld); 454d522f475Smrg assert(0); 455d522f475Smrg } else if (isScrnFlag(flag)) { 456956cc18dSsnj SHOW_SCRN_FLAG(LineClrFlag, 0); 457d522f475Smrg } 458d522f475Smrg 459956cc18dSsnj LineFlags(ld) &= ~flag; 460d522f475Smrg} 461d522f475Smrg 462d522f475Smrgvoid 463956cc18dSsnjLineSetFlag(LineData * ld, int flag) 464d522f475Smrg{ 465956cc18dSsnj if (ld == 0) { 466956cc18dSsnj SHOW_BAD_LINE(LineSetFlag, ld); 467d522f475Smrg assert(0); 468d522f475Smrg } else if (isScrnFlag(flag)) { 469956cc18dSsnj SHOW_SCRN_FLAG(LineSetFlag, 1); 470d522f475Smrg } 471d522f475Smrg 472956cc18dSsnj LineFlags(ld) |= flag; 473d522f475Smrg} 474d522f475Smrg 475d522f475Smrgint 476956cc18dSsnjLineTstFlag(LineData ld, int flag) 477d522f475Smrg{ 478d522f475Smrg int code = 0; 479956cc18dSsnj if (ld == 0) { 480956cc18dSsnj SHOW_BAD_LINE(LineTstFlag, ld); 481d522f475Smrg } else { 482956cc18dSsnj code = LineFlags(ld); 483956cc18dSsnj 484956cc18dSsnj if (isScrnFlag(flag)) { 485956cc18dSsnj SHOW_SCRN_FLAG(LineTstFlag, code); 486d522f475Smrg } 487d522f475Smrg } 488d522f475Smrg return code; 489d522f475Smrg} 490d522f475Smrg#endif /* OPT_TRACE_FLAGS */ 491d522f475Smrg 49220d2c4d2Smrgvoid 49320d2c4d2SmrgTraceFocus(Widget w, XEvent * ev) 49420d2c4d2Smrg{ 49520d2c4d2Smrg TRACE(("trace_focus event type %d:%s\n", 49620d2c4d2Smrg ev->type, visibleEventType(ev->type))); 49720d2c4d2Smrg switch (ev->type) { 49820d2c4d2Smrg case FocusIn: 49920d2c4d2Smrg case FocusOut: 50020d2c4d2Smrg { 50120d2c4d2Smrg XFocusChangeEvent *event = (XFocusChangeEvent *) ev; 50220d2c4d2Smrg TRACE(("\tdetail: %s\n", visibleNotifyDetail(event->detail))); 50320d2c4d2Smrg TRACE(("\tmode: %d\n", event->mode)); 50420d2c4d2Smrg TRACE(("\twindow: %#lx\n", event->window)); 50520d2c4d2Smrg } 50620d2c4d2Smrg break; 50720d2c4d2Smrg case EnterNotify: 50820d2c4d2Smrg case LeaveNotify: 50920d2c4d2Smrg { 51020d2c4d2Smrg XCrossingEvent *event = (XCrossingEvent *) ev; 51120d2c4d2Smrg TRACE(("\tdetail: %s\n", visibleNotifyDetail(event->detail))); 51220d2c4d2Smrg TRACE(("\tmode: %d\n", event->mode)); 51320d2c4d2Smrg TRACE(("\twindow: %#lx\n", event->window)); 51420d2c4d2Smrg TRACE(("\troot: %#lx\n", event->root)); 51520d2c4d2Smrg TRACE(("\tsubwindow: %#lx\n", event->subwindow)); 51620d2c4d2Smrg } 51720d2c4d2Smrg break; 51820d2c4d2Smrg } 51920d2c4d2Smrg while (w != 0) { 52020d2c4d2Smrg TRACE(("w %p -> %#lx\n", (void *) w, XtWindow(w))); 52120d2c4d2Smrg w = XtParent(w); 52220d2c4d2Smrg } 52320d2c4d2Smrg} 52420d2c4d2Smrg 525d522f475Smrgvoid 526d522f475SmrgTraceSizeHints(XSizeHints * hints) 527d522f475Smrg{ 528d522f475Smrg TRACE(("size hints:\n")); 529d522f475Smrg if (hints->flags & (USPosition | PPosition)) 530d522f475Smrg TRACE((" position %d,%d%s%s\n", hints->y, hints->x, 531d522f475Smrg hints->flags & USPosition ? " user" : "", 532d522f475Smrg hints->flags & PPosition ? " prog" : "")); 533d522f475Smrg if (hints->flags & (USSize | PSize)) 534d522f475Smrg TRACE((" size %d,%d%s%s\n", hints->height, hints->width, 535d522f475Smrg hints->flags & USSize ? " user" : "", 536d522f475Smrg hints->flags & PSize ? " prog" : "")); 537d522f475Smrg if (hints->flags & PMinSize) 538d522f475Smrg TRACE((" min %d,%d\n", hints->min_height, hints->min_width)); 539d522f475Smrg if (hints->flags & PMaxSize) 540d522f475Smrg TRACE((" max %d,%d\n", hints->max_height, hints->max_width)); 541d522f475Smrg if (hints->flags & PResizeInc) 542d522f475Smrg TRACE((" inc %d,%d\n", hints->height_inc, hints->width_inc)); 5432eaa94a1Schristos else 5442eaa94a1Schristos TRACE((" inc NONE!\n")); 545d522f475Smrg if (hints->flags & PAspect) 546d522f475Smrg TRACE((" min aspect %d/%d\n", hints->min_aspect.y, hints->min_aspect.y)); 547d522f475Smrg if (hints->flags & PAspect) 548d522f475Smrg TRACE((" max aspect %d/%d\n", hints->max_aspect.y, hints->max_aspect.y)); 549d522f475Smrg if (hints->flags & PBaseSize) 550d522f475Smrg TRACE((" base %d,%d\n", hints->base_height, hints->base_width)); 551d522f475Smrg if (hints->flags & PWinGravity) 552d522f475Smrg TRACE((" gravity %d\n", hints->win_gravity)); 553d522f475Smrg} 554d522f475Smrg 555d522f475Smrgvoid 556d522f475SmrgTraceWMSizeHints(XtermWidget xw) 557d522f475Smrg{ 558d522f475Smrg XSizeHints sizehints = xw->hints; 559d522f475Smrg 560d522f475Smrg getXtermSizeHints(xw); 561d522f475Smrg TraceSizeHints(&xw->hints); 562d522f475Smrg xw->hints = sizehints; 563d522f475Smrg} 564d522f475Smrg 565d522f475Smrg/* 566d522f475Smrg * Some calls to XGetAtom() will fail, and we don't want to stop. So we use 567d522f475Smrg * our own error-handler. 568d522f475Smrg */ 569d522f475Smrgstatic int 570d522f475Smrgno_error(Display * dpy GCC_UNUSED, XErrorEvent * event GCC_UNUSED) 571d522f475Smrg{ 572d522f475Smrg return 1; 573d522f475Smrg} 574d522f475Smrg 575d522f475Smrgvoid 576d522f475SmrgTraceTranslations(const char *name, Widget w) 577d522f475Smrg{ 578d522f475Smrg String result; 579d522f475Smrg XErrorHandler save = XSetErrorHandler(no_error); 580d522f475Smrg XtTranslations xlations; 581d522f475Smrg Widget xcelerat; 582d522f475Smrg 58320d2c4d2Smrg TRACE(("TraceTranslations for %s (widget %#lx) {{\n", name, (long) w)); 584d522f475Smrg if (w) { 585d522f475Smrg XtVaGetValues(w, 586d522f475Smrg XtNtranslations, &xlations, 587d522f475Smrg XtNaccelerators, &xcelerat, 588d522f475Smrg (XtPointer) 0); 589d522f475Smrg TRACE(("... xlations %#08lx\n", (long) xlations)); 590d522f475Smrg TRACE(("... xcelerat %#08lx\n", (long) xcelerat)); 591d522f475Smrg result = _XtPrintXlations(w, xlations, xcelerat, True); 59220d2c4d2Smrg TRACE(("%s\n", NonNull(result))); 593d522f475Smrg if (result) 59420d2c4d2Smrg XFree((char *) result); 595d522f475Smrg } else { 596d522f475Smrg TRACE(("none (widget is null)\n")); 597d522f475Smrg } 59820d2c4d2Smrg TRACE(("}}\n")); 599d522f475Smrg XSetErrorHandler(save); 600d522f475Smrg} 601d522f475Smrg 6022eaa94a1Schristosint 6032eaa94a1SchristosTraceResizeRequest(const char *fn, int ln, Widget w, 6042eaa94a1Schristos Dimension reqwide, 6052eaa94a1Schristos Dimension reqhigh, 6062eaa94a1Schristos Dimension * gotwide, 6072eaa94a1Schristos Dimension * gothigh) 6082eaa94a1Schristos{ 6092eaa94a1Schristos int rc; 6102eaa94a1Schristos 6112eaa94a1Schristos TRACE(("%s@%d ResizeRequest %dx%d\n", fn, ln, reqhigh, reqwide)); 6122eaa94a1Schristos rc = XtMakeResizeRequest((Widget) w, reqwide, reqhigh, gotwide, gothigh); 6132eaa94a1Schristos TRACE(("... ResizeRequest -> ")); 6142eaa94a1Schristos if (gothigh && gotwide) 6152eaa94a1Schristos TRACE(("%dx%d ", *gothigh, *gotwide)); 6162eaa94a1Schristos TRACE(("(%d)\n", rc)); 6172eaa94a1Schristos return rc; 6182eaa94a1Schristos} 6192eaa94a1Schristos 620d522f475Smrg#define XRES_S(name) Trace(#name " = %s\n", NonNull(resp->name)) 621d522f475Smrg#define XRES_B(name) Trace(#name " = %s\n", BtoS(resp->name)) 622d522f475Smrg#define XRES_I(name) Trace(#name " = %d\n", resp->name) 623d522f475Smrg 624d522f475Smrgvoid 625d522f475SmrgTraceXtermResources(void) 626d522f475Smrg{ 627d522f475Smrg XTERM_RESOURCE *resp = &resource; 628d522f475Smrg 629d522f475Smrg Trace("XTERM_RESOURCE settings:\n"); 630d522f475Smrg XRES_S(xterm_name); 631d522f475Smrg XRES_S(icon_geometry); 632d522f475Smrg XRES_S(title); 633d522f475Smrg XRES_S(icon_name); 634d522f475Smrg XRES_S(term_name); 635d522f475Smrg XRES_S(tty_modes); 636d522f475Smrg XRES_B(hold_screen); 637d522f475Smrg XRES_B(utmpInhibit); 638d522f475Smrg XRES_B(utmpDisplayId); 639d522f475Smrg XRES_B(messages); 640d522f475Smrg#if OPT_SUNPC_KBD 641d522f475Smrg XRES_B(sunKeyboard); 642d522f475Smrg#endif 643d522f475Smrg#if OPT_HP_FUNC_KEYS 644d522f475Smrg XRES_B(hpFunctionKeys); 645d522f475Smrg#endif 646d522f475Smrg#if OPT_SCO_FUNC_KEYS 647d522f475Smrg XRES_B(scoFunctionKeys); 648d522f475Smrg#endif 649d522f475Smrg#if OPT_SUN_FUNC_KEYS 650d522f475Smrg XRES_B(sunFunctionKeys); 651d522f475Smrg#endif 652d522f475Smrg#if OPT_INITIAL_ERASE 653d522f475Smrg XRES_B(ptyInitialErase); 654d522f475Smrg XRES_B(backarrow_is_erase); 655d522f475Smrg#endif 656d522f475Smrg XRES_B(useInsertMode); 657d522f475Smrg#if OPT_ZICONBEEP 658d522f475Smrg XRES_I(zIconBeep); 659d522f475Smrg#endif 660d522f475Smrg#if OPT_PTY_HANDSHAKE 661d522f475Smrg XRES_B(wait_for_map); 662d522f475Smrg XRES_B(ptyHandshake); 663d522f475Smrg XRES_B(ptySttySize); 664d522f475Smrg#endif 665d522f475Smrg#if OPT_SAME_NAME 666d522f475Smrg XRES_B(sameName); 667d522f475Smrg#endif 668d522f475Smrg#if OPT_SESSION_MGT 669d522f475Smrg XRES_B(sessionMgt); 670d522f475Smrg#endif 671d522f475Smrg} 672d522f475Smrg 673d522f475Smrgvoid 674d522f475SmrgTraceArgv(const char *tag, char **argv) 675d522f475Smrg{ 676d522f475Smrg int n = 0; 677d522f475Smrg 678d522f475Smrg TRACE(("%s:\n", tag)); 679d522f475Smrg while (*argv != 0) { 680d522f475Smrg TRACE((" %d:%s\n", n++, *argv++)); 681d522f475Smrg } 682d522f475Smrg} 683d522f475Smrg 684d522f475Smrgstatic char * 68520d2c4d2Smrgparse_option(char *dst, String src, int first) 686d522f475Smrg{ 687d522f475Smrg char *s; 688d522f475Smrg 689d522f475Smrg if (!strncmp(src, "-/+", 3)) { 690956cc18dSsnj dst[0] = (char) first; 691d522f475Smrg strcpy(dst + 1, src + 3); 692d522f475Smrg } else { 693d522f475Smrg strcpy(dst, src); 694d522f475Smrg } 695d522f475Smrg for (s = dst; *s != '\0'; s++) { 696d522f475Smrg if (*s == '#' || *s == '%' || *s == 'S') { 697d522f475Smrg s[1] = '\0'; 698d522f475Smrg } else if (*s == ' ') { 699d522f475Smrg *s = '\0'; 700d522f475Smrg break; 701d522f475Smrg } 702d522f475Smrg } 703d522f475Smrg return dst; 704d522f475Smrg} 705d522f475Smrg 706d522f475Smrgstatic Bool 707d522f475Smrgsame_option(OptionHelp * opt, XrmOptionDescRec * res) 708d522f475Smrg{ 709d522f475Smrg char temp[BUFSIZ]; 710d522f475Smrg return !strcmp(parse_option(temp, opt->opt, res->option[0]), res->option); 711d522f475Smrg} 712d522f475Smrg 713d522f475Smrgstatic Bool 71420d2c4d2Smrgstandard_option(String opt) 715d522f475Smrg{ 716d522f475Smrg static const char *table[] = 717d522f475Smrg { 718d522f475Smrg "+rv", 719d522f475Smrg "+synchronous", 720d522f475Smrg "-background", 721d522f475Smrg "-bd", 722d522f475Smrg "-bg", 723d522f475Smrg "-bordercolor", 724d522f475Smrg "-borderwidth", 725d522f475Smrg "-bw", 726d522f475Smrg "-display", 727d522f475Smrg "-fg", 728d522f475Smrg "-fn", 729d522f475Smrg "-font", 730d522f475Smrg "-foreground", 731d522f475Smrg "-geometry", 732d522f475Smrg "-iconic", 733d522f475Smrg "-name", 734d522f475Smrg "-reverse", 735d522f475Smrg "-rv", 736d522f475Smrg "-selectionTimeout", 737d522f475Smrg "-synchronous", 738d522f475Smrg "-title", 739d522f475Smrg "-xnllanguage", 740d522f475Smrg "-xrm", 741d522f475Smrg "-xtsessionID", 742d522f475Smrg }; 743d522f475Smrg Cardinal n; 744d522f475Smrg char temp[BUFSIZ]; 745d522f475Smrg 746d522f475Smrg opt = parse_option(temp, opt, '-'); 747d522f475Smrg for (n = 0; n < XtNumber(table); n++) { 748d522f475Smrg if (!strcmp(opt, table[n])) 749d522f475Smrg return True; 750d522f475Smrg } 751d522f475Smrg return False; 752d522f475Smrg} 753d522f475Smrg 754d522f475Smrg/* 755d522f475Smrg * Analyse the options/help messages for inconsistencies. 756d522f475Smrg */ 757d522f475Smrgvoid 758d522f475SmrgTraceOptions(OptionHelp * options, XrmOptionDescRec * resources, Cardinal res_count) 759d522f475Smrg{ 760d522f475Smrg OptionHelp *opt_array = sortedOpts(options, resources, res_count); 761d522f475Smrg size_t j, k; 762d522f475Smrg XrmOptionDescRec *res_array = sortedOptDescs(resources, res_count); 763d522f475Smrg Bool first, found; 764d522f475Smrg 765d522f475Smrg TRACE(("Checking options-tables for inconsistencies:\n")); 766d522f475Smrg 767d522f475Smrg#if 0 768d522f475Smrg TRACE(("Options listed in help-message:\n")); 769d522f475Smrg for (j = 0; options[j].opt != 0; j++) 770d522f475Smrg TRACE(("%5d %-28s %s\n", j, opt_array[j].opt, opt_array[j].desc)); 771d522f475Smrg TRACE(("Options listed in resource-table:\n")); 772d522f475Smrg for (j = 0; j < res_count; j++) 773d522f475Smrg TRACE(("%5d %-28s %s\n", j, res_array[j].option, res_array[j].specifier)); 774d522f475Smrg#endif 775d522f475Smrg 776d522f475Smrg /* list all options[] not found in resources[] */ 777d522f475Smrg for (j = 0, first = True; options[j].opt != 0; j++) { 778d522f475Smrg found = False; 779d522f475Smrg for (k = 0; k < res_count; k++) { 780d522f475Smrg if (same_option(&opt_array[j], &res_array[k])) { 781d522f475Smrg found = True; 782d522f475Smrg break; 783d522f475Smrg } 784d522f475Smrg } 785d522f475Smrg if (!found) { 786d522f475Smrg if (first) { 787d522f475Smrg TRACE(("Options listed in help, not found in resource list:\n")); 788d522f475Smrg first = False; 789d522f475Smrg } 790d522f475Smrg TRACE((" %-28s%s\n", opt_array[j].opt, 791d522f475Smrg standard_option(opt_array[j].opt) ? " (standard)" : "")); 792d522f475Smrg } 793d522f475Smrg } 794d522f475Smrg 795d522f475Smrg /* list all resources[] not found in options[] */ 796d522f475Smrg for (j = 0, first = True; j < res_count; j++) { 797d522f475Smrg found = False; 798d522f475Smrg for (k = 0; options[k].opt != 0; k++) { 799d522f475Smrg if (same_option(&opt_array[k], &res_array[j])) { 800d522f475Smrg found = True; 801d522f475Smrg break; 802d522f475Smrg } 803d522f475Smrg } 804d522f475Smrg if (!found) { 805d522f475Smrg if (first) { 806d522f475Smrg TRACE(("Resource list items not found in options-help:\n")); 807d522f475Smrg first = False; 808d522f475Smrg } 809d522f475Smrg TRACE((" %s\n", res_array[j].option)); 810d522f475Smrg } 811d522f475Smrg } 812d522f475Smrg 813d522f475Smrg TRACE(("Resource list items that will be ignored by XtOpenApplication:\n")); 814d522f475Smrg for (j = 0; j < res_count; j++) { 815d522f475Smrg switch (res_array[j].argKind) { 816d522f475Smrg case XrmoptionSkipArg: 817d522f475Smrg TRACE((" %-28s {param}\n", res_array[j].option)); 818d522f475Smrg break; 819d522f475Smrg case XrmoptionSkipNArgs: 820d522f475Smrg TRACE((" %-28s {%ld params}\n", res_array[j].option, (long) 821d522f475Smrg res_array[j].value)); 822d522f475Smrg break; 823d522f475Smrg case XrmoptionSkipLine: 824d522f475Smrg TRACE((" %-28s {remainder of line}\n", res_array[j].option)); 825d522f475Smrg break; 826d522f475Smrg case XrmoptionIsArg: 827d522f475Smrg case XrmoptionNoArg: 828d522f475Smrg case XrmoptionResArg: 829d522f475Smrg case XrmoptionSepArg: 830d522f475Smrg case XrmoptionStickyArg: 831d522f475Smrg default: 832d522f475Smrg break; 833d522f475Smrg } 834d522f475Smrg } 835d522f475Smrg} 836