home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 January / usenetsourcesnewsgroupsinfomagicjanuary1994.iso / sources / unix / volume14 / vplot / part24 < prev    next >
Encoding:
Internet Message Format  |  1988-03-31  |  53.9 KB

  1. Subject:  v14i029:  Device-independant graphics system, with drivers
  2. Newsgroups: comp.sources.unix
  3. Sender: sources
  4. Approved: rsalz@uunet.UU.NET
  5.  
  6. Submitted-by: Joe Dellinger <joe@hanauma.STANFORD.EDU>
  7. Posting-number: Volume 14, Issue 29
  8. Archive-name: vplot/part24
  9.  
  10. #! /bin/sh
  11. # This is a shell archive.  Remove anything before this line, then unpack
  12. # it by saving it into a file and typing "sh file".  To overwrite existing
  13. # files, type "sh file -c".  You can also feed this as standard input via
  14. # unshar, or by typing "sh <file", e.g..  If this archive is complete, you
  15. # will see the following message at the end:
  16. #        "End of archive 24 (of 24)."
  17. # Wrapped by rsalz@fig.bbn.com on Fri Mar 25 11:47:38 1988
  18. PATH=/bin:/usr/bin:/usr/ucb ; export PATH
  19. if test -f 'Vplot_Kernel/filters/dovplot.c' -a "${1}" != "-c" ; then 
  20.   echo shar: Will not clobber existing file \"'Vplot_Kernel/filters/dovplot.c'\"
  21. else
  22. echo shar: Extracting \"'Vplot_Kernel/filters/dovplot.c'\" \(51559 characters\)
  23. sed "s/^X//" >'Vplot_Kernel/filters/dovplot.c' <<'END_OF_FILE'
  24. X/*
  25. X * Copyright 1987 the Board of Trustees of the Leland Stanford Junior
  26. X * University. Official permission to use this software is included in
  27. X * the documentation. It authorizes you to use this file for any
  28. X * non-commercial purpose, provided that this copyright notice is not
  29. X * removed and that any modifications made to this file are commented
  30. X * and dated in the style of my example below.
  31. X */
  32. X
  33. X/*
  34. X *
  35. X *  source file:   ./filters/dovplot.c
  36. X *
  37. X * Joe Dellinger (SEP), June 11 1987
  38. X *    Inserted this sample edit history entry.
  39. X *    Please log any further modifications made to this file:
  40. X */
  41. X/*
  42. X * Joe Dellinger Oct 18 1987
  43. X *     Made text fatness scale with txscale and scale for GKS compatibility
  44. X * Joe Dellinger Nov 9 1987
  45. X *    Changed "\n" to CRLF in MESG_TEXT calls, since newlines are
  46. X *    no longer mapped into Carriage-return linefeeds automatically.
  47. X *    (This was due to Stew's turning off of output translation.)
  48. X * Joe Dellinger Dec 9 1987
  49. X *    Made the "bad color level" error message more verbose.
  50. X * Joe Dellinger Dec 19 1987
  51. X *    Call dev.attributes(NEW_DASH,...) when the dash pattern has
  52. X *    been changed, call dev.attributes(NEW_PAT,...) when a new raster
  53. X *    pattern has been loaded, call dev.attributes(NEW_FONT,...)
  54. X *    when the txfont, txprec, or txovly has been changed,
  55. X *    dev.attributes(NEW_OVERLAY,...) when the overlay mode has
  56. X *    been changed, dev.attributes(NEW_ALIGN) when the text
  57. X *    alignment mode has been changed, dev.attributes(NEW_FAT) when
  58. X *    the fatness has been changed. Call dev.message(MESG_MESSAGE)
  59. X *    when a message is generated via the VP_MESSAGE vplot command.
  60. X * Joe Dellinger Dec 20 1987
  61. X *    It's up to the device to turn around and call gentext if
  62. X *    txfont < NUMGENFONT.
  63. X * Joe Dellinger Jan 8 1988
  64. X *    Added reset_parameters() to frontend and dovplot.
  65. X *    Turn off ALL polygon shading if shade=NO, even that generated
  66. X *    by raster, text, etc.
  67. X * Joe Dellinger Jan 10 1988
  68. X *    Don't blindly scale up fatmult each time dovplot thinks it's
  69. X *    being called for the first time.
  70. X * Joe Dellinger Jan 14 1988
  71. X *    The text alignment should also be reset between plots.
  72. X * Joe Dellinger Jan 20 1988
  73. X *    Added VP_BEGIN_GROUP and VP_END_GROUP. Fixed nplots bug.
  74. X * Joe Dellinger Jan 22 1988
  75. X *    Added xdim_orig and ydim_orig to pat.h.
  76. X * Joe Dellinger Jan 26 1988
  77. X *    Fixed EOF bug in getvpstring(). Changed rule for mapping
  78. X *    colors to grey levels to match how B+W TV's do it.
  79. X * Joe Dellinger Feb 10 1988
  80. X *    Weight color mismatches to tally with grey mapping method.
  81. X * Joe Dellinger Feb 12 1988
  82. X *    Make sure that VP_WINDOW commands that specify an inverted
  83. X *    clipping rectangle cause everything to be clipped away.
  84. X * Joe Dellinger Feb 16 1988
  85. X *    Make number of arguments passed to dev.attributes and dev.raster
  86. X *    constant to head off future catastrophe from Sun IV's.
  87. X * Joe Dellinger Feb 22 1988
  88. X *    Created INT_PAUSE to be separate from INT_GET_STRING.
  89. X * Joe Dellinger Feb 24 1988
  90. X *    Txfont, txprec, txovly, style, dash line style also reset
  91. X *    on erases.
  92. X *    Only the erase command is handled specially at the start
  93. X *    of the file. This was causing initial setstyle commands
  94. X *    to be left out of their groups!
  95. X * Joe Dellinger Feb 26 1988
  96. X *    Allow vpattributes(END_GROUP,...) to signal dovplot whether it
  97. X *    should exit or not after the call.
  98. X * Joe Dellinger Feb 28 1988
  99. X *    Fatness behaves like a geometric attribute.
  100. X *    Can't use the *= operator on the Sun!
  101. X *    if integer i = 10, then i *= .5 sets i to ZERO.
  102. X *    I wish Sun would get their act together.
  103. X *    This explains several mysterious bugs on the Suns.
  104. X */
  105. X
  106. X/*
  107. X * process a vplot file or stream
  108. X * Keywords: vplot pen generic
  109. X */
  110. X
  111. X#include     <stdio.h>
  112. X#include     <math.h>
  113. X#include    <ctype.h>
  114. X#include    <strings.h>
  115. X
  116. X#include    <vplot.h>
  117. X
  118. X#include    "./include/params.h"    /* for machine dependencies */
  119. X#include    "./include/enum.h"
  120. X#include    "./include/err.h"
  121. X#include    "./include/attrcom.h"
  122. X#include    "./include/intcom.h"
  123. X#include    "./include/mesgcom.h"
  124. X#include    "./include/erasecom.h"
  125. X#include    "./include/closestat.h"
  126. X#include    "./include/getxy.h"
  127. X#include    "./include/pat.h"
  128. X#include    "./include/vertex.h"
  129. X#include    "./include/extern.h"
  130. X#include    "./include/round.h"
  131. X
  132. X#define COLOR_MAP(A) color_set[A][MAP];
  133. X#define GREY_MAP(A) color_set[A][_GREY];
  134. X
  135. X/*
  136. X * Banished to an include file so that "indent" can't get its hands on it
  137. X */
  138. X#include "./include/readraster.h"
  139. X
  140. extern int      wantras, smart_raster;
  141. extern int      allowecho;
  142. extern int      brake;
  143. extern FILE    *controltty;
  144. extern int      cur_color;
  145. extern int      pat_color;
  146. extern int      epause;
  147. extern int      erase;
  148. extern int      ever_called;
  149. extern int      fatbase;
  150. extern int      ifat;
  151. extern int      first_time;
  152. extern int      framewindows;
  153. extern int      next_color;
  154. extern int      ipat;
  155. extern int      nplots;
  156. extern int      overlay;
  157. extern struct pat pat[];
  158. extern FILE    *pltout, *pltin, *temp;
  159. extern char     group_name[];
  160. extern int      group_number;
  161. extern char    *txbuffer;
  162. extern int      txbuflen;
  163. extern struct vertex *vxbuffer;
  164. extern int      vxbuflen;
  165. extern int      window;
  166. extern int      xwmax, xwmin, ywmax, ywmin;
  167. extern int      xWmax, xWmin, yWmax, yWmin;
  168. int             xwmin_last, xwmax_last, ywmin_last, ywmax_last;
  169. extern int      xnew, ynew;
  170. extern int      xold, yold;
  171. extern int      xorigin, yorigin;
  172. extern float    scale;
  173. extern float    xscale;
  174. extern float    yscale;
  175. extern int      default_style;
  176. extern int      default_txfont, default_txprec, default_txovly;
  177. extern int      default_overlay;
  178. extern int      color_set[MAX_COL + 1][_NUM_PRIM];
  179. extern int      greycorr ();
  180. extern int      num_col_8;
  181. extern int      xret, yret;
  182. extern int      add_a_cor ();
  183. extern char     interact[];
  184. extern float    dashsum;
  185. extern float    dashpos;
  186. extern float    dashes[];
  187. extern struct txalign txalign;
  188. X
  189. char           *malloc ();
  190. char           *calloc ();
  191. char           *realloc ();
  192. long int        ftell ();
  193. extern void     dithline ();
  194. extern void     wlimit ();
  195. X
  196. int             need_devcolor = NO;
  197. X
  198. dovplot ()
  199. X{
  200. int             i, j, k, c;
  201. int             key, size, npts;
  202. int             nmul;
  203. int             nx, ny, nx_orig, ny_orig;
  204. int             orient, ras_orient;
  205. register int   *ptr;
  206. int             nx_mult, ny_mult;
  207. int             nx_temp, ny_temp;
  208. int            *tempbuf, *ptemp;
  209. FILE           *fopen ();
  210. int             new_style;
  211. int             starterase = 0;
  212. int             col_tab_no, red, green, blue, grey, dist, min_dist, best_col;
  213. int             hacol[NHATCH * 2], hafat[NHATCH * 2], haoff[NHATCH * 2], hasiz[NHATCH * 2], numhatch;
  214. float           angle, xrasmult, yrasmult;
  215. int             xpix, ypix, num_pat, num_byte;
  216. int             yrast, lastrast;
  217. int             xvr_min, xvr_max, yvr_min, yvr_max;
  218. int             xr_min, xr_max, yr_min, yr_max;
  219. int             xvru_min, xvru_max, yvru_min, yvru_max;
  220. int             xru_min, yru_max;
  221. int             xxx[4], yyy[4];
  222. int             pos, ii, jj, kk, num_rep, ras_offset, dither_it;
  223. unsigned char  *rasterline, *rasterline2, *outraster, *outraster2;
  224. unsigned char   ibyte;
  225. int             xnewer, ynewer;
  226. int             xtext0, xtext1, xtext2, ytext0, ytext1, ytext2;
  227. int             type;
  228. int            *marker_vec, *mvec;
  229. int             savefat;
  230. float           savefatmult;
  231. char            string[MAXFLEN + 1];
  232. X
  233. X    /*
  234. X     * Check to make sure we really got anything before we claim we've made a
  235. X     * plot. 
  236. X     */
  237. X    if ((c = getc (pltin)) == EOF)
  238. X    return;
  239. X    ungetc ((char) c, pltin);
  240. X
  241. X    while (((c = getc (pltin)) == VP_ERASE) || ((c == VP_BREAK) && brake))
  242. X    {
  243. X    /*
  244. X     * This is a baby version of the main switch that takes up most of
  245. X     * this file. 
  246. X     */
  247. X    switch (c)
  248. X    {
  249. X    case VP_ERASE:
  250. X    case VP_BREAK:
  251. X        starterase = 1;
  252. X        break;
  253. X    }
  254. X    }
  255. X
  256. X    /*
  257. X     * Files that consist only of erase characters and nothing else are
  258. X     * ignored. 
  259. X     */
  260. X    if (c == EOF)
  261. X    return;
  262. X    ungetc ((char) c, pltin);
  263. X
  264. X    if (first_time)
  265. X    {
  266. X    dev.reset ();
  267. X/*
  268. X * Device is now officially open for orders.
  269. X */
  270. X    if (dev_xmax <= dev_xmin ||
  271. X        dev_ymax <= dev_ymin ||
  272. X        pixels_per_inch == 0. ||
  273. X        aspect_ratio == 0. ||
  274. X        num_col == -1)
  275. X        ERR (FATAL, name, "Critical variables left unset by device!");
  276. X
  277. X/*
  278. X * Set maximum clipping window for dev.attributes(SET_WINDOW)
  279. X */
  280. X    xwmax_last = dev_xmax;
  281. X    xwmin_last = dev_xmin;
  282. X    ywmax_last = dev_ymax;
  283. X    ywmin_last = dev_ymin;
  284. X
  285. X/*
  286. X * Set up color maps
  287. X */
  288. X    init_colors ();
  289. X
  290. X    ever_called = 1;
  291. X    }
  292. X    else
  293. X    {
  294. X    dev.close (CLOSE_FLUSH);
  295. X    if (epause > 0)
  296. X    {
  297. X        sleep ((unsigned) epause);
  298. X    }
  299. X    else
  300. X    if (epause < 0)
  301. X    {
  302. X        dev.close (CLOSE_FLUSH);
  303. X        message (MESG_ERASE);
  304. X        message (MESG_ON);
  305. X        message (MESG_HOME);
  306. X        message (MESG_READY);
  307. X        message (MESG_HIGHLIGHT_ON);
  308. X        message (MESG_TEXT, "Type Return to Continue...  ");
  309. X        message (MESG_DONE);
  310. X        dev.interact (INT_PAUSE, controltty, string);
  311. X        message (MESG_HIGHLIGHT_OFF);
  312. X        if (!allowecho)
  313. X        {
  314. X        message (MESG_READY);
  315. X        message (MESG_TEXT, CRLF);
  316. X        }
  317. X        message (MESG_DONE);
  318. X        message (MESG_OFF);
  319. X        message (MESG_ERASE);
  320. X    }
  321. X    /*
  322. X     * Inquire point back from device 
  323. X     */
  324. X    if (interact[0] != '\0')
  325. X    {
  326. X        getapoint ();
  327. X    }
  328. X    }
  329. X
  330. X    /*
  331. X     * Erase the screen to background color 
  332. X     */
  333. X    if (((erase & FORCE_INITIAL) && (first_time || (erase & DO_LITERALS)))
  334. X    || (starterase && (erase & DO_LITERALS)))
  335. X    {
  336. X    if (first_time)
  337. X        dev.erase (ERASE_START);
  338. X    else
  339. X    {
  340. X        dev.erase (ERASE_MIDDLE);
  341. X        nplots++;
  342. X    }
  343. X    dev.close (CLOSE_FLUSH);
  344. X    }
  345. X
  346. X    first_time = NO;
  347. X
  348. X/*
  349. X * Reset fatness, cur_color, etc.
  350. X */
  351. X    new_style = default_style;
  352. X    setstyle (new_style);
  353. X    reset ();
  354. X
  355. X/*
  356. X * Make SURE the color is what it's supposed to be, just to be safe.
  357. X */
  358. X    dev.attributes (SET_COLOR, cur_color, 0, 0, 0);
  359. X    need_devcolor = NO;
  360. X
  361. X    message (MESG_OFF);
  362. X    dev.close (CLOSE_FLUSH);
  363. X
  364. X/*
  365. X * Start a group that will contain this frame (always group 0).
  366. X */
  367. X    ii = ftell (pltin);
  368. X    sprintf (group_name, "%s.%d", pltname, nplots);
  369. X    dev.attributes (BEGIN_GROUP, group_number, ii, 0, 0);
  370. X    group_number++;
  371. X
  372. X    if (framewindows)
  373. X    outline_window ();
  374. X
  375. X/*
  376. X * Finally, here's the main loop that does the actual processing of vplot.
  377. X * Notice that some tricky commands (VP_DRAW, VP_SET_COLOR_TABLE) look ahead
  378. X * at the next command to try to anticipate often-occuring situations,
  379. X * so things get a little complicated here.
  380. X */
  381. X    while ((c = getc (pltin)) != EOF)
  382. X    {
  383. X    switch (c)        /* command list */
  384. X    {
  385. X    case VP_SETSTYLE:    /* set the style */
  386. X        c = getc (pltin);
  387. X        if ((c == 'r') || (c == 'R') || (c == 'm') || (c == 'M'))
  388. X        new_style = ROTATED;
  389. X        else
  390. X        if ((c == 'o') || (c == 'O'))
  391. X        new_style = OLD;
  392. X        else
  393. X        if ((c == 'a') || (c == 'A'))
  394. X        new_style = ABSOLUTE;
  395. X        else
  396. X        new_style = STANDARD;
  397. X        setstyle (new_style);
  398. X
  399. X        if (framewindows)
  400. X        outline_window ();
  401. X
  402. X        break;
  403. X    case VP_MOVE:        /* move */
  404. X        /*
  405. X         * Reset position in dash pattern. 
  406. X         */
  407. X        dashpos = 0.;
  408. X
  409. X        GETXY (xold, yold);
  410. X        break;
  411. X    case VP_DRAW:        /* draw */
  412. X        GETXY (xnew, ynew);
  413. X        update_color ();
  414. X        while ((c = getc (pltin)) == VP_DRAW)
  415. X        {
  416. X        GETXY (xnewer, ynewer);
  417. X        /*
  418. X         * Is it the same point? 
  419. X         */
  420. X        if (xnewer == xnew && ynewer == ynew)
  421. X            continue;
  422. X        /*
  423. X         * Is it colinear and horizontal or vertical? 
  424. X         */
  425. X        if ((ynewer == ynew && ynew == yold &&
  426. X             ((xnewer > xnew) == (xnew > xold))) ||
  427. X            (xnewer == xnew && xnew == xold &&
  428. X             ((ynewer > ynew) == (ynew > yold))))
  429. X        {
  430. X            ynew = ynewer;
  431. X            xnew = xnewer;
  432. X            continue;
  433. X        }
  434. X        dev.vector (xold, yold, xnew, ynew, fat, dashon);
  435. X        xold = xnew;
  436. X        yold = ynew;
  437. X        xnew = xnewer;
  438. X        ynew = ynewer;
  439. X        }
  440. X        dev.vector (xold, yold, xnew, ynew, fat, dashon);
  441. X        xold = xnew;
  442. X        yold = ynew;
  443. X        if (c == EOF)
  444. X        goto End_of_file;
  445. X        ungetc ((char) c, pltin);
  446. X        break;
  447. X    case VP_PLINE:        /* polyline */
  448. X        /*
  449. X         * Reset position in dash pattern. 
  450. X         */
  451. X        dashpos = 0.;
  452. X
  453. X        npts = geth (pltin);
  454. X        if (npts == 0)
  455. X        break;
  456. X        GETXY (xold, yold);
  457. X        npts--;
  458. X        if (npts == 0)
  459. X        break;
  460. X        GETXY (xnew, ynew);
  461. X        npts--;
  462. X        update_color ();
  463. X        while (npts > 0)
  464. X        {
  465. X        GETXY (xnewer, ynewer);
  466. X        npts--;
  467. X        /*
  468. X         * Is it the same point? 
  469. X         */
  470. X        if (xnewer == xnew && ynewer == ynew)
  471. X            continue;
  472. X        /*
  473. X         * Is it colinear and horizontal or vertical? 
  474. X         */
  475. X        if ((ynewer == ynew && ynew == yold &&
  476. X             ((xnewer > xnew) == (xnew > xold))) ||
  477. X            (xnewer == xnew && xnew == xold &&
  478. X             ((ynewer > ynew) == (ynew > yold))))
  479. X        {
  480. X            ynew = ynewer;
  481. X            xnew = xnewer;
  482. X            continue;
  483. X        }
  484. X        dev.vector (xold, yold, xnew, ynew, fat, dashon);
  485. X        xold = xnew;
  486. X        yold = ynew;
  487. X        xnew = xnewer;
  488. X        ynew = ynewer;
  489. X        }
  490. X        dev.vector (xold, yold, xnew, ynew, fat, dashon);
  491. X        xold = xnew;
  492. X        yold = ynew;
  493. X        break;
  494. X    case VP_PMARK:        /* polymarker */
  495. X        npts = geth (pltin);/* how many markers ? */
  496. X        type = geth (pltin);/* what symbol? (any positive integer) */
  497. X        size = geth (pltin);/* How big? */
  498. X        size = size * mkscale * vdevscale * RPERIN / TXPERIN;
  499. X
  500. X        if (npts == 0)
  501. X        break;
  502. X        /* allocate space for the points */
  503. X        marker_vec = (int *) malloc ((unsigned) (npts * 2 * sizeof (int)));
  504. X        mvec = marker_vec;
  505. X        if (mvec == NULL)
  506. X        ERR (FATAL, name, "Can't malloc memory for markers!");
  507. X
  508. X        /* read the locations, and transform them to device coordinates */
  509. X        for (ii = 0; ii < npts; ii++)
  510. X        {
  511. X        GETXY (xnewer, ynewer);
  512. X        *mvec = xnewer;
  513. X        ++mvec;
  514. X        *mvec = ynewer;
  515. X        ++mvec;
  516. X        }
  517. X        update_color ();
  518. X        /* call the device routine to display the markers */
  519. X        dev.marker (npts, type, size, marker_vec);
  520. X        /* release the storage used for the points */
  521. X        free ((char *) marker_vec);
  522. X        break;
  523. X    case VP_ORIGIN:    /* set origin */
  524. X        xorigin = geth (pltin);
  525. X        yorigin = geth (pltin);
  526. X        break;
  527. X    case VP_BEGIN_GROUP:
  528. X        ii = ftell (pltin) - 1;
  529. X        getvpstring ();
  530. X        strncpy (group_name, txbuffer, MAXFLEN);
  531. X        dev.attributes (BEGIN_GROUP, group_number, ii, 0, 0);
  532. X        group_number++;
  533. X        break;
  534. X    case VP_END_GROUP:
  535. X        group_number--;
  536. X        if (group_number < 1)
  537. X        {
  538. X        ERR (WARN, name,
  539. X             "group invalidly nested");
  540. X        group_number = 1;
  541. X        }
  542. X        else
  543. X        {
  544. X        ii = dev.attributes (END_GROUP, group_number, 0, 0, 0);
  545. X        if (ii == DOVPLOT_EXIT)
  546. X        {
  547. X            dev.close (CLOSE_FLUSH);
  548. X            return;
  549. X        }
  550. X        if (ii != DOVPLOT_CONT)
  551. X            ERR (WARN, name, "dev.attributes(END_GROUP,...) returned junk.");
  552. X        }
  553. X        break;
  554. X    case VP_GTEXT:        /* GKS-like text */
  555. X        xtext0 = 0;
  556. X        ytext0 = 0;
  557. X        vptodevxy (xtext0, ytext0, &xtext0, &ytext0);
  558. X        GETXY (xtext1, ytext1);
  559. X        GETXY (xtext2, ytext2);
  560. X    g_text:
  561. X        xtext1 -= xtext0;
  562. X        xtext2 -= xtext0;
  563. X        ytext1 -= ytext0;
  564. X        ytext2 -= ytext0;
  565. X
  566. X        savefat = fat;
  567. X        savefatmult = fatmult;
  568. X        fatmult *= txscale;
  569. X        if (ifat >= 0)
  570. X        {
  571. X        fat = fatmult * (float) (ifat + fatbase);
  572. X        }
  573. X        else
  574. X        {
  575. X        fat = -1;
  576. X        }
  577. X        update_color ();
  578. X        getvpstring ();
  579. X/*
  580. X * Fonts less than NUMGENFONT reserved for gentext fonts:
  581. X * up to the device to enforce that rule, though.
  582. X */
  583. X        dev.text (txbuffer,
  584. X              (float) xtext1 / TEXTVECSCALE,
  585. X              (float) ytext1 / TEXTVECSCALE,
  586. X              (float) xtext2 / TEXTVECSCALE,
  587. X              (float) ytext2 / TEXTVECSCALE);
  588. X        fat = savefat;
  589. X        fatmult = savefatmult;
  590. X        break;
  591. X    case VP_TEXT:        /* text */
  592. X        size = geth (pltin);
  593. X        size = size * txscale * (float) RPERIN / (float) TXPERIN;
  594. X        orient = (int) geth (pltin);
  595. X    new_text:
  596. X        xtext0 = 0;
  597. X        ytext0 = 0;
  598. X        /* Character path direction */
  599. X        xtext1 =
  600. X         ROUND (TEXTVECSCALE * size * cos (orient * 3.14159 / 180.));
  601. X        ytext1 =
  602. X         ROUND (TEXTVECSCALE * size * sin (orient * 3.14159 / 180.));
  603. X        /* Character up vector direction */
  604. X        orient += 90;
  605. X        xtext2 =
  606. X         ROUND (TEXTVECSCALE * size * cos (orient * 3.14159 / 180.));
  607. X        ytext2 =
  608. X         ROUND (TEXTVECSCALE * size * sin (orient * 3.14159 / 180.));
  609. X        vptodevxy (xtext0, ytext0, &xtext0, &ytext0);
  610. X        vptodevxy (xtext1, ytext1, &xtext1, &ytext1);
  611. X        vptodevxy (xtext2, ytext2, &xtext2, &ytext2);
  612. X        goto g_text;
  613. X        break;
  614. X    case VP_OLDTEXT:    /* archaic format text */
  615. X        if ((key = geth (pltin)) < 0)
  616. X        ERR (FATAL, name, "invalid text key");
  617. X        size = (key & 037);
  618. X        size = size * txscale * (float) RPERIN / (float) TXPERIN;
  619. X        orient = (int) (((key & 0140) >> 5) * 90);
  620. X        goto new_text;
  621. X        break;
  622. X    case VP_OLDAREA:    /* polygon */
  623. X        npts = geth (pltin);
  624. X        afat = geth (pltin);
  625. X        if (afat >= 0)
  626. X        {
  627. X        afat = fatmult * (fatbase + afat);
  628. X        }
  629. X        nx_temp = geth (pltin);
  630. X        ny_temp = geth (pltin);
  631. X
  632. X/*
  633. X * If a monochrome device, then fill with dot pattern.
  634. X * If a color device, fill with solid color.
  635. X */
  636. X        nx = nx_temp * patternmult;
  637. X        if (nx_temp == 1 || (nx_temp > 0 && nx == 0))
  638. X        nx = 1;
  639. X        ny = ny_temp * patternmult;
  640. X        if (ny_temp == 1 || (ny_temp > 0 && ny == 0))
  641. X        ny = 1;
  642. X
  643. X        nx_orig = nx;
  644. X        ny_orig = ny;
  645. X
  646. X        if (!mono)
  647. X        {
  648. X        if (nx_temp == 0 || ny_temp == 0)
  649. X        {
  650. X            nx = 0;
  651. X            ny = 0;
  652. X        }
  653. X        else
  654. X        {
  655. X            nx = 1;
  656. X            ny = 1;
  657. X        }
  658. X        }
  659. X        /*
  660. X         * Create a temporary pattern 
  661. X         */
  662. X        ipat = 0;
  663. X        if (nx * ny > 0)
  664. X        {
  665. X        if ((ptr = (int *) calloc ((unsigned) nx * ny, sizeof (int))) == NULL)
  666. X            ERR (FATAL, name, "cannot alloc memory to load pattern");
  667. X        pat[ipat] .patbits = ptr;
  668. X        ptr[(nx * ny) - 1] = cur_color;
  669. X        }
  670. X        else
  671. X        pat[ipat] .patbits = NULL;
  672. X
  673. X        pat[ipat] .xdim = nx;
  674. X        pat[ipat] .ydim = ny;
  675. X        pat[ipat] .xdim_orig = nx_orig;
  676. X        pat[ipat] .ydim_orig = ny_orig;
  677. X        npts = getpolygon (npts);
  678. X        update_color ();
  679. X        if (afat >= 0)
  680. X        vecoutline (vxbuffer);
  681. X        if (npts > 2 && shade && nx > 0 && ny > 0)
  682. X        dev.area (npts, vxbuffer);
  683. X        if (nx * ny > 0)
  684. X        free ((char *) ptr);
  685. X        break;
  686. X    case VP_AREA:        /* polygon fill */
  687. X        npts = geth (pltin);
  688. X        ipat = pat_color;
  689. X
  690. X        if (pat[ipat] .patbits == NULL && shade)
  691. X        {
  692. X        /*
  693. X         * Create a default pattern (solid fill with this color) If
  694. X         * you don't like this default for a particular device, ie, a
  695. X         * black and white one, then the device itself can set up
  696. X         * defaults for colors 0 through 7 in dev.open 
  697. X         */
  698. X        nx = 1;
  699. X        ny = 1;
  700. X
  701. X        if ((ptr = (int *) calloc ((unsigned) nx * ny, sizeof (int))) == NULL)
  702. X            ERR (FATAL, name, "cannot alloc memory to load pattern");
  703. X        pat[ipat] .patbits = ptr;
  704. X        ptr[(nx * ny) - 1] = cur_color;
  705. X        pat[ipat] .xdim = nx;
  706. X        pat[ipat] .ydim = ny;
  707. X        pat[ipat] .xdim_orig = nx;
  708. X        pat[ipat] .ydim_orig = ny;
  709. X        }
  710. X
  711. X        npts = getpolygon (npts);
  712. X
  713. X        if (!shade)
  714. X        {
  715. X        /* At least draw the boundary to show where it is */
  716. X        afat = 0;
  717. X        update_color ();
  718. X        vecoutline (vxbuffer);
  719. X        }
  720. X        else
  721. X        {
  722. X        /* See whether raster or hatch area */
  723. X        if (pat[ipat] .xdim >= 0)
  724. X        {
  725. X            /* raster */
  726. X            if (npts > 2 && pat[ipat] .ydim > 0 && pat[ipat] .xdim > 0)
  727. X            {
  728. X            update_color ();
  729. X            dev.area (npts, vxbuffer);
  730. X            }
  731. X        }
  732. X        else
  733. X        {
  734. X            /* hatch */
  735. X            numhatch = -pat[ipat] .xdim;
  736. X            angle = 3.14159 * pat[ipat] .ydim / 180.;
  737. X            ptr = pat[ipat] .patbits;
  738. X            for (i = 0; i < numhatch * 2; i++)
  739. X            {
  740. X            hafat[i] = (*ptr++);
  741. X            hacol[i] = (*ptr++);
  742. X            haoff[i] = (*ptr++);
  743. X            hasiz[i] = (*ptr++);
  744. X            }
  745. X            if (npts > 2)
  746. X            {
  747. X            /*
  748. X             * Hatch patterns don't rotate. The polygon does, the
  749. X             * fill pattern doesn't. 
  750. X             */
  751. X            genhatch (npts, numhatch, angle, hafat, hacol, haoff, hasiz, vxbuffer);
  752. X            }
  753. X        }
  754. X        }
  755. X        break;
  756. X    case VP_FAT:        /* fat */
  757. X        /*
  758. X         * negative fat always means to not draw the line at all. 
  759. X         */
  760. X        ifat = geth (pltin);
  761. X        if (ifat >= 0)
  762. X        {
  763. X        fat = fatmult * (float) (ifat + fatbase);
  764. X        }
  765. X        else
  766. X        {
  767. X        fat = -1;
  768. X        }
  769. X        dev.attributes (NEW_FAT, fat, 0, 0, 0);
  770. X        break;
  771. X    case VP_COLOR:        /* change color */
  772. X        pat_color = geth (pltin);
  773. X        if (pat_color > MAX_COL || pat_color < 0)
  774. X        {
  775. X        ERR (WARN, name, "bad color number %d (max %d, min 0)",
  776. X             pat_color, MAX_COL);
  777. X        pat_color = DEFAULT_COLOR;
  778. X        }
  779. X        next_color = COLOR_MAP (pat_color);
  780. X        if (next_color != cur_color)
  781. X        {
  782. X        cur_color = next_color;
  783. X        need_devcolor = YES;
  784. X        }
  785. X        /*
  786. X         * Pattern zero reserved for the OLD_AREA command, so increment
  787. X         * the rest by one to make room. 
  788. X         */
  789. X        pat_color++;
  790. X        break;
  791. X    case VP_SET_COLOR_TABLE:    /* set color table entry */
  792. X        /*
  793. X         * The logic here is a bit tricky. Basically, it goes like this:
  794. X         * If the device actually has a settable color of that number,
  795. X         * then reset the device's color as asked. Otherwise, take the
  796. X         * closest color that we have and map to that. Color 0 is the
  797. X         * background color, and is special. Merely "close" colors are
  798. X         * not mapped to Color 0... it has to be exact. Even devices with
  799. X         * NO settable colors are still sent colors 0 through 7, and
  800. X         * these colors are then always left set to their original
  801. X         * defaults. In this way you can handle terminals like the GIGI
  802. X         * which have colors but not SETTABLE colors. Also remember that
  803. X         * the device itself will THEN have to permute colors 0 through 7
  804. X         * on top of all this to correspond with Vplot's definitions! 
  805. X         */
  806. X        col_tab_no = geth (pltin);
  807. X        if (col_tab_no > MAX_COL || col_tab_no < 0)
  808. X        {
  809. X        ERR (FATAL, name, "Bad color table value %d (%d max)",
  810. X             col_tab_no, MAX_COL);
  811. X        }
  812. X        red = geth (pltin);
  813. X        green = geth (pltin);
  814. X        blue = geth (pltin);
  815. X        if (red > MAX_GUN || green > MAX_GUN || blue > MAX_GUN
  816. X        || red < 0 || green < 0 || blue < 0)
  817. X        {
  818. X        ERR (FATAL, name,
  819. X             "Bad color level in color %d (%d,%d,%d), %d max",
  820. X             col_tab_no, red, green, blue, MAX_GUN);
  821. X        }
  822. X        if (col_tab_no < num_col)
  823. X        {
  824. X        dev.attributes (SET_COLOR_TABLE, col_tab_no, red, green, blue);
  825. X        color_set[col_tab_no][STATUS] = SET;
  826. X        }
  827. X        else
  828. X        if (col_tab_no > 7)
  829. X        {
  830. X        color_set[col_tab_no][STATUS] = MAPPED;
  831. X        }
  832. X        else
  833. X        {
  834. X        if (col_tab_no > 0)
  835. X        {
  836. X            color_set[col_tab_no][STATUS] = MAP_SET;
  837. X            /*
  838. X             * Means that we need to map these but they are still set
  839. X             * to the original colors and can't be changed. Color 0
  840. X             * is always background, and any other color exactly the
  841. X             * same color as color 0 "wants to be", even if color 0
  842. X             * actually can't be and hasn't been reset, is mapped to
  843. X             * color zero if it can't be set. 
  844. X             */
  845. X        }
  846. X        }
  847. X        /*
  848. X         * Save the color that this color table number wants to be 
  849. X         */
  850. X        color_set[col_tab_no][_RED] = red;
  851. X        color_set[col_tab_no][_GREEN] = green;
  852. X        color_set[col_tab_no][_BLUE] = blue;
  853. X        /*
  854. X         * grey level is "Black and White TV style" mapped from color,
  855. X         * with corrections added by the subroutine greycorr. 
  856. X         */
  857. X        grey = (blue * 1 + red * 2 + green * 4 + 6) / 7;
  858. X        color_set[col_tab_no][_GREY] = greycorr (grey);
  859. X        /*
  860. X         * If the next command is also a set color table command, we can
  861. X         * postpone doing this and kill 2 (or more) birds with one stone. 
  862. X         */
  863. X        c = getc (pltin);
  864. X        if (c == EOF)
  865. X        goto End_of_file;
  866. X        ungetc ((char) c, pltin);
  867. X        if (c != VP_SET_COLOR_TABLE)
  868. X        {
  869. X        if (mono)
  870. X        {
  871. X            for (ii = 1; ii <= MAX_COL; ii++)
  872. X            {
  873. X            if (color_set[ii][_RED] == color_set[0][_RED] &&
  874. X                color_set[ii][_GREEN] == color_set[0][_GREEN] &&
  875. X                color_set[ii][_BLUE] == color_set[0][_BLUE])
  876. X            {
  877. X                color_set[ii][MAP] = 0;
  878. X            }
  879. X            else
  880. X            {
  881. X                color_set[ii][MAP] = 7;
  882. X            }
  883. X            }
  884. X        }
  885. X        else
  886. X        {
  887. X            /*
  888. X             * For all color table entries that aren't set, (because
  889. X             * we ran out of colors, for example) find the best color
  890. X             * that IS set and use that instead. 
  891. X             */
  892. X            for (ii = num_col; ii <= MAX_COL; ii++)
  893. X            {
  894. X            if (color_set[ii][STATUS] & MAPPED)
  895. X            {
  896. X                min_dist = MAX_GUN * MAX_GUN * 8;
  897. X                for (i = num_col_8 - 1; i >= 0; i--)
  898. X                {
  899. X                /*
  900. X                 * Colors 1 through 7 are guaranteed SET, So
  901. X                 * we always get an answer. Color zero is
  902. X                 * background and special. To map to it you
  903. X                 * have to hit its color exactly, and no
  904. X                 * other color matched exactly first. 
  905. X                 */
  906. X                if (color_set[i][STATUS] & SET)
  907. X                {
  908. X                    if (color_set[i][STATUS] == SET)
  909. X                    {
  910. X                    k = color_set[i][_RED] - color_set[ii][_RED];
  911. X                    dist = 2 * k * k;
  912. X                    k = color_set[i][_GREEN] - color_set[ii][_GREEN];
  913. X                    dist += 4 * k * k;
  914. X                    k = color_set[i][_BLUE] - color_set[ii][_BLUE];
  915. X                    dist += k * k;
  916. X                    }
  917. X                    else
  918. X                    {
  919. X                    k = MAX_GUN * ((i & 2) / 2) - color_set[ii][_RED];
  920. X                    dist = 2 * k * k;
  921. X                    k = MAX_GUN * ((i & 4) / 4) - color_set[ii][_GREEN];
  922. X                    dist += 4 * k * k;
  923. X                    k = MAX_GUN * ((i & 1) / 1) - color_set[ii][_BLUE];
  924. X                    dist += k * k;
  925. X                    }
  926. X                    if (dist < min_dist && (i != 0 || dist == 0))
  927. X                    {
  928. X                    min_dist = dist;
  929. X                    best_col = i;
  930. X                    if (dist == 0)
  931. X                    {
  932. X                        /*
  933. X                         * Might as well look no further 
  934. X                         */
  935. X                        break;
  936. X                    }
  937. X                    }
  938. X                }
  939. X                }
  940. X                color_set[ii][MAP] = best_col;
  941. X            }
  942. X            }
  943. X        }
  944. X        }
  945. X        break;
  946. X    case VP_PURGE:        /* purge pltout buffers */
  947. X        dev.close (CLOSE_FLUSH);
  948. X        break;
  949. X    case VP_BREAK:        /* break */
  950. X    case VP_ERASE:        /* erase */
  951. X        dev.close (CLOSE_FLUSH);
  952. X
  953. X        if ((c == VP_ERASE) || brake)
  954. X        {
  955. X        group_number--;
  956. X        if (group_number != 0)
  957. X        {
  958. X            ERR (WARN, name,
  959. X             "group contains erase");
  960. X            group_number = 0;
  961. X        }
  962. X        else
  963. X        {
  964. X            ii = dev.attributes (END_GROUP, group_number, 0, 0, 0);
  965. X            if (ii == DOVPLOT_EXIT)
  966. X            return;
  967. X            if (ii != DOVPLOT_CONT)
  968. X            ERR (WARN, name, "dev.attributes(END_GROUP,...) returned junk.");
  969. X        }
  970. X        }
  971. X
  972. X        if (epause < 0)
  973. X        {
  974. X        message (MESG_ERASE);
  975. X        message (MESG_ON);
  976. X        message (MESG_HOME);
  977. X        message (MESG_READY);
  978. X        message (MESG_HIGHLIGHT_ON);
  979. X        message (MESG_TEXT, "Type Return to Continue...  ");
  980. X        message (MESG_DONE);
  981. X        dev.interact (INT_PAUSE, controltty, string);
  982. X        message (MESG_HIGHLIGHT_OFF);
  983. X        if (!allowecho)
  984. X        {
  985. X            message (MESG_READY);
  986. X            message (MESG_TEXT, CRLF);
  987. X        }
  988. X        message (MESG_DONE);
  989. X        message (MESG_OFF);
  990. X        message (MESG_ERASE);
  991. X        }
  992. X        else
  993. X        {
  994. X        if (epause > 0)
  995. X            sleep ((unsigned) epause);
  996. X        }
  997. X        /*
  998. X         * Inquire point back from device 
  999. X         */
  1000. X        if (interact[0] != '\0')
  1001. X        {
  1002. X        getapoint ();
  1003. X        }
  1004. X
  1005. X        if (erase & DO_LITERALS)
  1006. X        if ((c == VP_ERASE) || brake)
  1007. X        {
  1008. X            dev.erase (ERASE_MIDDLE);
  1009. X            nplots++;
  1010. X        }
  1011. X        else
  1012. X        {
  1013. X            dev.erase (ERASE_BREAK);
  1014. X            nplots++;
  1015. X        }
  1016. X
  1017. X        new_style = default_style;
  1018. X        setstyle (new_style);
  1019. X        reset ();
  1020. X
  1021. X        if ((c == VP_ERASE) || brake)
  1022. X        {
  1023. X        ii = ftell (pltin);
  1024. X        sprintf (group_name, "%s.%d", pltname, nplots);
  1025. X        dev.attributes (BEGIN_GROUP, group_number, ii, 0, 0);
  1026. X        group_number++;
  1027. X        }
  1028. X
  1029. X        if (framewindows)
  1030. X        outline_window ();
  1031. X
  1032. X        break;
  1033. X    case VP_WINDOW:    /* window */
  1034. X        if (window)
  1035. X        {
  1036. X        xwmin = geth (pltin);
  1037. X        ywmin = geth (pltin);
  1038. X        xwmax = geth (pltin);
  1039. X        ywmax = geth (pltin);
  1040. X
  1041. X        if (xwmin > xwmax || ywmin > ywmax)
  1042. X        {
  1043. X/*
  1044. X * vptodevw will always return a window that is the "right way around",
  1045. X * even if the original window was inverted. So produce an inside-out
  1046. X * window which will clip everything away to nothing.
  1047. X */
  1048. X
  1049. X            xwmin = xWmax + 1;
  1050. X            xwmax = xWmin - 1;
  1051. X            ywmin = yWmax + 1;
  1052. X            ywmax = yWmin - 1;
  1053. X        }
  1054. X        else
  1055. X        {
  1056. X
  1057. X            vptodevw (xwmin, ywmin, xwmax, ywmax, &xwmin, &ywmin, &xwmax, &ywmax);
  1058. X
  1059. X            wlimit (xWmin, xWmax, &xwmin, &xwmax);
  1060. X            wlimit (yWmin, yWmax, &ywmin, &ywmax);
  1061. X        }
  1062. X        }
  1063. X        else
  1064. X        {
  1065. X        geth (pltin);
  1066. X        geth (pltin);
  1067. X        geth (pltin);
  1068. X        geth (pltin);
  1069. X        }
  1070. X        reset_windows ();
  1071. X        if (framewindows)
  1072. X        outline_window ();
  1073. X        break;
  1074. X    case VP_NOOP:        /* no op */
  1075. X        break;
  1076. X    case VP_TXALIGN:    /* set text alignment */
  1077. X        /*
  1078. X         * These are made available to the device text routine 
  1079. X         */
  1080. X        txalign.hor = geth (pltin);
  1081. X        txalign.ver = geth (pltin);
  1082. X        dev.attributes (NEW_ALIGN, txalign.hor, txalign.ver, 0, 0);
  1083. X        break;
  1084. X    case VP_TXFONTPREC:    /* set text font */
  1085. X        /*
  1086. X         * These are made available to the device text routine 
  1087. X         */
  1088. X        ii = geth (pltin);
  1089. X        if (ii >= 0)
  1090. X        txfont = ii;
  1091. X        else
  1092. X        ii = -1;
  1093. X
  1094. X        jj = geth (pltin);
  1095. X        if (jj >= 0)
  1096. X        txprec = jj;
  1097. X        else
  1098. X        jj = -1;
  1099. X
  1100. X        kk = geth (pltin);
  1101. X        if (kk >= 0)
  1102. X        txovly = kk;
  1103. X        else
  1104. X        kk = -1;
  1105. X
  1106. X        /*
  1107. X         * Another way for the device to keep track of changes. 
  1108. X         */
  1109. X        dev.attributes (NEW_FONT, ii, jj, kk, 0);
  1110. X        break;
  1111. X    case VP_OVERLAY:    /* change overlay mode */
  1112. X        /*
  1113. X         * This is made available to the device dependent subroutines 
  1114. X         */
  1115. X        overlay = geth (pltin);
  1116. X        dev.attributes (NEW_OVERLAY, overlay, 0, 0, 0);
  1117. X        break;
  1118. X    case VP_PATLOAD:    /* load a pattern */
  1119. X        nmul = geth (pltin);
  1120. X        ny = geth (pltin);
  1121. X
  1122. X        /* See whether Raster or Hatch */
  1123. X        if (ny >= 0)
  1124. X        {
  1125. X        /* Raster */
  1126. X        /* nmul gives pixels_per_inch pattern is designed for */
  1127. X        ny_mult = ny * (pixels_per_inch / nmul) * patternmult / aspect_ratio;
  1128. X        if (ny_mult == 0 && ny > 0)
  1129. X            ny_mult = 1;
  1130. X        nx = geth (pltin);
  1131. X        nx_mult = nx * (pixels_per_inch / nmul) * patternmult;
  1132. X        if (nx_mult == 0 && nx > 0)
  1133. X            nx_mult = 1;
  1134. X
  1135. X        ipat = geth (pltin) + 1;
  1136. X        if (ipat > NPAT || ipat < 1)
  1137. X            ERR (FATAL, name, "bad pattern number %d (max %d, min 1)", ipat, NPAT);
  1138. X        /*
  1139. X         * Free up pattern that may already be there 
  1140. X         */
  1141. X        if (pat[ipat] .patbits != NULL)
  1142. X        {
  1143. X            free ((char *) pat[ipat] .patbits);
  1144. X        }
  1145. X
  1146. X        if (nx_mult * ny_mult > 0)
  1147. X        {
  1148. X            if ((ptr = (int *) malloc ((unsigned) (nx_mult * ny_mult * sizeof (int)))) == NULL)
  1149. X            ERR (FATAL, name, "cannot alloc memory to load pattern");
  1150. X            pat[ipat] .patbits = ptr;
  1151. X        }
  1152. X        else
  1153. X        {
  1154. X            if ((ptr = (int *) malloc ((unsigned) (1 * sizeof (int)))) == NULL)
  1155. X            ERR (FATAL, name, "cannot alloc memory to load dummy pattern");
  1156. X            pat[ipat] .patbits = ptr;
  1157. X            ptr[0] = 0;
  1158. X        }
  1159. X
  1160. X        if (nx * ny > 0)
  1161. X        {
  1162. X            if ((tempbuf = (int *) malloc ((unsigned) (nx * ny * sizeof (int)))) == NULL)
  1163. X            ERR (FATAL, name,
  1164. X                 "cannot alloc memory to load pattern's temporary buffer");
  1165. X        }
  1166. X        else
  1167. X            tempbuf = NULL;
  1168. X
  1169. X        /*
  1170. X         * read in pattern 
  1171. X         */
  1172. X        ptemp = tempbuf;
  1173. X        for (j = 0; j < nx * ny; j++)
  1174. X        {
  1175. X            k = geth (pltin);
  1176. X            if (k > MAX_COL || k < 0)
  1177. X            {
  1178. X            ERR (WARN, name, "bad color number in pattern %d (max %d, min 0)",
  1179. X                 k, MAX_COL);
  1180. X            k = DEFAULT_COLOR;
  1181. X            }
  1182. X            *ptemp++ = COLOR_MAP (k);
  1183. X        }
  1184. X
  1185. X        /*
  1186. X         * copy into patbits, with "stretching" 
  1187. X         */
  1188. X        for (i = 0; i < ny_mult; i++)
  1189. X        {
  1190. X            ny_temp = i * ny / ny_mult;
  1191. X            for (j = 0; j < nx_mult; j++)
  1192. X            {
  1193. X            nx_temp = j * nx / nx_mult;
  1194. X            ptr[j + nx_mult * i] = tempbuf[nx_temp + nx * ny_temp];
  1195. X            }
  1196. X        }
  1197. X        /*
  1198. X         * set dimensions of pattern 
  1199. X         */
  1200. X        pat[ipat] .xdim = nx_mult;
  1201. X        pat[ipat] .ydim = ny_mult;
  1202. X        pat[ipat] .xdim_orig = nx_mult;
  1203. X        pat[ipat] .ydim_orig = ny_mult;
  1204. X
  1205. X        if (tempbuf != NULL)
  1206. X            free ((char *) tempbuf);
  1207. X
  1208. X        dev.attributes (NEW_PAT, ipat, 0, 0, 0);
  1209. X        }
  1210. X        else
  1211. X        {
  1212. X        /* Hatch Pattern */
  1213. X        /* nmul gives angle, ny is merely a flag */
  1214. X        nx = geth (pltin);
  1215. X        if (nx <= 0 || nx * 2 > NHATCH)
  1216. X            ERR (FATAL, name, "bad numhatch %d (max %d/2, min 1)", nx, NHATCH);
  1217. X        ipat = geth (pltin) + 1;
  1218. X        if (ipat > NPAT || ipat < 1)
  1219. X            ERR (FATAL, name, "bad pattern number %d (max %d, min 1)", ipat, NPAT);
  1220. X        /*
  1221. X         * Free up pattern that may already be there 
  1222. X         */
  1223. X        if (pat[ipat] .patbits != NULL)
  1224. X        {
  1225. X            free ((char *) pat[ipat] .patbits);
  1226. X        }
  1227. X        if ((ptr = (int *) malloc ((unsigned) (nx * 4 * 2 * sizeof (int)))) == NULL)
  1228. X            ERR (FATAL, name, "cannot alloc memory to load pattern");
  1229. X        pat[ipat] .patbits = ptr;
  1230. X
  1231. X        for (i = 0; i < nx * 2; i++)
  1232. X        {
  1233. X            hafat[i] = geth (pltin);
  1234. X            if (hafat[i] >= 0)
  1235. X            {
  1236. X            hafat[i] = fatmult * (fatbase + hafat[i]);
  1237. X            }
  1238. X            k = geth (pltin);
  1239. X            if (k > MAX_COL || k < 0)
  1240. X            {
  1241. X            ERR (WARN, name, "bad color number in hatch %d (max %d, min 0)",
  1242. X                 k, MAX_COL);
  1243. X            k = DEFAULT_COLOR;
  1244. X            }
  1245. X            hacol[i] = COLOR_MAP (k);
  1246. X            haoff[i] = geth (pltin) * patternmult * pixels_per_inch / RPERIN;
  1247. X            hasiz[i] = geth (pltin);
  1248. X        }
  1249. X        /*
  1250. X         * Find the smallest hatch interval. 1/2 that, and then force
  1251. X         * everything to be a multiple of that. If this were not
  1252. X         * done, then hatch intervals that originally differed by
  1253. X         * some simple fraction might end up slightly off, causing
  1254. X         * very unsightly beats. 
  1255. X         */
  1256. X        /*
  1257. X         * Upper quantization limit of 1/10 inch 
  1258. X         */
  1259. X        k = (RPERIN / 10) * 2;
  1260. X        for (i = 0; i < nx * 2; i++)
  1261. X        {
  1262. X            if (hasiz[i] > 0 && hasiz[i] < k)
  1263. X            k = hasiz[i];
  1264. X        }
  1265. X        j = k * (patternmult * pixels_per_inch / RPERIN) / 2.;
  1266. X        if (j < 1)
  1267. X            j = 1;
  1268. X        for (i = 0; i < nx * 2; i++)
  1269. X        {
  1270. X            hasiz[i] = ((int) ((hasiz[i] * 2) / k)) * j;
  1271. X        }
  1272. X        /*
  1273. X         * The above algorithm also means that you can't have a hatch
  1274. X         * pattern come out on any device with a repetition rate of
  1275. X         * faster than once per two pixels. 
  1276. X         */
  1277. X
  1278. X        for (i = 0; i < nx * 2; i++)
  1279. X        {
  1280. X/*
  1281. X * Make sure haoff < hasiz
  1282. X */
  1283. X            if (haoff[i] >= hasiz[i])
  1284. X            haoff[i] = 0;
  1285. X            *ptr++ = hafat[i];
  1286. X            *ptr++ = hacol[i];
  1287. X            *ptr++ = haoff[i];
  1288. X            *ptr++ = hasiz[i];
  1289. X        }
  1290. X        /*
  1291. X         * set numhatch and angle... dimensions are 2 * numhatch by 4
  1292. X         * . pat[ipat].xdim negative is a flag that this is a hatch
  1293. X         * pattern, not raster, and so must be treated differently. 
  1294. X         */
  1295. X        /*
  1296. X         * numhatch, with neg as flag for hatch numhatch = 0 is OK,
  1297. X         * because that means don't fill, same as nx = 0. 
  1298. X         */
  1299. X        pat[ipat] .xdim = -nx;
  1300. X        pat[ipat] .ydim = nmul;    /* angle */
  1301. X        }
  1302. X        break;
  1303. X    case VP_BIT_RASTER:    /* bit raster data */
  1304. X    case VP_BYTE_RASTER:    /* byte raster data */
  1305. X        ras_orient = geth (pltin);
  1306. X        if (rotate % 90 != 0)
  1307. X        {
  1308. X        if (wantras)
  1309. X        {
  1310. X            ERR (WARN, name, "Raster only possible in 4 principal orientations");
  1311. X            wantras = NO;
  1312. X        }
  1313. X        }
  1314. X        else
  1315. X        {
  1316. X        ras_orient += rotate / 90;
  1317. X        if (ras_orient >= 0)
  1318. X            ras_orient = ras_orient % 4;
  1319. X        else
  1320. X            ras_orient = ((ras_orient % 4) + 4) % 4;
  1321. X        }
  1322. X
  1323. X        /*
  1324. X         * They're on their honor to not go out of bounds. This check is
  1325. X         * just for things that HAVE to go out of bounds. 
  1326. X         */
  1327. X        ras_offset = geth (pltin);
  1328. X
  1329. X        if (ras_offset + 0 > MAX_COL || ras_offset + 255 < 0)
  1330. X        {
  1331. X        ERR (FATAL, name, "Absurd raster offset %d", ras_offset);
  1332. X        }
  1333. X
  1334. X        xvr_min = geth (pltin);
  1335. X        yvr_min = geth (pltin);
  1336. X        xvr_max = geth (pltin);
  1337. X        yvr_max = geth (pltin);
  1338. X        vptodevw (xvr_min, yvr_min, xvr_max, yvr_max,
  1339. X              &xvr_min, &yvr_min, &xvr_max, &yvr_max);
  1340. X        xvru_min = xvr_min;
  1341. X        yvru_min = yvr_min;
  1342. X        xvru_max = xvr_max;
  1343. X        yvru_max = yvr_max;
  1344. X
  1345. X        xpix = geth (pltin);
  1346. X        ypix = geth (pltin);
  1347. X
  1348. X        switch (ras_orient)
  1349. X        {
  1350. X        case 0:
  1351. X        xrasmult = (float) xpix / (float) (xvr_max - xvr_min);
  1352. X        yrasmult = (float) ypix / (float) (yvr_max - yvr_min);
  1353. X        xvr_max--;
  1354. X        yvr_max--;
  1355. X        break;
  1356. X        case 1:
  1357. X        yrasmult = (float) ypix / (float) (xvr_max - xvr_min);
  1358. X        xrasmult = (float) xpix / (float) (yvr_max - yvr_min);
  1359. X        xvr_max--;
  1360. X        yvr_min++;
  1361. X        break;
  1362. X        case 2:
  1363. X        xrasmult = (float) xpix / (float) (xvr_max - xvr_min);
  1364. X        yrasmult = (float) ypix / (float) (yvr_max - yvr_min);
  1365. X        xvr_min++;
  1366. X        yvr_min++;
  1367. X        break;
  1368. X        case 3:
  1369. X        yrasmult = (float) ypix / (float) (xvr_max - xvr_min);
  1370. X        xrasmult = (float) xpix / (float) (yvr_max - yvr_min);
  1371. X        xvr_min++;
  1372. X        yvr_max--;
  1373. X        break;
  1374. X        }
  1375. X
  1376. X        if (wantras && smart_raster)
  1377. X        {
  1378. X        rasterline = (unsigned char *) malloc ((unsigned) ((xpix + 7 + 2) * sizeof (unsigned char)));
  1379. X        rasterline2 = (unsigned char *) malloc ((unsigned) ((xpix + 7 + 2) * sizeof (unsigned char)));
  1380. X        if (rasterline == NULL || rasterline2 == NULL)
  1381. X            ERR (FATAL, name, "cannot alloc memory to load raster line");
  1382. X
  1383. X        outraster = (unsigned char *) malloc ((unsigned) (xpix * ypix) * sizeof (unsigned char));
  1384. X        if (outraster == NULL)
  1385. X            ERR (FATAL, name, "cannot alloc memory to load raster image");
  1386. X
  1387. X/*
  1388. X * See whether we want to dither or not.
  1389. X * Dither if monochrome device and dithering has been asked for.
  1390. X * It's up to the device to decide whether to actually do this.
  1391. X */
  1392. X        dither_it = dither && mono;
  1393. X
  1394. X        /*
  1395. X         * Read in the Raster data for "Smart" devices, ie, those
  1396. X         * which can stretch (and dither) their own raster. 
  1397. X         */
  1398. X        num_rep = 0;
  1399. X        for (yrast = 0; yrast < ypix; yrast++)
  1400. X        {
  1401. X            /*
  1402. X             * Read in the next raster line, if we have a new one 
  1403. X             */
  1404. X            if (num_rep <= 0)
  1405. X            {
  1406. X            num_rep = geth (pltin);
  1407. X            if (num_rep <= 0)
  1408. X                ERR (FATAL, name, "Bad Raster line multiplier");
  1409. X            pos = 0;
  1410. X        new_pat:num_pat = geth (pltin);
  1411. X            num_byte = geth (pltin);
  1412. X            if (num_pat <= 0 || num_byte <= 0 ||
  1413. X                pos + num_pat * num_byte > xpix)
  1414. X                ERR (FATAL, name, "Raster line not length promised");
  1415. X
  1416. X            if (num_pat > 1)
  1417. X            {
  1418. X                if (dither_it)
  1419. X                {
  1420. X                READ_RASTER (
  1421. X                         rasterline2[j] = GREY_MAP (ras_offset + (int) fgetc (pltin)),
  1422. X                         rasterline2[j + jj] = GREY_MAP (ras_offset * ((ibyte & (001 << (7 - j))) != 0))
  1423. X                 );
  1424. X                }
  1425. X                else
  1426. X                {
  1427. X                READ_RASTER (
  1428. X                         rasterline2[j] = COLOR_MAP (ras_offset + (int) fgetc (pltin)),
  1429. X                         rasterline2[j + jj] = COLOR_MAP (ras_offset * ((ibyte & (001 << (7 - j))) != 0))
  1430. X                 );
  1431. X                }
  1432. X                for (j = 0; j < num_pat; j++)
  1433. X                {
  1434. X                for (k = 0; k < num_byte; k++)
  1435. X                {
  1436. X                    rasterline[pos] = rasterline2[k];
  1437. X                    pos++;
  1438. X                }
  1439. X                }
  1440. X            }
  1441. X            else
  1442. X            {
  1443. X                if (dither_it)
  1444. X                {
  1445. X                READ_RASTER (
  1446. X                         rasterline[pos + j] = GREY_MAP (ras_offset + (int) fgetc (pltin)),
  1447. X                         rasterline[pos + j + jj] = GREY_MAP (ras_offset * ((ibyte & (001 << (7 - j))) != 0))
  1448. X                 );
  1449. X                }
  1450. X                else
  1451. X                {
  1452. X                READ_RASTER (
  1453. X                         rasterline[pos + j] = COLOR_MAP (ras_offset + (int) fgetc (pltin)),
  1454. X                         rasterline[pos + j + jj] = COLOR_MAP (ras_offset * ((ibyte & (001 << (7 - j))) != 0))
  1455. X                 );
  1456. X                }
  1457. X                pos += num_byte;
  1458. X            }
  1459. X
  1460. X            if (pos < xpix)
  1461. X                goto new_pat;
  1462. X            if (pos != xpix)
  1463. X                ERR (FATAL, name, "Raster line not length promised");
  1464. X            }
  1465. X            num_rep--;
  1466. X            for (ii = 0; ii < xpix; ii++)
  1467. X            {
  1468. X            outraster[ii + yrast * xpix] = rasterline[ii];
  1469. X            }
  1470. X        }
  1471. X
  1472. X        /* Smart form */
  1473. X        dev.raster (xpix, ypix, xvr_min, yvr_min, xvr_max, yvr_max,
  1474. X                outraster, ras_orient, dither_it);
  1475. X
  1476. X        free ((char *) rasterline);
  1477. X        free ((char *) rasterline2);
  1478. X        free ((char *) outraster);
  1479. X        }
  1480. X        else
  1481. X        {
  1482. X        wlimit (xwmin, xwmax, &xvr_min, &xvr_max);
  1483. X        wlimit (ywmin, ywmax, &yvr_min, &yvr_max);
  1484. X
  1485. X        switch (ras_orient)
  1486. X        {
  1487. X        case 0:
  1488. X            xvr_max++;
  1489. X            yvr_max++;
  1490. X            xr_max = xvr_max - xvru_min;
  1491. X            xr_min = xvr_min - xvru_min;
  1492. X            yr_max = yvr_max - yvru_min;
  1493. X            yr_min = yvr_min - yvru_min;
  1494. X            yru_max = yvru_max - yvru_min;
  1495. X            break;
  1496. X        case 1:
  1497. X            xvr_max++;
  1498. X            yvr_min--;
  1499. X            xr_max = yvru_max - yvr_min;
  1500. X            xr_min = yvru_max - yvr_max;
  1501. X            yr_max = xvr_max - xvru_min;
  1502. X            yr_min = xvr_min - xvru_min;
  1503. X            yru_max = xvru_max - xvru_min;
  1504. X            break;
  1505. X        case 2:
  1506. X            xvr_min--;
  1507. X            yvr_min--;
  1508. X            xr_max = xvru_max - xvr_min;
  1509. X            xr_min = xvru_max - xvr_max;
  1510. X            yr_max = yvru_max - yvr_min;
  1511. X            yr_min = yvru_max - yvr_max;
  1512. X            yru_max = yvru_max - yvru_min;
  1513. X            break;
  1514. X        case 3:
  1515. X            xvr_min--;
  1516. X            yvr_max++;
  1517. X            xr_max = yvr_max - yvru_min;
  1518. X            xr_min = yvr_min - yvru_min;
  1519. X            yr_max = xvru_max - xvr_min;
  1520. X            yr_min = xvru_max - xvr_max;
  1521. X            yru_max = xvru_max - xvru_min;
  1522. X            break;
  1523. X        }
  1524. X        xru_min = 0;
  1525. X
  1526. X        if (yr_max < yr_min || xr_max < xr_min || !wantras)
  1527. X        {
  1528. X            /*
  1529. X             * We need to read through all the raster stuff, even if
  1530. X             * we never use it. 
  1531. X             */
  1532. X            yr_max = yr_min;
  1533. X            xr_max = xr_min;
  1534. X        }
  1535. X
  1536. X        rasterline = (unsigned char *) malloc ((unsigned) ((xpix + 7 + 2) * sizeof (unsigned char)));
  1537. X        rasterline2 = (unsigned char *) malloc ((unsigned) ((xpix + 7 + 2) * sizeof (unsigned char)));
  1538. X        if (rasterline == NULL || rasterline2 == NULL)
  1539. X            ERR (FATAL, name, "cannot alloc memory to load raster line");
  1540. X
  1541. X/*
  1542. X * See whether we need to dither or not.
  1543. X * Dither if monochrome device and dithering has been asked for,
  1544. X * Except if it is black-and-white bit raster already anyway.
  1545. X * For some reason putting "GREY_MAP" directly in the if makes a
  1546. X * syntax error. I think it is a compiler bug.
  1547. X */
  1548. X        dither_it = dither && mono;
  1549. X        if (dither_it && c == VP_BIT_RASTER)
  1550. X        {
  1551. X            j = GREY_MAP (0 * ras_offset);
  1552. X            k = GREY_MAP (1 * ras_offset);
  1553. X            if ((j == 0 || j == 255) && (k == 0 || k == 255))
  1554. X            dither_it = NO;
  1555. X        }
  1556. X
  1557. X        if (xr_max > xr_min)
  1558. X        {
  1559. X            outraster2 = (unsigned char *) malloc ((unsigned) ((xr_max - xr_min) * sizeof (char)));
  1560. X            if (dither_it)
  1561. X            {
  1562. X            outraster = (unsigned char *) malloc ((unsigned) ((xr_max - xr_min) * sizeof (char)));
  1563. X            }
  1564. X            else
  1565. X            {
  1566. X            outraster = outraster2;
  1567. X            }
  1568. X            if (outraster2 == NULL || outraster == NULL)
  1569. X            ERR (FATAL, name, "cannot alloc memory to load raster line");
  1570. X        }
  1571. X        else
  1572. X        {
  1573. X            outraster2 = NULL;
  1574. X            outraster = NULL;
  1575. X        }
  1576. X
  1577. X        /*
  1578. X         * Read in the Raster data 
  1579. X         */
  1580. X        lastrast = -1;
  1581. X        num_rep = 0;
  1582. X        for (i = yr_max - 1; i >= yr_min - 1; i--)
  1583. X        {
  1584. X            yrast = (yru_max - 1 - i) * yrasmult;
  1585. X            if (i == yr_min - 1)
  1586. X            {
  1587. X            /*
  1588. X             * Assure that the last bit of unused raster, if any,
  1589. X             * is read. This last time through the loop is a
  1590. X             * "dummy". 
  1591. X             */
  1592. X            yrast = ypix - 1;
  1593. X            }
  1594. X
  1595. X            for (ii = 0; ii < (yrast - lastrast); ii++)
  1596. X            {
  1597. X            /*
  1598. X             * Read in the next raster line, if we have a new one 
  1599. X             */
  1600. X            if (num_rep <= 0)
  1601. X            {
  1602. X                num_rep = geth (pltin);
  1603. X                if (num_rep <= 0)
  1604. X                ERR (FATAL, name, "Bad Raster line multiplier");
  1605. X                pos = 0;
  1606. X            new_pat2:num_pat = geth (pltin);
  1607. X                num_byte = geth (pltin);
  1608. X                if (num_pat <= 0 || num_byte <= 0 ||
  1609. X                pos + num_pat * num_byte > xpix)
  1610. X                ERR (FATAL, name, "Raster line not length promised");
  1611. X
  1612. X/*
  1613. X * Only bother with it if we're actually going to use it
  1614. X */
  1615. X                if (ii + num_rep >= yrast - lastrast
  1616. X                && xr_max > xr_min && i >= yr_min)
  1617. X                {
  1618. X                if (num_pat > 1)
  1619. X                {
  1620. X                    if (dither_it)
  1621. X                    {
  1622. X                    READ_RASTER (
  1623. X                             rasterline2[j] = GREY_MAP (ras_offset + (int) fgetc (pltin)),
  1624. X                             rasterline2[j + jj] = GREY_MAP (ras_offset * ((ibyte & (001 << (7 - j))) != 0))
  1625. X                     );
  1626. X                    }
  1627. X                    else
  1628. X                    {
  1629. X                    READ_RASTER (
  1630. X                             rasterline2[j] = COLOR_MAP (ras_offset + (int) fgetc (pltin)),
  1631. X                             rasterline2[j + jj] = COLOR_MAP (ras_offset * ((ibyte & (001 << (7 - j))) != 0))
  1632. X                     );
  1633. X                    }
  1634. X                    for (j = 0; j < num_pat; j++)
  1635. X                    {
  1636. X                    for (k = 0; k < num_byte; k++)
  1637. X                    {
  1638. X                        rasterline[pos] = rasterline2[k];
  1639. X                        pos++;
  1640. X                    }
  1641. X                    }
  1642. X                }
  1643. X                else
  1644. X                {
  1645. X                    if (dither_it)
  1646. X                    {
  1647. X                    READ_RASTER (
  1648. X                             rasterline[pos + j] = GREY_MAP (ras_offset + (int) fgetc (pltin)),
  1649. X                             rasterline[pos + j + jj] = GREY_MAP (ras_offset * ((ibyte & (001 << (7 - j))) != 0))
  1650. X                     );
  1651. X                    }
  1652. X                    else
  1653. X                    {
  1654. X                    READ_RASTER (
  1655. X                             rasterline[pos + j] = COLOR_MAP (ras_offset + (int) fgetc (pltin)),
  1656. X                             rasterline[pos + j + jj] = COLOR_MAP (ras_offset * ((ibyte & (001 << (7 - j))) != 0))
  1657. X                     );
  1658. X                    }
  1659. X                    pos += num_byte;
  1660. X                }
  1661. X                }
  1662. X                else
  1663. X                {
  1664. X/*
  1665. X * We're just going to turn right around and read another one,
  1666. X * So throw this away!
  1667. X */
  1668. X                if (c == VP_BYTE_RASTER)
  1669. X                {
  1670. X                    for (j = 0; j < num_byte; j++)
  1671. X                    {
  1672. X                    fgetc (pltin);
  1673. X                    }
  1674. X                }
  1675. X                else
  1676. X                {
  1677. X                    for (j = 0; j < num_byte; j += 8)
  1678. X                    {
  1679. X                    fgetc (pltin);
  1680. X                    }
  1681. X                }
  1682. X                pos += num_pat * num_byte;
  1683. X                }
  1684. X                if (pos < xpix)
  1685. X                goto new_pat2;
  1686. X                if (pos != xpix)
  1687. X                ERR (FATAL, name, "Raster line not length promised");
  1688. X
  1689. X                if (wantras && xr_max > xr_min && i >= yr_min)
  1690. X                {
  1691. X                for (j = xr_min; j < xr_max; j++)
  1692. X                {
  1693. X                    outraster2[j - xr_min] =
  1694. X                     rasterline[(int) ((j - xru_min) * xrasmult)];
  1695. X                }
  1696. X                }
  1697. X            }
  1698. X            num_rep--;
  1699. X            }
  1700. X            lastrast = yrast;
  1701. X
  1702. X            if (xr_max > xr_min && i >= yr_min)
  1703. X            {
  1704. X            if (dither_it)
  1705. X            {
  1706. X                dithline (outraster2, outraster, xr_max - xr_min, yr_max - 1 - i, dither);
  1707. X            }
  1708. X            /* Dumb forms */
  1709. X            switch (ras_orient)
  1710. X            {
  1711. X            case 0:
  1712. X                dev.raster (yr_max - 1 - i, yr_max - yr_min,
  1713. X                    xvr_min, i + yvru_min,
  1714. X                     xr_max - xr_min, ras_orient, outraster,
  1715. X                    0, 0);
  1716. X                break;
  1717. X            case 1:
  1718. X                dev.raster (yr_max - 1 - i, yr_max - yr_min,
  1719. X                    xvru_min + i, yvr_max,
  1720. X                     xr_max - xr_min, ras_orient, outraster,
  1721. X                    0, 0);
  1722. X                break;
  1723. X            case 2:
  1724. X                dev.raster (yr_max - 1 - i, yr_max - yr_min,
  1725. X                    xvr_max, yvru_max - i,
  1726. X                     xr_max - xr_min, ras_orient, outraster,
  1727. X                    0, 0);
  1728. X                break;
  1729. X            case 3:
  1730. X                dev.raster (yr_max - 1 - i, yr_max - yr_min,
  1731. X                    xvru_max - i, yvr_min,
  1732. X                     xr_max - xr_min, ras_orient, outraster,
  1733. X                    0, 0);
  1734. X                break;
  1735. X            }
  1736. X            }
  1737. X        }
  1738. X        free ((char *) rasterline);
  1739. X        free ((char *) rasterline2);
  1740. X        if (outraster2 != NULL)
  1741. X        {
  1742. X            free ((char *) outraster2);
  1743. X            if (dither_it)
  1744. X            free ((char *) outraster);
  1745. X        }
  1746. X        if (!wantras)
  1747. X        {
  1748. X            xxx[0] = xvru_min;
  1749. X            yyy[0] = yvru_min;
  1750. X            xxx[1] = xvru_min;
  1751. X            yyy[1] = yvru_max;
  1752. X            xxx[2] = xvru_max;
  1753. X            yyy[2] = yvru_max;
  1754. X            xxx[3] = xvru_max;
  1755. X            yyy[3] = yvru_min;
  1756. X            drawpolygon (4, xxx, yyy);
  1757. X        }
  1758. X        }
  1759. X        break;
  1760. X    case VP_MESSAGE:    /* Text message */
  1761. X        getvpstring ();
  1762. X        message (MESG_READY);
  1763. X        message (MESG_MESSAGE);
  1764. X        message (MESG_TEXT, txbuffer);
  1765. X        message (MESG_TEXT, CRLF);
  1766. X        message (MESG_DONE);
  1767. X        break;
  1768. X    case VP_SETDASH:
  1769. X        npts = geth (pltin);
  1770. X        if (npts > MAXDASH)
  1771. X        {
  1772. X        ERR (FATAL, name, "Too complicated a dash line pattern.");
  1773. X        }
  1774. X        dashon = npts;
  1775. X        k = 0;
  1776. X        dashsum = 0.;
  1777. X        for (ii = 0; ii < npts * 2; ii++)
  1778. X        {
  1779. X        dashes[ii] = dashscale * (float) geth (pltin) / RPERIN;
  1780. X        if (dashes[ii] < 0.)
  1781. X            ERR (FATAL, name, "Negative dash distance.");
  1782. X
  1783. X        if (dashes[ii] != 0.)
  1784. X            k = 1;
  1785. X
  1786. X        dashsum += dashes[ii];
  1787. X        }
  1788. X        if (!k)
  1789. X        dashon = NO;
  1790. X        dev.attributes (NEW_DASH, dashon, 0, 0, 0);
  1791. X        break;
  1792. X    default:        /* error */
  1793. X        ERR (FATAL, name,
  1794. X         "invalid VPLOT command decimal %d character %c",
  1795. X         (int) c, (char) c);
  1796. X        break;
  1797. X    }
  1798. X    }
  1799. End_of_file:
  1800. X/*
  1801. X * End of main while loop. Either fall out here or jump here when you hit
  1802. X * the end of the file somewhere.
  1803. X */
  1804. X
  1805. X    dev.close (CLOSE_FLUSH);    /* force last vector out */
  1806. X
  1807. X/*
  1808. X * End the group for this frame
  1809. X */
  1810. X    group_number--;
  1811. X    if (group_number != 0)
  1812. X    {
  1813. X    ERR (WARN, name,
  1814. X         "group left unclosed at end of file");
  1815. X    group_number = 0;
  1816. X    }
  1817. X    else
  1818. X    {
  1819. X    ii = dev.attributes (END_GROUP, group_number, 0, 0, 0);
  1820. X    if (ii == DOVPLOT_EXIT)
  1821. X        return;
  1822. X    if (ii != DOVPLOT_CONT)
  1823. X        ERR (WARN, name, "dev.attributes(END_GROUP,...) returned junk.");
  1824. X    }
  1825. X
  1826. X/*
  1827. X * Exit of dovplot
  1828. X */
  1829. X    return;
  1830. X}
  1831. X
  1832. X/*
  1833. X * reset variables that can be affected by vplot commands when
  1834. X * processing multiple plots, and don't stay set across pages
  1835. X */
  1836. reset ()
  1837. X{
  1838. int             ii, jj, kk;
  1839. X
  1840. X    xwmin = xWmin;        /* plot window parameters defaulted */
  1841. X    xwmax = xWmax;        /* to maximum size     */
  1842. X    ywmin = yWmin;
  1843. X    ywmax = yWmax;
  1844. X
  1845. X    reset_windows ();
  1846. X
  1847. X    fat = fatmult * (float) (fatbase);
  1848. X    dev.attributes (NEW_FAT, fat, 0, 0, 0);
  1849. X
  1850. X    if (cur_color != DEFAULT_COLOR)
  1851. X    {
  1852. X    need_devcolor = YES;
  1853. X    cur_color = DEFAULT_COLOR;
  1854. X    }
  1855. X
  1856. X    txalign.hor = TH_NORMAL;
  1857. X    txalign.ver = TV_NORMAL;
  1858. X    dev.attributes (NEW_ALIGN, txalign.hor, txalign.ver, 0, 0);
  1859. X
  1860. X    ii = -1;
  1861. X    jj = -1;
  1862. X    kk = -1;
  1863. X    if (txfont != default_txfont)
  1864. X    {
  1865. X    txfont = default_txfont;
  1866. X    ii = txfont;
  1867. X    }
  1868. X    if (txprec != default_txprec)
  1869. X    {
  1870. X    txprec = default_txprec;
  1871. X    jj = txprec;
  1872. X    }
  1873. X    if (txovly != default_txovly)
  1874. X    {
  1875. X    txovly = default_txovly;
  1876. X    kk = txovly;
  1877. X    }
  1878. X    dev.attributes (NEW_FONT, ii, jj, kk, 0);
  1879. X
  1880. X    dashon = NO;
  1881. X    dev.attributes (NEW_DASH, dashon, 0, 0, 0);
  1882. X
  1883. X    overlay = default_overlay;
  1884. X    dev.attributes (NEW_OVERLAY, overlay, 0, 0, 0);
  1885. X}
  1886. X
  1887. reset_windows ()
  1888. X{
  1889. extern int      xwmax_last, ywmax_last, xwmin_last, ywmin_last;
  1890. X
  1891. X    if (xwmax != xwmax_last || ywmax != ywmax_last
  1892. X    || xwmin != xwmin_last || ywmin != ywmin_last)
  1893. X    dev.attributes (SET_WINDOW, xwmin, ywmin, xwmax, ywmax);
  1894. X
  1895. X    xwmin_last = xwmin;
  1896. X    ywmin_last = ywmin;
  1897. X    xwmax_last = xwmax;
  1898. X    ywmax_last = ywmax;
  1899. X}
  1900. X
  1901. outline_window ()
  1902. X{
  1903. X    if (need_devcolor == YES || cur_color != DEFAULT_COLOR)
  1904. X    {
  1905. X    dev.attributes (SET_COLOR, DEFAULT_COLOR, 0, 0, 0);
  1906. X    need_devcolor = NO;
  1907. X    }
  1908. X    dev.vector (xwmin, ywmin, xwmax, ywmin, 0, 0);
  1909. X    dev.vector (xwmax, ywmin, xwmax, ywmax, 0, 0);
  1910. X    dev.vector (xwmax, ywmax, xwmin, ywmax, 0, 0);
  1911. X    dev.vector (xwmin, ywmax, xwmin, ywmin, 0, 0);
  1912. X    if (cur_color != DEFAULT_COLOR)
  1913. X    {
  1914. X    dev.attributes (SET_COLOR, cur_color, 0, 0, 0);
  1915. X    need_devcolor = NO;
  1916. X    }
  1917. X}
  1918. X
  1919. getvpstring ()
  1920. X{
  1921. char           *txptr;
  1922. int             ii;
  1923. X
  1924. X    txptr = txbuffer;
  1925. X
  1926. X    while (1)
  1927. X    {
  1928. X    ii = getc (pltin);
  1929. X
  1930. X    if (ii == EOF)
  1931. X    {
  1932. X        ERR (FATAL, name,
  1933. X         "Unexpected EOF encountered in Text string");
  1934. X    }
  1935. X
  1936. X    *txptr = ii;
  1937. X    txptr++;
  1938. X
  1939. X    if (ii == 0)
  1940. X    {
  1941. X        break;
  1942. X    }
  1943. X
  1944. X    if ((txptr - txbuffer) == txbuflen)
  1945. X    {
  1946. X        txbuffer = realloc (txbuffer, (unsigned) (txbuflen + TXBUFLEN));
  1947. X        txptr = txbuffer + txbuflen;
  1948. X        txbuflen += TXBUFLEN;
  1949. X    }
  1950. X    }
  1951. X    return;
  1952. X}
  1953. X
  1954. drawpolygon (npts, x, y)
  1955. X    int             npts, *x, *y;
  1956. X{
  1957. int             i, j;
  1958. struct vertex  *vertex;
  1959. static int      point;
  1960. X
  1961. X    j = 0;
  1962. X    if (npts > (vxbuflen - 1))
  1963. X    {
  1964. X    free ((char *) vxbuffer);
  1965. X    vxbuffer =
  1966. X     (struct vertex *) malloc ((unsigned) ((npts + 1) * sizeof (struct vertex)));
  1967. X    }
  1968. X    vertex = vxbuffer;
  1969. X    xnew = x[j];
  1970. X    ynew = y[j];
  1971. X    j++;
  1972. X    vertex->x = xnew;
  1973. X    vertex->y = ynew;
  1974. X    vertex->next = vertex + 1;
  1975. X    vertex++;
  1976. X    i = npts - 1;
  1977. X    while (i--)
  1978. X    {
  1979. X    vertex->x = x[j];
  1980. X    vertex->y = y[j];
  1981. X    j++;
  1982. X    if ((vertex->x != xnew) || (vertex->y != ynew))
  1983. X    {
  1984. X        xnew = vertex->x;
  1985. X        ynew = vertex->y;
  1986. X        vertex->next = vertex + 1;
  1987. X        vertex->last = vertex - 1;
  1988. X        vertex++;
  1989. X        continue;
  1990. X    }
  1991. X    npts--;
  1992. X    }
  1993. X    vertex--;
  1994. X    vxbuffer->last = vertex;
  1995. X    vertex->next = vxbuffer;
  1996. X
  1997. X    ipat = 0;
  1998. X    point = cur_color;
  1999. X    pat[ipat] .patbits = &point;
  2000. X    pat[ipat] .xdim = 1;
  2001. X    pat[ipat] .ydim = 1;
  2002. X    pat[ipat] .xdim_orig = 1;
  2003. X    pat[ipat] .ydim_orig = 1;
  2004. X    update_color ();
  2005. X    if (npts > 2)
  2006. X    {
  2007. X    if (shade)
  2008. X        dev.area (npts, vxbuffer);
  2009. X    else
  2010. X        vecoutline (vxbuffer);
  2011. X    }
  2012. X}
  2013. X
  2014. getpolygon (npts)
  2015. X    int             npts;
  2016. X{
  2017. int             i;
  2018. struct vertex  *vertex;
  2019. X
  2020. X    if (npts > (vxbuflen - 1))
  2021. X    {
  2022. X    free ((char *) vxbuffer);
  2023. X    vxbuffer =
  2024. X     (struct vertex *) malloc ((unsigned) ((npts + 1) * sizeof (struct vertex)));
  2025. X    }
  2026. X    vertex = vxbuffer;
  2027. X    GETXY (xnew, ynew);
  2028. X    vertex->x = xnew;
  2029. X    vertex->y = ynew;
  2030. X    vertex->next = vertex + 1;
  2031. X    vertex++;
  2032. X    i = npts - 1;
  2033. X    while (i--)
  2034. X    {
  2035. X    GETXY (vertex->x, vertex->y);
  2036. X    if ((vertex->x != xnew) || (vertex->y != ynew))
  2037. X    {
  2038. X        xnew = vertex->x;
  2039. X        ynew = vertex->y;
  2040. X        vertex->next = vertex + 1;
  2041. X        vertex->last = vertex - 1;
  2042. X        vertex++;
  2043. X        continue;
  2044. X    }
  2045. X    npts--;
  2046. X    }
  2047. X    vertex--;
  2048. X    vxbuffer->last = vertex;
  2049. X    vertex->next = vxbuffer;
  2050. X    return (npts);
  2051. X}
  2052. X
  2053. update_color ()
  2054. X{
  2055. X    if (need_devcolor)
  2056. X    {
  2057. X    dev.attributes (SET_COLOR, cur_color, 0, 0, 0);
  2058. X    need_devcolor = NO;
  2059. X    }
  2060. X}
  2061. X
  2062. getapoint ()
  2063. X{
  2064. X    while (1)
  2065. X    {
  2066. X    xret = dev_xmax + 1;
  2067. X    yret = dev_ymax + 1;
  2068. X    if ((int) dev.getpoint (controltty, &xret, &yret) ||
  2069. X        (xret > dev_xmax - 5 && yret > dev_ymax - 5))
  2070. X        break;
  2071. X    devtovpxy (xret, yret, &xret, &yret);
  2072. X    add_a_cor (interact, xret, yret);
  2073. X    }
  2074. X}
  2075. END_OF_FILE
  2076. if test 51559 -ne `wc -c <'Vplot_Kernel/filters/dovplot.c'`; then
  2077.     echo shar: \"'Vplot_Kernel/filters/dovplot.c'\" unpacked with wrong size!
  2078. fi
  2079. # end of 'Vplot_Kernel/filters/dovplot.c'
  2080. fi
  2081. echo shar: End of archive 24 \(of 24\).
  2082. cp /dev/null ark24isdone
  2083. MISSING=""
  2084. for I in 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 ; do
  2085.     if test ! -f ark${I}isdone ; then
  2086.     MISSING="${MISSING} ${I}"
  2087.     fi
  2088. done
  2089. if test "${MISSING}" = "" ; then
  2090.     echo You have unpacked all 24 archives.
  2091.     rm -f ark[1-9]isdone ark[1-9][0-9]isdone
  2092. else
  2093.     echo You still need to unpack the following archives:
  2094.     echo "        " ${MISSING}
  2095. fi
  2096. ##  End of shell archive.
  2097. exit 0
  2098.