Fix line wrapping of extensions list in usage message
[platform/upstream/xdpyinfo.git] / xdpyinfo.c
1 /*
2  * $Xorg: xdpyinfo.c,v 1.5 2001/02/09 02:05:41 xorgcvs Exp $
3  * 
4  * xdpyinfo - print information about X display connection
5  *
6  * 
7 Copyright 1988, 1998  The Open Group
8 Copyright 2005 Hitachi, Ltd.
9
10 Permission to use, copy, modify, distribute, and sell this software and its
11 documentation for any purpose is hereby granted without fee, provided that
12 the above copyright notice appear in all copies and that both that
13 copyright notice and this permission notice appear in supporting
14 documentation.
15
16 The above copyright notice and this permission notice shall be included in
17 all copies or substantial portions of the Software.
18
19 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
20 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
21 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
22 OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
23 AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
24 CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
25
26 Except as contained in this notice, the name of The Open Group shall not be
27 used in advertising or otherwise to promote the sale, use or other dealings
28 in this Software without prior written authorization from The Open Group.
29  *
30  * Author:  Jim Fulton, MIT X Consortium
31  */
32
33 /* $XFree86: xc/programs/xdpyinfo/xdpyinfo.c,v 3.29 2003/04/14 20:38:10 herrb Exp $ */
34
35 #ifdef HAVE_CONFIG_H
36 # include "config.h"
37 # if HAVE_X11_EXTENSIONS_MULTIBUF_H
38 #  define MULTIBUFFER
39 # endif
40
41 # if HAVE_X11_EXTENSIONS_XSHM_H
42 #  define MITSHM
43 # endif
44
45 # if HAVE_X11_EXTENSIONS_XKB_H && HAVE_X11_XKBLIB_H
46 #  define XKB
47 # endif
48
49 # if HAVE_X11_EXTENSIONS_XF86VMODE_H && HAVE_X11_EXTENSIONS_XF86VMSTR_H
50 #  define XF86VIDMODE
51 # endif
52
53 # if HAVE_X11_EXTENSIONS_XF86DGA_H && HAVE_X11_EXTENSIONS_XF86DGASTR_H
54 #  define XFreeXDGA
55 # endif
56
57 # if HAVE_X11_EXTENSIONS_XF86MISC_H && HAVE_X11_EXTENSIONS_XF86MSCSTR_H
58 #  define XF86MISC
59 # endif
60
61 # if HAVE_X11_EXTENSIONS_XINPUT_H
62 #  define XINPUT
63 # endif
64
65 # if HAVE_X11_EXTENSIONS_XRENDER_H
66 #  define XRENDER
67 # endif
68
69 # if HAVE_X11_EXTENSIONS_XINERAMA_H
70 #  define PANORAMIX
71 # endif
72
73 # if HAVE_X11_EXTENSIONS_DMXEXT_H
74 #  define DMX
75 # endif
76
77 # if HAVE_X11_EXTENSIONS_PRINT_H
78 #  define INCLUDE_XPRINT_SUPPORT
79 # endif
80
81 #endif
82
83 #include <X11/Xlib.h>
84 #include <X11/Xutil.h>
85 #ifdef MULTIBUFFER
86 #include <X11/extensions/multibuf.h>
87 #endif
88 #include <X11/extensions/XTest.h>
89 #include <X11/extensions/sync.h>
90 #include <X11/Xproto.h>
91 #include <X11/extensions/Xdbe.h>
92 #include <X11/extensions/record.h>
93 #include <X11/extensions/shape.h>
94 #ifdef MITSHM
95 #include <X11/extensions/XShm.h>
96 #endif
97 #ifdef XKB
98 #include <X11/extensions/XKB.h>
99 #include <X11/XKBlib.h>
100 #endif
101 #ifdef XF86VIDMODE
102 #include <X11/extensions/xf86vmode.h>
103 #include <X11/extensions/xf86vmstr.h>
104 #endif
105 #ifdef XFreeXDGA
106 #include <X11/extensions/xf86dga.h>
107 #include <X11/extensions/xf86dgastr.h>
108 #endif
109 #ifdef XF86MISC
110 #include <X11/extensions/xf86misc.h>
111 #include <X11/extensions/xf86mscstr.h>
112 #endif
113 #ifdef XINPUT
114 #include <X11/extensions/XInput.h>
115 #endif
116 #ifdef XRENDER
117 #include <X11/extensions/Xrender.h>
118 #endif
119 #ifdef PANORAMIX
120 #include <X11/extensions/Xinerama.h>
121 #endif
122 #ifdef DMX
123 #include <X11/extensions/dmxext.h>
124 #endif
125 #ifdef INCLUDE_XPRINT_SUPPORT
126 #include <X11/extensions/Print.h>
127 #endif /* INCLUDE_XPRINT_SUPPORT */
128 #include <X11/Xos.h>
129 #include <stdio.h>
130 #include <stdlib.h>
131
132 /* Turn a NULL pointer string into an empty string */
133 #define NULLSTR(x) (((x)!=NULL)?(x):(""))
134
135 char *ProgramName;
136 Bool queryExtensions = False;
137
138 static int print_event_mask(char *buf, int lastcol, int indent, long mask);
139
140 static int StrCmp(const void *a, const  void *b)
141 {
142     return strcmp(*(char **)a, *(char **)b);
143 }
144
145 static void
146 print_extension_info(Display *dpy)
147 {
148     int n = 0;
149     char **extlist = XListExtensions (dpy, &n);
150
151     printf ("number of extensions:    %d\n", n);
152
153     if (extlist) {
154         register int i;
155         int opcode, event, error;
156
157         qsort(extlist, n, sizeof(char *), StrCmp);
158         for (i = 0; i < n; i++) {
159             if (!queryExtensions) {
160                 printf ("    %s\n", extlist[i]);
161                 continue;
162             }
163             XQueryExtension(dpy, extlist[i], &opcode, &event, &error);
164             printf ("    %s  (opcode: %d", extlist[i], opcode);
165             if (event)
166                 printf (", base event: %d", event);
167             if (error)
168                 printf (", base error: %d", error);
169             printf(")\n");
170         }
171         /* do not free, Xlib can depend on contents being unaltered */
172         /* XFreeExtensionList (extlist); */
173     }
174 }
175
176 static void
177 print_display_info(Display *dpy)
178 {
179     char dummybuf[40];
180     char *cp;
181     int minkeycode, maxkeycode;
182     int i, n;
183     long req_size;
184     XPixmapFormatValues *pmf;
185     Window focuswin;
186     int focusrevert;
187
188     printf ("name of display:    %s\n", DisplayString (dpy));
189     printf ("version number:    %d.%d\n",
190             ProtocolVersion (dpy), ProtocolRevision (dpy));
191     printf ("vendor string:    %s\n", ServerVendor (dpy));
192     printf ("vendor release number:    %d\n", VendorRelease (dpy));
193
194     if (strstr(ServerVendor (dpy), "XFree86")) {
195         int vendrel = VendorRelease(dpy);
196
197         printf("XFree86 version: ");
198         if (vendrel < 336) {
199             /*
200              * vendrel was set incorrectly for 3.3.4 and 3.3.5, so handle
201              * those cases here.
202              */
203             printf("%d.%d.%d", vendrel / 100,
204                               (vendrel / 10) % 10,
205                                vendrel       % 10);
206         } else if (vendrel < 3900) {
207             /* 3.3.x versions, other than the exceptions handled above */
208             printf("%d.%d", vendrel / 1000,
209                            (vendrel /  100) % 10);
210             if (((vendrel / 10) % 10) || (vendrel % 10)) {
211                 printf(".%d", (vendrel / 10) % 10);
212                 if (vendrel % 10) {
213                     printf(".%d", vendrel % 10);
214                 }
215             }
216         } else if (vendrel < 40000000) {
217             /* 4.0.x versions */
218             printf("%d.%d", vendrel / 1000,
219                            (vendrel /   10) % 10);
220             if (vendrel % 10) {
221                 printf(".%d", vendrel % 10);
222             }
223         } else {
224             /* post-4.0.x */
225             printf("%d.%d.%d", vendrel / 10000000,
226                               (vendrel /   100000) % 100,
227                               (vendrel /     1000) % 100);
228             if (vendrel % 1000) {
229                 printf(".%d", vendrel % 1000);
230             }
231         }
232         printf("\n");
233     }
234
235     if (strstr(ServerVendor (dpy), "X.Org")) {
236         int vendrel = VendorRelease(dpy);
237
238         printf("X.Org version: ");
239         printf("%d.%d.%d", vendrel / 10000000,
240                (vendrel /   100000) % 100,
241                (vendrel /     1000) % 100);
242         if (vendrel % 1000)
243             printf(".%d", vendrel % 1000);
244         printf("\n");
245     }
246
247     if (strstr(ServerVendor (dpy), "DMX")) {
248         int vendrel = VendorRelease(dpy);
249         int major, minor, year, month, day;
250
251         major    = vendrel / 100000000;
252         vendrel -= major   * 100000000;
253         minor    = vendrel /   1000000;
254         vendrel -= minor   *   1000000;
255         year     = vendrel /     10000;
256         vendrel -= year    *     10000;
257         month    = vendrel /       100;
258         vendrel -= month   *       100;
259         day      = vendrel;
260
261                                 /* Add other epoch tests here */
262         if (major > 0 && minor > 0) year += 2000;
263
264                                 /* Do some sanity tests in case there is
265                                  * another server with the same vendor
266                                  * string.  That server could easily use
267                                  * values < 100000000, which would have
268                                  * the effect of keeping our major
269                                  * number 0. */
270         if (major > 0 && major <= 20
271             && minor >= 0 && minor <= 99
272             && year >= 2000
273             && month >= 1 && month <= 12
274             && day >= 1 && day <= 31)
275             printf("DMX version: %d.%d.%04d%02d%02d\n",
276                    major, minor, year, month, day);
277     }
278
279     req_size = XExtendedMaxRequestSize (dpy);
280     if (!req_size) req_size = XMaxRequestSize (dpy);
281     printf ("maximum request size:  %ld bytes\n", req_size * 4);
282     printf ("motion buffer size:  %ld\n", XDisplayMotionBufferSize (dpy));
283
284     switch (BitmapBitOrder (dpy)) {
285       case LSBFirst:    cp = "LSBFirst"; break;
286       case MSBFirst:    cp = "MSBFirst"; break;
287       default:    
288         sprintf (dummybuf, "unknown order %d", BitmapBitOrder (dpy));
289         cp = dummybuf;
290         break;
291     }
292     printf ("bitmap unit, bit order, padding:    %d, %s, %d\n",
293             BitmapUnit (dpy), cp, BitmapPad (dpy));
294
295     switch (ImageByteOrder (dpy)) {
296       case LSBFirst:    cp = "LSBFirst"; break;
297       case MSBFirst:    cp = "MSBFirst"; break;
298       default:    
299         sprintf (dummybuf, "unknown order %d", ImageByteOrder (dpy));
300         cp = dummybuf;
301         break;
302     }
303     printf ("image byte order:    %s\n", cp);
304
305     pmf = XListPixmapFormats (dpy, &n);
306     printf ("number of supported pixmap formats:    %d\n", n);
307     if (pmf) {
308         printf ("supported pixmap formats:\n");
309         for (i = 0; i < n; i++) {
310             printf ("    depth %d, bits_per_pixel %d, scanline_pad %d\n",
311                     pmf[i].depth, pmf[i].bits_per_pixel, pmf[i].scanline_pad);
312         }
313         XFree ((char *) pmf);
314     }
315
316
317     /*
318      * when we get interfaces to the PixmapFormat stuff, insert code here
319      */
320
321     XDisplayKeycodes (dpy, &minkeycode, &maxkeycode);
322     printf ("keycode range:    minimum %d, maximum %d\n",
323             minkeycode, maxkeycode);
324
325     XGetInputFocus (dpy, &focuswin, &focusrevert);
326     printf ("focus:  ");
327     switch (focuswin) {
328       case PointerRoot:
329         printf ("PointerRoot\n");
330         break;
331       case None:
332         printf ("None\n");
333         break;
334       default:
335         printf("window 0x%lx, revert to ", focuswin);
336         switch (focusrevert) {
337           case RevertToParent:
338             printf ("Parent\n");
339             break;
340           case RevertToNone:
341             printf ("None\n");
342             break;
343           case RevertToPointerRoot:
344             printf ("PointerRoot\n");
345             break;
346           default:                      /* should not happen */
347             printf ("%d\n", focusrevert);
348             break;
349         }
350         break;
351     }
352
353     print_extension_info (dpy);
354
355     printf ("default screen number:    %d\n", DefaultScreen (dpy));
356     printf ("number of screens:    %d\n", ScreenCount (dpy));
357 }
358
359 static void
360 print_visual_info(XVisualInfo *vip)
361 {
362     char errorbuf[40];                  /* for sprintfing into */
363     char *class = NULL;                 /* for printing */
364
365     switch (vip->class) {
366       case StaticGray:    class = "StaticGray"; break;
367       case GrayScale:    class = "GrayScale"; break;
368       case StaticColor:    class = "StaticColor"; break;
369       case PseudoColor:    class = "PseudoColor"; break;
370       case TrueColor:    class = "TrueColor"; break;
371       case DirectColor:    class = "DirectColor"; break;
372       default:    
373         sprintf (errorbuf, "unknown class %d", vip->class);
374         class = errorbuf;
375         break;
376     }
377
378     printf ("  visual:\n");
379     printf ("    visual id:    0x%lx\n", vip->visualid);
380     printf ("    class:    %s\n", class);
381     printf ("    depth:    %d plane%s\n", vip->depth, 
382             vip->depth == 1 ? "" : "s");
383     if (vip->class == TrueColor || vip->class == DirectColor)
384         printf ("    available colormap entries:    %d per subfield\n",
385                 vip->colormap_size);
386     else
387         printf ("    available colormap entries:    %d\n",
388                 vip->colormap_size);
389     printf ("    red, green, blue masks:    0x%lx, 0x%lx, 0x%lx\n",
390             vip->red_mask, vip->green_mask, vip->blue_mask);
391     printf ("    significant bits in color specification:    %d bits\n",
392             vip->bits_per_rgb);
393 }
394
395 /* xc/programs/twm/twm.c has a copy of |hasExtension()|, please
396  * keep both versions in sync... */
397 static
398 Bool hasExtension(Display *dpy, char *extname)
399 {
400   int    num_extensions,
401          i;
402   char **extensions;
403   extensions = XListExtensions(dpy, &num_extensions);
404   for (i = 0; i < num_extensions &&
405          (strcmp(extensions[i], extname) != 0); i++);
406   XFreeExtensionList(extensions);
407   return i != num_extensions;
408 }
409
410 #ifdef INCLUDE_XPRINT_SUPPORT
411 /* xc/programs/twm/twm.c has a copy of |IsPrintScreen()|, please
412  * keep both versions in sync... */
413 static
414 Bool IsPrintScreen(Screen *s)
415 {
416     Display *dpy = XDisplayOfScreen(s);
417     int      i;
418
419     /* Check whether this is a screen of a print DDX */
420     if (hasExtension(dpy, XP_PRINTNAME)) {
421         Screen **pscreens;
422         int      pscrcount;
423
424         pscreens = XpQueryScreens(dpy, &pscrcount);
425         for( i = 0 ; (i < pscrcount) && pscreens ; i++ ) {
426             if (s == pscreens[i]) {
427                 return True;
428             }
429         }
430         XFree(pscreens);                      
431     }
432     return False;
433 }
434 #endif /* INCLUDE_XPRINT_SUPPORT */
435
436 static void
437 print_screen_info(Display *dpy, int scr)
438 {
439     Screen *s = ScreenOfDisplay (dpy, scr);  /* opaque structure */
440     XVisualInfo viproto;                /* fill in for getting info */
441     XVisualInfo *vip;                   /* returned info */
442     int nvi;                            /* number of elements returned */
443     int i;                              /* temp variable: iterator */
444     char eventbuf[80];                  /* want 79 chars per line + nul */
445     static char *yes = "YES", *no = "NO", *when = "WHEN MAPPED";
446     double xres, yres;
447     int ndepths = 0, *depths = NULL;
448     unsigned int width, height;
449     Bool isPrintScreen = False; /* Initialise this if |INCLUDE_XPRINT_SUPPORT| is not set */
450
451     /*
452      * there are 2.54 centimeters to an inch; so there are 25.4 millimeters.
453      *
454      *     dpi = N pixels / (M millimeters / (25.4 millimeters / 1 inch))
455      *         = N pixels / (M inch / 25.4)
456      *         = N * 25.4 pixels / M inch
457      */
458
459     xres = ((((double) DisplayWidth(dpy,scr)) * 25.4) / 
460             ((double) DisplayWidthMM(dpy,scr)));
461     yres = ((((double) DisplayHeight(dpy,scr)) * 25.4) / 
462             ((double) DisplayHeightMM(dpy,scr)));
463
464     printf ("\n");
465     printf ("screen #%d:\n", scr);
466
467 #ifdef INCLUDE_XPRINT_SUPPORT
468     /* Check whether this is a screen of a print DDX */
469     isPrintScreen = IsPrintScreen(s);
470     printf ("  print screen:    %s\n", isPrintScreen?"yes":"no");
471 #endif /* INCLUDE_XPRINT_SUPPORT */
472
473     if (isPrintScreen) {
474         /* Print resolution is set on a per-printer basis (per-document
475          * or per-page), the screen itself has no "default" resolution */
476         printf ("  maximum dimensions:    %dx%d pixels\n",
477                 XDisplayWidth (dpy, scr),  XDisplayHeight (dpy, scr));
478     }
479     else
480     {
481         printf ("  dimensions:    %dx%d pixels (%dx%d millimeters)\n",
482                 XDisplayWidth (dpy, scr),  XDisplayHeight (dpy, scr),
483                 XDisplayWidthMM(dpy, scr), XDisplayHeightMM (dpy, scr));
484         printf ("  resolution:    %dx%d dots per inch\n", 
485                 (int) (xres + 0.5), (int) (yres + 0.5));
486     }
487     depths = XListDepths (dpy, scr, &ndepths);
488     if (!depths) ndepths = 0;
489     printf ("  depths (%d):    ", ndepths);
490     for (i = 0; i < ndepths; i++) {
491         printf ("%d", depths[i]);
492         if (i < ndepths - 1) { 
493             putchar (',');
494             putchar (' ');
495         }
496     }
497     putchar ('\n');
498     if (depths) XFree ((char *) depths);
499     printf ("  root window id:    0x%lx\n", RootWindow (dpy, scr));
500     printf ("  depth of root window:    %d plane%s\n",
501             DisplayPlanes (dpy, scr),
502             DisplayPlanes (dpy, scr) == 1 ? "" : "s");
503     printf ("  number of colormaps:    minimum %d, maximum %d\n",
504             MinCmapsOfScreen(s), MaxCmapsOfScreen(s));
505     printf ("  default colormap:    0x%lx\n", DefaultColormap (dpy, scr));
506     printf ("  default number of colormap cells:    %d\n",
507             DisplayCells (dpy, scr));
508     printf ("  preallocated pixels:    black %ld, white %ld\n",
509             BlackPixel (dpy, scr), WhitePixel (dpy, scr));
510     printf ("  options:    backing-store %s, save-unders %s\n",
511             (DoesBackingStore (s) == NotUseful) ? no :
512             ((DoesBackingStore (s) == Always) ? yes : when),
513             DoesSaveUnders (s) ? yes : no);
514     XQueryBestSize (dpy, CursorShape, RootWindow (dpy, scr), 65535, 65535,
515                     &width, &height);
516     if (width == 65535 && height == 65535)
517         printf ("  largest cursor:    unlimited\n");
518     else
519         printf ("  largest cursor:    %dx%d\n", width, height);
520     printf ("  current input event mask:    0x%lx\n", EventMaskOfScreen (s));
521     (void) print_event_mask (eventbuf, 79, 4, EventMaskOfScreen (s));
522
523     nvi = 0;
524     viproto.screen = scr;
525     vip = XGetVisualInfo (dpy, VisualScreenMask, &viproto, &nvi);
526     printf ("  number of visuals:    %d\n", nvi);
527     printf ("  default visual id:  0x%lx\n", 
528             XVisualIDFromVisual (DefaultVisual (dpy, scr)));
529     for (i = 0; i < nvi; i++) {
530         print_visual_info (vip+i);
531     }
532     if (vip) XFree ((char *) vip);
533 }
534
535 /*
536  * The following routine prints out an event mask, wrapping events at nice
537  * boundaries.
538  */
539
540 #define MASK_NAME_WIDTH 25
541
542 static struct _event_table {
543     char *name;
544     long value;
545 } event_table[] = {
546     { "KeyPressMask             ", KeyPressMask },
547     { "KeyReleaseMask           ", KeyReleaseMask },
548     { "ButtonPressMask          ", ButtonPressMask },
549     { "ButtonReleaseMask        ", ButtonReleaseMask },
550     { "EnterWindowMask          ", EnterWindowMask },
551     { "LeaveWindowMask          ", LeaveWindowMask },
552     { "PointerMotionMask        ", PointerMotionMask },
553     { "PointerMotionHintMask    ", PointerMotionHintMask },
554     { "Button1MotionMask        ", Button1MotionMask },
555     { "Button2MotionMask        ", Button2MotionMask },
556     { "Button3MotionMask        ", Button3MotionMask },
557     { "Button4MotionMask        ", Button4MotionMask },
558     { "Button5MotionMask        ", Button5MotionMask },
559     { "ButtonMotionMask         ", ButtonMotionMask },
560     { "KeymapStateMask          ", KeymapStateMask },
561     { "ExposureMask             ", ExposureMask },
562     { "VisibilityChangeMask     ", VisibilityChangeMask },
563     { "StructureNotifyMask      ", StructureNotifyMask },
564     { "ResizeRedirectMask       ", ResizeRedirectMask },
565     { "SubstructureNotifyMask   ", SubstructureNotifyMask },
566     { "SubstructureRedirectMask ", SubstructureRedirectMask },
567     { "FocusChangeMask          ", FocusChangeMask },
568     { "PropertyChangeMask       ", PropertyChangeMask },
569     { "ColormapChangeMask       ", ColormapChangeMask },
570     { "OwnerGrabButtonMask      ", OwnerGrabButtonMask },
571     { NULL, 0 }};
572
573 static int                      
574 print_event_mask(char *buf,     /* string to write into */
575                  int lastcol,   /* strlen(buf)+1 */
576                  int indent,    /* amount by which to indent */
577                  long mask)     /* event mask */
578 {
579     struct _event_table *etp;
580     int len;
581     int bitsfound = 0;
582
583     buf[0] = buf[lastcol] = '\0';       /* just in case */
584
585 #define INDENT() { register int i; len = indent; \
586                    for (i = 0; i < indent; i++) buf[i] = ' '; }
587
588     INDENT ();
589
590     for (etp = event_table; etp->name; etp++) {
591         if (mask & etp->value) {
592             if (len + MASK_NAME_WIDTH > lastcol) {
593                 puts (buf);
594                 INDENT ();
595             }
596             strcpy (buf+len, etp->name);
597             len += MASK_NAME_WIDTH;
598             bitsfound++;
599         }
600     }
601
602     if (bitsfound) puts (buf);
603
604 #undef INDENT
605
606     return (bitsfound);
607 }
608
609 static void
610 print_standard_extension_info(Display *dpy, char *extname, 
611                               int majorrev, int minorrev)
612 {
613     int opcode, event, error;
614
615     printf("%s version %d.%d ", extname, majorrev, minorrev);
616
617     XQueryExtension(dpy, extname, &opcode, &event, &error);
618     printf ("opcode: %d", opcode);
619     if (event)
620         printf (", base event: %d", event);
621     if (error)
622         printf (", base error: %d", error);
623     printf("\n");
624 }
625
626 #ifdef MULTIBUFFER
627 static int
628 print_multibuf_info(Display *dpy, char *extname)
629 {
630     int i, j;                   /* temp variable: iterator */
631     int nmono, nstereo;         /* count */
632     XmbufBufferInfo *mono_info = NULL, *stereo_info = NULL; /* arrays */
633     static char *fmt = 
634         "    visual id, max buffers, depth:    0x%lx, %d, %d\n";
635     int scr = 0;
636     int majorrev, minorrev;
637
638     if (!XmbufGetVersion(dpy, &majorrev, &minorrev))
639         return 0;
640
641     print_standard_extension_info(dpy, extname, majorrev, minorrev);
642
643     for (i = 0; i < ScreenCount (dpy); i++)
644     {
645         if (!XmbufGetScreenInfo (dpy, RootWindow(dpy, scr), &nmono, &mono_info,
646                                  &nstereo, &stereo_info)) {
647             fprintf (stderr,
648                      "%s:  unable to get multibuffer info for screen %d\n",
649                      ProgramName, scr);
650         } else {
651             printf ("  screen %d number of mono multibuffer types:    %d\n", i, nmono);
652             for (j = 0; j < nmono; j++) {
653                 printf (fmt, mono_info[j].visualid, mono_info[j].max_buffers,
654                         mono_info[j].depth);
655             }
656             printf ("  number of stereo multibuffer types:    %d\n", nstereo);
657             for (j = 0; j < nstereo; j++) {
658                 printf (fmt, stereo_info[j].visualid,
659                         stereo_info[j].max_buffers, stereo_info[j].depth);
660             }
661             if (mono_info) XFree ((char *) mono_info);
662             if (stereo_info) XFree ((char *) stereo_info);
663         }
664     }
665     return 1;
666 } /* end print_multibuf_info */
667 #endif
668
669 static int
670 print_xtest_info(Display *dpy, char *extname)
671 {
672     int majorrev, minorrev, foo;
673
674     if (!XTestQueryExtension(dpy, &foo, &foo, &majorrev, &minorrev))
675         return 0;
676     print_standard_extension_info(dpy, extname, majorrev, minorrev);
677     return 1;
678 }
679
680 static int
681 print_sync_info(Display *dpy, char *extname)
682 {
683     int majorrev, minorrev;
684     XSyncSystemCounter *syscounters;
685     int ncounters, i;
686
687     if (!XSyncInitialize(dpy, &majorrev, &minorrev))
688         return 0;
689     print_standard_extension_info(dpy, extname, majorrev, minorrev);
690
691     syscounters = XSyncListSystemCounters(dpy, &ncounters);
692     printf("  system counters: %d\n", ncounters);
693     for (i = 0; i < ncounters; i++)
694     {
695         printf("    %s  id: 0x%08x  resolution_lo: %d  resolution_hi: %d\n",
696                syscounters[i].name, (unsigned int)syscounters[i].counter,
697                XSyncValueLow32(syscounters[i].resolution),
698                XSyncValueHigh32(syscounters[i].resolution));
699     }
700     XSyncFreeSystemCounterList(syscounters);
701     return 1;
702 }
703
704 static int
705 print_shape_info(Display *dpy, char *extname)
706 {
707     int majorrev, minorrev;
708
709     if (!XShapeQueryVersion(dpy, &majorrev, &minorrev))
710         return 0;
711     print_standard_extension_info(dpy, extname, majorrev, minorrev);
712     return 1;
713 }
714
715 #ifdef XFreeXDGA
716 static int
717 print_dga_info(Display *dpy, char *extname)
718 {
719     int majorrev, minorrev, width, bank, ram, offset, flags;
720
721     if (!XF86DGAQueryVersion(dpy, &majorrev, &minorrev))
722         return 0;
723     print_standard_extension_info(dpy, extname, majorrev, minorrev);
724
725     if (!XF86DGAQueryDirectVideo(dpy, DefaultScreen(dpy), &flags) 
726         || ! (flags & XF86DGADirectPresent) )
727     {
728         printf("  DGA not available on screen %d.\n", DefaultScreen(dpy));
729         return 1;
730     }
731
732     if (!XF86DGAGetVideoLL(dpy, DefaultScreen(dpy), &offset,
733                             &width, &bank, &ram))
734         return 0;
735     printf("  Base address = 0x%X, Width = %d, Bank size = %d,"
736            " RAM size = %dk\n", offset, width, bank, ram);
737
738     return 1;
739 }
740 #endif
741
742 #ifdef XF86VIDMODE
743 #define V_PHSYNC        0x001 
744 #define V_NHSYNC        0x002
745 #define V_PVSYNC        0x004
746 #define V_NVSYNC        0x008
747 #define V_INTERLACE     0x010 
748 #define V_DBLSCAN       0x020
749 #define V_CSYNC         0x040
750 #define V_PCSYNC        0x080
751 #define V_NCSYNC        0x100
752
753 static int
754 print_XF86VidMode_info(Display *dpy, char *extname)
755 {
756     int majorrev, minorrev, modecount, dotclock, i;
757     XF86VidModeMonitor monitor;
758     XF86VidModeModeLine modeline;
759     XF86VidModeModeInfo **modelines;
760
761     if (!XF86VidModeQueryVersion(dpy, &majorrev, &minorrev))
762         return 0;
763     print_standard_extension_info(dpy, extname, majorrev, minorrev);
764
765     if (!XF86VidModeGetMonitor(dpy, DefaultScreen(dpy), &monitor))
766         return 0;
767     printf("  Monitor Information:\n");
768     printf("    Vendor: %s, Model: %s\n", monitor.vendor, monitor.model);
769     printf("    Num hsync: %d, Num vsync: %d\n", monitor.nhsync, monitor.nvsync);
770     for (i = 0; i < monitor.nhsync; i++) {
771         printf("    hsync range %d: %6.2f - %6.2f\n", i, monitor.hsync[i].lo,
772                monitor.hsync[i].hi);
773     }
774     for (i = 0; i < monitor.nvsync; i++) {
775         printf("    vsync range %d: %6.2f - %6.2f\n", i, monitor.vsync[i].lo,
776                monitor.vsync[i].hi);
777     }
778
779     if ((majorrev > 0) || (majorrev == 0 && minorrev > 5)) {
780       if (!XF86VidModeGetAllModeLines(dpy, DefaultScreen(dpy), &modecount,
781                                       &modelines))
782         return 0;
783       printf("  Available Video Mode Settings:\n");
784       printf("     Clock   Hdsp Hbeg Hend Httl   Vdsp Vbeg Vend Vttl  Flags\n");
785       for (i = 0; i < modecount; i++) {
786         printf("    %6.2f   %4d %4d %4d %4d   %4d %4d %4d %4d ",
787             (float)modelines[i]->dotclock/1000.0,
788             modelines[i]->hdisplay, modelines[i]->hsyncstart,
789             modelines[i]->hsyncend, modelines[i]->htotal,
790             modelines[i]->vdisplay, modelines[i]->vsyncstart,
791             modelines[i]->vsyncend, modelines[i]->vtotal);
792         if (modelines[i]->flags & V_PHSYNC)    printf(" +hsync");
793         if (modelines[i]->flags & V_NHSYNC)    printf(" -hsync");
794         if (modelines[i]->flags & V_PVSYNC)    printf(" +vsync");
795         if (modelines[i]->flags & V_NVSYNC)    printf(" -vsync");
796         if (modelines[i]->flags & V_INTERLACE) printf(" interlace");
797         if (modelines[i]->flags & V_CSYNC)     printf(" composite");
798         if (modelines[i]->flags & V_PCSYNC)    printf(" +csync");
799         if (modelines[i]->flags & V_PCSYNC)    printf(" -csync");
800         if (modelines[i]->flags & V_DBLSCAN)   printf(" doublescan");
801         printf("\n");
802       }
803
804       if (!XF86VidModeGetModeLine(dpy, DefaultScreen(dpy),
805                                   &dotclock, &modeline))
806         return 0;
807       printf("  Current Video Mode Setting:\n");
808       printf("    %6.2f   %4d %4d %4d %4d   %4d %4d %4d %4d ",
809              (float)dotclock/1000.0,
810              modeline.hdisplay, modeline.hsyncstart,
811              modeline.hsyncend, modeline.htotal,
812              modeline.vdisplay, modeline.vsyncstart,
813              modeline.vsyncend, modeline.vtotal);
814       if (modeline.flags & V_PHSYNC)    printf(" +hsync");
815       if (modeline.flags & V_NHSYNC)    printf(" -hsync");
816       if (modeline.flags & V_PVSYNC)    printf(" +vsync");
817       if (modeline.flags & V_NVSYNC)    printf(" -vsync");
818       if (modeline.flags & V_INTERLACE) printf(" interlace");
819       if (modeline.flags & V_CSYNC)     printf(" composite");
820       if (modeline.flags & V_PCSYNC)    printf(" +csync");
821       if (modeline.flags & V_PCSYNC)    printf(" -csync");
822       if (modeline.flags & V_DBLSCAN)   printf(" doublescan");
823       printf("\n");
824     }
825
826     return 1;
827 }
828 #endif
829
830 #ifdef XF86MISC
831
832 char *kbdtable[] = { "Unknown", "84-key", "101-key", "Other", "Xqueue" };
833 char *msetable[] = { "None", "Microsoft", "MouseSystems", "MMSeries",
834                      "Logitech", "BusMouse", "Mouseman", "PS/2", "MMHitTab",
835                      "GlidePoint", "IntelliMouse", "ThinkingMouse",
836                      "IMPS/2", "ThinkingMousePS/2", "MouseManPlusPS/2",
837                      "GlidePointPS/2", "NetMousePS/2", "NetScrollPS/2",
838                      "SysMouse", "Auto" };
839 char *flgtable[] = { "None", "ClearDTR", "ClearRTS",
840                      "ClearDTR and ClearRTS" };
841
842 static int
843 print_XF86Misc_info(Display *dpy, char *extname)
844 {
845     int majorrev, minorrev;
846     XF86MiscMouseSettings mouseinfo;
847     XF86MiscKbdSettings kbdinfo;
848
849     if (!XF86MiscQueryVersion(dpy, &majorrev, &minorrev))
850         return 0;
851     print_standard_extension_info(dpy, extname, majorrev, minorrev);
852
853     if ((majorrev > 0) || (majorrev == 0 && minorrev > 0)) {
854       if (!XF86MiscGetKbdSettings(dpy, &kbdinfo))
855         return 0;
856       printf("  Keyboard Settings-    Type: %s, Rate: %d, Delay: %d, ServerNumLock: %s\n",
857         kbdtable[kbdinfo.type], kbdinfo.rate, kbdinfo.delay,
858         (kbdinfo.servnumlock? "yes": "no"));
859
860       if (!XF86MiscGetMouseSettings(dpy, &mouseinfo))
861         return 0;
862       printf("  Mouse Settings-       Device: %s, Type: ",
863         strlen(mouseinfo.device) == 0 ? "None": mouseinfo.device);
864       if (mouseinfo.type == MTYPE_XQUEUE)
865         printf("Xqueue\n");
866       else if (mouseinfo.type == MTYPE_OSMOUSE)
867         printf("OSMouse\n");
868       else if (mouseinfo.type <= MTYPE_AUTOMOUSE)
869         printf("%s\n", msetable[mouseinfo.type+1]);
870       else
871         printf("Unknown\n");
872       printf("                        BaudRate: %d, SampleRate: %d, Resolution: %d\n",
873         mouseinfo.baudrate, mouseinfo.samplerate, mouseinfo.resolution);
874       printf("                        Emulate3Buttons: %s, Emulate3Timeout: %d ms\n",
875         mouseinfo.emulate3buttons? "yes": "no", mouseinfo.emulate3timeout);
876       printf("                        ChordMiddle: %s, Flags: %s\n",
877         mouseinfo.chordmiddle? "yes": "no",
878         flgtable[(mouseinfo.flags & MF_CLEAR_DTR? 1: 0)
879                 +(mouseinfo.flags & MF_CLEAR_RTS? 1: 0)] );
880       printf("                        Buttons: %d\n", mouseinfo.buttons);
881     }
882
883     return 1;
884 }
885 #endif
886
887 #ifdef MITSHM
888 static int
889 print_mitshm_info(Display *dpy, char *extname)
890 {
891     int majorrev, minorrev;
892     Bool sharedPixmaps;
893
894     if (!XShmQueryVersion(dpy, &majorrev, &minorrev, &sharedPixmaps))
895         return 0;
896     print_standard_extension_info(dpy, extname, majorrev, minorrev);
897     printf("  shared pixmaps: ");
898     if (sharedPixmaps)
899     {
900         int format = XShmPixmapFormat(dpy);
901         printf("yes, format: %d\n", format);
902     }
903     else
904     {
905         printf("no\n");
906     }
907     return 1;
908 }
909 #endif /* MITSHM */
910
911 #ifdef XKB
912 static int
913 print_xkb_info(Display *dpy, char *extname)
914 {
915     int opcode, eventbase, errorbase, majorrev, minorrev;
916
917     if (!XkbQueryExtension(dpy, &opcode, &eventbase, &errorbase,
918                            &majorrev, &minorrev)) {
919         return 0;
920     }
921     printf("%s version %d.%d ", extname, majorrev, minorrev);
922
923     printf ("opcode: %d", opcode);
924     if (eventbase)
925         printf (", base event: %d", eventbase);
926     if (errorbase)
927         printf (", base error: %d", errorbase);
928     printf("\n");
929
930     return 1;
931 }
932 #endif
933
934 static int
935 print_dbe_info(Display *dpy, char *extname)
936 {
937     int majorrev, minorrev;
938     XdbeScreenVisualInfo *svi;
939     int numscreens = 0;
940     int iscrn, ivis;
941
942     if (!XdbeQueryExtension(dpy, &majorrev, &minorrev))
943         return 0;
944
945     print_standard_extension_info(dpy, extname, majorrev, minorrev);
946     svi = XdbeGetVisualInfo(dpy, (Drawable *)NULL, &numscreens);
947     for (iscrn = 0; iscrn < numscreens; iscrn++)
948     {
949         printf("  Double-buffered visuals on screen %d\n", iscrn);
950         for (ivis = 0; ivis < svi[iscrn].count; ivis++)
951         {
952             printf("    visual id 0x%lx  depth %d  perflevel %d\n",
953                    svi[iscrn].visinfo[ivis].visual,
954                    svi[iscrn].visinfo[ivis].depth,
955                    svi[iscrn].visinfo[ivis].perflevel);
956         }
957     }
958     XdbeFreeVisualInfo(svi);
959     return 1;
960 }
961
962 static int
963 print_record_info(Display *dpy, char *extname)
964 {
965     int majorrev, minorrev;
966
967     if (!XRecordQueryVersion(dpy, &majorrev, &minorrev))
968         return 0;
969     print_standard_extension_info(dpy, extname, majorrev, minorrev);
970     return 1;
971 }
972
973 #ifdef XINPUT
974 static int
975 print_xinput_info(Display *dpy, char *extname)
976 {
977   int           loop, num_extensions, num_devices;
978   char          **extensions;
979   XDeviceInfo   *devices;
980   XExtensionVersion *ext;
981
982   ext = XGetExtensionVersion(dpy, extname);
983   
984   if (!ext || (ext == (XExtensionVersion*) NoSuchExtension))
985       return 0;
986
987   print_standard_extension_info(dpy, extname, ext->major_version,
988                                 ext->minor_version);
989
990   extensions = XListExtensions(dpy, &num_extensions);
991   for (loop = 0; loop < num_extensions &&
992          (strcmp(extensions[loop], extname) != 0); loop++);
993   XFreeExtensionList(extensions);
994   if (loop != num_extensions) {
995       printf("  Extended devices :\n");
996       devices = XListInputDevices(dpy, &num_devices);
997       for(loop=0; loop<num_devices; loop++) {
998           printf("      \"%s\"  [", devices[loop].name ? devices[loop].name : "<noname>");
999           switch(devices[loop].use) {
1000           case IsXPointer:
1001               printf("XPointer]\n");
1002               break;
1003           case IsXKeyboard:
1004               printf("XKeyboard]\n");
1005               break;
1006           case IsXExtensionDevice:
1007               printf("XExtensionDevice]\n");
1008               break;
1009           default:
1010               printf("invalid value]\n");
1011               break;
1012           }
1013         }
1014       XFreeDeviceList(devices);
1015       return 1;
1016     }
1017   else
1018       return 0;
1019 }
1020 #endif
1021
1022 #ifdef XRENDER
1023 static int
1024 print_xrender_info(Display *dpy, char *extname)
1025 {
1026   int               loop, num_extensions;
1027   char              **extensions;
1028   XRenderPictFormat *pictform;
1029   int               count;
1030   int               major, minor;
1031   int               i, j;
1032   XVisualInfo       viproto;            /* fill in for getting info */
1033   XVisualInfo       *vip;               /* retured info */
1034   int               nvi;                /* number of elements returned */
1035   int               ndepths = 0, *depths = NULL;
1036 #if RENDER_MAJOR > 0 || RENDER_MINOR >= 6
1037   XFilters          *filters;
1038   int               f;
1039 #endif
1040
1041   if (!XRenderQueryVersion (dpy, &major, &minor))
1042     return 0;
1043   
1044   print_standard_extension_info(dpy, extname, major, minor);
1045
1046   extensions = XListExtensions(dpy, &num_extensions);
1047   for (loop = 0; loop < num_extensions &&
1048          (strcmp(extensions[loop], extname) != 0); loop++);
1049   XFreeExtensionList(extensions);
1050   if (loop != num_extensions) {
1051     printf ("  Render formats :\n");
1052     for (count = 0; (pictform = XRenderFindFormat (dpy, 0, NULL, count)); count++)
1053     {
1054       printf  ("  pict format:\n");
1055       printf  ("\tformat id:    0x%lx\n", pictform->id);
1056       printf  ("\ttype:         %s\n",
1057              pictform->type == PictTypeIndexed ? "Indexed" : "Direct");
1058       printf  ("\tdepth:        %d\n", pictform->depth);
1059       if (pictform->type == PictTypeDirect) {
1060         printf("\talpha:        %2d mask 0x%x\n", pictform->direct.alpha, pictform->direct.alphaMask);
1061         printf("\tred:          %2d mask 0x%x\n", pictform->direct.red, pictform->direct.redMask);
1062         printf("\tgreen:        %2d mask 0x%x\n", pictform->direct.green, pictform->direct.greenMask);
1063         printf("\tblue:         %2d mask 0x%x\n", pictform->direct.blue, pictform->direct.blueMask);
1064       }
1065       else
1066         printf("\tcolormap      0x%lx\n", pictform->colormap);
1067     }
1068     printf ("  Screen formats :\n");
1069     for (i = 0; i < ScreenCount (dpy); i++) {
1070       nvi = 0;
1071       viproto.screen = i;
1072       vip = XGetVisualInfo (dpy, VisualScreenMask, &viproto, &nvi);
1073       printf ("    Screen %d", i);
1074 #if RENDER_MAJOR > 0 || RENDER_MINOR >= 6
1075       switch (XRenderQuerySubpixelOrder (dpy, i)) {
1076       case SubPixelUnknown: printf (" (sub-pixel order Unknown)"); break;
1077       case SubPixelHorizontalRGB: printf (" (sub-pixel order Horizontal RGB)"); break;
1078       case SubPixelHorizontalBGR: printf (" (sub-pixel order Horizontal BGR)"); break;
1079       case SubPixelVerticalRGB: printf (" (sub-pixel order Vertical RGB)"); break;
1080       case SubPixelVerticalBGR: printf (" (sub-pixel order Vertical BGR)"); break;
1081       case SubPixelNone: printf (" (sub-pixel order None)"); break;
1082       }
1083       printf ("\n");
1084       filters = XRenderQueryFilters (dpy, RootWindow (dpy, i));
1085       if (filters)
1086       {
1087         printf ("      filters: ");
1088         for (f = 0; f < filters->nfilter; f++)
1089         {
1090           printf ("%s", filters->filter[f]);
1091           if (f < filters->nalias && filters->alias[f] != FilterAliasNone)
1092             printf ("(%s)", filters->filter[filters->alias[f]]);
1093           if (f < filters->nfilter - 1)
1094             printf (", ");
1095         }
1096         XFree (filters);
1097       }
1098 #endif
1099       printf ("\n");
1100       for (j = 0; j < nvi; j++)
1101       {
1102         printf  ("      visual format:\n");
1103         printf  ("        visual id:      0x%lx\n", vip[j].visualid);
1104         pictform = XRenderFindVisualFormat (dpy, vip[j].visual);
1105         if (pictform)
1106           printf("        pict format id: 0x%lx\n", pictform->id);
1107         else
1108           printf("        pict format id: None\n");
1109       }
1110       if (vip) XFree ((char *) vip);
1111       depths = XListDepths (dpy, i, &ndepths);
1112       if (!depths) ndepths = 0;
1113       for (j = 0; j < ndepths; j++)
1114       {
1115         XRenderPictFormat templ;
1116
1117         templ.depth = depths[j];
1118         printf  ("     depth formats:\n");
1119         printf  ("       depth           %d\n", depths[j]);
1120         for (count = 0; (pictform = XRenderFindFormat (dpy, PictFormatDepth, &templ, count)); count++)
1121           printf("       pict format id: 0x%lx\n", pictform->id);
1122       }
1123     }
1124     return 1;
1125   }
1126   else
1127     return 0;
1128 }
1129 #endif /* XRENDER */
1130
1131
1132 #ifdef PANORAMIX
1133
1134 static int
1135 print_xinerama_info(Display *dpy, char *extname)
1136 {
1137   int              majorrev, minorrev;
1138
1139   if (!XineramaQueryVersion (dpy, &majorrev, &minorrev))
1140     return 0;
1141   
1142   print_standard_extension_info(dpy, extname, majorrev, minorrev);
1143
1144   if (!XineramaIsActive(dpy)) {
1145     printf("  Xinerama is inactive.\n");
1146   } else {
1147     int i, count = 0; 
1148     XineramaScreenInfo *xineramaScreens = XineramaQueryScreens(dpy, &count);
1149     
1150     for (i = 0; i < count; i++) {
1151       XineramaScreenInfo *xs = &xineramaScreens[i];
1152       printf("  head #%d: %dx%d @ %d,%d\n", xs->screen_number, 
1153              xs->width, xs->height, xs->x_org, xs->y_org);
1154     }
1155     
1156     XFree(xineramaScreens);
1157   }
1158   
1159   return 1;
1160 }
1161
1162 #endif /* PANORAMIX */
1163
1164 #ifdef DMX
1165 static const char *core(DMXInputAttributes *iinfo)
1166 {
1167     if (iinfo->isCore)         return "core";
1168     else if (iinfo->sendsCore) return "extension (sends core)";
1169     else                       return "extension";
1170 }
1171
1172 static int print_dmx_info(Display *dpy, char *extname)
1173 {
1174     int                  event_base, error_base;
1175     int                  major_version, minor_version, patch_version;
1176     DMXScreenAttributes  sinfo;
1177     DMXInputAttributes   iinfo;
1178     int                  count;
1179     int                  i;
1180
1181     if (!DMXQueryExtension(dpy, &event_base, &error_base)
1182         || !DMXQueryVersion(dpy, &major_version, &minor_version,
1183                             &patch_version)) return 0;
1184     print_standard_extension_info(dpy, extname, major_version, minor_version);
1185     printf("  Version stamp: %d\n", patch_version);
1186
1187     if (!DMXGetScreenCount(dpy, &count)) return 1;
1188     printf("  Screen count: %d\n", count);
1189     for (i = 0; i < count; i++) {
1190         if (DMXGetScreenAttributes(dpy, i, &sinfo)) {
1191             printf("    %2d %s %ux%u+%d+%d %d @%dx%d\n",
1192                    i, sinfo.displayName,
1193                    sinfo.screenWindowWidth, sinfo.screenWindowHeight,
1194                    sinfo.screenWindowXoffset, sinfo.screenWindowYoffset,
1195                    sinfo.logicalScreen,
1196                    sinfo.rootWindowXorigin, sinfo.rootWindowYorigin);
1197         }
1198     }
1199
1200     if (major_version != 1
1201         || minor_version < 1
1202         || !DMXGetInputCount(dpy, &count))
1203         return 1;
1204
1205     printf("  Input count = %d\n", count);
1206     for (i = 0; i < count; i++) {
1207 #ifdef XINPUT
1208         Display *backend;
1209         char    *backendname = NULL;
1210 #endif
1211         if (DMXGetInputAttributes(dpy, i, &iinfo)) {
1212             switch (iinfo.inputType) {
1213             case DMXLocalInputType:
1214                 printf("    %2d local %s", i, core(&iinfo));
1215                 break;
1216             case DMXConsoleInputType:
1217                 printf("    %2d console %s %s", i, core(&iinfo),
1218                        iinfo.name);
1219                 break;
1220             case DMXBackendInputType:
1221 #ifdef XINPUT
1222                 if (iinfo.physicalId >= 0) {
1223                     if ((backend = XOpenDisplay(iinfo.name))) {
1224                         XExtensionVersion *ext
1225                             = XGetExtensionVersion(backend, INAME);
1226                         if (ext
1227                             && ext != (XExtensionVersion *)NoSuchExtension) {
1228                             
1229                             int         count, i;
1230                             XDeviceInfo *devInfo = XListInputDevices(backend,
1231                                                                      &count);
1232                             if (devInfo) {
1233                                 for (i = 0; i < count; i++) {
1234                                     if ((unsigned)iinfo.physicalId
1235                                         == devInfo[i].id
1236                                         && devInfo[i].name) {
1237                                         backendname = strdup(devInfo[i].name);
1238                                         break;
1239                                     }
1240                                 }
1241                                 XFreeDeviceList(devInfo);
1242                             }
1243                         }
1244                         XCloseDisplay(backend);
1245                     }
1246                 }
1247 #endif
1248                 printf("    %2d backend %s o%d/%s",i, core(&iinfo),
1249                        iinfo.physicalScreen, iinfo.name);
1250                 if (iinfo.physicalId >= 0) printf("/id%d", iinfo.physicalId);
1251 #ifdef XINPUT
1252                 if (backendname) {
1253                     printf("=%s", backendname);
1254                     free(backendname);
1255                 }
1256 #endif
1257                 break;
1258             }
1259         }
1260         printf("\n");
1261     }
1262     return 1;
1263 }
1264
1265 #endif /* DMX */
1266
1267 #ifdef INCLUDE_XPRINT_SUPPORT
1268 static
1269 void print_xprint_attrpool(const char *name, const char *attrpool)
1270 {
1271   int         c;
1272   const char *s = attrpool;
1273   
1274   printf("    %s:\n      ", name);
1275   
1276   while( (c = *s++) != '\0' )
1277   {
1278     if (c == '\n') {
1279       printf("\n      ");
1280     }
1281     else
1282     {
1283       fputc(c, stdout);
1284     }
1285   }
1286   fputc('\n', stdout);
1287 }
1288
1289 static int
1290 print_xprint_info(Display *dpy, char *extname)
1291 {  
1292
1293   short           majorrev,
1294                   minorrev;
1295   int             xp_event_base,
1296                   xp_error_base;
1297   XPPrinterList   printerlist;
1298   Screen        **pscreens;
1299   int             plcount,
1300                   pscrcount,
1301                   i;
1302
1303   if (XpQueryVersion(dpy, &majorrev, &minorrev) == False) {
1304     return 0;
1305   }
1306   
1307   print_standard_extension_info(dpy, extname, majorrev, minorrev);
1308
1309   if (XpQueryExtension(dpy, &xp_event_base, &xp_error_base) == False) {
1310     printf("  XpQueryExtension() failed.\n");
1311     return 0;
1312   }
1313   
1314   /* Print event info */
1315   printf("  xp_event_base=%d, xp_error_base=%d\n", xp_event_base, xp_error_base);
1316   
1317   /* Print info which screens support the Xprint extension */
1318   printf("  Print screens = {");
1319   pscreens = XpQueryScreens(dpy, &pscrcount);
1320   for( i = 0 ; i < pscrcount ; i++ ) {
1321     printf("%s%d", ((i > 0)?(", "):("")), (int)XScreenNumberOfScreen(pscreens[i]));
1322   }
1323   XFree(pscreens);
1324   printf("}\n");
1325
1326   /* Enumerate the list of printers */
1327   printerlist = XpGetPrinterList(dpy, NULL, &plcount);
1328   /* Print number of printers, then each printer name and description */
1329   printf("  Found %d printers on this server.\n", plcount);
1330   for( i = 0 ; i < plcount ; i++) {
1331     printf("  printer %d: name='%s', descr='%s'\n",
1332            i, NULLSTR(printerlist[i].name), NULLSTR(printerlist[i].desc));
1333   }
1334   
1335   /* Enumerate the list of printers with details */
1336   for( i = 0 ; i < plcount ; i++) {
1337     char       *printername = printerlist[i].name;
1338     XPContext   pcontext;
1339     char       *s;
1340     
1341     printf("  Attributes of printer '%s':\n", NULLSTR(printername));
1342
1343     pcontext = XpCreateContext(dpy, printername);
1344     if (pcontext == None) {
1345       printf("    Error: Could not open printer.\n");
1346       continue;
1347     }
1348
1349     s=XpGetAttributes(dpy, pcontext, XPJobAttr);     print_xprint_attrpool("XPJobAttr",     s);  XFree(s);
1350     s=XpGetAttributes(dpy, pcontext, XPDocAttr);     print_xprint_attrpool("XPDocAttr",     s);  XFree(s);
1351     s=XpGetAttributes(dpy, pcontext, XPPageAttr);    print_xprint_attrpool("XPPageAttr",    s);  XFree(s);
1352     s=XpGetAttributes(dpy, pcontext, XPPrinterAttr); print_xprint_attrpool("XPPrinterAttr", s);  XFree(s);
1353     s=XpGetAttributes(dpy, pcontext, XPServerAttr);  print_xprint_attrpool("XPServerAttr",  s);  XFree(s);
1354
1355     XpDestroyContext(dpy, pcontext);
1356   }
1357   
1358   XpFreePrinterList(printerlist);
1359
1360   return 1;
1361 }
1362 #endif /* INCLUDE_XPRINT_SUPPORT */
1363
1364 /* utilities to manage the list of recognized extensions */
1365
1366
1367 typedef int (*ExtensionPrintFunc)(
1368     Display *, char *
1369 );
1370
1371 typedef struct {
1372     char *extname;
1373     ExtensionPrintFunc printfunc;
1374     Bool printit;
1375 } ExtensionPrintInfo;
1376
1377 ExtensionPrintInfo known_extensions[] =
1378 {
1379 #ifdef MITSHM
1380     {"MIT-SHM", print_mitshm_info, False},
1381 #endif /* MITSHM */
1382 #ifdef XKB
1383     {XkbName, print_xkb_info, False},
1384 #endif /* XKB */
1385 #ifdef MULTIBUFFER
1386     {MULTIBUFFER_PROTOCOL_NAME, print_multibuf_info, False},
1387 #endif
1388     {"SHAPE", print_shape_info, False},
1389     {SYNC_NAME, print_sync_info, False},
1390 #ifdef XFreeXDGA
1391     {XF86DGANAME, print_dga_info, False},
1392 #endif /* XFreeXDGA */
1393 #ifdef XF86VIDMODE
1394     {XF86VIDMODENAME, print_XF86VidMode_info, False},
1395 #endif /* XF86VIDMODE */
1396 #ifdef XF86MISC
1397     {XF86MISCNAME, print_XF86Misc_info, False},
1398 #endif /* XF86MISC */
1399     {XTestExtensionName, print_xtest_info, False},
1400     {"DOUBLE-BUFFER", print_dbe_info, False},
1401     {"RECORD", print_record_info, False},
1402 #ifdef XINPUT
1403     {INAME, print_xinput_info, False},
1404 #endif
1405 #ifdef XRENDER
1406     {RENDER_NAME, print_xrender_info, False},
1407 #endif
1408 #ifdef PANORAMIX
1409     {"XINERAMA", print_xinerama_info, False},
1410 #endif
1411 #ifdef DMX
1412     {"DMX", print_dmx_info, False},
1413 #endif
1414 #ifdef INCLUDE_XPRINT_SUPPORT
1415     {XP_PRINTNAME, print_xprint_info, False},
1416 #endif /* INCLUDE_XPRINT_SUPPORT */
1417     /* add new extensions here */
1418 };
1419
1420 int num_known_extensions = sizeof known_extensions / sizeof known_extensions[0];
1421
1422 static void
1423 print_known_extensions(FILE *f)
1424 {
1425     int i, col;
1426     for (i = 0, col = 6; i < num_known_extensions; i++)
1427     {
1428         int extlen = strlen(known_extensions[i].extname) + 1;
1429         
1430         if ((col + extlen) > 79)
1431         {
1432                 col = 6;
1433                 fprintf(f, "\n     ");
1434         }
1435         fprintf(f, "%s ", known_extensions[i].extname);
1436         col += extlen;
1437     }
1438 }
1439
1440 static void
1441 mark_extension_for_printing(char *extname)
1442 {
1443     int i;
1444
1445     if (strcmp(extname, "all") == 0)
1446     {
1447         for (i = 0; i < num_known_extensions; i++)
1448             known_extensions[i].printit = True;
1449     }
1450     else
1451     {
1452         for (i = 0; i < num_known_extensions; i++)
1453         {
1454             if (strcmp(extname, known_extensions[i].extname) == 0)
1455             {
1456                 known_extensions[i].printit = True;
1457                 return;
1458             }
1459         }
1460         printf("%s extension not supported by %s\n", extname, ProgramName);
1461     }
1462 }
1463
1464 static void
1465 print_marked_extensions(Display *dpy)
1466 {
1467     int i;
1468     for (i = 0; i < num_known_extensions; i++)
1469     {
1470         if (known_extensions[i].printit)
1471         {
1472             printf("\n");
1473             if (! (*known_extensions[i].printfunc)(dpy,
1474                                         known_extensions[i].extname))
1475             {
1476                 printf("%s extension not supported by server\n",
1477                        known_extensions[i].extname);
1478             }
1479         }
1480     }
1481 }
1482
1483 static void 
1484 usage(void)
1485 {
1486     fprintf (stderr, "usage:  %s [options]\n", ProgramName);
1487     fprintf (stderr, "-display displayname\tserver to query\n");
1488     fprintf (stderr, "-queryExtensions\tprint info returned by XQueryExtension\n");
1489     fprintf (stderr, "-ext all\t\tprint detailed info for all supported extensions\n");
1490     fprintf (stderr, "-ext extension-name\tprint detailed info for extension-name if one of:\n     ");
1491     print_known_extensions(stderr);
1492     fprintf (stderr, "\n");
1493     exit (1);
1494 }
1495
1496 int 
1497 main(int argc, char *argv[])
1498 {
1499     Display *dpy;                       /* X connection */
1500     char *displayname = NULL;           /* server to contact */
1501     int i;                              /* temp variable:  iterator */
1502
1503     ProgramName = argv[0];
1504
1505     for (i = 1; i < argc; i++) {
1506         char *arg = argv[i];
1507         int len = strlen(arg);
1508         
1509         if (!strncmp("-display", arg, len)) {
1510             if (++i >= argc) usage ();
1511             displayname = argv[i];
1512         } else if (!strncmp("-queryExtensions", arg, len)) {
1513             queryExtensions = True;
1514         } else if (!strncmp("-ext", arg, len)) {
1515             if (++i >= argc) usage ();
1516             mark_extension_for_printing(argv[i]);
1517         } else
1518             usage ();
1519     }
1520
1521     dpy = XOpenDisplay (displayname);
1522     if (!dpy) {
1523         fprintf (stderr, "%s:  unable to open display \"%s\".\n",
1524                  ProgramName, XDisplayName (displayname));
1525         exit (1);
1526     }
1527
1528     print_display_info (dpy);
1529     for (i = 0; i < ScreenCount (dpy); i++) {
1530         print_screen_info (dpy, i);
1531     }
1532
1533     print_marked_extensions(dpy);
1534
1535     XCloseDisplay (dpy);
1536     exit (0);
1537 }