1 /*
2  *  Type Printing for X11 protocol
3  *
4  *	James Peterson, 1988
5  *
6  * Copyright (C) 1988 MCC
7  *
8  * Permission to use, copy, modify, distribute, and sell this software and its
9  * documentation for any purpose is hereby granted without fee, provided that
10  * the above copyright notice appear in all copies and that both that
11  * copyright notice and this permission notice appear in supporting
12  * documentation, and that the name of MCC not be used in
13  * advertising or publicity pertaining to distribution of the software without
14  * specific, written prior permission.  MCC makes no
15  * representations about the suitability of this software for any purpose.  It
16  * is provided "as is" without express or implied warranty.
17  *
18  * MCC DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
19  * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
20  * EVENT SHALL MCC BE LIABLE FOR ANY SPECIAL, INDIRECT OR
21  * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
22  * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
23  * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
24  * PERFORMANCE OF THIS SOFTWARE.
25  *
26  */
27 /*
28  * Copyright (c) 2002, 2012, Oracle and/or its affiliates. All rights reserved.
29  *
30  * Permission is hereby granted, free of charge, to any person obtaining a
31  * copy of this software and associated documentation files (the "Software"),
32  * to deal in the Software without restriction, including without limitation
33  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
34  * and/or sell copies of the Software, and to permit persons to whom the
35  * Software is furnished to do so, subject to the following conditions:
36  *
37  * The above copyright notice and this permission notice (including the next
38  * paragraph) shall be included in all copies or substantial portions of the
39  * Software.
40  *
41  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
42  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
43  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
44  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
45  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
46  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
47  * DEALINGS IN THE SOFTWARE.
48  *
49  */
50 
51 #include "scope.h"
52 #include "x11.h"
53 
54 /*
55   For each of the types we need a way to print that type.
56   Types are of varieties:
57 
58   (1) BUILTIN -- we have a separate routine to interpret and print
59   each built-in type.
60   (2) ENUMERATED, SET -- we have one routine which prints, given the
61   data and the list of values.
62   (3) RECORDS -- a separate routine for each to print each field.
63 
64 */
65 
66 /* ************************************************************ */
67 /*								*/
68 /*								*/
69 /* ************************************************************ */
70 
71 /* print representation of a character for debugging */
72 static const char *
printrep(unsigned short c)73 printrep(unsigned short c)
74 {
75     static char pr[8];
76 
77     if (c < 32) {
78         /* control characters */
79         pr[0] = '^';
80         pr[1] = c + 64;
81         pr[2] = '\0';
82     }
83     else if (c < 127) {
84         /* printing characters */
85         pr[0] = (char) c;
86         pr[1] = '\0';
87     }
88     else if (c == 127)
89         return ("<del>");
90     else if (c <= 0377) {
91         /* upper 128 codes from 128 to 255;  print as \ooo - octal  */
92         pr[0] = '\\';
93         pr[3] = '0' + (c & 7);
94         c = c >> 3;
95         pr[2] = '0' + (c & 7);
96         c = c >> 3;
97         pr[1] = '0' + (c & 3);
98         pr[4] = '\0';
99     }
100     else {
101         /* very large number -- print as 0xffff - 4 digit hex */
102         snprintf(pr, sizeof(pr), "0x%04x", c);
103     }
104     return (pr);
105 }
106 
107 /* ************************************************************ */
108 /*								*/
109 /*								*/
110 /* ************************************************************ */
111 
112 /*
113   we use indentation for two purposes:
114 
115    (1) To show substructure of records inside records ...
116    (2) To separate the bytes from the client (on the left) from
117        those from the server (on the right).
118 
119    Each indention level is one tab (8 spaces).
120 */
121 
122 #define MaxIndent 10
123 char Leader[MaxIndent + 1];
124 static short CurrentLevel = 0;
125 
126 void
SetIndentLevel(short which)127 SetIndentLevel(short which)
128 {
129     short i;
130 
131     if (which > MaxIndent)
132         which = MaxIndent;
133     if (which < 0)
134         which = 0;
135     if (which == CurrentLevel)
136         return;
137 
138     /* set the indent level to <which> */
139     /* -> set the Print Leader to <which> tabs */
140     for (i = 0; i < which; i++)
141         Leader[i] = '\t';
142     Leader[which] = '\0';
143     CurrentLevel = which;
144 }
145 
146 static void
ModifyIndentLevel(short amount)147 ModifyIndentLevel(short amount)
148 {
149     SetIndentLevel(CurrentLevel + amount);
150 }
151 
152 static short
SizeofLeader(void)153 SizeofLeader(void)
154 {
155     return (CurrentLevel * 8);
156 }
157 
158 /* ************************************************************ */
159 /*								*/
160 /*								*/
161 /* ************************************************************ */
162 
163 /* if we want verbose enough output, we will dump the buffer in hex */
164 
165 void
DumpItem(const char * name,FD fd,const unsigned char * buf,long n)166 DumpItem(const char *name, FD fd, const unsigned char *buf, long n)
167 {
168     if (n == 0)
169         return;
170 
171     fprintf(stdout, "%s%20s (fd %d): ", Leader, name, fd);
172 
173     DumpHexBuffer(buf, n);
174     fprintf(stdout, "\n");
175 }
176 
177 /* ************************************************************ */
178 /*								*/
179 /*								*/
180 /* ************************************************************ */
181 
182 int
PrintINT8(const unsigned char * buf)183 PrintINT8(const unsigned char *buf)
184 {
185     /* print a INT8 -- 8-bit signed integer */
186     short n = IByte(buf);
187 
188     if (n > 127)
189         n = 256 - n;
190     fprintf(stdout, "%d", n);
191     return 1;
192 }
193 
194 int
PrintINT16(const unsigned char * buf)195 PrintINT16(const unsigned char *buf)
196 {
197     /* print a INT16 -- 16-bit signed integer */
198     long n = IShort(buf);
199 
200     if (n > 32767)
201         n = 65536 - n;
202     fprintf(stdout, "%ld", n);
203     return 2;
204 }
205 
206 int
PrintINT32(const unsigned char * buf)207 PrintINT32(const unsigned char *buf)
208 {
209     /* print a INT32 -- 32-bit signed integer */
210     long n = ILong(buf);
211 
212     fprintf(stdout, "%ld", n);
213     return 4;
214 }
215 
216 /* ************************************************************ */
217 
218 int
PrintCARD8(const unsigned char * buf)219 PrintCARD8(const unsigned char *buf)
220 {
221     /* print a CARD8 -- 8-bit unsigned integer */
222     unsigned short n = IByte(buf);
223 
224     fprintf(stdout, "%02x", (unsigned) (n & 0xff));
225     return 1;
226 }
227 
228 int
PrintCARD16(const unsigned char * buf)229 PrintCARD16(const unsigned char *buf)
230 {
231     /* print a CARD16 -- 16-bit unsigned integer */
232     unsigned long n = IShort(buf);
233 
234     fprintf(stdout, "%04x", (unsigned) (n & 0xffff));
235     return 1;
236 }
237 
238 int
PrintCARD32(const unsigned char * buf)239 PrintCARD32(const unsigned char *buf)
240 {
241     /* print a CARD32 -- 32-bit unsigned integer */
242     unsigned long n = ILong(buf);
243 
244     fprintf(stdout, "%08lx", n);
245     return (4);
246 }
247 
248 /* ************************************************************ */
249 
250 int
PrintBYTE(const unsigned char * buf)251 PrintBYTE(const unsigned char *buf)
252 {
253     /* print a BYTE -- 8-bit value */
254     short n = IByte(buf);
255 
256     fprintf(stdout, "%02x", n);
257     return (1);
258 }
259 
260 int
PrintCHAR8(const unsigned char * buf)261 PrintCHAR8(const unsigned char *buf)
262 {
263     /* print a CHAR8 -- 8-bit character */
264     unsigned short n = IByte(buf);
265 
266     fprintf(stdout, "%s", printrep(n));
267     return (1);
268 }
269 
270 int
PrintSTRING16(const unsigned char * buf)271 PrintSTRING16(const unsigned char *buf)
272 {
273     /* print a CHAR2B -- 16-bit character which is never byte-swapped */
274     unsigned short n = IChar2B(buf);
275 
276     fprintf(stdout, "%s", printrep(n));
277     return 2 + n;
278 }
279 
280 int
PrintSTR(const unsigned char * buf)281 PrintSTR(const unsigned char *buf)
282 {
283     /* STR have the length (1 byte) then a string of CHAR8 */
284     short n;
285 
286     short i;
287 
288     n = IByte(buf++);
289     for (i = 0; i < n; i++)
290         fprintf(stdout, "%s", printrep(buf[i]));
291     return (n + 1);
292 }
293 
294 /* ************************************************************ */
295 
296 int
PrintWINDOW(const unsigned char * buf)297 PrintWINDOW(const unsigned char *buf)
298 {
299     /* print a WINDOW -- CARD32  plus 0 = None */
300     long n = ILong(buf);
301 
302     if (n == 0)
303         fprintf(stdout, "None");
304     else
305         fprintf(stdout, "WIN %08lx", n);
306     return (4);
307 }
308 
309 int
PrintWINDOWD(const unsigned char * buf)310 PrintWINDOWD(const unsigned char *buf)
311 {
312     /* print a WINDOWD -- CARD32  plus 0 = PointerWindow, 1 = InputFocus */
313     long n = ILong(buf);
314 
315     if (n == 0)
316         fprintf(stdout, "PointerWindow");
317     else if (n == 1)
318         fprintf(stdout, "InputFocus");
319     else
320         (void) PrintWINDOW(buf);
321     return 4;
322 }
323 
324 int
PrintWINDOWNR(const unsigned char * buf)325 PrintWINDOWNR(const unsigned char *buf)
326 {
327     /* print a WINDOWNR -- CARD32  plus 0 = None, 1 = PointerRoot */
328     long n = ILong(buf);
329 
330     if (n == 0)
331         fprintf(stdout, "None");
332     else if (n == 1)
333         fprintf(stdout, "PointerRoot");
334     else
335         (void) PrintWINDOW(buf);
336     return 4;
337 }
338 
339 int
PrintPIXMAP(const unsigned char * buf)340 PrintPIXMAP(const unsigned char *buf)
341 {
342     /* print a PIXMAP -- CARD32  plus 0 = None */
343     long n = ILong(buf);
344 
345     if (n == 0)
346         fprintf(stdout, "None");
347     else
348         fprintf(stdout, "PXM %08lx", n);
349     return 4;
350 }
351 
352 int
PrintPIXMAPNPR(const unsigned char * buf)353 PrintPIXMAPNPR(const unsigned char *buf)
354 {
355     /* print a PIXMAPNPR -- CARD32  plus 0 = None, 1 = ParentRelative */
356     long n = ILong(buf);
357 
358     if (n == 0)
359         fprintf(stdout, "None");
360     else if (n == 1)
361         fprintf(stdout, "ParentRelative");
362     else
363         PrintPIXMAP(buf);
364     return 4;
365 }
366 
367 int
PrintPIXMAPC(const unsigned char * buf)368 PrintPIXMAPC(const unsigned char *buf)
369 {
370     /* print a PIXMAPC -- CARD32  plus 0 = CopyFromParent */
371     long n = ILong(buf);
372 
373     if (n == 0)
374         fprintf(stdout, "CopyFromParent");
375     else
376         PrintPIXMAP(buf);
377     return 4;
378 }
379 
380 int
PrintCURSOR(const unsigned char * buf)381 PrintCURSOR(const unsigned char *buf)
382 {
383     /* print a CURSOR -- CARD32  plus 0 = None */
384     long n = ILong(buf);
385 
386     if (n == 0)
387         fprintf(stdout, "None");
388     else
389         fprintf(stdout, "CUR %08lx", n);
390     return 4;
391 }
392 
393 int
PrintFONT(const unsigned char * buf)394 PrintFONT(const unsigned char *buf)
395 {
396     /* print a FONT -- CARD32  plus 0 = None */
397     long n = ILong(buf);
398 
399     if (n == 0)
400         fprintf(stdout, "None");
401     else
402         fprintf(stdout, "FNT %08lx", n);
403     return 4;
404 }
405 
406 int
PrintGCONTEXT(const unsigned char * buf)407 PrintGCONTEXT(const unsigned char *buf)
408 {
409     /* print a GCONTEXT -- CARD32 */
410     long n = ILong(buf);
411 
412     fprintf(stdout, "GXC %08lx", n);
413     return 4;
414 }
415 
416 int
PrintCOLORMAP(const unsigned char * buf)417 PrintCOLORMAP(const unsigned char *buf)
418 {
419     /* print a COLORMAP -- CARD32 plus 0 = None */
420     long n = ILong(buf);
421 
422     if (n == 0)
423         fprintf(stdout, "None");
424     else
425         fprintf(stdout, "CMP %08lx", n);
426     return (4);
427 }
428 
429 int
PrintCOLORMAPC(const unsigned char * buf)430 PrintCOLORMAPC(const unsigned char *buf)
431 {
432     /* print a COLORMAPC -- CARD32 plus 0 = CopyFromParent */
433     long n = ILong(buf);
434 
435     if (n == 0)
436         fprintf(stdout, "CopyFromParent");
437     else
438         (void) PrintCOLORMAP(buf);
439     return 4;
440 }
441 
442 int
PrintDRAWABLE(const unsigned char * buf)443 PrintDRAWABLE(const unsigned char *buf)
444 {
445     /* print a DRAWABLE -- CARD32 */
446     long n = ILong(buf);
447 
448     fprintf(stdout, "DWB %08lx", n);
449     return 4;
450 }
451 
452 int
PrintFONTABLE(const unsigned char * buf)453 PrintFONTABLE(const unsigned char *buf)
454 {
455     /* print a FONTABLE -- CARD32 */
456     long n = ILong(buf);
457 
458     fprintf(stdout, "FTB %08lx", n);
459     return 4;
460 }
461 
462 /* ************************************************************ */
463 
464 /* for atoms, we print the built-in atoms, as well as any user defined
465    ones we've captured during this session. */
466 
467 int
PrintATOM(const unsigned char * buf)468 PrintATOM(const unsigned char *buf)
469 {
470     /* print a ATOM -- CARD32 plus 0 = None */
471     long n = ILong(buf);
472     const char *name = FindAtomName(n);
473 
474     if (name != NULL) {
475         if (Verbose > 1)
476             fprintf(stdout, "ATM %08lx <%s>", n, name);
477         else
478             fprintf(stdout, "<%s>", name);
479     }
480     else
481         fprintf(stdout, "ATM %08lx", n);
482     return (4);
483 }
484 
485 int
PrintATOMT(const unsigned char * buf)486 PrintATOMT(const unsigned char *buf)
487 {
488     /* print a ATOMT -- CARD32 plus 0 = AnyPropertyType */
489     long n = ILong(buf);
490 
491     if (n == 0)
492         fprintf(stdout, "AnyPropertyType");
493     else
494         (void) PrintATOM(buf);
495     return 4;
496 }
497 
498 int
PrintVISUALID(const unsigned char * buf)499 PrintVISUALID(const unsigned char *buf)
500 {
501     /* print a VISUALID -- CARD32 plus 0 = None */
502     long n = ILong(buf);
503 
504     if (n == 0)
505         fprintf(stdout, "None");
506     else
507         fprintf(stdout, "VIS %08lx", n);
508     return 4;
509 }
510 
511 int
PrintVISUALIDC(const unsigned char * buf)512 PrintVISUALIDC(const unsigned char *buf)
513 {
514     /* print a VISUALIDC -- CARD32 plus 0 = CopyFromParent */
515     long n = ILong(buf);
516 
517     if (n == 0)
518         fprintf(stdout, "CopyFromParent");
519     else
520         PrintVISUALID(buf);
521     return 4;
522 }
523 
524 int
PrintTIMESTAMP(const unsigned char * buf)525 PrintTIMESTAMP(const unsigned char *buf)
526 {
527     /* print a TIMESTAMP -- CARD32 plus 0 as the current time */
528     long n = ILong(buf);
529 
530     if (n == 0)
531         fprintf(stdout, "CurrentTime");
532     else
533         fprintf(stdout, "TIM %08lx", n);
534     return 4;
535 }
536 
537 int
PrintRESOURCEID(const unsigned char * buf)538 PrintRESOURCEID(const unsigned char *buf)
539 {
540     /* print a RESOURCEID -- CARD32 plus 0 = AllTemporary */
541     long n = ILong(buf);
542 
543     if (n == 0)
544         fprintf(stdout, "AllTemporary");
545     else
546         fprintf(stdout, "RID %08lx", n);
547     return 4;
548 }
549 
550 int
PrintKEYSYM(const unsigned char * buf)551 PrintKEYSYM(const unsigned char *buf)
552 {
553     /* print a KEYSYM -- CARD32 */
554     long n = ILong(buf);
555 
556     fprintf(stdout, "KYS %08lx", n);
557     return (4);
558 }
559 
560 int
PrintKEYCODE(const unsigned char * buf)561 PrintKEYCODE(const unsigned char *buf)
562 {
563     /* print a KEYCODE -- CARD8 */
564     unsigned short n = IByte(buf);
565 
566     fprintf(stdout, "%d (%s)", n, printrep(n));
567     return (1);
568 }
569 
570 int
PrintKEYCODEA(const unsigned char * buf)571 PrintKEYCODEA(const unsigned char *buf)
572 {
573     /* print a KEYCODEA -- CARD8 plus 0 = AnyKey */
574     long n = IByte(buf);
575 
576     if (n == 0)
577         fprintf(stdout, "AnyKey");
578     else
579         (void) PrintKEYCODE(buf);
580     return 1;
581 }
582 
583 int
PrintBUTTON(const unsigned char * buf)584 PrintBUTTON(const unsigned char *buf)
585 {
586     /* print a BUTTON -- CARD8 */
587     unsigned short n = IByte(buf);
588 
589     fprintf(stdout, "%d (%s)", n, printrep(n));
590     return 1;
591 }
592 
593 int
PrintBUTTONA(const unsigned char * buf)594 PrintBUTTONA(const unsigned char *buf)
595 {
596     /* print a BUTTONA -- CARD8 plus 0 = AnyButton */
597     long n = IByte(buf);
598 
599     if (n == 0)
600         fprintf(stdout, "AnyButton");
601     else
602         PrintBUTTON(buf);
603     return 1;
604 }
605 
606 /* this is an interesting cheat -- we call DecodeEvent to print an event */
607 /* should work, but its never been tried */
608 int
PrintEVENTFORM(const unsigned char * buf)609 PrintEVENTFORM(const unsigned char *buf)
610 {
611     /* print an EVENT_FORM -- event format */
612     DecodeEvent(-1, buf, (long) -1);
613     return 32;
614 }
615 
616 int
PrintEVENT(const unsigned char * buf)617 PrintEVENT(const unsigned char *buf)
618 {
619     uint8_t n = IByte(buf);
620     long e = (long) (n & 0x7f);
621     struct ValueListEntry *p;
622 
623     p = TD[EVENT].ValueList;
624     while (p != NULL && p->Value != e)
625         p = p->Next;
626 
627     if (p != NULL)
628         fprintf(stdout, "%s", p->Name);
629     else
630         fprintf(stdout, "**INVALID** (%d)", n);
631 
632     if (n & 0x80)
633         fprintf(stdout, "\n%s%20s: %s", Leader, "source", "SendEvent");
634 
635     return 1;
636 }
637 
638 /* ************************************************************ */
639 
640 int
PrintENUMERATED(const unsigned char * buf,short length,struct ValueListEntry * ValueList)641 PrintENUMERATED(const unsigned char *buf,
642                 short length, struct ValueListEntry *ValueList)
643 {
644     long n;
645     struct ValueListEntry *p;
646 
647     if (length == 1)
648         n = IByte(buf);
649     else if (length == 2)
650         n = IShort(buf);
651     else
652         n = ILong(buf);
653 
654     p = ValueList;
655     while (p != NULL && p->Value != n)
656         p = p->Next;
657 
658     if (p != NULL)
659         fprintf(stdout, "%s", p->Name);
660     else
661         fprintf(stdout, "**INVALID** (%ld)", n);
662 
663     return length;
664 }
665 
666 /* ************************************************************ */
667 
668 int
PrintSET(const unsigned char * buf,short length,struct ValueListEntry * ValueList)669 PrintSET(const unsigned char *buf,
670          short length, struct ValueListEntry *ValueList)
671 {
672     unsigned long n;
673     struct ValueListEntry *p;
674     Boolean MatchesAll = false;
675     Boolean FoundOne = false;
676 
677     if (length == 1)
678         n = IByte(buf);
679     else if (length == 2)
680         n = IShort(buf);
681     else
682         n = ILong(buf);
683 
684     if (n != 0) {
685         /* first check if the value matches ALL of the bits. */
686         MatchesAll = true;
687         for (p = ValueList; MatchesAll && (p != NULL); p = p->Next) {
688             if ((p->Value & n) == 0)
689                 MatchesAll = false;
690         }
691 
692         if (!MatchesAll)
693             /* if it matches some, but not all, print only those it matches */
694             for (p = ValueList; p != NULL; p = p->Next) {
695                 if ((p->Value & n) != 0) {
696                     if (FoundOne)
697                         fprintf(stdout, " | ");
698                     fprintf(stdout, "%s", p->Name);
699                     FoundOne = true;
700                 }
701             }
702     }
703 
704     if (MatchesAll)
705         fprintf(stdout, "<ALL>");
706     else if (!FoundOne)
707         fprintf(stdout, "0");
708 
709     return length;
710 }
711 
712 /* ************************************************************ */
713 /*								*/
714 /*								*/
715 /* ************************************************************ */
716 
717 void
PrintField(const unsigned char * buf,short start,short length,short FieldType,const char * name)718 PrintField(const unsigned char *buf,
719            short start, short length, short FieldType, const char *name)
720 {
721     if (Verbose == 0)
722         return;
723 
724     if (length == 0)
725         return;
726 
727     fprintf(stdout, "%s%20s: ", Leader, name);
728 
729     if (debuglevel & 8)
730         DumpHexBuffer(&(buf[start]), (long) length);
731 
732     switch (TD[FieldType].Type) {
733     case BUILTIN:
734         (*TD[FieldType].PrintProc) (&buf[start]);
735         break;
736 
737     case ENUMERATED:
738         PrintENUMERATED(&buf[start], length, TD[FieldType].ValueList);
739         break;
740 
741     case SET:
742         PrintSET(&buf[start], length, TD[FieldType].ValueList);
743         break;
744 
745     case RECORD:
746         ModifyIndentLevel(1);
747         fprintf(stdout, "\n");
748         if (Verbose < 3)
749             return;
750         (*TD[FieldType].PrintProc) (&buf[start]);
751         ModifyIndentLevel(-1);
752         break;
753     }
754     fprintf(stdout, "\n");
755     fflush(stdout);
756 }
757 
758 /* ************************************************************ */
759 /*								*/
760 /*								*/
761 /* ************************************************************ */
762 
763 /* print a list of things.  The things are of type <ListType>.
764    They start at <buf>.  There are <number> things in the list */
765 
766 long
PrintList(const unsigned char * buf,long number,short ListType,const char * name)767 PrintList(const unsigned char *buf,
768           long number, short ListType, const char *name)
769 {
770     long n;
771     long i;
772     long sum;
773 
774     if (Verbose == 0)
775         return (0);
776 
777     if (number == 0)
778         return (0);
779 
780     fprintf(stdout, "%s%20s: (%ld)\n", Leader, name, number);
781     if (Verbose < 2)
782         return (0);
783 
784     ModifyIndentLevel(1);
785     sum = 0;
786     for (i = 0; i < number; i++) {
787         switch (TD[ListType].Type) {
788         case BUILTIN:
789             n = (*TD[ListType].PrintProc) (buf);
790             break;
791         case RECORD:
792             n = (*TD[ListType].PrintProc) (buf);
793             break;
794         default:
795             fprintf(stdout, "**INVALID**");
796             n = 0;
797             break;
798         }
799         buf = buf + n;
800         sum = sum + n;
801         fprintf(stdout, "%s---\n", Leader);
802     }
803 
804     ModifyIndentLevel(-1);
805     return (sum);
806 }
807 
808 /* ************************************************************ */
809 /*								*/
810 /*								*/
811 /* ************************************************************ */
812 
813 /* print a list of STRs.  Similar to PrintList
814    They start at <buf>.  There are <number> things in the list */
815 
816 long
PrintListSTR(const unsigned char * buf,long number,const char * name)817 PrintListSTR(const unsigned char *buf, long number, const char *name)
818 {
819     long n;
820     long i;
821     long sum;
822 
823     if (number == 0)
824         return (0);
825 
826     fprintf(stdout, "%s%20s: (%ld)\n", Leader, name, number);
827     if (Verbose < 2)
828         return (0);
829 
830     ModifyIndentLevel(1);
831     sum = 0;
832     for (i = 0; i < number; i++) {
833         fprintf(stdout, "%s", Leader);
834         n = PrintSTR(buf);
835         buf = buf + n;
836         sum = sum + n;
837         fprintf(stdout, "\n");
838     }
839 
840     ModifyIndentLevel(-1);
841     return (sum);
842 }
843 
844 
845 /* ************************************************************ */
846 /*								*/
847 /*								*/
848 /* ************************************************************ */
849 
850 
851 int
PrintBytes(const unsigned char * buf,long number,const char * name)852 PrintBytes(const unsigned char *buf, long number, const char *name)
853 {
854     /* print a list of BYTE -- 8-bit character */
855     long i;
856     short column;
857 
858     if (number == 0)
859         return (0);
860 
861     fprintf(stdout, "%s%20s: ", Leader, name);
862     column = SizeofLeader() + 25;
863     for (i = 0; i < number; i++) {
864         if (column > 80) {
865             if (Verbose < 2)
866                 break;
867             fprintf(stdout, "\n%s%20s: ", Leader, "");
868             column = SizeofLeader() + 25;
869         }
870         fprintf(stdout, "%02x ", ((unsigned int) buf[i]));
871         column += 3;
872     }
873     fprintf(stdout, "\n");
874 
875     return (number);
876 }
877 
878 
879 /* ************************************************************ */
880 /*								*/
881 /*								*/
882 /* ************************************************************ */
883 
884 
885 /* print a String of CHAR8 -- 8-bit characters */
886 
887 int
PrintString8(const unsigned char * buf,int number,const char * name)888 PrintString8(const unsigned char *buf, int number, const char *name)
889 {
890     short i;
891 
892     if (number == 0)
893         return (0);
894 
895     fprintf(stdout, "%s%20s: \"", Leader, name);
896     for (i = 0; i < number; i++)
897         fprintf(stdout, "%s", printrep(buf[i]));
898     fprintf(stdout, "\"\n");
899 
900     return (number);
901 }
902 
903 /* print a String of CHAR16 -- 16-bit characters */
904 
905 int
PrintString16(const unsigned char * buf,int number,const char * name)906 PrintString16(const unsigned char *buf, int number, const char *name)
907 {
908     long i;
909     unsigned short c;
910 
911     if (number == 0)
912         return (0);
913 
914     fprintf(stdout, "%s%20s: \"", Leader, name);
915     for (i = 0; i < number * 2; i += 2) {
916         c = IChar2B(&buf[i]);
917         fprintf(stdout, "%s", printrep(c));
918     }
919     fprintf(stdout, "\"\n");
920 
921     return (number);
922 }
923 
924 void
PrintTString8(const unsigned char * buf,long number,const char * name)925 PrintTString8(const unsigned char *buf, long number, const char *name)
926 {
927     long i;
928     int off;
929 
930     if (number == 0)
931         return;
932 
933     off = 0;
934     if (TranslateText)
935         off = 0x20;
936     fprintf(stdout, "%s%20s: \"", Leader, name);
937     for (i = 0; i < number; i++)
938         fprintf(stdout, "%s", printrep(buf[i] + off));
939     fprintf(stdout, "\"\n");
940 }
941 
942 /* print a String of CHAR2B -- 16-bit characters */
943 void
PrintTString16(const unsigned char * buf,long number,const char * name)944 PrintTString16(const unsigned char *buf, long number, const char *name)
945 {
946     long i;
947     unsigned short c;
948     int off;
949 
950     if (number == 0)
951         return;
952 
953     off = 0;
954     if (TranslateText)
955         off = 0x20;
956     fprintf(stdout, "%s%20s: \"", Leader, name);
957     for (i = 0; i < number * 2; i += 2) {
958         c = IChar2B(&buf[i]);
959         fprintf(stdout, "%s", printrep(c + off));
960     }
961     fprintf(stdout, "\"\n");
962 }
963 
964 
965 /* ************************************************************ */
966 /*								*/
967 /*								*/
968 /* ************************************************************ */
969 
970 /*
971   A Value List is two things:
972 
973   (1) A controlling bitmask.  For each one bit in the control,
974   a value is in the list.
975   (2) A list of values.
976 */
977 
978 void
PrintValues(const unsigned char * control,int clength,int ctype,const unsigned char * values,const char * name)979 PrintValues(const unsigned char *control,
980             int clength,
981             int ctype, const unsigned char *values, const char *name)
982 {
983     long cmask;
984     struct ValueListEntry *p;
985 
986     /* first get the control mask */
987     if (clength == 1)
988         cmask = IByte(control);
989     else if (clength == 2)
990         cmask = IShort(control);
991     else
992         cmask = ILong(control);
993 
994     /* now if it is zero, ignore and return */
995     if (cmask == 0)
996         return;
997 
998     /* there are bits in the controlling bitmask, figure out which */
999     /* the ctype is a set type, so this code is similar to PrintSET */
1000     fprintf(stdout, "%s%20s:\n", Leader, name);
1001     ModifyIndentLevel(1);
1002     for (p = TD[ctype].ValueList; p != NULL; p = p->Next) {
1003         if ((p->Value & cmask) != 0) {
1004             short m;
1005 
1006             if (littleEndian)
1007                 m = 0;
1008             else
1009                 m = 4 - p->Length;
1010             PrintField(values, m, p->Length, p->Type, p->Name);
1011             values += 4;
1012         }
1013     }
1014     ModifyIndentLevel(-1);
1015 }
1016 
1017 /* ************************************************************ */
1018 /*								*/
1019 /*								*/
1020 /* ************************************************************ */
1021 
1022 /* PolyText8 and PolyText16 take lists of characters with possible
1023    font changes in them. */
1024 
1025 void
PrintTextList8(const unsigned char * buf,int length,const char * name)1026 PrintTextList8(const unsigned char *buf, int length, const char *name)
1027 {
1028     short n;
1029 
1030     fprintf(stdout, "%s%20s:\n", Leader, name);
1031     while (length > 1) {
1032         n = IByte(&buf[0]);
1033         if (n != 255) {
1034             PrintField(buf, 1, 1, INT8, "delta");
1035             PrintTString8(&buf[2], (long) n, "text item 8 string");
1036             buf += n + 2;
1037             length -= n + 2;
1038         }
1039         else {
1040             PrintField(buf, 1, 4, FONT, "font-shift-id");
1041             buf += 4;
1042             length -= 4;
1043         }
1044     }
1045 }
1046 
1047 void
PrintTextList16(const unsigned char * buf,int length,const char * name)1048 PrintTextList16(const unsigned char *buf, int length, const char *name)
1049 {
1050     short n;
1051 
1052     fprintf(stdout, "%s%20s:\n", Leader, name);
1053     while (length > 1) {
1054         n = IByte(&buf[0]);
1055         if (n != 255) {
1056             PrintField(buf, 1, 1, INT8, "delta");
1057             PrintTString16(&buf[2], (long) n, "text item 16 string");
1058             buf += n + 2;
1059             length -= n + 2;
1060         }
1061         else {
1062             PrintField(buf, 1, 4, FONT, "font-shift-id");
1063             buf += 4;
1064             length -= 4;
1065         }
1066     }
1067 }
1068 
1069 /* ************************************************************ */
1070 /*								*/
1071 /*								*/
1072 /* ************************************************************ */
1073 
1074 /* Several extensions have grown property requests mimicing the
1075    core protocol Window properties, and share this code for printing
1076    lists of property values */
1077 int
PrintPropertyValues(const unsigned char * buf,uint32_t type,uint8_t unit,uint32_t num,const char * name)1078 PrintPropertyValues(const unsigned char *buf, uint32_t type /* atom */,
1079                     uint8_t unit, uint32_t num, const char *name)
1080 {
1081     short fieldType = 0;
1082 
1083     switch (type) {
1084     case 4: /* XA_ATOM */
1085         fieldType = ATOM;
1086         break;
1087     case 6: /* XA_CARDINAL */
1088         switch (unit) {
1089         case 4: fieldType = CARD32; break;
1090         case 2: fieldType = CARD16; break;
1091         case 1: fieldType = CARD8;  break;
1092         default:
1093             goto rawbytes;
1094         }
1095         break;
1096     case 19: /* XA_INTEGER */
1097         switch (unit) {
1098         case 4: fieldType = INT32; break;
1099         case 2: fieldType = INT16; break;
1100         case 1: fieldType = INT8;  break;
1101         default:
1102             goto rawbytes;
1103         }
1104         break;
1105     case 31: /* XA_STRING */
1106         return PrintString8(buf, num * unit, name);
1107     case 33: /* XA_WINDOW */
1108         fieldType = WINDOW;
1109         break;
1110     default:
1111         /* Fall through to check for known non-builtin types below */
1112         break;
1113     }
1114 
1115     if (fieldType != 0) {
1116         if (num == 1) {
1117             PrintField(buf, 0, unit, fieldType, name);
1118             return unit;
1119         }
1120         else
1121             return PrintList(buf, num, fieldType, name);
1122     }
1123     else {
1124         const char *typename = FindAtomName(type);
1125 
1126         if (typename) {
1127             if (strcmp(typename, "UTF8_STRING") == 0) {
1128                 if (IsUTF8locale)
1129                     return PrintString8(buf, num * unit, name);
1130                 else
1131                     goto rawbytes;
1132             }
1133         }
1134     }
1135 
1136   rawbytes:
1137     /* When all else fails, print raw bytes */
1138     return PrintBytes(buf, num * unit, name);
1139 }
1140 
1141 /* ************************************************************ */
1142 /*								*/
1143 /*								*/
1144 /* ************************************************************ */
1145 
1146 #define MAXline 78
1147 
1148 void
DumpHexBuffer(const unsigned char * buf,long n)1149 DumpHexBuffer(const unsigned char *buf, long n)
1150 {
1151     long i;
1152     short column;
1153     char h[6]; /* one hex or octal character */
1154 
1155     column = 27 + SizeofLeader();
1156     for (i = 0; i < n; i++) {
1157         /* get the hex representations */
1158         snprintf(h, sizeof(h), "%02x", (0xff & buf[i]));
1159 
1160         /* check if these characters will fit on this line */
1161         if ((column + strlen(h) + 1) > MAXline) {
1162             /* line will be too long -- print it */
1163             fprintf(stdout, "\n");
1164             column = 0;
1165         }
1166         fprintf(stdout, "%s ", h);
1167         column += 3;
1168     }
1169 }
1170 
1171 void
PrintValueRec(uint32_t key,uint32_t cmask,short ctype)1172 PrintValueRec(uint32_t key, uint32_t cmask, short ctype)
1173 {
1174     unsigned char *values;
1175     struct ValueListEntry *p;
1176     ValuePtr value;
1177 
1178     value = GetValueRec(key);
1179     if (!value)
1180         return;
1181     values = (unsigned char *) value->values;
1182 
1183     /* now if it is zero, ignore and return */
1184     if (cmask == 0)
1185         return;
1186 
1187     /* there are bits in the controlling bitmask, figure out which */
1188     /* the ctype is a set type, so this code is similar to PrintSET */
1189     ModifyIndentLevel(1);
1190     for (p = TD[ctype].ValueList; p != NULL; p = p->Next) {
1191         if ((p->Value & cmask) != 0) {
1192             short m;
1193 
1194             if (littleEndian)
1195                 m = 0;
1196             else
1197                 m = 4 - p->Length;
1198             PrintField(values, m, p->Length, p->Type, p->Name);
1199         }
1200         values += 4;
1201     }
1202     ModifyIndentLevel(-1);
1203 }
1204