|
|
1.1 ! root 1: #include <X11/Xlib.h> ! 2: #include <X11/Xutil.h> ! 3: #include <string.h> ! 4: #include <stdio.h> ! 5: #include <ctype.h> ! 6: ! 7: #include <X11/Xatom.h> ! 8: ! 9: #include "dsimple.h" ! 10: ! 11: #define MAXSTR 10000 ! 12: ! 13: #define min(a,b) ((a) < (b) ? (a) : (b)) ! 14: ! 15: /* ! 16: * ! 17: * The Thunk Manager - routines to create, add to, and free thunk lists ! 18: * ! 19: */ ! 20: ! 21: typedef struct { ! 22: int thunk_count; ! 23: long value; ! 24: char *extra_value; ! 25: char *format; ! 26: char *dformat; ! 27: } thunk; ! 28: ! 29: thunk *Create_Thunk_List() ! 30: { ! 31: thunk *tptr; ! 32: ! 33: tptr = (thunk *) Malloc( sizeof(thunk) ); ! 34: ! 35: tptr->thunk_count = 0; ! 36: ! 37: return(tptr); ! 38: } ! 39: ! 40: Free_Thunk_List(list) ! 41: thunk *list; ! 42: { ! 43: free(list); ! 44: } ! 45: ! 46: thunk *Add_Thunk(list, t) ! 47: thunk *list; ! 48: thunk t; ! 49: { ! 50: int i; ! 51: ! 52: i = list->thunk_count; ! 53: ! 54: list = (thunk *) realloc(list, (i+1)*sizeof(thunk) ); ! 55: if (!list) ! 56: Fatal_Error("Out of memory!"); ! 57: ! 58: list[i++] = t; ! 59: list->thunk_count = i; ! 60: ! 61: return(list); ! 62: } ! 63: ! 64: /* ! 65: * Misc. routines ! 66: */ ! 67: ! 68: char *Copy_String(string) ! 69: char *string; ! 70: { ! 71: char *new; ! 72: int length; ! 73: ! 74: length = strlen(string) + 1; ! 75: ! 76: new = (char *) Malloc(length); ! 77: bcopy(string, new, length); ! 78: ! 79: return(new); ! 80: } ! 81: ! 82: int Read_Char(stream) ! 83: FILE *stream; ! 84: { ! 85: int c; ! 86: ! 87: c = getc(stream); ! 88: if (c==EOF) ! 89: Fatal_Error("Bad format file: Unexpected EOF."); ! 90: return(c); ! 91: } ! 92: ! 93: Read_White_Space(stream) ! 94: FILE *stream; ! 95: { ! 96: int c; ! 97: ! 98: while ((c=getc(stream))==' ' || c=='\n' || c=='\t'); ! 99: ungetc(c, stream); ! 100: } ! 101: ! 102: static char _large_buffer[MAXSTR+10]; ! 103: ! 104: char *Read_Quoted(stream) ! 105: FILE *stream; ! 106: { ! 107: char *ptr; ! 108: int c, length; ! 109: ! 110: Read_White_Space(stream); ! 111: if (Read_Char(stream)!='\'') ! 112: Fatal_Error("Bad format file format: missing dformat."); ! 113: ! 114: ptr = _large_buffer; length=MAXSTR; ! 115: for (;;) { ! 116: if (length<0) ! 117: Fatal_Error("Bad format file format: dformat too long."); ! 118: c = Read_Char(stream); ! 119: if (c==(int) '\'') ! 120: break; ! 121: ptr++[0]=c; length--; ! 122: if (c== (int) '\\') { ! 123: c=Read_Char(stream); ! 124: if (c=='\n') { ! 125: ptr--; length++; ! 126: } else ! 127: ptr++[0]=c; length--; ! 128: } ! 129: } ! 130: ptr++[0]='\0'; ! 131: ! 132: return(Copy_String(_large_buffer)); ! 133: } ! 134: ! 135: /* ! 136: * ! 137: * Atom to format, dformat mapping Manager ! 138: * ! 139: */ ! 140: ! 141: #define D_FORMAT "0x" /* Default format for properties */ ! 142: #define D_DFORMAT " = $0+\n"; /* Default display pattern for properties */ ! 143: ! 144: static thunk *_property_formats = 0; /* Holds mapping */ ! 145: ! 146: Apply_Default_Formats(format, dformat) ! 147: char **format; ! 148: char **dformat; ! 149: { ! 150: if (!*format) ! 151: *format = D_FORMAT; ! 152: if (!*dformat) ! 153: *dformat = D_DFORMAT; ! 154: } ! 155: ! 156: Lookup_Formats(atom, format, dformat) ! 157: Atom atom; ! 158: char **format; ! 159: char **dformat; ! 160: { ! 161: int i; ! 162: ! 163: if (_property_formats) ! 164: for (i=_property_formats->thunk_count-1; i>=0; i--) ! 165: if (_property_formats[i].value==atom) { ! 166: if (!*format) ! 167: *format = _property_formats[i].format; ! 168: if (!*dformat) ! 169: *dformat = _property_formats[i].dformat; ! 170: break; ! 171: } ! 172: } ! 173: ! 174: Add_Mapping(atom, format, dformat) ! 175: Atom atom; ! 176: char *format; ! 177: char *dformat; ! 178: { ! 179: thunk t; ! 180: ! 181: if (!_property_formats) ! 182: _property_formats = Create_Thunk_List(); ! 183: ! 184: t.value=atom; ! 185: t.format=format; ! 186: t.dformat=dformat; ! 187: ! 188: _property_formats = Add_Thunk(_property_formats, t); ! 189: } ! 190: ! 191: /* ! 192: * ! 193: * Setup_Mapping: Routine to setup default atom to format, dformat mapping: ! 194: * ! 195: */ ! 196: ! 197: typedef struct { Atom atom; char *format; char *dformat } _default_mapping; ! 198: _default_mapping _default_mappings[] = { ! 199: ! 200: /* ! 201: * General types: ! 202: */ ! 203: { XA_INTEGER, "0i", 0 }, ! 204: { XA_CARDINAL, "0c", 0 }, ! 205: { XA_STRING, "8s", 0 }, ! 206: { XA_ATOM, "32a", 0 }, ! 207: ! 208: { XA_POINT, "16ii", " = $0, $1\n" }, ! 209: { XA_RECTANGLE, "16iicc", ":\n\t\tupper left corner: $0, $1\n\ ! 210: \t\tsize: $2 by $3\n" }, ! 211: { XA_ARC, "16iiccii", ":\n\t\tarc at $0, $1\n\ ! 212: \t\tsize: $2 by $3\n\ ! 213: \t\tfrom angle $4 to angle $5\n" }, ! 214: ! 215: { XA_FONT, "32x", ": font id # $0\n" }, ! 216: { XA_DRAWABLE, "32x", ": drawable id # $0\n" }, ! 217: { XA_WINDOW, "32x", ": window id # $0\n" }, ! 218: { XA_PIXMAP, "32x", ": pixmap id # $0\n" }, ! 219: { XA_BITMAP, "32x", ": bitmap id # $0\n" }, ! 220: { XA_VISUALID, "32x", ": visual id # $0\n" }, ! 221: { XA_COLORMAP, "32x", ": colormap id # $0\n" }, ! 222: { XA_CURSOR, "32x", ": cursor id # $0\n" }, ! 223: ! 224: { XA_RGB_COLOR_MAP, "32xccccccc", ":\n\ ! 225: \t\tcolormap id #: $0\n\ ! 226: \t\tred-max: $1\n\ ! 227: \t\tred-mult: $2\n\ ! 228: \t\tgreen-max: $3\n\ ! 229: \t\tgreen-mult: $4\n\ ! 230: \t\tblue-max: $5\n\ ! 231: \t\tblue-mult: $6\n\ ! 232: \t\tbase-pixel: $7\n" }, ! 233: ! 234: /* ! 235: * Window manager types: ! 236: */ ! 237: { XA_WM_COMMAND, "8s", " = { $0+ }\n" }, ! 238: { XA_WM_HINTS, "32mbcxxxii", ":\n\ ! 239: ?m0(\t\tApplication accepts input\\?: $1\n)\ ! 240: ?m1(\t\tInitial state is \ ! 241: ?$2=0(Don't Care State)\ ! 242: ?$2=1(Normal State)\ ! 243: ?$2=2(Zoomed State)\ ! 244: ?$2=3(Iconic State)\ ! 245: ?$2=4(Inactive State)\ ! 246: .\n)\ ! 247: ?m2(\t\tpixmap id # to use for icon: $3\n)\ ! 248: ?m5(\t\tbitmap id # of mask for icon: $5\n)\ ! 249: ?m3(\t\twindow id # to use for icon: $4\n)\ ! 250: ?m4(\t\tstarting position for icon: $6, $7\n)" }, ! 251: { XA_WM_SIZE_HINTS, "32mii", ":\n\ ! 252: ?m0(\t\tuser specified location: $1, $2\n)\ ! 253: ?m2(\t\tprogram specified location: $1, $2\n)\ ! 254: ?m1(\t\tuser specified size: $3 by $4\n)\ ! 255: ?m3(\t\tprogram specified size: $3 by $4\n)\ ! 256: ?m4(\t\tprogram specified minimum size: $5 by $6\n)\ ! 257: ?m5(\t\tprogram specified maximum size: $7 by $8\n)\ ! 258: ?m6(\t\tprogram specified resize increment: $9 by $10\n)\ ! 259: ?m7(\t\tprogram specified minimum ascept ratio: $11/$12\n\ ! 260: \t\tprogram specified maximum ascept ratio: $13/$14\n)" }, ! 261: { XA_WM_ICON_SIZE, "32cccccc", ":\n\ ! 262: \t\tminimum icon size: $0 by $1\n\ ! 263: \t\tmaximum icon size: $2 by $3\n\ ! 264: \t\tincremental size change: $4 by $5\n" }, ! 265: ! 266: /* ! 267: * Font specific mapping of property names to types: ! 268: */ ! 269: { XA_MIN_SPACE, "32c", 0 }, ! 270: { XA_NORM_SPACE, "32c", 0 }, ! 271: { XA_MAX_SPACE, "32c", 0 }, ! 272: { XA_END_SPACE, "32c", 0 }, ! 273: { XA_SUPERSCRIPT_X, "32i", 0 }, ! 274: { XA_SUPERSCRIPT_Y, "32i", 0 }, ! 275: { XA_SUBSCRIPT_X, "32i", 0 }, ! 276: { XA_SUBSCRIPT_Y, "32i", 0 }, ! 277: { XA_UNDERLINE_POSITION, "32i", 0 }, ! 278: { XA_UNDERLINE_THICKNESS, "32c", 0 }, ! 279: { XA_STRIKEOUT_ASCENT, "32i", 0 }, ! 280: { XA_STRIKEOUT_DESCENT, "32i", 0 }, ! 281: { XA_ITALIC_ANGLE, "32i", 0 }, ! 282: { XA_X_HEIGHT, "32i", 0 }, ! 283: { XA_QUAD_WIDTH, "32i", 0 }, ! 284: { XA_WEIGHT, "32c", 0 }, ! 285: { XA_POINT_SIZE, "32c", 0 }, ! 286: { XA_RESOLUTION, "32c", 0 }, ! 287: { XA_COPYRIGHT, "32a", 0 }, ! 288: { XA_NOTICE, "32a", 0 }, ! 289: { XA_FONT_NAME, "32a", 0 }, ! 290: { XA_FAMILY_NAME, "32a", 0 }, ! 291: { XA_FULL_NAME, "32a", 0 }, ! 292: ! 293: { 0, 0, 0 } }; ! 294: ! 295: Setup_Mapping() ! 296: { ! 297: _default_mapping *dmap = _default_mappings; ! 298: ! 299: while (dmap->format) { ! 300: Add_Mapping( dmap->atom, dmap->format, dmap->dformat ); ! 301: dmap++; ! 302: } ! 303: } ! 304: ! 305: /* ! 306: * Read_Mapping: routine to read in additional mappings from a stream ! 307: * already open for reading. ! 308: */ ! 309: ! 310: Read_Mappings(stream) ! 311: FILE *stream; ! 312: { ! 313: char format_buffer[100]; ! 314: char name[1000], *dformat, *format; ! 315: int count, c; ! 316: Atom atom, Parse_Atom(); ! 317: ! 318: while ((count=fscanf(stream," %990s %90s ",name,format_buffer))!=EOF) { ! 319: if (count != 2) ! 320: Fatal_Error("Bad format file format."); ! 321: ! 322: atom = Parse_Atom(name, False); ! 323: format = Copy_String(format_buffer); ! 324: ! 325: Read_White_Space(stream); ! 326: dformat = D_DFORMAT; ! 327: c = getc(stream); ! 328: ungetc(c, stream); ! 329: if (c==(int)'\'') ! 330: dformat = Read_Quoted(stream); ! 331: ! 332: Add_Mapping(atom, format, dformat); ! 333: } ! 334: } ! 335: ! 336: /* ! 337: * ! 338: * Formatting Routines: a group of routines to translate from various ! 339: * values to a static read-only string useful for output. ! 340: * ! 341: * Routines: Format_Hex, Format_Unsigned, Format_Signed, Format_Atom, ! 342: * Format_Mask_Word, Format_Bool, Format_String, Format_Len_String. ! 343: * ! 344: * All of the above routines take a long except for Format_String and ! 345: * Format_Len_String. ! 346: * ! 347: */ ! 348: static char _formatting_buffer[MAXSTR+100]; ! 349: static char _formatting_buffer2[10]; ! 350: ! 351: char *Format_Hex(word) ! 352: long word; ! 353: { ! 354: sprintf(_formatting_buffer2, "0x%lx", word); ! 355: return(_formatting_buffer2); ! 356: } ! 357: ! 358: char *Format_Unsigned(word) ! 359: long word; ! 360: { ! 361: sprintf(_formatting_buffer2, "%lu", word); ! 362: return(_formatting_buffer2); ! 363: } ! 364: ! 365: char *Format_Signed(word) ! 366: long word; ! 367: { ! 368: sprintf(_formatting_buffer2, "%ld", word); ! 369: return(_formatting_buffer2); ! 370: } ! 371: ! 372: char *Format_Atom(atom) ! 373: Atom atom; ! 374: { ! 375: char *name; ! 376: ! 377: name=XGetAtomName(dpy, atom); ! 378: if (!name) ! 379: sprintf(_formatting_buffer, "undefined atom # 0x%lx", atom); ! 380: else ! 381: strncpy(_formatting_buffer, name, MAXSTR); ! 382: ! 383: return(_formatting_buffer); ! 384: } ! 385: ! 386: char *Format_Mask_Word(word) ! 387: long word; ! 388: { ! 389: long bit_mask, bit; ! 390: int seen = 0; ! 391: ! 392: strcpy(_formatting_buffer, "{MASK: "); ! 393: for (bit=0, bit_mask=1; bit<=sizeof(long)*8; bit++, bit_mask<<=1) { ! 394: if (bit_mask & word) { ! 395: if (seen) { ! 396: strcat(_formatting_buffer, ", "); ! 397: } ! 398: seen=1; ! 399: strcat(_formatting_buffer, Format_Unsigned(bit)); ! 400: } ! 401: } ! 402: strcat(_formatting_buffer, "}"); ! 403: ! 404: return(_formatting_buffer); ! 405: } ! 406: ! 407: char *Format_Bool(value) ! 408: long value; ! 409: { ! 410: if (!value) ! 411: return("False"); ! 412: ! 413: return("True"); ! 414: } ! 415: ! 416: static char *_buf_ptr; ! 417: static int _buf_len; ! 418: ! 419: _put_char(c) ! 420: char c; ! 421: { ! 422: if (--_buf_len<0) { ! 423: _buf_ptr[0]='\0'; ! 424: return; ! 425: } ! 426: _buf_ptr++[0] = c; ! 427: } ! 428: ! 429: _format_char(c) ! 430: char c; ! 431: { ! 432: switch (c) { ! 433: case '\\': ! 434: case '\"': ! 435: _put_char('\\'); ! 436: _put_char(c); ! 437: break; ! 438: case '\n': ! 439: _put_char('\\'); ! 440: _put_char('n'); ! 441: break; ! 442: case '\t': ! 443: _put_char('\\'); ! 444: _put_char('t'); ! 445: break; ! 446: default: ! 447: if (c<' ') { ! 448: _put_char('\\'); ! 449: sprintf(_buf_ptr, "%o", (int) c); ! 450: _buf_ptr += strlen(_buf_ptr); ! 451: _buf_len -= strlen(_buf_ptr); ! 452: } else ! 453: _put_char(c); ! 454: } ! 455: } ! 456: ! 457: char *Format_String(string) ! 458: char *string; ! 459: { ! 460: char c; ! 461: ! 462: _buf_ptr = _formatting_buffer; ! 463: _buf_len = MAXSTR; ! 464: _put_char('\"'); ! 465: ! 466: while (c = string++[0]) ! 467: _format_char(c); ! 468: ! 469: _buf_len += 3; ! 470: _put_char('\"'); ! 471: _put_char('\0'); ! 472: return(_formatting_buffer); ! 473: } ! 474: ! 475: char *Format_Len_String(string, len) ! 476: char *string; ! 477: int len; ! 478: { ! 479: char *data, *result; ! 480: ! 481: data = (char *) Malloc(len+1); ! 482: ! 483: bcopy(string, data, len); ! 484: data[len]='\0'; ! 485: ! 486: result = Format_String(data); ! 487: free(data); ! 488: ! 489: return(result); ! 490: } ! 491: ! 492: /* ! 493: * ! 494: * Parsing Routines: a group of routines to parse strings into values ! 495: * ! 496: * Routines: Parse_Atom, Scan_Long, Skip_Past_Right_Paran, Scan_Octal ! 497: * ! 498: * Routines of the form Parse_XXX take a string which is parsed to a value. ! 499: * Routines of the form Scan_XXX take a string, parse the beginning to a value, ! 500: * and return the rest of the string. The value is returned via. the last ! 501: * parameter. All numeric values are longs! ! 502: * ! 503: */ ! 504: ! 505: char *Skip_Digits(string) ! 506: char *string; ! 507: { ! 508: while (isdigit(string[0])) string++; ! 509: return(string); ! 510: } ! 511: ! 512: char *Scan_Long(string, value) ! 513: char *string; ! 514: long *value; ! 515: { ! 516: if (!isdigit(*string)) ! 517: Fatal_Error("Bad number: %s.", string); ! 518: ! 519: *value = atol(string); ! 520: return(Skip_Digits(string)); ! 521: } ! 522: ! 523: char *Scan_Octal(string, value) ! 524: char *string; ! 525: long *value; ! 526: { ! 527: if (sscanf(string, "%lo", value)!=1) ! 528: Fatal_Error("Bad octal number: %s.", string); ! 529: return(Skip_Digits(string)); ! 530: } ! 531: ! 532: Atom Parse_Atom(name, only_if_exists) ! 533: char *name; ! 534: int only_if_exists; ! 535: { ! 536: Atom atom; ! 537: ! 538: if ((atom = XInternAtom(dpy, name, only_if_exists))==None) ! 539: return(0); ! 540: ! 541: return(atom); ! 542: } ! 543: ! 544: char *Skip_Past_Right_Paran(string) ! 545: char *string; ! 546: { ! 547: char c; ! 548: int nesting=0; ! 549: ! 550: while (c=string++[0], c!=')' || nesting) ! 551: switch (c) { ! 552: case '\0': ! 553: Fatal_Error("Missing ')'."); ! 554: case '(': ! 555: nesting++; ! 556: break; ! 557: case ')': ! 558: nesting--; ! 559: break; ! 560: case '\\': ! 561: string++; ! 562: break; ! 563: } ! 564: return(string); ! 565: } ! 566: ! 567: /* ! 568: * ! 569: * The Format Manager: a group of routines to manage "formats" ! 570: * ! 571: */ ! 572: ! 573: int Is_A_Format(string) ! 574: char *string; ! 575: { ! 576: return(isdigit(string[0])); ! 577: } ! 578: ! 579: int Get_Format_Size(format) ! 580: char *format; ! 581: { ! 582: long size; ! 583: ! 584: Scan_Long(format, &size); ! 585: ! 586: /* Check for legal sizes */ ! 587: if (size != 0 && size != 8 && size != 16 && size != 32) ! 588: Fatal_Error("bad format: %s", format); ! 589: ! 590: return((int) size); ! 591: } ! 592: ! 593: char Get_Format_Char(format, i) ! 594: char *format; ! 595: int i; ! 596: { ! 597: long size; ! 598: ! 599: /* Remove # at front of format */ ! 600: format = Scan_Long(format, &size); ! 601: if (!*format) ! 602: Fatal_Error("bad format: %s", format); ! 603: ! 604: /* Last character repeats forever... */ ! 605: if (i>=strlen(format)) ! 606: i=strlen(format)-1; ! 607: ! 608: return(format[i]); ! 609: } ! 610: ! 611: char *Format_Thunk(t, format_char) ! 612: thunk t; ! 613: char format_char; ! 614: { ! 615: long value; ! 616: value = t.value; ! 617: ! 618: switch (format_char) { ! 619: case 's': ! 620: return(Format_Len_String(t.extra_value, t.value)); ! 621: case 'x': ! 622: return(Format_Hex(value)); ! 623: case 'c': ! 624: return(Format_Unsigned(value)); ! 625: case 'i': ! 626: return(Format_Signed(value)); ! 627: case 'b': ! 628: return(Format_Bool(value)); ! 629: case 'm': ! 630: return(Format_Mask_Word(value)); ! 631: case 'a': ! 632: return(Format_Atom(value)); ! 633: default: ! 634: Fatal_Error("bad format character: %c", format_char); ! 635: } ! 636: } ! 637: ! 638: char *Format_Thunk_I(thunks, format, i) ! 639: thunk *thunks; ! 640: char *format; ! 641: int i; ! 642: { ! 643: if (i >= thunks->thunk_count) ! 644: return("<field not available>"); ! 645: ! 646: return(Format_Thunk(thunks[i], Get_Format_Char(format, i))); ! 647: } ! 648: ! 649: long Mask_Word(thunks, format) ! 650: thunk *thunks; ! 651: char *format; ! 652: { ! 653: int j; ! 654: ! 655: for (j=0; j<strlen(format); j++) ! 656: if (Get_Format_Char(format, j) == 'm') ! 657: return(thunks[j].value); ! 658: return(0L); ! 659: } ! 660: ! 661: /* ! 662: * ! 663: * The Display Format Manager: ! 664: * ! 665: */ ! 666: ! 667: int Is_A_DFormat(string) ! 668: char *string; ! 669: { ! 670: return( string[0] && string[0]!='-' && !isalpha(string[0]) ); ! 671: } ! 672: ! 673: char *Handle_Backslash(dformat) ! 674: char *dformat; ! 675: { ! 676: char c; ! 677: long i; ! 678: ! 679: if (!(c = *(dformat++))) ! 680: return(dformat); ! 681: ! 682: switch (c) { ! 683: case 'n': ! 684: putchar('\n'); ! 685: break; ! 686: case 't': ! 687: putchar('\t'); ! 688: break; ! 689: case '0': ! 690: case '1': ! 691: case '2': ! 692: case '3': ! 693: case '4': ! 694: case '5': ! 695: case '6': ! 696: case '7': ! 697: dformat = Scan_Octal(dformat, &i); ! 698: putchar((int) i); ! 699: break; ! 700: default: ! 701: putchar(c); ! 702: break; ! 703: } ! 704: return(dformat); ! 705: } ! 706: ! 707: char *Handle_Dollar_sign(dformat, thunks, format) ! 708: char *dformat; ! 709: thunk *thunks; ! 710: char *format; ! 711: { ! 712: long i; ! 713: ! 714: dformat = Scan_Long(dformat, &i); ! 715: ! 716: if (dformat[0]=='+') { ! 717: int seen=0; ! 718: dformat++; ! 719: for (; i<thunks->thunk_count; i++) { ! 720: if (seen) ! 721: printf(", "); ! 722: seen = 1; ! 723: printf("%s", Format_Thunk_I(thunks, format, (int) i)); ! 724: } ! 725: } else ! 726: printf("%s", Format_Thunk_I(thunks, format, (int) i)); ! 727: ! 728: return(dformat); ! 729: } ! 730: ! 731: int Mask_Bit_I(thunks, format, i) ! 732: thunk *thunks; ! 733: char *format; ! 734: int i; ! 735: { ! 736: long value; ! 737: ! 738: value = Mask_Word(thunks, format); ! 739: ! 740: value = value & (1L<<i); ! 741: if (value) ! 742: value=1; ! 743: return(value); ! 744: } ! 745: ! 746: char *Scan_Term(string, thunks, format, value) ! 747: thunk *thunks; ! 748: char *string, *format; ! 749: long *value; ! 750: { ! 751: long i; ! 752: ! 753: *value=0; ! 754: ! 755: if (isdigit(*string)) ! 756: string = Scan_Long(string, value); ! 757: else if (*string=='$') { ! 758: string = Scan_Long(++string, &i); ! 759: if (i>=thunks->thunk_count) ! 760: i=thunks->thunk_count; ! 761: *value = thunks[i].value; ! 762: } else if (*string=='m') { ! 763: string = Scan_Long(++string, &i); ! 764: *value = Mask_Bit_I(thunks, format, (int) i); ! 765: } else ! 766: Fatal_Error("Bad term: %s.", string); ! 767: ! 768: return(string); ! 769: } ! 770: ! 771: char *Scan_Exp(string, thunks, format, value) ! 772: thunk *thunks; ! 773: char *string, *format; ! 774: long *value; ! 775: { ! 776: long temp; ! 777: ! 778: if (string[0]=='(') { ! 779: string = Scan_Exp(++string, thunks, format, value); ! 780: if (string[0]!=')') ! 781: Fatal_Error("Missing ')'"); ! 782: return(++string); ! 783: } ! 784: if (string[0]=='!') { ! 785: string = Scan_Exp(++string, thunks, format, value); ! 786: *value = !*value; ! 787: return(string); ! 788: } ! 789: ! 790: string = Scan_Term(string, thunks, format, value); ! 791: ! 792: if (string[0]=='=') { ! 793: string = Scan_Exp(++string, thunks, format, &temp); ! 794: *value = *value == temp; ! 795: } ! 796: ! 797: return(string); ! 798: } ! 799: ! 800: char *Handle_Question_Mark(dformat, thunks, format) ! 801: thunk *thunks; ! 802: char *dformat, *format; ! 803: { ! 804: long true; ! 805: ! 806: dformat = Scan_Exp(dformat, thunks, format, &true); ! 807: ! 808: if (*dformat!='(') ! 809: Fatal_Error("Bad conditional: '(' expected: %s.", dformat); ! 810: ++dformat; ! 811: ! 812: if (!true) ! 813: dformat = Skip_Past_Right_Paran(dformat); ! 814: ! 815: return(dformat); ! 816: } ! 817: ! 818: Display_Property(thunks, dformat, format) ! 819: thunk *thunks; ! 820: char *dformat, *format; ! 821: { ! 822: char c; ! 823: ! 824: while (c = *(dformat++)) ! 825: switch (c) { ! 826: case ')': ! 827: continue; ! 828: case '\\': ! 829: dformat = Handle_Backslash(dformat); ! 830: continue; ! 831: case '$': ! 832: dformat = Handle_Dollar_sign(dformat, thunks, format); ! 833: continue; ! 834: case '?': ! 835: dformat = Handle_Question_Mark(dformat, thunks, format); ! 836: continue; ! 837: default: ! 838: putchar(c); ! 839: continue; ! 840: } ! 841: } ! 842: ! 843: /* ! 844: * ! 845: * Routines to convert property data to and from thunks ! 846: * ! 847: */ ! 848: ! 849: long Extract_Value(pointer, length, size, signedp) ! 850: char **pointer; ! 851: int *length; ! 852: int size; ! 853: { ! 854: long value, mask; ! 855: ! 856: switch (size) { ! 857: case 8: ! 858: value = (long) * (char *) *pointer; ! 859: *pointer += 1; ! 860: *length -= 1; ! 861: mask = 0xff; ! 862: break; ! 863: case 16: ! 864: value = (long) * (short *) *pointer; ! 865: *pointer += 2; ! 866: *length -= 2; ! 867: mask = 0xffff; ! 868: break; ! 869: default: ! 870: /* Error */ ! 871: case 32: ! 872: value = (long) * (long *) *pointer; ! 873: *pointer += 4; ! 874: *length -= 4; ! 875: mask = 0xffffffff; ! 876: break; ! 877: } ! 878: if (!signedp) ! 879: value &= mask; ! 880: return(value); ! 881: } ! 882: ! 883: long Extract_Len_String(pointer, length, size, string) ! 884: char **pointer; ! 885: int *length; ! 886: int size; ! 887: char **string; ! 888: { ! 889: int len; ! 890: ! 891: if (size!=8) ! 892: Fatal_Error("can't use format character 's' with any size except 8."); ! 893: len=0; *string = *pointer; ! 894: while ((len++, --*length, *((*pointer)++)) && *length>0); ! 895: ! 896: return(len); ! 897: } ! 898: ! 899: thunk *Break_Down_Property(pointer, length, format, size) ! 900: char *pointer, *format; ! 901: int length, size; ! 902: { ! 903: thunk *thunks; ! 904: thunk t; ! 905: int i; ! 906: char format_char; ! 907: ! 908: thunks = Create_Thunk_List(); ! 909: i=0; ! 910: ! 911: while (length>=(size/8)) { ! 912: format_char = Get_Format_Char(format, i); ! 913: if (format_char=='s') ! 914: t.value=Extract_Len_String(&pointer,&length,size,&t.extra_value); ! 915: else ! 916: t.value=Extract_Value(&pointer,&length,size,format_char=='i'); ! 917: thunks = Add_Thunk(thunks, t); ! 918: i++; ! 919: } ! 920: ! 921: return(thunks); ! 922: } ! 923: ! 924: /* ! 925: * ! 926: * Routines for parsing command line: ! 927: * ! 928: */ ! 929: ! 930: usage() ! 931: { ! 932: outl("\n%s: usage: %s [<select option>] <option>* <mapping>* <spec>*", ! 933: program_name, program_name); ! 934: outl("\n\tselect option ::= -root | -id <id> | -font <font> | -name <name>\ ! 935: \n\toption ::= -len <n> | -notype | -spy | {-formats|-fs} <format file>\ ! 936: \n\tmapping ::= {-f|-format} <atom> <format> [<dformat>]\ ! 937: \n\tspec ::= [<format> [<dformat>]] <atom>\ ! 938: \n\tformat ::= {0|8|16|32}{a|b|c|i|m|s|x}*\ ! 939: \n\tdformat ::= <unit><unit>* (can't start with a letter or '-')\ ! 940: \n\tunit ::= ?<exp>(<unit>*) | $<n> | <display char>\ ! 941: \n\texp ::= <term> | <term>=<exp> | !<exp>\ ! 942: \n\tterm ::= <n> | $<n> | m<n>\ ! 943: \n\tdisplay char ::= <normal char> | \\<non digit char> | \\<octal number>\ ! 944: \n\tnormal char ::= <any char except a digit, $, ?, \\, or )>\ ! 945: \n\n"); ! 946: exit(1); ! 947: } ! 948: ! 949: Parse_Format_Mapping(argc, argv) ! 950: int *argc; ! 951: char ***argv; ! 952: #define ARGC (*argc) ! 953: #define ARGV (*argv) ! 954: #define OPTION ARGV[0] ! 955: #define NXTOPT if (++ARGV, --ARGC==0) usage() ! 956: { ! 957: char *type_name, *format, *dformat; ! 958: ! 959: NXTOPT; type_name = OPTION; ! 960: ! 961: NXTOPT; format = OPTION; ! 962: if (!Is_A_Format(format)) ! 963: Fatal_Error("Bad format: %s.", format); ! 964: ! 965: dformat=0; ! 966: if (ARGC>0 && Is_A_DFormat(ARGV[1])) { ! 967: ARGV++; ARGC--; dformat=OPTION; ! 968: } ! 969: ! 970: Add_Mapping( Parse_Atom(type_name, False), format, dformat); ! 971: } ! 972: ! 973: /* ! 974: * ! 975: * The Main Program: ! 976: * ! 977: */ ! 978: ! 979: Window target_win=0; ! 980: int notype=0; ! 981: int spy=0; ! 982: int max_len=MAXSTR; ! 983: XFontStruct *font; ! 984: ! 985: main(argc, argv) ! 986: int argc; ! 987: char **argv; ! 988: { ! 989: FILE *stream; ! 990: char *name, *getenv(); ! 991: thunk *props, *Handle_Prop_Requests(); ! 992: ! 993: INIT_NAME; ! 994: ! 995: /* Handle display name, opening the display */ ! 996: Setup_Display_And_Screen(&argc, argv); ! 997: ! 998: /* Handle selecting the window to display properties for */ ! 999: target_win = Select_Window_Args(&argc, argv); ! 1000: ! 1001: /* Set up default atom to format, dformat mapping */ ! 1002: Setup_Mapping(); ! 1003: if (name = getenv("XPROPFORMATS")) { ! 1004: if (!(stream=fopen(name, "r"))) ! 1005: Fatal_Error("unable to open file %s for reading.", name); ! 1006: Read_Mappings(stream); ! 1007: fclose(stream); ! 1008: } ! 1009: ! 1010: /* Handle '-' options to setup xprop, select window to work on */ ! 1011: while (argv++, --argc>0 && **argv=='-') { ! 1012: if (!strcmp(argv[0], "-")) ! 1013: continue; ! 1014: if (!strcmp(argv[0], "-notype")) { ! 1015: notype=1; ! 1016: continue; ! 1017: } ! 1018: if (!strcmp(argv[0], "-spy")) { ! 1019: spy=1; ! 1020: continue; ! 1021: } ! 1022: if (!strcmp(argv[0], "-len")) { ! 1023: if (++argv, --argc==0) usage(); ! 1024: max_len = atoi(argv[0]); ! 1025: continue; ! 1026: } ! 1027: if (!strcmp(argv[0], "-formats") || !strcmp(argv[0], "-fs")) { ! 1028: if (++argv, --argc==0) usage(); ! 1029: if (!(stream=fopen(argv[0], "r"))) ! 1030: Fatal_Error("unable to open file %s for reading.", argv[0]); ! 1031: Read_Mappings(stream); ! 1032: fclose(stream); ! 1033: continue; ! 1034: } ! 1035: if (!strcmp(argv[0], "-font")) { ! 1036: if (++argv, --argc==0) usage(); ! 1037: font = Open_Font(argv[0]); ! 1038: target_win = -1; ! 1039: continue; ! 1040: } ! 1041: if (!strcmp(argv[0], "-f") || !strcmp(argv[0], "-format")) { ! 1042: Parse_Format_Mapping(&argc, &argv); ! 1043: continue; ! 1044: } ! 1045: usage(); ! 1046: } ! 1047: ! 1048: if (target_win==0) ! 1049: target_win = Select_Window(dpy); ! 1050: ! 1051: props=Handle_Prop_Requests(argc, argv); ! 1052: ! 1053: if (spy && target_win != -1) { ! 1054: XEvent event; ! 1055: char *format, *dformat; ! 1056: ! 1057: XSelectInput(dpy, target_win, PropertyChangeMask); ! 1058: for (;;) { ! 1059: XNextEvent(dpy, &event); ! 1060: format = dformat = NULL; ! 1061: if (props) { ! 1062: int i; ! 1063: for (i=0; i<props->thunk_count; i++) ! 1064: if (props[i].value == event.xproperty.atom) ! 1065: break; ! 1066: if (i>=props->thunk_count) ! 1067: continue; ! 1068: format = props[i].format; ! 1069: dformat = props[i].dformat; ! 1070: } ! 1071: Show_Prop(format, dformat, Format_Atom(event.xproperty.atom)); ! 1072: } ! 1073: } ! 1074: } ! 1075: ! 1076: /* ! 1077: * ! 1078: * Other Stuff (temp.): ! 1079: * ! 1080: */ ! 1081: ! 1082: thunk *Handle_Prop_Requests(argc, argv) ! 1083: int argc; ! 1084: char **argv; ! 1085: { ! 1086: char *format, *dformat, *prop; ! 1087: thunk *thunks, t; ! 1088: ! 1089: thunks = Create_Thunk_List(); ! 1090: ! 1091: /* if no prop referenced, by default list all properties for given window */ ! 1092: if (!argc) { ! 1093: Show_All_Props(); ! 1094: return(NULL); ! 1095: } ! 1096: ! 1097: while (argc>0) { ! 1098: format = 0; ! 1099: dformat = 0; ! 1100: ! 1101: /* Get overriding formats, if any */ ! 1102: if (Is_A_Format(argv[0])) { ! 1103: format = argv++[0]; argc--; ! 1104: if (!argc) usage(); ! 1105: } ! 1106: if (Is_A_DFormat(argv[0])) { ! 1107: dformat = argv++[0]; argc--; ! 1108: if (!argc) usage(); ! 1109: } ! 1110: ! 1111: /* Get property name */ ! 1112: prop = argv++[0]; argc--; ! 1113: ! 1114: t.value = Parse_Atom(prop, True); ! 1115: t.format = format; ! 1116: t.dformat = dformat; ! 1117: if (t.value) ! 1118: thunks = Add_Thunk(thunks, t); ! 1119: Show_Prop(format, dformat, prop); ! 1120: } ! 1121: return(thunks); ! 1122: } ! 1123: ! 1124: Show_All_Props() ! 1125: { ! 1126: Atom *atoms, atom; ! 1127: char *name; ! 1128: int count, i; ! 1129: ! 1130: if (target_win!=-1) { ! 1131: atoms = XListProperties(dpy, target_win, &count); ! 1132: for (i=0; i<count; i++) { ! 1133: name = Format_Atom(atoms[i]); ! 1134: Show_Prop(0, 0, name); ! 1135: } ! 1136: } else ! 1137: for (i=0; i<font->n_properties; i++) { ! 1138: atom = font->properties[i].name; ! 1139: name = Format_Atom(atom); ! 1140: Show_Prop(0, 0, name); ! 1141: } ! 1142: } ! 1143: ! 1144: Set_Prop(format, dformat, prop, mode, value) ! 1145: char *format, *dformat, *prop, *value; ! 1146: char mode; ! 1147: { ! 1148: outl("Seting prop %s(%s) using %s mode %c to %s", ! 1149: prop, format, dformat, mode, value); ! 1150: } ! 1151: ! 1152: static unsigned long _font_prop; ! 1153: ! 1154: char *Get_Font_Property_Data_And_Type(atom, length, type, size) ! 1155: Atom atom; ! 1156: long *length; ! 1157: Atom *type; ! 1158: int *size; ! 1159: { ! 1160: int i; ! 1161: ! 1162: *type = 0; ! 1163: ! 1164: for (i=0; i<font->n_properties; i++) ! 1165: if (atom==font->properties[i].name) { ! 1166: _font_prop=font->properties[i].card32; ! 1167: *length=4; ! 1168: *size=32; ! 1169: return((char *) &_font_prop); ! 1170: } ! 1171: return(0); ! 1172: } ! 1173: ! 1174: char *Get_Window_Property_Data_And_Type(atom, length, type, size) ! 1175: Atom atom; ! 1176: long *length; ! 1177: Atom *type; ! 1178: int *size; ! 1179: { ! 1180: Atom actual_type; ! 1181: int actual_format; ! 1182: long nitems; ! 1183: long bytes_after; ! 1184: char *prop; ! 1185: int status; ! 1186: ! 1187: status = XGetWindowProperty(dpy, target_win, atom, 0, (max_len+3)/4, ! 1188: False, AnyPropertyType, &actual_type, ! 1189: &actual_format, &nitems, &bytes_after, ! 1190: &prop); ! 1191: if (status==BadWindow) ! 1192: Fatal_Error("window id # 0x%lx does not exists!", target_win); ! 1193: if (status!=Success) ! 1194: Fatal_Error("XGetWindowProperty failed!"); ! 1195: ! 1196: *length = min(nitems * actual_format/8, max_len); ! 1197: *type = actual_type; ! 1198: *size = actual_format; ! 1199: return(prop); ! 1200: } ! 1201: ! 1202: char *Get_Property_Data_And_Type(atom, length, type, size) ! 1203: Atom atom; ! 1204: long *length; ! 1205: Atom *type; ! 1206: int *size; ! 1207: { ! 1208: if (target_win == -1) ! 1209: return(Get_Font_Property_Data_And_Type(atom, length, type, size)); ! 1210: else ! 1211: return(Get_Window_Property_Data_And_Type(atom, length, type, size)); ! 1212: } ! 1213: ! 1214: Show_Prop(format, dformat, prop) ! 1215: char *format, *dformat, *prop; ! 1216: { ! 1217: char *data; ! 1218: long length; ! 1219: Atom atom, type; ! 1220: thunk *thunks; ! 1221: int size, fsize; ! 1222: ! 1223: printf("%s", prop); ! 1224: if (!(atom = Parse_Atom(prop, True))) { ! 1225: printf(": not defined.\n"); ! 1226: return; ! 1227: } ! 1228: ! 1229: data = Get_Property_Data_And_Type(atom, &length, &type, &size); ! 1230: if (!size) { ! 1231: puts(": not defined."); ! 1232: return; ! 1233: } ! 1234: ! 1235: if (!notype && type) ! 1236: printf("(%s)", Format_Atom(type)); ! 1237: ! 1238: Lookup_Formats(atom, &format, &dformat); ! 1239: if (type) ! 1240: Lookup_Formats(type, &format, &dformat); ! 1241: Apply_Default_Formats(&format, &dformat); ! 1242: ! 1243: fsize=Get_Format_Size(format); ! 1244: if (fsize!=size && fsize!=0) { ! 1245: printf(": Type mismatch: assumed size %d bits, actual size %d bits.\n", ! 1246: fsize, size); ! 1247: return; ! 1248: } ! 1249: ! 1250: thunks = Break_Down_Property(data, length, format, size); ! 1251: ! 1252: Display_Property(thunks, dformat, format); ! 1253: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.