1 /* $XConsortium: dsimple.c /main/17 1995/12/07 10:23:27 kaleb $ */
2 /* $XFree86: xc/programs/xwd/dsimple.c,v 3.0 1996/06/10 09:20:34 dawes Exp $ */
3 /*
4
5 Copyright (c) 1993 X Consortium
6
7 Permission is hereby granted, free of charge, to any person obtaining
8 a copy of this software and associated documentation files (the
9 "Software"), to deal in the Software without restriction, including
10 without limitation the rights to use, copy, modify, merge, publish,
11 distribute, sublicense, and/or sell copies of the Software, and to
12 permit persons to whom the Software is furnished to do so, subject to
13 the following conditions:
14
15 The above copyright notice and this permission notice shall be included
16 in all copies or substantial portions of the Software.
17
18 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
19 OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
20 MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
21 IN NO EVENT SHALL THE X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR
22 OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
23 ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
24 OTHER DEALINGS IN THE SOFTWARE.
25
26 Except as contained in this notice, the name of the X Consortium shall
27 not be used in advertising or otherwise to promote the sale, use or
28 other dealings in this Software without prior written authorization
29 from the X Consortium.
30
31 */
32
33 #include <X11/Xos.h>
34 #include <X11/Xlib.h>
35 #include <X11/Xutil.h>
36 #include <X11/cursorfont.h>
37 #include <stdio.h>
38 /*
39 * Other_stuff.h: Definitions of routines in other_stuff.
40 *
41 * Written by Mark Lillibridge. Last updated 7/1/87
42 */
43
44 #ifdef X_NOT_STDC_ENV
45 char *malloc(), realloc();
46 #else
47 #include <stdlib.h>
48 #endif
49
50 extern Bool silent;
51 unsigned long Resolve_Color();
52 Pixmap Bitmap_To_Pixmap();
53 Window Select_Window();
54 void out();
55 void blip();
56 Window Window_With_Name();
57 void Fatal_Error();
58 void usage(void);
59
60 /* forward */
61 void outl();
62
63 /*
64 * Just_display: A group of routines designed to make the writting of simple
65 * X11 applications which open a display but do not open
66 * any windows much faster and easier. Unless a routine says
67 * otherwise, it may be assumed to require program_name, dpy,
68 * and screen already defined on entry.
69 *
70 * Written by Mark Lillibridge. Last updated 7/1/87
71 */
72
73
74 /* This stuff is defined in the calling program by just_display.h */
75 extern char *program_name;
76 extern Display *dpy;
77 extern int screen;
78
79
80 /*
81 * Malloc: like malloc but handles out of memory using Fatal_Error.
82 */
Malloc(size)83 char *Malloc(size)
84 unsigned size;
85 {
86 char *data;
87
88 if (!(data = malloc(size)))
89 Fatal_Error("Out of memory!");
90
91 return(data);
92 }
93
94
95 /*
96 * Realloc: like Malloc except for realloc, handles NULL using Malloc.
97 */
Realloc(ptr,size)98 char *Realloc(ptr, size)
99 char *ptr;
100 int size;
101 {
102 char *new_ptr;
103
104 if (!ptr)
105 return(Malloc(size));
106
107 if (!(new_ptr = realloc(ptr, size)))
108 Fatal_Error("Out of memory!");
109
110 return(new_ptr);
111 }
112
113
114 /*
115 * Get_Display_Name (argc, argv) Look for -display, -d, or host:dpy (obselete)
116 * If found, remove it from command line. Don't go past a lone -.
117 */
Get_Display_Name(pargc,argv)118 char *Get_Display_Name(pargc, argv)
119 int *pargc; /* MODIFIED */
120 char **argv; /* MODIFIED */
121 {
122 int argc = *pargc;
123 char **pargv = argv+1;
124 char *displayname = NULL;
125 int i;
126
127 for (i = 1; i < argc; i++) {
128 char *arg = argv[i];
129
130 if (!strcmp (arg, "-display") || !strcmp (arg, "-d")) {
131 if (++i >= argc) usage ();
132
133 displayname = argv[i];
134 *pargc -= 2;
135 continue;
136 }
137 if (!strcmp(arg,"-")) {
138 while (i<argc)
139 *pargv++ = argv[i++];
140 break;
141 }
142 *pargv++ = arg;
143 }
144
145 *pargv = NULL;
146 return (displayname);
147 }
148
149
150 /*
151 * Open_Display: Routine to open a display with correct error handling.
152 * Does not require dpy or screen defined on entry.
153 */
Open_Display(display_name)154 Display *Open_Display(display_name)
155 char *display_name;
156 {
157 Display *d;
158
159 d = XOpenDisplay(display_name);
160 if (d == NULL) {
161 fprintf (stderr, "%s: unable to open display '%s'\n",
162 program_name, XDisplayName (display_name));
163 usage ();
164 /* doesn't return */
165 }
166
167 return(d);
168 }
169
170
171 /*
172 * Setup_Display_And_Screen: This routine opens up the correct display (i.e.,
173 * it calls Get_Display_Name) and then stores a
174 * pointer to it in dpy. The default screen
175 * for this display is then stored in screen.
176 * Does not require dpy or screen defined.
177 */
Setup_Display_And_Screen(argc,argv)178 void Setup_Display_And_Screen(argc, argv)
179 int *argc; /* MODIFIED */
180 char **argv; /* MODIFIED */
181 {
182 dpy = Open_Display (Get_Display_Name(argc, argv));
183 screen = DefaultScreen(dpy);
184 }
185
186
187 /*
188 * Open_Font: This routine opens a font with error handling.
189 */
Open_Font(name)190 XFontStruct *Open_Font(name)
191 char *name;
192 {
193 XFontStruct *font;
194
195 if (!(font=XLoadQueryFont(dpy, name)))
196 Fatal_Error("Unable to open font %s!", name);
197
198 return(font);
199 }
200
201
202 /*
203 * ReadBitmapFile: same as XReadBitmapFile except it returns the bitmap
204 * directly and handles errors using Fatal_Error.
205 */
_bitmap_error(status,filename)206 static void _bitmap_error(status, filename)
207 int status;
208 char *filename;
209 {
210 if (status == BitmapOpenFailed)
211 Fatal_Error("Can't open file %s!", filename);
212 else if (status == BitmapFileInvalid)
213 Fatal_Error("file %s: Bad bitmap format.", filename);
214 else
215 Fatal_Error("Out of memory!");
216 }
217
ReadBitmapFile(d,filename,width,height,x_hot,y_hot)218 Pixmap ReadBitmapFile(d, filename, width, height, x_hot, y_hot)
219 Drawable d;
220 char *filename;
221 int *width, *height, *x_hot, *y_hot;
222 {
223 Pixmap bitmap;
224 int status;
225
226 status = XReadBitmapFile(dpy, RootWindow(dpy, screen), filename,
227 (unsigned int *)width, (unsigned int *)height,
228 &bitmap, x_hot, y_hot);
229 if (status != BitmapSuccess)
230 _bitmap_error(status, filename);
231
232 return(bitmap);
233 }
234
235
236 /*
237 * WriteBitmapFile: same as XWriteBitmapFile except it handles errors
238 * using Fatal_Error.
239 */
WriteBitmapFile(filename,bitmap,width,height,x_hot,y_hot)240 void WriteBitmapFile(filename, bitmap, width, height, x_hot, y_hot)
241 char *filename;
242 Pixmap bitmap;
243 int width, height, x_hot, y_hot;
244 {
245 int status;
246
247 status= XWriteBitmapFile(dpy, filename, bitmap, width, height, x_hot,
248 y_hot);
249 if (status != BitmapSuccess)
250 _bitmap_error(status, filename);
251 }
252
253
254 /*
255 * Select_Window_Args: a rountine to provide a common interface for
256 * applications that need to allow the user to select one
257 * window on the screen for special consideration.
258 * This routine implements the following command line
259 * arguments:
260 *
261 * -root Selects the root window.
262 * -id <id> Selects window with id <id>. <id> may
263 * be either in decimal or hex.
264 * -name <name> Selects the window with name <name>.
265 *
266 * Call as Select_Window_Args(&argc, argv) in main before
267 * parsing any of your program's command line arguments.
268 * Select_Window_Args will remove its arguments so that
269 * your program does not have to worry about them.
270 * The window returned is the window selected or 0 if
271 * none of the above arguments was present. If 0 is
272 * returned, Select_Window should probably be called after
273 * all command line arguments, and other setup is done.
274 * For examples of usage, see xwininfo, xwd, or xprop.
275 */
Select_Window_Args(rargc,argv)276 Window Select_Window_Args(rargc, argv)
277 int *rargc;
278 char **argv;
279 #define ARGC (*rargc)
280 {
281 int nargc=1;
282 int argc;
283 char **nargv;
284 Window w=0;
285
286 nargv = argv+1; argc = ARGC;
287 #define OPTION argv[0]
288 #define NXTOPTP ++argv, --argc>0
289 #define NXTOPT if (++argv, --argc==0) usage()
290 #define COPYOPT nargv++[0]=OPTION, nargc++
291
292 while (NXTOPTP) {
293 if (!strcmp(OPTION, "-")) {
294 COPYOPT;
295 while (NXTOPTP)
296 COPYOPT;
297 break;
298 }
299 if (!strcmp(OPTION, "-root")) {
300 w=RootWindow(dpy, screen);
301 continue;
302 }
303 if (!strcmp(OPTION, "-name")) {
304 NXTOPT;
305 w = Window_With_Name(dpy, RootWindow(dpy, screen),
306 OPTION);
307 if (!w)
308 Fatal_Error("No window with name %s exists!",OPTION);
309 continue;
310 }
311 if (!strcmp(OPTION, "-id")) {
312 NXTOPT;
313 w=0;
314 sscanf(OPTION, "0x%lx", &w);
315 if (!w)
316 sscanf(OPTION, "%ld", &w);
317 if (!w)
318 Fatal_Error("Invalid window id format: %s.", OPTION);
319 continue;
320 }
321 COPYOPT;
322 }
323 ARGC = nargc;
324
325 return(w);
326 }
327
328 /*
329 * Other_stuff: A group of routines which do common X11 tasks.
330 *
331 * Written by Mark Lillibridge. Last updated 7/1/87
332 */
333
334 extern Display *dpy;
335 extern int screen;
336
337 /*
338 * Resolve_Color: This routine takes a color name and returns the pixel #
339 * that when used in the window w will be of color name.
340 * (WARNING: The colormap of w MAY be modified! )
341 * If colors are run out of, only the first n colors will be
342 * as correct as the hardware can make them where n depends
343 * on the display. This routine does not require wind to
344 * be defined.
345 */
Resolve_Color(w,name)346 unsigned long Resolve_Color(w, name)
347 Window w;
348 char *name;
349 {
350 XColor c;
351 Colormap colormap;
352 XWindowAttributes wind_info;
353
354 /*
355 * The following is a hack to insure machines without a rgb table
356 * handle at least white & black right.
357 */
358 if (!strcmp(name, "white"))
359 name="#ffffffffffff";
360 if (!strcmp(name, "black"))
361 name="#000000000000";
362
363 XGetWindowAttributes(dpy, w, &wind_info);
364 colormap = wind_info.colormap;
365
366 if (!XParseColor(dpy, colormap, name, &c))
367 Fatal_Error("Bad color format '%s'.", name);
368
369 if (!XAllocColor(dpy, colormap, &c))
370 Fatal_Error("XAllocColor failed!");
371
372 return(c.pixel);
373 }
374
375
376 /*
377 * Bitmap_To_Pixmap: Convert a bitmap to a 2 colored pixmap. The colors come
378 * from the foreground and background colors of the gc.
379 * Width and height are required solely for efficiency.
380 * If needed, they can be obtained via. XGetGeometry.
381 */
Bitmap_To_Pixmap(dpy,d,gc,bitmap,width,height)382 Pixmap Bitmap_To_Pixmap(dpy, d, gc, bitmap, width, height)
383 Display *dpy;
384 Drawable d;
385 GC gc;
386 Pixmap bitmap;
387 int width, height;
388 {
389 Pixmap pix;
390 int x;
391 unsigned int i, depth;
392 Drawable root;
393
394 if (!XGetGeometry(dpy, d, &root, &x, &x, &i, &i, &i, &depth))
395 return(0);
396
397 pix = XCreatePixmap(dpy, d, width, height, (int)depth);
398
399 XCopyPlane(dpy, bitmap, pix, gc, 0, 0, width, height, 0, 0, 1);
400
401 return(pix);
402 }
403
404
405 /*
406 * blip: a debugging routine. Prints Blip! on stderr with flushing.
407 */
blip()408 void blip()
409 {
410 outl("blip!");
411 }
412
413
414 /*
415 * Routine to let user select a window using the mouse
416 */
417
Select_Window(dpy)418 Window Select_Window(dpy)
419 Display *dpy;
420 {
421 int status;
422 Cursor cursor;
423 XEvent event;
424 Window target_win = None, root = RootWindow(dpy,screen);
425 int buttons = 0;
426
427 /* Make the target cursor */
428 cursor = XCreateFontCursor(dpy, XC_crosshair);
429
430 /* Grab the pointer using target cursor, letting it room all over */
431 status = XGrabPointer(dpy, root, False,
432 ButtonPressMask|ButtonReleaseMask, GrabModeSync,
433 GrabModeAsync, root, cursor, CurrentTime);
434 if (status != GrabSuccess) Fatal_Error("Can't grab the mouse.");
435
436 /* Let the user select a window... */
437 while ((target_win == None) || (buttons != 0)) {
438 /* allow one more event */
439 XAllowEvents(dpy, SyncPointer, CurrentTime);
440 XWindowEvent(dpy, root, ButtonPressMask|ButtonReleaseMask, &event);
441 switch (event.type) {
442 case ButtonPress:
443 if (target_win == None) {
444 target_win = event.xbutton.subwindow; /* window selected */
445 if (target_win == None) target_win = root;
446 }
447 buttons++;
448 break;
449 case ButtonRelease:
450 if (buttons > 0) /* there may have been some down before we started */
451 buttons--;
452 break;
453 }
454 }
455
456 XUngrabPointer(dpy, CurrentTime); /* Done with pointer */
457
458 return(target_win);
459 }
460
461
462 /*
463 * Window_With_Name: routine to locate a window with a given name on a display.
464 * If no window with the given name is found, 0 is returned.
465 * If more than one window has the given name, the first
466 * one found will be returned. Only top and its subwindows
467 * are looked at. Normally, top should be the RootWindow.
468 */
Window_With_Name(dpy,top,name)469 Window Window_With_Name(dpy, top, name)
470 Display *dpy;
471 Window top;
472 char *name;
473 {
474 Window *children, dummy;
475 unsigned int nchildren;
476 int i;
477 Window w=0;
478 char *window_name;
479
480 if (XFetchName(dpy, top, &window_name) && !strcmp(window_name, name))
481 return(top);
482
483 if (!XQueryTree(dpy, top, &dummy, &dummy, &children, &nchildren))
484 return(0);
485
486 for (i=0; i<nchildren; i++) {
487 w = Window_With_Name(dpy, children[i], name);
488 if (w)
489 break;
490 }
491 if (children) XFree ((char *)children);
492 return(w);
493 }
494
495 /*
496 * outl: a debugging routine. Flushes stdout then prints a message on stderr
497 * and flushes stderr. Used to print messages when past certain points
498 * in code so we can tell where we are. Outl may be invoked like
499 * printf with up to 7 arguments.
500 */
501 /* VARARGS1 */
502 void
outl(msg,arg0,arg1,arg2,arg3,arg4,arg5,arg6)503 outl(msg, arg0,arg1,arg2,arg3,arg4,arg5,arg6)
504 char *msg;
505 char *arg0, *arg1, *arg2, *arg3, *arg4, *arg5, *arg6;
506 {
507 fflush(stdout);
508 fprintf(stderr, msg, arg0, arg1, arg2, arg3, arg4, arg5, arg6);
509 fprintf(stderr, "\n");
510 fflush(stderr);
511 }
512
513
514 /*
515 * Standard fatal error routine - call like printf but maximum of 7 arguments.
516 * Does not require dpy or screen defined.
517 */
518 /* VARARGS1 */
Fatal_Error(msg,arg0,arg1,arg2,arg3,arg4,arg5,arg6)519 void Fatal_Error(msg, arg0,arg1,arg2,arg3,arg4,arg5,arg6)
520 char *msg;
521 char *arg0, *arg1, *arg2, *arg3, *arg4, *arg5, *arg6;
522 {
523 fflush(stdout);
524 fflush(stderr);
525 fprintf(stderr, "%s: error: ", program_name);
526 fprintf(stderr, msg, arg0, arg1, arg2, arg3, arg4, arg5, arg6);
527 fprintf(stderr, "\n");
528 exit(1);
529 }
530