home *** CD-ROM | disk | FTP | other *** search
/ Shareware Overload / ShartewareOverload.cdr / graf / macpnt1.zip / PRINTER.C < prev    next >
Text File  |  1987-01-16  |  10KB  |  433 lines

  1.  
  2.  
  3. /*
  4.  ***************************************************************
  5.  * PRINTER.C - routines to support the printer
  6.  *
  7.  *
  8.  * (c) Copyright 1987 by:
  9.  *
  10.  *          Computerwise Consulting Services
  11.  *          P.O. Box 813
  12.  *          McLean, VA 22101
  13.  *          (703) 280-2809
  14.  *
  15.  * All rights reserved.
  16.  *
  17.  * Permission is granted for personal use of this program, with the
  18.  * exception that the following potential users ARE EXPLICITLY DENIED
  19.  * PERMISSION TO RECEIVE, USE, OR TRANSFER THIS PROGRAM IN SOURCE OR
  20.  * OBJECT OR EXECUTABLE OR ANY OTHER FORM:
  21.  *
  22.  *     1) Lotus Development Corporation, and any employee thereof
  23.  *        or consultant thereto;
  24.  *
  25.  *     2) ADAPSO, and any firm which is a member thereof, or any
  26.  *        employee of such a firm.
  27.  *
  28.  * These two organizations have - in the opinion of CCS - acted as
  29.  * "software pirates" by continually and intentionally violating
  30.  * U.S. Copyright law, specifically by first "copy-protecting" software
  31.  * disks and then zealously prosecuting innocent users who exercised
  32.  * their rights under the law to make copies of their own property.
  33.  *
  34.  * Further, permission is granted to transfer this program only if
  35.  * it is transferred absolutely unmodified in any form.
  36.  *
  37.  ***************************************************************
  38.  */
  39.  
  40.  
  41.  
  42. /*
  43.  * Explicitly ask user for a printer type, and set print_type per his selection
  44.  */
  45.  
  46. ptype()
  47. {
  48.     static BYTE inline[255];
  49.     int i;
  50.     
  51.     mode(TEXT);                /* In case we're in graphics mode */
  52.  
  53.     fprintf(stderr, "What type of printer do you have?\n");
  54.     
  55.     for ( i = 0; i < NUMPRINT; i++ )
  56.         {
  57.         fprintf(stderr, "\n%-6s = %s", printers[i].name, printers[i].desc );
  58.         }
  59.         
  60.     fprintf(stderr, "\n\nPrinter = ");
  61.     inline[0] = '-';
  62.     gets( &inline[1] );
  63.     pswitch(inline);
  64. }
  65.  
  66.  
  67.  
  68. /*
  69.  * Send mem_image to the printer
  70.  */
  71.  
  72. print()
  73. {
  74.  
  75.     static BYTE graphics_data[MAC_HORIZ + 2];
  76.  
  77.     static BYTE masks[16] =
  78.         {
  79.         0xff, 0xfe, 0xfc, 0xf8, 0xf0, 0xe0, 0xc0, 0x80,        /* For normal bytes */
  80.         0xff, 0x7f, 0x3f, 0x1f, 0x0f, 0x07, 0x03, 0x01        /* For reversed bytes */
  81.         };
  82.  
  83.     BYTE mask;
  84.     unsigned line, pixel;        /* Where we're at */
  85.     struct _printer *p;        /* Our printer's info */
  86.     BYTE *s;
  87.     BYTE c;
  88.     int i;
  89.     int aborted;            /* Non-zero if he pressed a key to abort printout */
  90.  
  91.     /*
  92.      * Make sure that we have selected a printer
  93.      */
  94.  
  95.     while ( print_type == -1 )
  96.         {
  97.         ptype();
  98.         }
  99.  
  100.     p = &printers[print_type];        /* Point to its params */
  101.  
  102.     if ( p->ignore )
  103.         {
  104.         return;                /* We are to ignore this */
  105.         }
  106.  
  107.     print_error = 0;            /* Reset error flag */
  108.     aborted = 0;                /* We're not aborted yet! */
  109.     string( p->page_init );            /* Init the printer */
  110.  
  111.     /*
  112.      * Dump the image one print line (7 or 8 wires) at a time
  113.      */
  114.  
  115.     mask = 0xff;                /* Mask everything on for now */
  116.  
  117.     if ( p->delta == 7 )            /* Except lost bit in 7-wire data */
  118.         {
  119.         mask = (p->reversed) ? 0x7f : 0xfe;
  120.         }
  121.  
  122.     for ( line = 0; line < MAC_VERT; line += p->delta )
  123.         {
  124.  
  125.         if ( kbhit() )
  126.             {
  127.  
  128.             /*
  129.              * We are to cancel this printout, because
  130.              * he has pressed a key. Go through all of the
  131.              * CRLF's to get us to the bottom of the page,
  132.              * but don't waste time assembling graphics
  133.              * bytes that won't be printed.
  134.              */
  135.  
  136.             aborted = -1;
  137.             key();            /* Swallow his keypress */
  138.             }
  139.  
  140.  
  141.         /*
  142.          * If doing a wierd delta (like 7), we must not grab
  143.          * up to 6 lines after end of image. So we mask out
  144.          * any bits that come from lines MAC_VERT+. We do this by
  145.          * here figuring out a mask byte for this whole line,
  146.          * and applying it later.
  147.          */
  148.  
  149.         if ( line > 712 )
  150.             {
  151.             mask = masks[ (line - 712) + (p->reversed ? 8 : 0) ];
  152.             }
  153.  
  154.         /*
  155.          * Get a line full of pixels. When we're done, c will be
  156.          * zero if the entire line is zero.
  157.          */
  158.  
  159.         s = graphics_data;
  160.         c = 0;
  161.  
  162.         if ( !print_error && !aborted )
  163.             {
  164.             for ( pixel = 0; pixel < MAC_HORIZ; pixel++ )
  165.                 {
  166.                 c |= (*s++ = vslice(line, pixel, p->reversed) & mask);
  167.                 }
  168.             }
  169.  
  170.         /*
  171.          * Pass it to printer, per whatever method we're supposed
  172.          * to use. If this entire line is zero (blank), then don't
  173.          * bother.
  174.          */
  175.  
  176.         if ( c && !print_error && !aborted )
  177.             {
  178.             string( p->line_init );        /* Init printer for graphics data */
  179.  
  180.             if ( p->buffered == 1 )
  181.                 {
  182.  
  183.                 /*
  184.                  * line_init has taken care of everything. Just blast
  185.                  * all data out there.
  186.                  */
  187.  
  188.                 prints(MAC_HORIZ, graphics_data);
  189.                 }
  190.             else
  191.                 {
  192.  
  193.                 /*
  194.                  * line_init has merely put the printer into
  195.                  * graphics mode. The printer has no idea how
  196.                  * many bytes are coming. Send 'em one at a time,
  197.                  * checking for special editing as we do.
  198.                  */
  199.  
  200.                 for ( i = 0; i < MAC_HORIZ; i++ )
  201.                     {
  202.                     c = graphics_data[i];    /* Get next byte of graphics data */
  203.  
  204.                     switch(p->special)    /* Edit it properly */
  205.                         {
  206.                         case 1:
  207.  
  208.                             /*
  209.                              * The Data Products (boo!) will
  210.                              * interpret 0x03 as a command. So change
  211.                              * it to 0x03 0x03 to get it through as
  212.                              * a graphics data byte.
  213.                              */
  214.  
  215.                             if ( c == 3 )
  216.                                 {
  217.                                 printchar(3);
  218.                                 }
  219.  
  220.                             printchar(c);
  221.                             break;
  222.  
  223.                         default:
  224.                             printchar(c);
  225.                         }
  226.                     }
  227.                 }
  228.  
  229.             string(p->line_end);        /* Wrap up line */
  230.             }
  231.  
  232.         string(p->crlf);        /* Move to next line */
  233.         }
  234.  
  235.     /*
  236.      * Wrap up printed page
  237.      */
  238.  
  239.     string(p->wrapup);
  240.  
  241.     /*
  242.      * If we are in "print all files automatically" mode and we were
  243.      * aborted by a keypress, then pass this state back to the mainline
  244.      * so that it can exit.
  245.      */
  246.  
  247.     if ( aborted && print_all )
  248.         {
  249.         time2quit = -1;
  250.         }
  251.  
  252. }
  253.  
  254.  
  255.  
  256. /*
  257.  * Construct and return a one-byte vertical slice of mem_image, consisting
  258.  * of 1 bit from each of 8 consecutive screen lines. This is how many printers
  259.  * expect to see bit-image graphics.
  260.  *
  261.  * Input is the line number n (0 - 712) of the first of 8 lines, and a pixel
  262.  * offset p (0 - 575) within the line.
  263.  *
  264.  * Output is the vertical slice of those 8 lines at that pixel offset, as
  265.  * graphically illustrated:
  266.  *
  267.  *              pixel:  p   p+1  p+2  p+3  p+4  p+5  p+6  p+7  p+8  p+9
  268.  *                    +---+
  269.  * mem_image line n   | 1 |  1    1    1    1    1    1    1    0    0
  270.  *                n+1 | 1 |  1    1    1    1    1    1    1    0    0
  271.  *                n+2 | 0 |  0    0    1    1    0    0    0    0    0
  272.  *                n+3 | 0 |  0    0    1    1    0    0    0    0    0
  273.  *                n+4 | 0 |  0    0    1    1    0    0    0    0    0
  274.  *                n+5 | 0 |  0    0    1    1    0    0    0    0    0
  275.  *                n+6 | 0 |  0    0    1    1    0    0    0    0    0
  276.  *                n+7 | 0 |  0    0    1    1    0    0    0    0    0
  277.  *                    +---+
  278.  *                      ^
  279.  *                      |
  280.  *                      +--- Returned byte
  281.  *
  282.  * For printers which use this method, a printed output line consists of
  283.  * 576 bytes as sliced by this routine (with possible leading spacing to
  284.  * center the line on the page), preceeded by whatever escape codes are
  285.  * needed to put the printer into bit-image graphics mode for this line.
  286.  *
  287.  * NOTE: The byte returned by this routine can be oriented one of two ways:
  288.  *
  289.  *          1) With bit 7 being the topmost line's pixel, and bit 0 being
  290.  *             from the bottom line.
  291.  *
  292.  *          2) With bit 0 being the topmost line's pixel, and bit 7 being
  293.  *             from the bottom line.
  294.  *
  295.  * This depends upon the printer. Some expect data one way, some the other.
  296.  * If the arg "reverse" is zero, then you get the returned byte according
  297.  * to description (1) above. If "reverse" is non-zero, then the returned
  298.  * byte is reversed, and comes back per description (2) above.
  299.  *
  300.  */
  301.  
  302. BYTE vslice(n, p, reverse)
  303. int n;                /* Line number (0-712) of first of 8 lines */
  304. int p;                /* Pixel number (0-575) of slice within line */
  305. int reverse;            /* Non-zero to return reversed byte */
  306. {
  307.     int i;
  308.     BYTE result;
  309.     BYTE *ptr;
  310.     BYTE mask;
  311.     
  312.     ptr = &mem_image[n][p / 8];        /* What byte to look at */
  313.     mask = 1 << ( 7 - ( p & 7 ) );        /* What bit to look at */
  314.     result = 0;
  315.  
  316.     if (reverse)
  317.         {
  318.             
  319.         /*
  320.          * Produce a reversed byte
  321.          */
  322.  
  323.         for ( i = 0; i < 8; i++ )
  324.             {
  325.             result >>= 1;
  326.             if ( *ptr & mask ) result |= 0x80;
  327.             ptr += (MAC_HORIZ/8);            /* Move to next line, same byte */
  328.             }
  329.         }
  330.     else
  331.         {
  332.         
  333.         /*
  334.          * Produce a normal byte (not reversed)
  335.          */
  336.      
  337.         for ( i = 0; i < 8; i++ )
  338.             {
  339.             result <<= 1;
  340.             if ( *ptr & mask ) result |= 1;
  341.             ptr += (MAC_HORIZ/8);            /* Move to next line, same byte */
  342.             }
  343.         }
  344.         
  345.     return(result);
  346. }
  347.  
  348.  
  349.  
  350. /*
  351.  * Print n bytes, starting at s, to printer.
  352.  */
  353.  
  354. prints(n, s)
  355. unsigned n;            /* # bytes to do */
  356. BYTE *s;            /* Data to be sent */
  357. {
  358.     if ( !print_error )
  359.         {
  360.         while( n-- )
  361.             {
  362.             printchar(*s++);
  363.             }
  364.         }
  365. }
  366.  
  367.  
  368. /*
  369.  * Print string s on printer. String s is assumed to be standard C string,
  370.  * or a NULL.
  371.  */
  372.  
  373. string(s)
  374. BYTE *s;
  375. {
  376.     if ( s )
  377.         {
  378.         if ( !print_error ) prints( strlen(s), s );
  379.         }
  380. }
  381.  
  382.  
  383. /*
  384.  * Send char c to printer via ROM BIOS
  385.  */
  386.  
  387. printchar(c)
  388. BYTE c;
  389. {
  390.     if (print_error)
  391.         {
  392.         return;                /* Previous error occurred */
  393.         }
  394.  
  395.     inregs.x.dx = 0;            /* LPT1: */
  396.     inregs.h.ah = 0;            /* "Print AL" ROM BIOS func */
  397.     inregs.h.al = c;            /* Char to print */
  398.  
  399. again:
  400.     int86( 0x17, &inregs, &outregs);
  401.  
  402.     /*
  403.      * Check for error printing
  404.      */
  405.  
  406.     while ( outregs.h.ah & 1 )
  407.         {
  408.         if ( cur_mode != TEXT )
  409.             {
  410.             mode(TEXT);
  411.             }
  412.  
  413.         fprintf(stderr, "\nPrinter error. (C)ancel print or (R)etry: ");
  414.  
  415.         switch( key() )
  416.             {
  417.             case 0x2e63:            /* c = cancel */
  418.             case 0x2e43:            /* C = Cancel */
  419.  
  420.                 fprintf(stderr, "CANCEL");
  421.                 print_error = -1;
  422.                 return;
  423.  
  424.             case 0x1372:            /* r = retry */
  425.             case 0x1352:            /* R = Retry */
  426.  
  427.                 fprintf(stderr, "RETRY");
  428.                 goto again;
  429.             }
  430.         }
  431. }
  432.  
  433.