home *** CD-ROM | disk | FTP | other *** search
/ ARM Club 3 / TheARMClub_PDCD3.iso / hensa / maths / plplot / plplot_2 / drivers / ps.c < prev    next >
Encoding:
C/C++ Source or Header  |  1996-03-31  |  16.2 KB  |  637 lines

  1. /* $Id: ps.c,v 1.29 1994/09/01 22:28:09 mjl Exp $
  2.  * $Log: ps.c,v $
  3.  * Revision 1.29  1994/09/01  22:28:09  mjl
  4.  * Fixed bug in current point update after state change.
  5.  *
  6.  * Revision 1.28  1994/08/27  03:40:32  mjl
  7.  * Fix to allow cmap1 color selections to appear in grayscale.  Contributed
  8.  * by Radey Shouman.
  9.  *
  10.  * Revision 1.27  1994/07/19  22:30:27  mjl
  11.  * All device drivers: enabling macro renamed to PLD_<driver>, where <driver>
  12.  * is xwin, ps, etc.  See plDevs.h for more detail.
  13.  *
  14.  * Revision 1.26  1994/07/12  19:14:41  mjl
  15.  * Fix to prevent postscript interpreter from forgetting the current point
  16.  * location after a color change.  I lost track of who contributed this.
  17.  *
  18.  * Revision 1.25  1994/06/30  17:52:25  mjl
  19.  * Made another pass to eliminate warnings when using gcc -Wall, especially
  20.  * those created by changing a PLINT from a long to an int.
  21.  *
  22.  * Revision 1.24  1994/05/07  03:00:04  mjl
  23.  * Changed all occurances of bgcolor to cmap0[0].
  24.  *
  25.  * Revision 1.23  1994/04/30  16:14:46  mjl
  26.  * Fixed format field (%ld instead of %d) or introduced casts where
  27.  * appropriate to eliminate warnings given by gcc -Wall.
  28.  *
  29.  * Revision 1.22  1994/03/23  06:44:26  mjl
  30.  * Added support for: color map 1 color selection, color map 0 or color map 1
  31.  * state change (palette change), polygon fills.  Changes to generated
  32.  * postscript code: now leaner and more robust, with less redundant
  33.  * instructions.  Is suitable for backward paging using ghostview!
  34.  *
  35.  * All drivers: cleaned up by eliminating extraneous includes (stdio.h and
  36.  * stdlib.h now included automatically by plplotP.h), extraneous clears
  37.  * of pls->fileset, pls->page, and pls->OutFile = NULL (now handled in
  38.  * driver interface or driver initialization as appropriate).  Special
  39.  * handling for malloc includes eliminated (no longer needed) and malloc
  40.  * prototypes fixed as necessary.
  41.  *
  42.  * Revision 1.21  1994/02/07  22:52:11  mjl
  43.  * Changed the default pen width to 3 so that the default output actually
  44.  * looks good.
  45.  *
  46.  * Revision 1.20  1993/12/08  06:08:20  mjl
  47.  * Fixes to work better with Lucid emacs hilite mode.
  48. */
  49.  
  50. /*    ps.c
  51.  
  52.     PLPLOT PostScript device driver.
  53. */
  54. #include "plDevs.h"
  55.  
  56. #ifdef PLD_ps
  57.  
  58. #include "plplotP.h"
  59. #include "drivers.h"
  60.  
  61. #include <string.h>
  62. #include <time.h>
  63.  
  64. /* Prototypes for functions in this file. */
  65.  
  66. static char  *ps_getdate    (void);
  67. static void  ps_init        (PLStream *);
  68. static void  fill_polygon    (PLStream *pls);
  69.  
  70. /* top level declarations */
  71.  
  72. #define LINELENGTH      78
  73. #define COPIES          1
  74. #define XSIZE           540    /* 7.5 x 10 [inches] (72 points = 1 inch) */
  75. #define YSIZE           720
  76. #define ENLARGE         5
  77. #define XPSSIZE         ENLARGE*XSIZE
  78. #define YPSSIZE         ENLARGE*YSIZE
  79. #define XOFFSET         36    /* Offsets are .5 inches each */
  80. #define YOFFSET         36
  81. #define PSX             XPSSIZE-1
  82. #define PSY             YPSSIZE-1
  83.  
  84. #define OF        pls->OutFile
  85.  
  86. /* Struct to hold device-specific info. */
  87.  
  88. typedef struct {
  89.     PLFLT pxlx, pxly;
  90.     PLINT xold, yold;
  91.  
  92.     PLINT xmin, xmax, xlen;
  93.     PLINT ymin, ymax, ylen;
  94.  
  95.     PLINT xmin_dev, xmax_dev, xlen_dev;
  96.     PLINT ymin_dev, ymax_dev, ylen_dev;
  97.  
  98.     PLFLT xscale_dev, yscale_dev;
  99.  
  100.     int llx, lly, urx, ury, ptcnt;
  101. } PSDev;
  102.  
  103. static char outbuf[128];
  104.  
  105. /*----------------------------------------------------------------------*\
  106.  * plD_init_ps()
  107.  *
  108.  * Initialize device.
  109. \*----------------------------------------------------------------------*/
  110.  
  111. void
  112. plD_init_psm(PLStream *pls)
  113. {
  114.     if (!pls->colorset)
  115.     pls->color = 0;        /* no color by default: user can override */
  116.     ps_init(pls);
  117. }
  118.  
  119. void
  120. plD_init_psc(PLStream *pls)
  121. {
  122.     pls->color = 1;        /* always color */
  123.     ps_init(pls);
  124. }
  125.  
  126. static void
  127. ps_init(PLStream *pls)
  128. {
  129.     PSDev *dev;
  130.     float r, g, b;
  131.     float pxlx = YPSSIZE/LPAGE_X;
  132.     float pxly = XPSSIZE/LPAGE_Y;
  133.  
  134.     pls->termin = 0;        /* not an interactive terminal */
  135.     pls->icol0 = 1;
  136.     pls->bytecnt = 0;
  137.     pls->page = 0;
  138.     pls->family = 0;        /* I don't want to support familying here */
  139.     pls->dev_fill0 = 1;        /* Can do solid fills */
  140.  
  141.     if (pls->width == 0)    /* Is 0 if uninitialized */
  142.     pls->width = 3;
  143.  
  144. /* Prompt for a file name if not already set */
  145.  
  146.     plOpenFile(pls);
  147.  
  148. /* Allocate and initialize device-specific data */
  149.  
  150.     if (pls->dev != NULL)
  151.     free((void *) pls->dev);
  152.  
  153.     pls->dev = calloc(1, (size_t) sizeof(PSDev));
  154.     if (pls->dev == NULL)
  155.     plexit("ps_init: Out of memory.");
  156.  
  157.     dev = (PSDev *) pls->dev;
  158.  
  159.     dev->xold = UNDEFINED;
  160.     dev->yold = UNDEFINED;
  161.  
  162.     plP_setpxl(pxlx, pxly);
  163.  
  164.     dev->llx = XPSSIZE;
  165.     dev->lly = YPSSIZE;
  166.     dev->urx = 0;
  167.     dev->ury = 0;
  168.     dev->ptcnt = 0;
  169.  
  170. /* Rotate by 90 degrees since portrait mode addressing is used */
  171.  
  172.     dev->xmin = 0;
  173.     dev->ymin = 0;
  174.     dev->xmax = PSY;
  175.     dev->ymax = PSX;
  176.     dev->xlen = dev->xmax - dev->xmin;
  177.     dev->ylen = dev->ymax - dev->ymin;
  178.  
  179.     plP_setphy(dev->xmin, dev->xmax, dev->ymin, dev->ymax);
  180.  
  181. /* Header comments into PostScript file */
  182.  
  183.     fprintf(OF, "%%!PS-Adobe-2.0 EPSF-2.0\n");
  184.     fprintf(OF, "%%%%BoundingBox:         \n");
  185.     fprintf(OF, "%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n");
  186.  
  187.     fprintf(OF, "%%%%Title: PLPLOT Graph\n");
  188.     fprintf(OF, "%%%%Creator: PLPLOT Version 4.0\n");
  189.     fprintf(OF, "%%%%CreationDate: %s\n", ps_getdate());
  190.     fprintf(OF, "%%%%Pages: (atend)\n");
  191.     fprintf(OF, "%%%%EndComments\n\n");
  192.  
  193. /* Definitions */
  194. /* Save VM state */
  195.  
  196.     fprintf(OF, "/PSSave save def\n");
  197.  
  198. /* Define a dictionary and start using it */
  199.  
  200.     fprintf(OF, "/PSDict 200 dict def\n");
  201.     fprintf(OF, "PSDict begin\n");
  202.  
  203.     fprintf(OF, "/@restore /restore load def\n");
  204.     fprintf(OF, "/restore\n");
  205.     fprintf(OF, "   {vmstatus pop\n");
  206.     fprintf(OF, "    dup @VMused lt {pop @VMused} if\n");
  207.     fprintf(OF, "    exch pop exch @restore /@VMused exch def\n");
  208.     fprintf(OF, "   } def\n");
  209.     fprintf(OF, "/@pri\n");
  210.     fprintf(OF, "   {\n");
  211.     fprintf(OF, "    ( ) print\n");
  212.     fprintf(OF, "    (                                       ) cvs print\n");
  213.     fprintf(OF, "   } def\n");
  214.     fprintf(OF, "/@copies\n");    /* n @copies - */
  215.     fprintf(OF, "   {\n");
  216.     fprintf(OF, "    /#copies exch def\n");
  217.     fprintf(OF, "   } def\n");
  218.  
  219. /* - @start -  -- start everything */
  220.  
  221.     fprintf(OF, "/@start\n");
  222.     fprintf(OF, "   {\n");
  223.     fprintf(OF, "    vmstatus pop /@VMused exch def pop\n");
  224.     fprintf(OF, "   } def\n");
  225.  
  226. /* - @end -  -- finished */
  227.  
  228.     fprintf(OF, "/@end\n");
  229.     fprintf(OF, "   {flush\n");
  230.     fprintf(OF, "    end\n");
  231.     fprintf(OF, "    PSSave restore\n");
  232.     fprintf(OF, "   } def\n");
  233.  
  234. /* bop -  -- begin a new page */
  235.  
  236.     fprintf(OF, "/bop\n");
  237.     fprintf(OF, "   {\n");
  238.     fprintf(OF, "    /SaveImage save def\n");
  239.     if (pls->color) {
  240.     fprintf(OF, "    Z %d %d M %d %d D %d %d D %d %d D %d %d closepath\n",
  241.         0, 0, 0, PSY, PSX, PSY, PSX, 0, 0, 0);
  242.     r = ((float) pls->cmap0[0].r) / 255.;
  243.     g = ((float) pls->cmap0[0].g) / 255.;
  244.     b = ((float) pls->cmap0[0].b) / 255.;
  245.     fprintf(OF, "    %.4f %.4f %.4f setrgbcolor fill\n", r, g, b);
  246.     }
  247.     fprintf(OF, "   } def\n");
  248.  
  249. /* - eop -  -- end a page */
  250.  
  251.     fprintf(OF, "/eop\n");
  252.     fprintf(OF, "   {\n");
  253.     fprintf(OF, "    showpage\n");
  254.     fprintf(OF, "    SaveImage restore\n");
  255.     fprintf(OF, "   } def\n");
  256.  
  257. /* Set line parameters */
  258.  
  259.     fprintf(OF, "/@line\n");
  260.     fprintf(OF, "   {0 setlinecap\n");
  261.     fprintf(OF, "    0 setlinejoin\n");
  262.     fprintf(OF, "    1 setmiterlimit\n");
  263.     fprintf(OF, "   } def\n");
  264.  
  265. /* d @hsize -  horizontal clipping dimension */
  266.  
  267.     fprintf(OF, "/@hsize   {/hs exch def} def\n");
  268.     fprintf(OF, "/@vsize   {/vs exch def} def\n");
  269.  
  270. /* d @hoffset - shift for the plots */
  271.  
  272.     fprintf(OF, "/@hoffset {/ho exch def} def\n");
  273.     fprintf(OF, "/@voffset {/vo exch def} def\n");
  274.  
  275. /* Default line width */
  276.  
  277.     fprintf(OF, "/lw %d def\n", (int) pls->width);
  278.  
  279. /* Setup user specified offsets, scales, sizes for clipping */
  280.  
  281.     fprintf(OF, "/@SetPlot\n");
  282.     fprintf(OF, "   {\n");
  283.     fprintf(OF, "    ho vo translate\n");
  284.     fprintf(OF, "    XScale YScale scale\n");
  285.     fprintf(OF, "    lw setlinewidth\n");
  286.     fprintf(OF, "   } def\n");
  287.  
  288. /* Setup x & y scales */
  289.  
  290.     fprintf(OF, "/XScale\n");
  291.     fprintf(OF, "   {hs %d div} def\n", YPSSIZE);
  292.     fprintf(OF, "/YScale\n");
  293.     fprintf(OF, "   {vs %d div} def\n", XPSSIZE);
  294.  
  295. /* Macro definitions of common instructions, to keep output small */
  296.  
  297.     fprintf(OF, "/M {moveto} def\n");
  298.     fprintf(OF, "/D {lineto} def\n");
  299.     fprintf(OF, "/S {stroke} def\n");
  300.     fprintf(OF, "/Z {stroke newpath} def\n");
  301.     fprintf(OF, "/F {fill} def\n");
  302.     fprintf(OF, "/C {setrgbcolor} def\n");
  303.     fprintf(OF, "/G {setgray} def\n");
  304.     fprintf(OF, "/W {setlinewidth} def\n");
  305.  
  306. /* End of dictionary definition */
  307.  
  308.     fprintf(OF, "end\n\n");
  309.  
  310. /* Set up the plots */
  311.  
  312.     fprintf(OF, "PSDict begin\n");
  313.     fprintf(OF, "@start\n");
  314.     fprintf(OF, "%d @copies\n", COPIES);
  315.     fprintf(OF, "@line\n");
  316.     fprintf(OF, "%d @hsize\n", YSIZE);
  317.     fprintf(OF, "%d @vsize\n", XSIZE);
  318.     fprintf(OF, "%d @hoffset\n", YOFFSET);
  319.     fprintf(OF, "%d @voffset\n", XOFFSET);
  320.  
  321.     fprintf(OF, "@SetPlot\n\n");
  322. }
  323.  
  324. /*----------------------------------------------------------------------*\
  325.  * plD_line_ps()
  326.  *
  327.  * Draw a line in the current color from (x1,y1) to (x2,y2).
  328. \*----------------------------------------------------------------------*/
  329.  
  330. void
  331. plD_line_ps(PLStream *pls, short x1a, short y1a, short x2a, short y2a)
  332. {
  333.     PSDev *dev = (PSDev *) pls->dev;
  334.     int x1 = x1a, y1 = y1a, x2 = x2a, y2 = y2a;
  335.  
  336. /* Rotate by 90 degrees */
  337.  
  338.     plRotPhy(1, dev->xmin, dev->ymin, dev->xmax, dev->ymax, &x1, &y1);
  339.     plRotPhy(1, dev->xmin, dev->ymin, dev->xmax, dev->ymax, &x2, &y2);
  340.  
  341.     if (x1 == dev->xold && y1 == dev->yold && dev->ptcnt < 40) {
  342.     if (pls->linepos + 12 > LINELENGTH) {
  343.         putc('\n', OF);
  344.         pls->linepos = 0;
  345.     }
  346.     else
  347.         putc(' ', OF);
  348.  
  349.     sprintf(outbuf, "%d %d D", x2, y2);
  350.     dev->ptcnt++;
  351.     pls->linepos += 12;
  352.     }
  353.     else {
  354.     fprintf(OF, " Z\n");
  355.     pls->linepos = 0;
  356.  
  357.     sprintf(outbuf, "%d %d M %d %d D", x1, y1, x2, y2);
  358.     dev->llx = MIN(dev->llx, x1);
  359.     dev->lly = MIN(dev->lly, y1);
  360.     dev->urx = MAX(dev->urx, x1);
  361.     dev->ury = MAX(dev->ury, y1);
  362.     dev->ptcnt = 1;
  363.     pls->linepos += 24;
  364.     }
  365.     dev->llx = MIN(dev->llx, x2);
  366.     dev->lly = MIN(dev->lly, y2);
  367.     dev->urx = MAX(dev->urx, x2);
  368.     dev->ury = MAX(dev->ury, y2);
  369.  
  370.     fprintf(OF, "%s", outbuf);
  371.     pls->bytecnt += 1 + strlen(outbuf);
  372.     dev->xold = x2;
  373.     dev->yold = y2;
  374. }
  375.  
  376. /*----------------------------------------------------------------------*\
  377.  * plD_polyline_ps()
  378.  *
  379.  * Draw a polyline in the current color.
  380. \*----------------------------------------------------------------------*/
  381.  
  382. void
  383. plD_polyline_ps(PLStream *pls, short *xa, short *ya, PLINT npts)
  384. {
  385.     PLINT i;
  386.  
  387.     for (i = 0; i < npts - 1; i++)
  388.     plD_line_ps(pls, xa[i], ya[i], xa[i + 1], ya[i + 1]);
  389. }
  390.  
  391. /*----------------------------------------------------------------------*\
  392.  * plD_eop_ps()
  393.  *
  394.  * End of page.
  395. \*----------------------------------------------------------------------*/
  396.  
  397. void
  398. plD_eop_ps(PLStream *pls)
  399. {
  400.     fprintf(OF, " S\neop\n");
  401. }
  402.  
  403. /*----------------------------------------------------------------------*\
  404.  * plD_bop_ps()
  405.  *
  406.  * Set up for the next page.
  407. \*----------------------------------------------------------------------*/
  408.  
  409. void
  410. plD_bop_ps(PLStream *pls)
  411. {
  412.     PSDev *dev = (PSDev *) pls->dev;
  413.  
  414.     dev->xold = UNDEFINED;
  415.     dev->yold = UNDEFINED;
  416.  
  417.     pls->page++;
  418.     fprintf(OF, "%%%%Page: %d %d\n", (int) pls->page, (int) pls->page);
  419.     fprintf(OF, "bop\n");
  420.     pls->linepos = 0;
  421.  
  422. /* This ensures the color is set correctly at the beginning of each page */
  423.  
  424.     plD_state_ps(pls, PLSTATE_COLOR0);
  425. }
  426.  
  427. /*----------------------------------------------------------------------*\
  428.  * plD_tidy_ps()
  429.  *
  430.  * Close graphics file or otherwise clean up.
  431. \*----------------------------------------------------------------------*/
  432.  
  433. void
  434. plD_tidy_ps(PLStream *pls)
  435. {
  436. #ifdef __riscos
  437.     char *sys_string;
  438. #endif
  439.     PSDev *dev = (PSDev *) pls->dev;
  440.  
  441.     fprintf(OF, "\n%%%%Trailer\n");
  442.  
  443.     dev->llx /= ENLARGE;
  444.     dev->lly /= ENLARGE;
  445.     dev->urx /= ENLARGE;
  446.     dev->ury /= ENLARGE;
  447.     dev->llx += XOFFSET;
  448.     dev->lly += YOFFSET;
  449.     dev->urx += XOFFSET;
  450.     dev->ury += YOFFSET;
  451.  
  452. /* changed for correct Bounding boundaries Jan Thorbecke  okt 1993*/
  453. /* occurs from the integer truncation -- postscript uses fp arithmetic */
  454.  
  455.     dev->urx += 1;
  456.     dev->ury += 1;
  457.  
  458.     fprintf(OF, "%%%%Pages: %d\n", (int) pls->page);
  459.     fprintf(OF, "@end\n");
  460.  
  461. /* Backtrack to write the BoundingBox at the beginning */
  462. /* Some applications don't like it atend */
  463.  
  464.     rewind(OF);
  465.     fprintf(OF, "%%!PS-Adobe-2.0 EPSF-2.0\n");
  466.     fprintf(OF, "%%%%BoundingBox: %d %d %d %d\n",
  467.         dev->llx, dev->lly, dev->urx, dev->ury);
  468.     fclose(OF);
  469. #ifdef __riscos
  470.     sys_string=malloc(sizeof(pls->FileName)+15);
  471.     if (sys_string == NULL) {
  472.       plwarn("malloc failed - cannot change filetype to PS");
  473.     }
  474.     else {
  475.       sprintf(sys_string, "settype %s FF5", pls->FileName);
  476.       system(sys_string);
  477.     }
  478. #endif
  479. }
  480.  
  481. /*----------------------------------------------------------------------*\
  482.  * plD_state_ps()
  483.  *
  484.  * Handle change in PLStream state (color, pen width, fill attribute, etc).
  485. \*----------------------------------------------------------------------*/
  486.  
  487. void
  488. plD_state_ps(PLStream *pls, PLINT op)
  489. {
  490.     PSDev *dev = (PSDev *) pls->dev;
  491.  
  492.     switch (op) {
  493.  
  494.     case PLSTATE_WIDTH:
  495.     if (pls->width < 1 || pls->width > 10)
  496.         fprintf(stderr, "\nInvalid pen width selection.");
  497.     else
  498.         fprintf(OF, " S\n%d W", (int) pls->width);
  499.  
  500.     dev->xold = UNDEFINED;
  501.     dev->yold = UNDEFINED;
  502.     break;
  503.  
  504.     case PLSTATE_COLOR0:
  505.      if (! pls->color) {
  506.         fprintf(OF, " S\n%.4f G", (pls->icol0 ? 0.0 : 1.0));
  507.         break;
  508.     }
  509.     /* else fallthrough */
  510.     case PLSTATE_COLOR1:
  511.     if (pls->color) {
  512.         float r = ((float) pls->curcolor.r) / 255.0;
  513.         float g = ((float) pls->curcolor.g) / 255.0;
  514.         float b = ((float) pls->curcolor.b) / 255.0;
  515.  
  516.         fprintf(OF, " S\n%.4f %.4f %.4f C", r, g, b);
  517.     }
  518.     else {
  519.         float r = ((float) pls->curcolor.r) / 255.0;
  520.         fprintf(OF, " S\n%.4f G", 1.0 - r);
  521.     }
  522.     break;
  523.     }
  524.  
  525. /* Reinitialize current point location. */
  526.  
  527.     if (dev->xold != UNDEFINED && dev->yold != UNDEFINED) {
  528.     fprintf(OF, " %d %d M \n", (int)dev->xold, (int)dev->yold);
  529.     }
  530. }
  531.  
  532. /*----------------------------------------------------------------------*\
  533.  * plD_esc_ps()
  534.  *
  535.  * Escape function.
  536. \*----------------------------------------------------------------------*/
  537.  
  538. void
  539. plD_esc_ps(PLStream *pls, PLINT op, void *ptr)
  540. {
  541.     switch (op) {
  542.       case PLESC_FILL:
  543.     fill_polygon(pls);
  544.     break;
  545.     }
  546. }
  547.  
  548. /*----------------------------------------------------------------------*\
  549.  * fill_polygon()
  550.  *
  551.  * Fill polygon described in points pls->dev_x[] and pls->dev_y[].
  552.  * Only solid color fill supported.
  553. \*----------------------------------------------------------------------*/
  554.  
  555. static void
  556. fill_polygon(PLStream *pls)
  557. {
  558.     PSDev *dev = (PSDev *) pls->dev;
  559.     PLINT n, ix = 0, iy = 0;
  560.     int x, y;
  561.  
  562.     fprintf(OF, " Z\n");
  563.  
  564.     for (n = 0; n < pls->dev_npts; n++) {
  565.     x = pls->dev_x[ix++];
  566.     y = pls->dev_y[iy++];
  567.  
  568. /* Rotate by 90 degrees */
  569.  
  570.     plRotPhy(1, dev->xmin, dev->ymin, dev->xmax, dev->ymax, &x, &y);
  571.  
  572. /* First time through start with a x y moveto */
  573.  
  574.     if (n == 0) {
  575.         sprintf(outbuf, "%d %d M", x, y);
  576.         dev->llx = MIN(dev->llx, x);
  577.         dev->lly = MIN(dev->lly, y);
  578.         dev->urx = MAX(dev->urx, x);
  579.         dev->ury = MAX(dev->ury, y);
  580.         fprintf(OF, "%s", outbuf);
  581.         pls->bytecnt += strlen(outbuf);
  582.         continue;
  583.     }
  584.  
  585.     if (pls->linepos + 21 > LINELENGTH) {
  586.         putc('\n', OF);
  587.         pls->linepos = 0;
  588.     }
  589.     else
  590.         putc(' ', OF);
  591.  
  592.     pls->bytecnt++;
  593.  
  594.     sprintf(outbuf, "%d %d D", x, y);
  595.     dev->llx = MIN(dev->llx, x);
  596.     dev->lly = MIN(dev->lly, y);
  597.     dev->urx = MAX(dev->urx, x);
  598.     dev->ury = MAX(dev->ury, y);
  599.  
  600.     fprintf(OF, "%s", outbuf);
  601.     pls->bytecnt += strlen(outbuf);
  602.     pls->linepos += 21;
  603.     }
  604.     dev->xold = UNDEFINED;
  605.     dev->yold = UNDEFINED;
  606.     fprintf(OF, " F ");
  607. }
  608.  
  609. /*----------------------------------------------------------------------*\
  610.  * ps_getdate()
  611.  *
  612.  * Get the date and time
  613. \*----------------------------------------------------------------------*/
  614.  
  615. static char *
  616. ps_getdate(void)
  617. {
  618.     int len;
  619.     time_t t;
  620.     char *p;
  621.  
  622.     t = time((time_t *) 0);
  623.     p = ctime(&t);
  624.     len = strlen(p);
  625.     *(p + len - 1) = '\0';    /* zap the newline character */
  626.     return p;
  627. }
  628.  
  629. #else
  630. int
  631. pldummy_ps()
  632. {
  633.     return 0;
  634. }
  635.  
  636. #endif                /* PLD_ps */
  637.