home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 January / usenetsourcesnewsgroupsinfomagicjanuary1994.iso / sources / x / volume8 / xiconw / part01 / dsimple.c < prev    next >
C/C++ Source or Header  |  1990-08-27  |  13KB  |  503 lines

  1. /* $XConsortium: dsimple.c,v 1.10 89/12/13 11:47:29 rws Exp $ */
  2. #include <X11/Xos.h>
  3. #include <X11/Xlib.h>
  4. #include <X11/Xutil.h>
  5. #include <X11/cursorfont.h>
  6. #include <stdio.h>
  7. /*
  8.  * Other_stuff.h: Definitions of routines in other_stuff.
  9.  *
  10.  * Written by Mark Lillibridge.   Last updated 7/1/87
  11.  *
  12.  * Send bugs, etc. to chariot@athena.mit.edu.
  13.  */
  14.  
  15. unsigned long Resolve_Color();
  16. Pixmap Bitmap_To_Pixmap();
  17. Window Select_Window();
  18. void out();
  19. void blip();
  20. Window Window_With_Name();
  21. void Fatal_Error();
  22.  
  23. /*
  24.  * Just_display: A group of routines designed to make the writting of simple
  25.  *               X11 applications which open a display but do not open
  26.  *               any windows much faster and easier.  Unless a routine says
  27.  *               otherwise, it may be assumed to require program_name, dpy,
  28.  *               and screen already defined on entry.
  29.  *
  30.  * Written by Mark Lillibridge.   Last updated 7/1/87
  31.  *
  32.  * Send bugs, etc. to chariot@athena.mit.edu.
  33.  */
  34.  
  35.  
  36. /* This stuff is defined in the calling program by just_display.h */
  37. extern char *program_name;
  38. extern Display *dpy;
  39. extern int screen;
  40.  
  41.  
  42. /*
  43.  * Malloc: like malloc but handles out of memory using Fatal_Error.
  44.  */
  45. char *Malloc(size)
  46.      unsigned size;
  47. {
  48.     char *data, *malloc();
  49.  
  50.     if (!(data = malloc(size)))
  51.       Fatal_Error("Out of memory!");
  52.  
  53.     return(data);
  54. }
  55.     
  56.  
  57. /*
  58.  * Realloc: like Malloc except for realloc, handles NULL using Malloc.
  59.  */
  60. char *Realloc(ptr, size)
  61.         char *ptr;
  62.         int size;
  63. {
  64.     char *new_ptr, *realloc();
  65.  
  66.     if (!ptr)
  67.       return(Malloc(size));
  68.  
  69.     if (!(new_ptr = realloc(ptr, size)))
  70.       Fatal_Error("Out of memory!");
  71.  
  72.     return(new_ptr);
  73. }
  74.  
  75.  
  76. /*
  77.  * Get_Display_Name (argc, argv) Look for -display, -d, or host:dpy (obselete)
  78.  * If found, remove it from command line.  Don't go past a lone -.
  79.  */
  80. char *Get_Display_Name(pargc, argv)
  81.     int *pargc;  /* MODIFIED */
  82.     char **argv; /* MODIFIED */
  83. {
  84.     int argc = *pargc;
  85.     char **pargv = argv+1;
  86.     char *displayname = NULL;
  87.     int i;
  88.  
  89.     for (i = 1; i < argc; i++) {
  90.     char *arg = argv[i];
  91.  
  92.     if (!strcmp (arg, "-display") || !strcmp (arg, "-d")) {
  93.         if (++i >= argc) usage ();
  94.  
  95.         displayname = argv[i];
  96.         *pargc -= 2;
  97.         continue;
  98.     }
  99.     if (!strcmp(arg,"-")) {
  100.         while (i<argc)
  101.             *pargv++ = argv[i++];
  102.         break;
  103.     }
  104.     *pargv++ = arg;
  105.     }
  106.  
  107.     *pargv = NULL;
  108.     return (displayname);
  109. }
  110.  
  111.  
  112. /*
  113.  * Open_Display: Routine to open a display with correct error handling.
  114.  *               Does not require dpy or screen defined on entry.
  115.  */
  116. Display *Open_Display(display_name)
  117. char *display_name;
  118. {
  119.     Display *d;
  120.  
  121.     d = XOpenDisplay(display_name);
  122.     if (d == NULL) {
  123.         fprintf (stderr, "%s:  unable to open display '%s'\n",
  124.              program_name, XDisplayName (display_name));
  125.         usage ();
  126.         /* doesn't return */
  127.     }
  128.  
  129.     return(d);
  130. }
  131.  
  132.  
  133. /*
  134.  * Setup_Display_And_Screen: This routine opens up the correct display (i.e.,
  135.  *                           it calls Get_Display_Name) and then stores a
  136.  *                           pointer to it in dpy.  The default screen
  137.  *                           for this display is then stored in screen.
  138.  *                           Does not require dpy or screen defined.
  139.  */
  140. void Setup_Display_And_Screen(argc, argv)
  141. int *argc;      /* MODIFIED */
  142. char **argv;    /* MODIFIED */
  143. {
  144.     dpy = Open_Display (Get_Display_Name(argc, argv));
  145.     screen = DefaultScreen(dpy);
  146. }
  147.  
  148.  
  149. /*
  150.  * Open_Font: This routine opens a font with error handling.
  151.  */
  152. XFontStruct *Open_Font(name)
  153. char *name;
  154. {
  155.     XFontStruct *font;
  156.  
  157.     if (!(font=XLoadQueryFont(dpy, name)))
  158.       Fatal_Error("Unable to open font %s!", name);
  159.  
  160.     return(font);
  161. }
  162.  
  163.  
  164. /*
  165.  * Beep: Routine to beep the display.
  166.  */
  167. void Beep()
  168. {
  169.     XBell(dpy, 50);
  170. }
  171.  
  172.  
  173. /*
  174.  * ReadBitmapFile: same as XReadBitmapFile except it returns the bitmap
  175.  *                 directly and handles errors using Fatal_Error.
  176.  */
  177. static void _bitmap_error(status, filename)
  178.      int status;
  179.      char *filename;
  180. {
  181.   if (status == BitmapOpenFailed)
  182.     Fatal_Error("Can't open file %s!", filename);
  183.   else if (status == BitmapFileInvalid)
  184.     Fatal_Error("file %s: Bad bitmap format.", filename);
  185.   else
  186.     Fatal_Error("Out of memory!");
  187. }
  188.  
  189. Pixmap ReadBitmapFile(d, filename, width, height, x_hot, y_hot)
  190.      Drawable d;
  191.      char *filename;
  192.      int *width, *height, *x_hot, *y_hot;
  193. {
  194.   Pixmap bitmap;
  195.   int status;
  196.  
  197.   status = XReadBitmapFile(dpy, RootWindow(dpy, screen), filename,
  198.                (unsigned int *)width, (unsigned int *)height,
  199.                &bitmap, x_hot, y_hot);
  200.   if (status != BitmapSuccess)
  201.     _bitmap_error(status, filename);
  202.  
  203.   return(bitmap);
  204. }
  205.  
  206.  
  207. /*
  208.  * WriteBitmapFile: same as XWriteBitmapFile except it handles errors
  209.  *                  using Fatal_Error.
  210.  */
  211. void WriteBitmapFile(filename, bitmap, width, height, x_hot, y_hot)
  212.      char *filename;
  213.      Pixmap bitmap;
  214.      int width, height, x_hot, y_hot;
  215. {
  216.   int status;
  217.  
  218.   status= XWriteBitmapFile(dpy, filename, bitmap, width, height, x_hot,
  219.                y_hot);
  220.   if (status != BitmapSuccess)
  221.     _bitmap_error(status, filename);
  222. }
  223.  
  224.  
  225. /*
  226.  * Select_Window_Args: a rountine to provide a common interface for
  227.  *                     applications that need to allow the user to select one
  228.  *                     window on the screen for special consideration.
  229.  *                     This routine implements the following command line
  230.  *                     arguments:
  231.  *
  232.  *                       -root            Selects the root window.
  233.  *                       -id <id>         Selects window with id <id>. <id> may
  234.  *                                        be either in decimal or hex.
  235.  *                       -name <name>     Selects the window with name <name>.
  236.  *
  237.  *                     Call as Select_Window_Args(&argc, argv) in main before
  238.  *                     parsing any of your program's command line arguments.
  239.  *                     Select_Window_Args will remove its arguments so that
  240.  *                     your program does not have to worry about them.
  241.  *                     The window returned is the window selected or 0 if
  242.  *                     none of the above arguments was present.  If 0 is
  243.  *                     returned, Select_Window should probably be called after
  244.  *                     all command line arguments, and other setup is done.
  245.  *                     For examples of usage, see xwininfo, xwd, or xprop.
  246.  */
  247. Window Select_Window_Args(rargc, argv)
  248.      int *rargc;
  249.      char **argv;
  250. #define ARGC (*rargc)
  251. {
  252.     int nargc=1;
  253.     int argc;
  254.     char **nargv;
  255.     Window w=0;
  256.  
  257.     nargv = argv+1; argc = ARGC;
  258. #define OPTION argv[0]
  259. #define NXTOPTP ++argv, --argc>0
  260. #define NXTOPT if (++argv, --argc==0) usage()
  261. #define COPYOPT nargv++[0]=OPTION; nargc++
  262.  
  263.     while (NXTOPTP) {
  264.         if (!strcmp(OPTION, "-")) {
  265.             COPYOPT;
  266.             while (NXTOPTP)
  267.               COPYOPT;
  268.             break;
  269.         }
  270.         if (!strcmp(OPTION, "-root")) {
  271.             w=RootWindow(dpy, screen);
  272.             continue;
  273.         }
  274.         if (!strcmp(OPTION, "-name")) {
  275.             NXTOPT;
  276.             w = Window_With_Name(dpy, RootWindow(dpy, screen),
  277.                          OPTION);
  278.             if (!w)
  279.               Fatal_Error("No window with name %s exists!",OPTION);
  280.             continue;
  281.         }
  282.         if (!strcmp(OPTION, "-id")) {
  283.             NXTOPT;
  284.             w=0;
  285.             sscanf(OPTION, "0x%lx", &w);
  286.             if (!w)
  287.               sscanf(OPTION, "%ld", &w);
  288.             if (!w)
  289.               Fatal_Error("Invalid window id format: %s.", OPTION);
  290.             continue;
  291.         }
  292.         COPYOPT;
  293.     }
  294.     ARGC = nargc;
  295.     
  296.     return(w);
  297. }
  298.  
  299. /*
  300.  * Other_stuff: A group of routines which do common X11 tasks.
  301.  *
  302.  * Written by Mark Lillibridge.   Last updated 7/1/87
  303.  *
  304.  * Send bugs, etc. to chariot@athena.mit.edu.
  305.  */
  306.  
  307.  
  308. #define NULL 0
  309.  
  310. extern Display *dpy;
  311. extern int screen;
  312.  
  313. /*
  314.  * Resolve_Color: This routine takes a color name and returns the pixel #
  315.  *                that when used in the window w will be of color name.
  316.  *                (WARNING:  The colormap of w MAY be modified! )
  317.  *                If colors are run out of, only the first n colors will be
  318.  *                as correct as the hardware can make them where n depends
  319.  *                on the display.  This routine does not require wind to
  320.  *                be defined.
  321.  */
  322. unsigned long Resolve_Color(w, name)
  323.      Window w;
  324.      char *name;
  325. {
  326.     XColor c;
  327.     Colormap colormap;
  328.     XWindowAttributes wind_info;
  329.  
  330.     /*
  331.      * The following is a hack to insure machines without a rgb table
  332.      * handle at least white & black right.
  333.      */
  334.     if (!strcmp(name, "white"))
  335.       name="#ffffffffffff";
  336.     if (!strcmp(name, "black"))
  337.       name="#000000000000";
  338.  
  339.     XGetWindowAttributes(dpy, w, &wind_info);
  340.     colormap = wind_info.colormap;
  341.  
  342.     if (!XParseColor(dpy, colormap, name, &c))
  343.       Fatal_Error("Bad color format '%s'.", name);
  344.  
  345.     if (!XAllocColor(dpy, colormap, &c))
  346.       Fatal_Error("XAllocColor failed!");
  347.  
  348.     return(c.pixel);
  349. }
  350.  
  351.  
  352. /*
  353.  * Bitmap_To_Pixmap: Convert a bitmap to a 2 colored pixmap.  The colors come
  354.  *                   from the foreground and background colors of the gc.
  355.  *                   Width and height are required solely for efficiency.
  356.  *                   If needed, they can be obtained via. XGetGeometry.
  357.  */
  358. Pixmap Bitmap_To_Pixmap(dpy, d, gc, bitmap, width, height)
  359.      Display *dpy;
  360.      Drawable d;
  361.      GC gc;
  362.      Pixmap bitmap;
  363.      int width, height;
  364. {
  365.   Pixmap pix;
  366.   int x;
  367.   unsigned int i, depth;
  368.   Drawable root;
  369.  
  370.   if (!XGetGeometry(dpy, d, &root, &x, &x, &i, &i, &i, &depth))
  371.     return(0);
  372.  
  373.   pix = XCreatePixmap(dpy, d, width, height, (int)depth);
  374.  
  375.   XCopyPlane(dpy, bitmap, pix, gc, 0, 0, width, height, 0, 0, 1);
  376.  
  377.   return(pix);
  378. }
  379.  
  380.  
  381. /*
  382.  * blip: a debugging routine.  Prints Blip! on stderr with flushing. 
  383.  */
  384. void blip()
  385. {
  386.   outl("blip!");
  387. }
  388.  
  389.  
  390. /*
  391.  * Routine to let user select a window using the mouse
  392.  */
  393.  
  394. Window Select_Window(dpy)
  395.      Display *dpy;
  396. {
  397.   int status;
  398.   Cursor cursor;
  399.   XEvent event;
  400.   Window target_win = None, root = RootWindow(dpy,screen);
  401.   int buttons = 0;
  402.  
  403.   /* Make the target cursor */
  404.   cursor = XCreateFontCursor(dpy, XC_crosshair);
  405.  
  406.   /* Grab the pointer using target cursor, letting it room all over */
  407.   status = XGrabPointer(dpy, root, False,
  408.             ButtonPressMask|ButtonReleaseMask, GrabModeSync,
  409.             GrabModeAsync, root, cursor, CurrentTime);
  410.   if (status != GrabSuccess) Fatal_Error("Can't grab the mouse.");
  411.  
  412.   /* Let the user select a window... */
  413.   while ((target_win == None) || (buttons != 0)) {
  414.     /* allow one more event */
  415.     XAllowEvents(dpy, SyncPointer, CurrentTime);
  416.     XWindowEvent(dpy, root, ButtonPressMask|ButtonReleaseMask, &event);
  417.     switch (event.type) {
  418.     case ButtonPress:
  419.       if (target_win == None) {
  420.     target_win = event.xbutton.subwindow; /* window selected */
  421.     if (target_win == None) target_win = root;
  422.       }
  423.       buttons++;
  424.       break;
  425.     case ButtonRelease:
  426.       if (buttons > 0) /* there may have been some down before we started */
  427.     buttons--;
  428.        break;
  429.     }
  430.   } 
  431.  
  432.   XUngrabPointer(dpy, CurrentTime);      /* Done with pointer */
  433.  
  434.   return(target_win);
  435. }
  436.  
  437.  
  438. /*
  439.  * Window_With_Name: routine to locate a window with a given name on a display.
  440.  *                   If no window with the given name is found, 0 is returned.
  441.  *                   If more than one window has the given name, the first
  442.  *                   one found will be returned.  Only top and its subwindows
  443.  *                   are looked at.  Normally, top should be the RootWindow.
  444.  */
  445. Window Window_With_Name(dpy, top, name)
  446.      Display *dpy;
  447.      Window top;
  448.      char *name;
  449. {
  450.     Window *children, dummy;
  451.     unsigned int nchildren;
  452.     int i;
  453.     Window w=0;
  454.     char *window_name;
  455.  
  456.     if (XFetchName(dpy, top, &window_name) && !strcmp(window_name, name))
  457.       return(top);
  458.  
  459.     if (!XQueryTree(dpy, top, &dummy, &dummy, &children, &nchildren))
  460.       return(0);
  461.  
  462.     for (i=0; i<nchildren; i++) {
  463.         w = Window_With_Name(dpy, children[i], name);
  464.         if (w)
  465.           break;
  466.     }
  467.     if (children) XFree ((char *)children);
  468.     return(w);
  469. }
  470.  
  471. /*
  472.  * outl: a debugging routine.  Flushes stdout then prints a message on stderr
  473.  *       and flushes stderr.  Used to print messages when past certain points
  474.  *       in code so we can tell where we are.  Outl may be invoked like
  475.  *       printf with up to 7 arguments.
  476.  */
  477. outl(msg, arg0,arg1,arg2,arg3,arg4,arg5,arg6)
  478.      char *msg;
  479.      char *arg0, *arg1, *arg2, *arg3, *arg4, *arg5, *arg6;
  480. {
  481.     fflush(stdout);
  482.     fprintf(stderr, msg, arg0, arg1, arg2, arg3, arg4, arg5, arg6);
  483.     fprintf(stderr, "\n");
  484.     fflush(stderr);
  485. }
  486.  
  487.  
  488. /*
  489.  * Standard fatal error routine - call like printf but maximum of 7 arguments.
  490.  * Does not require dpy or screen defined.
  491.  */
  492. void Fatal_Error(msg, arg0,arg1,arg2,arg3,arg4,arg5,arg6)
  493. char *msg;
  494. char *arg0, *arg1, *arg2, *arg3, *arg4, *arg5, *arg6;
  495. {
  496.     fflush(stdout);
  497.     fflush(stderr);
  498.     fprintf(stderr, "%s: error: ", program_name);
  499.     fprintf(stderr, msg, arg0, arg1, arg2, arg3, arg4, arg5, arg6);
  500.     fprintf(stderr, "\n");
  501.     exit(1);
  502. }
  503.