home *** CD-ROM | disk | FTP | other *** search
/ Programmer 7500 / MAX_PROGRAMMERS.iso / INFO / GRAPHICS / SHOWGL10.ZIP / SHOWHPGL.C < prev    next >
Encoding:
C/C++ Source or Header  |  1991-08-29  |  44.2 KB  |  1,571 lines

  1. #pragma linesize(132)    /* listing linewidth = 132 */
  2.  
  3. /* showhpgl.c */
  4.  
  5. /* program for reading HP-GL files and plotting to the screen */
  6. /* copyright 1991, Robert C. Becker, Lantern Systems */
  7.  
  8. /* Notice: HP-GL, HP-GL/2, and HP are registered trademarks of the
  9. Hewlett-Packard company */
  10.  
  11. #include <stdio.h>
  12. #include <stdlib.h>
  13. #include <string.h>
  14. #include <ctype.h>
  15. #include <math.h>
  16. #include <dos.h>
  17. #include <time.h>
  18. #include "hpgl.h"
  19. #include "graphix.h"
  20.  
  21. /* Identifiable graphics adapters and modes are:
  22.  
  23. CGA_640x200    IBM CGA 640x200 BW 
  24. ATT_640x400    AT&T 640x400 BW, tiny type 
  25. EGA_640x350    IBM EGA high-res 640x350, 16 color 
  26. MCGA_640x480    IBM MCGA high-res 640x480, BW
  27. VGA_640x480    IBM VGA high-res 640x480, 16 color 
  28.  
  29. This program is linked with autogrph.c to determine the graphics adapter type.
  30. The user is allowed to select the display type if not satisfied with the
  31. default selection.  This permits the user to examine the effect changing 
  32. resolution has on the resulting display when using compatible displays. */
  33.  
  34. struct video_dsp
  35.     {
  36.     struct _vid_x_parm_ *vid_mode;
  37.     int max_colors;
  38.     } ;
  39.  
  40. struct video_dsp video_mode [] = {
  41.     { CGA_640x200, 0},        /* 0: dummy disp. type--no pens (no graphics) */
  42.     { CGA_640x200, 2},        /* 1: CGA */
  43.     { MEGA_640x350, 2},        /* 2: IBM mono EGA */
  44.     { ATT_640x400, 2},        /* 3: ATT PC6300 */
  45.     { MCGA_640x480, 2},        /* 4: IBM MCGA */
  46.     { MCGA_640x480, 2},        /* 5: IBM mono VGA (same mode as high res BW MCGA */
  47.     { EGA_640x350, 16},        /* 6: IBM EGA */
  48.     { VGA_640x480, 16}        /* 7: IBM VGA */
  49.     /* ,{ HERC, 2}            Not Supported    */
  50.     /* ,{ HERC_PLUS, 2}            "    */
  51.     /* ,{ IN_COLOR, 4}            "    */
  52.     };
  53.  
  54.  
  55. #define MAX_COLORS    16    /* maximum number of colors to remap to HP colors */
  56. #define MAX_MODE    7    /* number of unique supported modes */
  57.  
  58. unsigned from_mode [] = { 0, 1, 2, 6, 0, 5, 7, 4, 4, 4, 3, 0, 0, 0, 0, 0 };
  59.  
  60. /* translate returned mode numbers from video_test.  0 -> mapped out 
  61. value (not used).  This array also includes "scoring" of modes.  Least 
  62. desireable modes have the lowest numbers. */
  63.  
  64. /*    media ranges (maximum plotting range) */
  65. /*    paper size    Xmax        Ymax         size */
  66. /*    ANSI A        10365        7962        8.5 x 11 in. */
  67. /*    ANSI B        16640        10365        11 x 17 in. */
  68. /*    ISO A4        11040        7721        210 x 297 mm */
  69. /*    ISO A3        16153        11040        297 x 420 mm */
  70.  
  71. struct cplot cp;    /* variables for CP instruction */
  72. struct csizes cs;    /* variables for SI & SR instructions */
  73.  
  74. extern unsigned video_test ( void );    /* return video display types */
  75.  
  76. static struct paper_size ps[] =
  77.     {
  78.     {0.0, 0.0, 11040.0, 7721.0, 9600.0, 7100.0, 11693.0, 8268.0,
  79.     603.0, 521.0, 10603.0, 7721.0},        /* A4-size */
  80.  
  81.     {0.0, 0.0, 16153.0, 11040.0, 14550.0, 10600.0, 16535.0, 11693.0,
  82.     170.0, 602.0, 15370.0, 10602.0},    /* A3-size */
  83.  
  84.     {0.0, 0.0, 22915.0, 16153.0, 22450.0, 14550.0, 23386.0, 16535.0,
  85.     239.0, 1004.0, 21339.0, 16004.0},    /* A2-size: estimated values */
  86.  
  87.     {0.0, 0.0, 32340.0, 22751.0, 31400.0, 22450.0, 33071.0, 23386.0,
  88.     462.0, 248.0, 31682.0, 21348.0},    /* A1-size: estimated values */
  89.  
  90.     {0.0, 0.0, 45110.0, 33751.0, 44600.0, 32450.0, 46810.0, 33071.0,
  91.     362.0, 448.0, 44682.0, 33348.0},    /* A0-size: estimated values */
  92.  
  93.     {0.0, 0.0, 10300.0, 7650.0, 8900.0, 7350.0, 11000.0, 8500.0,
  94.     250.0, 279.0, 10250.0, 7479.0},        /* A-size */
  95.  
  96.     {0.0, 0.0, 16640.0, 10365.0, 15000.0, 9850.0, 17000.0, 11000.0,
  97.     522.0, 259.0, 15722.0, 10259.0},    /* B-size */
  98.  
  99.     {0.0, 0.0, 21365.0, 16640.0, 21050.0, 15000.0, 22000.0, 17000.0,
  100.     225.0, 1141.0, 21325.0, 16341.0},    /* C-size: estimated values */
  101.  
  102.     {0.0, 0.0, 33640.0, 21365.0, 32300.0, 21050.0, 34000.0, 22000.0,
  103.     372.0, 233.0, 33522.0, 21333.0},    /* D-size: estimated values */
  104.  
  105.     {0.0, 0.0, 42542, 33344.0, 42300.0, 32300.0, 44000.0, 34000.0,
  106.     600.0, 600.0, 41944.0, 33250.0}        /* E-size: estimated values */
  107.     };
  108.  
  109. static struct paper_size ps_dp[] =
  110.     {
  111.     {-4860.0, -3600.0, 4860.0, 3600.0, 9600.0, 7100.0, 11693.0, 8268.0,
  112.     -4260.0, -3000.0, 4260.0, 3000.0},        /* A4-size */
  113.  
  114.     {-7320.0, -5340.0, 7320.0, 5340.0, 14550.0, 10600.0, 16535.0, 11693.0,
  115.     -6720.0, 4740.0, 6720.0, 4740.0},    /* A3-size */
  116.  
  117.     {-10800.0, -7800.0, 10800.0, 7800.0, 22450.0, 14550.0, 23386.0, 16535.0,
  118.     -10200.0, -7200.0, 10200.0, 7200.0},    /* A2-size: estimated values */
  119.  
  120.     {-15720.0, -11280.0, 15720.0, 11280.0, 31400.0, 22450.0, 33071.0, 23386.0,
  121.     -15120.0, -10680.0, 15120.0, 10680.0},    /* A1-size: estimated values */
  122.  
  123.     {-22680.0, -16200.0, 22680.0, 16200.0, 44600.0, 32450.0, 46810.0, 33071.0,
  124.     -22080.0, -15600.0, 22080.0, 15600.0},    /* A0-size: estimated values */
  125.  
  126.     {-4508.0, -3718.0, 4508.0, 3718.0, 8900.0, 7350.0, 11000.0, 8500.0,
  127.     -3908.0, -3118.0, 3908.0, 3118.0},        /* A-size */
  128.  
  129.     {-7556.0, -4988.0, 7556.0, 4998.0, 15000.0, 9850.0, 17000.0, 11000.0,
  130.     -6956.0, -4388.0, 6956.0, 4388.0},    /* B-size */
  131.  
  132.     {-10096.0, -8036.0, 10096.0, 8036.0, 21050.0, 15000.0, 22000.0, 17000.0,
  133.     -9496.0, -7436.0, 9496.0, 7436.0},    /* C-size */
  134.  
  135.     {-16192.0, -10576.0, 16192.0, 10576.0, 32300.0, 21050.0, 34000.0, 22000.0,
  136.     -15592.0, -9976.0, 15592.0, 9976.0},    /* D-size */
  137.  
  138.     {-21272.0, -16672.0, 21272.0, 16672.0, 42300.0, 32300.0, 44000.0, 34000.0,
  139.     -20672.0, -16072.0, 20672.0, 16072.0}        /* E-size */
  140.     };
  141.  
  142. static struct options *args;
  143.  
  144. static void anchor_corn ( FILE * );    /* static fn's defined in this file */
  145. static void cold_start ( void );
  146. static void default_coords ( void );
  147. static void error ( char, char );
  148. static void fix_anchor ( void );
  149. static void input_p1p2 ( FILE *, int );
  150. static void iwindow ( FILE * );
  151. static void plot_line ( FILE *, int );
  152. static void pen_down ( FILE * );
  153. static void pen_up ( FILE * );
  154. static void plot_size ( FILE *, int );
  155. static void scale ( FILE * );
  156. static void select_pen ( FILE *, int );
  157. static void set_anchor ( double , double );
  158. static void set_aspect_ratio ( void );
  159. static void set_defaults ( void );
  160. static int video_start ( void );    /* autodetect video adapter */
  161.  
  162. static char copyright [] = "copyright 1991, Robert C. Becker, Lantern Systems";
  163.  
  164. static double x, y, ang1, ang2, ang3, x_1, y_1, x_2, y_2, type;
  165. static int p, init, error_flag, scale_type;
  166. static int plotmode;        /* plotting mode: absolute or relative */
  167.  
  168. static double clip_xmin, clip_xmax, clip_ymin, clip_ymax;
  169. static double cr_xpos, cr_ypos, chord_angle, radius;
  170. static int scaling, i_window, plotter;
  171. static double uux1, uux2, uuy1, uuy2;
  172. static double iwx1, iwx2, iwy1, iwy2;
  173. static int pen_map [MAX_COLORS + 1];
  174.  
  175. struct fill_anchor
  176.     {
  177.     double x, y, px, py;
  178.     int mode;
  179.     };
  180.  
  181. static struct fill_anchor anchor;    /* anchor corner structure */
  182.  
  183. double ip1x, ip1y, ip2x, ip2y, ipxsize, ipysize;
  184. double ipxmin, ipymin, ipxmax, ipymax;
  185. double psxdef, psydef;
  186. double uu_2_pux, uu_2_puy;    /* user units per plotter unit (x, y) */
  187. double p1x, p1y, p2x, p2y;    /* P1/P2 coordinates */
  188. double gdu_cm;            /* # GDU's per cm */
  189. int x_mirror, y_mirror;        /* character mirror flags: 0 = no mirror */
  190. int chord_type;            /* type of chord lines drawn: 0 = fixed angle; 1 = adaptive */
  191. int p_status, symbol_mode;    /* pen_status (up/down), symbol mode flag */
  192. char symbol;        /* char for symbol mode plots */
  193. unsigned endlabel;    /* end-of-line char for LB */
  194.  
  195. main (int argc, char **argv)
  196.     {
  197.     char *s, *t;
  198.     unsigned char c1, c2, ch;
  199.     unsigned l;
  200.     int segs, i, max_pens, video, paper;
  201.     FILE *infile;
  202.  
  203.     args = getargs (argc, argv);
  204.  
  205.     infile = (*args).infile;
  206.     paper = (*args).paper;    /* returns default value of A_paper if not specified */
  207.     video = (*args).video;    /* returns default value of 0 if not specified */
  208.     plotter = (*args).plotter;    /* returns 0 for default, DRAFTPRO otherwise */
  209.  
  210.     if (infile == NULL)
  211.         {
  212.         printf ("Error opening source file\n");
  213.         exit (1);
  214.         }
  215.     if (plotter == DRAFTPRO)
  216.         {
  217.         ip1x = ps_dp[paper].ip1x;    /* default paper size is A-size */
  218.         ip1y = ps_dp[paper].ip1y;
  219.         ip2x = ps_dp[paper].ip2x;
  220.         ip2y = ps_dp[paper].ip2y;    /* default IP positions */
  221.         ipxmin = ps_dp[paper].ipxmin;
  222.         ipymin = ps_dp[paper].ipymin;    /* minimum value for IP coordinates */
  223.         ipxmax = ps_dp[paper].ipxmax;
  224.         ipymax = ps_dp[paper].ipymax;    /* maximum value for IP coordinates */
  225.         ipxsize = ps_dp[paper].ipxsize;
  226.         ipysize = ps_dp[paper].ipysize;    /* size of paper in 1000th's of an inch */
  227.         psxdef = ps_dp[paper].psxdef;
  228.         psydef = ps_dp[paper].psydef;    /* default plot sizes (PS) */
  229.         }
  230.     else
  231.         {
  232.         ip1x = ps[paper].ip1x;    /* default paper size is A-size */
  233.         ip1y = ps[paper].ip1y;
  234.         ip2x = ps[paper].ip2x;
  235.         ip2y = ps[paper].ip2y;    /* default IP positions */
  236.         ipxmin = ps[paper].ipxmin;
  237.         ipymin = ps[paper].ipymin;
  238.         ipxmax = ps[paper].ipxmax;
  239.         ipymax = ps[paper].ipymax;    /* maximum value for PS coordinates */
  240.         ipxsize = ps[paper].ipxsize;
  241.         ipysize = ps[paper].ipysize;    /* size of paper in 1000th's of an inch */
  242.         psxdef = ps[paper].psxdef;
  243.         psydef = ps[paper].psydef;    /* default plot sizes (PS) */
  244.         }
  245.  
  246.     if (!video)        /* no video option force on command line */
  247.         {
  248.         if ((max_pens = video_start ()) < 1)        /* detect and select video adapter & init graphix lib */
  249.             {
  250.             printf ("Unable to detect supported graphix adapter\n");
  251.             exit (1);
  252.             }
  253.         }
  254.     else        /* force adapter into specified video mode */
  255.         {
  256.         max_pens = video_mode [ from_mode [video] ].max_colors;
  257.         g_init (video_mode [ from_mode [video] ].vid_mode);
  258.         }
  259.  
  260.     pen_map[0] = 0;    /* no pen */
  261.  
  262.     for (i = 1; i < max_pens; ++i)        /* build color map: HP colors are the reverse of PC colors */
  263.         pen_map[i] = max_pens - i;
  264.     for (i = max_pens; i <= MAX_COLORS; ++i)
  265.         pen_map[i] = max_pens - 1;    /* make all other pen colors white */
  266.  
  267.  
  268.     cp.lorg = LORG_DEFAULT;        /* default initial label origin */
  269.     cp.x = cp.y = 0.0;        /* initial values for CP last position */
  270.     cs.slant = 0.0;            /* initial char slant */
  271.     cs.rcsize_x = 0.75;
  272.     cs.rcsize_y = 1.5;        /* set default relative char sizes */
  273.  
  274.     /* some basic limitations to HPGL:
  275.     Plotting area can be scaled from -32768 to 32767.  Larger absolute
  276.     values turn off scaling.
  277.     */
  278.  
  279.     csize_mm ();            /* set default csize units to mm's */
  280.  
  281.     cold_start ();            /* initialize plotter */
  282.     endlabel = ETX;            /* default label termination */
  283.     p_status = PENUP;
  284.  
  285.     while ( (c1 = getc (infile)) != (unsigned char) EOF)
  286.         {
  287.         c2 = getc (infile);
  288.         DB (printf ("c1 c2 = %c%c\n", c1, c2);)
  289.         error_flag = 0;        /* clear error_flag */
  290.         switch ( tolower ( c1 ) )
  291.             {
  292.             case ESC:    /* esc: preceeds RS-232C device control instructions */
  293.                 DB (printf ("ESC:\n");)
  294.                 if ( c2 != '.')
  295.                     {
  296.                     print_string ("Unknown escape sequence encountered\n");
  297.                     break;
  298.                     }
  299.                 if (c2 == 'Y' || c2 == 'Z' || c2 == 'B' || c2 == 'E' || c2 == 'J' ||
  300.                      c2 == 'K' || c2 == 'L' || c2 == 'O' || c2 == 'R')
  301.                      {
  302.                      break;    /* these commands take no optional arguments */
  303.                      }
  304.                 if (c2 == '@' || c2 == 'H' || c2 == 'I' || c2 == 'M' || c2 == 'N')
  305.                     {
  306.                     while ( (c2 = getc (infile)) != ':');    /* kill off characters until terminator */
  307.                     break;
  308.                     }
  309.                 break;
  310.             case 'a':    /* aa, ac, ad, ap, ar, at */
  311.                 switch (tolower (c2))
  312.                     {
  313.                     case 'a':    /* absolute arc */
  314.                         abs_arc (infile);
  315.                         break;
  316.                     case 'c':    /* anchor corner */
  317.                         anchor_corn ( infile );
  318.                         break;
  319.                     case 'd':    /* alternate font definition */
  320.                         print_noinstr ("AD");
  321.                         while (get_val (infile, &x));    /* trim off any following values */
  322.                         break;
  323.                     case 'p':    /* automatic pen: NOP */
  324.                         (void) get_val (infile, &x);    /* possibly one trailing value */
  325.                         break;
  326.                     case 'r':    /* relative arc */
  327.                         rel_arc (infile);
  328.                         break;
  329.                     case 't':    /* 3 point arc, absolute */
  330.                         arc_3pt_abs (infile);
  331.                         break;
  332.                     default:    /* illegal instr */
  333.                         error (c1, c2);
  334.                     }
  335.                 break;
  336.             case 'b':    /* bp */
  337.                 if (tolower (c2) != 'p')
  338.                     {
  339.                     error (c1, c2);
  340.                     break;
  341.                     }
  342.                 begin_plot (infile);    /* bp: begin plot */
  343.                 break;
  344.             case 'c':    /* ca, cf, ci, cp, cr, cs, ct */
  345.                 switch (tolower (c2))
  346.                     {
  347.                     case 'a':    /* designate alternative char set */
  348.                         (void) get_val (infile, &x);    /* get any trailing character set value */
  349.                         print_noinstr ("CA");
  350.                         break;
  351.                     case 'f':    /* character fill mode */
  352.                         print_noinstr ("CF");
  353.                         while (get_val (infile, &x));    /* collect trailing values, if any */
  354.                         break;
  355.                     case 'i':    /* circle */
  356.                         circle (infile);
  357.                         break;
  358.                     case 'p':    /* char plot */
  359.                         char_plot (infile);
  360.                         break;
  361.                     case 'r':    /* set color range */
  362.                         while (1)    /* remove any trailing arguments (should be 6) */
  363.                             if (!get_val (infile, &x)) break;
  364.                         print_noinstr ("CR");
  365.                         break;
  366.                     case 's':    /* designate standard char set */
  367.                         (void) get_val (infile, &x);    /* get any trailing argument */
  368.                         print_noinstr ("CS");
  369.                         break;
  370.                     case 't':    /* chord tolerance */
  371.                         chord_t (infile);
  372.                         break;
  373.                     default:
  374.                         error (c1, c2);
  375.                     }
  376.                 break;
  377.             case 'd':    /* dc, df, di, dl, dp, dr, ds, dt, dv */
  378.                 switch (tolower (c2))
  379.                     {
  380.                     case 'c': break;    /* digitize clear: NOP */
  381.                     case 'f': set_defaults ();    /* set default values */
  382.                         break;
  383.                     case 'i': label_adir (infile);    /* get absolute label direction */
  384.                         break;
  385.                     case 'l':    /* download character */
  386.                         while (1)    /* remove any trailing arguments (should be 6) */
  387.                             if (!get_val (infile, &x)) break;
  388.                         print_noinstr ("DL");
  389.                         break;
  390.                     case 'p': break;    /* digitize point: not meaningful here */
  391.                     case 'r': label_rdir (infile);    /* get relative label direction */
  392.                         break;
  393.                     case 's':        /* designate char. set into slot */
  394.                         print_noinstr ("DS");
  395.                         for (i = 0; i < 2; ++i)        /* trim off up to 2 trailing values */
  396.                             if (!get_val (infile, &x)) break;
  397.                         break;
  398.  
  399.                     case 't':        /* define label terminator */
  400.                         label_term (infile);
  401.                         break;
  402.                     case 'v':        /* define variable text path */
  403.                         define_path (infile);
  404.                         break;
  405.                     default:
  406.                         error (c1, c2);
  407.                     }
  408.                 break;
  409.             case 'e':    /* ea, ec, ep, er, es, ew */
  410.                 switch (tolower (c2))
  411.                     {
  412.                     case 'a':    /* edge rectangle absolute */
  413.                         edge_rect_abs (infile);
  414.                         break;
  415.                     case 'c':    /* enable cutter */
  416.                         (void) get_val (infile, &x);    /* trim trailing value */
  417.                         break;
  418.                     case 'p':
  419.                         break;
  420.                     case 'r':
  421.                         edge_rect_rel (infile);
  422.                         break;
  423.                     case 's':    /* extra space */
  424.                         x = 0.0;
  425.                         y = 0.0;
  426.                         get_val (infile, &x);
  427.                         get_val (infile, &y);
  428.                         /* get_val returns x, y values unchanged
  429.                         and file pointer unchanged if file pointer
  430.                         points to non-numeric data */
  431.                         extra_space (x, y);
  432.                         break;
  433.                     case 'w':    /* edge wedge */
  434.                         draw_wedge (infile);
  435.                         break;
  436.                     default:
  437.                         error (c1, c2);
  438.                     }
  439.                 break;
  440.             case 'f':    /* fi, fn, fp, fr, ft */
  441.                 switch (tolower (c2))
  442.                     {
  443.                     case 'i': print_noinstr ("FI");
  444.                         break;
  445.                     case 'n': print_noinstr ("FN");
  446.                         break;
  447.                     case 'p': print_noinstr ("FP");
  448.                         break;
  449.                     case 'r': print_noinstr ("FR");
  450.                         break;
  451.                     case 't': fill_type (infile, scaling);
  452.                         break;
  453.                     default:
  454.                         error (c1, c2);
  455.                     }
  456.                 break;
  457.  
  458.             case 'g':    /* gm (DraftPro instruction: allocate graphics memory */
  459.                 if (tolower (c2) == 'm')
  460.                     {
  461.                     for (i = 0; i < 5; ++i)    /* up to 5 arguments allowed */
  462.                         if (!get_val (infile, &x)) break;
  463.                     }
  464.                 else
  465.                     {
  466.                     error (c1, c2);
  467.                     }
  468.                 break;
  469.  
  470.             case 'i':    /* im, in, ip, ir, iw */
  471.                 switch (tolower (c2))
  472.                     {
  473.                     case 'm':    /* at least 1 arg, and at most 3 args */
  474.                         if ( !get_val (infile, &x)) break;
  475.                         if ( !get_val (infile, &x)) break;
  476.                         if ( !get_val (infile, &x)) break;
  477.                         break;
  478.                     case 'n':
  479.                         initialize (infile);    /* initialize graphics routines */
  480.                         break;
  481.                     case 'p':
  482.                         input_p1p2abs (infile);    /* input p1 & p2 coordinates */
  483.                         break;
  484.                     case 'r':
  485.                         input_p1p2rel (infile);    /* input P1/P2 relative coordinates */
  486.                         break;
  487.                     case 'w':    /* get corner of clipping window */
  488.                         iwindow (infile);
  489.                         break;
  490.                     default: 
  491.                         error (c1, c2);
  492.                         break;
  493.                     }
  494.                 break;
  495.  
  496.             case 'l':    /* la, lb, lo, lt */
  497.                 switch (tolower (c2))
  498.                     {
  499.                     case 'a':    /* line attributes */
  500.                         print_noinstr ("LA");
  501.                         for (i =0; i < 6; ++i)    /* trim off up to 6 trailing values */
  502.                             if (!get_val (infile, &x)) break;
  503.                         break;
  504.                     case 'b':    /* lb instr. */
  505.                         label_graph (infile);
  506.                         break;
  507.                     case 'o':    /* lo instr. */
  508.                         label_origin (infile);
  509.                         break;
  510.                     case 't':    /* lt instr */
  511.                         line_pattern (infile);
  512.                         break;
  513.                     default:
  514.                         error (c1, c2);
  515.                     }
  516.                 break;
  517.  
  518.             case 'm':    /* mc, mg, mt */
  519.                 switch (tolower (c2))
  520.                     {
  521.                     case 'c':    /* merge control */
  522.                         (void) get_val (infile, &x);    /* dump trailing value */
  523.                         break;
  524.                     case 'g':    /* message */
  525.                         ch = getc (infile);
  526.                         while (ch != TERMCHAR && ch != (unsigned char) EOF) ch = getc (infile);
  527.                         break;        /* dump the entire message */
  528.                     case 't':    /* media type: ignored */
  529.                         (void) get_val (infile, &x);
  530.                         break;
  531.                     default:
  532.                         error (c1, c2);
  533.                     }
  534.                 break;
  535.             case 'n':    /* np, nr */
  536.                 switch ( tolower (c2))
  537.                     {
  538.                     case 'p':    /* number of pens */
  539.                         break;
  540.                     case 'r':    /* not ready */
  541.                         twait (infile, -1);    /* read delay value from stream & wait */
  542.                         break;
  543.                     default:
  544.                         error (c1, c2);
  545.                     }
  546.                 break;
  547.             case 'o':    /* oa, oc, od, oe, of, oh, oi, oo, op, os, ow */
  548.                 switch ( tolower (c2))
  549.                     {
  550.                     case 'a':    /* ignore all output instructions */
  551.                     case 'c':
  552.                     case 'd':
  553.                     case 'e':
  554.                     case 'f':
  555.                     case 'h':
  556.                     case 'i':
  557.                     case 'o':
  558.                     case 'p':
  559.                     case 's':
  560.                     case 'w': break;
  561.                     default:
  562.                         error (c1, c2);
  563.                     }
  564.                 break;
  565.  
  566.             case 'p':    /* pa, pc, pd, pe, pg, pm, pr, ps, pu, pw */
  567.                 switch ( tolower ( c2 ) )
  568.                     {
  569.                     case 'a':
  570.                         plot_abs (infile);
  571.                         break;
  572.                     case 'c':
  573.                         print_noinstr ("PC");
  574.                         for (i =0; i < 4; ++i)    /* trim off up to 4 trailing values */
  575.                             if (!get_val (infile, &x)) break;
  576.                         break;
  577.                     case 'd':     /* keep track of pen status here */
  578.                         pen_down (infile);
  579.                         break;
  580.                     case 'e':
  581.                         print_noinstr ("PE");
  582.                         break;
  583.                     case 'g':    /* page advance */
  584.                         page_adv (infile);
  585.                         new_plot ();    /* new plot: not plotted on...yet */
  586.                         break;
  587.                     case 'm':    /* polygon mode */
  588.                         print_noinstr ("PM");
  589.                         get_val (infile, &x);
  590.                         break;
  591.                     case 'r':
  592.                         plot_rel (infile);
  593.                         break;
  594.                     case 's':    /* plot_size */
  595.                         plot_size (infile, plotter);
  596.                         break;
  597.                     case 'u': penup ();        /* raise pen */
  598.                         pen_up (infile);
  599.                         break;
  600.                     case 'w':        /* pen width */
  601.                         print_noinstr ("PW");
  602.                         for (i = 0; i < 2; ++i)    /* trim off up to 2 trailing values */
  603.                             if (!get_val (infile, &x)) break;
  604.                         break;
  605.                     default:
  606.                         error (c1, c2);
  607.                         break;
  608.                     }
  609.                 break;
  610.             case 'q':
  611.                 DB (printf ("case 'q', c2 = %c\n", c2);)
  612.                 if (tolower (c2) == 'l')    /* ql: quality level. NOP */
  613.                     {
  614.                     (void) get_val (infile, &x);    /* dump any trailing value */
  615.                     break;
  616.                     }
  617.                 error (c1, c2);    /* unknown instruction */
  618.                 break;
  619.             case 'r':
  620.                 switch ( tolower (c2) )
  621.                     {
  622.                     case 'a':    /* filled rectangle, absolute */
  623.                         filled_rect_abs (infile);
  624.                         break;
  625.                     case 'f':    /* raster fill definition */
  626.                         print_noinstr ("RF");
  627.                         while (get_val (infile, &x));    /* dump all trailing values */
  628.                         break;
  629.                     case 'o':    /* rotate origin */
  630.                         print_noinstr ("RO");
  631.                         get_val (infile, &x);    /* dump trailing angle value (if any) */
  632.                         break;
  633.                     case 'p':    /* replot */
  634.                         get_val (infile, &x);    /* dump any trailing value */
  635.                         break;
  636.                     case 'r':    /* filled rectangle, relative */
  637.                         filled_rect_rel (infile);
  638.                         break;
  639.                     case 't':    /* edge 3-pt arc, relative */
  640.                         arc_3pt_rel (infile);
  641.                         break;
  642.                     default:
  643.                         error (c1, c2);    /* illegal instr */
  644.                         break;
  645.                     }
  646.                 break;
  647.             case 's':    /* sb, sp, sc, sd, si, sl, sm, sp, sr, ss, st, sv */
  648.                 switch ( tolower (c2) )
  649.                     {
  650.                     case 'a':    /* select alternate font */
  651.                         print_noinstr ("SA");
  652.                         break;
  653.                     case 'b':    /* scalable or bitmap fonts */
  654.                         print_noinstr ("SB");
  655.                         break;
  656.                     case 'c':
  657.                         scale (infile);        /* set scale parameters */
  658.                         break;
  659.                     case 'd':    /* standard font definition */
  660.                         print_noinstr ("SD");
  661.                         break;
  662.                     case 'i': /* char size (absolute) */
  663.                         set_acsize (infile);    /* set char size (in cm) */
  664.                         break;
  665.                     case 'l':    /* char slant */
  666.                         set_slant (infile);
  667.                         break;
  668.                     case 'm':    /* symbol mode */
  669.                         c2 = getc (infile);    /* get next symbol */
  670.                         DB (printf ("SM: symbol char = %c (0x%02X)\n", c2, c2);)
  671.                         if (c2 == TERMCHAR || c2 == ' ' || iscntrl (c2) || (c2 > 126 && (c2 != 161 || c2 != 254)))
  672.                             {
  673.                             symbol_mode = 0;    /* symbol mode off */
  674.                             break;
  675.                             }
  676.                         symbol = c2;
  677.                         symbol_mode = 1;    /* turn symbol mode on */
  678.                         DB (printf ("symbol mode on\n");)
  679.                         break;
  680.                     case 'p':
  681.                         select_pen (infile, max_pens);
  682.                         break;
  683.                     case 'r': /* char size (relative) */
  684.                         set_rcsize (infile);    /* set relative csize */
  685.                         break;
  686.                     case 's':    /* select standard font */
  687.                         print_noinstr ("SS");
  688.                         break;
  689.                     case 't':    /* sort vectors: NOP */
  690.                         (void) get_val (infile, &x);    /* possibly get one parameter */
  691.                         break;
  692.                     case 'v':    /* screened vectors */
  693.                         while (1)    /* trim off up to 3 trailing values */
  694.                             (void) get_val (infile, &x);
  695.                         print_noinstr ("SV");
  696.                         break;
  697.                     default:
  698.                         error (c1, c2);
  699.                         break;
  700.                     }
  701.                 break;    /* end of case 's' switch */
  702.             case 't':    /* td, tl, tr */
  703.                 switch (tolower (c2))
  704.                     {
  705.                     case 'd':
  706.                         print_noinstr ("TD");
  707.                         break;
  708.                     case 'l':
  709.                         tick_length (infile);
  710.                         break;
  711.                     case 'r':
  712.                         print_noinstr ("TR");
  713.                         break;
  714.                     default:
  715.                         error (c1, c2);
  716.                         break;
  717.                     }
  718.                 break;
  719.             case 'u':    /* ul */
  720.                 if (tolower (c2) != 'l')
  721.                     {
  722.                     error (c1, c2);
  723.                     break;
  724.                     }
  725.                 print_noinstr ("UL");
  726.                 break;
  727.             case 'v':    /* vs: not needed for CRT */
  728.                 if (tolower (c2) != 's')
  729.                     {
  730.                     error (c1, c2);
  731.                     break;
  732.                     }
  733.                 velocity_sel (infile);
  734.                 break;
  735.             case 'w':    /* wg, wu */
  736.                 switch (tolower (c2))
  737.                     {
  738.                     case 'g':    /* wg: filled wedge */
  739.                         draw_wedge (infile);    /* outline wedge: no filled wedge available */
  740.                         break;
  741.                     case 'u':    /* pen width: not implimented */
  742.                         (void) get_val (infile, &x);    /* dump value assoc. with instr */
  743.                         print_noinstr ("WU");
  744.                         break;
  745.                     default: error (c1, c2);
  746.                     }
  747.                 break;
  748.             case 'x':    /* xt */
  749.                 if (tolower (c2) != 't')
  750.                     {
  751.                     error (c1, c2);
  752.                     break;
  753.                     }
  754.                 draw_xtick ();
  755.                 break;
  756.             case 'y':    /* yt */
  757.                 if (tolower (c2) != 't')
  758.                     {
  759.                     error (c1, c2);
  760.                     break;
  761.                     }
  762.                 draw_ytick ();
  763.                 break;
  764.             default:
  765.                 ungetc (c2, infile);    /* in case if trailing trash */
  766.                 break;
  767.             }
  768.         if (error_flag) ungetc (c2, infile);    /* in case of illegal instruction */
  769.         }
  770.     fclose (infile);
  771.     }
  772.  
  773. /*--------------------------------------*/
  774.  
  775. void initialize (FILE * infile)    /* graphics setup routine */
  776.     {
  777.     double t;    /* trash variable */
  778.  
  779.     DB (printf ("IN:  initializing: window set for HP7470A\n");)
  780.  
  781.     (void) get_val (infile, &t);    /* check for value (unused) for HPGL/2 compatibility */
  782.     cold_start ();
  783.     return;
  784.     }
  785.  
  786. /*--------------------------------------*/
  787.  
  788. static void cold_start ( void )    /* plotter initialization routine */
  789.     {
  790.     double x;
  791.  
  792.     default_coords ();        /* set default coordinates for plotter */
  793.     set_aspect_ratio ();        /* activate new hard clip limits */
  794.     x_mirror = y_mirror = 0;    /* clear char mirroring flags */
  795.  
  796.     p_status = PENUP;
  797.     set_defaults ();        /* set default plotter conditions */
  798.     move (p1x, p1y);        /* move to P1 corner of "hard" clip */
  799.     set_anchor (p1x, p1y);        /* anchor corner for fill types */
  800.  
  801.     init_fills ();            /* clear previous fill-codes */
  802.  
  803.     new_plot ();            /* this plot has not been drawn on, yet */
  804.     return;
  805.     }
  806.  
  807. /*--------------------------------------*/
  808.  
  809. static void set_defaults ( void )
  810.     {
  811.  
  812.     symbol_mode = OFF;        /* symbol mode is off */
  813.     i_window = OFF;            /* input window is off */
  814.     plotmode = PA;            /* absolute plotting */
  815.     ldir (0);
  816.     cdir (0);            /* reset label direction to horizontal */
  817.     cp.dv = 0;            /* update stacking direction code to default direction */
  818.     cp.dvdir = 0.0;            /* update stacking direction angle (degrees) */
  819.     cp.ldir = 0.0;            /* update label direction vector (degrees) */
  820.     line_type (0, 0);
  821.     cs.cscale_mode = 1;        /* select relative char size scaling */
  822.     cs.slant = 0.0;            /* no char. slant */
  823.     chord_type = ANG;        /* select chords in angle units */
  824.     scaling = OFF;            /* scaling is off */
  825.  
  826.     /* set default character size & size in current plotter units */
  827.     cs.rcsize_x = 0.75;
  828.     cs.rcsize_y = 1.50;    /* character width (x) and height (y) in % of page sizes in X & Y directions */
  829.  
  830.     /* set char size */
  831.     calc_csize (cs.rcsize_x, cs.rcsize_y, cs.cscale_mode );
  832.  
  833.     calc_ticksize (DEF_TICK, DEF_TICK);    /* set default tick size */
  834.  
  835.     extra_space (0.0, 0.0);        /* turn off extra spacing in char strings */
  836.  
  837.     /* ******** NOTE ********* */
  838.     /* HPGL/2 defaults to the maximum hard clip limits after IN; or IP; */
  839.  
  840.  
  841.     /* turn off scaling */
  842.     set_window (p1x, p2x, p1y, p2y);
  843.         /* only set window this way from power-on or IN */
  844.  
  845.  
  846.     endlabel = ETX;
  847.     chord_angle = DEF_CHORD;    /* chord angle default */
  848.     DB (printf ("default parameters now set\n");)
  849.  
  850.     return;
  851.     }
  852.  
  853. /*--------------------------------------*/
  854.  
  855. static void default_coords ( void )
  856.     {
  857.  
  858.     /* Initialize sets the default viewport  */
  859.     p1x = ip1x;
  860.     p1y = ip1y;
  861.     p2x = ip2x;
  862.     p2y = ip2y;    /* default corner positions */
  863.  
  864.     return;
  865.     }
  866.  
  867. /*--------------------------------------*/
  868.  
  869. static void set_aspect_ratio ( void )
  870.     {
  871.     double xmax, ymax;
  872.  
  873.     DB (printf ("setting aspect ratio\n");)
  874.     if (X_mm / Y_mm > ipxsize / ipysize)    /* is screen aspect ratio > aspect ratio of paper? */
  875.         {    /* adjust limit () for correct aspect ratio */
  876.         ymax = Y_mm;        /* ymax = y screen size */
  877.         xmax = Y_mm * (ipxsize / ipysize);    /* xmax = x screen size */
  878.         gdu_cm = 1000.0 / Y_mm;            /* GDU's/cm:  100 * 10 mm / cm's */
  879.         }
  880.     else    /* aspect ratio < 11:8.5 */
  881.         {
  882.         xmax = X_mm;        /* xmax = x screen size */
  883.         ymax = X_mm / (ipxsize / ipysize);    /* ymax = y screen size */
  884.         gdu_cm = 1000.0 / X_mm;            /* GDU's/cm:  100 * 10 mm / cm's */
  885.         }
  886.  
  887.     /* set hard clip limits for correct aspect ratio */
  888.  
  889.     DB (printf ("xmax = %lf, ymax = %lf\n", xmax, ymax);)
  890.  
  891.     limit (0.0, xmax, 0.0, ymax);
  892.  
  893.     clip_xmin = p1x;
  894.     clip_xmax = p2x;
  895.     clip_ymin = p1y;
  896.     clip_ymax = p2y;    /* save clip border for IW instr. with scaling OFF */
  897.  
  898.  
  899.     return;
  900.     }
  901.  
  902. /*--------------------------------------*/
  903.  
  904. static void iwindow (FILE *infile)
  905.     {
  906.     double x_1, x_2, y_1, y_2;
  907.  
  908.     if ( !get_val (infile, &x_1) )    /* no argument */
  909.         {
  910.         DB (printf ("IW; Clipping off\n");)
  911.         i_window = OFF;
  912.         if (scaling == ON)    /* clip border depends on scaling */
  913.             clip (uux1, uux2, uuy1, uuy2);
  914.         else
  915.             clip (clip_xmin, clip_xmax, clip_ymin, clip_ymax);
  916.         return;
  917.         }
  918.     if ( !get_val (infile, &y_1) )
  919.         {
  920.         print_string ("Error: expecting y1 from IW instruction\n");
  921.         return;
  922.         }
  923.     if ( !get_xy (infile, &x_2, &y_2) )
  924.         {
  925.         print_string ("IW:  missing x2 or y2 argument\n");
  926.         return;
  927.         }
  928.  
  929.     if (x_1 == x_2 || y_1 == y_2)
  930.         {
  931.         print_string ("Error: zero range in X or Y in SC instruction\n");
  932.         return;
  933.         }
  934.  
  935.     iwx1 = x_1;
  936.     iwx2 = x_2;
  937.     iwy1 = y_1;
  938.     iwy2 = y_2;    /* save clipping window values  */
  939.  
  940.     i_window = ON;
  941.     clip (x_1, x_2, y_1, y_2);    /* turn on clipping */
  942.     return;
  943.  
  944.     }
  945.  
  946. /*--------------------------------------*/
  947.  
  948. static void scale (FILE *infile)
  949.     {
  950.  
  951.     DB (printf ("SC\n");)
  952.     if ( !get_val (infile, &x_1) )    /* no argument */
  953.         {
  954.         DB (printf ("SC; scaling off\n");)
  955.         /* turn off scaling: revert to default units */
  956.         scaling = OFF;
  957.         set_window (p1x, p2x, p1y, p2y);    /* scaling is now in plotter units */
  958.         return;        /* anchor and hatch codes are already in plotter units */
  959.                 /* no reason for special routines to "freeze" them */
  960.         }
  961.     if ( !get_val (infile, &x_2) )
  962.         {
  963.         print_string ("Error: expecting x_2 from SC instruction\n");
  964.         return;
  965.         }
  966.     if ( !get_xy (infile, &y_1, &y_2) )
  967.         {
  968.         print_string ("SC: missing y1 or y2 argument\n");
  969.         return;
  970.         }
  971.     if ( !get_val (infile, &type) )
  972.         {
  973.         if (x_1 == x_2 || y_1 == y_2)
  974.             {
  975.             print_string ("Error: zero range in X or Y in SC instruction\n");
  976.             return;
  977.             }
  978.         DB (printf ("SC: (x1,y1) = (%lf, %lf), (x2,y2) = (%lf, %lf)\n", x_1, y_1, x_2, y_2);)
  979.         scaling = ON;
  980.  
  981.         uux1 = x_1;
  982.         uux2 = x_2;
  983.         uuy1 = y_1;
  984.         uuy2 = y_2;    /* save user scaling values */
  985.  
  986.         set_window (x_1, x_2, y_1, y_2);    /* no type: assume type 0 (anisotropic) */
  987.         scale_type = ANISOTROPIC;        /* remember type of scaling */
  988.         fix_anchor ();    /* move anchor corner (plotter units) for new scale */
  989.         fix_hatch ();    /* change size of hatch (in plotter units) for new scale */
  990.         return;
  991.         }
  992.     else
  993.         {    /* have a scale type: check for anchor parameters */
  994.         if ( !get_val (infile, &x) )    /* get x-anchor (%) */
  995.             {
  996.             if (type == 0.0)    /* anisotropic scaling */
  997.                 {
  998.                 DB (printf ("SC: type 0: (x1,y1) = (%lf, %lf), (x2,y2) = (%lf, %lf)\n", x_1, y_1, x_2, y_2);)
  999.  
  1000.                 uux1 = x_1;
  1001.                 uux2 = x_2;
  1002.                 uuy1 = y_1;
  1003.                 uuy2 = y_2;    /* save user scaling values */
  1004.  
  1005.                 scaling = ON;
  1006.                 set_window (x_1, x_2, y_1, y_2);
  1007.                 scale_type = ANISOTROPIC;        /* remember type of scaling */
  1008.                 fix_anchor ();    /* move anchor corner (plotter units) for new scale */
  1009.                 fix_hatch ();    /* change size of hatch (in plotter units) for new scale */
  1010.                 }
  1011.             else
  1012.                 if (type == 1.0)    /* isotropic scaling */
  1013.                     {
  1014.  
  1015.                     uux1 = x_1;
  1016.                     uux2 = x_2;
  1017.                     uuy1 = y_1;
  1018.                     uuy2 = y_2;    /* save user scaling values */
  1019.  
  1020.                     scaling = ON;
  1021.                     scale_type = ISOTROPIC;        /* remember type of scaling */
  1022.                     set_show (x_1, x_2, y_1, y_2);
  1023.                     fix_anchor ();    /* move anchor corner (plotter units) for new scale */
  1024.                     fix_hatch ();    /* change size of hatch (in plotter units) for new scale */
  1025.                     }
  1026.                 else if (type == 2.0)    /* point & factor scaling */
  1027.                     {
  1028.                     if (x_2 == 0.0 || y_2 == 0.0)
  1029.                         {
  1030.                         print_string ("Error: x-factor or y-factor in type-2 SC instruction is zero\n");
  1031.                         return;
  1032.                         }
  1033.                     /* convert from scaling factor to P2 coordinate for window function */
  1034.                     x_2 = x_1 + (p2x - p1x) / x_2;
  1035.                     y_2 = y_1 + (p2y - p1y) / y_2;
  1036.                     DB (printf ("SC: type 2: (x1,y1) = (%lf, %lf), (x2,y2) = (%lf, %lf)\n", x_1, y_1, x_2, y_2);)
  1037.  
  1038.                     uux1 = x_1;
  1039.                     uux2 = x_2;
  1040.                     uuy1 = y_1;
  1041.                     uuy2 = y_2;    /* save user scaling values */
  1042.  
  1043.                     scaling = ON;
  1044.                     scale_type = ANISOTROPIC;        /* remember type of scaling */
  1045.                     set_window (x_1, x_2, y_1, y_2);
  1046.                     fix_anchor ();    /* move anchor corner (plotter units) for new scale */
  1047.                     fix_hatch ();    /* change size of hatch (in plotter units) for new scale */
  1048.                     }
  1049.             return;
  1050.             }
  1051.         if ( !get_val (infile, &y) )
  1052.             {
  1053.             print_string ("Error: expecting bottom argument from SC instruction\n");
  1054.             return;
  1055.             }
  1056.         if (type != 1.0)
  1057.             {
  1058.             printf ("Error: illegal arguments to type %1.1d SC instruction\n", (int) type);
  1059.             return;
  1060.             }
  1061.         }
  1062.     /* we have a type 1 SC instruction with left and bottom param's */
  1063.     /* x, y = anchor parameters (left, bottom, resp.) */
  1064.     DB (printf ("SC: type 1: (x1,y1) = (%lf, %lf), (x2,y2) = (%lf, %lf)\n", x_1, y_1, x_2, y_2);)
  1065.     print_string ("SC: left and bottom parameters not yet implimented\n");
  1066.     return;
  1067.     }
  1068.  
  1069. /*--------------------------------------*/
  1070.  
  1071. static void select_pen (FILE * infile, int max_pens)
  1072.     {
  1073.  
  1074.     if ( !get_val ( infile, &x ))
  1075.         p = 0;
  1076.     else    /* pen value: must limit to valid ranges */
  1077.         p =  MAX ( MIN ( (int) x, max_pens), 0);
  1078.     pen ( pen_map[p] );
  1079.     DB (printf ("SP: %d, internal pen = %d\n", p, pen_map[p]);)
  1080.  
  1081.     return;
  1082.     }
  1083.  
  1084. /*--------------------------------------*/
  1085.  
  1086. static void plot_line (FILE *infile, int type)    /* type 1 => relative; type 0 => absolute */
  1087.     {
  1088.     double xp, yp, x_1, y_1;    /* local variables */
  1089.  
  1090.     DB (if (type) printf ("PR\n"); else printf ("PA\n");)
  1091.     if (get_val (infile, &xp))    /* get x values */
  1092.          {
  1093.         if ( !get_val (infile, &yp))    /* get y value */
  1094.             {
  1095.             if (type)
  1096.                 print_string ("PR: missing value\n");
  1097.             else
  1098.                 print_string ("PA: missing value\n");
  1099.             return;
  1100.             }
  1101.         DB (printf ("%s: (%lf, %lf), pen status = %d;\n", (type) ? "PR" : "PA", xp, yp, p_status);)
  1102.  
  1103.         plotmode = (type) ? PR : PA;
  1104.         plotted_on (1);        /* we drew something on this plot */
  1105.         do
  1106.             {
  1107.             if (type)    /* relative plotting */
  1108.                 {
  1109.                 where (&x_1, &y_1);        /* get current position */
  1110.                 DB (printf ("PR: current location: (%lf, %lf)\n", x_1, y_1);)
  1111.                 xp += x_1;
  1112.                 yp += y_1;            /* relative position */
  1113.                 }
  1114.             if (!p_status == PENDOWN)
  1115.                 move (xp, yp);
  1116.             else
  1117.                 draw (xp, yp);        /* actual drawing depends on pen being up or down */
  1118.  
  1119.             where (&x_1, &y_1);        /* get current position */
  1120.             DB (printf ("now at: (%lf, %lf)\n", x_1, y_1);)
  1121.  
  1122.             cp.x = x_1;
  1123.             cp.y = y_1;    /* update (x,y) for char plot fn. */
  1124.  
  1125.             if (symbol_mode)
  1126.                 {
  1127.                 symbol_mark (symbol);
  1128.                 move (xp, yp);
  1129.                 }
  1130.             }
  1131.         while (get_xy (infile, &xp,&yp));
  1132.         return;
  1133.         }
  1134.     plotmode = (type) ? PR : PA;
  1135.     DB (if (type) printf ("PR: plotting mode:  relative\n"); else
  1136.         printf ("PA: plotting mode:  absolute\n");)
  1137.     return;
  1138.     }
  1139.  
  1140. /*--------------------------------------*/
  1141.  
  1142. static void pen_down (FILE *infile)
  1143.     {
  1144.     double xp, yp, x_1, y_1;    /* local variables */
  1145.  
  1146.     DB (printf ("PD\n");)
  1147.     p_status = PENDOWN;        /* pen is down */
  1148.     if (get_val (infile, &xp))    /* get x values */
  1149.          {
  1150.         if ( !get_val (infile, &yp))    /* get y value */
  1151.             {
  1152.             print_string ("PD: missing y-value\n");
  1153.             return;
  1154.             }
  1155.         plotted_on (1);        /* we drew something on this plot */
  1156.         do
  1157.             {
  1158.             DB (printf ("PD: plot to (%lf, %lf)\n", xp, yp);)
  1159.             if (plotmode == PR)
  1160.                 {
  1161.                 where (&x_1, &y_1);
  1162.                 DB (printf ("PD: current location: (%lf, %lf)\n", x_1, y_1);)
  1163.                 xp += x_1;
  1164.                 yp += y_1;    /* new position relative to last */
  1165.                 }
  1166.             draw (xp, yp);
  1167.  
  1168.             cp.x = xp;
  1169.             cp.y = yp;    /* update (x,y) for char plot fn. */
  1170.  
  1171.             if (symbol_mode)
  1172.                 {
  1173.                 symbol_mark (symbol);
  1174.                 move (xp, yp);
  1175.                 }
  1176.             }
  1177.         while (get_xy (infile, &xp, &yp));
  1178.         }
  1179.     return;
  1180.     }
  1181.  
  1182. /*--------------------------------------*/
  1183.  
  1184. static void pen_up (FILE *infile)
  1185.     {
  1186.     double xp, yp, x_1, y_1;    /* local variables */
  1187.  
  1188.     DB (printf ("PU\n");)
  1189.     p_status = PENUP;
  1190.     if (get_val (infile, &xp))    /* get x values */
  1191.          {
  1192.         if ( !get_val (infile, &yp))    /* get y value */
  1193.             {
  1194.             print_string ("PU: missing y-value\n");
  1195.             return;
  1196.             }
  1197.         do
  1198.             {
  1199.             DB (printf ("PU: (x,y) = (%lf, %lf)\n", xp, yp);)
  1200.             if (plotmode == PR)
  1201.                 {
  1202.                 where (&x_1, &y_1);    /* current location */
  1203.                 DB (printf ("PU: current location: (%lf, %lf)\n", x_1, y_1);)
  1204.                 xp += x_1;
  1205.                 yp += y_1;
  1206.                 }
  1207.             move (xp, yp);
  1208.  
  1209.             cp.x = xp;
  1210.             cp.y = yp;    /* update (x,y) for char plot fn. */
  1211.  
  1212.             if (symbol_mode)
  1213.                 {
  1214.                 symbol_mark (symbol);
  1215.                 move (xp, yp);
  1216.                 }
  1217.             DB (printf ("PU: move to (%lf, %lf)\n", xp, yp);)
  1218.             }
  1219.         while (get_xy (infile, &xp, &yp));
  1220.         }
  1221.     return;
  1222.     }
  1223.  
  1224. /*--------------------------------------*/
  1225.  
  1226. static void input_p1p2 (FILE *infile, int type)
  1227.     {        /* type = 0 -> absolute coordinates, type = 1 -> relative coordinates */
  1228.     double old_p1x, old_p1y, x_1, y_1, x_2, y_2;
  1229.  
  1230.     DB ( if (type) printf ("IR\n"); else printf ("IP\n");)
  1231.     old_p1x = p1x;
  1232.     old_p1y = p1y;        /* save for use in case of only P1 specified */
  1233.     if ( !get_val (infile, &x_1))    /* no arguments: use default sizes */
  1234.          {
  1235.         default_coords ();    /* no arguments: use default corner positions */
  1236.  
  1237.         set_aspect_ratio ();
  1238.  
  1239.         set_window (p1x, p2x, p1y, p2y);    /* scale current window */
  1240.         y_mirror = x_mirror = 0;    /* char mirroring flags */
  1241.  
  1242.         if (cs.cscale_mode) calc_csize (cs.rcsize_x, cs.rcsize_y, cs.cscale_mode);
  1243.         /* rescale char size if relative scaling is in effect */
  1244.  
  1245.         return;
  1246.         }
  1247.     else
  1248.         {
  1249.         if ( !get_val (infile, &y_1))    /* get y value */
  1250.             {
  1251.             return;    /* error: no p1y coordinate */
  1252.             }
  1253.         DB (printf ("IP:  P1 = (%lf, %lf)\n", x_1, y_1);)
  1254.         }
  1255.  
  1256.     if (get_val (infile, &x_2))
  1257.          {
  1258.         if (!get_val (infile, &y_2))
  1259.             {
  1260.             if (type)
  1261.                 printf ("IR: missing P2 y-value\n");
  1262.             else
  1263.                 print_string ("IP: missing P2 y-value\n");
  1264.             return;
  1265.             }
  1266.         if (type)    /* IR */
  1267.             {    /* set P1/P1 as a percentage of the hardclip limits */
  1268.             p1x = x_1 * (ipxmax - ipxmin) / 100.0 + ipxmin;
  1269.             p1y = y_1 * (ipymax - ipymin) / 100.0 + ipymin;
  1270.             p2x = x_2 * (ipxmax - ipxmin) / 100.0 + ipxmin;
  1271.             p2x = y_2 * (ipymax - ipymin) / 100.0 + ipymin;
  1272.             }
  1273.         else
  1274.             {
  1275.             p1x = x_1;
  1276.             p1y = y_1;
  1277.             p2x = x_2;
  1278.             p2y = y_2;
  1279.             }
  1280.         DB (if (type) printf ("IR:  P2 = (%lf, %lf)\n", x_2, y_2);
  1281.             else printf ("IP: P2 = (%lf,%lf)\n", x_2, y_2);)
  1282.         y_mirror = x_mirror = 0;    /* char mirroring flags */
  1283.         if (p2x - p1x < 0) x_mirror = 1;
  1284.         if (p2y - p1y < 0) y_mirror = 1;
  1285.  
  1286.         set_aspect_ratio ();
  1287.  
  1288.         set_window (p1x, p2x, p1y, p2y);
  1289.  
  1290.         if (cs.cscale_mode) calc_csize (cs.rcsize_x, cs.rcsize_y, cs.cscale_mode);
  1291.         /* rescale char size if relative scaling is in effect */
  1292.  
  1293.         return;
  1294.         }
  1295.     /* only P1 specified */
  1296.     if (type)    /* IR */
  1297.         {    /* P1 specified as a percent of hardclip size */
  1298.         p1x = x_1 * (ipxmax - ipxmin) / 100.0 + ipxmin;
  1299.         p1y = y_1 * (ipymax - ipymin) / 100.0 + ipymin;
  1300.         }
  1301.     else        /* IP */
  1302.         {
  1303.         p1x = x_1;
  1304.         p1y = y_1;
  1305.         }
  1306.     p2x += (p1x - old_p1x);
  1307.     p2y += (p1y - old_p1y);    /* adjusted P2 s/t distance between P1 & P2 is constant */
  1308.  
  1309.     set_aspect_ratio ();
  1310.  
  1311.     set_window (p1x, p2x, p1y, p2y);
  1312.     y_mirror = x_mirror = 0;    /* char mirroring flags */
  1313.     if (p2x - p1x < 0) x_mirror = 1;
  1314.     if (p2y - p1y < 0) y_mirror = 1;
  1315.  
  1316.     if (cs.cscale_mode) calc_csize (cs.rcsize_x, cs.rcsize_y, cs.cscale_mode);
  1317.     /* rescale char size if relative scaling is in effect */
  1318.  
  1319.     return;
  1320.     }
  1321.  
  1322. /*--------------------------------------*/
  1323.  
  1324. void set_scale (double x1, double x2, double y1, double y2, int type)
  1325.     {    /* type = 0 -> anisotropic scaling; type = 1 -> isotropic scaling */
  1326.     double dipx, dipy, dpx, dpy, dux, duy, xt, yt, xp1, xp2, yp1, yp2;
  1327.     double xo, yo;
  1328.  
  1329.     /* new scaling program.  Does not change hardclip limits.  Only changes
  1330.     soft clip window.  Rescales parameters s/t user may specify hard clip
  1331.     areas larger than the plotting medium (sheet size), scale those areas,
  1332.     and display only those areas which fall within the size of the plotting 
  1333.     medium */
  1334.  
  1335.     dpx = ipxmax - ipxmin;
  1336.     dpy = ipymax - ipymin;    /* delta P1/P2 (x,y) for full sheet */
  1337.     dipx = p2x - p1x;
  1338.     dipy = p2y - p1y;    /* delta P1/P2 (x,y) for user P1/P2 */
  1339.  
  1340.     if (dipx == 0.0) dipx = 1.0;    /* force minimum size plotting area */
  1341.     if (dipy == 0.0) dipy = 1.0;
  1342.  
  1343.     dux = x2 - x1;
  1344.     duy = y2 - y1;        /* size of user scaled area */
  1345.  
  1346.     xt = dpx * dux / dipx;        /* total # of x user units in hard clip window */
  1347.     xo = (p1x - ipxmin) * dux / dipx;    /* user units x-offset to start of hard clip window */
  1348.     xp1 = x1 - xo;            /* new user unit xmin */
  1349.     xp2 = xp1 + xt;            /* new user unit xmax */
  1350.  
  1351.     yt = dpy * duy / dipy;        /* total # of y user units in hard clip window */
  1352.     yo = (p1y - ipymin) * duy / dipy;    /* user unit y-offset to start of hard clip window */
  1353.     yp1 = y1 - yo;            /* new user unit ymin */
  1354.     yp2 = yp1 + yt;            /* new user unit ymax */
  1355.  
  1356.     uu_2_pux = xt / dipx;    /* user units per plotter unit */
  1357.     uu_2_puy = yt / dipy;    /* note that this fails when isotropic scaling is used */
  1358.  
  1359.     DB (printf ("set_window: xt = %lf, yt = %lf\n", xt, yt);)
  1360.     DB (printf ("set_window: (xp1,yp1) = (%lf, %lfl), (xp2, yp2) = (%lf, %lf)\n", xp1, yp1, xp2, yp2);)
  1361.  
  1362.     if (type)
  1363.         show (xp1, xp2, yp1, yp2);    /* call the real isotropic scaling function */
  1364.     else
  1365.         window (xp1, xp2, yp1, yp2);    /* call the real anisotropic scaling function */
  1366.     if (i_window == ON)
  1367.         clip (iwx1, iwx2, iwy1, iwy2);
  1368.     else
  1369.         clip (x1, x2, y1, y2);
  1370.     return;
  1371.  
  1372.     }
  1373.  
  1374. /*--------------------------------------*/
  1375.  
  1376. static void error (char c1, char c2)
  1377.     {
  1378.  
  1379.     fprintf (stderr, "%c%c -- invalid HPGL command\n", c1, c2);
  1380.  
  1381.     error_flag = 1;
  1382.  
  1383.     return;
  1384.     }
  1385.  
  1386. /*--------------------------------------*/
  1387.  
  1388. static void anchor_corn (FILE *infile)
  1389.     {
  1390.     double x_1, y_1;
  1391.  
  1392.     x_1 = y_1 = 0.0;    /* default to plotter origin if no values present */
  1393.     get_xy (infile, &x_1, &y_1);    /* x_1, y_1 unchanged if no values present */
  1394.     set_anchor (x_1, y_1);
  1395.  
  1396.     return;
  1397.     }
  1398.  
  1399. /*--------------------------------------*/
  1400.  
  1401. static void fix_anchor ( void )
  1402.     {
  1403.  
  1404.     if (anchor.mode == USERUNITS)
  1405.         {
  1406.         anchor.px = anchor.x;
  1407.         anchor.py = anchor.y;
  1408.         plotter_units (&anchor.px, &anchor.py);
  1409.         }    /* change anchor corner plotter units to reflect new scale */
  1410.     return;
  1411.     }
  1412.  
  1413. /*--------------------------------------*/
  1414.  
  1415. void get_anchor (double *x, double *y)
  1416.     {
  1417.  
  1418.     *x = anchor.px;        /* return anchor corner in plotter units */
  1419.     *y = anchor.py;
  1420.     return;
  1421.     }
  1422.  
  1423. /*--------------------------------------*/
  1424.  
  1425. static void set_anchor (double x, double y)
  1426.     {
  1427.  
  1428.     anchor.px = anchor.x = x;    /* set both user and plotter units same */
  1429.     anchor.py = anchor.y = y;
  1430.     anchor.mode = PLOTTERUNITS;
  1431.     if (scaling == ON)    /* anchor corner is in user units */
  1432.         {
  1433.         anchor.mode = USERUNITS;
  1434.         plotter_units (&anchor.px, &anchor.py);
  1435.         }    /* get anchor corner in plotter units */
  1436.     return;
  1437.     }
  1438.  
  1439. /*--------------------------------------*/
  1440.  
  1441. void plotter_units ( double *x, double *y)
  1442.     {
  1443.     double xp, yp;
  1444.  
  1445.     if (scaling == OFF)
  1446.         return;    /* no changes */
  1447.     where (&xp, &yp);    /* remember where we are */
  1448.     move (*x, *y);        /* move to (x,y) */
  1449.     set_window (p1x, p2x, p1y, p2y);
  1450.     where (x, y);        /* get plotter units of where we are */
  1451.     if (scale_type == ISOTROPIC)
  1452.         set_show (uux1, uux2, uuy1, uuy2);
  1453.     else
  1454.         set_window (uux1, uux2, uuy1, uuy2);
  1455.     move (xp, yp);    /* return to former position */
  1456.     return;
  1457.     }
  1458.  
  1459. /*--------------------------------------*/
  1460.  
  1461. void twait (FILE *infile, int delay)
  1462.     {
  1463.     time_t t1, t2, t3;
  1464.     double v1;
  1465.  
  1466.     if (delay < 0)
  1467.         {
  1468.         if ( !get_val (infile, &v1)) return;    /* zero delay */
  1469.         t3 = (time_t) v1;
  1470.         }
  1471.     else
  1472.         t3 = (time_t) delay;
  1473.     time (&t1);
  1474.     time (&t2);
  1475.     while (difftime (t2, t1) < t3) time (&t2);    /* delay */
  1476.  
  1477.     return;
  1478.     }
  1479.  
  1480. /*--------------------------------------*/
  1481.  
  1482. static void plot_size (FILE * infile, int plotter)
  1483.     {
  1484.     double x, y;
  1485.  
  1486.     if (!get_val (infile, &x))
  1487.         {
  1488.         if ( plotted_on (0) ) return;    /* can't change plot size in middle of plotting */
  1489.         if (plotter == DRAFTPRO)
  1490.             {
  1491.             p2x = psxdef / 2.0;
  1492.             p2y = psydef / 2.0;
  1493.             p1x = -p2x;
  1494.             p1y = -p2y;    /* change hard clip to default plot sizes */
  1495.             }
  1496.         else
  1497.             {
  1498.             p1x = 0.0;
  1499.             p2x = psxdef;
  1500.             p1y = 0.0;
  1501.             p2y = psydef;    /* change hard clip to default plot sizes */
  1502.             }
  1503.         set_aspect_ratio ();
  1504.         set_window (p1x, p2x, p1y, p2y);    /* default window scale */
  1505.         scaling = OFF;
  1506.         if (cs.cscale_mode) calc_csize (cs.rcsize_x, cs.rcsize_y, cs.cscale_mode);
  1507.             /* change font size if relative scaling */
  1508.         return;
  1509.         }
  1510.     if (!get_val (infile, &y))
  1511.         {
  1512.         print_string ("PS: missing y-parameter\n");
  1513.         return;
  1514.         }
  1515.  
  1516.     x = MAX (0.0, x);
  1517.     y = MAX (0.0, y);
  1518.     if (x == 0.0 || y == 0.0) return;    /* ignore zero length or width plot sizes */
  1519.  
  1520.     if (plotter == DRAFTPRO)
  1521.         {
  1522.         p2x = x / 2.0;
  1523.         p2y = y / 2.0;
  1524.         p1x = -p2x;
  1525.         p1y = -p2y;
  1526.         }
  1527.     else
  1528.         {
  1529.         p1x = 0.0;
  1530.         p1y = 0.0;
  1531.         p2x = x;
  1532.         p2y = y;
  1533.         }
  1534.     set_aspect_ratio ();
  1535.     set_window (p1x, p2x, p1y, p2y);    /* set window scale */
  1536.     if (cs.cscale_mode) calc_csize (cs.rcsize_x, cs.rcsize_y, cs.cscale_mode);
  1537.         /* recalculate relative char sizes */
  1538.  
  1539.     return;
  1540.     }
  1541.  
  1542. /*--------------------------------------*/
  1543.  
  1544. int video_start ( void )
  1545.     {
  1546.     int mode, max_pen;
  1547.     union REGS regs;
  1548.     unsigned display_type, disp_a, disp_b;
  1549.  
  1550.     display_type = video_test ();    /* get type of video adapter */
  1551.     disp_a = display_type & 0xFF;    /* get adapter "A" */
  1552.     disp_b = display_type >> 8;    /* get adapter "B" */
  1553.  
  1554.     disp_a = from_mode [disp_a & 0xF];    /* test for unsupported modes */
  1555.     disp_b = from_mode [disp_b & 0xF];    /* test for unsupported modes */
  1556.  
  1557.     disp_a = ( disp_a > disp_b ) ? disp_a : disp_b;
  1558.     /* select the video adapter with the highest resolution for display.
  1559.     scoring by display code number does this implicitly. */
  1560.  
  1561.     if (disp_a == 0) return (0);    /* no graphics adapter recognized */
  1562.  
  1563.     max_pen = video_mode [disp_a].max_colors;
  1564.     
  1565.     g_init (video_mode [disp_a].vid_mode );
  1566.  
  1567.     return (max_pen);    /* highest # pens available in this mode */
  1568.     }
  1569.  
  1570. /*--------------------------------------*/
  1571.