home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 January / usenetsourcesnewsgroupsinfomagicjanuary1994.iso / sources / x / volume3 / awm2 / part07 / RubberBand.c < prev   
Encoding:
C/C++ Source or Header  |  1989-02-20  |  11.9 KB  |  380 lines

  1.  
  2.  
  3.  
  4. #ifndef lint
  5. static char *rcsid_RubberBand_c = "$Header: /usr/graph2/X11.3/contrib/windowmgrs/awm/RCS/RubberBand.c,v 1.2 89/02/07 21:23:46 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.  * MODIFICATION HISTORY
  54.  *
  55.  * 000 -- Loretta Guarino Reid, DEC Ultrix Engineering Group
  56.  * 001 -- Ralph R. Swick, DEC/MIT Project Athena
  57.  *      tailor to uwm; use global resources created by uwm
  58.  */
  59.  
  60. #include "awm.h"
  61. #include "X11/Xutil.h"
  62. #include "X11/cursorfont.h"
  63.  
  64. #define max(a,b) ( (a) > (b) ? (a) : (b) )
  65. #define min(a,b) ( (a) > (b) ? (b) : (a) )
  66. #define abs(a) ( (a) > 0 ? (a) : -(a))
  67. #define makemult(a, b) ((b==1) ? (a) : (((int)((a) / (b))) * (b)) )
  68.  
  69. #define DCOUNT 2
  70. #define PCOUNT 1 + (4 * 2 * DCOUNT)
  71.  
  72. #define BW    PBorderWidth        /* pop-up window border width */
  73. #define IBW    PPadding        /* internal border width for pop-up */
  74.  
  75. AskUser(dpy, scr, window, x, y, width, height, hints, transient)
  76. Display *dpy;
  77. int scr;
  78. Window window;
  79. int *x, *y;
  80. unsigned int *width, *height;
  81. XSizeHints *hints;
  82. Window transient;
  83. {
  84.      Cursor ur, ul, ll, lr;          /* cursors for rubber banding    */
  85.      int change_cursor = FALSE;
  86.      int current_cursor;
  87.      char *text;            /* text for prompt string       */
  88.      int nz;                         /* count where zeros are        */
  89.      unsigned int popw, poph;        /* width and height of prompt window*/
  90. #define invertGC DrawGC
  91.      int x1, y1;                     /* location of mouse            */
  92.      int x2, y2;                     /* other corner of box          */
  93.      int rootx, rooty;
  94.      unsigned int mask;         /* for XQueryPointer          */
  95.      Window root, subw;        /* for XQueryPointer */
  96.      int xa = -1, ya = -1, xb = -1, yb = -1;
  97.      int xinc, yinc;
  98.      unsigned int minwidth, minheight;
  99.      unsigned int maxwidth, maxheight;
  100.      unsigned int defwidth, defheight;
  101.      int chosen = -1;
  102.      int stop = FALSE;
  103.      int changed = TRUE;
  104.      int doit = FALSE;
  105.      int dx, dy;
  106.      int delta;
  107.      int ijunk;
  108.      XPoint box[PCOUNT];
  109.      int hsize, vsize;
  110.      int zero = '0';                 /* zero offset for char conversion  */
  111.      XEvent e;                 /* someplace to put the event   */
  112.      unsigned int events;               /* what events we want.             */
  113.      Window pop, wjunk;                     /* pop up prompt window         */
  114.      int i;
  115.      char *name;
  116.      int width_offset, height_offset; /* to subtract if resize increments */
  117.      
  118.      Entry("AskUser")
  119.  
  120.      if (transient) {
  121.       XGetGeometry( dpy, window, &wjunk, x, y, width, height,
  122.                &ijunk, &ijunk);
  123.       Leave_void
  124.      }
  125.      if ((hints->flags & USPosition) && (hints->flags & USSize)) {
  126.       *x = hints->x;
  127.       *y = hints->y;
  128.       *width = hints->width;
  129.       *height = hints->height;
  130.       Leave_void
  131.      }
  132.      if (!XFetchName(dpy, window, &name)) 
  133.       name = "Unnamed Window";
  134.      
  135.      ur = XCreateFontCursor(dpy, XC_ur_angle);
  136.      ul = XCreateFontCursor(dpy, XC_ul_angle);
  137.      ll = XCreateFontCursor(dpy, XC_ll_angle);
  138.      lr = XCreateFontCursor(dpy, XC_lr_angle);
  139.      current_cursor = ul;
  140.      
  141.      events = ButtonPressMask | ButtonReleaseMask;
  142.      
  143.      /* 
  144.       * go get the mouse as soon as you can 
  145.       */
  146.      
  147.      while (1) {
  148.       if (XGrabPointer (dpy, RootWindow(dpy, scr), FALSE, events, 
  149.                    GrabModeAsync, GrabModeAsync, None, ul,
  150.                    CurrentTime) == GrabSuccess)
  151.            break;
  152.       sleep (1);
  153.      }
  154.      nz = strlen(name);        /* compute number of characters */
  155.      text = (char *)malloc( nz + 11 );
  156.      (void) strcpy(text, name);
  157.      (void) strcat(text, ": 000x000");
  158.      nz += 9;
  159.      popw = XTextWidth (PFontInfo, text, nz) + 2 * IBW;
  160.      poph = PFontInfo->ascent+PFontInfo->descent + 2 * IBW;
  161.      
  162.      pop = XCreateSimpleWindow(dpy, RootWindow(dpy, scr), 
  163.                    0, 0, popw, poph, BW, PBorder, PBackground);
  164.      XMapWindow (dpy, pop);
  165.      
  166.      if (hints->flags & PMinSize) {
  167.       minwidth = hints->min_width;
  168.       minheight = hints->min_height;
  169.      } else {
  170.       minwidth = 0;
  171.       minheight = 0;
  172.      }
  173.      if (hints->flags & PMaxSize) {
  174.       maxwidth = max(hints->max_width, minwidth);
  175.       maxheight = max(hints->max_height, minheight);
  176.      } else {
  177.       maxwidth = DisplayWidth(dpy, scr);
  178.       maxheight = DisplayHeight(dpy, scr);
  179.      }
  180.      if (hints->flags & PResizeInc) {
  181.       xinc = hints->width_inc;
  182.       yinc = hints->height_inc;
  183.      } else {
  184.       xinc = 1;
  185.       yinc = 1;
  186.      }
  187.      if (hints->flags & PSize || hints->flags & USSize) {
  188.       defwidth = hints->width;
  189.       defheight = hints->height;
  190.      } else if (hints->flags&PMinSize) {
  191.       defwidth = hints->min_width;
  192.       defheight = hints->min_height;
  193.      } else if (hints->flags&PMaxSize) {
  194.       defwidth = hints->max_width;
  195.       defheight = hints->max_height;
  196.      } else {
  197.       long dummy;
  198.       XGetGeometry(dpy, window, &dummy, &dummy, &dummy,
  199.                &defwidth, &defheight, &dummy, &dummy);
  200.      }
  201.      
  202.      /* until there are better WM_HINTS, we'll assume that the client's
  203.       * minimum width and height are the appropriate offsets to subtract
  204.       * when resizing with an explicit resize increment.
  205.       */
  206.      if (hints->flags & PMinSize && hints->flags & PResizeInc) {
  207.       width_offset = hints->min_width;
  208.       height_offset = hints->min_height;
  209.      } else
  210.       width_offset = height_offset = 0;
  211.      
  212.      
  213.      XQueryPointer (dpy, RootWindow(dpy, scr), &root, &subw, 
  214.             &rootx, &rooty, &x1, &y1, &mask);
  215.      hsize = minwidth; 
  216.      vsize = minheight;
  217.      x2 = x1+hsize; 
  218.      y2 = y1+vsize;
  219.      
  220.      while (stop == FALSE) {
  221.       if ( (xb != max (x1, x2)) || (yb != max (y1, y2))
  222.           ||(xa != min (x1, x2)) || (ya != min (y1, y2)) ) {
  223.            xa = min (x1, x2);
  224.            ya = min (y1, y2);
  225.            xb = max (x1, x2);
  226.            yb = max (y1, y2);
  227.            for ( i = 0; i < PCOUNT; i += 4) {
  228.                     box[i].x = xa; box[i].y = ya;
  229.                     if (i+1 == PCOUNT) break;
  230.                     box[i+1].x = xb; box[i+1].y = ya;
  231.                     box[i+2].x = xb; box[i+2].y = yb;
  232.                     box[i+3].x = xa; box[i+3].y = yb;
  233.            }
  234.            doit = TRUE;
  235.       }
  236.       if (changed) {
  237.            int Hsize = (hsize - width_offset) / xinc;
  238.            int Vsize = (vsize - height_offset) / yinc;
  239.            int pos = 3;
  240.            
  241.            changed = FALSE;
  242.            text[nz - 7] = (Hsize>99) ? (Hsize / 100 + zero)    : ' ';
  243.            text[nz - 6] = (Hsize>9)  ? ((Hsize / 10) % 10 + zero)  : ' ';
  244.            text[nz - 5] = Hsize % 10 + zero;
  245.            if (Vsize>99) text[nz - pos--] = Vsize / 100 + zero;
  246.            if (Vsize>9)  text[nz - pos--] = (Vsize / 10) % 10 + zero;
  247.            text[nz - pos--]     = Vsize % 10 + zero;
  248.            while (pos>0) text[nz - pos--] = ' ';
  249.            XDrawImageString(dpy, pop, PopGC, IBW, IBW+PFontInfo->ascent,
  250.                 text, nz);
  251.       }
  252.       if (doit) {
  253.            XDrawLines(dpy, RootWindow(dpy, scr), invertGC, box, PCOUNT, 
  254.               CoordModeOrigin);
  255.       }
  256.       if (XPending(dpy) &&
  257.           XCheckMaskEvent(dpy, ButtonPressMask|ButtonReleaseMask, &e)) {
  258.            if ((chosen < 0) && (e.type == ButtonPress)) {
  259.             x1 = x2 = ((XButtonEvent *)&e)->x;
  260.             y1 = y2 = ((XButtonEvent *)&e)->y;
  261.             chosen = ((XButtonEvent *)&e)->button;
  262.             if (chosen == Button2)
  263.              change_cursor = TRUE;
  264.            }
  265.            else if ((e.type == ButtonRelease) &&
  266.                         ((((XButtonEvent *)&e)->button) == chosen)) {
  267.             x2 = ((XButtonEvent *)&e)->x;
  268.             y2 = ((XButtonEvent *)&e)->y;
  269.             stop = TRUE;
  270.            }
  271.            else
  272.             XQueryPointer (dpy, RootWindow(dpy, scr), &root, 
  273.                    &subw, &rootx, &rooty, &x2, &y2, &mask);
  274.       }
  275.       else        XQueryPointer (dpy, RootWindow(dpy, scr), &root, 
  276.                      &subw, &rootx, &rooty, &x2, &y2, &mask);
  277.       if (change_cursor) {
  278.            if ((x2 >= x1) && (y2 >= y1) &&
  279.            current_cursor != lr) {
  280.                     XChangeActivePointerGrab (dpy, events, lr, CurrentTime );
  281.                     current_cursor = lr;
  282.                }
  283.            else if ((x2 >= x1) && (y2 < y1) &&
  284.             current_cursor != ur) {
  285.                     XChangeActivePointerGrab (dpy, events, ur, CurrentTime );
  286.                     current_cursor = ur;
  287.            }
  288.            else if ((x2 < x1) && (y2 >= y1) &&
  289.             current_cursor != ll) {
  290.                     XChangeActivePointerGrab (dpy, events, ll, CurrentTime );
  291.                     current_cursor = ll;
  292.            }
  293.            else if ((x2 < x1) && (y2 < y1) &&
  294.             (current_cursor != ul)) {
  295.                     XChangeActivePointerGrab (dpy, events, ul, CurrentTime );
  296.                     current_cursor = ul;
  297.            }
  298.       }
  299.       if (chosen != Button2) {
  300.            x1 = x2;
  301.            y1 = y2;
  302.            if (chosen >= 0) {
  303.             x2 = defwidth;
  304.             if (chosen == Button1)
  305.              y2 = defheight;
  306.             else
  307.              y2 = (DisplayHeight(dpy, scr) - y1);
  308.             x2 = x1 + x2;
  309.             y2 = y1 + y2;
  310.            }
  311.       }
  312.       
  313.       dx = max(min(abs (x2 - x1), maxwidth), minwidth);
  314.       dx = makemult(dx-minwidth, xinc)+minwidth; 
  315.       dy = max(min(abs(y2 - y1), maxheight), minheight);
  316.       dy = makemult(dy-minheight, yinc)+minheight; 
  317.       
  318.       if (hints->flags & PAspect) {
  319.            if ((dx * hints->max_aspect.y > dy * hints->max_aspect.x)) {
  320.             delta = makemult((dx * hints->max_aspect.y /
  321.                       hints->max_aspect.x) - dy, yinc); 
  322.             if ((dy + delta) <= maxheight)
  323.              dy += delta;
  324.             else {
  325.              delta = makemult(dx - hints->max_aspect.x
  326.                       * dy/hints->max_aspect.y, xinc);
  327.              if ((dx - delta) >= minwidth)
  328.                   dx -= delta;
  329.             }
  330.            }
  331.            if (dx * hints->min_aspect.y < dy * hints->min_aspect.x) {
  332.             delta = makemult((hints->min_aspect.x *
  333.                       dy/hints->min_aspect.y) - dx, xinc);
  334.             if (dx + delta <= maxwidth)
  335.              dx += delta;
  336.             else {
  337.              delta = makemult(dy - (dx * hints->min_aspect.y /
  338.                         hints->min_aspect.x), yinc); 
  339.              if ((dy - delta) >= minheight)
  340.                   dy -= delta; 
  341.             }
  342.            }
  343.            
  344.       }
  345.       
  346.       if (dx != hsize) {
  347.            hsize = dx;
  348.            changed = TRUE;
  349.       }
  350.       if (dy != vsize) {
  351.            vsize = dy;
  352.            changed = TRUE;
  353.       }
  354.       if (x2 < x1)
  355.            x2 = x1 - dx;
  356.       else
  357.            x2 = x1 + dx;
  358.       
  359.       if (y2 < y1)
  360.            y2 = y1 - dy;
  361.       else
  362.            y2 = y1 + dy;
  363.      }
  364.      XUngrabPointer(dpy, CurrentTime);
  365.      
  366.      XDestroyWindow (dpy, pop);
  367.      XFreeCursor (dpy, ur);
  368.      XFreeCursor (dpy, ul);
  369.      XFreeCursor (dpy, lr);
  370.      XFreeCursor (dpy, ll);
  371.      free(name);
  372.      free(text);
  373.      *x = min(x1, x2);
  374.      *y = min(y1, y2);
  375.      *width = hsize;
  376.      *height = vsize;
  377.      XSync(dpy, FALSE);
  378.      Leave_void
  379. }
  380.