home *** CD-ROM | disk | FTP | other *** search
/ Frozen Fish 1: Amiga / FrozenFish-Apr94.iso / bbs / alib / d3xx / d386 / xlispstat.lha / XLispStat / src3.lzh / UNIX / X11slider.c < prev    next >
Encoding:
C/C++ Source or Header  |  1990-07-30  |  12.8 KB  |  434 lines

  1. /* X11slider - slider/scroll items for X11 dialogs                     */
  2. /* XLISP-STAT 2.1 Copyright (c) 1990, by Luke Tierney                  */
  3. /* Additions to Xlisp 2.1, Copyright (c) 1989 by David Michael Betz    */
  4. /* You may give out copies of this software; for conditions see the    */
  5. /* file COPYING included with this distribution.                       */
  6.  
  7. /***********************************************************************/
  8. /**                                                                   **/
  9. /**                    General Includes and Definitions               **/
  10. /**                                                                   **/
  11. /***********************************************************************/
  12.  
  13. #include <X11/Xlib.h>
  14. #include <X11/Xutil.h>
  15. #include <X11/Xos.h>
  16.  
  17. #include "dialogs.h"
  18.  
  19. extern Display *StX11Display();
  20. extern Point DialogStringSize();
  21. extern LVAL StX11ItemObject();
  22. extern char *checkstring();
  23.  
  24. typedef struct {
  25.   unsigned long fore, back;
  26. } ColorPair;
  27.  
  28. /* layout defines */
  29. # define BUTTON_SIZE 16
  30. # define MIN_SLIDER_HEIGHT  16
  31. # define MIN_SLIDER_WIDTH  250
  32. # define THUMB_WIDTH BUTTON_SIZE / 2
  33.  
  34. /***********************************************************************/
  35. /**                                                                   **/
  36. /**                        Global Variables                           **/
  37. /**                                                                   **/
  38. /***********************************************************************/
  39.  
  40. /* configuration parameters - should be set using the defaults database */
  41. extern XFontStruct *DialogFont;
  42. extern unsigned long DialogBorderColor;
  43. extern ColorPair DialogC;
  44. extern unsigned int dialog_border_width;
  45. extern int min_slider_width;
  46.  
  47. extern GC DialogGC, DialogRGC;
  48.  
  49. extern XContext ObjectContext, Button1Context,
  50.   Button2Context, ThumbContext;
  51.  
  52. extern Pixmap LeftSliderPM, RightSliderPM;
  53. extern Cursor DoubleArrowCursor, RightArrowCursor, LeftArrowCursor,
  54.   ArrowCursor;
  55.  
  56. /***********************************************************************/
  57. /**                                                                   **/
  58. /**                          Slider Items                             **/
  59. /**                                                                   **/
  60. /***********************************************************************/
  61.  
  62. static adjust_slider(item)
  63.      LVAL item;
  64. {
  65.   Display *dpy = StX11Display();
  66.   LVAL win_id;
  67.   LVAL s_window_id = xlenter("WINDOW-ID");
  68.   Window win, thumb;
  69.   Point size;
  70.   int left, low, high, val, width;
  71.   double x;
  72.  
  73.   win_id = slot_value(item, s_window_id);
  74.   if (fixp(win_id)) {
  75.     win = (Window) getfixnum(win_id);
  76.     size = ListToPoint(slot_value(item, s_size));
  77.     low = getfixnum(slot_value(item, s_min_value));
  78.     high = getfixnum(slot_value(item, s_max_value));
  79.     val = getfixnum(slot_value(item, s_value));
  80.     width = size.h - 2 * BUTTON_SIZE - THUMB_WIDTH;
  81.     if (low < high) {
  82.       x = ((double) (val - low)) / ((double) (high - low));
  83.       left = BUTTON_SIZE + x * width;
  84.       left = max(BUTTON_SIZE, min(left, width + BUTTON_SIZE));
  85.     }
  86.     else left = BUTTON_SIZE;
  87.     if (XFindContext(dpy, win, ThumbContext, &thumb) != 0)
  88.       xlfail("can't find thumb context");
  89.     XMoveWindow(dpy, thumb, left, 0);
  90.   }
  91. }
  92.  
  93. static track_thumb(dpy, win, report, item)
  94.      Display *dpy;
  95.      Window win;
  96.      XEvent report;
  97.      LVAL item;
  98. {
  99.   Point size;
  100.   int low, high, val, old_val, width, page, up, done = FALSE;
  101.   double x;
  102.  
  103.   size = ListToPoint(slot_value(item, s_size));
  104.   low = getfixnum(slot_value(item, s_min_value));
  105.   high = getfixnum(slot_value(item, s_max_value));
  106.   width = size.h - 2 * BUTTON_SIZE - THUMB_WIDTH;
  107.  
  108.   switch (report.xbutton.button) {
  109.   case Button1:
  110.   case Button3:
  111.     up = (report.xbutton.button == Button3) ? TRUE : FALSE;
  112.     XDefineCursor(dpy, win, (up) ? RightArrowCursor : LeftArrowCursor); 
  113.     old_val = low - 1;  /* an "impossible" value */
  114.     while (! done) {
  115.       if (XCheckTypedEvent(dpy, ButtonRelease, &report)) done = TRUE;
  116.       else{
  117.     val = getfixnum(slot_value(item, s_value));
  118.     page = getfixnum(slot_value(item, s_page_increment));
  119.     if (up) val += page;
  120.     else val -= page;
  121.     val = max(low, min(val, high));
  122.     DialogScrollItemValue(item, TRUE, val);
  123.     if (val != old_val) send_message(item, sk_scroll_action);
  124.     old_val = val;
  125.     XSync(dpy, FALSE);
  126.       }
  127.     }
  128.     break; 
  129.   case Button2: 
  130.     if (width > 0)
  131.       x = ((double) report.xbutton.x - BUTTON_SIZE) / ((double) width);
  132.     else x = 0.0;
  133.     val = low + x * (high - low);
  134.     val = max(low, min(val, high));
  135.     DialogScrollItemValue(item, TRUE, val);
  136.     XGrabPointer(dpy, win, TRUE, ButtonMotionMask,
  137.                  GrabModeAsync, GrabModeAsync, win, 
  138.          DoubleArrowCursor, CurrentTime);
  139.     while (! done) {
  140.       XNextEvent(dpy, &report);
  141.       switch (report.type) {
  142.       case ButtonRelease:
  143.     done = TRUE;
  144.     break;
  145.       case MotionNotify:
  146.     x = ((double) report.xmotion.x - BUTTON_SIZE) / ((double) width);
  147.     val = low + x * (high - low);
  148.     val = max(low, min(val, high));
  149.     DialogScrollItemValue(item, TRUE, val);
  150.     break;
  151.       default:
  152.     break;
  153.       }
  154.     }
  155.     XUngrabPointer(dpy, CurrentTime);
  156.     send_message(item, sk_do_action);
  157.     XSync(dpy, FALSE);
  158.     break;
  159.   }
  160.  
  161.   XDefineCursor(dpy, win, DoubleArrowCursor);
  162. }
  163.  
  164. static LVAL slider_handler(report, modal)
  165.      XEvent report;
  166.      int modal;
  167. {
  168.   Display *dpy = StX11Display();
  169.   Window win;
  170.   LVAL item;
  171.   LVAL result = NIL;
  172.  
  173.   win = report.xany.window;
  174.   item = StX11ItemObject(dpy, win);
  175.   if (item != NIL) {
  176.     switch (report.type) {
  177.     case Expose:
  178.       break;
  179.     case ButtonPress:
  180.       track_thumb(dpy, win, report, item);
  181. /*
  182.       if (! modal) {
  183.     send_message(item, sk_do_action);
  184.     XSync(dpy, FALSE);
  185.       }
  186. */
  187. /*      send_message(item, sk_do_action);*/
  188.       XSync(dpy, FALSE);
  189.       break;
  190.     case ButtonRelease:
  191.       break;
  192.     default: 
  193.       break;
  194.     }
  195.   }
  196.   return(result);
  197. }
  198.  
  199. static LVAL button_handler(report, is_right)
  200.      XEvent report;
  201.      int is_right;
  202. {
  203.   Display *dpy = StX11Display();
  204.   Window win;
  205.   LVAL item;
  206.   LVAL result = NIL;
  207.   int low, high, val, done, old_val;
  208.  
  209.   win = report.xany.window;
  210.   item = StX11ItemObject(dpy, win);
  211.   if (item != NIL) {
  212.     switch (report.type) {
  213.     case ButtonPress:
  214.       done = FALSE;
  215.       low = getfixnum(slot_value(item, s_min_value));
  216.       high = getfixnum(slot_value(item, s_max_value));
  217.       old_val = low - 1; /* an "impossible" value */
  218.       while (! done) {
  219.     if (XCheckTypedEvent(dpy, ButtonRelease, &report)) done = TRUE;
  220.     else {
  221.       val = getfixnum(slot_value(item, s_value));
  222.       if (is_right) val++;
  223.       else val--;
  224.       val = max(low, min(val, high));
  225.       DialogScrollItemValue(item, TRUE, val);
  226.       if (val != old_val) send_message(item, sk_scroll_action);
  227.       old_val = val;
  228.       XSync(dpy, FALSE);
  229.     }
  230.       }
  231.       /* send_message(item, sk_do_action); */
  232.       break;
  233.     default: 
  234.       break;
  235.     }
  236.   }
  237.   return(result);
  238. }
  239.  
  240. static LVAL left_button_handler(report, modal)
  241.      XEvent report;
  242.      int modal;
  243. {
  244.   return(button_handler(report, FALSE));
  245. }
  246.  
  247. static LVAL right_button_handler(report, modal)
  248.      XEvent report;
  249.      int modal;
  250. {
  251.   return(button_handler(report, TRUE));
  252. }
  253.  
  254. InstallScrollItem(win, item)
  255.      Window win;
  256.      LVAL item;
  257. {
  258.   Display *dpy = StX11Display();
  259.   Point loc, size;
  260.   Window slider, button1, button2, thumb;
  261.   LVAL s_window_id = xlenter("WINDOW-ID");
  262.  
  263.   check_value(item);
  264.   loc = ListToPoint(slot_value(item, s_location));
  265.   size = ListToPoint(slot_value(item, s_size));
  266.   size.v = BUTTON_SIZE;
  267.   slider = XCreateSimpleWindow(dpy, win, loc.h, loc.v, size.h, size.v,
  268.                    dialog_border_width, 
  269.                    DialogBorderColor, DialogC.back);
  270.   XSelectInput(dpy, slider, 
  271.            ExposureMask | ButtonPressMask | ButtonReleaseMask);
  272.   XDefineCursor(dpy, slider, DoubleArrowCursor);
  273.  
  274.   button1 = XCreateSimpleWindow(dpy, slider, 
  275.                 -dialog_border_width, -dialog_border_width, 
  276.                 BUTTON_SIZE, BUTTON_SIZE,
  277.                 dialog_border_width,
  278.                 DialogBorderColor, DialogC.back);
  279.   XSelectInput(dpy, button1,
  280.                ExposureMask | ButtonPressMask | ButtonReleaseMask);
  281.   XSetWindowBackgroundPixmap(dpy, button1, LeftSliderPM);
  282. #ifdef DODO
  283.   XDefineCursor(dpy, button1, LeftArrowCursor);
  284. #endif DODO
  285.   XDefineCursor(dpy, button1, ArrowCursor);
  286.  
  287.   button2 = XCreateSimpleWindow(dpy, slider, 
  288.                 size.h - BUTTON_SIZE, -dialog_border_width, 
  289.                 BUTTON_SIZE, BUTTON_SIZE,
  290.                 dialog_border_width,
  291.                                 DialogBorderColor, DialogC.back);
  292.   XSelectInput(dpy, button2,
  293.                ExposureMask | ButtonPressMask | ButtonReleaseMask);
  294.   XSetWindowBackgroundPixmap(dpy, button2, RightSliderPM);
  295. #ifdef DODO
  296.   XDefineCursor(dpy, button2, RightArrowCursor);
  297. #endif DODO
  298.   XDefineCursor(dpy, button2, ArrowCursor);
  299.   
  300.   thumb = XCreateSimpleWindow(dpy, slider, BUTTON_SIZE, 0,
  301.                   THUMB_WIDTH, BUTTON_SIZE,
  302.                   0, DialogBorderColor, DialogC.fore);
  303.  
  304.   set_slot_value(item, s_window_id, cvfixnum((FIXTYPE) slider));
  305.  
  306.   install_dialog_item_handler(dpy, slider, slider_handler, item);
  307.   if (XSaveContext(dpy, slider, ObjectContext, (XContext) item) != 0)
  308.     xlfail("could not install object in window");
  309.   if (XSaveContext(dpy, slider, ThumbContext, (XContext) thumb) != 0)
  310.     xlfail("could not install thumb in slider");
  311.  
  312.   if (XSaveContext(dpy, slider, Button1Context, (XContext) button1) != 0)
  313.     xlfail("could not install left button in slider");
  314.   install_dialog_item_handler(dpy, button1, left_button_handler, item);
  315.   if (XSaveContext(dpy, button1, ObjectContext, (XContext) item) != 0)
  316.     xlfail("could not install object in window");
  317.  
  318.   if (XSaveContext(dpy, slider, Button2Context, (XContext) button2) != 0)
  319.     xlfail("could not install right button in slider");
  320.   install_dialog_item_handler(dpy, button2, right_button_handler, item);
  321.   if (XSaveContext(dpy, button2, ObjectContext, (XContext) item) != 0)
  322.     xlfail("could not install object in window");
  323.  
  324.   adjust_slider(item);
  325.  
  326.   XMapSubwindows(dpy, slider);
  327. }
  328.  
  329. DeleteScrollItem(win, item)
  330.      Window win;
  331.      LVAL item;
  332. {
  333.   Display *dpy = StX11Display();
  334.   Window slider, button1, button2;
  335.   LVAL s_window_id = xlenter("WINDOW-ID");
  336.  
  337.   slider = (Window) getfixnum(slot_value(item, s_window_id));
  338.  
  339.   delete_dialog_item_handler(dpy, slider);
  340.   if (XDeleteContext(dpy, slider, ObjectContext) != 0)
  341.     xlfail("cound not delete object context");
  342.   if (XDeleteContext(dpy, slider, ThumbContext) != 0)
  343.     xlfail("cound not delete thumb context");
  344.  
  345.   if (XFindContext(dpy, slider, Button1Context, &button1) != 0)
  346.     xlfail("can't find left button context");
  347.   if (XDeleteContext(dpy, slider, Button1Context) != 0)
  348.     xlfail("cound not delete left button context");
  349.   delete_dialog_item_handler(dpy, button1);
  350.   if (XDeleteContext(dpy, button1, ObjectContext) != 0)
  351.     xlfail("cound not delete object context");
  352.  
  353.   if (XFindContext(dpy, slider, Button2Context, &button2) != 0)
  354.     xlfail("can't find right button context");
  355.   if (XDeleteContext(dpy, slider, Button2Context) != 0)
  356.     xlfail("cound not delete right button context");
  357.   delete_dialog_item_handler(dpy, button2);
  358.   if (XDeleteContext(dpy, button2, ObjectContext) != 0)
  359.     xlfail("cound not delete object context");
  360.  
  361.   set_slot_value(item, s_window_id, NIL);
  362. }
  363.  
  364. DialogScrollGetDefaultSize(item, width, height)
  365.      LVAL item;
  366.      int *width, *height;
  367. {
  368.   if (width != nil) *width = MIN_SLIDER_WIDTH;
  369.   if (height != nil) *height = MIN_SLIDER_HEIGHT;
  370. }
  371.  
  372. LVAL DialogScrollItemValue(item, set, value)
  373.      LVAL item;
  374.      int set, value;
  375. {
  376.   if (set) {
  377.     set_slot_value(item, s_value, cvfixnum((FIXTYPE) value));
  378.     check_value(item);
  379.     adjust_slider(item);
  380.   }
  381.   else check_value(item);
  382.  
  383.   return(slot_value(item, s_value));
  384. }
  385.  
  386. LVAL DialogScrollItemMin(item, set, value) 
  387.      LVAL item;
  388.      int set, value;
  389. {
  390.   if (set) {
  391.     set_slot_value(item, s_min_value, cvfixnum((FIXTYPE) value));
  392.     check_value(item);
  393.     adjust_slider(item);
  394.   }
  395.   return(slot_value(item, s_min_value));
  396. }
  397.  
  398. LVAL DialogScrollItemMax(item, set, value)
  399.      LVAL item;
  400.      int set, value;
  401. {
  402.   if (set) {
  403.     set_slot_value(item, s_max_value, cvfixnum((FIXTYPE) value));
  404.     check_value(item);
  405.     adjust_slider(item);
  406.   }
  407.   return(slot_value(item, s_max_value));
  408. }
  409.  
  410. static check_value(item)
  411.      LVAL item;
  412. {
  413.   LVAL low, high, value;
  414.   int ilow, ihigh, ivalue;
  415.  
  416.   low = slot_value(item, s_min_value);
  417.   high = slot_value(item, s_max_value);
  418.   value = slot_value(item, s_value);
  419.  
  420.   ilow = (fixp(low)) ? getfixnum(low): 0;
  421.   ihigh = (fixp(high)) ? getfixnum(high) : 100;
  422.   ivalue = (fixp(value)) ? getfixnum(value) : ilow;
  423.  
  424.   if (ilow >= ihigh) ihigh = ilow + 1;
  425.   ivalue = max(ilow, min(ihigh, ivalue));
  426.  
  427.   if (! fixp(low) || ilow != getfixnum(low)) 
  428.     set_slot_value(item, s_min_value, cvfixnum((FIXTYPE) ilow));
  429.   if (! fixp(high) || ihigh != getfixnum(high)) 
  430.     set_slot_value(item, s_max_value, cvfixnum((FIXTYPE) ihigh));
  431.   if (! fixp(value) || ivalue != getfixnum(value)) 
  432.     set_slot_value(item, s_value, cvfixnum((FIXTYPE) ivalue));
  433. }
  434.