home *** CD-ROM | disk | FTP | other *** search
/ InfoMagic Source Code 1993 July / THE_SOURCE_CODE_CD_ROM.iso / X / mit / clients / bitmap / Handlers.c < prev    next >
Encoding:
C/C++ Source or Header  |  1991-07-24  |  17.9 KB  |  671 lines

  1. /*
  2.  * $XConsortium: Handlers.c,v 1.10 91/07/24 15:25:01 converse Exp $
  3.  *
  4.  * Copyright 1989 Massachusetts Institute of Technology
  5.  *
  6.  * Permission to use, copy, modify, distribute, and sell this software and its
  7.  * documentation for any purpose is hereby granted without fee, provided that
  8.  * the above copyright notice appear in all copies and that both that
  9.  * copyright notice and this permission notice appear in supporting
  10.  * documentation, and that the name of M.I.T. not be used in advertising or
  11.  * publicity pertaining to distribution of the software without specific,
  12.  * written prior permission.  M.I.T. makes no representations about the
  13.  * suitability of this software for any purpose.  It is provided "as is"
  14.  * without express or implied warranty.
  15.  *
  16.  * M.I.T. DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL
  17.  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL M.I.T.
  18.  * BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
  19.  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
  20.  * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
  21.  * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  22.  *
  23.  * Author:  Davor Matic, MIT X Consortium
  24.  */
  25.  
  26. #include <X11/StringDefs.h>
  27. #include <X11/IntrinsicP.h>
  28. #include "BitmapP.h"
  29.     
  30. #include <stdio.h>
  31. #include <string.h>
  32. #include <math.h>
  33.  
  34. #ifndef abs
  35. #define abs(x)                        (((int)(x) > 0) ? (x) : -(x))
  36. #endif
  37. #define min(x, y)                     (((int)(x) < (int)(y)) ? (x) : (y))
  38. #define max(x, y)                     (((int)(x) > (int)(y)) ? (x) : (y))
  39.  
  40. #include "Requests.h"
  41.  
  42. extern Boolean DEBUG;
  43.  
  44. /*****************************************************************************
  45.  *                                  Handlers                                 *
  46.  *****************************************************************************/
  47.  
  48. #define QueryInSquare(BW, x, y, square_x, square_y)\
  49.     ((InBitmapX(BW, x) == (square_x)) &&\
  50.      (InBitmapY(BW, y) == (square_y)))
  51.  
  52.  
  53. void DragOnePointHandler(w, client_data, event, cont) /* ARGSUSED */
  54.      Widget       w;
  55.      XtPointer    client_data;
  56.      XEvent      *event;
  57.      Boolean     *cont;
  58. {
  59.     BWStatus *status = (BWStatus *)client_data;
  60.     BitmapWidget BW = (BitmapWidget) w;
  61.  
  62.     if (DEBUG)
  63.     fprintf(stderr, "D1PH ");
  64.  
  65.     switch (event->type) {
  66.     
  67.     case ButtonPress:
  68.     if (event->xbutton.state != status->state) return;
  69.     if (!QuerySet(status->at_x, status->at_y)) {
  70.         BWStoreToBuffer(w);
  71.         status->value = Value(BW, event->xbutton.button);
  72.         status->btime = event->xbutton.time;
  73.         status->at_x = InBitmapX(BW, event->xbutton.x);
  74.         status->at_y = InBitmapY(BW, event->xbutton.y);
  75.         status->success = (Boolean) status->draw;
  76.         if (status->draw)
  77.         (*status->draw)(w,
  78.                 status->at_x, status->at_y, status->value);
  79.     }
  80.     break;
  81.     
  82.     case ButtonRelease:
  83.     if (QuerySet(status->at_x, status->at_y)) {
  84.         status->value = Value(BW, event->xbutton.button);
  85.         status->btime = event->xbutton.time;
  86.         status->at_x = InBitmapX(BW, event->xbutton.x);
  87.         status->at_y = InBitmapY(BW, event->xbutton.y);
  88.         status->success = (Boolean) status->draw;
  89.         /* SUPPRESS 701 */
  90.         BWTerminateRequest(w, TRUE); 
  91.     }
  92.     break;
  93.  
  94.     case MotionNotify:
  95.     if (QuerySet(status->at_x, status->at_y)) {
  96.         if (!QueryInSquare(BW, event->xmotion.x, event->xmotion.y,
  97.                    status->at_x, status->at_y)) {
  98.         status->at_x = InBitmapX(BW, event->xmotion.x);
  99.         status->at_y = InBitmapY(BW, event->xmotion.y);
  100.         if (status->draw)
  101.             (*status->draw)(w,
  102.                     status->at_x, status->at_y, status->value);
  103.         }
  104.     }
  105.     break;
  106.  
  107.     }
  108. }
  109.  
  110. void DragOnePointEngage(w, status, draw, state)
  111.     Widget      w;
  112.     BWStatus   *status;
  113.     void      (*draw)();
  114.     int        *state;
  115. {
  116.     
  117.     status->at_x = NotSet;
  118.     status->at_y = NotSet;
  119.     status->draw = draw;
  120.     status->success = False;
  121.     status->state = *state;
  122.     
  123.     XtAddEventHandler(w,
  124.               ButtonPressMask | ButtonReleaseMask | PointerMotionMask,
  125.               FALSE, DragOnePointHandler, (XtPointer)status);
  126. }
  127.  
  128. /* ARGSUSED */
  129. void DragOnePointTerminate(w, status, client_data)
  130.     Widget     w;
  131.     BWStatus  *status;
  132.     caddr_t    client_data;
  133. {
  134.     
  135.     if (status->success) {
  136.     BWChangeNotify(w, NULL, NULL);
  137.     BWSetChanged(w);
  138.     }
  139.     
  140.     XtRemoveEventHandler(w,
  141.          ButtonPressMask | ButtonReleaseMask | PointerMotionMask,
  142.          FALSE, DragOnePointHandler, (XtPointer)status);
  143.     
  144. }
  145.  
  146. void OnePointHandler(w, client_data, event, cont) /* ARGSUSED */
  147.     Widget       w;
  148.     XtPointer    client_data;
  149.     XEvent      *event;
  150.     Boolean     *cont;
  151. {
  152.     BWStatus    *status = (BWStatus *)client_data;
  153.     BitmapWidget BW = (BitmapWidget) w;
  154.     
  155.     if (DEBUG)
  156.     fprintf(stderr, "1PH ");
  157.  
  158.     switch (event->type) {
  159.     
  160.     case Expose:
  161.     if (QuerySet(status->at_x, status->at_y)) {
  162.         BWClip(w, event->xexpose.x, event->xexpose.y,
  163.            event->xexpose.width, event->xexpose.height);
  164.         if (status->draw)
  165.         (*status->draw)(w,
  166.                 status->at_x, status->at_y, Highlight);
  167.         
  168.         BWUnclip(w);
  169.     }
  170.     break;
  171.     
  172.     case ButtonPress:
  173.     if (event->xbutton.state != status->state) return;
  174.     if (!QuerySet(status->at_x, status->at_y)) {
  175.         status->value = Value(BW, event->xbutton.button);
  176.         status->btime = event->xbutton.time;
  177.         status->at_x = InBitmapX(BW, event->xbutton.x);
  178.         status->at_y = InBitmapY(BW, event->xbutton.y);
  179.         if (status->draw)
  180.         (*status->draw)(w,
  181.                 status->at_x, status->at_y, Highlight);
  182.     }
  183.     break;
  184.     
  185.     case ButtonRelease:
  186.     if (QuerySet(status->at_x, status->at_y)) {
  187.         if (status->draw)
  188.         (*status->draw)(w,
  189.                 status->at_x, status->at_y, Highlight);
  190.         
  191.         status->value = Value(BW, event->xbutton.button);
  192.         status->btime = event->xbutton.time;
  193.         status->at_x = InBitmapX(BW, event->xbutton.x);
  194.         status->at_y = InBitmapY(BW, event->xbutton.y);
  195.         status->success = True;
  196.         
  197.         BWTerminateRequest(w, TRUE);
  198.     }
  199.     break;
  200.     
  201.     case MotionNotify:
  202.     if (QuerySet(status->at_x, status->at_y)) {
  203.         if (!QueryInSquare(BW, event->xmotion.x, event->xmotion.y,
  204.                    status->at_x, status->at_y)) {
  205.         if (status->draw)
  206.             (*status->draw)(w,
  207.                     status->at_x, status->at_y, Highlight);
  208.         status->at_x = InBitmapX(BW, event->xmotion.x);
  209.         status->at_y = InBitmapY(BW, event->xmotion.y);
  210.         if (status->draw)
  211.             (*status->draw)(w,
  212.                     status->at_x, status->at_y, Highlight);
  213.         }
  214.     }      
  215.     break;
  216.     }
  217. }
  218.  
  219. void OnePointEngage(w, status, draw, state)
  220.     Widget      w;
  221.     BWStatus   *status;
  222.     void      (*draw)();
  223.     int        *state;
  224. {
  225.     status->at_x = NotSet;
  226.     status->at_y = NotSet;
  227.     status->draw = draw;
  228.     status->success = False;
  229.     status->state = *state;
  230.  
  231.     XtAddEventHandler(w,
  232.               ButtonPressMask | ButtonReleaseMask | 
  233.               ExposureMask | PointerMotionMask,
  234.               FALSE, OnePointHandler, (XtPointer)status);
  235. }
  236.  
  237. void OnePointImmediateEngage(w, status, draw, state)
  238.     Widget      w;
  239.     BWStatus   *status;
  240.     void      (*draw)();
  241.     int        *state;
  242. {
  243.     status->at_x = 0;
  244.     status->at_y = 0;
  245.     status->draw = draw;
  246.     status->success = False;
  247.     status->state = *state;
  248.     
  249.     if (status->draw)
  250.     (*status->draw)(w,
  251.             status->at_x, status->at_y, Highlight);
  252.     
  253.     XtAddEventHandler(w,
  254.               ButtonPressMask | ButtonReleaseMask | 
  255.               ExposureMask | PointerMotionMask,
  256.               FALSE, OnePointHandler, (XtPointer)status);
  257. }
  258.  
  259. void OnePointTerminate(w, status, draw)
  260.     Widget     w;
  261.     BWStatus  *status;
  262.     void     (*draw)();
  263. {
  264.     
  265.     if (status->success && draw) {
  266.     BWStoreToBuffer(w);
  267.     (*draw)(w,
  268.         status->at_x, status->at_y,
  269.         status->value);
  270.     BWChangeNotify(w, NULL, NULL);
  271.     BWSetChanged(w);
  272.     }    
  273.     else
  274.     if (QuerySet(status->at_x, status->at_y))
  275.         if (status->draw)
  276.         (*status->draw)(w,
  277.                 status->at_x, status->at_y, Highlight);
  278.     
  279.     XtRemoveEventHandler(w,
  280.              ButtonPressMask | ButtonReleaseMask | 
  281.              ExposureMask | PointerMotionMask,
  282.              FALSE, OnePointHandler, (XtPointer)status);
  283. }
  284.  
  285. void OnePointTerminateTransparent(w, status, draw)
  286.     Widget     w;
  287.     BWStatus  *status;
  288.     void     (*draw)();
  289. {
  290.     
  291.     if (status->success && draw)
  292.     (*draw)(w,
  293.         status->at_x, status->at_y,
  294.         status->value);
  295.     else
  296.     if (QuerySet(status->at_x, status->at_y))
  297.         if (status->draw)
  298.         (*status->draw)(w,
  299.                 status->at_x, status->at_y, Highlight);
  300.     
  301.     XtRemoveEventHandler(w,
  302.              ButtonPressMask | ButtonReleaseMask | 
  303.              ExposureMask | PointerMotionMask,
  304.              FALSE, OnePointHandler, (XtPointer)status);
  305.     
  306. }
  307.  
  308.  
  309. void TwoPointsHandler(w, client_data, event, cont) /* ARGSUSED */
  310.     Widget      w;
  311.     XtPointer  client_data;
  312.     XEvent     *event;
  313.     Boolean    *cont;
  314. {
  315.     BitmapWidget BW = (BitmapWidget) w;
  316.     BWStatus   *status = (BWStatus *)client_data;
  317.     if (DEBUG)
  318.     fprintf(stderr, "2PH ");
  319.     
  320.     switch (event->type) {
  321.     
  322.     case Expose:
  323.     if (QuerySet(status->from_x, status->from_y) && 
  324.         QuerySet(status->to_x, status->to_y)) {
  325.         BWClip(w, event->xexpose.x, event->xexpose.y,
  326.            event->xexpose.width, event->xexpose.height);
  327.         if (status->draw)
  328.         (*status->draw)(w,
  329.                 status->from_x, status->from_y, 
  330.                 status->to_x, status->to_y, Highlight);
  331.         BWUnclip(w);
  332.     }
  333.     break;
  334.     
  335.     case ButtonPress:
  336.     if (event->xbutton.state != status->state) return;
  337.     if (!QuerySet(status->from_x, status->from_y)) {
  338.         status->value = Value(BW, event->xbutton.button);
  339.         status->btime = event->xbutton.time;
  340.         status->from_x = InBitmapX(BW, event->xbutton.x);
  341.         status->from_y = InBitmapY(BW, event->xbutton.y);
  342.         status->to_x = InBitmapX(BW, event->xbutton.x);
  343.         status->to_y = InBitmapY(BW, event->xbutton.y);
  344.         if (status->draw)
  345.         (*status->draw)(w,
  346.                 status->from_x, status->from_y, 
  347.                 status->to_x, status->to_y, Highlight);
  348.     }
  349.     break;
  350.     
  351.     case ButtonRelease:
  352.     if (QuerySet(status->from_x, status->from_y)) {
  353.         if (status->draw)
  354.         (*status->draw)(w,
  355.                 status->from_x, status->from_y, 
  356.                 status->to_x, status->to_y, Highlight);
  357.         status->value = Value(BW, event->xbutton.button);
  358.         status->btime = event->xbutton.time;        
  359.         status->to_x = InBitmapX(BW, event->xbutton.x);
  360.         status->to_y = InBitmapY(BW, event->xbutton.y);
  361.         status->success = True;
  362.         
  363.         BWTerminateRequest(w, TRUE);
  364.     }
  365.     break;
  366.     
  367.     case MotionNotify:
  368.     if (QuerySet(status->from_x, status->from_y)) {
  369.         if (QuerySet(status->to_x, status->to_y)) {
  370.         if (!QueryInSquare(BW, event->xmotion.x, event->xmotion.y,
  371.                    status->to_x, status->to_y)) {
  372.             if (status->draw)
  373.             (*status->draw)(w,
  374.                     status->from_x, status->from_y, 
  375.                     status->to_x, status->to_y, Highlight);
  376.             status->to_x = InBitmapX(BW, event->xmotion.x);
  377.             status->to_y = InBitmapY(BW, event->xmotion.y);
  378.             if (status->draw)
  379.             (*status->draw)(w,
  380.                     status->from_x, status->from_y, 
  381.                     status->to_x, status->to_y, Highlight);
  382.         }
  383.         }
  384.         else {
  385.         status->to_x = InBitmapX(BW, event->xmotion.x);
  386.         status->to_y = InBitmapY(BW, event->xmotion.y);
  387.         if (status->draw)
  388.             (*status->draw)(w,
  389.                     status->from_x, status->from_y, 
  390.                     status->to_x, status->to_y, Highlight);
  391.         }
  392.     }
  393.     break;
  394.     }
  395. }
  396.  
  397. void TwoPointsEngage(w, status, draw, state)
  398.     Widget     w;
  399.     BWStatus  *status;
  400.     void     (*draw)();
  401.     int       *state;
  402. {
  403.     
  404.     status->from_x = NotSet;
  405.     status->from_y = NotSet;
  406.     status->to_x = NotSet;
  407.     status->to_y = NotSet;
  408.     status->draw = draw;
  409.     status->success = False;
  410.     status->state = *state;
  411.  
  412.     XtAddEventHandler(w,
  413.               ButtonPressMask | ButtonReleaseMask | 
  414.               ExposureMask | PointerMotionMask,
  415.               FALSE, TwoPointsHandler, (XtPointer)status);
  416. }
  417.  
  418. void TwoPointsTerminate(w, status, draw)
  419.     Widget    w;
  420.     BWStatus *status;
  421.     void    (*draw)();
  422. {
  423.     
  424.     if (status->success && draw) {
  425.     BWStoreToBuffer(w);
  426.     (*draw)(w,
  427.         status->from_x, status->from_y,
  428.         status->to_x, status->to_y,
  429.         status->value);
  430.     BWChangeNotify(w, NULL, NULL);
  431.     BWSetChanged(w);
  432.     }
  433.     else
  434.     if (QuerySet(status->from_x, status->from_y) && 
  435.         QuerySet(status->to_x, status->to_y))
  436.         if (status->draw)
  437.         (*status->draw)(w,
  438.                 status->from_x, status->from_y, 
  439.                 status->to_x, status->to_y, Highlight);
  440.     
  441.     XtRemoveEventHandler(w,
  442.              ButtonPressMask | ButtonReleaseMask | 
  443.              ExposureMask | PointerMotionMask,
  444.              FALSE, TwoPointsHandler, (XtPointer)status);
  445. }
  446.  
  447. void TwoPointsTerminateTransparent(w, status, draw)
  448.     Widget    w;
  449.     BWStatus *status;
  450.     void    (*draw)();
  451. {
  452.     
  453.     if (status->success && draw)
  454.     (*draw)(w,
  455.         status->from_x, status->from_y,
  456.         status->to_x, status->to_y,
  457.         status->value);
  458.     else
  459.     if (QuerySet(status->from_x, status->from_y) && 
  460.         QuerySet(status->to_x, status->to_y))
  461.         if (status->draw)
  462.         (*status->draw)(w,
  463.                 status->from_x, status->from_y, 
  464.                 status->to_x, status->to_y, Highlight);
  465.     
  466.     XtRemoveEventHandler(w,
  467.              ButtonPressMask | ButtonReleaseMask | 
  468.              ExposureMask | PointerMotionMask,
  469.              FALSE, TwoPointsHandler, (XtPointer)status);
  470. }
  471.  
  472. void TwoPointsTerminateTimed(w, status, draw)
  473.     Widget    w;
  474.     BWStatus *status;
  475.     void    (*draw)();
  476. {
  477.     
  478.     if (status->success && draw)
  479.     (*draw)(w,
  480.         status->from_x, status->from_y,
  481.         status->to_x, status->to_y,
  482.         status->btime);
  483.     else
  484.     if (QuerySet(status->from_x, status->from_y) && 
  485.         QuerySet(status->to_x, status->to_y))
  486.         if (status->draw)
  487.         (*status->draw)(w,
  488.                 status->from_x, status->from_y, 
  489.                 status->to_x, status->to_y, Highlight);
  490.     
  491.     XtRemoveEventHandler(w,
  492.              ButtonPressMask | ButtonReleaseMask | 
  493.              ExposureMask | PointerMotionMask,
  494.              FALSE, TwoPointsHandler, (XtPointer)status);
  495. }
  496.  
  497. /* ARGSUSED */
  498. void Interface(w, status, action)
  499.     Widget     w;
  500.     caddr_t    status;
  501.     void     (*action)();
  502. {
  503.      (*action)(w);
  504. }
  505.  
  506. void Paste(w, at_x, at_y, value)
  507.     Widget    w;
  508.     Position  at_x, at_y;
  509.     int       value;
  510. {
  511.     BitmapWidget    BW = (BitmapWidget) w;
  512.     BWStatus       *my_status;
  513.     BWRequest       request;
  514.  
  515.     my_status = (BWStatus *) 
  516.     BW->bitmap.request_stack[BW->bitmap.current].status;
  517.  
  518.     my_status->draw = NULL;
  519.  
  520.    request = (BWRequest)
  521.    BW->bitmap.request_stack[BW->bitmap.current].request->terminate_client_data;
  522.     
  523.     BWTerminateRequest(w, FALSE);
  524.     
  525.     if ((at_x == max(BW->bitmap.mark.from_x, min(at_x, BW->bitmap.mark.to_x)))
  526.     &&
  527.       (at_y == max(BW->bitmap.mark.from_y, min(at_y, BW->bitmap.mark.to_y)))) {
  528.     
  529.     BWStatus *status;
  530.     
  531.     if (DEBUG)
  532.         fprintf(stderr, "Prepaste request: %s\n", request);
  533.     
  534.     BWEngageRequest(w, request, False, (char *)&(my_status->state), sizeof(int));
  535.     
  536.     status = (BWStatus *) 
  537.         BW->bitmap.request_stack[BW->bitmap.current].status;
  538.     
  539.     status->at_x = at_x;
  540.     status->at_y = at_y;
  541.     status->value = value;
  542.     (*status->draw) (w, at_x, at_y, Highlight);    
  543.     }
  544.     else {
  545.  
  546.     BWStatus *status;
  547.     
  548.       BWEngageRequest(w, MarkRequest, False, (char *)&(my_status->state), sizeof(int));
  549.     
  550.     status = (BWStatus *) 
  551.         BW->bitmap.request_stack[BW->bitmap.current].status;
  552.     
  553.     status->from_x = status->to_x = at_x;
  554.     status->from_y = status->to_y = at_y;
  555.     status->value = value;
  556.     (*status->draw) (w, at_x, at_y, at_x, at_y, Highlight);
  557.     }
  558. }
  559.  
  560.  
  561. void DragTwoPointsHandler(w, client_data, event, cont) /* ARGSUSED */
  562.     Widget      w;
  563.     XtPointer   client_data;
  564.     XEvent     *event;
  565.     Boolean    *cont;
  566. {
  567.     BitmapWidget BW = (BitmapWidget) w;
  568.     BWStatus   *status = (BWStatus *)client_data;
  569.  
  570.     if (DEBUG)
  571.     fprintf(stderr, "D2PH ");
  572.  
  573.     switch (event->type) {
  574.     
  575.     case ButtonPress:
  576.     if (event->xbutton.state != status->state) return;
  577.     if (!QuerySet(status->from_x, status->from_y)) {
  578.         BWStoreToBuffer(w);
  579.         status->value = Value(BW, event->xbutton.button);
  580.         status->btime = event->xbutton.time;
  581.         status->from_x = InBitmapX(BW, event->xbutton.x);
  582.         status->from_y = InBitmapY(BW, event->xbutton.y);
  583.         status->to_x = InBitmapX(BW, event->xbutton.x);
  584.         status->to_y = InBitmapY(BW, event->xbutton.y);
  585.         status->success = (Boolean) status->draw;
  586.         if (status->draw)
  587.         (*status->draw)(w,
  588.                 status->from_x, status->from_y, 
  589.                 status->to_x, status->to_y, status->value);
  590.     }
  591.     break;
  592.     
  593.     case ButtonRelease:
  594.     if (QuerySet(status->from_x, status->from_y)) {
  595.         status->value = Value(BW, event->xbutton.button);
  596.         status->btime = event->xbutton.time;        
  597.         status->from_x = status->to_x;
  598.         status->from_y = status->to_y;
  599.         status->to_x = InBitmapX(BW, event->xbutton.x);
  600.         status->to_y = InBitmapY(BW, event->xbutton.y);
  601.         status->success = True;
  602.         
  603.         BWTerminateRequest(w, TRUE);
  604.     }
  605.     break;
  606.     
  607.     case MotionNotify:
  608.     if (QuerySet(status->from_x, status->from_y)) {
  609.         if (QuerySet(status->to_x, status->to_y)) {
  610.         if (!QueryInSquare(BW, event->xmotion.x, event->xmotion.y,
  611.                    status->to_x, status->to_y)) {
  612.             status->from_x = status->to_x;
  613.             status->from_y = status->to_y;
  614.             status->to_x = InBitmapX(BW, event->xmotion.x);
  615.             status->to_y = InBitmapY(BW, event->xmotion.y);
  616.             if (status->draw)
  617.             (*status->draw)(w,
  618.                     status->from_x, status->from_y, 
  619.                     status->to_x, status->to_y, status->value);
  620.         }
  621.         }
  622.     }
  623.     break;
  624.     }
  625. }
  626.  
  627. void DragTwoPointsEngage(w, status, draw, state)
  628.     Widget     w;
  629.     BWStatus  *status;
  630.     void     (*draw)();
  631.     int       *state;
  632. {
  633.     
  634.     status->from_x = NotSet;
  635.     status->from_y = NotSet;
  636.     status->to_x = NotSet;
  637.     status->to_y = NotSet;
  638.     status->draw = draw;
  639.     status->success = False;
  640.     status->state = *state;
  641.  
  642.     XtAddEventHandler(w,
  643.               ButtonPressMask | ButtonReleaseMask | PointerMotionMask,
  644.               FALSE, DragTwoPointsHandler, (XtPointer)status);
  645. }
  646.  
  647. void DragTwoPointsTerminate(w, status, draw)
  648.     Widget     w;
  649.     BWStatus  *status;
  650.     void     (*draw)();
  651. {
  652.     
  653.     if (status->success && draw) {
  654.     if ((status->from_x != status->to_x) 
  655.         || 
  656.         (status->from_y != status->to_y))
  657.         (*draw)(w,
  658.             status->from_x, status->from_y,
  659.             status->to_x, status->to_y,
  660.             status->value);
  661.     BWChangeNotify(w, NULL, NULL);
  662.     BWSetChanged(w);
  663.     }
  664.     
  665.     XtRemoveEventHandler(w,
  666.                  ButtonPressMask | ButtonReleaseMask | PointerMotionMask,
  667.              FALSE, DragTwoPointsHandler, (XtPointer)status);
  668. }
  669.  
  670. /*****************************************************************************/
  671.