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