|
1 /* |
|
2 * $XConsortium: xlswins.c,v 1.12 89/12/10 17:14:02 rws Exp $ |
|
3 * |
|
4 * Copyright 1989 Massachusetts Institute of Technology |
|
5 * |
|
6 * Permission to use, copy, modify, distribute, and sell this software and its |
|
7 * documentation for any purpose is hereby granted without fee, provided that |
|
8 * the above copyright notice appear in all copies and that both that |
|
9 * copyright notice and this permission notice appear in supporting |
|
10 * documentation, and that the name of M.I.T. not be used in advertising or |
|
11 * publicity pertaining to distribution of the software without specific, |
|
12 * written prior permission. M.I.T. makes no representations about the |
|
13 * suitability of this software for any purpose. It is provided "as is" |
|
14 * without express or implied warranty. |
|
15 * |
|
16 * M.I.T. DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL |
|
17 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL M.I.T. |
|
18 * BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES |
|
19 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION |
|
20 * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN |
|
21 * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. |
|
22 * |
|
23 * Author: Jim Fulton, MIT X Consortium |
|
24 */ |
|
25 |
|
26 #include <stdio.h> |
|
27 #include <X11/Xos.h> |
|
28 #include <X11/Xlib.h> |
|
29 #include <X11/Xutil.h> |
|
30 |
|
31 char *ProgramName; |
|
32 static char *output_format = "0x%lx"; |
|
33 static char widget_name_buf[1024], widget_class_buf[1024]; |
|
34 |
|
35 static void usage () |
|
36 { |
|
37 static char *help[] = { |
|
38 " -display displayname X server to contact", |
|
39 " -format {hex, decimal, octal} format used to print window id", |
|
40 " -indent number amount to indent per level", |
|
41 " -long print a long listing", |
|
42 " -resources print a listing of widget resources", |
|
43 "", |
|
44 NULL}; |
|
45 char **cpp; |
|
46 |
|
47 fprintf (stderr, "usage:\n %s [-options ...] [windowid] ...\n\n", |
|
48 ProgramName); |
|
49 fprintf (stderr, "where options include:\n"); |
|
50 for (cpp = help; *cpp; cpp++) { |
|
51 fprintf (stderr, "%s\n", *cpp); |
|
52 } |
|
53 exit (1); |
|
54 } |
|
55 |
|
56 static long parse_long (s) |
|
57 char *s; |
|
58 { |
|
59 char *fmt = "%lu"; |
|
60 long retval = 0; |
|
61 |
|
62 if (s && *s) { |
|
63 if (*s == '0') s++, fmt = "%lo"; |
|
64 if (*s == 'x' || *s == 'X') s++, fmt = "%lx"; |
|
65 (void) sscanf (s, fmt, &retval); |
|
66 } |
|
67 return retval; |
|
68 } |
|
69 |
|
70 static int got_xerror = 0; |
|
71 |
|
72 static int myxerror (dpy, rep) |
|
73 Display *dpy; |
|
74 XErrorEvent *rep; |
|
75 { |
|
76 char buffer[BUFSIZ]; |
|
77 char mesg[BUFSIZ]; |
|
78 char number[32]; |
|
79 char *mtype = "XlibMessage"; |
|
80 |
|
81 got_xerror++; |
|
82 if (rep->error_code == BadWindow) { |
|
83 fflush (stdout); |
|
84 fprintf (stderr, "%s: no such window ", ProgramName); |
|
85 fprintf (stderr, output_format, rep->resourceid); |
|
86 fprintf (stderr, "\n"); |
|
87 return 0; |
|
88 } |
|
89 XGetErrorText(dpy, rep->error_code, buffer, BUFSIZ); |
|
90 XGetErrorDatabaseText(dpy, mtype, "XError", "X Error", mesg, BUFSIZ); |
|
91 (void) fprintf(stderr, "%s: %s\n ", mesg, buffer); |
|
92 XGetErrorDatabaseText(dpy, mtype, "MajorCode", "Request Major code %d", |
|
93 mesg, BUFSIZ); |
|
94 (void) fprintf(stderr, mesg, rep->request_code); |
|
95 sprintf(number, "%d", rep->request_code); |
|
96 XGetErrorDatabaseText(dpy, "XRequest", number, "", buffer, BUFSIZ); |
|
97 (void) fprintf(stderr, " %s", buffer); |
|
98 fputs("\n ", stderr); |
|
99 XGetErrorDatabaseText(dpy, mtype, "MinorCode", "Request Minor code", |
|
100 mesg, BUFSIZ); |
|
101 (void) fprintf(stderr, mesg, rep->minor_code); |
|
102 fputs("\n ", stderr); |
|
103 XGetErrorDatabaseText(dpy, mtype, "ResourceID", "ResourceID 0x%x", |
|
104 mesg, BUFSIZ); |
|
105 (void) fprintf(stderr, mesg, rep->resourceid); |
|
106 fputs("\n ", stderr); |
|
107 XGetErrorDatabaseText(dpy, mtype, "ErrorSerial", "Error Serial #%d", |
|
108 mesg, BUFSIZ); |
|
109 (void) fprintf(stderr, mesg, rep->serial); |
|
110 fputs("\n ", stderr); |
|
111 XGetErrorDatabaseText(dpy, mtype, "CurrentSerial", "Current Serial #%d", |
|
112 mesg, BUFSIZ); |
|
113 (void) fprintf(stderr, mesg, NextRequest(dpy)-1); |
|
114 fputs("\n", stderr); |
|
115 if (rep->error_code == BadImplementation) return 0; |
|
116 exit (1); |
|
117 } |
|
118 |
|
119 |
|
120 main (argc, argv) |
|
121 int argc; |
|
122 char *argv[]; |
|
123 { |
|
124 char *displayname = NULL; |
|
125 Display *dpy; |
|
126 Bool long_version = False; |
|
127 Bool print_resources = False; |
|
128 int i; |
|
129 int indent = 2; |
|
130 |
|
131 ProgramName = argv[0]; |
|
132 |
|
133 for (i = 1; i < argc; i++) { |
|
134 char *arg = argv[i]; |
|
135 |
|
136 if (arg[0] == '-') { |
|
137 switch (arg[1]) { |
|
138 case 'd': /* -display displayname */ |
|
139 if (++i >= argc) usage (); |
|
140 displayname = argv[i]; |
|
141 continue; |
|
142 case 'i': /* -indent number */ |
|
143 if (++i >= argc) usage (); |
|
144 indent = atoi (argv[i]); |
|
145 continue; |
|
146 case 'l': |
|
147 long_version = True; /* -long */ |
|
148 continue; |
|
149 case 'r': /* -resources */ |
|
150 print_resources = True; |
|
151 continue; |
|
152 case 'f': /* -format [odh] */ |
|
153 if (++i >= argc) usage (); |
|
154 switch (argv[i][0]) { |
|
155 case 'd': /* decimal */ |
|
156 output_format = "%lu"; |
|
157 continue; |
|
158 case 'o': /* octal */ |
|
159 output_format = "0%lo"; |
|
160 continue; |
|
161 case 'h': /* hex */ |
|
162 output_format = "0x%lx"; |
|
163 continue; |
|
164 } |
|
165 usage (); |
|
166 |
|
167 default: |
|
168 usage (); |
|
169 } |
|
170 } else { |
|
171 break; /* out of for loop */ |
|
172 } |
|
173 } |
|
174 |
|
175 dpy = XOpenDisplay (displayname); |
|
176 if (!dpy) { |
|
177 fprintf (stderr, "%s: unable to open display \"%s\"\n", |
|
178 ProgramName, XDisplayName (displayname)); |
|
179 exit (1); |
|
180 } |
|
181 |
|
182 XSetErrorHandler (myxerror); |
|
183 |
|
184 widget_name_buf[0] = widget_class_buf[0] = '\0'; |
|
185 if (i >= argc) { |
|
186 list_window (dpy, RootWindow (dpy, DefaultScreen (dpy)), 0, |
|
187 indent, long_version, print_resources, |
|
188 widget_name_buf, widget_class_buf); |
|
189 } else { |
|
190 for (; i < argc; i++) { |
|
191 Window w = parse_long (argv[i]); |
|
192 if (w == 0) { |
|
193 fprintf (stderr, "%s: bad window number \"%s\"\n", |
|
194 ProgramName, argv[i]); |
|
195 } else { |
|
196 list_window (dpy, w, 0, indent, long_version, print_resources, |
|
197 widget_name_buf, widget_class_buf); |
|
198 } |
|
199 } |
|
200 } |
|
201 |
|
202 XCloseDisplay (dpy); |
|
203 exit (0); |
|
204 } |
|
205 |
|
206 |
|
207 list_window (dpy, w, depth, indent, long_version, print_resources, |
|
208 pname, pclass) |
|
209 Display *dpy; |
|
210 Window w; |
|
211 int depth; |
|
212 int indent; |
|
213 Bool long_version; |
|
214 Bool print_resources; |
|
215 char *pname, *pclass; |
|
216 { |
|
217 Window root, parent; |
|
218 unsigned int nchildren; |
|
219 Window *children = NULL; |
|
220 int n; |
|
221 char *name = NULL; |
|
222 XClassHint ch; |
|
223 int pnamelen, pclasslen; |
|
224 |
|
225 if (!print_resources) { |
|
226 if (long_version) { |
|
227 printf ("%d: ", depth); |
|
228 } |
|
229 for (n = depth * indent; n > 0; n--) { |
|
230 putchar (' '); |
|
231 } |
|
232 printf (output_format, w); |
|
233 } |
|
234 |
|
235 /* |
|
236 * if we put anything before the XFetchName then we'll have to change the |
|
237 * error handler |
|
238 */ |
|
239 got_xerror = 0; |
|
240 (void) XFetchName (dpy, w, &name); |
|
241 |
|
242 ch.res_name = ch.res_class = NULL; |
|
243 if (!print_resources) { |
|
244 printf (" (%s)", name ? name : ""); |
|
245 |
|
246 if (long_version && got_xerror == 0) { |
|
247 int x, y, rx, ry; |
|
248 unsigned int width, height, bw, depth; |
|
249 |
|
250 if (XGetClassHint (dpy, w, &ch)) { |
|
251 printf ("; (%s)(%s)", |
|
252 ch.res_name ? ch.res_name : "nil", |
|
253 ch.res_class ? ch.res_class : "nil"); |
|
254 } else { |
|
255 printf ("; ()()"); |
|
256 } |
|
257 |
|
258 if (XGetGeometry(dpy, w, &root, &x,&y,&width,&height,&bw,&depth)) { |
|
259 Window child; |
|
260 |
|
261 printf (" %ux%u+%d+%d", width, height, x, y); |
|
262 if (XTranslateCoordinates (dpy, w,root,0,0,&rx,&ry,&child)) { |
|
263 printf (" +%d+%d", rx - bw, ry - bw); |
|
264 } |
|
265 } |
|
266 } |
|
267 } else { |
|
268 (void) XGetClassHint (dpy, w, &ch); |
|
269 if (got_xerror == 0) { |
|
270 if (*pname) strcat (pname, "."); |
|
271 if (ch.res_name) strcat (pname, ch.res_name); |
|
272 if (*pclass) strcat (pclass, "."); |
|
273 if (ch.res_class) strcat (pclass, ch.res_class); |
|
274 |
|
275 printf ("%s = %s", pclass, pname); |
|
276 } |
|
277 } |
|
278 putchar ('\n'); |
|
279 |
|
280 if (got_xerror) goto done; |
|
281 |
|
282 if (!XQueryTree (dpy, w, &root, &parent, &children, &nchildren)) |
|
283 goto done; |
|
284 |
|
285 pnamelen = strlen(pname); |
|
286 pclasslen = strlen(pclass); |
|
287 for (n = 0; n < nchildren; n++) { |
|
288 pname[pnamelen] = '\0'; |
|
289 pclass[pclasslen] = '\0'; |
|
290 list_window (dpy, children[n], depth + 1, indent, long_version, |
|
291 print_resources, pname, pclass); |
|
292 } |
|
293 |
|
294 done: |
|
295 if (ch.res_name) XFree (ch.res_name); |
|
296 if (ch.res_class) XFree (ch.res_class); |
|
297 if (name) XFree ((char *) name); |
|
298 if (children) XFree ((char *) children); |
|
299 return; |
|
300 } |
|
301 |