home *** CD-ROM | disk | FTP | other *** search
/ vsiftp.vmssoftware.com / VSIPUBLIC@vsiftp.vmssoftware.com.tar / FREEWARE / FREEWARE40.ZIP / xpaint-247 / lineop.c < prev    next >
C/C++ Source or Header  |  1996-06-25  |  7KB  |  297 lines

  1. /* +-------------------------------------------------------------------+ */
  2. /* | Copyright 1992, 1993, David Koblas (koblas@netcom.com)           | */
  3. /* |                                       | */
  4. /* | Permission to use, copy, modify, and to distribute this software  | */
  5. /* | and its documentation for any purpose is hereby granted without   | */
  6. /* | fee, provided that the above copyright notice appear in all       | */
  7. /* | copies and that both that copyright notice and this permission    | */
  8. /* | notice appear in supporting documentation.     There is no           | */
  9. /* | representations about the suitability of this software for           | */
  10. /* | any purpose.  this software is provided "as is" without express   | */
  11. /* | or implied warranty.                           | */
  12. /* |                                       | */
  13. /* +-------------------------------------------------------------------+ */
  14.  
  15. /* $Id: lineOp.c,v 1.3 1996/04/19 09:09:01 torsten Exp $ */
  16.  
  17. #include <X11/Intrinsic.h>
  18. #include <X11/StringDefs.h>
  19. #include <math.h>
  20. #include "xpaint.h"
  21. #include "misc.h"
  22. #include "Paint.h"
  23. #include "ops.h"
  24.  
  25. typedef struct {
  26.     int isRay;
  27.     int type;
  28.     Boolean didUndo, didSet, tracking;
  29.     int rx, ry;
  30.     int startX, startY, endX, endY;
  31.     int drawn;
  32.     Drawable drawable;
  33.     GC gcx;
  34. } LocalInfo;
  35.  
  36. static void 
  37. press(Widget w, LocalInfo * l, XButtonEvent * event, OpInfo * info)
  38. {
  39.     /*
  40.     **    Check to make sure all buttons are up, before doing this
  41.      */
  42.     if ((event->state & AllButtonsMask) != 0)
  43.     return;
  44.  
  45.     if (event->button == Button1 && ((!l->tracking && l->isRay) || !l->isRay)) {
  46.     l->rx = info->x;
  47.     l->ry = info->y;
  48.     l->startX = event->x;
  49.     l->startY = event->y;
  50.  
  51.     l->drawable = info->drawable;
  52.     l->drawn = False;
  53.     l->didUndo = False;
  54.     l->didSet = False;
  55.     l->tracking = True;
  56.     } else if (event->button == Button2) {
  57.     if (l->drawn)
  58.         XDrawLine(XtDisplay(w), info->drawable, l->gcx,
  59.               l->startX, l->startY, l->endX, l->endY);
  60.     l->tracking = False;
  61.     return;
  62.     }
  63.     if (l->tracking) {
  64.     if (l->drawn)
  65.         XDrawLine(XtDisplay(w), info->drawable, l->gcx,
  66.               l->startX, l->startY, l->endX, l->endY);
  67.  
  68.     l->endX = event->x;
  69.     l->endY = event->y;
  70.  
  71.     XDrawLine(XtDisplay(w), info->drawable, l->gcx,
  72.           l->startX, l->startY, l->endX, l->endY);
  73.     l->drawn = True;
  74.     }
  75. }
  76.  
  77. static void 
  78. motion(Widget w, LocalInfo * l, XMotionEvent * event, OpInfo * info)
  79. {
  80.     if (!l->tracking)
  81.     return;
  82.  
  83.     if (l->drawn) {
  84.     XDrawLine(XtDisplay(w), info->drawable, l->gcx,
  85.           l->startX, l->startY, l->endX, l->endY);
  86.     }
  87.     l->type = (event->state & ShiftMask);
  88.  
  89.     if (l->type) {
  90.     int ax = ABS(event->x - l->startX);
  91.     int ay = ABS(event->y - l->startY);
  92.     int dx = MIN(ax, ay);
  93.     int v, v1 = dx - ax, v2 = dx - ay;
  94.     int addX, addY;
  95.  
  96.     v = v1 * v1 + v2 * v2;
  97.  
  98.     if (ay * ay < v) {
  99.         addX = event->x - l->startX;
  100.         addY = 0;
  101.     } else if (ax * ax < v) {
  102.         addX = 0;
  103.         addY = event->y - l->startY;
  104.     } else {
  105.         if (ax < ay) {
  106.         addX = event->x - l->startX;
  107.         addY = SIGN(event->y - l->startY) * ax;
  108.         } else {
  109.         addX = SIGN(event->x - l->startX) * ay;
  110.         addY = event->y - l->startY;
  111.         }
  112.     }
  113.  
  114.     l->endX = l->startX + addX;
  115.     l->endY = l->startY + addY;
  116.     } else {
  117.     l->endX = event->x;
  118.     l->endY = event->y;
  119.     }
  120.  
  121.     /*
  122.     **    Really set this flag in the if statement
  123.      */
  124.     if ((l->drawn = (l->startX != l->endX || l->startY != l->endY))) {
  125.     XDrawLine(XtDisplay(w), info->drawable, l->gcx,
  126.           l->startX, l->startY, l->endX, l->endY);
  127.     }
  128. }
  129.  
  130. static void 
  131. release(Widget w, LocalInfo * l, XButtonEvent * event, OpInfo * info)
  132. {
  133.     XRectangle undo;
  134.     int mask;
  135.  
  136.     if (!l->tracking)
  137.     return;
  138.  
  139.     /*
  140.     **    Check to make sure all buttons are up, before doing this
  141.      */
  142.     mask = AllButtonsMask;
  143.     switch (event->button) {
  144.     case Button1:
  145.     mask ^= Button1Mask;
  146.     break;
  147.     case Button2:
  148.     mask ^= Button2Mask;
  149.     break;
  150.     case Button3:
  151.     mask ^= Button3Mask;
  152.     break;
  153.     case Button4:
  154.     mask ^= Button4Mask;
  155.     break;
  156.     case Button5:
  157.     mask ^= Button5Mask;
  158.     break;
  159.     }
  160.     if ((event->state & mask) != 0)
  161.     return;
  162.  
  163.     if (l->drawn && info->surface == opWindow) {
  164.     XDrawLine(XtDisplay(w), info->drawable, l->gcx,
  165.           l->startX, l->startY, l->endX, l->endY);
  166.     l->drawn = False;
  167.     }
  168.     if (info->surface == opWindow && info->isFat)
  169.     return;
  170.  
  171.     if (!l->didUndo && info->surface == opPixmap) {
  172.     UndoStart(w, info);
  173.     l->didUndo = True;
  174.     }
  175.     if (l->type) {
  176.     int ax = ABS(event->x - l->rx);
  177.     int ay = ABS(event->y - l->ry);
  178.     int dx = MIN(ax, ay);
  179.     int v, v1 = dx - ax, v2 = dx - ay;
  180.     int addX, addY;
  181.  
  182.     v = v1 * v1 + v2 * v2;
  183.  
  184.     if (ay * ay < v) {
  185.         addX = event->x - l->rx;
  186.         addY = 0;
  187.     } else if (ax * ax < v) {
  188.         addX = 0;
  189.         addY = event->y - l->ry;
  190.     } else {
  191.         if (ax < ay) {
  192.         addX = event->x - l->rx;
  193.         addY = SIGN(event->y - l->ry) * ax;
  194.         } else {
  195.         addX = SIGN(event->x - l->rx) * ay;
  196.         addY = event->y - l->ry;
  197.         }
  198.     }
  199.  
  200.     l->endX = l->rx + addX;
  201.     l->endY = l->ry + addY;
  202.     } else {
  203.     l->endX = event->x;
  204.     l->endY = event->y;
  205.     }
  206.  
  207.     XDrawLine(XtDisplay(w), info->drawable, info->first_gc,
  208.           l->rx, l->ry, l->endX, l->endY);
  209.  
  210.     if (info->surface == opPixmap) {
  211.     XYtoRECT(l->rx, l->ry, l->endX, l->endY, &undo);
  212.  
  213.     if (l->didSet) {
  214.         UndoGrow(w, l->endY, l->endY);
  215.     } else {
  216.         UndoSetRectangle(w, &undo);
  217.         l->didSet = True;
  218.     }
  219.  
  220.     PwUpdate(w, &undo, False);
  221.     }
  222. }
  223.  
  224. /*
  225. **  Those public functions
  226.  */
  227. void *
  228. LineAdd(Widget w)
  229. {
  230.     LocalInfo *l = (LocalInfo *) XtMalloc(sizeof(LocalInfo));
  231.  
  232.     l->isRay = False;
  233.     l->tracking = False;
  234.     l->gcx = GetGCX(w);
  235.     XtVaSetValues(w, XtNcompress, True, NULL);
  236.  
  237.     OpAddEventHandler(w, opWindow, ButtonPressMask, FALSE,
  238.               (OpEventProc) press, l);
  239.     OpAddEventHandler(w, opWindow, ButtonMotionMask, FALSE,
  240.               (OpEventProc) motion, l);
  241.     OpAddEventHandler(w, opWindow | opPixmap, ButtonReleaseMask, FALSE,
  242.               (OpEventProc) release, l);
  243.     SetCrossHairCursor(w);
  244.     return l;
  245. }
  246.  
  247. void 
  248. LineRemove(Widget w, void *l)
  249. {
  250.     OpRemoveEventHandler(w, opWindow, ButtonPressMask, FALSE,
  251.              (OpEventProc) press, l);
  252.     OpRemoveEventHandler(w, opWindow, ButtonMotionMask, FALSE,
  253.              (OpEventProc) motion, l);
  254.     OpRemoveEventHandler(w, opWindow | opPixmap, ButtonReleaseMask, FALSE,
  255.              (OpEventProc) release, l);
  256.     XtFree((XtPointer) l);
  257. }
  258.  
  259. void *
  260. RayAdd(Widget w)
  261. {
  262.     LocalInfo *l = (LocalInfo *) XtMalloc(sizeof(LocalInfo));
  263.  
  264.     l->isRay = True;
  265.     l->tracking = False;
  266.     l->gcx = GetGCX(w);
  267.     XtVaSetValues(w, XtNcompress, True, NULL);
  268.  
  269.     OpAddEventHandler(w, opWindow, ButtonPressMask, FALSE,
  270.               (OpEventProc) press, l);
  271.     OpAddEventHandler(w, opWindow, PointerMotionMask, FALSE,
  272.               (OpEventProc) motion, l);
  273.     OpAddEventHandler(w, opWindow | opPixmap, ButtonReleaseMask, FALSE,
  274.               (OpEventProc) release, l);
  275.     SetCrossHairCursor(w);
  276.     return l;
  277. }
  278.  
  279. void 
  280. RayRemove(Widget w, void *p)
  281. {
  282.     LocalInfo *l = (LocalInfo *) p;
  283.  
  284.     OpRemoveEventHandler(w, opWindow, ButtonPressMask, FALSE,
  285.              (OpEventProc) press, l);
  286.     OpRemoveEventHandler(w, opWindow, PointerMotionMask, FALSE,
  287.              (OpEventProc) motion, l);
  288.     OpRemoveEventHandler(w, opWindow | opPixmap, ButtonReleaseMask, FALSE,
  289.              (OpEventProc) release, l);
  290.  
  291.     if (l->tracking && l->drawn)
  292.     XDrawLine(XtDisplay(w), l->drawable, l->gcx,
  293.           l->startX, l->startY, l->endX, l->endY);
  294.  
  295.     XtFree((XtPointer) l);
  296. }
  297.