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