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