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