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