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