home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 January / usenetsourcesnewsgroupsinfomagicjanuary1994.iso / sources / x / volume8 / xfig2.8 / part11 / line.c next >
C/C++ Source or Header  |  1990-07-03  |  12KB  |  486 lines

  1. /* 
  2.  *    FIG : Facility for Interactive Generation of figures
  3.  *
  4.  *    Copyright (c) 1985 by Supoj Sutanthavibul (supoj@sally.UTEXAS.EDU)
  5.  *    January 1985.
  6.  *    1st revision : Aug 1985.
  7.  *
  8.  *    %W%    %G%
  9. */
  10. #include "fig.h"
  11. #include "resources.h"
  12. #include "alloc.h"
  13. #include "func.h"
  14. #include "object.h"
  15. #include "paintop.h"
  16.  
  17. extern            (*canvas_kbd_proc)();
  18. extern            (*canvas_locmove_proc)();
  19. extern            (*canvas_leftbut_proc)();
  20. extern            (*canvas_middlebut_proc)();
  21. extern            (*canvas_rightbut_proc)();
  22. extern            null_proc();
  23. extern            set_popupmenu();
  24.  
  25. extern int        fix_x, fix_y, cur_x, cur_y;
  26. extern int        fill_mode,cur_areafill;
  27.  
  28. extern int        cur_command;
  29. extern int        manhattan_mode, mountain_mode;
  30. extern int        latexline_mode, latexarrow_mode;
  31. extern int        magnet_mode, latexarrow_mode;
  32. extern int        autoforwardarrow_mode, autobackwardarrow_mode;
  33. extern int        line_style, line_thickness;
  34. extern float        cur_styleval;
  35. extern int        cur_color;
  36. extern F_compound    objects;
  37. extern int        num_point;
  38. extern int        latex_endpoint();
  39.  
  40. extern F_point        *first_point, *cur_point; 
  41.  
  42. /*************************** locally global variables *********************/
  43.  
  44. static int        firstx, firsty;
  45. extern int        init_line_drawing();
  46.  
  47. extern int        create_lineobject();
  48. extern int        create_latexobject();
  49. extern int        determine_angle();
  50. extern int        freehand_elasticline();
  51. extern int        latex_elasticline();
  52. extern int        angle0_elasticline(), angle90_elasticline(); 
  53. extern int        angle45_elasticline(), angle135_elasticline(); 
  54. extern int        get_direction(), get_intermediatepoint();
  55. extern int        get_latexpoint();
  56.  
  57. /**********************  polyline and polygon section  **********************/
  58.  
  59. line_drawing_selected()
  60. {
  61.     canvas_kbd_proc = null_proc;
  62.     canvas_locmove_proc = null_proc;
  63.     canvas_leftbut_proc = init_line_drawing;
  64.     canvas_middlebut_proc = null_proc;
  65.     canvas_rightbut_proc = set_popupmenu;
  66.     set_cursor(&arrow_cursor);
  67.     reset_action_on();
  68.     }
  69.  
  70. init_line_drawing(x, y)
  71. int    x, y;
  72. {
  73.     first_point = Point_malloc(cur_point);
  74.     if (cur_point == NULL) {
  75.         blink_msg();
  76.         put_msg(Err_mem);
  77.         return;
  78.         }
  79.     canvas_rightbut_proc = null_proc;
  80.     set_action_on();
  81.     cur_point->x = firstx = fix_x = cur_x = x;
  82.     cur_point->y = firsty = fix_y = cur_y = y;
  83.     cur_point->next = NULL;
  84.     num_point = 1;
  85.     if (latexline_mode || latexarrow_mode) {
  86.         canvas_locmove_proc = latex_elasticline;
  87.         canvas_leftbut_proc = get_latexpoint;
  88.         canvas_middlebut_proc = create_latexobject;
  89.         }
  90.     else if (manhattan_mode || mountain_mode) {
  91.         canvas_locmove_proc = determine_angle;
  92.         canvas_leftbut_proc = get_direction;
  93.         canvas_middlebut_proc = create_lineobject;
  94.         }
  95.     else {
  96.         canvas_locmove_proc = freehand_elasticline;
  97.         canvas_leftbut_proc = get_intermediatepoint;
  98.         canvas_middlebut_proc = create_lineobject;
  99.         }
  100.     set_temp_cursor(&null_cursor);
  101.     cur_cursor = &null_cursor;
  102.     draw_elasticline();
  103.     }
  104.  
  105. draw_elasticline()
  106. {
  107.     pw_vector(canvas_win, fix_x, fix_y, cur_x, cur_y, 
  108.         INV_PAINT, 1, SOLID_LINE, 0.0);
  109.     }
  110.  
  111. freehand_elasticline(x, y)
  112. int    x, y;
  113. {
  114.     draw_elasticline();
  115.     cur_x = x;  
  116.     cur_y = y;
  117.     draw_elasticline();
  118.     }
  119.  
  120. draw_latexline()
  121. {
  122.     int  x, y;
  123.     CURSOR c;
  124.  
  125.     latex_endpoint(fix_x, fix_y, cur_x, cur_y, &x, &y, latexarrow_mode, (magnet_mode)? 5: 1);
  126.     pw_vector(canvas_win, fix_x, fix_y, x, y, INV_PAINT,1,SOLID_LINE, 0.0);
  127.     c = (x == cur_x  &&  y == cur_y)? &null_cursor: &crosshair_cursor;
  128.     if (c != cur_cursor) {
  129.         set_temp_cursor(c);
  130.         cur_cursor = c;
  131.         }
  132.     }
  133.  
  134. latex_elasticline(x, y)
  135. int    x, y;
  136. {
  137.     draw_latexline();
  138.     cur_x = x;  
  139.     cur_y = y;
  140.     draw_latexline();
  141.     }
  142.  
  143. angle0_elasticline(x, y)
  144. int    x, y;
  145. {
  146.     if (x == cur_x && y == cur_y) return;
  147.     pw_vector(canvas_win, fix_x, fix_y, cur_x, cur_y, INV_PAINT,1,SOLID_LINE, 0.0);
  148.     cur_x = x;
  149.     pw_vector(canvas_win, fix_x, fix_y, cur_x, cur_y, INV_PAINT,1,SOLID_LINE, 0.0);
  150.     win_setmouseposition(canvas_win, cur_x, cur_y);
  151.     }
  152.  
  153. angle90_elasticline(x, y)
  154. int    x, y;
  155. {
  156.     if (x == cur_x && y == cur_y) return;
  157.     pw_vector(canvas_win, fix_x, fix_y, cur_x, cur_y, INV_PAINT,1,SOLID_LINE, 0.0);
  158.     cur_y = y;
  159.     pw_vector(canvas_win, fix_x, fix_y, cur_x, cur_y, INV_PAINT,1,SOLID_LINE, 0.0);
  160.     win_setmouseposition(canvas_win, cur_x, cur_y);
  161.     }
  162.  
  163. angle45_elasticline(x, y)
  164. int    x, y;
  165. {
  166.     if (x == cur_x && y == cur_y) return;
  167.     pw_vector(canvas_win, fix_x, fix_y, cur_x, cur_y, INV_PAINT,1,SOLID_LINE, 0.0);
  168.     if (abs(x - cur_x) < abs(y - cur_y)) {
  169.         cur_x += cur_y - y;
  170.         cur_y = y;
  171.         }
  172.     else {
  173.         cur_y -= x - cur_x;
  174.         cur_x = x;
  175.         }
  176.     pw_vector(canvas_win, fix_x, fix_y, cur_x, cur_y, INV_PAINT,1,SOLID_LINE, 0.0);
  177.     win_setmouseposition(canvas_win, cur_x, cur_y);
  178.     }
  179.  
  180. angle135_elasticline(x, y)
  181. int    x, y;
  182. {
  183.     if (x == cur_x && y == cur_y) return;
  184.     pw_vector(canvas_win, fix_x, fix_y, cur_x, cur_y, INV_PAINT,1,SOLID_LINE, 0.0);
  185.     if (abs(x - cur_x) < abs(y - cur_y)) {
  186.         cur_x += y - cur_y;
  187.         cur_y = y;
  188.         }
  189.     else {
  190.         cur_y += x - cur_x;
  191.         cur_x = x;
  192.         }
  193.     pw_vector(canvas_win, fix_x, fix_y, cur_x, cur_y, INV_PAINT,1,SOLID_LINE, 0.0);
  194.     win_setmouseposition(canvas_win, cur_x, cur_y);
  195.     }
  196.  
  197. get_direction(x, y)
  198. int    x, y;
  199. {
  200.     (*canvas_locmove_proc) (x, y);
  201.     canvas_locmove_proc = determine_angle;
  202.     get_intermediatepoint(cur_x, cur_y);
  203.     }
  204.  
  205. determine_angle(x, y)
  206. int    x, y;
  207. {
  208.     float    angle, dx, dy;
  209.  
  210.     dx = x - fix_x;  dy = fix_y - y;
  211.     if (sqrt((double)(dx*dx + dy*dy)) < 7) return;
  212.     if (dx == 0)
  213.         angle = -90;
  214.     else
  215.         angle = 180 * atan((double)(dy / dx)) / 3.1416;
  216.  
  217.     if (manhattan_mode) {
  218.         if (mountain_mode) {
  219.         if (angle < -67.5) canvas_locmove_proc = angle90_elasticline;
  220.         else if (angle < -22.5) canvas_locmove_proc = angle135_elasticline;
  221.         else if (angle <  22.5) canvas_locmove_proc = angle0_elasticline;
  222.         else if (angle <  67.5) canvas_locmove_proc = angle45_elasticline;
  223.         else canvas_locmove_proc = angle90_elasticline;
  224.         }
  225.         else {
  226.         if (angle < -45) canvas_locmove_proc = angle90_elasticline;
  227.         else if (angle < 45) canvas_locmove_proc = angle0_elasticline;
  228.         else canvas_locmove_proc = angle90_elasticline;
  229.         }
  230.         }
  231.     else {
  232.         if (angle < 0) canvas_locmove_proc = angle135_elasticline;
  233.         else canvas_locmove_proc = angle45_elasticline;
  234.         }
  235.         
  236.     (*canvas_locmove_proc)(x, y);
  237.     }
  238.  
  239. get_latexpoint(x, y)
  240. int    x, y;
  241. {
  242.     draw_latexline();
  243.     latex_endpoint(fix_x, fix_y, x, y, &cur_x, &cur_y, latexarrow_mode, (magnet_mode)? 5: 1);
  244.     if (cur_cursor != &null_cursor) {
  245.         set_temp_cursor(&null_cursor);
  246.         cur_cursor = &null_cursor;
  247.         }
  248.     win_setmouseposition(canvas_win, cur_x, cur_y);
  249.     get_intermediatepoint(cur_x, cur_y);
  250.     }
  251.  
  252. get_intermediatepoint(x, y)
  253. int    x, y;
  254. {
  255.     draw_elasticline();    /* erase elastic line */
  256.     cur_x = x;
  257.     cur_y = y;
  258.     draw_elasticline();
  259.     num_point++;
  260.     fix_x = x;
  261.     fix_y = y;
  262.     draw_elasticline();
  263.     append_point(fix_x, fix_y, &cur_point);
  264.     }
  265.  
  266. create_latexobject(x, y)
  267. int    x, y;
  268. {
  269.     if (x != fix_x || y != fix_y || num_point == 1) {
  270.         draw_latexline();
  271.         latex_endpoint(fix_x, fix_y, x, y, &cur_x, &cur_y, latexarrow_mode, (magnet_mode)? 5: 1);
  272.         if (cur_cursor != &null_cursor) {
  273.         set_temp_cursor(&null_cursor);
  274.         cur_cursor = &null_cursor;
  275.         }
  276.         win_setmouseposition(canvas_win, cur_x, cur_y);
  277.         }
  278.     create_lineobject(cur_x, cur_y);
  279.     }
  280.  
  281. /* come here upon pressing middle button (last point of lineobject) */
  282.  
  283. create_lineobject(x, y)
  284. int    x, y;
  285. {
  286.     extern F_arrow    *forward_arrow(), *backward_arrow();
  287.     F_point        *p, *q;
  288.     F_line        *line;
  289.     int        dot;
  290.  
  291.     dot = 0;
  292.     if (x != fix_x || y != fix_y) {
  293.         if( manhattan_mode || mountain_mode )
  294.             get_direction(x, y);
  295.         else if( latexline_mode || latexarrow_mode )
  296.             get_latexpoint(x, y);
  297.         else
  298.             get_intermediatepoint(x, y);
  299.         draw_elasticline();
  300.         }
  301.     else if (num_point == 1) {
  302.         dot = 1;
  303.         if( manhattan_mode || mountain_mode )
  304.             get_direction(x, y);
  305.         else if( latexline_mode || latexarrow_mode )
  306.             get_latexpoint(x, y);
  307.         else
  308.             get_intermediatepoint(x, y);
  309.         draw_elasticline();
  310.         }
  311.     if (NULL == (Line_malloc(line))) {
  312.         put_msg(Err_mem);
  313.         line_drawing_selected();
  314.         return;
  315.         }
  316.     line->type = T_POLYLINE;
  317.     line->style = SOLID_LINE;
  318.     line->thickness = 1;        /* these will be changed to final values */
  319.     line->style_val = 0;
  320.     line->color = cur_color;
  321.     line->depth = 0;
  322.     line->area_fill = 0;
  323.     line->pen = 0;
  324.     line->points = first_point;
  325.     line->next = NULL;
  326.     line->for_arrow = NULL;
  327.     line->back_arrow = NULL;
  328.     if (cur_command == F_POLYGON) {  /* polygon; close it off with one more point */
  329.         if (num_point >= 3) {
  330.         line->type = T_POLYGON;
  331.         num_point++;
  332.         append_point(firstx, firsty, &cur_point);
  333.         draw_elasticline();
  334.         fix_x=firstx;
  335.         fix_y=firsty;
  336.         draw_elasticline();        /* fix last elastic line */
  337.         }
  338.         }
  339.     else if (dot) {            /* single point */
  340.         pw_vector(canvas_win, fix_x, fix_y, cur_x, cur_y, PAINT, 2, SOLID_LINE, 0.0);
  341.         line->style = SOLID_LINE;
  342.         }
  343.     else if (num_point > 1) {        /* polyline; draw any arrows */
  344.         if (autoforwardarrow_mode) {
  345.         line->for_arrow = forward_arrow();
  346.         for (p = line->points; p != cur_point; q = p, p = p->next);
  347.         draw_arrow(q->x, q->y, p->x, p->y, line->for_arrow, PAINT);
  348.         }
  349.         if (autobackwardarrow_mode) {
  350.         line->back_arrow = backward_arrow();
  351.         p = line->points->next;
  352.         draw_arrow(p->x, p->y, firstx, firsty, line->back_arrow, PAINT);
  353.         }
  354.         }
  355.     if (!dot)
  356.         {
  357.         line->thickness = 1;
  358.         line->area_fill = 0;
  359.         draw_line(line,INV_PAINT);    /* erase temporary outline */
  360.         line->thickness = line_thickness;
  361.         line->area_fill = fill_mode? cur_areafill : 0;
  362.         line->thickness = line_thickness;
  363.         line->style = line_style;
  364.         line->style_val = cur_styleval;
  365.         draw_line(line,PAINT);        /* draw final */
  366.         }
  367.     clean_up();
  368.     set_action_object(F_CREATE, O_POLYLINE);
  369.     insert_line(&objects.lines, line);
  370.     set_latestline(line);
  371.     set_modifiedflag();
  372.     line_drawing_selected();
  373.     }
  374.  
  375. append_point(x, y, point)
  376. int    x, y;
  377. F_point    **point;
  378. {
  379.     F_point    *p;
  380.  
  381.     if (NULL == (Point_malloc(p))) {
  382.         put_msg(Err_mem);
  383.         return;
  384.         }
  385.     p->x = x;
  386.     p->y = y;
  387.     p->next = NULL;
  388.     (*point)->next = p;
  389.     *point = p;
  390.     }
  391.  
  392.  
  393. fill_object(line, op)
  394. F_line *line;
  395. int op;
  396.     {
  397.     int npts,i;
  398.     struct f_point *pnt;
  399.     XPoint *points;
  400.     GC gc;
  401.  
  402.     if (line->area_fill <= 0 || line->type == T_POLYLINE)
  403.         return;
  404.  
  405.     if (op == PAINT)        /* fill */
  406.         gc = fill_gc[line->area_fill-1];
  407.     else                /* un-fill */
  408.         gc = un_fill_gc[line->area_fill-1];
  409.  
  410.     if (line->type == T_ARC_BOX)
  411.         {
  412.         fill_arc_box(line,gc);
  413.         return;
  414.         }
  415.     npts=0;
  416.     /* count number of points in this object */
  417.     for (pnt=line->points; pnt != NULL; pnt = pnt->next)
  418.         npts++;
  419.     if ((points = (XPoint *) malloc(npts*sizeof(XPoint)))==0)
  420.         {
  421.         put_msg(Err_mem);
  422.         return;
  423.         }
  424.     for (pnt=line->points, i=0; i<npts; i++, pnt=pnt->next)
  425.         {
  426.         points[i].x = pnt->x;
  427.         points[i].y = pnt->y;
  428.         }
  429.     XFillPolygon(tool_d,canvas_win,gc,points, npts,
  430.             Complex, CoordModeOrigin);
  431.     free(points);
  432.     }
  433.  
  434. fill_arc_box(line, gc)
  435. F_line *line;
  436. GC gc;
  437.     {
  438.     F_point    *point;
  439.     int    xmin,xmax,ymin,ymax;
  440.     int    radius,diam;
  441.  
  442.     point = line->points;
  443.     radius = line->radius;
  444.  
  445.     xmin = xmax = point->x;
  446.     ymin = ymax = point->y;
  447.     while (point->next)        /* find lower left (upper-left on screen) */
  448.         {            /* and upper right (lower right on screen) */
  449.         point = point->next;
  450.         if (point->x < xmin)
  451.             xmin = point->x;
  452.         else if (point->x > xmax)
  453.             xmax = point->x;
  454.         if (point->y < ymin)
  455.             ymin = point->y;
  456.         else if (point->y > ymax)
  457.             ymax = point->y;
  458.         }
  459.     
  460.     diam = 2*radius;
  461.     /* upper left */
  462.     XFillArc(tool_d, canvas_win, gc, xmin, ymin,
  463.             diam, diam, 90*64, 90*64);
  464.     /* lower left */
  465.     XFillArc(tool_d, canvas_win, gc, xmin, ymax-diam,
  466.             diam, diam, 180*64, 90*64);
  467.     /* lower right */
  468.     XFillArc(tool_d, canvas_win, gc, xmax-diam, ymax-diam,
  469.             diam, diam, 270*64, 90*64);
  470.     /* upper right */
  471.     XFillArc(tool_d, canvas_win, gc, xmax-diam, ymin,
  472.             diam, diam, 0*64, 90*64);
  473.     /* fill strip on left side between upper and lower arcs */
  474.     if (ymax-ymin-diam > 0)
  475.         XFillRectangle(tool_d, canvas_win, gc, xmin, ymin+radius,
  476.             radius, ymax-ymin-diam);
  477.     /* fill middle section */
  478.     if (xmax-xmin-diam > 0)
  479.         XFillRectangle(tool_d, canvas_win, gc, xmin+radius, ymin,
  480.             xmax-xmin-diam, ymax-ymin);
  481.     /* fill strip on right side between upper and lower arcs */
  482.     if (ymax-ymin-diam > 0)
  483.         XFillRectangle(tool_d, canvas_win, gc, xmax-radius, ymin+radius,
  484.             radius, ymax-ymin-diam);
  485.     }
  486.