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