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