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