dsimple.c revision fc89c0fb
1/* $Xorg: dsimple.c,v 1.4 2001/02/09 02:05:54 xorgcvs Exp $ */
2/*
3
4Copyright 1993, 1998  The Open Group
5
6Permission to use, copy, modify, distribute, and sell this software and its
7documentation for any purpose is hereby granted without fee, provided that
8the above copyright notice appear in all copies and that both that
9copyright notice and this permission notice appear in supporting
10documentation.
11
12The above copyright notice and this permission notice shall be included
13in all copies or substantial portions of the Software.
14
15THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
16OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
17MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
18IN NO EVENT SHALL THE OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR
19OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
20ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
21OTHER DEALINGS IN THE SOFTWARE.
22
23Except as contained in this notice, the name of The Open Group shall
24not be used in advertising or otherwise to promote the sale, use or
25other dealings in this Software without prior written authorization
26from 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 */
58char    *program_name = "unknown_program";
59Display *dpy = NULL;
60int      screen = 0;
61
62/*
63 * Malloc: like malloc but handles out of memory using Fatal_Error.
64 */
65char *Malloc(unsigned 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 * Get_Display_Name (argc, argv) Look for -display, -d, or host:dpy (obselete)
78 * If found, remove it from command line.  Don't go past a lone -.
79 */
80char *Get_Display_Name(
81    int *pargc,  /* MODIFIED */
82    char **argv) /* MODIFIED */
83{
84    int argc = *pargc;
85    char **pargv = argv+1;
86    char *displayname = NULL;
87    int i;
88
89    for (i = 1; i < argc; i++) {
90	char *arg = argv[i];
91
92	if (!strcmp (arg, "-display") || !strcmp (arg, "-d")) {
93	    if (++i >= argc) usage ();
94
95	    displayname = argv[i];
96	    *pargc -= 2;
97	    continue;
98	}
99	if (!strcmp(arg,"-")) {
100		while (i<argc)
101			*pargv++ = argv[i++];
102		break;
103	}
104	*pargv++ = arg;
105    }
106
107    *pargv = NULL;
108    return (displayname);
109}
110
111
112
113/*
114 * Open_Display: Routine to open a display with correct error handling.
115 *               Does not require dpy or screen defined on entry.
116 */
117Display *Open_Display(const char *display_name)
118{
119	Display *d;
120
121	d = XOpenDisplay(display_name);
122	if (d == NULL) {
123	    fprintf (stderr, "%s:  unable to open display '%s'\n",
124		     program_name, XDisplayName (display_name));
125	    usage ();
126	    /* doesn't return */
127	}
128
129	return(d);
130}
131
132
133/*
134 * Setup_Display_And_Screen: This routine opens up the correct display (i.e.,
135 *                           it calls Get_Display_Name) and then stores a
136 *                           pointer to it in dpy.  The default screen
137 *                           for this display is then stored in screen.
138 *                           Does not require dpy or screen defined.
139 */
140void Setup_Display_And_Screen(
141    int *argc,      /* MODIFIED */
142    char **argv)    /* MODIFIED */
143{
144        char *displayname = NULL;
145
146        displayname = Get_Display_Name(argc, argv);
147        dpy = Open_Display (displayname);
148        screen = XDefaultScreen(dpy);
149}
150
151/*
152 * Close_Display: Close display
153 */
154void Close_Display(void)
155{
156    if (dpy == NULL)
157      return;
158
159    XCloseDisplay(dpy);
160    dpy = NULL;
161}
162
163
164/*
165 * Open_Font: This routine opens a font with error handling.
166 */
167XFontStruct *Open_Font(const char *name)
168{
169	XFontStruct *font;
170
171	if (!(font=XLoadQueryFont(dpy, name)))
172	  Fatal_Error("Unable to open font %s!", name);
173
174	return(font);
175}
176
177
178
179
180/*
181 * Select_Window_Args: a rountine to provide a common interface for
182 *                     applications that need to allow the user to select one
183 *                     window on the screen for special consideration.
184 *                     This routine implements the following command line
185 *                     arguments:
186 *
187 *                       -root            Selects the root window.
188 *                       -id <id>         Selects window with id <id>. <id> may
189 *                                        be either in decimal or hex.
190 *                       -name <name>     Selects the window with name <name>.
191 *
192 *                     Call as Select_Window_Args(&argc, argv) in main before
193 *                     parsing any of your program's command line arguments.
194 *                     Select_Window_Args will remove its arguments so that
195 *                     your program does not have to worry about them.
196 *                     The window returned is the window selected or 0 if
197 *                     none of the above arguments was present.  If 0 is
198 *                     returned, Select_Window should probably be called after
199 *                     all command line arguments, and other setup is done.
200 *                     For examples of usage, see xwininfo, xwd, or xprop.
201 */
202Window Select_Window_Args(
203    int *rargc,
204    char **argv)
205#define ARGC (*rargc)
206{
207	int nargc=1;
208	int argc;
209	char **nargv;
210	Window w=0;
211
212	nargv = argv+1; argc = ARGC;
213#define OPTION argv[0]
214#define NXTOPTP ++argv, --argc>0
215#define NXTOPT if (++argv, --argc==0) usage()
216#define COPYOPT nargv++[0]=OPTION, nargc++
217
218	while (NXTOPTP) {
219		if (!strcmp(OPTION, "-")) {
220			COPYOPT;
221			while (NXTOPTP)
222			  COPYOPT;
223			break;
224		}
225		if (!strcmp(OPTION, "-root")) {
226			w=RootWindow(dpy, screen);
227			continue;
228		}
229		if (!strcmp(OPTION, "-name")) {
230			NXTOPT;
231			w = Window_With_Name(dpy, RootWindow(dpy, screen),
232					     OPTION);
233			if (!w)
234			  Fatal_Error("No window with name %s exists!",OPTION);
235			continue;
236		}
237		if (!strcmp(OPTION, "-id")) {
238			NXTOPT;
239			w=0;
240			sscanf(OPTION, "0x%lx", &w);
241			if (!w)
242			  sscanf(OPTION, "%lu", &w);
243			if (!w)
244			  Fatal_Error("Invalid window id format: %s.", OPTION);
245			continue;
246		}
247		COPYOPT;
248	}
249	ARGC = nargc;
250
251	return(w);
252}
253
254/*
255 * Other_stuff: A group of routines which do common X11 tasks.
256 *
257 * Written by Mark Lillibridge.   Last updated 7/1/87
258 */
259
260
261
262/*
263 * Routine to let user select a window using the mouse
264 */
265
266Window Select_Window(Display *dpy)
267{
268  int status;
269  Cursor cursor;
270  XEvent event;
271  Window target_win = None, root = RootWindow(dpy,screen);
272  int buttons = 0;
273
274  /* Make the target cursor */
275  cursor = XCreateFontCursor(dpy, XC_crosshair);
276
277  /* Grab the pointer using target cursor, letting it room all over */
278  status = XGrabPointer(dpy, root, False,
279			ButtonPressMask|ButtonReleaseMask, GrabModeSync,
280			GrabModeAsync, root, cursor, CurrentTime);
281  if (status != GrabSuccess) Fatal_Error("Can't grab the mouse.");
282
283  /* Let the user select a window... */
284  while ((target_win == None) || (buttons != 0)) {
285    /* allow one more event */
286    XAllowEvents(dpy, SyncPointer, CurrentTime);
287    XWindowEvent(dpy, root, ButtonPressMask|ButtonReleaseMask, &event);
288    switch (event.type) {
289    case ButtonPress:
290      if (target_win == None) {
291	target_win = event.xbutton.subwindow; /* window selected */
292	if (target_win == None) target_win = root;
293      }
294      buttons++;
295      break;
296    case ButtonRelease:
297      if (buttons > 0) /* there may have been some down before we started */
298	buttons--;
299       break;
300    }
301  }
302
303  XUngrabPointer(dpy, CurrentTime);      /* Done with pointer */
304
305  return(target_win);
306}
307
308
309/*
310 * Window_With_Name: routine to locate a window with a given name on a display.
311 *                   If no window with the given name is found, 0 is returned.
312 *                   If more than one window has the given name, the first
313 *                   one found will be returned.  Only top and its subwindows
314 *                   are looked at.  Normally, top should be the RootWindow.
315 */
316Window Window_With_Name(
317    Display *dpy,
318    Window top,
319    const char *name)
320{
321	Window *children, dummy;
322	unsigned int nchildren;
323	int i;
324	Window w=0;
325	char *window_name;
326
327	if (XFetchName(dpy, top, &window_name) && !strcmp(window_name, name))
328	  return(top);
329
330	if (!XQueryTree(dpy, top, &dummy, &dummy, &children, &nchildren))
331	  return(0);
332
333	for (i=0; i<nchildren; i++) {
334		w = Window_With_Name(dpy, children[i], name);
335		if (w)
336		  break;
337	}
338	if (children) XFree ((char *)children);
339	return(w);
340}
341
342
343/*
344 * Standard fatal error routine - call like printf but maximum of 7 arguments.
345 * Does not require dpy or screen defined.
346 */
347void Fatal_Error(char *msg, ...)
348{
349	va_list args;
350	fflush(stdout);
351	fflush(stderr);
352	fprintf(stderr, "%s: error: ", program_name);
353	va_start(args, msg);
354	vfprintf(stderr, msg, args);
355	va_end(args);
356	fprintf(stderr, "\n");
357        Close_Display();
358	exit(EXIT_FAILURE);
359}
360