dsimple.c revision ff7e0acc
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 writing 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/*
64 * Get_Display_Name (argc, argv) Look for -display, -d, or host:dpy (obselete)
65 * If found, remove it from command line.  Don't go past a lone -.
66 */
67char *Get_Display_Name(
68    int *pargc,  /* MODIFIED */
69    char **argv) /* MODIFIED */
70{
71    int argc = *pargc;
72    char **pargv = argv+1;
73    char *displayname = NULL;
74    int i;
75
76    for (i = 1; i < argc; i++) {
77	char *arg = argv[i];
78
79	if (!strcmp (arg, "-display") || !strcmp (arg, "-d")) {
80	    if (++i >= argc) usage ();
81
82	    displayname = argv[i];
83	    *pargc -= 2;
84	    continue;
85	}
86	if (!strcmp(arg,"-")) {
87		while (i<argc)
88			*pargv++ = argv[i++];
89		break;
90	}
91	*pargv++ = arg;
92    }
93
94    *pargv = NULL;
95    return (displayname);
96}
97
98
99
100/*
101 * Open_Display: Routine to open a display with correct error handling.
102 *               Does not require dpy or screen defined on entry.
103 */
104Display *Open_Display(char *display_name)
105{
106	Display *d;
107
108	d = XOpenDisplay(display_name);
109	if (d == NULL) {
110	    fprintf (stderr, "%s:  unable to open display '%s'\n",
111		     program_name, XDisplayName (display_name));
112	    usage ();
113	    /* doesn't return */
114	}
115
116	return(d);
117}
118
119
120/*
121 * Setup_Display_And_Screen: This routine opens up the correct display (i.e.,
122 *                           it calls Get_Display_Name) and then stores a
123 *                           pointer to it in dpy.  The default screen
124 *                           for this display is then stored in screen.
125 *                           Does not require dpy or screen defined.
126 */
127void Setup_Display_And_Screen(
128    int *argc,      /* MODIFIED */
129    char **argv)    /* MODIFIED */
130{
131	char *displayname = NULL;
132
133        displayname = Get_Display_Name(argc, argv);
134	dpy = Open_Display (displayname);
135	screen = XDefaultScreen(dpy);
136}
137
138/*
139 * Close_Display: Close display
140 */
141void Close_Display(void)
142{
143    if (dpy == NULL)
144      return;
145
146    XCloseDisplay(dpy);
147    dpy = NULL;
148}
149
150
151/*
152 * Select_Window_Args: a rountine to provide a common interface for
153 *                     applications that need to allow the user to select one
154 *                     window on the screen for special consideration.
155 *                     This routine implements the following command line
156 *                     arguments:
157 *
158 *                       -root            Selects the root window.
159 *                       -id <id>         Selects window with id <id>. <id> may
160 *                                        be either in decimal or hex.
161 *                       -name <name>     Selects the window with name <name>.
162 *
163 *                     Call as Select_Window_Args(&argc, argv) in main before
164 *                     parsing any of your program's command line arguments.
165 *                     Select_Window_Args will remove its arguments so that
166 *                     your program does not have to worry about them.
167 *                     The window returned is the window selected or 0 if
168 *                     none of the above arguments was present.  If 0 is
169 *                     returned, Select_Window should probably be called after
170 *                     all command line arguments, and other setup is done.
171 *                     For examples of usage, see xwininfo, xwd, or xprop.
172 */
173Window Select_Window_Args(
174    int *rargc,
175    char **argv)
176#define ARGC (*rargc)
177{
178	int nargc=1;
179	int argc;
180	char **nargv;
181	Window w=0;
182
183	nargv = argv+1; argc = ARGC;
184#define OPTION argv[0]
185#define NXTOPTP ++argv, --argc>0
186#define NXTOPT if (++argv, --argc==0) usage()
187#define COPYOPT nargv++[0]=OPTION, nargc++
188
189	while (NXTOPTP) {
190		if (!strcmp(OPTION, "-")) {
191			COPYOPT;
192			while (NXTOPTP)
193			  COPYOPT;
194			break;
195		}
196		if (!strcmp(OPTION, "-root")) {
197			w=RootWindow(dpy, screen);
198			continue;
199		}
200		if (!strcmp(OPTION, "-name")) {
201			NXTOPT;
202			w = Window_With_Name(dpy, RootWindow(dpy, screen),
203					     OPTION);
204			if (!w)
205			  Fatal_Error("No window with name %s exists!",OPTION);
206			continue;
207		}
208		if (!strcmp(OPTION, "-id")) {
209			NXTOPT;
210			w=0;
211			sscanf(OPTION, "0x%lx", &w);
212			if (!w)
213			  sscanf(OPTION, "%lu", &w);
214			if (!w)
215			  Fatal_Error("Invalid window id format: %s.", OPTION);
216			continue;
217		}
218		COPYOPT;
219	}
220	ARGC = nargc;
221
222	return(w);
223}
224
225/*
226 * Other_stuff: A group of routines which do common X11 tasks.
227 *
228 * Written by Mark Lillibridge.   Last updated 7/1/87
229 */
230
231
232/*
233 * Routine to let user select a window using the mouse
234 */
235
236Window Select_Window(Display *dpy)
237{
238  int status;
239  Cursor cursor;
240  XEvent event;
241  Window target_win = None, root = RootWindow(dpy,screen);
242  int buttons = 0;
243
244  /* Make the target cursor */
245  cursor = XCreateFontCursor(dpy, XC_crosshair);
246
247  /* Grab the pointer using target cursor, letting it room all over */
248  status = XGrabPointer(dpy, root, False,
249			ButtonPressMask|ButtonReleaseMask, GrabModeSync,
250			GrabModeAsync, root, cursor, CurrentTime);
251  if (status != GrabSuccess) Fatal_Error("Can't grab the mouse.");
252
253  /* Let the user select a window... */
254  while ((target_win == None) || (buttons != 0)) {
255    /* allow one more event */
256    XAllowEvents(dpy, SyncPointer, CurrentTime);
257    XWindowEvent(dpy, root, ButtonPressMask|ButtonReleaseMask, &event);
258    switch (event.type) {
259    case ButtonPress:
260      if (target_win == None) {
261	target_win = event.xbutton.subwindow; /* window selected */
262	if (target_win == None) target_win = root;
263      }
264      buttons++;
265      break;
266    case ButtonRelease:
267      if (buttons > 0) /* there may have been some down before we started */
268	buttons--;
269       break;
270    }
271  }
272
273  XUngrabPointer(dpy, CurrentTime);      /* Done with pointer */
274
275  return(target_win);
276}
277
278
279/*
280 * Window_With_Name: routine to locate a window with a given name on a display.
281 *                   If no window with the given name is found, 0 is returned.
282 *                   If more than one window has the given name, the first
283 *                   one found will be returned.  Only top and its subwindows
284 *                   are looked at.  Normally, top should be the RootWindow.
285 */
286Window Window_With_Name(
287    Display *dpy,
288    Window top,
289    char *name)
290{
291	Window *children, dummy;
292	unsigned int nchildren;
293	int i;
294	Window w=0;
295	char *window_name;
296
297	if (XFetchName(dpy, top, &window_name) && !strcmp(window_name, name))
298	  return(top);
299
300	if (!XQueryTree(dpy, top, &dummy, &dummy, &children, &nchildren))
301	  return(0);
302
303	for (i=0; i<nchildren; i++) {
304		w = Window_With_Name(dpy, children[i], name);
305		if (w)
306		  break;
307	}
308	if (children) XFree ((char *)children);
309	return(w);
310}
311
312
313/*
314 * Standard fatal error routine - call like printf
315 * Does not require dpy or screen defined.
316 */
317void Fatal_Error(char *msg, ...)
318{
319	va_list args;
320	fflush(stdout);
321	fflush(stderr);
322	fprintf(stderr, "%s: error: ", program_name);
323	va_start(args, msg);
324	vfprintf(stderr, msg, args);
325	va_end(args);
326	fprintf(stderr, "\n");
327        Close_Display();
328	exit(EXIT_FAILURE);
329}
330