|
|
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.