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