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/* 38 * Other_stuff.h: Definitions of routines in other_stuff. 39 * 40 * Written by Mark Lillibridge. Last updated 7/1/87 41 */ 42 43#include "clientwin.h" 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 */ 58const char *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 (obsolete) 65 * If found, remove it from command line. Don't go past a lone -. 66 */ 67char * 68Get_Display_Name(int *pargc, /* MODIFIED */ 69 char **argv) /* MODIFIED */ 70{ 71 int argc = *pargc; 72 char **pargv = argv + 1; 73 char *displayname = NULL; 74 75 for (int i = 1; i < argc; i++) { 76 char *arg = argv[i]; 77 78 if (!strcmp(arg, "-display") || !strcmp(arg, "-d")) { 79 if (++i >= argc) 80 usage("-display requires an argument", EXIT_FAILURE); 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 * Open_Display: Routine to open a display with correct error handling. 101 * Does not require dpy or screen defined on entry. 102 */ 103Display * 104Open_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 exit(1); 113 } 114 115 return (d); 116} 117 118 119/* 120 * Setup_Display_And_Screen: This routine opens up the correct display (i.e., 121 * it calls Get_Display_Name) and then stores a 122 * pointer to it in dpy. The default screen 123 * for this display is then stored in screen. 124 * Does not require dpy or screen defined. 125 */ 126void 127Setup_Display_And_Screen(int *argc, /* MODIFIED */ 128 char **argv) /* MODIFIED */ 129{ 130 char *displayname = NULL; 131 132 displayname = Get_Display_Name(argc, argv); 133 dpy = Open_Display(displayname); 134 screen = XDefaultScreen(dpy); 135} 136 137/* 138 * Close_Display: Close display 139 */ 140void 141Close_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 routine 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 174Select_Window_Args(int *rargc, char **argv) 175#define ARGC (*rargc) 176{ 177 int nargc = 1; 178 int argc; 179 char **nargv; 180 Window w = 0; 181 182 nargv = argv + 1; 183 argc = ARGC; 184 185#define OPTION argv[0] 186#define NXTOPTP ++argv, --argc>0 187#define NXTOPT(arg) if (++argv, --argc==0) \ 188 usage(arg " requires an argument", EXIT_FAILURE) 189#define COPYOPT nargv++[0]=OPTION, nargc++ 190 191 while (NXTOPTP) { 192 if (!strcmp(OPTION, "-")) { 193 COPYOPT; 194 while (NXTOPTP) 195 COPYOPT; 196 break; 197 } 198 if (!strcmp(OPTION, "-root")) { 199 w = RootWindow(dpy, screen); 200 continue; 201 } 202 if (!strcmp(OPTION, "-name")) { 203 NXTOPT("-name"); 204 w = Window_With_Name(dpy, RootWindow(dpy, screen), OPTION); 205 if (!w) 206 Fatal_Error("No window with name %s exists!", OPTION); 207 continue; 208 } 209 if (!strcmp(OPTION, "-id")) { 210 NXTOPT("-id"); 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 238Select_Window(Display *disp, int descend) 239{ 240 int status; 241 Cursor cursor; 242 XEvent event; 243 Window target_win = None, root = RootWindow(disp, screen); 244 int buttons = 0; 245 246 /* Make the target cursor */ 247 cursor = XCreateFontCursor(disp, XC_crosshair); 248 249 /* Grab the pointer using target cursor, letting it room all over */ 250 status = XGrabPointer(disp, root, False, 251 ButtonPressMask | ButtonReleaseMask, GrabModeSync, 252 GrabModeAsync, root, cursor, CurrentTime); 253 if (status != GrabSuccess) 254 Fatal_Error("Can't grab the mouse."); 255 256 /* Let the user select a window... */ 257 while ((target_win == None) || (buttons != 0)) { 258 /* allow one more event */ 259 XAllowEvents(disp, SyncPointer, CurrentTime); 260 XWindowEvent(disp, root, ButtonPressMask | ButtonReleaseMask, &event); 261 switch (event.type) { 262 case ButtonPress: 263 if (target_win == None) { 264 target_win = event.xbutton.subwindow; /* window selected */ 265 if (target_win == None) 266 target_win = root; 267 } 268 buttons++; 269 break; 270 case ButtonRelease: 271 if (buttons > 0) /* there may have been some down before we started */ 272 buttons--; 273 break; 274 } 275 } 276 277 XUngrabPointer(disp, CurrentTime); /* Done with pointer */ 278 279 if (!descend || (target_win == root)) 280 return (target_win); 281 282 target_win = Find_Client(disp, root, target_win); 283 284 return (target_win); 285} 286 287 288/* 289 * Window_With_Name: routine to locate a window with a given name on a display. 290 * If no window with the given name is found, 0 is returned. 291 * If more than one window has the given name, the first 292 * one found will be returned. Only top and its subwindows 293 * are looked at. Normally, top should be the RootWindow. 294 */ 295Window 296Window_With_Name(Display *disp, Window top, const char *name) 297{ 298 Window *children, dummy; 299 unsigned int nchildren; 300 unsigned int i; 301 Window w = 0; 302 char *window_name; 303 304 if (XFetchName(disp, top, &window_name) && !strcmp(window_name, name)) 305 return (top); 306 307 if (!XQueryTree(disp, top, &dummy, &dummy, &children, &nchildren)) 308 return (0); 309 310 for (i = 0; i < nchildren; i++) { 311 w = Window_With_Name(disp, children[i], name); 312 if (w) 313 break; 314 } 315 316 if (children) 317 XFree((char *) children); 318 319 return (w); 320} 321 322/* 323 * outl: a debugging routine. Flushes stdout then prints a message on stderr 324 * and flushes stderr. Used to print messages when past certain points 325 * in code so we can tell where we are. Outl may be invoked like printf. 326 */ 327void 328outl(const char *msg, ...) 329{ 330 va_list args; 331 332 fflush(stdout); 333 va_start(args, msg); 334 vfprintf(stderr, msg, args); 335 va_end(args); 336 fprintf(stderr, "\n"); 337 fflush(stderr); 338} 339 340/* 341 * Standard fatal error routine - call like printf. 342 * Does not require dpy or screen defined. 343 */ 344void 345Fatal_Error(const char *msg, ...) 346{ 347 va_list args; 348 349 fflush(stdout); 350 fflush(stderr); 351 fprintf(stderr, "%s: error: ", program_name); 352 va_start(args, msg); 353 vfprintf(stderr, msg, args); 354 va_end(args); 355 fprintf(stderr, "\n"); 356 Close_Display(); 357 exit(EXIT_FAILURE); 358} 359