home *** CD-ROM | disk | FTP | other *** search
/ Club Amiga de Montreal - CAM / CAM_CD_1.iso / files / 531.lha / postdj / postdj.c < prev    next >
C/C++ Source or Header  |  1991-07-03  |  17KB  |  687 lines

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