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