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