home *** CD-ROM | disk | FTP | other *** search
/ Club Amiga de Montreal - CAM / CAM_CD_1.iso / files / 380.lha / post_v1.1 / source / postband.c < prev    next >
Encoding:
C/C++ Source or Header  |  1990-06-10  |  19.3 KB  |  790 lines

  1. /* Band rendering print driver for Post V1.1.  File "postband.c"
  2.  * (C) Adrian Aylward 1989, 1990
  3.  *
  4.  * You may freely copy, use, and modify this file.
  5.  *
  6.  * This file is a PostScript program driver that splits a PostScript file
  7.  * that conforms to the structuring conventions and calls Post to print
  8.  * it in a series of bands, even if there is not enough memory for a full
  9.  * page buffer.  It is totally Amiga specific.
  10.  *
  11.  * The program was tested using Lattice C V5.05.  It has various Lattice
  12.  * dependencies.
  13.  */
  14.  
  15. # include <dos.h>
  16. # include <devices/printer.h>
  17. # include <devices/prtbase.h>
  18. # include <exec/exec.h>
  19. # include <exec/execbase.h>
  20. # include <exec/tasks.h>
  21. # include <graphics/gfx.h>
  22. # include <graphics/rastport.h>
  23. # include <proto/dos.h>
  24. # include <proto/exec.h>
  25. # include <stdio.h>
  26.  
  27. # include "postlib.h"
  28.  
  29. /* Assembler routines */
  30.  
  31. extern void insertbreak(void);
  32. extern void deletebreak(void);
  33. extern void insertftrap(void);
  34. extern void deleteftrap(void);
  35.  
  36. /* Routines defined and referenced only within this module */
  37.  
  38. extern void prints(BPTR fh, char *string);
  39. extern void errmsg(char *string);
  40. extern void setprinter(void);
  41. extern void setprintden(void);
  42. extern int  strtoint(char **sp, int *ip);
  43. extern void __saveds __asm copypage(register __d0 int num);
  44. extern void printpage(void);
  45. extern void splitpage(void);
  46.  
  47. /* External data (initialised to zero) */
  48.  
  49. int retcode, errcode, ioerror;
  50.  
  51. int arec;
  52.  
  53. BPTR errfh;
  54.  
  55. int prologue, trailer;
  56. FILE *printfile;
  57.  
  58. struct library *PSbase;
  59. struct PSparm parm;
  60.  
  61. struct BitMap bitmap;
  62. struct ColorMap colormap;
  63.  
  64. int propen, prden;
  65. struct IODRPReq prreq;
  66. struct PrinterData *prdata;
  67. struct PrinterExtendedData *prextdata;
  68. struct Preferences *prprefs;
  69. struct RastPort prrast;
  70. struct MsgPort *prport;
  71. ULONG prsig;
  72. UBYTE prstatus[2];
  73.  
  74. int breakset, ftrapset;
  75.  
  76. /* Colour tables.  The default color map type is a vector or UWORD RGB
  77.  * values.  The colours are inverted as we set a bit in the bitmap whenever
  78.  * we want to place a drop of (black or cyan/magenta/yellow) ink */
  79.  
  80. static UWORD bcolors[2] =  /* Black and white */
  81. {   0xfff, 0x000                /* White   black */
  82. };
  83.  
  84. static UWORD ccolors[16] = /* Colour (RGB or CMYK) */
  85. {   0xfff, 0x0ff, 0xf0f, 0x00f, /* White   cyan    magenta blue */
  86.     0xff0, 0x0f0, 0xf00, 0x000, /* Yellow  green   red     black */
  87.     0x000, 0x000, 0x000, 0x000, /* Black */
  88.     0x000, 0x000, 0x000, 0x000  /* Black */
  89. };
  90.  
  91. /* Arguments */
  92.  
  93. int argfilec;
  94. char *argprint, *argsize, *argmem;
  95. char *argfilev[5];
  96. char *argkey[] =
  97. {   "PRINT", "SIZE", "MEM", NULL };
  98.  
  99. /* Startup code */
  100.  
  101. extern void main(int argc, char **argv);
  102.  
  103. void _main(char *line)
  104. {   char *argv[32];
  105.     int argc;
  106.  
  107.     /* Parse the arguments to break words and strip quotes.  N.B. the
  108.      * main program can determine that the arument was quoted by inspecting
  109.      * the preceeding character */
  110.  
  111.     argc = 0;
  112.     if (line == NULL) goto endline;
  113.     for (;;)
  114.     {   while (*line == ' ' || *line == '\t' || *line == '\n') line++;
  115.         if (*line == 0) break;
  116.         if (argc == 32)
  117.         {   argc = 0;
  118.             goto endline;
  119.         }
  120.         if (*line == '"')
  121.         {   argv[argc] = ++line;
  122.             while (*line != '"')
  123.             {   if (*line == 0)
  124.                 {   argc = 0;
  125.                     goto endline;
  126.                 }
  127.                 line++;
  128.             }
  129.         }
  130.         else
  131.         {   argv[argc] = line;
  132.             while (*line != ' ' && *line != '\t' && *line != '\n')
  133.             {   if (*line == 0)
  134.                 {   argc++;
  135.                     goto endline;
  136.                 }
  137.                 line++;
  138.             }
  139.         }
  140.         *line++ = 0;
  141.         argc++;
  142.     }
  143. endline:
  144.  
  145.     /* Set up the standard input/output files */
  146.  
  147.     errfh = Open("*", MODE_OLDFILE);
  148.     if (errfh == NULL)
  149.     {   retcode = 20;
  150.         goto tidyexit;
  151.     }
  152.  
  153.     /* Call the main program  */
  154.  
  155.     main(argc, argv);
  156.  
  157.     /* Tidy up and exit */
  158.  
  159. tidyexit:
  160.     if (errfh) Close(errfh);
  161.  
  162.     XCEXIT(retcode);
  163. }
  164.  
  165. /* Main program */
  166.  
  167. void main(int argc, char **argv)
  168. {   char *s;
  169.     int *ip, i, ch;
  170.     int xsize, ysize, ssize, xden, yden, pden;
  171.  
  172.     /* Open the libraries */
  173.  
  174.     PSbase = OpenLibrary("post.library", 0);
  175.     if (PSbase == NULL)
  176.     {   errmsg("can't open post.library");
  177.         goto errorexit;
  178.     }
  179.  
  180.     /* Parse the arguments and keywords.  See the usage string below */
  181.  
  182.     argc--;
  183.     argv++;
  184.     if (argc == 1 && (strcmp(*argv, "?") == 0)) goto usage;
  185.  
  186.     while (argc--)
  187.     {   s = *argv++;
  188.         i = -1;
  189.         if (s[-1] != '"')
  190.             for (;;)
  191.             {   i++;
  192.                 if (argkey[i] == NULL)
  193.                 {   i = -1;
  194.                     break;
  195.                 }
  196.                 if (stricmp(s, argkey[i]) == 0) break;
  197.             }
  198.         switch (i)
  199.         {   case  0:    /* PRINT */
  200.                 if (argc == 0) goto badargs;
  201.                 argc--;
  202.                 argprint = *argv++;
  203.                 break;
  204.  
  205.             case  1:    /* SIZE */
  206.                 if (argc == 0) goto badargs;
  207.                 argc--;
  208.                 argsize = *argv++;
  209.                 break;
  210.  
  211.             case  2:    /* MEM */
  212.                 if (argc == 0) goto badargs;
  213.                 argc--;
  214.                 argmem = *argv++;
  215.                 break;
  216.  
  217.             default:
  218.                 if (argfilec == 5) goto badargs;
  219.                 argfilev[argfilec++] = s;
  220.         }
  221.     }
  222.     if (argprint == NULL) goto badargs;
  223.  
  224.     /* Get up the default page size from the printer preferences */
  225.  
  226.     bitmap.BytesPerRow = 1;
  227.     bitmap.Rows = 1;
  228.     bitmap.Flags = 0;
  229.     bitmap.Depth = parm.page.depth = 3;
  230.     setprinter();
  231.     if (prport == NULL)
  232.     {   errmsg("can't open printer device");
  233.         goto errorexit;
  234.     }
  235.     parm.page.ydir = -1;
  236.  
  237.     /* Parse the "SIZE xyd..s..p.bc." option. */
  238.  
  239.     xsize = ysize = ssize = xden = yden = pden = 0;
  240.     if (argsize)
  241.     {   s = argsize;
  242.         for (;;)
  243.         {   ch = *s++;
  244.             if (ch == 0) break;
  245.             ch = tolower(ch);
  246.             switch (ch)
  247.             {   case 'x':
  248.                     if (tolower(*s) == 'd')
  249.                     {   s++;
  250.                         ip = &xden;
  251.                     }
  252.                     else
  253.                         ip = &xsize;
  254.                     break;
  255.  
  256.                 case 'y':
  257.                     if (tolower(*s) == 'd')
  258.                     {   s++;
  259.                         ip = &yden;
  260.                     }
  261.                     else
  262.                         ip = &ysize;
  263.                     break;
  264.  
  265.                 case 's':
  266.                     ip = &ssize;
  267.                     break;
  268.  
  269.                 case 'p':
  270.                     ip = &pden;
  271.                     break;
  272.  
  273.                 case 'd':
  274.                 {   if (!strtoint(&s, &xden)) goto badvalue;
  275.                     yden = xden;
  276.                     continue;
  277.                 }
  278.  
  279.                 case 'b':
  280.                     parm.page.depth = 1;
  281.                     continue;
  282.  
  283.                 case 'c':
  284.                     ch = *s;
  285.                     if      (ch == '3')
  286.                     {   s++;
  287.                         parm.page.depth = 3;
  288.                     }
  289.                     else if (ch == '4')
  290.                     {   s++;
  291.                         parm.page.depth  = 4;
  292.                     }
  293.                     else
  294.                         parm.page.depth = 3;
  295.                     continue;
  296.  
  297.                 default:
  298.                     goto badvalue;
  299.             }
  300.             if (!strtoint(&s, ip)) goto badvalue;
  301.         }
  302.     }
  303.     if (xden != 0) parm.page.xden = xden;
  304.     if (yden != 0) parm.page.yden = yden;
  305.     if (xsize != 0) parm.page.xsize = xsize;
  306.     if (ysize != 0) parm.page.ysize = ysize;
  307.     if (pden != 0)
  308.     {   prden = pden;
  309.         setprintden();
  310.     }
  311.  
  312.     /* Set up the default memory sizes */
  313.  
  314.     parm.memvlen = 280000;
  315.     parm.memflen =  60000;
  316.     parm.memllen =  60000;
  317.     parm.memhlen =  20000;
  318.  
  319.     /* Parse the "MEM fhlv.." option */
  320.  
  321.     if (argmem)
  322.     {   s = argmem;
  323.         for (;;)
  324.         {   ch = *s++;
  325.             if (ch == 0) break;
  326.             ch = tolower(ch);
  327.             switch (ch)
  328.             {   case 'f':
  329.                     ip = &parm.memflen;
  330.                     break;
  331.  
  332.                 case 'h':
  333.                     ip = &parm.memhlen;
  334.                     break;
  335.  
  336.                 case 'l':
  337.                     ip = &parm.memllen;
  338.                     break;
  339.  
  340.                 case 'v':
  341.                     ip = &parm.memvlen;
  342.                     break;
  343.  
  344.                 default:
  345.                     goto badvalue;
  346.             }
  347.             if (!strtoint(&s, ip)) goto badvalue;
  348.         }
  349.     }
  350.  
  351.     /* Set up the color map according to the number of bitplanes */
  352.  
  353.     colormap.Count = 1 << parm.page.depth;
  354.     if (parm.page.depth == 1)
  355.         colormap.ColorTable = (APTR) bcolors;
  356.     else
  357.         colormap.ColorTable = (APTR) ccolors;
  358.  
  359.     parm.page.ybase = 0;
  360.     parm.page.yheight = parm.page.ysize;
  361.     if (ssize != 0 && ssize < parm.page.ysize) parm.page.ysize = ssize;
  362.     if (parm.page.xsize == 0 || parm.page.ysize == 0)
  363.     {   errmsg("page size not set in preferences");
  364.         goto errorexit;
  365.     }
  366.     parm.page.xbytes = (parm.page.xsize + 15) >> 3 & 0xfffffffe;
  367.     parm.page.len = parm.page.xbytes * parm.page.ysize;
  368.  
  369.     /* Allocate the page buffer */
  370.  
  371.     for (i= 0; i < parm.page.depth; i++)
  372.     {   if ((parm.page.buf[i] =
  373.                 AllocMem(parm.page.len, MEMF_PUBLIC|MEMF_CLEAR)) == NULL)
  374.         {   errmsg("can't get page buffer");
  375.             goto errorexit;
  376.         }
  377.     }
  378.  
  379.     /* Initialise the bitmap */
  380.  
  381.     bitmap.BytesPerRow = parm.page.xbytes;
  382.     bitmap.Rows = parm.page.ysize;
  383.     bitmap.Flags = 0;
  384.     bitmap.Depth = parm.page.depth;
  385.     memcpy((char *) bitmap.Planes, (char *) parm.page.buf,
  386.            sizeof bitmap.Planes);
  387.  
  388.     /* Open the print file and check the header */
  389.  
  390.     printfile = fopen(argprint, "r");
  391.     if (printfile == NULL)
  392.     {   errmsg("can't open print file\n");
  393.         goto errorexit;
  394.     }
  395.     s = "%!PS-Adobe-";
  396.     while (*s)
  397.     {   ch = fgetc(printfile);
  398.         if (ch != *s++) goto pferror;
  399.     }
  400.     for (;;)
  401.     {   ch = fgetc(printfile);
  402.         if (ch == '\n') break;
  403.         if (ch == EOF) goto pferror;
  404.     }
  405.     prologue = 1;
  406.     trailer = 0;
  407.  
  408.     /* Initialise for interpretation */
  409.  
  410.     insertbreak();
  411.     SetExcept(~0, SIGBREAKF_CTRL_C);
  412.     breakset = 1;
  413.     insertftrap();
  414.     ftrapset = 1;
  415.  
  416.     parm.copyfunc = (APTR) copypage;
  417.  
  418.     parm.infh = Input();
  419.     parm.outfh = Output();
  420.     parm.errfh = errfh;
  421.  
  422.     arec = PScreateact(&parm);
  423.     if (arec == 0)
  424.     {   errmsg("can't get memory");
  425.         goto errorexit;
  426.     }
  427.     if ((unsigned) arec <= errmax)
  428.     {   arec = 0;
  429.         retcode = 10;
  430.         goto tidyexit;
  431.     }
  432.  
  433.     /* Interpret the argument files */
  434.  
  435.     for (i = 0; i < argfilec; i++)
  436.         if (PSintstring(arec, argfilev[i],
  437.                         -1, PSFLAGFILE|PSFLAGCLEAR|PSFLAGERASE) != 0)
  438.         {   retcode = 10;
  439.             goto tidyexit;
  440.         }
  441.  
  442.     /* Interpret the prologue and each page */
  443.  
  444.     for (;;)
  445.     {   if (trailer) break;
  446.         splitpage();
  447.         if (retcode != 0) break;
  448.         if (PSintstring(arec,
  449.                         prologue ?
  450.             "(t:postband.ps) run" :
  451.             "currentband 1 sub{setband (t:postband.ps) run} for 0 setband",
  452.                         -1, PSFLAGSTRING) != 0)
  453.         {   retcode = 10;
  454.             break;
  455.         }
  456.         prologue = 0;
  457.     }
  458.  
  459.     goto tidyexit;
  460.  
  461.     /* File format error */
  462.  
  463. pferror:
  464.     errmsg("print file not PostScript conforming");
  465.     goto errorexit;
  466.  
  467.     /* Argument errors and usage query */
  468.  
  469. badargs:
  470.     errmsg("arguments bad, or value missing");
  471.     goto badusage;
  472.  
  473. badvalue:
  474.     errmsg("argument bad value");
  475.  
  476. badusage:
  477.     retcode = 20;
  478.  
  479. usage:
  480.     errmsg("usage:\n"
  481.     "    postband [files...] PRINT file [SIZE xyd..s..p.bc.] [MEM fhlv..]");
  482.     goto tidyexit;
  483.  
  484.     /* Tidy up and exit */
  485.  
  486. errorexit:
  487.     retcode = 20;
  488.  
  489. tidyexit:
  490.     DeleteFile("t:postband.ps");
  491.     if (printfile) fclose(printfile);
  492.  
  493.     if (breakset)
  494.     {   SetExcept(0, SIGBREAKF_CTRL_C);
  495.         deletebreak();
  496.         breakset = 0;
  497.     }
  498.     if (ftrapset)
  499.     {   deleteftrap();
  500.         ftrapset = 0;
  501.     }
  502.  
  503.     if (arec) PSdeleteact(arec);
  504.  
  505.     for (i = 0; i < parm.page.depth; i++)
  506.         if (parm.page.buf[i])
  507.         {   FreeMem(parm.page.buf[i], parm.page.len);
  508.             parm.page.buf[i] = NULL;
  509.         }
  510.  
  511.     if (propen) CloseDevice((struct IORequest *) &prreq);
  512.     if (prport) DeletePort(prport);
  513.  
  514.     if (PSbase)  CloseLibrary(PSbase);
  515. }
  516.  
  517. /* Print a string to a DOS file handle */
  518.  
  519. void prints(BPTR fh, char *string)
  520. {   Write(fh, string, strlen(string));
  521. }
  522.  
  523. /* Display an error message */
  524.  
  525. void errmsg(char *string)
  526. {   prints(errfh, "postband: ");
  527.     prints(errfh, string);
  528.     prints(errfh, "\n");
  529. }
  530.  
  531. /* Open the printer device and set up the page size */
  532.  
  533. void setprinter(void)
  534. {   if (propen == 0)
  535.     {   if (OpenDevice("printer.device", 0,
  536.                        (struct IOReqest *) &prreq, 0) != 0)
  537.             return;
  538.         propen = 1;
  539.     }
  540.     if (prport == NULL)
  541.     {   prport = CreatePort(NULL, 0);
  542.         if (prport == NULL) return;
  543.         prreq.io_Message.mn_ReplyPort = prport;
  544.         prsig = 1 << prport->mp_SigBit;
  545.         prdata = (struct PrinterData *) prreq.io_Device;
  546.         prextdata = &prdata->pd_SegmentData->ps_PED;
  547.         prprefs = &prdata->pd_Preferences;
  548.         prden = prprefs->PrintDensity;
  549.     }
  550.     if ((prprefs->PrintShade & SHADE_COLOR) == 0) parm.page.depth = 1;
  551.     setprintden();
  552. }
  553.  
  554. /* Set the printer density */
  555.  
  556. void setprintden(void)
  557. {   int pxsize, pysize;
  558.  
  559.     /* New density, call the device driver to change its extended data.  No
  560.      * error check */
  561.  
  562.     if (prden > 7) prden = 7;
  563.     if (prden != prprefs->PrintDensity)
  564.     {   prreq.io_Command = PRD_DUMPRPORT;
  565.         prrast.BitMap = &bitmap;
  566.         prreq.io_RastPort = &prrast;
  567.         prreq.io_ColorMap = (struct ColorMap *) &colormap;
  568.         prreq.io_Modes = 0;
  569.         prreq.io_SrcX = 0;
  570.         prreq.io_SrcY = 0;
  571.         prreq.io_SrcWidth = 1;
  572.         prreq.io_SrcHeight = 1;
  573.         prreq.io_DestCols = 1;
  574.         prreq.io_DestRows = 1;
  575.         prreq.io_Special = (SPECIAL_DENSITY1 * prden) | SPECIAL_NOPRINT;
  576.         prprefs->PrintDensity = prden;
  577.         DoIO((struct IORequest *) &prreq);
  578.     }
  579.  
  580.     /* Extract the page size and density from the printer device preferences
  581.      * and extended data */
  582.  
  583.     parm.page.xden = prextdata->ped_XDotsInch;
  584.     parm.page.yden = prextdata->ped_YDotsInch;
  585.     if      (prprefs->PrintFlags & PIXEL_DIMENSIONS)
  586.     {   pxsize = prprefs->PrintMaxWidth;
  587.         pysize = prprefs->PrintMaxHeight;
  588.     }
  589.     else if (prprefs->PrintFlags &
  590.                 (BOUNDED_DIMENSIONS|ABSOLUTE_DIMENSIONS))
  591.     {   pxsize = prprefs->PrintMaxWidth * parm.page.xden / 10;
  592.         pysize = prprefs->PrintMaxHeight * parm.page.yden / 10;
  593.     }
  594.     if (pxsize != 0) parm.page.xsize = pxsize;
  595.     if (pysize != 0) parm.page.ysize = pysize;
  596. }
  597.  
  598. /* String to integer conversion; digits only, with error check */
  599.  
  600. int strtoint(char **sp, int *ip)
  601. {   char *s = *sp;
  602.     int i = 0;
  603.     int ch;
  604.     for (;;)
  605.     {   ch = *s;
  606.         if (ch < '0' || ch > '9') break;
  607.         i = i * 10 + (ch - '0');
  608.         s++;
  609.     }
  610.     if (s == *sp)
  611.         return 0;
  612.     else
  613.     {   *sp = s;
  614.         *ip = i;
  615.         return 1;
  616.     }
  617. }
  618.  
  619. /* Signal an interrupt */
  620.  
  621. void __saveds sigint()
  622. {   PSsignalint(arec, 1);
  623. }
  624.  
  625. /* Signal a floating point error */
  626.  
  627. void __saveds sigfpe()
  628. {   PSsignalfpe(arec);
  629. }
  630.  
  631. /* Copy the page to the output */
  632.  
  633. void __saveds __asm copypage(register __d0 int num)
  634. {   ioerror = 0;
  635.     printpage();
  636.     if (ioerror) PSerror(arec, ioerror);
  637. }
  638.  
  639. /* Print the page */
  640.  
  641. void printpage()
  642. {   ULONG sig;
  643.  
  644.     /* Disable break exceptions so we can wait on the signal instead */
  645.  
  646.     SetExcept(0, SIGBREAKF_CTRL_C);
  647.     breakset = 0;
  648.  
  649.     /* First check the printer is ready */
  650.  
  651.     prreq.io_Command = PRD_QUERY;
  652.     ((struct IOStdReq *) &prreq)->io_Data = (APTR) prstatus;
  653.     if (DoIO((struct IORequest *) &prreq))
  654.     {   ioerror = errioerror;
  655.         return;
  656.     }
  657.     if (((struct IOStdReq *) &prreq)->io_Actual == 1 && prstatus[0] & 3 != 0)
  658.         errmsg("printer not ready (CTRL/C to abort)");
  659.  
  660.     /* Now dump the page */
  661.  
  662.     prrast.BitMap = &bitmap;
  663.     prreq.io_Command = PRD_DUMPRPORT;
  664.     prreq.io_RastPort = &prrast;
  665.     prreq.io_ColorMap = (struct ColorMap *) &colormap;
  666.     prreq.io_Modes = 0;
  667.     prreq.io_SrcX = 0;
  668.     prreq.io_SrcY = 0;
  669.     prreq.io_SrcWidth = parm.page.xsize;
  670.     prreq.io_SrcHeight = parm.page.ysize;
  671.     prreq.io_DestCols = parm.page.xsize;
  672.     prreq.io_DestRows = parm.page.ysize;
  673.     prreq.io_Special = (SPECIAL_DENSITY1 * prden) | SPECIAL_TRUSTME;
  674.     if (parm.page.ybase + parm.page.ysize >= parm.page.yheight)
  675.         prreq.io_SrcHeight = prreq.io_DestRows =
  676.                 parm.page.yheight - parm.page.ybase;
  677.     else
  678.         prreq.io_Special |= SPECIAL_NOFORMFEED;
  679.  
  680.     /* We use asynchronous IO so we can abort it with a CTRL/C */
  681.  
  682.     SendIO((struct IORequest *) &prreq);
  683.  
  684.     for (;;)
  685.     {   sig = Wait(prsig | SIGBREAKF_CTRL_C);
  686.         if (sig & SIGBREAKF_CTRL_C)
  687.         {   AbortIO((struct IORequest *) &prreq);
  688.             WaitIO((struct IORequest *) &prreq);
  689.             ioerror = errioerror;
  690.             break;
  691.         }
  692.         if (sig & prsig)
  693.         {   GetMsg(prport);
  694.             break;
  695.         }
  696.     }
  697.     if (prreq.io_Error != 0) ioerror = errioerror;
  698.  
  699.     /* Restore break exceptions */
  700.  
  701.     SetExcept(~0, SIGBREAKF_CTRL_C);
  702.     breakset = 1;
  703. }
  704.  
  705. /* Split the prologue or next page of the print file into the temp file */
  706.  
  707. void splitpage(void)
  708. {   FILE *tempfile;
  709.     char *s;
  710.     int matched, ch;
  711.  
  712.     tempfile = fopen("t:postband.ps", "w");
  713.     if (tempfile == NULL)
  714.     {   errmsg("can't open temporary file");
  715.         retcode = 20;
  716.         return;
  717.     }
  718.  
  719.     matched = 0;
  720.     for (;;)
  721.     {   ch = fgetc(printfile);
  722.  
  723.         /* Comment lines are not copied */
  724.  
  725.         if (ch == '%')
  726.         {   ch = fgetc(printfile);
  727.  
  728.             /* %% Comments may be a trailer */
  729.  
  730.             if (ch == '%')
  731.             {   ch = fgetc(printfile);
  732.                 if      (ch == 'P')
  733.                 {   s = "age:";
  734.                     while (*s)
  735.                     {   ch = fgetc(printfile);
  736.                         if (ch != *s++) goto nomatch;
  737.                     }
  738.                     matched = 1;
  739.                 }
  740.                 else if (ch == 'T')
  741.                 {   s = "railer";
  742.                     while (*s)
  743.                     {   ch = fgetc(printfile);
  744.                         if (ch != *s++) goto nomatch;
  745.                     }
  746.                     if (prologue) goto pferror;
  747.                     matched = 1;
  748.                     trailer = 1;
  749.                 }
  750.             }
  751.  
  752.             /* Skip the rest of the comment */
  753.  
  754. nomatch:    if (ch == EOF) goto pferror;
  755.             for (;;)
  756.             {   ch = fgetc(printfile);
  757.                 if (ch == '\n') break;
  758.                 if (ch == EOF) goto pferror;
  759.             }
  760.         }
  761.  
  762.         /* All other lines are copied to the temp file */
  763.  
  764.         else
  765.         {   for (;;)
  766.             {   if (ch == EOF) goto pferror;
  767.                 if (fputc(ch, tempfile) == EOF) goto tferror;
  768.                 if (ch == '\n') break;
  769.                 ch = fgetc(printfile);
  770.             }
  771.         }
  772.         if (matched) break;
  773.     }
  774.     if (fclose(tempfile) == EOF) goto tferror;
  775.     return;
  776.  
  777. pferror:
  778.     errmsg("print file not conforming or io error");
  779.     goto errorexit;
  780.  
  781. tferror:
  782.     errmsg("error with temporary file");
  783.  
  784. errorexit:
  785.     fclose(tempfile);
  786.     retcode = 20;
  787. }
  788.  
  789. /* End of file "postband.c" */
  790.