6cd6f465f0070fb058599b2c4e045c8fb8e495fb
[xscreensaver] / utils / xmu.c
1 /* This file contains compatibility routines for systems without Xmu.
2  * You would be better served by installing Xmu on your machine or
3  * yelling at your vendor to ship it.
4  */
5
6 #ifdef HAVE_CONFIG_H
7 # include "config.h"
8 #endif
9
10 #ifndef HAVE_XMU
11 /*
12  * Copyright 1989 Massachusetts Institute of Technology
13  *
14  * Permission to use, copy, modify, and distribute this software and its
15  * documentation for any purpose and without fee is hereby granted, provided
16  * that the above copyright notice appear in all copies and that both that
17  * copyright notice and this permission notice appear in supporting
18  * documentation, and that the name of M.I.T. not be used in advertising
19  * or publicity pertaining to distribution of the software without specific,
20  * written prior permission.  M.I.T. makes no representations about the
21  * suitability of this software for any purpose.  It is provided "as is"
22  * without express or implied warranty.
23  *
24  * M.I.T. DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL
25  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL M.I.T.
26  * BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
27  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
28  * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN 
29  * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
30  */
31
32 #include "xmu.h"
33
34 #ifndef NEED_EVENTS
35 # define NEED_EVENTS            /* to make Xproto.h define xEvent */
36 #endif
37 #ifndef VMS
38 # include <X11/Xproto.h>        /* for xEvent (used by Xlibint.h) */
39 # include <X11/Xlibint.h>       /* for _XExtension */
40 #else /* VMS */
41 # include <X11/Xlib.h>
42 #endif /* VMS */
43 #include <X11/Intrinsic.h>      /* for XtSpecificationRelease */
44
45 /*
46  * XmuPrintDefaultErrorMessage - print a nice error that looks like the usual 
47  * message.  Returns 1 if the caller should consider exitting else 0.
48  */
49 int XmuPrintDefaultErrorMessage (Display *dpy, XErrorEvent *event, FILE *fp)
50 {
51     char buffer[BUFSIZ];
52     char mesg[BUFSIZ];
53     char number[32];
54     char *mtype = "XlibMessage";
55     _XExtension *ext = (_XExtension *)NULL;
56     XGetErrorText(dpy, event->error_code, buffer, BUFSIZ);
57     XGetErrorDatabaseText(dpy, mtype, "XError", "X Error", mesg, BUFSIZ);
58     (void) fprintf(fp, "%s:  %s\n  ", mesg, buffer);
59     XGetErrorDatabaseText(dpy, mtype, "MajorCode", "Request Major code %d", 
60         mesg, BUFSIZ);
61     (void) fprintf(fp, mesg, event->request_code);
62     if (event->request_code < 128) {
63         sprintf(number, "%d", event->request_code);
64         XGetErrorDatabaseText(dpy, "XRequest", number, "", buffer, BUFSIZ);
65     } else {
66         /* XXX this is non-portable */
67         for (ext = dpy->ext_procs;
68              ext && (ext->codes.major_opcode != event->request_code);
69              ext = ext->next)
70           ;
71         if (ext)
72             strcpy(buffer, ext->name);
73         else
74             buffer[0] = '\0';
75     }
76     (void) fprintf(fp, " (%s)", buffer);
77     fputs("\n  ", fp);
78 #if (XtSpecificationRelease >= 5)
79     if (event->request_code >= 128) {
80         XGetErrorDatabaseText(dpy, mtype, "MinorCode", "Request Minor code %d",
81                               mesg, BUFSIZ);
82         (void) fprintf(fp, mesg, event->minor_code);
83         if (ext) {
84             sprintf(mesg, "%s.%d", ext->name, event->minor_code);
85             XGetErrorDatabaseText(dpy, "XRequest", mesg, "", buffer, BUFSIZ);
86             (void) fprintf(fp, " (%s)", buffer);
87         }
88         fputs("\n  ", fp);
89     }
90     if (event->error_code >= 128) {
91         /* let extensions try to print the values */
92         /* XXX this is non-portable code */
93         for (ext = dpy->ext_procs; ext; ext = ext->next) {
94             if (ext->error_values)
95                 (*ext->error_values)(dpy, event, fp);
96         }
97         /* the rest is a fallback, providing a simple default */
98         /* kludge, try to find the extension that caused it */
99         buffer[0] = '\0';
100         for (ext = dpy->ext_procs; ext; ext = ext->next) {
101             if (ext->error_string) 
102                 (*ext->error_string)(dpy, event->error_code, &ext->codes,
103                                      buffer, BUFSIZ);
104             if (buffer[0])
105                 break;
106         }    
107         if (buffer[0])
108             sprintf(buffer, "%s.%d", ext->name,
109                     event->error_code - ext->codes.first_error);
110         else
111             strcpy(buffer, "Value");
112         XGetErrorDatabaseText(dpy, mtype, buffer, "", mesg, BUFSIZ);
113         if (*mesg) {
114             (void) fprintf(fp, mesg, event->resourceid);
115             fputs("\n  ", fp);
116         }
117     } else if ((event->error_code == BadWindow) ||
118                (event->error_code == BadPixmap) ||
119                (event->error_code == BadCursor) ||
120                (event->error_code == BadFont) ||
121                (event->error_code == BadDrawable) ||
122                (event->error_code == BadColor) ||
123                (event->error_code == BadGC) ||
124                (event->error_code == BadIDChoice) ||
125                (event->error_code == BadValue) ||
126                (event->error_code == BadAtom)) {
127         if (event->error_code == BadValue)
128             XGetErrorDatabaseText(dpy, mtype, "Value", "Value 0x%x",
129                                   mesg, BUFSIZ);
130         else if (event->error_code == BadAtom)
131             XGetErrorDatabaseText(dpy, mtype, "AtomID", "AtomID 0x%x",
132                                   mesg, BUFSIZ);
133         else
134             XGetErrorDatabaseText(dpy, mtype, "ResourceID", "ResourceID 0x%x",
135                                   mesg, BUFSIZ);
136         (void) fprintf(fp, mesg, event->resourceid);
137         fputs("\n  ", fp);
138     }
139 #elif (XtSpecificationRelease == 4)
140     XGetErrorDatabaseText(dpy, mtype, "MinorCode", "Request Minor code %d",
141                           mesg, BUFSIZ);
142     (void) fprintf(fp, mesg, event->minor_code);
143     fputs("\n  ", fp);
144     if (ext) {
145       sprintf(mesg, "%s.%d", ext->name, event->minor_code);
146       XGetErrorDatabaseText(dpy, "XRequest", mesg, "", buffer, BUFSIZ);
147       (void) fprintf(fp, " (%s)", buffer);
148     }
149     XGetErrorDatabaseText(dpy, mtype, "ResourceID", "ResourceID 0x%x",
150                           mesg, BUFSIZ);
151     (void) fprintf(fp, mesg, event->resourceid);
152     fputs("\n  ", fp);
153 #else
154 ERROR! Unsupported release of X11
155 #endif
156     XGetErrorDatabaseText(dpy, mtype, "ErrorSerial", "Error Serial #%d", 
157         mesg, BUFSIZ);
158     (void) fprintf(fp, mesg, event->serial);
159     fputs("\n  ", fp);
160     XGetErrorDatabaseText(dpy, mtype, "CurrentSerial", "Current Serial #%d",
161         mesg, BUFSIZ);
162     (void) fprintf(fp, mesg, NextRequest(dpy)-1);
163     fputs("\n", fp);
164     if (event->error_code == BadImplementation) return 0;
165     return 1;
166 }
167
168 #else  /* HAVE_XMU */
169
170 # ifdef __osf__
171   /* Stupid alpha 3.2 compiler returns a FAILURE exit code if compiling
172      an empty file.  Fake it out with a file-private variable. */
173   static const int digital_unix_compiler_sucks;
174 # endif /* __osf__ */
175
176 #endif /* HAVE_XMU */