home *** CD-ROM | disk | FTP | other *** search
/ Encyclopedia of Graphics File Formats Companion / GFF_CD.ISO / software / unix / saoimage / sao1_07.tar / csrmove.c < prev    next >
C/C++ Source or Header  |  1991-01-03  |  9KB  |  291 lines

  1. #ifndef lint
  2. static char SccsId[] = "%W%  %G%";
  3. #endif
  4.  
  5. /* Module:    csrmove.c (Cursor Move)
  6.  * Purpose:    Move, resize, or rotate the software cursor
  7.  * Subroutine:    move_cursor()            returns: void
  8.  * Subroutine:    size_cursor()            returns: void
  9.  * Subroutine:    angle_cursor()            returns: void
  10.  * Subroutine:  start_size()            returns: int
  11.  * Called by:    control_cursor() in CursorCtrl.c
  12.  * Copyright:    1989 Smithsonian Astrophysical Observatory
  13.  *        You may do anything you like with this file except remove
  14.  *        this copyright.  The Smithsonian Astrophysical Observatory
  15.  *        makes no representations about the suitability of this
  16.  *        software for any purpose.  It is provided "as is" without
  17.  *        express or implied warranty.
  18.  * Modified:    {0} Michael VanHilst    initial version          4 June 1989
  19.  *        {1} MVH don't try to set angle if offset is 0,0      22 Feb 1990
  20.  *        {2} MVH added arrow and text cursors           1 Jan 1991
  21.  *        {n} <who> -- <does what> -- <when>
  22.  */
  23.  
  24. #include <stdio.h>        /* stderr, NULL, etc. */
  25. #include <math.h>        /* get trig functions and sqrt */
  26. #include <X11/Xlib.h>        /* X window stuff */
  27. #include <X11/Xutil.h>        /* X window manager stuff */
  28. #include "hfiles/color.h"    /* cursor colors needed by Cursor.h */
  29. #include "hfiles/constant.h"    /* define codes */
  30. #include "hfiles/cursor.h"    /* define cursor parameter structures */
  31. #include "hfiles/define.h"    /* SMALL_NUMBER, LARGE_NUMBER and more */
  32.  
  33. extern struct colorRec color;    /* need to know color.gcset */
  34.  
  35. #ifdef ANSIC
  36. /*  Exported declarations must be centralized before ANSI C can be used  */
  37.  
  38. void        move_cursor(    struct cursorRec *cursor, XEvent *event,
  39.                 int erase);
  40. void        size_cursor(    struct cursorRec *cursor, XEvent *event,
  41.                 int erase);
  42. void        angle_cursor(    struct cursorRec *cursor, XEvent *event);
  43. int        start_size(    struct cursorRec *cursor, XEvent *event);
  44.  
  45. #else
  46.  
  47.   void draw_cursor(), make_cursor(), angle_cursor();
  48.   void size_polygon(), set_polygon_hashmarks();
  49.  
  50. #endif
  51.  
  52. /*  Subroutine:    move_cursor
  53.  *  Purpose:    Change cursor location cursor
  54.  */
  55. #ifdef ANSIC
  56. void move_cursor ( struct cursorRec *cursor, XEvent *event, int erase )
  57. #else
  58. void move_cursor ( cursor, event, erase )
  59.      struct cursorRec *cursor;
  60.      XEvent *event;        /* i: XMotionEvent for location of mouse */
  61.      int erase;            /* i: erase-before-moving */
  62. #endif
  63. {
  64.   int dxm, dym;
  65.   int cnt;
  66.   register XPoint *point;
  67.   register int i;
  68.  
  69.   if( erase )
  70.     /*  Erase existing cursor  */
  71.     draw_cursor(cursor, &color.gcset.undraw);
  72.   /*  How much did we move?  */
  73.   dxm = event->xmotion.x - cursor->win.x;
  74.   dym = event->xmotion.y - cursor->win.y;
  75.   if( cursor->type == COP_Text ) {
  76.     /*  Move text drawing parameters  */
  77.     move_textcursor(dxm, dym);
  78.   } else {
  79.     /*  Move all points (or segments)  */
  80.     if( (cnt = cursor->point_cnt) < 0 )
  81.       cnt *= -2;
  82.     point = cursor->points;
  83.     for( i=0; i < cnt; i++ ) {
  84.       point[i].x += dxm;
  85.       point[i].y += dym;
  86.     }
  87.     if( cursor->type == COP_Polygon )
  88.       set_polygon_hashmarks(cursor);
  89.   }
  90.   /*  Update record of center  */
  91.   cursor->win.x = event->xmotion.x;
  92.   cursor->win.y = event->xmotion.y;
  93.   cursor->win.X = (double)cursor->win.x + 0.5;
  94.   cursor->win.Y = (double)cursor->win.y + 0.5;
  95.   /*  Draw it  */
  96.   draw_cursor(cursor, &color.gcset.track);
  97. }
  98.  
  99.  
  100. /*  Subroutine:    size_cursor
  101.  *  Purpose:    Change size of cursor to intersect current mouse cursor
  102.  *        on side or at corner depending on side argument
  103.  */
  104. #ifdef ANSIC
  105. void size_cursor ( struct cursorRec *cursor, XEvent *event, int erase )
  106. #else
  107. void size_cursor ( cursor, event, erase )
  108.      struct cursorRec *cursor;
  109.      XEvent *event;        /* i: XMotionEvent for location of mouse */
  110.      int erase;            /* i: erase-before-resizing */
  111. #endif
  112. {
  113.   double rayX, rayY;
  114.   int side;
  115.  
  116.   if( cursor->type == COP_Text ) {
  117.     return;
  118.   } else if( cursor->type == COP_Arrow ) {
  119.     angle_cursor(cursor, event);
  120.     return;
  121.   }
  122.   /*  Compute distance from center  */
  123.   rayX = ((double)event->xmotion.x + 0.5) - cursor->win.X;
  124.   rayY = ((double)event->xmotion.y + 0.5) - cursor->win.Y;
  125.   side = cursor->ctrl.active_side;
  126.   if( erase )
  127.     /*  Erase existing cursor  */
  128.     draw_cursor(cursor, &color.gcset.undraw);
  129.   switch( cursor->type ) {
  130.   case COP_Box:
  131.     if( cursor->rot.angle == 0.0 ) {
  132.       /*  Change specified side to share X and/or Y coordinate with mouse  */
  133.       if( (side == XYCORNER) || (side == XSIDE) )
  134.     cursor->win.rayX = fabs(rayX);
  135.       if( (side == XYCORNER) || (side == YSIDE) )
  136.     cursor->win.rayY = fabs(rayY);
  137.       break;
  138.     }
  139.   case COP_Ellipse:
  140.     /*  Change specified side to share X and/or Y coordinate with mouse  */
  141.     /*  Ellipse is drawn within rotated box defined by mouse */
  142.     if( (side == XYCORNER) || (side == XSIDE) )
  143.       cursor->win.rayX =
  144.     fabs(rayX * cursor->rot.cos + rayY * cursor->rot.sin);
  145.     if( (side == XYCORNER) || (side == YSIDE) )
  146.       cursor->win.rayY =
  147.     fabs(rayY * cursor->rot.cos - rayX * cursor->rot.sin);
  148.     break;
  149.   case COP_Circle:
  150.     /*  Circle is drawn to place edge at mouse position  */
  151.     cursor->win.rayX = sqrt((rayX * rayX) + (rayY * rayY));
  152.     cursor->win.rayY = cursor->win.rayX;
  153.     break;
  154.   case COP_Polygon:
  155.     /*  Cursor sizing is unique, involving specified point  */
  156.     size_polygon(cursor, event->xmotion.x, event->xmotion.y);
  157.     draw_cursor(cursor, &color.gcset.track);
  158.     return;
  159.   case COP_Point:
  160.   default:
  161.     (void)fprintf(stderr, "cursor type error\n");
  162.     return;
  163.   }
  164.   /*  Make cursor with new size  */
  165.   make_cursor(cursor);
  166.   /*  Draw it  */
  167.   draw_cursor(cursor, &color.gcset.track);
  168. }
  169.  
  170.  
  171. /*  Subroutine:    angle_cursor
  172.  *  Purpose:    Change angle of cursor to line up with current mouse cursor
  173.  */
  174. #ifdef ANSIC
  175. void angle_cursor ( struct cursorRec *cursor, XEvent *event )
  176. #else
  177. void angle_cursor ( cursor, event )
  178.      struct cursorRec *cursor;
  179.      XEvent *event;        /* i: XMotionEvent for location of mouse */
  180. #endif
  181. {
  182.   double angle;
  183.  
  184.   /*  Do nothing if click is on cursor center  */
  185.   if( (event->xmotion.x == cursor->win.x) &&
  186.       (event->xmotion.y == cursor->win.y) )
  187.     return;
  188.   /*  Compute distance from center  */
  189.   angle = atan2((cursor->win.X - ((double)(event->xmotion.x) + 0.5)),
  190.         (((double)(event->xmotion.y) + 0.5) - cursor->win.Y));
  191.   /*  Erase existing cursor  */
  192.   draw_cursor(cursor, &color.gcset.undraw);
  193.   switch( cursor->type ) {
  194.   case COP_Box:
  195.   case COP_Ellipse:
  196.   case COP_Arrow:
  197.     /*  Update cursor record  */
  198.     /*  We reversed the sign of Y before, so ...  */
  199.     cursor->rot.cos = cos(angle);
  200.     cursor->rot.sin = sin(angle);
  201.     /*  The angle variable is for priinted feedback only, we make it go counter
  202.     clockwise from x=0, 0 to 2pi, as per astronomical convention  */
  203.     cursor->rot.angle = PI - angle;
  204.     if( cursor->type == COP_Arrow ) {
  205.       double rayX, rayY;
  206.  
  207.       rayX = ((double)event->xmotion.x + 0.5) - cursor->win.X;
  208.       rayY = ((double)event->xmotion.y + 0.5) - cursor->win.Y;
  209.       cursor->win.rayX = sqrt((rayX * rayX) + (rayY * rayY));
  210.     }
  211.     break;
  212.   default:
  213.     (void)fprintf(stderr, "cursor type error\n");
  214.     return;
  215.   }
  216.   /*  Set new drawing line coords  */
  217.   make_cursor(cursor);
  218.   /*  Draw it  */
  219.   draw_cursor(cursor, &color.gcset.track);
  220. }
  221.  
  222.  
  223. /*  Subroutine:    start_size
  224.  *  Purpose:    Calculate restrictions applied to sizing restrictions can apply
  225.  *        where x and y dimensions are independent zones are defines
  226.  *        by 2 rays from center through rayX/2,rayY and rayX,rayY/2
  227.  *  Returns:    Code to indicate kind of sizing to do
  228.  */
  229. #ifdef ANSIC
  230. int start_size ( struct cursorRec *cursor, XEvent *event )
  231. #else
  232. int start_size ( cursor, event )
  233.      struct cursorRec *cursor;
  234.      XEvent *event;        /* i: XButtonEvent for location of mouse */
  235. #endif
  236. {
  237.   double rayX, rayY;
  238.   double mouse_ratio;
  239.   int size_side;
  240.  
  241.   if( (cursor->type == COP_Box) ||
  242.       (cursor->type == COP_Ellipse) ) {
  243.     /*  Calculate relation between x and y (slope through corner)  */
  244.     if( cursor->win.rayX < SMALL_NUMBER ) {
  245.       if( cursor->win.rayY < SMALL_NUMBER ) {
  246.     /*  Object has no size, adjust both sides  */
  247.     cursor->ctrl.axis_ratio = 1.0;
  248.     return( XYCORNER );
  249.       } else
  250.     cursor->ctrl.axis_ratio = LARGE_NUMBER;
  251.     } else if( cursor->win.rayY < SMALL_NUMBER ) {
  252.       cursor->ctrl.axis_ratio = SMALL_NUMBER;
  253.     } else
  254.       cursor->ctrl.axis_ratio = cursor->win.rayY / cursor->win.rayX;
  255.     /*  For annuli, we need the ratio, but not the restriction choice  */
  256.     if( cursor->annuli )
  257.       return( XYCORNER );
  258.     /*  Get positive rays in zero centered, orthogonal space  */
  259.     rayX = ((double)event->xbutton.x + 0.5) - cursor->win.X;
  260.     rayY = ((double)event->xbutton.y + 0.5) - cursor->win.Y;
  261.     if( cursor->type != COP_Box ) {
  262.       double temp;
  263.       temp = (rayX * cursor->rot.cos) + (rayY * cursor->rot.sin);
  264.       rayY = (rayY * cursor->rot.cos) - (rayX * cursor->rot.sin);
  265.       rayX = temp;
  266.     }
  267.     if( rayX < 0.0 )
  268.       rayX = -rayX;
  269.     if( rayY < 0.0 )
  270.       rayY = -rayY;
  271.     /*  Determine slope of ray to mouse  */
  272.     if( rayX < SMALL_NUMBER ) {
  273.       if( rayY < SMALL_NUMBER )
  274.     /*  Mouse is on center, adjust both sides  */
  275.     return( XYCORNER );
  276.       else
  277.     mouse_ratio = LARGE_NUMBER;
  278.     } else
  279.       mouse_ratio = rayY / rayX;
  280.     /*  Determine which of the three restriction zones ray occupies  */
  281.     if( (mouse_ratio / 4.0) > cursor->ctrl.axis_ratio ) {
  282.       size_side = YSIDE;
  283.     } else if( (mouse_ratio * 4.0) < cursor->ctrl.axis_ratio) {
  284.       size_side = XSIDE;
  285.     } else
  286.       size_side = XYCORNER;
  287.     return( size_side );
  288.   } else
  289.     return( XYCORNER );
  290. }
  291.