dsimple.c revision afe13c8e
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 writting 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 * 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(const 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, int descend)
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  if (!descend || (target_win == root))
276    return(target_win);
277
278  target_win = Find_Client(dpy, root, target_win);
279
280  return(target_win);
281}
282
283
284/*
285 * Window_With_Name: routine to locate a window with a given name on a display.
286 *                   If no window with the given name is found, 0 is returned.
287 *                   If more than one window has the given name, the first
288 *                   one found will be returned.  Only top and its subwindows
289 *                   are looked at.  Normally, top should be the RootWindow.
290 */
291Window Window_With_Name(
292    Display *dpy,
293    Window top,
294    const char *name)
295{
296	Window *children, dummy;
297	unsigned int nchildren;
298	int i;
299	Window w=0;
300	char *window_name;
301
302	if (XFetchName(dpy, top, &window_name) && !strcmp(window_name, name))
303	  return(top);
304
305	if (!XQueryTree(dpy, top, &dummy, &dummy, &children, &nchildren))
306	  return(0);
307
308	for (i=0; i<nchildren; i++) {
309		w = Window_With_Name(dpy, children[i], name);
310		if (w)
311		  break;
312	}
313	if (children) XFree ((char *)children);
314	return(w);
315}
316
317/*
318 * outl: a debugging routine.  Flushes stdout then prints a message on stderr
319 *       and flushes stderr.  Used to print messages when past certain points
320 *       in code so we can tell where we are.  Outl may be invoked like
321 *       printf with up to 7 arguments.
322 */
323void
324outl(char *msg, ...)
325{
326	va_list args;
327	fflush(stdout);
328	va_start(args, msg);
329	vfprintf(stderr, msg, args);
330	va_end(args);
331	fprintf(stderr, "\n");
332	fflush(stderr);
333}
334
335
336/*
337 * Standard fatal error routine - call like printf but maximum of 7 arguments.
338 * Does not require dpy or screen defined.
339 */
340void Fatal_Error(char *msg, ...)
341{
342	va_list args;
343	fflush(stdout);
344	fflush(stderr);
345	fprintf(stderr, "%s: error: ", program_name);
346	va_start(args, msg);
347	vfprintf(stderr, msg, args);
348	va_end(args);
349	fprintf(stderr, "\n");
350        Close_Display();
351	exit(EXIT_FAILURE);
352}
353