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