home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 January / usenetsourcesnewsgroupsinfomagicjanuary1994.iso / sources / x / volume3 / awm2 / part01 / awm.c next >
Encoding:
C/C++ Source or Header  |  1989-02-17  |  42.1 KB  |  1,555 lines

  1.  
  2.  
  3.  
  4. #ifndef lint
  5. static char *rcsid_awm_c = "$Header: /usr/graph2/X11.3/contrib/windowmgrs/awm/RCS/awm.c,v 1.3 89/02/07 22:39:57 jkh Exp $";
  6. #endif  lint
  7.  
  8. #include "X11/copyright.h"
  9. /*
  10.  *
  11.  * Copyright 1987, 1988 by Ardent Computer Corporation, Sunnyvale, Ca.
  12.  *
  13.  * Copyright 1987 by Jordan Hubbard.
  14.  *
  15.  *
  16.  *                         All Rights Reserved
  17.  *
  18.  * Permission to use, copy, modify, and distribute this software and its
  19.  * documentation for any purpose and without fee is hereby granted,
  20.  * provided that the above copyright notice appear in all copies and that
  21.  * both that copyright notice and this permission notice appear in
  22.  * supporting documentation, and that the name of Ardent Computer
  23.  * Corporation or Jordan Hubbard not be used in advertising or publicity
  24.  * pertaining to distribution of the software without specific, written
  25.  * prior permission.
  26.  *
  27.  */
  28.  
  29. /*
  30.  * Copyright 1987 by Digital Equipment Corporation, Maynard, Massachusetts.
  31.  *
  32.  *                         All Rights Reserved
  33.  *
  34.  * Permission to use, copy, modify, and distribute this software and its
  35.  * documentation for any purpose and without fee is hereby granted,
  36.  * provided that the above copyright notice appear in all copies and that
  37.  * both that copyright notice and this permission notice appear in
  38.  * supporting documentation, and that the name of Digital Equipment
  39.  * Corporation not be used in advertising or publicity pertaining to
  40.  * distribution of the software without specific, written prior permission.
  41.  *
  42.  *
  43.  * DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
  44.  * ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
  45.  * DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
  46.  * ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
  47.  * WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
  48.  * ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
  49.  * SOFTWARE.
  50.  */
  51.  
  52.  
  53. /*
  54.  * MODIFICATION HISTORY
  55.  *
  56.  * 000 -- M. Gancarz, DEC Ultrix Engineering Group
  57.  * 001 -- Loretta Guarino Reid, DEC Ultrix Engineering Group,
  58.  *  Western Software Lab. Convert to X11.
  59.  * 002 -- Jordan Hubbard, U.C. Berkeley. Add title bar context stuff.
  60.  * 003 -- Jordan Hubbard, Ardent Computer. Added gadgets, border contexts.
  61.  * 1.6 -- Various irritating changes. Support for WMSTATE..
  62.  */
  63.  
  64. #include <signal.h>
  65. #include "awm.h"
  66. #include <sys/ioctl.h>
  67. #include "X11/Xutil.h"
  68. #include "X11/cursorfont.h"
  69.  
  70. #ifdef titan
  71. #include <sys/file.h>
  72. #endif
  73.  
  74. #ifdef PCS
  75. #include <unistd.h>
  76. #include <bsd/sys/time.h>
  77. #endif
  78. #ifdef PROFIL
  79. #include <signal.h>
  80. /*
  81.  * Dummy handler for profiling.
  82.  */
  83. ptrap()
  84. {
  85.      exit(0);
  86. }
  87. #endif
  88.  
  89. Boolean NeedRootInput=FALSE;
  90. MenuOptionsMask options;
  91. char *sfilename;
  92. char execfile[NAME_LEN]; /* Pointer to file to exec with -e */
  93. Boolean Snatched;
  94. Boolean desktop_execd = TRUE;
  95. extern FILE *yyin;
  96. extern int errorStatus;
  97. extern int ErrorHandler();
  98. extern XContext AwmContext;
  99.  
  100. /*
  101.  * Main program.
  102.  */
  103. main(argc, argv, environ)
  104. int argc;
  105. char **argv;
  106. char **environ;
  107. {
  108.      int hi;            /* Button event high detail. */
  109.      int lo;            /* Button event low detail. */
  110.      int x, y;                  /* Mouse X and Y coordinates. */
  111.      int root_x, root_y;        /* Mouse root X and Y coordinates. */
  112.      int cur_x, cur_y;        /* Current mouse X and Y coordinates. */
  113.      int down_x, down_y;    /* mouse X and Y at ButtonPress. */
  114.      int str_width;             /* Width in pixels of output string. */
  115.      unsigned int pop_width, pop_height; /* Pop up window width and height. */
  116.      int context;        /* Root, window, or icon context. */
  117.      unsigned int ptrmask;    /* for QueryPointer */
  118.      Boolean func_stat;        /* If true, function swallowed a ButtonUp. */
  119.      Boolean delta_done;    /* If true, then delta functions are done. */
  120.      Boolean local;        /* If true, then do not use system defaults. */
  121.      Boolean nolocal;        /* If true, ignore user defaults */
  122.      register Binding *bptr;    /* Pointer to Bindings list. */
  123.      char *root_name;        /* Root window name. */
  124.      char *display = NULL;    /* Display name pointer. */
  125.      char message[128];        /* Error message buffer. */
  126.      char *rc_file;        /* Pointer to $HOME/.awmrc. */
  127.      Window event_win;          /* Event window. */
  128.      Window root;        /* Root window for QueryPointer. */
  129.      AwmInfoPtr awi;
  130.      XEvent button_event;     /* Button input event. */
  131.      XGCValues xgc;        /* to create font GCs */
  132.      char *malloc();
  133.      XSetWindowAttributes swa;
  134.      unsigned long valuemask;
  135.      Window bwin;        /* Button window */
  136.      int num;
  137.      
  138.      /* next three variables are for XQueryWindow */
  139.      Window junk;
  140.      Window *kiddies = NULL;
  141.      unsigned int nkids;
  142.      
  143.      Entry("main")
  144.       
  145. #ifdef PROFIL
  146.       signal(SIGTERM, ptrap);
  147. #endif
  148.      
  149.      /* 
  150.       * Parse the command line arguments.
  151.       */
  152.      Argv = argv;
  153.      Environ = environ;
  154.      local = nolocal = FALSE;
  155.      argc--, argv++;
  156.      /*
  157.       * The destruction of '-e' args below is to prevent the startup
  158.       * command from being invoked again if we do an f.restart (see
  159.       * Restart.c and Argv)
  160.       */
  161.      while (argc) {
  162.       if (**argv == '-') {
  163.            if (!strcmp(*argv, "-display") || !strcmp(*argv, "-d")) {
  164.             argc--; argv++;
  165.             if (argc <= 0)
  166.              Usage();
  167.             display = *argv;
  168.            }
  169.            else if (!(strcmp(*argv, "-f"))) {
  170.             argc--, argv++;
  171.             if ((argc == 0) || (Startup_File[0] != '\0'))
  172.              Usage();
  173.             strncpy(Startup_File, *argv, NAME_LEN);
  174.            }
  175.            else if (!(strcmp(*argv, "-e"))) {
  176.             strcpy(*argv, "--");    /* destroy the arg */
  177.             argc--; argv++;
  178.             if ((argc == 0) || (execfile[0] != '\0'))
  179.              Usage();
  180.             desktop_execd = FALSE; /* assume we have desktop to run */
  181.             strncpy(execfile, *argv, NAME_LEN);
  182.            }
  183.            /* Destroyed arg, skip over what used to be filename for -e */
  184.            else if (!(strcmp(*argv, "--"))) {
  185.             argv += 2; argc -= 2;
  186.             continue;
  187.            }
  188.            else if (!(strcmp(*argv, "-b")))
  189.             local = TRUE;
  190.            else if (!(strcmp(*argv, "-i")))
  191.             nolocal = TRUE;
  192.            
  193.            else Usage();
  194.       }
  195.       else
  196.            Usage();
  197.       argc--, argv++;
  198.      }
  199.  
  200. #ifdef CONSOLE
  201.      if (access("/dev/console", W_OK) == 0) {
  202.           freopen("/dev/console", "w", stderr);
  203.       freopen("/dev/console", "w", stdout);
  204.      }
  205. #endif /* CONSOLE */
  206.      /* Open the damn display */
  207.      if ((dpy = XOpenDisplay(display)) == NULL) {
  208.       fprintf(stderr, "awm: Unable to open display\n");
  209.       exit(1);
  210.      }
  211.  
  212.      scr = DefaultScreen(dpy);
  213.      
  214.      /*
  215.       * Set XErrorFunction to be non-terminating.
  216.       */
  217.      XSetErrorHandler(ErrorHandler);
  218.      
  219.      /*
  220.       * Force child processes to disinherit the TCP file descriptor.
  221.       * This helps shell commands forked and exec'ed from menus
  222.       * to work properly. God knows if this works under SysV.
  223.       */
  224.      if ((status = fcntl(ConnectionNumber(dpy), F_SETFD, 1)) == -1) {
  225.       perror("awm: child cannot disinherit TCP fd");
  226.       Error("TCP file descriptor problems");
  227.      }
  228.      
  229.      /*
  230.       * Initialize the menus for later use.
  231.       */
  232.      RTLMenu_Option_Set(options, rightoffset);
  233.      RTLMenu_Initialize(options);
  234.      
  235.      /* Init the context manager stuff */
  236.      AwmContext = XUniqueContext();
  237.      
  238.      /*
  239.       * Get all the defaults we expect from the resource manager.
  240.       */
  241.      FocusSetByUser = FALSE;
  242.      Get_Defaults();
  243. #if defined(WMSTATE)
  244.      wm_state_atom = XInternAtom(dpy, "WM_STATE", False);
  245. #endif /* WMSTATE */
  246.  
  247.      /*
  248.       * Initialize the default bindings.
  249.       */
  250.      if (!local)
  251.       InitBindings();
  252.      
  253.      /*
  254.       * Read in and parse $HOME/.awmrc, if it exists.
  255.       */
  256.      if (!nolocal) {
  257.       extern char *getenv();
  258.       char *home = getenv("HOME");
  259.       if( !home )
  260.           Error( "Cannot find home" );
  261.       sfilename = rc_file = malloc(NAME_LEN);
  262.       sprintf(rc_file, "%s/.awmrc", home);
  263.       if ((yyin = fopen(rc_file, "r")) != NULL) {
  264.            Lineno = 1;
  265.            yyparse();
  266.            fclose(yyin);
  267.            if (Startup_File_Error)
  268.             Error("Bad .awmrc file...aborting");
  269.       }
  270.      }
  271.      /* 
  272.       * Read in and parse the startup file from the command line, if
  273.       * specified.
  274.       */
  275.      if (Startup_File[0] != '\0') {
  276.       sfilename = Startup_File;
  277.       if ((yyin = fopen(Startup_File, "r")) == NULL) {
  278.            sprintf(message, "Cannot open startup file '%s'", Startup_File);
  279.            Error(message);
  280.       }
  281.       Lineno = 1;
  282.       yyparse();
  283.       fclose(yyin);
  284.       if (Startup_File_Error)
  285.            Error("Bad startup file...aborting");
  286.      }
  287.  
  288.      if (Startup_File_Error)
  289.       Error("Bad startup file...aborting");
  290.  
  291.      /*
  292.       * Catch some of the basic signals so we don't get rudely killed without
  293.       * cleaning up first.
  294.       */
  295. #ifdef titan
  296.           signal(SIGHUP, Quit);
  297.      signal(SIGTERM, Quit);
  298.      signal(SIGQUIT, Quit);
  299.      signal(SIGINT, Quit);
  300.  
  301.      /* ignore SIGTTOU */
  302.  
  303.      signal(SIGTTOU, SIG_IGN);
  304. #else
  305.  
  306.      if (signal(SIGHUP, SIG_IGN) != SIG_IGN)
  307.       signal(SIGHUP, Quit);
  308.      if (signal(SIGTERM, SIG_IGN) != SIG_IGN)
  309.       signal(SIGTERM, Quit);
  310.      if (signal(SIGQUIT, SIG_IGN) != SIG_IGN)
  311.       signal(SIGTERM, Quit);
  312.      if (signal(SIGINT, SIG_IGN) != SIG_IGN)
  313.       signal(SIGINT, Quit);
  314. #endif
  315.  
  316.      /*
  317.       * If the root window has not been named, name it.
  318.       */
  319.      status = XFetchName(dpy, RootWindow(dpy, scr), &root_name);
  320.      if (root_name == NULL) 
  321.       XStoreName(dpy, RootWindow(dpy, scr), " X Root Window ");
  322.      else
  323.       XFree(root_name);
  324.      /* register the root window */
  325.      RegisterWindow(RootWindow(dpy, scr));
  326.  
  327.      ScreenHeight = DisplayHeight(dpy, scr);
  328.      ScreenWidth = DisplayWidth(dpy, scr);
  329.  
  330.      /*
  331.       * Create the menus. This function also sticks the RTL menu "handle"
  332.       * into the appropriate binding after it's been created and initialized.
  333.       */
  334.      Create_Menus();
  335.  
  336.      /*
  337.       * check the gadgets.
  338.       */
  339.      if (CheckGadgets())
  340.       Error("Error in gadget declarations. Exiting...\n");
  341.  
  342.      /*
  343.       * Store all the cursors.
  344.       */
  345.      StoreCursors();
  346.      
  347.      /* 
  348.       * grab the mouse buttons according to the map structure
  349.       */
  350.      Grab_Buttons();
  351.      
  352.      /* 
  353.       * watch for initial window mapping and window destruction
  354.       */
  355.      
  356.      errorStatus = False;
  357.      swa.event_mask = (SubstructureRedirectMask | FocusChangeMask |
  358.                (NeedRootInput ? EVENTMASK |
  359.             OwnerGrabButtonMask : 0));
  360.      XChangeWindowAttributes(dpy, RootWindow(dpy, scr), CWEventMask, &swa);
  361.      XSync(dpy, False);
  362.      if (errorStatus)
  363.       Error("Hmmm.. Looks like you're running another window manager!\n");
  364.      /*
  365.       * Before we go creating more windows, we buzz through the ones that
  366.       * are currently mapped and reparent and/or select on them as necessary
  367.       * (for autoraise and titles).
  368.       */
  369.      
  370.      if (XQueryTree(dpy, DefaultRootWindow(dpy), &junk, &junk, &kiddies,
  371.             &nkids)) {
  372.       int i;
  373.  
  374.       for (i = 0; i < (int)nkids; i++) {
  375.            XWindowAttributes xwa;
  376.            Window transient;
  377.            AwmInfoPtr awi;
  378.            unsigned long event_mask;
  379.            
  380.            XGetWindowAttributes(dpy, kiddies[i], &xwa);
  381.            
  382.            /* check to see if it's a popup or something */
  383.            XGetTransientForHint(dpy, kiddies[i], &transient);
  384.            if (xwa.class == InputOutput && xwa.map_state == IsViewable &&
  385.            xwa.override_redirect == False && transient == None) {
  386.             awi = RegisterWindow(kiddies[i]);
  387.             awi->state |= ST_PLACED;
  388.             /* Possibly add a frame */
  389.             FDecorate(kiddies[i],0,0,0,0);
  390.             event_mask = PropertyChangeMask | FocusChangeMask;
  391.             if (!awi->frame || !FrameFocus)
  392.              event_mask |= (EnterWindowMask | LeaveWindowMask);
  393. #ifndef RAINBOW
  394.             SetBorderPixmaps(awi, GrayPixmap);
  395. #else
  396.             SetBorderPixmaps(awi, awi->grayPixmap);
  397. #endif
  398.             XSelectInput(dpy, kiddies[i], event_mask);
  399.            }
  400.       }
  401.       if (kiddies && *kiddies)
  402.           XFree(kiddies);
  403.      }
  404.      /*
  405.       * Calculate size of the resize pop-up window.
  406.       */
  407.      valuemask = CWBorderPixel | CWBackPixel;
  408.      swa.border_pixel = PBorder;
  409.      swa.background_pixel = PBackground;
  410.      if (SaveUnder) {
  411.       swa.save_under = True;
  412.       valuemask |= CWSaveUnder;
  413.      }
  414.      str_width = XTextWidth(PFontInfo, PText, strlen(PText));
  415.      pop_width = str_width + (PPadding << 1);
  416.      PWidth = pop_width + (PBorderWidth << 1);
  417.      pop_height = PFontInfo->ascent + PFontInfo->descent + (PPadding << 1);
  418.      PHeight = pop_height + (PBorderWidth << 1);
  419.  
  420.      /*
  421.       * Create the pop-up window.  Create it at (0, 0) for now.  We will
  422.       * move it where we want later.
  423.       */
  424.      Pop = XCreateWindow(dpy, RootWindow(dpy, scr),
  425.              0, 0,
  426.              pop_width, pop_height,
  427.              PBorderWidth,
  428.              0,
  429.              CopyFromParent,
  430.              CopyFromParent,
  431.              valuemask,
  432.              &swa);
  433.      if (Pop == FAILURE)
  434.       Error("Can't create pop-up dimension display window.");
  435.      
  436.      /*
  437.       * Create graphics context.
  438.       */
  439.      xgc.font = IFontInfo->fid;
  440.      xgc.graphics_exposures = FALSE;
  441.      xgc.foreground = IForeground;
  442.      xgc.background = IBackground;
  443.      IconGC = XCreateGC(dpy, 
  444.             RootWindow(dpy, scr),
  445.             (GCForeground | GCBackground | GCGraphicsExposures |
  446.              GCFont), &xgc);
  447.      
  448.      xgc.foreground = PForeground;
  449.      xgc.background = PBackground;
  450.      xgc.font = PFontInfo->fid;
  451.      PopGC = XCreateGC(dpy, 
  452.                RootWindow(dpy, scr),
  453.                (GCForeground | GCBackground | GCFont), &xgc);
  454.      xgc.line_width = DRAW_WIDTH;
  455.      xgc.foreground = DRAW_VALUE;
  456.      xgc.function = DRAW_FUNC;
  457.      xgc.subwindow_mode = IncludeInferiors;
  458.      DrawGC = XCreateGC(dpy, RootWindow(dpy, scr), 
  459.             GCLineWidth | GCForeground | GCFunction |
  460.             GCSubwindowMode, &xgc);
  461.  
  462.      /*
  463.       * As our last "startup" task, invoke the execfile if was specified.
  464.       */
  465.      if (!desktop_execd) {
  466.       if (access(execfile, X_OK) == 0) {
  467.            if (fork() == 0) {
  468.             setpgrp(0, getpid());
  469.             signal(SIGHUP, SIG_DFL);
  470.             signal(SIGQUIT, SIG_DFL);
  471.             signal(SIGINT, SIG_DFL);
  472.             execl("/bin/sh", "sh", "-c", execfile, 0);
  473.             _exit(127);
  474.            }
  475.            else
  476.             desktop_execd = TRUE;
  477.       }
  478.      }
  479.      /*
  480.       * Tell the user we're alive and well.
  481.       */
  482.      XBell(dpy, VOLUME_PERCENTAGE(Volume));
  483.      
  484.      /* 
  485.       * Main command loop.
  486.       */
  487.      while (TRUE) {
  488.       
  489.       delta_done = func_stat = FALSE;
  490.       
  491.       /*
  492.        * Get the next mouse button event.  Spin our wheels until
  493.        * a ButtonPressed event is returned.
  494.        * Note that mouse events within an icon window are handled
  495.        * in the "GetButton" function or by the icon's owner if
  496.        * it is not awm.
  497.        */
  498.       while (TRUE) {
  499.            if (!GetButton(&button_event))
  500.             continue;
  501.            else if (button_event.type == ButtonPress)
  502.             break;
  503.       }
  504.       bwin = button_event.xbutton.window;
  505.       /* save mouse coords in case we want them later for a delta action */
  506.       down_x = button_event.xbutton.x;
  507.       down_y = button_event.xbutton.y;
  508.       
  509.       /*
  510.        * Okay, determine the event window and mouse coordinates.
  511.        */
  512.       status = XTranslateCoordinates(dpy, 
  513.                      bwin,
  514.                      RootWindow(dpy, scr),
  515.                      button_event.xbutton.x, 
  516.                      button_event.xbutton.y,
  517.                      &x, &y,
  518.                      &event_win);
  519.       if (status == 0)
  520.            continue;
  521.       
  522.       awi = GetAwmInfo(bwin);
  523.       if (!awi)
  524.            continue;
  525.  
  526.           if (awi->frame == bwin)
  527.                context = BORDER;
  528.       else if (awi->title == bwin)
  529.            context = TITLE;
  530.       else if (IsGadgetWin(bwin, &num))
  531.            context = GADGET | (1 << (num + BITS_USED));
  532.       else if (awi->icon == bwin)
  533.            context = ICON;
  534.       else if (awi->client == RootWindow(dpy, scr)) {
  535.            event_win = RootWindow(dpy, scr);
  536.            context = ROOT;
  537.       }
  538.       else
  539.            context = WINDOW;
  540.  
  541.       /*
  542.        * Get the button event detail.
  543.        */
  544.       lo = button_event.xbutton.button;
  545.       hi = button_event.xbutton.state;
  546.       
  547.       /*
  548.        * Determine which function was selected and invoke it.
  549.        */
  550.       for(bptr = Blist; bptr; bptr = bptr->next) {
  551.            if ((bptr->button != lo) ||
  552.            (((int)bptr->mask & ModMask) != hi))
  553.             continue;
  554.            
  555.            if ((bptr->context & context) != context) {
  556.             continue;
  557.                }
  558.            if (!(bptr->mask & ButtonDown))
  559.             continue;
  560.            
  561.            /*
  562.         * Found a match! Invoke the function.
  563.         */
  564.            if ((*bptr->func)(event_win, (int)bptr->mask & ModMask,
  565.                  bptr->button,
  566.                  x, y,
  567.                  bptr->menu, bptr->menuname))
  568.             func_stat = TRUE;
  569.            break;
  570.       }
  571.       
  572.       /*
  573.        * If the function ate the ButtonUp event, then restart the loop.
  574.        */
  575.       
  576.       if (func_stat)
  577.            continue;
  578.       while (TRUE) {
  579.            /*
  580.         * Wait for the next button event.
  581.         */
  582.            if (XPending(dpy) && GetButton(&button_event)) {
  583.             bwin = button_event.xbutton.window;
  584.             /*
  585.              * If it's not a release of button that was pressed,
  586.              * don't do the function bound to 'ButtonUp'.
  587.              */
  588.             if (button_event.type != ButtonRelease)
  589.              break;
  590.             if (lo != button_event.xbutton.button)
  591.              break;
  592.             if ((hi | ButtonMask(lo)) != button_event.xbutton.state)
  593.              break;
  594.             /*
  595.              * Okay, determine the event window and mouse coordinates.
  596.              */
  597.             status = XTranslateCoordinates(dpy, 
  598.                            bwin,
  599.                            RootWindow(dpy, scr),
  600.                            button_event.xbutton.x,
  601.                            button_event.xbutton.y,
  602.                            &x, &y,
  603.                            &event_win);
  604.             if (status == BadWindow)
  605.              break;
  606.             awi = GetAwmInfo(bwin);
  607.             if (!awi)
  608.              continue;
  609.             if (awi->frame == bwin)
  610.              context = BORDER;
  611.             else if (awi->title == bwin)
  612.              context = TITLE;
  613.             else if (IsGadgetWin(bwin, &num))
  614.              context = GADGET | (1 << (num + BITS_USED));
  615.             else if (awi->icon == bwin)
  616.              context = ICON;
  617.             else if (awi->client == RootWindow(dpy, scr)) {
  618.              event_win = RootWindow(dpy, scr);
  619.              context = ROOT;
  620.             }
  621.             else
  622.              context = WINDOW;
  623.             /*
  624.              * Determine which function was selected and invoke it.
  625.              */
  626.             for(bptr = Blist; bptr; bptr = bptr->next) {
  627.              
  628.              if ((bptr->button != lo) ||
  629.                  (((int)bptr->mask & ModMask) != hi))
  630.                   continue;
  631.              
  632.              if (!((bptr->context & context) == context)) {
  633.                   continue;
  634.                          }
  635.              
  636.              if (!(bptr->mask & ButtonUp))
  637.                   continue;
  638.              
  639.              /*
  640.               * Found a match! Invoke the function.
  641.               */
  642.              
  643.              (*bptr->func)(event_win,
  644.                        (int)bptr->mask & ModMask,
  645.                        bptr->button,
  646.                        x, y,
  647.                        bptr->menu, bptr->menuname);
  648.              break;
  649.             }
  650.             break;
  651.            }
  652.            XQueryPointer(dpy, RootWindow(dpy, scr),
  653.                  &root, &junk, &root_x, &root_y, &cur_x, &cur_y,
  654.                  &ptrmask);
  655.            if (!delta_done &&
  656.            (abs(cur_x - x) > Delta || abs(cur_y - y) > Delta)) {
  657.             /*
  658.              * Delta functions are done once (and only once.)
  659.              */
  660.             delta_done = TRUE;
  661.             
  662.             /*
  663.              * Determine the new event window's coordinates from the
  664.              * original ButtonPress event.
  665.              */
  666.             status = XTranslateCoordinates(dpy, bwin,
  667.                            RootWindow(dpy, scr),
  668.                            down_x, down_y, &x, &y,
  669.                            &junk);
  670.             if (status == 0)
  671.              break;
  672.  
  673.             /*
  674.              * Determine the event window and context.
  675.              */
  676.             if (awi->frame == bwin)
  677.              context = BORDER;
  678.             else if (awi->title == bwin)
  679.              context = TITLE;
  680.             else if (IsGadgetWin(bwin, &num))
  681.              context = GADGET | (1 << (num + BITS_USED));
  682.             else if (awi->icon == bwin)
  683.              context = ICON;
  684.             else if (awi->client == RootWindow(dpy, scr)) {
  685.              event_win = RootWindow(dpy, scr);
  686.              context = ROOT;
  687.             }
  688.             else
  689.              context = WINDOW;
  690.             /*
  691.              * Determine which function was selected and invoke it.
  692.              */
  693.             for(bptr = Blist; bptr; bptr = bptr->next) {
  694.              
  695.              if ((bptr->button != lo) ||
  696.                  (((int)bptr->mask & ModMask) != hi))
  697.                   continue;
  698.              
  699.              if (!((bptr->context & context) == context))
  700.                   continue;
  701.              
  702.              if (!(bptr->mask & DeltaMotion))
  703.                   continue;
  704.              
  705.              /*
  706.               * Found a match! Invoke the function.
  707.               */
  708.              
  709.              if ((*bptr->func)(event_win,
  710.                        (int)bptr->mask & ModMask,
  711.                        bptr->button,
  712.                        x, y,
  713.                        bptr->menu, bptr->menuname)) {
  714.                   func_stat = TRUE;
  715.                   break;
  716.              }
  717.             }
  718.             /*
  719.              * If the function ate the ButtonUp event,
  720.              * then restart the loop.
  721.              */
  722.             
  723.             if (func_stat)
  724.              break;
  725.            }
  726.       }
  727.      }
  728. }
  729.  
  730. /*
  731.  * Get defaults from the resource manager. Most of these things used to be
  732.  * in the rc file, but they really belong here, I think.
  733.  */
  734. Get_Defaults()
  735. {
  736.      /*
  737.       * Get the pixmap search path, if it exists.
  738.       */
  739.      awmPath = GetStringRes("path", (char *) NULL);
  740.  
  741.      /* Default foreground/background colors (text) */
  742.      Foreground = GetStringRes("foreground", "black");
  743.      Background = GetStringRes("background", "white");
  744.      Reverse = GetBoolRes("reverse", FALSE);
  745.      
  746.      if (Reverse) { /* Swap the foreground and background */
  747.       char *tmp;
  748.       
  749.       tmp = Foreground;
  750.       Foreground = Background;
  751.           Background = tmp;
  752.      }
  753.      WBorder = GetStringRes("border.foreground", Foreground);
  754.      
  755.      Autoselect = GetBoolRes("autoselect", FALSE);
  756.      Autoraise = GetBoolRes("autoraise", FALSE);
  757.      Borders = GetBoolRes("borderContexts", FALSE);
  758.      ConstrainResize = GetBoolRes("constrainResize", FALSE);
  759.      FrameFocus = GetBoolRes("frameFocus", FALSE);
  760.      Freeze = GetBoolRes("freeze", FALSE);
  761.      Grid = GetBoolRes("grid", FALSE);
  762.      InstallColormap = GetBoolRes("installColormap", FALSE);
  763.      Titles = GetBoolRes("titles", FALSE);
  764.      IconLabels = GetBoolRes("icon.labels", FALSE);
  765.      ILabelTop = GetBoolRes("icon.labelTop", FALSE);
  766.      PushDown = GetBoolRes("title.push", FALSE);
  767.      UseGadgets = GetBoolRes("gadgets", FALSE);
  768.      Hilite = GetBoolRes("hilite", FALSE);
  769.      BorderHilite = GetBoolRes("border.hilite", Hilite);
  770.      RootResizeBox = GetBoolRes("rootResizeBox", FALSE);
  771.      ResizeRelative = GetBoolRes("resizeRelative", FALSE);
  772.      NIcon = GetBoolRes("normali", TRUE);
  773.      ShowName = GetBoolRes("showName", TRUE);
  774.      NWindow = GetBoolRes("normalw", TRUE);
  775.      Push = GetBoolRes("pushRelative", FALSE);
  776.      SaveUnder = GetBoolRes("saveUnder", FALSE);
  777.      Wall = GetBoolRes("wall", FALSE);
  778.      WarpOnRaise = GetBoolRes("warpOnRaise", FALSE);
  779.      WarpOnIconify = GetBoolRes("warpOnIconify", FALSE);
  780.      WarpOnDeIconify = GetBoolRes("warpOnDeIconify", FALSE);
  781.      Zap = GetBoolRes("zap", FALSE);
  782.      
  783.      HIconPad = GetIntRes("icon.hPad", DEF_ICON_PAD);
  784.      VIconPad = GetIntRes("icon.vPad", DEF_ICON_PAD);
  785.      RaiseDelay = GetIntRes("raiseDelay", DEF_RAISE_DELAY);
  786.      PBorderWidth = GetIntRes("popup.borderWidth", DEF_POP_BORDER_WIDTH);
  787.      IBorderWidth = GetIntRes("icon.borderWidth", DEF_ICON_BORDER_WIDTH);
  788.      PPadding = GetIntRes("popup.pad", DEF_POP_PAD);
  789.      MBorderWidth = GetIntRes("menu.borderWidth", DEF_MENU_BORDER_WIDTH);
  790.      MItemBorder = GetIntRes("menu.itemBorder", 1);
  791.      MDelta = GetIntRes("menu.delta", DEF_MENU_DELTA);
  792.      MPad = GetIntRes("menu.pad", DEF_MENU_PAD);
  793.      Delta = GetIntRes("delta", DEF_DELTA);
  794.      Volume = GetIntRes("volume", DEF_VOLUME);
  795.      Pushval = GetIntRes("push", DEF_PUSH);
  796.      BContext = GetIntRes("borderContext.width", DEF_BCONTEXT_WIDTH);
  797.  
  798.      ForeColor = GetColorRes("foreground", BlackPixel(dpy, scr));
  799.      BackColor = GetColorRes("background", WhitePixel(dpy, scr));
  800.      IForeground = GetColorRes("icon.foreground", ForeColor);
  801.      IBackground = GetColorRes("icon.background", BackColor);
  802.      IBorder = GetColorRes("icon.border", IForeground);
  803.      ITextForeground = GetColorRes("icon.text.foreground", IForeground);
  804.      ITextBackground = GetColorRes("icon.text.background", IBackground);
  805.      PBorder = GetColorRes("popup.border", ForeColor);
  806.      PForeground = GetColorRes("popup.foreground", PBorder);
  807.      PBackground = GetColorRes("popup.background", BackColor);
  808.      MForeground = GetColorRes("menu.foreground", ForeColor);
  809.      MBackground = GetColorRes("menu.background", BackColor);
  810.      MBorder = GetColorRes("menu.border", MForeground);
  811.  
  812.      /*
  813.       * Create and store the grey and solid pixmaps, and default icon pixmap
  814.       */
  815.      GrayPixmap = XCreatePixmapFromBitmapData(dpy, RootWindow(dpy, scr),
  816.                           gray_bits,
  817.                           gray_width, gray_height,
  818.                           ForeColor,
  819.                           BackColor,
  820.                           (unsigned)DefaultDepth(dpy,scr));
  821.  
  822.      SolidPixmap = XCreatePixmapFromBitmapData(dpy, RootWindow(dpy, scr),
  823.                            solid_bits,
  824.                            solid_width, solid_height,
  825.                            ForeColor,
  826.                            BackColor,
  827.                            (unsigned)DefaultDepth(dpy,
  828.                                       scr));
  829.      
  830.      IDefPixmap = XCreatePixmapFromBitmapData(dpy, RootWindow(dpy, scr),
  831.                            xlogo32_bits,
  832.                            xlogo32_width, xlogo32_height,
  833.                            IForeground,
  834.                            IBackground,
  835.                            (unsigned)DefaultDepth(dpy,
  836.                                       scr));
  837.  
  838.      IFontInfo = GetFontRes("icon.font", DEF_ICON_FONT);
  839.      PFontInfo = GetFontRes("popup.font", DEF_POPUP_FONT);
  840.      MFontInfo = GetFontRes("menu.font", DEF_MENU_FONT);
  841.      MBoldFontInfo = GetFontRes("menu.boldFont", DEF_BOLD_FONT);
  842.  
  843.      
  844.      IBackPixmap = GetPixmapRes("icon.backpixmap", GrayPixmap, IForeground,
  845.                 IBackground);
  846.      IDefPixmap =  GetPixmapRes("icon.defpixmap", IDefPixmap, IForeground,
  847.                 IBackground);
  848.  
  849. #ifdef NEATEN
  850.      AbsMinWidth = GetIntRes("neaten.absMinWidth", DEFAULT_ABS_MIN);
  851.      AbsMinHeight = GetIntRes("neaten.absMinHeight", DEFAULT_ABS_MIN);
  852.      
  853.      RetainSize = GetBoolRes("neaten.retainSize", TRUE);
  854.      KeepOpen = GetBoolRes("neaten.keepOpen", TRUE);
  855.      Fill = GetBoolRes("neaten.fill", TRUE);
  856.      UsePriorities = GetBoolRes("neaten.usePriorities", TRUE);
  857.      FixTopOfStack = GetBoolRes("neaten.fixTopOfStack", TRUE);
  858.      
  859.      PrimaryIconPlacement = GetStringRes("neaten.primaryIconPlacement",
  860.                      DEF_PRIMARY_PLACEMENT);
  861.      SecondaryIconPlacement = GetStringRes("neaten.secondaryIconPlacement",
  862.                        DEF_SECONDARY_PLACEMENT);
  863. #endif
  864.      
  865.      Leave_void
  866. }
  867.  
  868. /*
  869.  * Look up string resource "string". If undefined, return "def_val"
  870.  */
  871. char *GetStringRes(string, def_val)
  872. char *string, *def_val;
  873. {
  874.      char *cp;
  875.      
  876.      Entry("GetStringRes")
  877.      
  878.      if ((cp = XGetDefault(dpy, NAME, string)) ||
  879.      (cp = XGetDefault(dpy, CLASS, string))) {
  880.       if (!strlen(cp))
  881.            Leave(def_val)
  882.       else
  883.            Leave(cp)
  884.      }
  885.      Leave(def_val)
  886. }
  887.  
  888. /*
  889.  * Look up boolean resource "string". If undefined, return "def_val"
  890.  */
  891. Boolean GetBoolRes(string, def_val)
  892. char *string;
  893. Boolean def_val;
  894. {
  895.      char *cp;
  896.      
  897.      Entry("GetBoolRes")
  898.      
  899.      if ((cp = XGetDefault(dpy, NAME, string)) ||
  900.      (cp = XGetDefault(dpy, CLASS, string)))
  901.       if (Pred(cp) > 0)
  902.         def_val = TRUE;
  903.      Leave(def_val)
  904. }
  905.  
  906. /*
  907.  * Look up integer resource "string". If undefined or non-numeric,
  908.  * return def_val.
  909.  */
  910. int GetIntRes(string, def_val)
  911. char *string;
  912. int def_val;
  913. {
  914.      char *cp;
  915.      
  916.      Entry("GetIntRes")
  917.      
  918.      if ((cp = XGetDefault(dpy, NAME, string)) ||
  919.      (cp = XGetDefault(dpy, CLASS, string))) {
  920.       if (!strlen(cp) || !((*cp >= '0' && *cp <= '9') || *cp == '-'))
  921.            Leave(def_val)
  922.       Leave(atoi(cp))
  923.      }
  924.      Leave(def_val)
  925. }
  926.  
  927. /*
  928.  * Try to load pixmap file named by resource "string". Return 0 if
  929.  * unsuccessful. Otherwise, set width, height and return data.
  930.  */
  931. char *GetPixmapDataRes(string, wide, high)
  932. char *string;
  933. unsigned int *wide, *high;
  934. {
  935.      char *cp, *cp2;
  936.  
  937.      Entry("GetPixmapDataRes")
  938.      
  939.      if ((cp = XGetDefault(dpy, NAME, string)) ||
  940.      (cp = XGetDefault(dpy, CLASS, string))) {
  941.       char *data;
  942.       int junk;
  943.       
  944.       cp2 = expand_from_path(cp);
  945.       if (!cp2) {
  946.            fprintf(stderr, "awm: Can't find pixmap file '%s' for '%s'\n",
  947.                cp, string);
  948.            Leave(0)
  949.       }
  950.       if (XmuReadBitmapDataFromFile(cp2, wide, high, &data, &junk, &junk)
  951.           != BitmapSuccess) {
  952.            fprintf(stderr, "awm: Can't read pixmap file '%s' for '%s'.\n",
  953.                cp, string);
  954.       }
  955.       else {
  956.            Leave(data)
  957.       }
  958.      }
  959.      Leave(0)
  960. }
  961.  
  962. /*
  963.  * Try to allocate pixmap resources named by "string", return "def_pix"
  964.  * if not found.
  965.  */
  966. Pixmap GetPixmapRes(string, def_pix, fg, bg)
  967. char *string;
  968. Pixmap def_pix;
  969. Pixel fg, bg;
  970. {
  971.      char *data;
  972.      Pixmap tmp;
  973.      unsigned int wide, high;
  974.  
  975.      Entry("GetPixmapRes")
  976.  
  977.      if (data = GetPixmapDataRes(string, &wide, &high)) {
  978.       tmp = XCreatePixmapFromBitmapData(dpy, RootWindow(dpy, scr),
  979.                         data, wide, high, fg, bg,
  980.                         (unsigned) DefaultDepth(dpy, scr));
  981.       XFree(data);
  982.       if (!tmp) {
  983.            fprintf(stderr,
  984.                "awm: Can't create pixmap '%s', using default.\n",
  985.                string);
  986.            tmp = def_pix;
  987.       }
  988.      }
  989.      else
  990.       tmp = def_pix;
  991.      Leave(tmp)
  992.      }
  993.  
  994. /*
  995.  * Try to allocate color resource named by "string", return "color"
  996.  * if not found.This routine is only used for allocating colors from
  997.  * the default colormap.
  998.  */
  999. Pixel GetColorRes(string, color)
  1000. char *string;
  1001. Pixel color;
  1002. {
  1003.      char *cp;
  1004.      Pixel tmp_color;
  1005.      Boolean status;
  1006.      extern Pixel LookupColor();
  1007.      
  1008.      Entry("GetColorRes")
  1009.      
  1010.      if ((cp = XGetDefault(dpy, NAME, string)) ||
  1011.      (cp = XGetDefault(dpy, CLASS, string))) {
  1012.       tmp_color = LookupColor(cp, DefaultColormap(dpy, scr), &status);
  1013.       if (!status) /* lookup succeeded */
  1014.            Leave(tmp_color)
  1015.       else
  1016.            tmp_color = color;
  1017.      }
  1018.      else
  1019.       tmp_color = color;
  1020.      Leave(tmp_color)
  1021. }
  1022.  
  1023. /*
  1024.  * Try and get font resource "string", using "default" if not found. If
  1025.  * neither are available, use server default.
  1026.  */
  1027.  
  1028. XFontStruct *GetFontRes(string, dflt)
  1029. char *string, *dflt;
  1030. {
  1031.      char *cp;
  1032.      XFontStruct *tmp;
  1033.      static XFontStruct *def_font = 0;
  1034.      
  1035.      Entry("GetFontRes")
  1036.      
  1037.      if (!def_font)
  1038.       def_font = XLoadQueryFont(dpy, DEF_FONT);
  1039.      
  1040.      if ((cp = XGetDefault(dpy, NAME, string)) ||
  1041.      (cp = XGetDefault(dpy, CLASS, string))) {
  1042.       if (tmp = XLoadQueryFont(dpy, cp))
  1043.            Leave(tmp)
  1044.       else if (dflt)
  1045.            fprintf(stderr, "awm: Can't load %s '%s', trying '%s'.\n",
  1046.                string, cp, dflt);
  1047.      }
  1048.      if (!dflt) /* NULL means we're not supposed to try again */
  1049.       Leave(NULL)
  1050.      if (tmp = XLoadQueryFont(dpy, dflt))
  1051.       Leave(tmp)
  1052.      else
  1053.       fprintf(stderr, "awm: Can't open default font '%s', using server default.\n", dflt);
  1054.      Leave(def_font)
  1055. }
  1056.  
  1057. AwmInfoPtr GetAwmInfo(w)
  1058. Window w;
  1059. {
  1060.      static AwmInfoPtr tmp;
  1061.      
  1062.      Entry("GetAwmInfo")
  1063.      
  1064.      if (!XFindContext(dpy, w, AwmContext, (caddr_t *) &tmp))
  1065.       Leave(tmp)
  1066.      else
  1067.       Leave((AwmInfoPtr)NULL)
  1068. }
  1069.  
  1070. AwmInfoPtr RegisterWindow(w)
  1071. Window w;
  1072. {
  1073.      AwmInfoPtr tmp;
  1074.      XClassHint clh;
  1075.      XWMHints *wm_hints;
  1076.      char *cp;
  1077.  
  1078.      Entry("RegisterWindow")
  1079.      
  1080.      tmp = (AwmInfoPtr)malloc(sizeof(AwmInfo));
  1081.      if (tmp == (AwmInfoPtr)NULL) {
  1082.       fprintf(stderr, "awm: Woe! No memory to register window.\n");
  1083.       Leave((AwmInfoPtr)NULL)
  1084.      }
  1085.      tmp->client = w;
  1086.      tmp->title = tmp->frame = tmp->icon = (Window)0;
  1087.      tmp->gadgets = (Window *)0;
  1088.      tmp->name = (char *)0;
  1089.      tmp->own = (Boolean)FALSE;
  1090.      tmp->back = tmp->bold = tmp->BC_back = tmp->BC_bold =
  1091.       tmp->iconPixmap = (Pixmap)0;
  1092.      tmp->state = ST_WINDOW;
  1093. #ifdef WMSTATE
  1094.      tmp->wm_state.icon=0;
  1095.      tmp->wm_state.state=NormalState;
  1096.      XChangeProperty(dpy,w,wm_state_atom,wm_state_atom,32,PropModeReplace,
  1097.              (char *) &tmp->wm_state,2);
  1098. #endif /* WMSTATE */
  1099.      tmp->winGC = XCreateGC(dpy, w, (unsigned long)0, (XGCValues *) NULL);
  1100.      /*
  1101.       * Determine attribute set by first turning on all attributes
  1102.       * that are set by booleans and then (possibly) override them
  1103.       * by checking to see what an individual window might want.
  1104.       */
  1105.      tmp->attrs = AT_NONE;
  1106.      if (Titles)
  1107.       tmp->attrs |= AT_TITLE;
  1108.      if (UseGadgets)
  1109.       tmp->attrs |= AT_GADGETS;
  1110.      if (Borders)
  1111.       tmp->attrs |= AT_BORDER;
  1112.      if (Autoraise)
  1113.       tmp->attrs |= AT_RAISE;
  1114.      if (IconLabels)
  1115.       tmp->attrs |= AT_ICONLABEL;
  1116.      if (wm_hints = XGetWMHints(dpy, w)) {
  1117.       if (wm_hints->input)
  1118.              tmp->attrs |= AT_INPUT;
  1119.       XFree(wm_hints);
  1120.      }
  1121. #ifdef RAINBOW
  1122.      tmp->foreColor = ForeColor;
  1123.      tmp->backColor = BackColor;
  1124.      tmp->grayPixmap = GrayPixmap;
  1125.      tmp->solidPixmap = SolidPixmap;
  1126. #endif
  1127.      clh.res_name = clh.res_class = (char *)NULL;
  1128.      XGetClassHint(dpy, w, &clh);
  1129.      if (clh.res_class) {
  1130. #ifdef RAINBOW
  1131.       Pixel tmp_color;
  1132.       Boolean status;
  1133.       
  1134.       if (cp = (XGetDefault(dpy, clh.res_class, "wm_option.foreground"))){
  1135.           tmp_color = LookupColor( cp, DefaultColormap( dpy, scr ), & status );
  1136.           if( !status )
  1137.               tmp->foreColor = tmp_color;
  1138.       }
  1139.  
  1140.       if (cp = (XGetDefault(dpy, clh.res_class, "wm_option.background"))){
  1141.           tmp_color = LookupColor( cp, DefaultColormap( dpy, scr ), & status );
  1142.           if( !status )
  1143.               tmp->backColor = tmp_color;
  1144.       }
  1145. #endif
  1146.       
  1147.       if (cp = (XGetDefault(dpy, clh.res_class, "wm_option.title")))
  1148.            tmp->attrs = SetOptFlag(tmp->attrs, AT_TITLE, Pred(cp));
  1149.       
  1150.       if (cp = (XGetDefault(dpy, clh.res_class, "wm_option.gadgets")))
  1151.            tmp->attrs = SetOptFlag(tmp->attrs, AT_GADGETS, Pred(cp));
  1152.  
  1153.       if (cp = (XGetDefault(dpy, clh.res_class,"wm_option.borderContext")))
  1154.            tmp->attrs = SetOptFlag(tmp->attrs, AT_BORDER, Pred(cp));
  1155.  
  1156.       if (cp = (XGetDefault(dpy, clh.res_class, "wm_option.autoRaise")))
  1157.            tmp->attrs = SetOptFlag(tmp->attrs, AT_RAISE, Pred(cp));
  1158.  
  1159.       if (cp = (XGetDefault(dpy, clh.res_class, "wm_option.icon.labels")))
  1160.            tmp->attrs = SetOptFlag(tmp->attrs, AT_ICONLABEL, Pred(cp));
  1161.      }
  1162.      if (clh.res_name) {
  1163. #ifdef RAINBOW
  1164.       Pixel tmp_color;
  1165.       Boolean status;
  1166.  
  1167.       if (cp = (XGetDefault(dpy, clh.res_name, "wm_option.foreground"))){
  1168.           tmp_color = LookupColor( cp, DefaultColormap( dpy, scr ), & status );
  1169.           if( !status )
  1170.               tmp->foreColor = tmp_color;
  1171.       }
  1172.  
  1173.       if (cp = (XGetDefault(dpy, clh.res_name, "wm_option.background"))){
  1174.           tmp_color = LookupColor( cp, DefaultColormap( dpy, scr ), & status );
  1175.           if( !status )
  1176.               tmp->backColor = tmp_color;
  1177.       }
  1178. #endif
  1179.       if (cp = (XGetDefault(dpy, clh.res_name, "wm_option.title")))
  1180.            tmp->attrs = SetOptFlag(tmp->attrs, AT_TITLE, Pred(cp));
  1181.       
  1182.       if (cp = (XGetDefault(dpy, clh.res_name, "wm_option.gadgets")))
  1183.            tmp->attrs = SetOptFlag(tmp->attrs, AT_GADGETS, Pred(cp));
  1184.  
  1185.       if (cp = (XGetDefault(dpy, clh.res_name, "wm_option.borderContext")))
  1186.            tmp->attrs = SetOptFlag(tmp->attrs, AT_BORDER, Pred(cp));
  1187.  
  1188.       if (cp = (XGetDefault(dpy, clh.res_name, "wm_option.autoRaise")))
  1189.            tmp->attrs = SetOptFlag(tmp->attrs, AT_RAISE, Pred(cp));
  1190.  
  1191.       if (cp = (XGetDefault(dpy, clh.res_name, "wm_option.icon.labels")))
  1192.            tmp->attrs = SetOptFlag(tmp->attrs, AT_ICONLABEL, Pred(cp));
  1193.      }
  1194. #ifdef RAINBOW
  1195.      /* Has a different fore/back colour been given? */
  1196.      if( (tmp->foreColor != ForeColor) || (tmp->backColor != BackColor) ){
  1197.       /*
  1198.        * Create and store the grey and solid pixmaps
  1199.        */
  1200.          tmp->grayPixmap = 
  1201.            XCreatePixmapFromBitmapData(dpy, RootWindow(dpy, scr),
  1202.                        gray_bits,
  1203.                        gray_width, gray_height,
  1204.                        tmp->foreColor,
  1205.                        tmp->backColor,
  1206.                        (unsigned)DefaultDepth(dpy, scr));
  1207.          
  1208.          tmp->solidPixmap = 
  1209.            XCreatePixmapFromBitmapData(dpy, RootWindow(dpy, scr),
  1210.                        solid_bits,
  1211.                        solid_width, solid_height,
  1212.                        tmp->foreColor,
  1213.                        tmp->backColor,
  1214.                        (unsigned)DefaultDepth(dpy, scr));
  1215.          
  1216.      }
  1217. #endif
  1218.      XSaveContext(dpy, w, AwmContext, (caddr_t) tmp);
  1219.      Leave(tmp)
  1220. }
  1221.  
  1222. /*
  1223.  * Sets bit "flag" conditionally, based on state of "mask" and
  1224.  * "predicate" (mask denotes current state, predicate denotes
  1225.  * whether change is desired).
  1226.  */
  1227. int SetOptFlag(mask, flag, predicate)
  1228. int mask, flag, predicate;
  1229. {
  1230.      Entry("SetOptFlag")
  1231.  
  1232.      switch (predicate) {
  1233.      case -1:
  1234.       Leave(mask)
  1235.           break;
  1236.  
  1237.      case 0:
  1238.           if (mask & flag)
  1239.            Leave(mask ^ flag)
  1240.           else
  1241.            Leave(mask)
  1242.       break;
  1243.  
  1244.      case 1:
  1245.       Leave(mask | flag)
  1246.       break;
  1247.      }
  1248.      Leave(-1);
  1249. }
  1250.  
  1251. /*
  1252.  * check whether a string denotes an "on" or "off" value. Return 0
  1253.  * if "off", 1 if "on" and -1 if undefined (or null).
  1254.  */
  1255. Pred(s)
  1256. char *s;
  1257. {
  1258.      int i, len;
  1259.      char *tmp;
  1260.      Boolean ret = -1;
  1261.      Entry("Pred")
  1262.  
  1263.      if (!s)
  1264.       Leave(-1)
  1265.      len = strlen(s);
  1266.      if (!len)
  1267.       Leave(-1)
  1268.      tmp = (char *)malloc(len + 1);
  1269.      if (!tmp) {
  1270.       fprintf(stderr, "awm: Pred: Can't allocate storage for '%s'!\n", s);
  1271.       Leave(-1)
  1272.      }
  1273.      strcpy(tmp, s);
  1274.      for (i = 0; i < len; i++)
  1275.       if (tmp[i] >= 'A' && tmp[i] <= 'Z')
  1276.            tmp[i] += 32;
  1277.      if (*tmp == 'y' || !strcmp(tmp, "on")
  1278.      || !strcmp(tmp, "true")
  1279.      || !strncmp(tmp, "enable", 6))
  1280.       ret = 1;
  1281.      else if (*tmp == 'n' || !strcmp(tmp, "off")
  1282.           || !strcmp(tmp, "false")
  1283.           || !strncmp(tmp, "disable", 7))
  1284.       ret = 0;
  1285.      free(tmp);
  1286.      Leave(ret)
  1287. }
  1288.  
  1289. /*
  1290.  * Initialize the default bindings.  First, write the character array
  1291.  * out to a temp file, then point the parser to it and read it in.
  1292.  * Afterwards, we unlink the temp file.
  1293.  */
  1294. InitBindings()
  1295. {
  1296.      char *mktemp();
  1297.      char *tempfile;
  1298.      register FILE *fp;        /* Temporary file pointer. */
  1299.      register char **ptr;    /* Default bindings string array pointer. */
  1300.      
  1301.      Entry("InitBindings")
  1302.      
  1303.      /*
  1304.       * Create and write the temp file.
  1305.       */
  1306.      /*
  1307.       * This used to just call mktemp() on TEMPFILE, which was very
  1308.       * evil as it involved writing on a string constant. This extra
  1309.       * mastication is necessary to prevent that.
  1310.       */
  1311.      tempfile = (char *)malloc(strlen(TEMPFILE) + 1);
  1312.      strcpy(tempfile, TEMPFILE);
  1313.      sfilename = mktemp(tempfile);
  1314.      if ((fp = fopen(tempfile, "w")) == NULL) {
  1315.       perror("awm: cannot create temp file");
  1316.       exit(1);
  1317.      }
  1318.      for (ptr = DefaultBindings; *ptr; ptr++) {
  1319.       fputs(*ptr, fp);
  1320.       fputc('\n', fp);
  1321.      }
  1322.      fclose(fp);
  1323.      
  1324.      /*
  1325.       * Read in the bindings from the temp file and parse them.
  1326.       */
  1327.      if ((yyin = fopen(tempfile, "r")) == NULL) {
  1328.       perror("awm: cannot open temp file");
  1329.       exit(1);
  1330.      }
  1331.      Lineno = 1;
  1332.      yyparse();
  1333.      fclose(yyin);
  1334.      unlink(tempfile);
  1335.      free(tempfile);
  1336.      if (Startup_File_Error)
  1337.       Error("Bad default bindings...aborting");
  1338.      
  1339.      /*
  1340.       * Parse the system startup file, if one exists.
  1341.       */
  1342.      if ((yyin = fopen(SYSFILE, "r")) != NULL) {
  1343.       sfilename = SYSFILE;
  1344.       Lineno = 1;
  1345.       yyparse();
  1346.       fclose(yyin);
  1347.       if (Startup_File_Error)
  1348.            Error("Bad system startup file...aborting");
  1349.      }
  1350.      Leave_void
  1351. }
  1352.  
  1353. /*
  1354.  * Create the menus and alter any appropriate bindings so that the RTL menu
  1355.  * handle is passed along in subsequent actions.
  1356.  */
  1357. Create_Menus()
  1358. {
  1359.      Binding *bptr;
  1360.      MenuInfo *minfo;
  1361.      MenuLink *lnk;
  1362.      extern MenuInfo *FindMenu();
  1363.      extern RTLMenu create_menu();
  1364.      
  1365.      Entry("Create_Menus")
  1366.      
  1367.      /*
  1368.       * We start with the bindings list because we don't want to bother
  1369.       * creating a menu that's been declared but not referenced.
  1370.       */
  1371.      for(bptr = Blist; bptr; bptr = bptr->next) {
  1372.       if (bptr->func == DoMenu) {
  1373.            if (minfo = FindMenu(bptr->menuname))
  1374.             bptr->menu = create_menu(minfo);
  1375.            else {
  1376.             fprintf(stderr, "awm: non-existent menu reference: \"%s\"\n",
  1377.                 bptr->menuname);
  1378.             Startup_File_Error = TRUE;
  1379.            }
  1380.       }
  1381.      }
  1382.      for (lnk = Menus; lnk; lnk = lnk->next) {
  1383.       free(lnk->menu);
  1384.       free(lnk);
  1385.      }
  1386.      Leave_void
  1387. }
  1388.  
  1389. /*
  1390.  * Grab the mouse buttons according to the bindings list.
  1391.  */
  1392.  
  1393. Grab_Buttons()
  1394. {
  1395.      Binding *bptr;
  1396.      
  1397.      Entry("Grab_Buttons")
  1398.      
  1399.      /*
  1400.       * don't grab buttons if you don't have to - allow application
  1401.       * access to buttons unless context includes window.
  1402.       */
  1403.      for (bptr = Blist; bptr; bptr = bptr->next) {
  1404.       if (bptr->context == ROOT)
  1405.            NeedRootInput = TRUE;
  1406.       else if (bptr->context & WINDOW) /* We gotta grab on windows */
  1407.            GrabAll(bptr->mask);
  1408.      }
  1409.      Leave_void
  1410. }
  1411.  
  1412. /*
  1413.  * Register a grab on all windows in the hierarchy. This is better than
  1414.  * registering a grab on the RootWindow since it leaves button/key chords
  1415.  * available for other contexts.
  1416.  */
  1417. GrabAll(mask)
  1418. unsigned int mask;
  1419. {
  1420.      unsigned int junk, nkids;
  1421.      Window *kiddies;
  1422.      
  1423.      Entry("GrabAll")
  1424.      
  1425.      if (XQueryTree(dpy, DefaultRootWindow(dpy), &junk, &junk, &kiddies,
  1426.             &nkids)) {
  1427.       int i;
  1428.       
  1429.       for (i = 0; i < (int)nkids; i++) {
  1430.            Window transient;
  1431.            XWindowAttributes xwa;
  1432.            
  1433.            /* check to see if it's a popup or something */
  1434.            XGetWindowAttributes(dpy, kiddies[i], &xwa);
  1435.            XGetTransientForHint(dpy, kiddies[i], &transient);
  1436.            if (xwa.class == InputOutput && xwa.map_state == IsViewable &&
  1437.            xwa.override_redirect == False && transient == None)
  1438.             Grab(mask, kiddies[i]);
  1439.       }
  1440.      }
  1441.      else
  1442.       Error("awm: Can't XQueryTree in GrabAll!\n");
  1443.      Leave_void
  1444. }
  1445.  
  1446. /*
  1447.  * Grab a mouse button according to the given mask.
  1448.  */
  1449. Grab(mask, w)
  1450. unsigned int mask;
  1451. Window w;
  1452. {
  1453.      unsigned int m = LeftMask | MiddleMask | RightMask;
  1454.      
  1455.      Entry("Grab")
  1456.      
  1457.      switch (mask & m) {
  1458.      case LeftMask:
  1459.       XGrabButton(dpy, LeftButton, mask & ModMask, w, TRUE, EVENTMASK,
  1460.               GrabModeAsync, GrabModeAsync, None, LeftButtonCursor);
  1461.       break;
  1462.       
  1463.      case MiddleMask:
  1464.       XGrabButton(dpy, MiddleButton, mask & ModMask, w, TRUE, EVENTMASK,
  1465.               GrabModeAsync, GrabModeAsync, None, MiddleButtonCursor);
  1466.       break;
  1467.       
  1468.      case RightMask:
  1469.       XGrabButton(dpy, RightButton, mask & ModMask, w, TRUE, EVENTMASK,
  1470.               GrabModeAsync, GrabModeAsync, None, RightButtonCursor);
  1471.       break;
  1472.      }
  1473.      Leave_void
  1474. }
  1475.  
  1476. /*
  1477.  * Restore cursor to normal state.
  1478.  */
  1479. ResetCursor(button)
  1480. int button;
  1481. {
  1482.      Entry("ResetCursor")
  1483.      
  1484.      switch (button) {
  1485.      case LeftButton:
  1486.       XChangeActivePointerGrab(dpy, EVENTMASK, LeftButtonCursor,
  1487.                    CurrentTime);
  1488.       break;
  1489.       
  1490.      case MiddleButton:
  1491.       XChangeActivePointerGrab(dpy, EVENTMASK, MiddleButtonCursor,
  1492.                    CurrentTime);
  1493.       break;
  1494.       
  1495.      case RightButton:
  1496.       XChangeActivePointerGrab(dpy, EVENTMASK, RightButtonCursor,
  1497.                    CurrentTime);
  1498.       break;
  1499.      }
  1500.      Leave_void
  1501. }
  1502.  
  1503. /*
  1504.  * error routine for .awmrc parser
  1505.  */
  1506. yyerror(s)
  1507. char*s;
  1508. {
  1509.      Entry("yyerror")
  1510.      
  1511.      fprintf(stderr, "awm: %s: Line %d: %s\n", sfilename, Lineno, s);
  1512.      Startup_File_Error = TRUE;
  1513.      Leave_void
  1514. }
  1515.  
  1516. /*
  1517.  * warning routine for .awmrc parser
  1518.  */
  1519. yywarn(s)
  1520. char*s;
  1521. {
  1522.      Entry("yywarn")
  1523.      
  1524.      fprintf(stderr, "awm: Warning: %s: Line %d: %s\n", sfilename, Lineno, s);
  1525.      Leave_void
  1526. }
  1527.  
  1528. /*
  1529.  * Print usage message and quit.
  1530.  */
  1531. Usage()
  1532. {
  1533.      Entry("Usage")
  1534.      
  1535.      fputs("Usage: awm [-b] [-i] [-f <file>] [-e <file>] [<host>:<display>]\n\n",
  1536.        stderr);
  1537.      fputs("The -b option bypasses system and default bindings\n", stderr);
  1538.      fputs("The -i option ignores the $HOME/.awmrc file\n", stderr);
  1539.      fputs("The -f option specifies an alternate startup file\n", stderr);
  1540.      fputs("The -e option specifies a program/script to exec after startup\n",
  1541.        stderr);
  1542.      exit(1);
  1543. }
  1544.  
  1545. /*
  1546.  * error handler for X I/O errors
  1547.  */
  1548. /*ARGSUSED*/
  1549. XIOError(dsp)
  1550. Display *dsp;
  1551. {
  1552.      /* perror("awm"); */
  1553.      exit(3);
  1554. }
  1555.