home *** CD-ROM | disk | FTP | other *** search
/ Frozen Fish 1: Amiga / FrozenFish-Apr94.iso / bbs / alib / d5xx / d518 / post.lha / Post / post16s.lzh / postlj.c < prev    next >
C/C++ Source or Header  |  1991-04-17  |  16KB  |  639 lines

  1. /* LaserJet print driver for Post V1.6.  File "postlj.c"
  2.  * (C) Adrian Aylward 1990, 1991
  3.  *
  4.  * You may freely copy, use, and modify this file.
  5.  *
  6.  * This program prints PostScript files to a LaserJet.  It sends the output
  7.  * to the PAR: handler.  Page size and orientation are read from the command
  8.  * line.  There are no printer status checks; if the output hangs check your
  9.  * printer is ready.  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 <string.h>
  26. # include <stdio.h>
  27. # include <fcntl.h>
  28. # include <ios1.h>
  29.  
  30. # include "postlib.h"
  31.  
  32. /* Assembler routines */
  33.  
  34. extern void insertbreak(void);
  35. extern void deletebreak(void);
  36. extern void insertftrap(void);
  37. extern void deleteftrap(void);
  38.  
  39. /* Routines defined and referenced only within this module */
  40.  
  41. extern int  strtoint(char **sp, int *ip);
  42. extern void __saveds __asm copypage(register __d0 int num);
  43. extern void prtsetup(void);
  44. extern void prtreset(void);
  45. extern void prtdump(int copies);
  46. extern void prtdumpline(char *buf, int len);
  47.  
  48. /* Lattice startup */
  49.  
  50. extern struct UFB _ufbs[];
  51.  
  52. /* External data (initialised to zero) */
  53.  
  54. int retcode;
  55.  
  56. int arec;
  57.  
  58. BPTR errfh;
  59. FILE *parfp;
  60.  
  61. struct library *PSbase;
  62. struct PSparm parm;
  63.  
  64. int breakset, ftrapset;
  65.  
  66. /* Options */
  67.  
  68. # define DEFSIZE 3 /* A4 page size */
  69. # define DEFLAND 0 /* Portrait orientation */
  70. # define DEFCOMP 1 /* Allow graphics compression (LJ2P etc.) */
  71.  
  72. # define MAXSIZE 8
  73.  
  74. int optsize = DEFSIZE;
  75. int optland = DEFLAND;
  76. int optcomp = DEFCOMP;
  77. int optcopies;
  78. int optbeg, optend;
  79.  
  80. int pagenum;
  81.  
  82. /* Page size tables.
  83.  * (See Figures 2-2 and 2-3 in the LaserJet 2P Technical Reference Manual.)
  84.  *
  85.  *                     Let   Legal Exec  A4    COM10 Mon   C5    DL
  86.  */
  87.  
  88. int psize[MAXSIZE] = {    2,    3,    1,   26,   81,   80,   91,   90 };
  89.  
  90. int xsize[MAXSIZE] = { 2550, 2550, 2175, 2480, 1237, 1162, 1913, 1299 };
  91. int ysize[MAXSIZE] = { 3300, 4200, 3150, 3507, 2850, 2250, 2704, 2598 };
  92. int ppoff[MAXSIZE] = {   75,   75,   75,   71,   75,   75,   71,   71 };
  93. int ploff[MAXSIZE] = {   60,   60,   60,   59,   60,   60,   59,   59 };
  94.  
  95. char *showsize[MAXSIZE] = {"letter", "legal", "executive", "A4",
  96.                            "COM-10", "monarch", "C5", "DL" };
  97. char *showland[2] = {"portrait", "landscape" };
  98.  
  99. int compsize;
  100. char *compbuf;
  101.  
  102. /* Arguments */
  103.  
  104. char *argto = "par:";
  105. int argfilec, argmemc;
  106. char *argfilev[5], *argmemv[5];
  107. char *argkey[] =
  108. {   "TO", "MEM", NULL };
  109.  
  110. /* Startup code */
  111.  
  112. extern void main(int argc, char **argv);
  113.  
  114. void _main(char *line)
  115. {   char *argv[32];
  116.     int argc;
  117.  
  118.     /* Parse the arguments to break words and strip quotes.  N.B. the
  119.      * main program can determine that the arument was quoted by inspecting
  120.      * the preceeding character */
  121.  
  122.     argc = 0;
  123.     if (line == NULL) goto endline;
  124.     for (;;)
  125.     {   while (*line == ' ' || *line == '\t' || *line == '\n') line++;
  126.         if (*line == 0) break;
  127.         if (argc == 32)
  128.         {   argc = 0;
  129.             goto endline;
  130.         }
  131.         if (*line == '"')
  132.         {   argv[argc] = ++line;
  133.             while (*line != '"')
  134.             {   if (*line == 0)
  135.                 {   argc = 0;
  136.                     goto endline;
  137.                 }
  138.                 line++;
  139.             }
  140.         }
  141.         else
  142.         {   argv[argc] = line;
  143.             while (*line != ' ' && *line != '\t' && *line != '\n')
  144.             {   if (*line == 0)
  145.                 {   argc++;
  146.                     goto endline;
  147.                 }
  148.                 line++;
  149.             }
  150.         }
  151.         *line++ = 0;
  152.         argc++;
  153.     }
  154. endline:
  155.  
  156.     /* Set up the standard input/output files */
  157.  
  158.     errfh = Open("*", MODE_OLDFILE);
  159.     if (errfh == NULL)
  160.     {   retcode = 20;
  161.         goto tidyexit;
  162.     }
  163.     _ufbs[2].ufbfh = (long) errfh;
  164.     _ufbs[2].ufbflg |= UFB_WA|O_RAW|UFB_NC;
  165.     stderr->_file = 2;
  166.     stderr->_flag = _IOWRT;
  167.     setbuf(stderr, NULL);
  168.  
  169.     /* Call the main program  */
  170.  
  171.     main(argc, argv);
  172.  
  173.     /* Tidy up and exit */
  174.  
  175. tidyexit:
  176.     if (errfh) Close(errfh);
  177.  
  178.     XCEXIT(retcode);
  179. }
  180.  
  181. /* Main program */
  182.  
  183. void main(int argc, char **argv)
  184. {   char *s, *t;
  185.     int *ip, i, m, n, ch;
  186.  
  187.     /* Open the libraries */
  188.  
  189.     PSbase = OpenLibrary("post.library", POSTVERNO);
  190.     if (PSbase == NULL)
  191.     {   fprintf(stderr, "postlj: can't open post.library\n");
  192.         goto errorexit;
  193.     }
  194.  
  195.     /* Parse the arguments and keywords.  See the usage string below */
  196.  
  197.     argc--;
  198.     argv++;
  199.     if (argc == 0 || (argc == 1 && strcmp(*argv, "?") == 0)) goto usage;
  200.  
  201.     while (argc--)
  202.     {   s = *argv++;
  203.         i = -1;
  204.         if (s[-1] != '"')
  205.             if (*s == '-')
  206.             {   s++;
  207.                 while (t = s, ch = *s++)
  208.                 {   switch (ch)
  209.                     {   case 'S': case 's':
  210.                            m = MAXSIZE;
  211.                            ip = &optsize;
  212.                            break;
  213.     
  214.                         case 'L': case 'l':
  215.                            m = 2;
  216.                            ip = &optland;
  217.                            break;
  218.     
  219.                         case 'B': case 'b':
  220.                            m = 10000;
  221.                            ip = &optbeg;
  222.                            break;
  223.  
  224.                         case 'E': case 'e':
  225.                            m = 10000;
  226.                            ip = &optend;
  227.                            break;
  228.  
  229.                         case 'N': case 'n':
  230.                            m = 100;
  231.                            ip = &optcopies;
  232.                            break;
  233.     
  234.                         case 'C': case 'c':
  235.                            m = 2;
  236.                            ip = &optcomp;
  237.                            break;
  238.  
  239.                         default:
  240.                            fprintf(stderr,
  241.                                    "postlj: unknown option \"%c\"\n", ch);
  242.                            goto badusage;
  243.                     }
  244.                     if (!strtoint(&s, &i)) goto badvalue;
  245.                     if ((unsigned) i >= m)
  246.                     {   fprintf(stderr,
  247.                                 "postlj: option value out of range "
  248.                                 "(0-%d) \"%.*s\"\n", m - 1, s - t, t);
  249.                         goto errorexit;
  250.                     }
  251.                     *ip = i;
  252.                 }
  253.                 continue;
  254.             }
  255.             else
  256.                 for (;;)
  257.                 {   i++;
  258.                     if (argkey[i] == NULL)
  259.                     {   i = -1;
  260.                         break;
  261.                     }
  262.                     if (stricmp(s, argkey[i]) == 0) break;
  263.                 }
  264.         switch (i)
  265.         {   case  0:    /* TO */
  266.                 if (argc == 0) goto badargs;
  267.                 argc--;
  268.                 argto = *argv++;
  269.                 break;
  270.  
  271.             case  1:    /* MEM */
  272.                 if (argc == 0) goto badargs;
  273.                 argc--;
  274.                 if (argmemc == 5) goto badargs;
  275.                 argmemv[argmemc++] = *argv++;
  276.                 break;
  277.  
  278.             default:
  279.                 if (argfilec == 5) goto badargs;
  280.                 argfilev[argfilec++] = s;
  281.         }
  282.     }
  283.  
  284.     /* Parse the "MEM fhlv.." options */
  285.  
  286.     for (i = 0; i < argmemc; i++)
  287.     {   s = argmemv[i];
  288.         for (;;)
  289.         {   ch = *s++;
  290.             if (ch == 0) break;
  291.             ch = tolower(ch);
  292.             switch (ch)
  293.             {   case 'f':
  294.                     ip = &parm.memflen;
  295.                     break;
  296.  
  297.                 case 'h':
  298.                     ip = &parm.memhlen;
  299.                     break;
  300.  
  301.                 case 'l':
  302.                     ip = &parm.memllen;
  303.                     break;
  304.  
  305.                 case 'v':
  306.                     ip = &parm.memvlen;
  307.                     break;
  308.  
  309.                 default:
  310.                     goto badvalue;
  311.             }
  312.             if (!strtoint(&s, ip)) goto badvalue;
  313.         }
  314.     }
  315.  
  316.     /* Determine the page size */
  317.  
  318.     if (optland)
  319.     {   n = xsize[optsize];
  320.         m = ysize[optsize];
  321.     }
  322.     else
  323.     {   m = xsize[optsize];
  324.         n = ysize[optsize];
  325.     }
  326.     parm.page.depth = 1;
  327.     parm.page.xoff = parm.page.yoff = 0;
  328.     parm.page.xsize = m;
  329.     parm.page.ysize = n;
  330.     parm.page.xbytes = (parm.page.xsize + 7) >> 3;
  331.     parm.page.len = parm.page.xbytes * parm.page.ysize;
  332.     parm.page.ybase = 0;
  333.     parm.page.yheight = parm.page.ysize;
  334.     parm.page.xden = parm.page.yden = 300;
  335.     parm.page.ydir = -1;
  336.  
  337.     /* Allocate the page buffer */
  338.  
  339.     for (i = 0; i < parm.page.depth; i++)
  340.     {   if ((parm.page.buf[i] =
  341.                 AllocMem(parm.page.len, MEMF_PUBLIC|MEMF_CLEAR)) == NULL)
  342.         {   fprintf(stderr, "postlj: can't get page buffer\n");
  343.             goto errorexit;
  344.         }
  345.     }
  346.  
  347.     /* Allocate the print compression buffer */
  348.  
  349.     compsize = parm.page.xbytes + parm.page.xbytes / 128 + 2;
  350.     compbuf = AllocMem(compsize, MEMF_PUBLIC);
  351.     if (compbuf == NULL)
  352.     {   fprintf(stderr, "postlj: can't get memory\n");
  353.         goto errorexit;
  354.     }
  355.  
  356.     /* Open a file to the par: handler and initialise the printer */
  357.  
  358.     parfp = fopen(argto, "w");
  359.     if (parfp == NULL)
  360.     {   fprintf(stderr, "postlj: can't open %s\n", argto);
  361.         goto errorexit;
  362.     }
  363.     prtsetup();
  364.     if (ferror(parfp))
  365.     {   fprintf(stderr, "postlj: error writing printer file\n");
  366.         goto errorexit;
  367.     }
  368.  
  369.     /* Initialise for interpretation */
  370.  
  371.     insertbreak();
  372.     SetExcept(~0, SIGBREAKF_CTRL_C);
  373.     breakset = 1;
  374.     insertftrap();
  375.     ftrapset = 1;
  376.  
  377.     parm.copyfunc = (APTR) copypage;
  378.  
  379.     parm.infh = Input();
  380.     parm.outfh = Output();
  381.     parm.errfh = errfh;
  382.  
  383.     arec = PScreateact(&parm);
  384.     if (arec == 0)
  385.     {   fprintf(stderr, "postlj: can't get memory\n");
  386.         goto errorexit;
  387.     }
  388.     if ((unsigned) arec <= errmax)
  389.     {   arec = 0;
  390.         retcode = 10;
  391.         goto tidyexit;
  392.     }
  393.  
  394.     /* Interpret the argument files */
  395.  
  396.     fprintf(stderr, "postlj: running (%s, %s)\n",
  397.             showsize[optsize], showland[optland]);
  398.  
  399.     pagenum = 0;
  400.     for (i = 0; i < argfilec; i++)
  401.         if (PSintstring(arec, argfilev[i],
  402.                         -1, PSFLAGFILE|PSFLAGCLEAR|PSFLAGERASE) != 0)
  403.         {   retcode = 10;
  404.             goto tidyexit;
  405.         }
  406.  
  407.     if (ferror(parfp))
  408.     {   fprintf(stderr, "postlj: error writing printer file\n");
  409.         goto errorexit;
  410.     }
  411.     fprintf(stderr, "postlj: finished\n");
  412.     goto tidyexit;
  413.  
  414.     /* Argument errors and usage query */
  415.  
  416. badargs:
  417.     fprintf(stderr, "postlj: arguments bad, or value missing\n");
  418.     goto badusage;
  419.  
  420. badvalue:
  421.     fprintf(stderr, "postlj: argument bad value\n");
  422.  
  423. badusage:
  424.     retcode = 20;
  425.  
  426. usage:
  427.     fprintf(stderr, "postlj: usage:\n"
  428.     "    postlj -s.l.b.e.n.c. [files...] [TO tofile] [MEM fhlv..]\n");
  429.     goto tidyexit;
  430.  
  431.     /* Tidy up and exit */
  432.  
  433. errorexit:
  434.     retcode = 20;
  435.  
  436. tidyexit:
  437.     if (breakset)
  438.     {   SetExcept(0, SIGBREAKF_CTRL_C);
  439.         deletebreak();
  440.         breakset = 0;
  441.     }
  442.     if (ftrapset)
  443.     {   deleteftrap();
  444.         ftrapset = 0;
  445.     }
  446.  
  447.     if (arec) PSdeleteact(arec);
  448.  
  449.     if (parfp)
  450.     {   prtreset();
  451.         fclose(parfp);
  452.     }
  453.  
  454.     if (compbuf) FreeMem(compbuf, compsize);
  455.  
  456.     for (i = 0; i < parm.page.depth; i++)
  457.         if (parm.page.buf[i])
  458.         {   FreeMem(parm.page.buf[i], parm.page.len);
  459.             parm.page.buf[i] = NULL;
  460.         }
  461.  
  462.     if (PSbase) CloseLibrary(PSbase);
  463. }
  464.  
  465. /* String to integer conversion; digits only, with error check */
  466.  
  467. int strtoint(char **sp, int *ip)
  468. {   char *s = *sp;
  469.     int i = 0;
  470.     int ch;
  471.     for (;;)
  472.     {   ch = *s;
  473.         if (ch < '0' || ch > '9') break;
  474.         i = i * 10 + (ch - '0');
  475.         s++;
  476.     }
  477.     if (s == *sp)
  478.         return 0;
  479.     else
  480.     {   *sp = s;
  481.         *ip = i;
  482.         return 1;
  483.     }
  484. }
  485.  
  486. /* Signal an interrupt */
  487.  
  488. void __saveds sigint()
  489. {   PSsignalint(arec, 1);
  490. }
  491.  
  492. /* Signal a floating point error */
  493.  
  494. void __saveds sigfpe()
  495. {   PSsignalfpe(arec);
  496. }
  497.  
  498. /* Copy the page to the output */
  499.  
  500. void __saveds __asm copypage(register __d0 int num)
  501. {   pagenum++;
  502.     if ((optbeg == 0 || pagenum >= optbeg) &&
  503.         (optend == 0 || pagenum <= optend))
  504.     {   prtdump(optcopies == 0 ? num : optcopies);
  505.         if (ferror(parfp)) PSerror(arec, errioerror);
  506.     }
  507. }
  508.  
  509. /* Printer setup */
  510.  
  511. void prtsetup(void)
  512. {
  513.     /* Printer reset, Page size, Orientation, Perf skip off, Top Mgn 0 */
  514.  
  515.     fprintf(parfp, "\33E\33&l%da%do0l0E", psize[optsize], optland);
  516.  
  517.     /* Long edge offset, Short edge offset */
  518.  
  519.     if (optland)
  520.         fprintf(parfp, "\33&l%dz%dU",
  521.                 -(150 - ploff[optsize] * 720) / 300, 0);
  522.     else
  523.         fprintf(parfp, "\33&l%du%dZ",
  524.                  (150 - ppoff[optsize] * 720) / 300, 0);
  525. }
  526.  
  527. /* Printer reset */
  528.  
  529. void prtreset(void)
  530. {   fprintf(parfp, "\33E");
  531. }
  532.  
  533. /* Printer dump */
  534.  
  535. void prtdump(int num)
  536. {   char *buf;
  537.     int ysize;
  538.  
  539.     /* Set the number of copies */
  540.  
  541.     if (num == 0 || num > 99) num = 1;
  542.     fprintf(parfp, "\33&l%dX", num);
  543.  
  544.     /* Set cursor to (0,0), 300 dpi, aligned logical page, start graphics */
  545.  
  546.     fprintf(parfp, "\33*p0x0Y\33*t300R\33*r0f0A");
  547.  
  548.     /* Loop for the rows */
  549.  
  550.     buf = parm.page.buf[0];
  551.     ysize = parm.page.ysize;
  552.  
  553.     while (ysize--)
  554.     {   prtdumpline(buf, parm.page.xbytes);
  555.         buf += parm.page.xbytes;
  556.     }
  557.  
  558.     /* End graphics, form feed, reset number of copies */
  559.  
  560.     fprintf(parfp, "\33*rB\14\33&l1X");
  561. }
  562.  
  563. /* Dump a line of pixels */
  564.  
  565. void prtdumpline(char *buf, int len)
  566. {   char *ptr;
  567.     int b, c, l;
  568.  
  569.     /* Strip trailing zeros */
  570.  
  571.     while (len && buf[len - 1] == 0) len--;
  572.  
  573.     /* Compression */
  574.  
  575.     if (optcomp)
  576.     {   ptr = compbuf;
  577.         l = 0;
  578.         while (len--)
  579.         {   b = *buf++;                  /* Pick up a byte */
  580.             c = 1;
  581.             while (len && *buf == b && c < 128)
  582.             {   c++;
  583.                 buf++;
  584.                 len--;                   /* See if it begins a run */
  585.             }
  586.             if (c == 2 &&                /* If a two byte run */
  587.                 l > 0 &&                 /*  and preceeded by literals */
  588.                 l <= 125 &&              /*  and not more than 125 of them */
  589.                 (len <= 2 ||             /*  and no more than 2 bytes left */
  590.                  *buf != *(buf + 1)))    /*      or not followed by a run */
  591.             {   c = 1;                   /* Then make it a literal */
  592.                 buf--;
  593.                 len++;
  594.             }
  595.             if (c == 1)                  /* If not a run */
  596.             {   l++;                     /* Then it must be a literal */
  597.                 c = 0;
  598.             }
  599.             if (l > 0 &&                 /* If we have some literals */
  600.                 (c > 1 ||                /*  and beginning a run */
  601.                  l == 127 ||             /*  or reached 127 */
  602.                  len == 0))              /*  or no more bytes left */
  603.             {   *ptr++ = l - 1;          /* Then write out the literals */
  604.                 memcpy(ptr, buf - c - l, l);
  605.                 ptr += l;
  606.                 l = 0;
  607.             }
  608.             if (c > 1)                   /* If we have a run */
  609.             {   *ptr++ = 1 - c;          /* Then write it */
  610.                 *ptr++ = b;
  611.             }
  612.         }
  613.         len = ptr - compbuf;
  614.         fprintf(parfp, "\33*b2m%dW", len);
  615.         buf = compbuf;
  616.     }
  617.  
  618.     /* No compression */
  619.  
  620.     else
  621.         fprintf(parfp, "\33*b%dW", len);
  622.  
  623.     fwrite(buf, 1, len, parfp);
  624. }
  625.  
  626. /* Dummy stub routine */
  627.  
  628. void stub(void)
  629. {   return;
  630. }
  631.  
  632. /* Dummy check abort routine */
  633.  
  634. void chkabort(void)
  635. {   return;
  636. }
  637.  
  638. /* End of file "postlj.c" */
  639.