dsimple.c revision b3307321
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#ifdef BUILD_PRINTSUPPORT 45#include <X11/XprintUtil/xprintutil.h> 46#endif /* BUILD_PRINTSUPPORT */ 47#include "dsimple.h" 48 49/* 50 * Just_display: A group of routines designed to make the writting of simple 51 * X11 applications which open a display but do not open 52 * any windows much faster and easier. Unless a routine says 53 * otherwise, it may be assumed to require program_name, dpy, 54 * and screen already defined on entry. 55 * 56 * Written by Mark Lillibridge. Last updated 7/1/87 57 */ 58 59 60/* This stuff is defined in the calling program by just_display.h */ 61char *program_name = "unknown_program"; 62Display *dpy = NULL; 63int screen = 0; 64Bool printer_output = False; /* Video or printer output ? */ 65#ifdef BUILD_PRINTSUPPORT 66XPContext pcontext = None; 67#endif /* BUILD_PRINTSUPPORT */ 68 69static void _bitmap_error(int, char *); 70 71/* 72 * Malloc: like malloc but handles out of memory using Fatal_Error. 73 */ 74char *Malloc(size) 75 unsigned size; 76{ 77 char *data; 78 79 if (!(data = malloc(size))) 80 Fatal_Error("Out of memory!"); 81 82 return(data); 83} 84 85 86/* 87 * Realloc: like Malloc except for realloc, handles NULL using Malloc. 88 */ 89char *Realloc(ptr, size) 90 char *ptr; 91 int size; 92{ 93 char *new_ptr; 94 95 if (!ptr) 96 return(Malloc(size)); 97 98 if (!(new_ptr = realloc(ptr, size))) 99 Fatal_Error("Out of memory!"); 100 101 return(new_ptr); 102} 103 104 105/* 106 * Get_Display_Name (argc, argv) Look for -display, -d, or host:dpy (obselete) 107 * If found, remove it from command line. Don't go past a lone -. 108 */ 109char *Get_Display_Name(pargc, argv) 110 int *pargc; /* MODIFIED */ 111 char **argv; /* MODIFIED */ 112{ 113 int argc = *pargc; 114 char **pargv = argv+1; 115 char *displayname = NULL; 116 int i; 117 118 for (i = 1; i < argc; i++) { 119 char *arg = argv[i]; 120 121 if (!strcmp (arg, "-display") || !strcmp (arg, "-d")) { 122 if (++i >= argc) usage (); 123 124 displayname = argv[i]; 125 *pargc -= 2; 126 continue; 127 } 128 if (!strcmp(arg,"-")) { 129 while (i<argc) 130 *pargv++ = argv[i++]; 131 break; 132 } 133 *pargv++ = arg; 134 } 135 136 *pargv = NULL; 137 return (displayname); 138} 139 140 141#ifdef BUILD_PRINTSUPPORT 142/* 143 * Get_Printer_Name (argc, argv) Look for -printer, -p, 144 * If found, remove it from command line. Don't go past a lone -. 145 */ 146char *Get_Printer_Name(pargc, argv) 147 int *pargc; /* MODIFIED */ 148 char **argv; /* MODIFIED */ 149{ 150 int argc = *pargc; 151 char **pargv = argv+1; 152 char *printername = NULL; 153 int i; 154 155 for (i = 1; i < argc; i++) { 156 char *arg = argv[i]; 157 158 if (!strcmp (arg, "-printer") || !strcmp (arg, "-p")) { 159 if (++i >= argc) usage (); 160 161 printername = argv[i]; 162 *pargc -= 2; 163 continue; 164 } 165 if (!strcmp(arg,"-")) { 166 while (i<argc) 167 *pargv++ = argv[i++]; 168 break; 169 } 170 *pargv++ = arg; 171 } 172 173 *pargv = NULL; 174 return (printername); 175} 176#endif /* BUILD_PRINTSUPPORT */ 177 178/* 179 * Open_Display: Routine to open a display with correct error handling. 180 * Does not require dpy or screen defined on entry. 181 */ 182Display *Open_Display(display_name) 183char *display_name; 184{ 185 Display *d; 186 187 d = XOpenDisplay(display_name); 188 if (d == NULL) { 189 fprintf (stderr, "%s: unable to open display '%s'\n", 190 program_name, XDisplayName (display_name)); 191 usage (); 192 /* doesn't return */ 193 } 194 195 return(d); 196} 197 198 199/* 200 * Setup_Display_And_Screen: This routine opens up the correct display (i.e., 201 * it calls Get_Display_Name) and then stores a 202 * pointer to it in dpy. The default screen 203 * for this display is then stored in screen. 204 * Does not require dpy or screen defined. 205 */ 206void Setup_Display_And_Screen(argc, argv) 207int *argc; /* MODIFIED */ 208char **argv; /* MODIFIED */ 209{ 210 char *displayname = NULL, 211 *printername = NULL; 212 213 displayname = Get_Display_Name(argc, argv); 214#ifdef BUILD_PRINTSUPPORT 215 printername = Get_Printer_Name(argc, argv); 216 217 if (displayname && printername) { 218 fprintf (stderr, "%s: you cannot specify -printer (-p) and -display (-d) at the same time.\n", 219 program_name); 220 usage (); 221 } 222 223 if (printername) { 224 printer_output = True; 225 226 if (XpuGetPrinter(printername, &dpy, &pcontext) != 1) { 227 fprintf(stderr, "%s: Cannot open printer '%s'.\n", program_name, printername); 228 exit(EXIT_FAILURE); 229 } 230 231 screen = XScreenNumberOfScreen(XpGetScreenOfContext(dpy, pcontext)); 232 } 233 else 234#endif /* BUILD_PRINTSUPPORT */ 235 { 236 printer_output = False; 237 238 dpy = Open_Display (displayname); 239 screen = XDefaultScreen(dpy); 240 } 241} 242 243/* 244 * Close_Display: Close display 245 */ 246void Close_Display(void) 247{ 248 if (dpy == NULL) 249 return; 250 251#ifdef BUILD_PRINTSUPPORT 252 if (printer_output) { 253 XpuClosePrinterDisplay(dpy, pcontext); 254 dpy = NULL; 255 pcontext = None; 256 printer_output = False; 257 } 258 else 259#endif /* BUILD_PRINTSUPPORT */ 260 { 261 XCloseDisplay(dpy); 262 dpy = NULL; 263 } 264} 265 266 267/* 268 * Open_Font: This routine opens a font with error handling. 269 */ 270XFontStruct *Open_Font(name) 271char *name; 272{ 273 XFontStruct *font; 274 275 if (!(font=XLoadQueryFont(dpy, name))) 276 Fatal_Error("Unable to open font %s!", name); 277 278 return(font); 279} 280 281 282/* 283 * Beep: Routine to beep the display. 284 */ 285void Beep() 286{ 287 XBell(dpy, 50); 288} 289 290 291/* 292 * ReadBitmapFile: same as XReadBitmapFile except it returns the bitmap 293 * directly and handles errors using Fatal_Error. 294 */ 295static void _bitmap_error(status, filename) 296 int status; 297 char *filename; 298{ 299 if (status == BitmapOpenFailed) 300 Fatal_Error("Can't open file %s!", filename); 301 else if (status == BitmapFileInvalid) 302 Fatal_Error("file %s: Bad bitmap format.", filename); 303 else 304 Fatal_Error("Out of memory!"); 305} 306 307Pixmap ReadBitmapFile(d, filename, width, height, x_hot, y_hot) 308 Drawable d; 309 char *filename; 310 int *width, *height, *x_hot, *y_hot; 311{ 312 Pixmap bitmap; 313 int status; 314 315 status = XReadBitmapFile(dpy, RootWindow(dpy, screen), filename, 316 (unsigned int *)width, (unsigned int *)height, 317 &bitmap, x_hot, y_hot); 318 if (status != BitmapSuccess) 319 _bitmap_error(status, filename); 320 321 return(bitmap); 322} 323 324 325/* 326 * WriteBitmapFile: same as XWriteBitmapFile except it handles errors 327 * using Fatal_Error. 328 */ 329void WriteBitmapFile(filename, bitmap, width, height, x_hot, y_hot) 330 char *filename; 331 Pixmap bitmap; 332 int width, height, x_hot, y_hot; 333{ 334 int status; 335 336 status= XWriteBitmapFile(dpy, filename, bitmap, width, height, x_hot, 337 y_hot); 338 if (status != BitmapSuccess) 339 _bitmap_error(status, filename); 340} 341 342 343/* 344 * Select_Window_Args: a rountine to provide a common interface for 345 * applications that need to allow the user to select one 346 * window on the screen for special consideration. 347 * This routine implements the following command line 348 * arguments: 349 * 350 * -root Selects the root window. 351 * -id <id> Selects window with id <id>. <id> may 352 * be either in decimal or hex. 353 * -name <name> Selects the window with name <name>. 354 * 355 * Call as Select_Window_Args(&argc, argv) in main before 356 * parsing any of your program's command line arguments. 357 * Select_Window_Args will remove its arguments so that 358 * your program does not have to worry about them. 359 * The window returned is the window selected or 0 if 360 * none of the above arguments was present. If 0 is 361 * returned, Select_Window should probably be called after 362 * all command line arguments, and other setup is done. 363 * For examples of usage, see xwininfo, xwd, or xprop. 364 */ 365Window Select_Window_Args(rargc, argv) 366 int *rargc; 367 char **argv; 368#define ARGC (*rargc) 369{ 370 int nargc=1; 371 int argc; 372 char **nargv; 373 Window w=0; 374 375 nargv = argv+1; argc = ARGC; 376#define OPTION argv[0] 377#define NXTOPTP ++argv, --argc>0 378#define NXTOPT if (++argv, --argc==0) usage() 379#define COPYOPT nargv++[0]=OPTION, nargc++ 380 381 while (NXTOPTP) { 382 if (!strcmp(OPTION, "-")) { 383 COPYOPT; 384 while (NXTOPTP) 385 COPYOPT; 386 break; 387 } 388 if (!strcmp(OPTION, "-root")) { 389 w=RootWindow(dpy, screen); 390 continue; 391 } 392 if (!strcmp(OPTION, "-name")) { 393 NXTOPT; 394 w = Window_With_Name(dpy, RootWindow(dpy, screen), 395 OPTION); 396 if (!w) 397 Fatal_Error("No window with name %s exists!",OPTION); 398 continue; 399 } 400 if (!strcmp(OPTION, "-id")) { 401 NXTOPT; 402 w=0; 403 sscanf(OPTION, "0x%lx", &w); 404 if (!w) 405 sscanf(OPTION, "%lu", &w); 406 if (!w) 407 Fatal_Error("Invalid window id format: %s.", OPTION); 408 continue; 409 } 410 COPYOPT; 411 } 412 ARGC = nargc; 413 414 return(w); 415} 416 417/* 418 * Other_stuff: A group of routines which do common X11 tasks. 419 * 420 * Written by Mark Lillibridge. Last updated 7/1/87 421 */ 422 423/* 424 * Resolve_Color: This routine takes a color name and returns the pixel # 425 * that when used in the window w will be of color name. 426 * (WARNING: The colormap of w MAY be modified! ) 427 * If colors are run out of, only the first n colors will be 428 * as correct as the hardware can make them where n depends 429 * on the display. This routine does not require wind to 430 * be defined. 431 */ 432unsigned long Resolve_Color(w, name) 433 Window w; 434 char *name; 435{ 436 XColor c; 437 Colormap colormap; 438 XWindowAttributes wind_info; 439 440 /* 441 * The following is a hack to insure machines without a rgb table 442 * handle at least white & black right. 443 */ 444 if (!strcmp(name, "white")) 445 name="#ffffffffffff"; 446 if (!strcmp(name, "black")) 447 name="#000000000000"; 448 449 XGetWindowAttributes(dpy, w, &wind_info); 450 colormap = wind_info.colormap; 451 452 if (!XParseColor(dpy, colormap, name, &c)) 453 Fatal_Error("Bad color format '%s'.", name); 454 455 if (!XAllocColor(dpy, colormap, &c)) 456 Fatal_Error("XAllocColor failed!"); 457 458 return(c.pixel); 459} 460 461 462/* 463 * Bitmap_To_Pixmap: Convert a bitmap to a 2 colored pixmap. The colors come 464 * from the foreground and background colors of the gc. 465 * Width and height are required solely for efficiency. 466 * If needed, they can be obtained via. XGetGeometry. 467 */ 468Pixmap Bitmap_To_Pixmap(dpy, d, gc, bitmap, width, height) 469 Display *dpy; 470 Drawable d; 471 GC gc; 472 Pixmap bitmap; 473 int width, height; 474{ 475 Pixmap pix; 476 int x; 477 unsigned int i, depth; 478 Drawable root; 479 480 if (!XGetGeometry(dpy, d, &root, &x, &x, &i, &i, &i, &depth)) 481 return(0); 482 483 pix = XCreatePixmap(dpy, d, width, height, (int)depth); 484 485 XCopyPlane(dpy, bitmap, pix, gc, 0, 0, width, height, 0, 0, 1); 486 487 return(pix); 488} 489 490 491/* 492 * blip: a debugging routine. Prints Blip! on stderr with flushing. 493 */ 494void blip() 495{ 496 fflush(stdout); 497 fprintf(stderr, "blip!\n"); 498 fflush(stderr); 499} 500 501 502/* 503 * Routine to let user select a window using the mouse 504 */ 505 506Window Select_Window(dpy) 507 Display *dpy; 508{ 509 int status; 510 Cursor cursor; 511 XEvent event; 512 Window target_win = None, root = RootWindow(dpy,screen); 513 int buttons = 0; 514 515 /* Make the target cursor */ 516 cursor = XCreateFontCursor(dpy, XC_crosshair); 517 518 /* Grab the pointer using target cursor, letting it room all over */ 519 status = XGrabPointer(dpy, root, False, 520 ButtonPressMask|ButtonReleaseMask, GrabModeSync, 521 GrabModeAsync, root, cursor, CurrentTime); 522 if (status != GrabSuccess) Fatal_Error("Can't grab the mouse."); 523 524 /* Let the user select a window... */ 525 while ((target_win == None) || (buttons != 0)) { 526 /* allow one more event */ 527 XAllowEvents(dpy, SyncPointer, CurrentTime); 528 XWindowEvent(dpy, root, ButtonPressMask|ButtonReleaseMask, &event); 529 switch (event.type) { 530 case ButtonPress: 531 if (target_win == None) { 532 target_win = event.xbutton.subwindow; /* window selected */ 533 if (target_win == None) target_win = root; 534 } 535 buttons++; 536 break; 537 case ButtonRelease: 538 if (buttons > 0) /* there may have been some down before we started */ 539 buttons--; 540 break; 541 } 542 } 543 544 XUngrabPointer(dpy, CurrentTime); /* Done with pointer */ 545 546 return(target_win); 547} 548 549 550/* 551 * Window_With_Name: routine to locate a window with a given name on a display. 552 * If no window with the given name is found, 0 is returned. 553 * If more than one window has the given name, the first 554 * one found will be returned. Only top and its subwindows 555 * are looked at. Normally, top should be the RootWindow. 556 */ 557Window Window_With_Name(dpy, top, name) 558 Display *dpy; 559 Window top; 560 char *name; 561{ 562 Window *children, dummy; 563 unsigned int nchildren; 564 int i; 565 Window w=0; 566 char *window_name; 567 568 if (XFetchName(dpy, top, &window_name) && !strcmp(window_name, name)) 569 return(top); 570 571 if (!XQueryTree(dpy, top, &dummy, &dummy, &children, &nchildren)) 572 return(0); 573 574 for (i=0; i<nchildren; i++) { 575 w = Window_With_Name(dpy, children[i], name); 576 if (w) 577 break; 578 } 579 if (children) XFree ((char *)children); 580 return(w); 581} 582 583/* 584 * outl: a debugging routine. Flushes stdout then prints a message on stderr 585 * and flushes stderr. Used to print messages when past certain points 586 * in code so we can tell where we are. Outl may be invoked like 587 * printf with up to 7 arguments. 588 */ 589void 590outl(char *msg, ...) 591{ 592 va_list args; 593 fflush(stdout); 594 va_start(args, msg); 595 vfprintf(stderr, msg, args); 596 va_end(args); 597 fprintf(stderr, "\n"); 598 fflush(stderr); 599} 600 601 602/* 603 * Standard fatal error routine - call like printf but maximum of 7 arguments. 604 * Does not require dpy or screen defined. 605 */ 606void Fatal_Error(char *msg, ...) 607{ 608 va_list args; 609 fflush(stdout); 610 fflush(stderr); 611 fprintf(stderr, "%s: error: ", program_name); 612 va_start(args, msg); 613 vfprintf(stderr, msg, args); 614 va_end(args); 615 fprintf(stderr, "\n"); 616 Close_Display(); 617 exit(EXIT_FAILURE); 618} 619