home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 January / usenetsourcesnewsgroupsinfomagicjanuary1994.iso / sources / unix / volume11 / graphedit / part02 < prev    next >
Encoding:
Internet Message Format  |  1987-10-05  |  42.5 KB

  1. Subject:  v11i098:  Graphcs editor for Suns, Part02/06
  2. Newsgroups: comp.sources.unix
  3. Sender: sources
  4. Approved: rs@uunet.UU.NET
  5.  
  6. Submitted-by: steinmetz!sbcs!nyfca1!chan (Douglas Chan)
  7. Posting-number: Volume 11, Issue 98
  8. Archive-name: graphedit/part02
  9.  
  10. # This is a shell archive.  Remove anything before this line,
  11. # then unpack it by saving it in a file and typing "sh file".
  12. #
  13. # Contents:  draw.c.shar1 /tmp/catshar
  14.  
  15. echo x - draw.c.shar1
  16. sed 's/^@//' > "draw.c.shar1" <<'@//E*O*F draw.c.shar1//'
  17.  
  18. static char SccsId[] = "@(#)draw.c    1.2 6/8/87 Copyright 1987 SBCS-chan";
  19.  
  20. /*****************************************************************************
  21.  
  22.           (c) Copyright 1987 
  23.  
  24.           Lap-Tak Chan
  25.           Computer Science Department
  26.           State University of New York at Stony Brook
  27.           Stony Brook, NY 11794
  28.  
  29.     This software and its documentation may be used, copied, and
  30.   distributed, provided that this legend appear in all copies and
  31.   that it is not copied or distributed for a profit.
  32.  
  33.   No representations is made about the suitability of this software
  34.   for any purpose.  It is provided "as is" with no support and no
  35.   express or implied warranty.
  36.  
  37. *****************************************************************************/
  38.  
  39. /*****************************************************************************
  40.  
  41.                          Graphic Editor
  42.                          ==============
  43.  
  44.    This file contains all the editing routines in the graphic editor.
  45.  
  46. *****************************************************************************/
  47.  
  48. #include <math.h>
  49. #include <sys/param.h>
  50. #include <sun/fbio.h>
  51. #include <sys/types.h>
  52. #include <sys/dir.h>
  53. #include <strings.h>
  54. #include <errno.h>
  55. #include <sys/file.h>
  56. #include <suntool/sunview.h>
  57. #include <suntool/panel.h>
  58. #include <suntool/icon.h>
  59. #include "display.h"
  60. #include <stdio.h>
  61. #include <sys/file.h>
  62. #include <sunwindow/notify.h>
  63. #include <sys/time.h>
  64.  
  65. static int newseg = GE_MIN_SEG, segopen=0, opensegment;
  66. static struct list *curr_dlist;
  67. static float xlist[100], ylist[100];
  68. static int pointcount;
  69. static float gridxintv=GE_DEFAULT_GRID, gridyintv=GE_DEFAULT_GRID;
  70. double sin(), cos();
  71.  
  72. struct saveattr save_attr =
  73.   { 0,1,75,100, 1, 5, 5 };
  74.  
  75. int segnam, pickid;
  76. Frame base_frame;
  77. static int basefd;
  78.  
  79. static int align=0;
  80. static int show_sample=1;
  81. static char curr_dir[MAXPATHLEN];
  82. static int deleted[MAXUNDELETE];
  83. static int lastdeleted;
  84. static struct attr curr_attr;
  85. static int attr_changed;
  86.  
  87. extern Panel_item text_filen, text_dirn, text_textstr;
  88. extern Panel_item menu_font, cycle_newseg, cycle_fill, cycle_cont;
  89. extern Panel_item menu_linestyle, slider_color, slider_linewidth, slider_charsize;
  90. extern int do_message();
  91.  
  92. /*****************************************************************************
  93.  
  94.     Main will initialize the display list, create the control pad and
  95.   SunCore view surface, create the attribute samples, and pass control
  96.   to window_main_loop to do all the editing.  When control is returned
  97.   after the control pad is quitted, it will call do_exit to terminate the
  98.   view surface and exit.
  99.  
  100. *****************************************************************************/
  101.  
  102. main(argc, argv)
  103. int argc;
  104. char *argv[];
  105. {
  106.     char frame_label[80]; /* label for control pad */
  107.  
  108.     /* define icon for the control pad */
  109.     static short edit_icon_image[]={
  110. #include "images/graphedit.icon"
  111.     };
  112.     DEFINE_ICON_FROM_IMAGE(edit_icon, edit_icon_image);
  113.  
  114.     /* initialize the display list */
  115.     ge_init_display();
  116.  
  117.     /* create the Suncore view surface */
  118.     set_up_core(argv);
  119.  
  120.     /* create the control pad */
  121.     sprintf(frame_label,"graphedit %s - control pad", GE_VERSION);
  122.     base_frame=(window_create(NULL, FRAME,
  123.                               WIN_SHOW,TRUE,
  124.                               FRAME_LABEL, frame_label,
  125.                               FRAME_ARGC_PTR_ARGV, &argc, argv,
  126.                               FRAME_ICON, &edit_icon,
  127.                               0));
  128.     basefd = ( int ) window_get(base_frame, WIN_FD);
  129.     make_control_panel(base_frame);
  130.  
  131.     ge_make_samples();
  132.  
  133.     /* start the interval timer for blinking the current segment */
  134.     start_timer(1);
  135.  
  136.     /* initialize the data structure to undelete segments */
  137.     ge_init_undelete();
  138.  
  139.     /* pass control to SunView */
  140.     window_main_loop(base_frame);
  141.  
  142.     /* terminate the view surface */
  143.     do_exit();
  144.  
  145.     /* done */
  146.     exit(0);
  147.  
  148. } /* main */
  149.  
  150. static int ge_client_id;
  151. static int *ge_id = &ge_client_id;
  152.  
  153. /*****************************************************************************
  154.  
  155.      ge_blinker is the real time timer handling routine to blink the
  156.   current segment.
  157.  
  158. *****************************************************************************/
  159.  
  160. Notify_value ge_blinker(id, which)
  161. int *id;
  162. int which;
  163. {
  164.   if ( segopen && (! curr_dlist->attr.deleted) && curr_dlist->attr.drawn )
  165.     ge_redisplay(curr_dlist);
  166. } /* ge_blinker */
  167.  
  168. /*****************************************************************************
  169.  
  170.     start_timer will start or stop the real time interval timer via the Sun
  171.   notifier to blink the current segment at two seconds intervals.
  172.  
  173.   Input
  174.     start - whether to start blinking
  175.  
  176. *****************************************************************************/
  177.  
  178. start_timer(start)
  179. int start;
  180. {
  181.   struct itimerval timer;
  182.  
  183.   if ( start ) {
  184.     /* start timer */
  185.     timer.it_interval.tv_usec = 0;
  186.     timer.it_interval.tv_sec = 2;
  187.     timer.it_value.tv_usec = 0;
  188.     timer.it_value.tv_sec =2;
  189.  
  190.     (void) notify_set_itimer_func(ge_id, ge_blinker, ITIMER_REAL, &timer, 0);
  191.   }
  192.   else {
  193.     /* stop timer */
  194.     (void) notify_set_itimer_func(ge_id, ge_blinker, ITIMER_REAL, 0, 0);
  195.   }
  196.  
  197. } /* start_timer */
  198.  
  199. /*****************************************************************************
  200.  
  201.     do_set_timer is the notify procedure for the blink current segment option.
  202.   It start/stop the timer according to the value of the option.
  203.  
  204.   Input
  205.     value - value of the option
  206.  
  207. *****************************************************************************/
  208.  
  209. do_set_timer(item, value, event)
  210. Panel_item item;
  211. int value;
  212. Event *event;
  213. {
  214.  
  215.   start_timer(value);
  216.  
  217. } /* do_set_timer */
  218.  
  219. /*****************************************************************************
  220.  
  221.     make_new_seg is called to create a new segment and initialize the 
  222.   attributes of the segment.  When segno is 0, it will assign the next
  223.   segment number available and make it the current segment.
  224.  
  225.   Input
  226.     segno - segment number for the created segment
  227.  
  228.   Output
  229.     Return the segment number of the segment created
  230.  
  231. *****************************************************************************/
  232.  
  233. make_new_seg(segno)
  234. int segno;
  235. {
  236.     struct list *dlist, *ge_display_list();
  237.  
  238.     /* assign the next segment number available and make it the current
  239.        segment when segno is 0 */
  240.     if ( ! segno ) {
  241.       opensegment = newseg++;
  242.       segno = opensegment;
  243.       segopen = TRUE;
  244.       attr_changed = 0;
  245.     }
  246.  
  247.     /* add segment on display list */
  248.     ge_new_segment(segno);
  249.  
  250.     /* initialize attributes for segment */
  251.     dlist=ge_display_list(segno);
  252.     dlist->attr.color=(int)panel_get_value(slider_color);
  253.     dlist->attr.linestyle=(int)panel_get_value(menu_linestyle);
  254.     dlist->attr.linewidth=(int)panel_get_value(slider_linewidth);
  255.     dlist->attr.font=(int)panel_get_value(menu_font);
  256.     dlist->attr.charsize=(int)panel_get_value(slider_charsize);
  257.     dlist->attr.drawn=0;
  258.     dlist->attr.deleted=0;
  259.     dlist->attr.tx=0.; dlist->attr.ty=0.;
  260.     dlist->attr.sx=1.; dlist->attr.sy=1.;
  261.     dlist->attr.ang=0.;
  262.  
  263.     /* update reference to the current segment */
  264.     if ( segno >= GE_MIN_SEG ) {
  265.       curr_dlist=dlist;
  266.       curr_attr = dlist->attr;
  267.     }
  268.  
  269.     /* return segment number */
  270.     return(segno);
  271.  
  272. } /* make_new_seg */
  273.  
  274. /*****************************************************************************
  275.  
  276.     do_new_seg will create a new segment with an assigned segment number
  277.   and give message in the panel.
  278.  
  279. *****************************************************************************/
  280.  
  281. do_new_seg()
  282. {
  283.     make_new_seg(0);
  284.     do_message("New segment created.");
  285.     do_usage("","","");
  286. } /* do_new_seg */
  287.  
  288. /*****************************************************************************
  289.  
  290.     unxform will determine the coordinate of a point from which a world
  291.   coordinate is transformed according to the transformation of the current
  292.   segment.
  293.  
  294.   Input
  295.     x,y - world coordinate
  296.  
  297.   Output
  298.     ux,uy - coordinate relative to current segment
  299.  
  300. *****************************************************************************/
  301.  
  302. unxform(x,y,ux,uy)
  303. float x,y, *ux, *uy;
  304. {
  305.     float sina, cosa;
  306.  
  307.     sina=sin((double)curr_dlist->attr.ang);
  308.     cosa=cos((double)curr_dlist->attr.ang);
  309.     *ux=((x-curr_dlist->attr.tx)*cosa + (y-curr_dlist->attr.ty)*sina)
  310.         /curr_dlist->attr.sx;
  311.     *uy=((y-curr_dlist->attr.ty)*cosa - (x-curr_dlist->attr.tx)*sina)
  312.         /curr_dlist->attr.sy;
  313.  
  314. } /* unxform */
  315.  
  316. /*****************************************************************************
  317.  
  318.     ge_initdraw do the necessary initializion before a primitive can be
  319.   added.  It create a new segment if necessary, flush previous mouse
  320.   input, and update the attributes of the current segment if they are
  321.   different from the attributes chosen.
  322.  
  323. *****************************************************************************/
  324.  
  325. ge_initdraw()
  326. {
  327.   struct attr newattr;
  328.  
  329.   /* create new segment if necessary */
  330.   if ( (! segopen) || (int)panel_get_value(cycle_newseg))
  331.     do_new_seg();
  332.  
  333.   /* flush previous mouse input */
  334.   ge_flush();
  335.  
  336.   /* clear any previous message */
  337.   do_message("");
  338.  
  339.   /* update any changed attributes */
  340.   if ( attr_changed ) {
  341.  
  342.     /* get attributes chosen */
  343.     newattr.color=(int)panel_get_value(slider_color);
  344.     newattr.linestyle=(int)panel_get_value(menu_linestyle);
  345.     newattr.linewidth=(int)panel_get_value(slider_linewidth);
  346.     newattr.font=(int)panel_get_value(menu_font);
  347.     newattr.charsize=(int)panel_get_value(slider_charsize);
  348.  
  349.     /* update attributes */
  350.     if ( newattr.color != curr_attr.color ) {
  351.       ge_graph(opensegment, GE_SETCOLOR, (float)newattr.color, 0.);
  352.       curr_attr.color = newattr.color;
  353.     }
  354.     if ( newattr.linestyle != curr_attr.linestyle ) {
  355.       ge_graph(opensegment, GE_SETTYPELINE, (float)newattr.linestyle, 0.);
  356.       curr_attr.linestyle = newattr.linestyle;
  357.     }
  358.     if ( newattr.linewidth != curr_attr.linewidth ) {
  359.       ge_graph(opensegment, GE_SETLINEWIDTH, (float)newattr.linewidth, 0.);
  360.       curr_attr.linewidth = newattr.linewidth;
  361.     }
  362.     if ( newattr.font != curr_attr.font ) {
  363.       ge_graph(opensegment, GE_SETFONT, (float)newattr.font, 0.);
  364.       curr_attr.font = newattr.font;
  365.     }
  366.     if ( newattr.charsize != curr_attr.charsize ) {
  367.       ge_graph(opensegment, GE_SETCHARSIZE, (float)newattr.charsize, 0.);
  368.       curr_attr.charsize = newattr.charsize;
  369.     }
  370.  
  371.     attr_changed = 0;
  372.   } /* if */
  373.  
  374. } /* ge_initdraw */
  375.  
  376. /*****************************************************************************
  377.  
  378.     do_text is used to add text primitive to the current segment.  The content
  379.   of the text is supposed to be in the text field on the control pad.  It will
  380.   ask for the position to put the text.
  381.  
  382. *****************************************************************************/
  383.  
  384. do_text()
  385. {
  386.     int butnum;
  387.     float x, y, ux, uy;
  388.     char *string;
  389.     int length;
  390.  
  391.     /* get text from text field on control pad */
  392.     string=(char *)panel_get_value(text_textstr);
  393.  
  394.     /* abort if text field is empty */
  395.     if ( string[0] == '\0' ) {
  396.       do_message("Empty text.");
  397.       return;
  398.     }
  399.  
  400.     /* initialize for primitive */
  401.     ge_initdraw();
  402.  
  403.     /* get position to put text */
  404.     do_usage("Put Text", "", "Cancel");
  405.     do {
  406.         ge_locator(1,&butnum, &x, &y);
  407.     if (butnum == 3) return(0);
  408.         ge_align(&x, &y);
  409.     } while (butnum != 1);
  410.     unxform(x,y,&ux,&uy);
  411.  
  412.     /* add primitive to display list of segment */
  413.     ge_graph(opensegment, GE_MOVE, ux, uy);
  414.     ge_graph(opensegment, GE_TEXT,
  415.       (float)((int)strcpy((char *)malloc(strlen(string)),string)), 0.);
  416.  
  417.     /* redraw segment */
  418.     ge_draw(opensegment);
  419.  
  420.     /* clear usage */
  421.     do_usage("","","");
  422.  
  423.     /* repeat if continous option is on */
  424.     if ( panel_get_value(cycle_cont) ) do_text();
  425.  
  426. } /* do_text */
  427.  
  428. /*****************************************************************************
  429.  
  430.     do_rect is used to add a rectangle to the current segment.  It will ask
  431.   for the diagonal corners of the rectangle.
  432.  
  433. *****************************************************************************/
  434.  
  435. do_rect()
  436. {
  437.     int butnum, tmp;
  438.     float c1x, c1y, c2x, c2y, u1x, u1y, u2x, u2y, u3x, u3y, u4x, u4y;
  439.  
  440.     /* initialize to add primitive */
  441.     ge_initdraw();
  442.  
  443.     /* ask for first corner */
  444.     do_usage("Corner", "", "Cancel");
  445.     do {
  446.         ge_locator(1,&butnum, &c1x, &c1y);
  447.         if (butnum == 3) return(0);
  448.     } while (butnum != 1);
  449.     ge_align(&c1x, &c1y);
  450.  
  451.     /* ask for the diagonal corners */
  452.     do_usage("", "", "Done");
  453.     ge_locator(-1,&butnum, &c2x, &c2y);
  454.     ge_align(&c2x, &c2y);
  455.     do {
  456.       /* draw current rectangle */
  457.       ge_tmp_new(c1x, c1y, curr_attr);
  458.       ge_tmp_line(c1x, c2y);
  459.       ge_tmp_line(c2x, c2y);
  460.       ge_tmp_line(c2x, c1y);
  461.       ge_tmp_line(c1x, c1y);
  462.       /* get location of other corner */
  463.       ge_locator(-1,&butnum, &c2x, &c2y);
  464.       ge_align(&c2x, &c2y);
  465.       ge_tmp_delete();
  466.     } while ( butnum != 3 );
  467.  
  468.     /* get coordinates of the four corners for the current segment */
  469.     unxform(c1x, c1y, &u1x, &u1y);
  470.     unxform(c1x, c2y, &u2x, &u2y);
  471.     unxform(c2x, c2y, &u3x, &u3y);
  472.     unxform(c2x, c1y, &u4x, &u4y);
  473.  
  474.     /* check when retangle has to be filled */
  475.     tmp = (int)panel_get_value(cycle_fill);
  476.     if ( tmp )
  477.       ge_graph(opensegment, GE_FILL, (float)tmp, 0.);
  478.  
  479.     /* add rectangle to current segment as polygon */
  480.     ge_graph(opensegment, GE_POLYGON, u1x, u1y);
  481.     ge_graph(opensegment, GE_CONT, u2x, u2y);
  482.     ge_graph(opensegment, GE_CONT, u3x, u3y);
  483.     ge_graph(opensegment, GE_CONT, u4x, u4y);
  484.     ge_draw(opensegment);
  485.  
  486.     do_usage("","","");
  487.  
  488.     /* repeat if continous option is on */
  489.     if ( panel_get_value(cycle_cont) ) do_rect();
  490.  
  491. } /* do_rect */
  492.  
  493. /*****************************************************************************
  494.  
  495.     do_arc is used to add an arc to the current segment.  It will ask for
  496.   the two end points of the arc and a third point which the arc will pass
  497.   through.
  498.  
  499. *****************************************************************************/
  500.  
  501. do_arc()
  502. {
  503.   int butnum;
  504.   float x1, y1, x2, y2, x3, y3, x, y;
  505.   float ux1, uy1, ux2, uy2, ux3, uy3, radius, ang1, ang2, angs1, angs2, tmp;
  506.   extern float ge_radius2();
  507.   struct list *arc_dlist;
  508.   static int drawn  = 0;
  509.  
  510.   /* initailize to add primitive */
  511.   ge_initdraw();
  512.  
  513.   /* ask for start point */
  514.   do_usage("Start Point", "", "Cancel");
  515.   do {
  516.     ge_locator(1,&butnum, &x1, &y1);
  517.     if (butnum == 3) return(0);
  518.     ge_align(&x1,&y1);
  519.   } while (butnum != 1);
  520.   unxform(x1,y1,&ux1,&uy1);
  521.  
  522.   /* ask for end point */
  523.   do_usage("End point", "", "Cancel");
  524.   do {
  525.     x2=x1;
  526.     y2=y1;
  527.     ge_locator(2,&butnum, &x2, &y2);
  528.     if (butnum == 3) return(0);
  529.   } while (butnum != 1);
  530.   ge_align(&x2, &y2);
  531.   unxform(x2,y2,&ux2,&uy2);
  532.  
  533.   /* ask for where the arc will pass */
  534.   do_usage("","","Done");
  535.   do {
  536.     /* create sample */
  537.     if ( drawn )
  538.       ge_delete_segment(GE_ARC_SAMPLE);
  539.     make_new_seg(GE_ARC_SAMPLE);
  540.  
  541.     /* set attributes of sample */
  542.     arc_dlist=ge_display_list(GE_ARC_SAMPLE);
  543.     arc_dlist->attr=curr_dlist->attr;
  544.     arc_dlist->attr.linestyle = curr_attr.linestyle;
  545.     arc_dlist->attr.linewidth = curr_attr.linewidth;
  546.     arc_dlist->attr.drawn = drawn;
  547.  
  548.     /* get location of mouse where the three points together can
  549.        form an arc */
  550.     do {
  551.       ge_locator(-1,&butnum, &x3, &y3);
  552.       ge_align(&x3,&y3);
  553.       unxform(x3,y3,&ux3,&uy3);
  554.       radius=ge_radius2(ux1,uy1,ux3,uy3,ux2,uy2,&x,&y);
  555.     } while ( radius == 0. );
  556.  
  557.     /* determine the start and end angles of the start and
  558.        end points */
  559.     ang1=atan2((double)(uy1-y), (double)(ux1-x));
  560.     ang2=atan2((double)(uy2-y), (double)(ux2-x));
  561.  
  562.     /* make sure the angles are in the range of 0 and 2PI */
  563.     if (ang1 < 0.) ang1 += 2*PI;
  564.     if (ang2 < 0.) ang2 += 2*PI;
  565.  
  566.     /* check whether the arc is clockwise or counterclockwise from
  567.        the angles between the two lines */
  568.     angs1=atan2((double)(uy3-uy1),(double)(ux3-ux1));
  569.     angs2=atan2((double)(uy2-uy3),(double)(ux2-ux3));
  570.     tmp = angs2-angs1;
  571.  
  572.     /* swap the angles if the arc is clockwise */
  573.     if ( (tmp > PI) ||
  574.          (tmp < 0 && tmp > -PI) ) {
  575.       tmp=ang1;
  576.       ang1=ang2;
  577.       ang2=tmp;
  578.     }
  579.  
  580.     /* draw sample arc */
  581.     ge_graph(GE_ARC_SAMPLE, GE_MOVE, x, y);
  582.     ge_graph(GE_ARC_SAMPLE, GE_ARC, ang1, ang2);
  583.     ge_graph(GE_ARC_SAMPLE, GE_ARCEXT, radius, 0.);
  584.     ge_draw(GE_ARC_SAMPLE);
  585.     drawn = 1;
  586.   } while (butnum != 3);
  587.  
  588.   /* delete sample */
  589.   arc_dlist->attr.deleted=1;
  590.   ge_draw(GE_ARC_SAMPLE);
  591.  
  592.   /* add arc primitive to current segment */
  593.   ge_graph(opensegment, GE_MOVE, x, y);
  594.   ge_graph(opensegment, GE_ARC, ang1, ang2);
  595.   ge_graph(opensegment, GE_ARCEXT, radius, 0.);
  596.   ge_draw(opensegment);
  597.  
  598.   do_usage("","","");
  599.  
  600.   /* repeat if continous mode is on */
  601.   if ( panel_get_value(cycle_cont) ) do_arc();
  602.  
  603. } /* do_arc */
  604.  
  605. /*****************************************************************************
  606.  
  607.     do_draw_circle is used to add a circle or ellipse primitive to the
  608.   current segment.  It will ask for the center of the circle/ellipse.
  609.   Then it will ask for where the circle/ellipse will pass through while
  610.   drawing the circle for the current location of the mouse.
  611.  
  612.   Input
  613.     instr - either GE_CIRCLE or GE_ELLIPSE to indicate what it is drawing
  614.  
  615. *****************************************************************************/
  616.  
  617. do_draw_circle(instr)
  618. int instr;
  619. {
  620.     int butnum, tmp;
  621.     float cx, cy, x, y, ux, uy, ux2, uy2, x2, y2, radius, a, b;
  622.     float sina, cosa, sqrt2;
  623.     struct list *cir_dlist;
  624.  
  625.     /* initialize to add primitive */
  626.     ge_initdraw();
  627.  
  628.     /* ask for center */
  629.     do_usage("Center", "", "Cancel");
  630.     do {
  631.         ge_locator(1,&butnum, &x, &y);
  632.         if (butnum == 3) return(0);
  633.         ge_align(&x,&y);
  634.     } while (butnum != 1);
  635.     unxform(x,y,&ux,&uy);
  636.  
  637.     /* create sample circle if it is not there yet */
  638.     if ( ! (cir_dlist=ge_display_list(GE_CIRCLE_SAMPLE)) ){
  639.       float i;
  640.  
  641.       make_new_seg(GE_CIRCLE_SAMPLE);
  642.       cir_dlist=ge_display_list(GE_CIRCLE_SAMPLE);
  643.       ge_graph(GE_CIRCLE_SAMPLE,GE_MOVE, 0.,0.);
  644.       ge_graph(GE_CIRCLE_SAMPLE,GE_CIRCLE, GE_DEFAULT_RADIUS, 0.);
  645.     }
  646.  
  647.     /* set the attributes for the sample circle */
  648.     cir_dlist->attr.ang=curr_dlist->attr.ang;
  649.     cir_dlist->attr.linestyle=curr_dlist->attr.linestyle;
  650.     cir_dlist->attr.linewidth=curr_dlist->attr.linewidth;
  651.     cir_dlist->attr.deleted=0;
  652.     sina = sin((double)curr_dlist->attr.ang);
  653.     cosa = cos((double)curr_dlist->attr.ang);
  654.  
  655.     /* get location of mouse */
  656.     ge_locator(-1,&butnum, &x2, &y2);
  657.     ge_align(&x2, &y2);
  658.     unxform(x2,y2,&ux2,&uy2);
  659.  
  660.     /* draw circle/ellipse passing through location */
  661.     if ( (instr == GE_CIRCLE) ) {
  662.       radius=sqrt((double)((ux2-ux)*(ux2-ux)+(uy2-uy)*(uy2-uy)));
  663.       if ( radius < 1.0 ) radius=1.0;
  664.       cir_dlist->attr.sx=curr_dlist->attr.sx*radius/GE_DEFAULT_RADIUS;
  665.       cir_dlist->attr.sy=curr_dlist->attr.sy*radius/GE_DEFAULT_RADIUS;
  666.       cir_dlist->attr.tx = x;
  667.       cir_dlist->attr.ty = y;
  668.     }
  669.     else {
  670.       sqrt2 = sqrt((double)2.);
  671.       a=fabs((double)(ux2-ux))*sqrt2;
  672.       b=fabs((double)(uy2-uy))*sqrt2;
  673.       if (a < 1.0) a=1.0;
  674.       if (b < 1.0) b=1.0;
  675.       cir_dlist->attr.sx=curr_dlist->attr.sx*a/GE_DEFAULT_RADIUS;
  676.       cir_dlist->attr.sy=curr_dlist->attr.sy*b/GE_DEFAULT_RADIUS;
  677.       cir_dlist->attr.ang=curr_dlist->attr.ang;
  678.       cir_dlist->attr.tx = x;
  679.       cir_dlist->attr.ty = y;
  680.     }
  681.     ge_draw(GE_CIRCLE_SAMPLE);
  682.  
  683.  
  684.     do_usage("","","Done");
  685.  
  686.     do {
  687.  
  688.       /* get current location */
  689.       ge_locator(-1,&butnum, &x2, &y2);
  690.       ge_align(&x2, &y2);
  691.       unxform(x2,y2,&ux2,&uy2);
  692.  
  693.       /* redraw circle sample passing through location */
  694.       if ( (instr == GE_CIRCLE) ) {
  695.         radius=sqrt((double)((ux2-ux)*(ux2-ux)+(uy2-uy)*(uy2-uy)));
  696.         if ( radius < 1.0 ) radius=1.0;
  697.         cir_dlist->attr.sx=curr_dlist->attr.sx*radius/GE_DEFAULT_RADIUS;
  698.         cir_dlist->attr.sy=curr_dlist->attr.sy*radius/GE_DEFAULT_RADIUS;
  699.       }
  700.       else {
  701.         a=fabs((double)(ux2-ux))*sqrt2;
  702.         b=fabs((double)(uy2-uy))*sqrt2;
  703.         if (a < 1.0) a=1.0;
  704.         if (b < 1.0) b=1.0;
  705.         cir_dlist->attr.sx=curr_dlist->attr.sx*a/GE_DEFAULT_RADIUS;
  706.         cir_dlist->attr.sy=curr_dlist->attr.sy*b/GE_DEFAULT_RADIUS;
  707.       }
  708.       ge_redisplay(cir_dlist);
  709.  
  710.     } while (butnum != 3);
  711.  
  712.     /* add circle/ellipse to current segment */
  713.     ge_graph(opensegment, GE_MOVE, ux, uy);
  714.     tmp=(int)panel_get_value(cycle_fill);
  715.     if ( tmp )
  716.       ge_graph(opensegment, GE_FILL, (float)tmp, 0.);
  717.     if ( instr == GE_CIRCLE ) {
  718.       ge_graph(opensegment, GE_CIRCLE, radius, 0.);
  719.     }
  720.     else {
  721.       ge_graph(opensegment, GE_ELLIPSE, a, b);
  722.     }
  723.  
  724.     /* make sample circle/ellipse invisible */
  725.     cir_dlist->attr.deleted=1;
  726.     ge_draw(GE_CIRCLE_SAMPLE);
  727.  
  728.     /* redraw current segment */
  729.     ge_draw(opensegment);
  730.     do_usage("","","");
  731.  
  732.     /* repeat if continous option is on */
  733.     if ( panel_get_value(cycle_cont) ) do_draw_circle(instr);
  734.  
  735. } /* do_draw_circle */
  736.  
  737. /*****************************************************************************
  738.  
  739.     do_circle just call do_draw_circle to draw a circle.
  740.  
  741. *****************************************************************************/
  742.  
  743. do_circle()
  744. {
  745.  
  746.   do_draw_circle(GE_CIRCLE);
  747.  
  748. }
  749.  
  750. /*****************************************************************************
  751.  
  752.     do_ellipse just call do_draw_circle to draw a ellipse.
  753.  
  754. *****************************************************************************/
  755.  
  756. do_ellipse()
  757. {
  758.  
  759.   do_draw_circle(GE_ELLIPSE);
  760.  
  761. }
  762.  
  763. /*****************************************************************************
  764.  
  765.      do_trace is used to add to the current segment a number of lines
  766.   following the movement of the mouse.
  767.  
  768. *****************************************************************************/
  769.  
  770. do_trace()
  771. {
  772.   int butnum;
  773.   float x, y, ux, uy, cx, cy;
  774.  
  775.   /* do necessary initialization */
  776.   ge_initdraw();
  777.  
  778.   /* ask for starting point */
  779.   do_usage("Start point", "", "Cancel");
  780.   do {
  781.     ge_locator(1, &butnum, &x, &y);
  782.       if (butnum == 3) {
  783.         do_usage("","","");
  784.         return(0);
  785.       }
  786.       ge_align(&x,&y);
  787.   } while (butnum != 1);
  788.   unxform(x,y,&ux,&uy);
  789.  
  790.   /* add starting point to current segment */
  791.   ge_graph(opensegment, GE_MOVE, ux, uy);
  792.   ge_tmp_new(x,y, curr_attr);
  793.  
  794.   do_usage("","","Done");
  795.   cx=x;
  796.   cy=y;
  797.   do {
  798.  
  799.     /* ask for current location */
  800.     ge_locator(-1,&butnum, &x, &y);
  801.     if (butnum == 3) {
  802.       ge_tmp_delete();
  803.       ge_draw(opensegment);
  804.       do_usage("","","");
  805.  
  806.       /* repeat if continous mode is on */
  807.       if ( panel_get_value(cycle_cont) ) do_trace();
  808.       return;
  809.     }
  810.  
  811.     /* add line from last location to current location if the distance
  812.        between them is significant enough */
  813.     if ( (fabs((double)x-cx) + fabs((double)y-cy)) > 5. ) {
  814.  
  815.       unxform(x,y,&ux,&uy);
  816.       ge_graph(opensegment, GE_LINE, ux, uy);
  817.       ge_tmp_line(x,y);
  818.  
  819.       cx=x;
  820.       cy=y;
  821.  
  822.     } /* if */
  823.  
  824.   } while (TRUE);
  825.  
  826. } /* do_trace */
  827.  
  828. /*****************************************************************************
  829.  
  830.      do_polyline is used to add a list of connected lines to the current
  831.   segment.
  832.  
  833. *****************************************************************************/
  834.  
  835. do_polyline()
  836. {
  837.     int butnum;
  838.     float cx, cy, x, y, ux, uy;
  839.  
  840.     /* initialize for adding primitive */
  841.     ge_initdraw();
  842.  
  843.     /* get starting location */
  844.     do_usage("Start point","","Cancel");
  845.     do {
  846.       ge_locator(1, &butnum, &x, &y);
  847.     if (butnum == 3) {
  848.           do_usage("","","");
  849.           return(0);
  850.         }
  851.         ge_align(&x,&y);
  852.       } while (butnum != 1);
  853.     unxform(x,y,&ux,&uy);
  854.     ge_graph(opensegment, GE_MOVE, ux, uy);
  855.     ge_tmp_new(x, y, curr_attr);
  856.  
  857.     do_usage("Next point","","Done");
  858.     cx=x;
  859.     cy=y;
  860.     do {
  861.  
  862.         /* ask for next point */
  863.     do {
  864.  
  865.             x=cx;
  866.             y=cy;
  867.             ge_locator(2,&butnum, &x, &y);
  868.             ge_align(&x,&y);
  869.         if (butnum == 3) {
  870.                 /* delete echo */
  871.                 ge_tmp_delete();
  872.  
  873.                 /* draw current segment */
  874.                 ge_draw(opensegment);
  875.                 do_usage("","","");
  876.  
  877.                 /* repeat if continous option is on */
  878.                 if ( panel_get_value(cycle_cont) ) do_polyline();
  879.                 return;
  880.         } /* if */
  881.  
  882.     } while (butnum != 1);
  883.         unxform(x,y,&ux,&uy);
  884.  
  885.         /* add line to next point */
  886.         ge_graph(opensegment, GE_LINE, ux, uy);
  887.  
  888.         /* echo line */
  889.         ge_tmp_line(x,y);
  890.  
  891.         cx=x;
  892.         cy=y;
  893.  
  894.     } while (TRUE);
  895.  
  896. } /* do_polyline */
  897.  
  898. /*****************************************************************************
  899.  
  900.     do_polygon is used to add a polygon primitive to the current segment.
  901.   It will ask for a starting point and a number of other points.  It will
  902.   also connect automatically connect from the last point to the first point.
  903.  
  904. *****************************************************************************/
  905.  
  906. do_polygon()
  907. {
  908.     int butnum,tmp;
  909.     float cx, cy, x, y, ux, uy;
  910.  
  911.     /* initialize for adding primitive */
  912.     ge_initdraw();
  913.  
  914.     /* ask for starting poitn */
  915.     do_usage("Start point","","Cancel");
  916.     do {
  917.     ge_locator(1, &butnum, &x, &y);
  918.     if (butnum == 3) {
  919.           do_usage("","","");
  920.           return(0);
  921.         }
  922.         ge_align(&x,&y);
  923.     } while (butnum != 1);
  924.     unxform(x,y,&ux,&uy);
  925.  
  926.     /* check the fill option and update display list of current segment */
  927.     tmp=(int)panel_get_value(cycle_fill);
  928.     if ( tmp )
  929.       ge_graph(opensegment, GE_FILL, (float)tmp, 0.);
  930.  
  931.     /* add polygon to display list and initialize for other points */
  932.     ge_graph(opensegment, GE_POLYGON, ux, uy);
  933.     ge_tmp_new(x,y,curr_attr);
  934.     cx=x; cy=y;
  935.     pointcount = 1;
  936.  
  937.     /* ask for the other points */
  938.     do_usage("Next point","","Done");
  939.     do {
  940.         /* get next point */
  941.     do {
  942.             x=cx; y=cy;
  943.             ge_locator(2, &butnum, &x, &y);
  944.         if (butnum == 3 || pointcount > 98) {
  945.                 /* delete echo */
  946.                 ge_tmp_delete();
  947.  
  948.                 /* draw current segment */
  949.                 ge_draw(opensegment);
  950.                 do_usage("","","");
  951.  
  952.                 /* repeat if continous option is on */
  953.                 if ( panel_get_value(cycle_cont) )
  954.                   do_polygon();
  955.         return;
  956.             } /* if */
  957.             ge_align(&x,&y);
  958.     } while (butnum != 1);
  959.         unxform(x,y,&ux,&uy);
  960.  
  961.         /* add point to display list of current segment */
  962.         ge_graph(opensegment, GE_CONT, ux, uy);
  963.  
  964.         /* echo */
  965.         ge_tmp_line(x,y);
  966.         pointcount++;
  967.         cx=x; cy=y;
  968.  
  969.     } while (TRUE);
  970.  
  971. } /* do_polygon */
  972.  
  973. /*****************************************************************************
  974.  
  975.     do_del_seg is used to delete a segment, which may be undeleted later.
  976.   It will ask for the segment to delete.
  977.  
  978. *****************************************************************************/
  979.  
  980. do_del_seg()
  981. {
  982.   struct list *dlist;
  983.   int segnam;
  984.  
  985.   /* ask for segment to delete */
  986.   do_message("");
  987.   do_usage("Select segment","","");
  988.  
  989.   /* get segment number and ask for confirm */
  990.   if ( (segnam=ge_pick()) && 
  991.        wmgr_confirm(basefd, "Press the left mouse button to confirm Delete.  To cancel, press the right mouse button now.")) {
  992.  
  993.     /* mark segment as deleted */
  994.     dlist=ge_display_list(segnam);
  995.     dlist->attr.deleted = 1;
  996.     ge_draw(segnam);
  997.  
  998.     /* close current segment if segment is current segment */
  999.     if (opensegment == segnam) segopen = FALSE;
  1000.  
  1001.     /* add segment to list of deleted segment */
  1002.     lastdeleted = (lastdeleted + 1) % MAXUNDELETE;
  1003.     deleted[lastdeleted] = segnam;
  1004.  
  1005.     do_message("Segment deleted");
  1006.   }
  1007.   else do_message("No segment selected.");
  1008.   do_usage("","","");
  1009.  
  1010.   /* repeat if continous option is on */
  1011.   if ( segnam && panel_get_value(cycle_cont) )
  1012.     do_del_seg();
  1013.  
  1014. } /* do_del_seg */
  1015.  
  1016. /*****************************************************************************
  1017.  
  1018.     ge_init_undelete initialize the circular stack storing the segment
  1019.   numbers of the deleted segments.
  1020.  
  1021. *****************************************************************************/
  1022.  
  1023. ge_init_undelete()
  1024. {
  1025.   int i;
  1026.  
  1027.   for ( i=0; i < MAXUNDELETE; i++ )
  1028.     deleted[i]=0;
  1029.   lastdeleted=0;
  1030.  
  1031. } /* ge_init_undelete */
  1032.  
  1033. /*****************************************************************************
  1034.  
  1035.     do_undelete will undelete the last segment deleted, which is at the top
  1036.   of the circular stack.  It will not delete if the stack is empty.
  1037.  
  1038. *****************************************************************************/
  1039.  
  1040. do_undelete()
  1041. {
  1042.   struct list *dlist;
  1043.  
  1044.   /* do not delete if stack is empty */
  1045.   if ( ! deleted[lastdeleted] ) {
  1046.     do_message("Cannot undelete");
  1047.     return;
  1048.   }
  1049.  
  1050.   /* unmark segment as deleted */
  1051.   dlist=ge_display_list(deleted[lastdeleted]);
  1052.   dlist->attr.deleted = 0;
  1053.  
  1054.   /* draw segment on view surface */
  1055.   ge_draw(deleted[lastdeleted]);
  1056.  
  1057.   /* pop segment number off stack */
  1058.   deleted[lastdeleted]=0;
  1059.   lastdeleted = (lastdeleted + MAXUNDELETE - 1) % MAXUNDELETE;
  1060.   do_message("Undeleted.");
  1061.  
  1062. } /* do_undelete */
  1063.  
  1064. /*****************************************************************************
  1065.  
  1066.      do_edit_seg is used to choose an existing segment to become the current
  1067.   segment.  It will ask the user to pick a segment, and update the
  1068.   attributes in curr_attr according to the initial attribute and any changes
  1069.   in the display list.
  1070.  
  1071. *****************************************************************************/
  1072.  
  1073. do_edit_seg()
  1074. {
  1075.   int segnam;
  1076.   struct list_item *ptr;
  1077.  
  1078.   /* ask user to pick a segment */
  1079.   do_message("");
  1080.   do_usage("Select segment", "", "");
  1081.  
  1082.   if (segnam=ge_pick() ) {
  1083.     /* make it the current segment */
  1084.     opensegment=segnam;
  1085.     segopen=TRUE;
  1086.     curr_dlist=ge_display_list(segnam);
  1087.  
  1088.     /* update curr_attr */
  1089.     curr_attr=curr_dlist->attr;
  1090.     if ((ptr=curr_dlist->d_list)) {
  1091.  
  1092.       ptr=ptr->next;
  1093.       /* scan display list for change of attributes */
  1094.       do {
  1095.         switch (ptr->instr){
  1096.           case GE_SETCOLOR:
  1097.             curr_attr.color = (int) ptr->x;
  1098.             break;
  1099.           case GE_SETTYPELINE:
  1100.             curr_attr.linestyle = (int) ptr->x;
  1101.             break;
  1102.           case GE_SETLINEWIDTH:
  1103.             curr_attr.linewidth = (int) ptr->x;
  1104.             break;
  1105.           case GE_SETFONT:
  1106.             curr_attr.font = (int) ptr->x;
  1107.             break;
  1108.           case GE_SETCHARSIZE:
  1109.             curr_attr.charsize = (int) ptr->x;
  1110.             break;
  1111.           default: break;
  1112.         } /* switch */
  1113.         ptr=ptr->next;
  1114.       } while ( ptr != curr_dlist->d_list->next );
  1115.  
  1116.     } /* if */
  1117.     do_message("Segment selected");
  1118.  
  1119.   }
  1120.   else do_message("No segment selected.");
  1121.   do_usage("","","");
  1122.  
  1123. } /* do_edit_seg */
  1124.  
  1125. /*****************************************************************************
  1126.  
  1127.     do_transform_segment is used to move, rotate or scale a segment.  It
  1128.   will ask the user to pick a segment, and then let the user adjust the
  1129.   transformation with the mouse while eching the current transformation.
  1130.   The transformation will be done on the point where the segment is picked.
  1131.  
  1132.   Input
  1133.     mode - 0: move
  1134.            1: rotate
  1135.            2: scale
  1136.  
  1137. *****************************************************************************/
  1138.  
  1139. do_transform_segment( mode)
  1140. int mode;
  1141. {
  1142.     int segnam, pickid, butnum;
  1143.     float sx0, sy0, ang0, tx0, ty0;
  1144.     float x, y;
  1145.     float dx, dy, nx, ny, sina, cosa;
  1146.     float wx, wy;
  1147.     struct list *dlist;
  1148.  
  1149.     /* ask the user to pick a segment */
  1150.     do_usage("Select segment","","");
  1151.     do_message("");
  1152.     if ((segnam=ge_pick()) < GE_MIN_SEG) {
  1153.       do_message("No segment selected.");
  1154.       return;
  1155.     }
  1156.  
  1157.     /* get location where segment is picked */
  1158.     ge_locator( -1, &butnum, &wx, &wy);
  1159.  
  1160.     /* save current transformation of segment */
  1161.     dlist=ge_display_list(segnam);
  1162.     ang0=dlist->attr.ang;
  1163.     sx0=dlist->attr.sx; sy0=dlist->attr.sy;
  1164.     tx0=dlist->attr.tx; ty0=dlist->attr.ty;
  1165.  
  1166.     sina = sin(ang0); cosa = cos(ang0);
  1167.  
  1168.     /* keep doing transformation until it is done */
  1169.     do_usage("","Cancel","Done");
  1170.     do {
  1171.     ge_locator( -1, &butnum, &x, &y);
  1172.         if ( butnum==2 ) {
  1173.             /* cancel transformation */
  1174.             dlist->attr.tx=tx0;
  1175.             dlist->attr.ty=ty0;
  1176.             dlist->attr.sx=sx0;
  1177.             dlist->attr.sy=sy0;
  1178.             dlist->attr.ang=ang0;
  1179.             ge_redisplay(dlist);
  1180.             do_usage("","","");
  1181.             do_message("Cancelled");
  1182.             return;
  1183.         }
  1184.  
  1185.         /* determine new transformation */
  1186.     switch (mode) {
  1187.     case 0:
  1188.         {
  1189.               /* move */
  1190.               float tx, ty;
  1191.  
  1192.               /* determine amount of move */
  1193.               tx = x-wx;
  1194.               ty = y-wy;
  1195.               ge_align(&tx,&ty);
  1196.               dlist->attr.tx = tx0 + tx;
  1197.               dlist->attr.ty = ty0 + ty;
  1198.             }
  1199.         break;
  1200.  
  1201.     case 1:
  1202.             /* rotate */
  1203.  
  1204.             /* determine angle to rotate */
  1205.         dlist->attr.ang = ang0 + (x-wx) * 0.012;
  1206.  
  1207.             /* calculate adjustment necessary to rotate at (wx,wy) */
  1208.         sina = sin(dlist->attr.ang-ang0);
  1209.             cosa = cos(dlist->attr.ang-ang0);
  1210.         nx = wx - (cosa * wx - sina * wy);
  1211.         ny = wy - (sina * wx + cosa * wy);
  1212.             dlist->attr.tx = tx0 * cosa - ty0 * sina + nx;
  1213.             dlist->attr.ty = tx0 * sina + ty0 * cosa + ny;
  1214.         break;
  1215.     case 2:
  1216.           {
  1217.             /* scale */
  1218.             extern Panel_item cycle_scale;
  1219.  
  1220.             /* determine how much to scale */
  1221.         dlist->attr.sx = sx0 + (x-wx) * 0.02 * fabs((double)cosa)
  1222.                                  + (y-wy) * 0.02 * fabs((double)sina);
  1223.             if ( (int)panel_get_value(cycle_scale) ) {
  1224.               /* scale uniformly when option is on */
  1225.               dlist->attr.sy = dlist->attr.sx/sx0*sy0;
  1226.             }
  1227.             else {
  1228.               dlist->attr.sy = sy0 + (y-wy) * 0.02 * fabs((double)cosa)
  1229.                                    + (x-wx) * 0.02 * fabs((double)sina);
  1230.             } /* else */
  1231.  
  1232.             /* calculate adjustment necessary to scale at (wx,wy).
  1233.                it is difficult to adjust */
  1234.             nx = ((wx-tx0)*cosa + (wy-ty0)*sina)/sx0;
  1235.             ny = ((wy-ty0)*cosa - (wx-tx0)*sina)/sy0;
  1236.             dlist->attr.tx = tx0 + nx*cosa*(sx0 - dlist->attr.sx) -
  1237.                                    ny*sina*(sy0 - dlist->attr.sy);
  1238.             dlist->attr.ty = ty0 + nx*sina*(sx0 - dlist->attr.sx) +
  1239.                                    ny*cosa*(sy0 - dlist->attr.sy);
  1240.           } /* case scale */
  1241.           break;
  1242.     default:;
  1243.     } /* switch */
  1244.  
  1245.       /* redraw segment */
  1246.       ge_redisplay(dlist);
  1247.     } while (butnum != 3);
  1248.  
  1249.     do_usage("","","");
  1250.  
  1251.     /* repeat if continous option is on */
  1252.     if ( panel_get_value(cycle_cont) )
  1253.       do_transform_segment(mode);
  1254.  
  1255. } /* do_transform_segment */
  1256.  
  1257. /*****************************************************************************
  1258.  
  1259.     do_pos call do_transform_segment to move a segment.
  1260.  
  1261. *****************************************************************************/
  1262.  
  1263. do_pos()
  1264. {
  1265.  
  1266.   do_transform_segment(0);
  1267.  
  1268. } /* do_pos */
  1269.  
  1270. /*****************************************************************************
  1271.  
  1272.     do_rot calls do_transform_segment to move a segment.
  1273.  
  1274. *****************************************************************************/
  1275.  
  1276. do_rot()
  1277. {
  1278.  
  1279.   do_transform_segment(1);
  1280.  
  1281. } /* do_rot */
  1282.  
  1283. /*****************************************************************************
  1284.  
  1285.     do_size calls do_transform_segment to move a segment.
  1286.  
  1287. *****************************************************************************/
  1288.  
  1289. do_size()
  1290. {
  1291.  
  1292.   do_transform_segment(2);
  1293.  
  1294. } /* do_size */
  1295.  
  1296. /*****************************************************************************
  1297.  
  1298.     do_confirm_exit is used by the quit function to confirm the quit, and
  1299.   actually destroy the control pad upon confirmation.
  1300.  
  1301. *****************************************************************************/
  1302.  
  1303. do_confirm_exit()
  1304. {
  1305.    if ( wmgr_confirm(basefd, "Press the left mouse button to confirm Quit.  To cancel, press the right mouse button now.") ) {
  1306.  
  1307.      /* destroy the control pad */
  1308.      window_set(base_frame,
  1309.        FRAME_NO_CONFIRM, TRUE,
  1310.        0);
  1311.      window_destroy(base_frame);
  1312.    } /* if */
  1313.  
  1314. } /* do_confirm_exit */
  1315.  
  1316. /*****************************************************************************
  1317.  
  1318.     do_align is the notify procedure of the align on/off option.  It just
  1319.   change align to the value.
  1320.  
  1321. *****************************************************************************/
  1322.  
  1323. do_align(item, value, event)
  1324. Panel_item item;
  1325. int value;
  1326. Event *event;
  1327. {
  1328.  
  1329.   align=value;
  1330.  
  1331. } /* do_align */
  1332.  
  1333. /*****************************************************************************
  1334.  
  1335.     ge_align will change (x,y) by any necessary alignment.
  1336.  
  1337.     Input
  1338.       x,y - pointer to coordinate to be aligned
  1339.  
  1340.     Output
  1341.       x,y - pointer to aligned coordinate
  1342.  
  1343. *****************************************************************************/
  1344.  
  1345. ge_align(x,y)
  1346. float *x, *y;
  1347. {
  1348.  
  1349.   if ( align ) {
  1350.     *x = floor(*x/gridxintv + 0.5) * gridxintv;
  1351.     *y = floor(*y/gridyintv + 0.5) * gridyintv;
  1352.   }
  1353.  
  1354. } /* ge_align */
  1355.  
  1356. /*****************************************************************************
  1357.  
  1358.     do_change_grid is the notify procedure for the sliders of the grid interval
  1359.   along the x and y axis.  It change the grid interval by changing the
  1360.   scale of the sample grid.
  1361.  
  1362. *****************************************************************************/
  1363.  
  1364. do_change_grid(item, value, event)
  1365. Panel_item item;
  1366. int value;
  1367. Event *event;
  1368. {
  1369.   struct list *dlist;
  1370.   extern Panel_item slider_gridx, slider_gridy;
  1371.  
  1372.   dlist=ge_display_list(GE_GRID);
  1373.  
  1374.   /* change scale of the grid according to the value.
  1375.   if ( item == slider_gridx ) {
  1376.     gridxintv=value;
  1377.     dlist->attr.sx=gridxintv/GE_DEFAULT_GRID;
  1378.   }
  1379.   else {
  1380.     gridyintv=value;
  1381.     dlist->attr.sy=gridyintv/GE_DEFAULT_GRID;
  1382.   }
  1383.  
  1384.   /* redraw grid */
  1385.   if ( ! dlist->attr.deleted )
  1386.     ge_redisplay(dlist);
  1387.  
  1388. } /* do_change_grid */
  1389.  
  1390. /*****************************************************************************
  1391.  
  1392.     do_grid is the notify procedure for the grid on/off option.  It will
  1393.   create the segment for the grid if it is not there and either display it
  1394.   or make it invisible according to value.
  1395.  
  1396. *****************************************************************************/
  1397.  
  1398. do_grid(item, value, event)
  1399. Panel_item item;
  1400. int value;
  1401. Event *event;
  1402. {
  1403.   struct list *dlist;
  1404.   int i;
  1405.  
  1406.   /* create grid segment if it is not there */
  1407.   if ( ! (dlist=ge_display_list(GE_GRID)) ) {
  1408.  
  1409.     /* create grid */
  1410.     make_new_seg(GE_GRID);
  1411.     dlist=ge_display_list(GE_GRID);
  1412.     dlist->attr.linestyle=1;
  1413.  
  1414.     /* draw vertical lines */
  1415.     for ( i=1; i <= (GE_WIN_X/GE_MIN_GRID); i++ ) {
  1416.       ge_graph(GE_GRID, GE_MOVE, i * GE_DEFAULT_GRID, 0.);
  1417.       ge_graph(GE_GRID, GE_LINE, i * GE_DEFAULT_GRID, GE_WIN_Y/GE_MIN_GRID*GE_DEFAULT_GRID);
  1418.     } /* for */
  1419.  
  1420.     /* draw horizontal lines */
  1421.     for ( i=1; i <= (GE_WIN_Y/GE_MIN_GRID); i++ ) {
  1422.       ge_graph(GE_GRID, GE_MOVE, 0., i * GE_DEFAULT_GRID);
  1423.       ge_graph(GE_GRID, GE_LINE, GE_WIN_X/GE_MIN_GRID*GE_DEFAULT_GRID, i * GE_DEFAULT_GRID);
  1424.     } /* for */
  1425.   } /* if */
  1426.  
  1427.   /* display/delete grid according to value */
  1428.   dlist->attr.deleted = !value;
  1429.   ge_draw(GE_GRID);
  1430.  
  1431. } /* do_grid */
  1432.  
  1433. /*****************************************************************************
  1434.  
  1435.     ge_make_samples will create the text, color and line samples and the
  1436.   grid.
  1437.  
  1438. *****************************************************************************/
  1439.  
  1440. ge_make_samples()
  1441. {
  1442.     int i, j;
  1443.  
  1444.     do_change_color(0,0,0);
  1445.     do_change_linewidth(0,0,0);
  1446.     do_change_linestyle(0,0,0);
  1447.     do_change_font(0,0,0);
  1448.     do_change_charsize(0,GE_DEFAULT_CHARSIZE,0);
  1449.     do_grid(0,0,0);
  1450.     do_usage("","","");
  1451.  
  1452. } /* ge_make_samples */
  1453.  
  1454. /*****************************************************************************
  1455.  
  1456.     do_change_color is the notify procedure for the color slider.  It will
  1457.   create the color sample if it is not there and update the color of
  1458.   the color sample according to the value from the slider.
  1459.  
  1460. *****************************************************************************/
  1461.  
  1462. /* define coordinates of the color sample */
  1463. #define COLORX 20.
  1464. #define COLORY 350.
  1465. static float colorbox[4] = {0., 25., 25., 0.};
  1466. static float colorboy[4] = {0., 0., 25., 25.};
  1467.  
  1468. do_change_color(item, value,event)
  1469. Panel_item item;
  1470. int value;
  1471. Event *event;
  1472. {
  1473.     struct list *dlist;
  1474.     extern int *font_menu;
  1475.  
  1476.     /* create segment for the color sample if it is not there */
  1477.     if ( !(dlist=ge_display_list(GE_COLOR_SAMPLE)) ) {
  1478.  
  1479.       /* create segment and draw box as color sample */
  1480.       make_new_seg(GE_COLOR_SAMPLE);
  1481.       dlist=ge_display_list(GE_COLOR_SAMPLE);
  1482.       ge_graph(GE_COLOR_SAMPLE, GE_FILL, (float)GE_FILLONLY, 0.);
  1483.       ge_graph(GE_COLOR_SAMPLE, GE_POLYGON,COLORX+colorbox[0], COLORY+colorboy[0]);
  1484.       ge_graph(GE_COLOR_SAMPLE, GE_CONT,COLORX+colorbox[1], COLORY+colorboy[1]);
  1485.       ge_graph(GE_COLOR_SAMPLE, GE_CONT,COLORX+colorbox[2], COLORY+colorboy[2]);
  1486.       ge_graph(GE_COLOR_SAMPLE, GE_CONT,COLORX+colorbox[3], COLORY+colorboy[3]);
  1487.  
  1488.     } /* if */
  1489.  
  1490.     /* change color of color sample and draw sample */
  1491.     dlist->attr.color=value;
  1492.     attr_changed = 1;
  1493.     ge_draw(GE_COLOR_SAMPLE);
  1494.  
  1495. } /* do_change_color */
  1496.  
  1497. /*****************************************************************************
  1498.  
  1499.     do_change_font is the notify procedure of the font choice.  It will create
  1500.   the text sample if it is not there and update the font of the text sample
  1501.   according to the value chosen on..
  1502.  
  1503. *****************************************************************************/
  1504.  
  1505. /* define coordinates and text of the color sample */
  1506. #define TEXTX 160.
  1507. #define TEXTY 370.
  1508. static char *text_sample="A B C a b c";
  1509.  
  1510. do_change_font(item, value, event)
  1511. Panel_item item;
  1512. int value;
  1513. Event *event;
  1514. {
  1515.     struct list *dlist;
  1516.  
  1517. @//E*O*F draw.c.shar1//
  1518. chmod u=rw,g=r,o=r draw.c.shar1
  1519.  
  1520. echo x - /tmp/catshar
  1521. sed 's/^@//' > "/tmp/catshar" <<'@//E*O*F /tmp/catshar//'
  1522. #!/bin/csh
  1523. #
  1524. # This script combine draw.c.shar1 and draw.c.shar2 together
  1525. if ( -f draw.c.shar1 && -f draw.c.shar2 ) then
  1526. echo 'Reconstruct draw.c from draw.c.shar1 and draw.c.shar2...'
  1527. cat draw.c.shar1 draw.c.shar2 >> draw.c
  1528. /bin/rm -f draw.c.shar1 draw.c.shar2
  1529. endif
  1530. exit 0
  1531. @//E*O*F /tmp/catshar//
  1532. chmod u=rwx,g=rx,o=rx /tmp/catshar
  1533.  
  1534. echo Inspecting for damage in transit...
  1535. temp=/tmp/shar$$; dtemp=/tmp/.shar$$
  1536. trap "rm -f $temp $dtemp; exit" 0 1 2 3 15
  1537. cat > $temp <<\!!!
  1538.     1500    4285   42038 draw.c.shar1
  1539.        9      38     275 catshar
  1540.     1509    4323   42313 total
  1541. !!!
  1542. wc  draw.c.shar1 /tmp/catshar | sed 's=[^ ]*/==' | diff -b $temp - >$dtemp
  1543. if [ -s $dtemp ]
  1544. then echo "Ouch [diff of wc output]:" ; cat $dtemp
  1545. else echo "No problems found."
  1546. fi
  1547. /tmp/catshar
  1548. /bin/rm -f /tmp/catshar
  1549. exit 0
  1550.  
  1551.