File: common\printer.c
    1 /*  Printer.c
    2  *      Simple screen printing functions for FRACTINT
    3  *      By Matt Saucier CIS: [72371,3101]      7/2/89
    4  *      "True-to-the-spirit" of FRACTINT, this code makes few checks that you
    5  *      have specified a valid resolution for the printer (just in case yours
    6  *      has more dots/line than the Standard HP and IBM/EPSON,
    7  *      (eg, Wide Carriage, etc.))
    8  *
    9  *      PostScript support by Scott Taylor [72401,410] / (DGWM18A)   10/8/90
   10  *      For PostScript, use 'printer=PostScript/resolution' where resolution
   11  *      is ANY NUMBER between 10 and 600. Common values: 300,150,100,75.
   12  *      Default resolution for PostScript is 150 pixels/inch.
   13  *      At 200 DPI, a fractal that is 640x480 prints as a 3.2"x2.4" picture.
   14  *      PostScript printer names:
   15  *
   16  *      PostScript/PS                   = Portrait printing
   17  *      PostScriptH/PostScriptL/PSH/PSL = Landscape printing
   18  *
   19  *      This code supports printers attached to a LPTx (1-3) parallel port.
   20  *      It also now supports serial printers AFTER THEY ARE CONFIGURED AND
   21  *      WORKING WITH THE DOS MODE COMMAND, eg. MODE COM1:9600,n,8,1 (for HP)
   22  *      (NOW you can also configure the serial port with the comport= command)
   23  *      Printing calls are made directly to the BIOS for DOS can't handle fast
   24  *      transfer of data to the HP.  (Or maybe visa-versa, HP can't handle the
   25  *      slow transfer of data from DOS)
   26  *
   27  *      I just added direct port access for COM1 and COM2 **ONLY**. This method
   28  *      does a little more testing than BIOS, and may work (especially on
   29  *      serial printer sharing devices) where the old method doesn't. I noticed
   30  *      maybe a 5% speed increase at 9600 baud. These are selected in the
   31  *      printer=.../.../31 for COM1 or 32 for COM2.
   32  *
   33  *      I also added direct parallel port access for LPT1 and LPT2 **ONLY**.
   34  *      This toggles the "INIT" line of the parallel port to reset the printer
   35  *      for each print session. It will also WAIT for a error / out of paper /
   36  *      not selected condition instead of quitting with an error.
   37  *
   38  *      Supported Printers:     Tested Ok:
   39  *       HP LaserJet
   40  *          LJ+,LJII             MDS
   41  *       Toshiba PageLaser       MDS (Set FRACTINT to use HP)
   42  *       IBM Graphics            MDS
   43  *       EPSON
   44  *          Models?              Untested.
   45  *       IBM LaserPrinter
   46  *          with PostScript      SWT
   47  *       HP Plotter              SWT
   48  *
   49  *      Future support to include OKI 20 (color) printer, and just about
   50  *      any printer you request.
   51  *
   52  *      Future modifications to include a more flexible, standard interface
   53  *      with the surrounding program, for easier portability to other
   54  *      programs.
   55  *
   56  * PostScript Styles:
   57  *  0  Dot
   58  *  1  Dot*            [Smoother]
   59  *  2  Inverted Dot
   60  *  3  Ring
   61  *  4  Inverted Ring
   62  *  5  Triangle        [45-45-90]
   63  *  6  Triangle*       [30-75-75]
   64  *  7  Grid
   65  *  8  Diamond
   66  *  9  Line
   67  * 10  Microwaves
   68  * 11  Ellipse
   69  * 12  RoundBox
   70  * 13  Custom
   71  * 14  Star
   72  * 15  Random
   73  * 16  Line*           [Not much different]
   74  *
   75  *  *  Alternate style
   76  *
   77 
   78  */
   79 
   80 
   81 #ifndef XFRACT
   82 #include <bios.h>
   83 #include <io.h>
   84 #endif
   85 
   86 #include <fcntl.h>
   87 #include <sys/types.h>
   88 #include <errno.h>
   89 
   90 #ifndef XFRACT
   91 #include <conio.h>
   92 #endif
   93 
   94 #ifndef USE_VARARGS
   95 #include <stdarg.h>
   96 #else
   97 #include <varargs.h>    98 #endif
   99 
  100 #include <string.h>
  101 
  102   /* see Fractint.c for a description of the "include"  hierarchy */
  103 #include "port.h"
  104 #include "prototyp.h"
  105 #include "fractype.h"
  106 
  107 /* macros for near-space-saving purposes */
  108 /* CAE 9211 changed these for BC++ */
  109 
  110 #define PRINTER_PRINTF1(X) {\
  111    static FCODE tmp[] = X;\
  112    Printer_printf(tmp);\
  113 }
  114 
  115 #define PRINTER_PRINTF2(X,Y) {\
  116    static FCODE tmp[] = X;\
  117    Printer_printf(tmp,(Y));\
  118 }
  119 #define PRINTER_PRINTF3(X,Y,Z) {\
  120    static FCODE tmp[] = X;\
  121    Printer_printf(tmp,(Y),(Z));\
  122 }
  123 #define PRINTER_PRINTF4(X,Y,Z,W) {\
  124    static FCODE tmp[] = X;\
  125    Printer_printf(tmp,(Y),(Z),(W));\
  126 }
  127 #define PRINTER_PRINTF5(X,Y,Z,W,V) {\
  128    static FCODE tmp[] = X;\
  129    Printer_printf(tmp,(Y),(Z),(W),(V));\
  130 }
  131 #define PRINTER_PRINTF6(X,Y,Z,W,V,U) {\
  132    static FCODE tmp[] = X;\
  133    Printer_printf(tmp,(Y),(Z),(W),(V),(U));\
  134 }
  135 #define PRINTER_PRINTF7(X,Y,Z,W,V,U,T) {\
  136    static FCODE tmp[] = X;\
  137    Printer_printf(tmp,(Y),(Z),(W),(V),(U),(T));\
  138 }
  139 
  140 /********      PROTOTYPES     ********/
  141 
  142 #ifndef USE_VARARGS
  143 static void Printer_printf(char far *fmt,...);
  146 #endif
  147 static int  _fastcall printer(int c);
  148 static void _fastcall print_title(int,int,char *);
  149 static void printer_reset(void);
  150 static void rleprolog(int x,int y);
  151 static void _fastcall graphics_init(int,int,char *);
  152 
  153 /********       GLOBALS       ********/
  154 
  155 int Printer_Resolution,        /* 75,100,150,300 for HP;                   */
  156                                /* 60,120,240 for IBM;                      */
  157                                /* 90 or 180 for the PaintJet;              */
  158                                /* 10-600 for PS                            */
  159                                /* 1-20 for Plotter                         */
  160     LPTNumber,                 /* ==1,2,3 LPTx; or 11,12,13,14 for COM1-4  */
  161                                /* 21,22 for direct port access for LPT1-2  */
  162                                /* 31,32 for direct port access for COM1-2  */
  163     Printer_Type,                      /* ==1 HP,
  164                                           ==2 IBM/EPSON,
  165                                           ==3 Epson color,
  166                                           ==4 HP PaintJet,
  167                                           ==5,6 PostScript,
  168                                           ==7 HP Plotter                   */
  169     Printer_Titleblock,       /* Print info about the fractal?             */
  170     Printer_Compress,         /* PostScript only - rle encode output       */
  171     Printer_ColorXlat,        /* PostScript only - invert colors           */
  172     Printer_SetScreen,        /* PostScript only - reprogram halftone ?    */
  173     Printer_SFrequency,       /* PostScript only - Halftone Frequency K    */
  174     Printer_SAngle,           /* PostScript only - Halftone angle     K    */
  175     Printer_SStyle,           /* PostScript only - Halftone style     K    */
  176     Printer_RFrequency,       /* PostScript only - Halftone Frequency R    */
  177     Printer_RAngle,           /* PostScript only - Halftone angle     R    */
  178     Printer_RStyle,           /* PostScript only - Halftone style     R    */
  179     Printer_GFrequency,       /* PostScript only - Halftone Frequency G    */
  180     Printer_GAngle,           /* PostScript only - Halftone angle     G    */
  181     Printer_GStyle,           /* PostScript only - Halftone style     G    */
  182     Printer_BFrequency,       /* PostScript only - Halftone Frequency B    */
  183     Printer_BAngle,           /* PostScript only - Halftone angle     B    */
  184     Printer_BStyle,           /* PostScript only - Halftone style     B    */
  185     Print_To_File,            /* Print to file toggle                      */
  186     EPSFileType,              /* EPSFileType -
  187                                                1 = well-behaved,
  188                                                2 = much less behaved,
  189                                                3 = not well behaved        */
  190     Printer_CRLF,             /* (0) CRLF (1) CR (2) LF                    */
  191     ColorPS;                  /* (0) B&W  (1) Color                        */
  192 int pj_width;
  193 double ci,ck;
  194 
  195 static int repeat, item, count, repeatitem, itembuf[128], rlebitsperitem,
  196     rlebitshift, bitspersample, rleitem, repeatcount, itemsperline, items,
  197     /* bitsperitem, */ bitshift2;
  198 /*
  199  *  The tables were copied from Lee Crocker's PGIF program, with
  200  *  the 8 undithered colors moved to the first 8 table slots.
  201  *
  202  *  This file contains various lookup tables used by PJGIF.  Patterns contains
  203  *  unsigned values representing each of the 330 HP PaintJet colors.  Each color
  204  *  at 90 DPI is composed of four dots in 8 colors.  Each hex digit of these
  205  *  unsigned values represents one of the four dots.  Although the PaintJet will
  206  *  produce these patterns automatically in 90 DPI mode, it is much faster to do
  207  *  it in software with the PaintJet in 8-color 180 DPI mode.
  208  *
  209  *  920501 Hans Wolfgang Schulze converted from printera.asm for xfractint.
  210  *         (hans@garfield.metal2.polymtl.ca)
  211  */
  212 
  213 static UIFCODE pj_patterns [] = {
  214       0x7777,0x0000,0x1111,0x2222,0x3333,0x4444,0x5555,0x6666,
  215              0x0001,0x0002,0x0003,0x0004,0x0005,0x0006,0x0007,
  216       0x0110,0x0120,0x0130,0x0140,0x0150,0x0160,0x0170,0x0220,
  217       0x0230,0x0240,0x0250,0x0260,0x0270,0x0330,0x0340,0x0350,
  218       0x0360,0x0370,0x0440,0x0450,0x0460,0x0470,0x0550,0x0560,
  219       0x0570,0x0660,0x0670,0x0770,0x0111,0x0112,0x0113,0x0114,
  220       0x0115,0x0116,0x0117,0x2012,0x0123,0x0124,0x0125,0x0126,
  221       0x0127,0x3013,0x0134,0x0135,0x0136,0x0137,0x4014,0x0145,
  222       0x0146,0x0147,0x5015,0x0156,0x0157,0x6016,0x0167,0x7017,
  223       0x0222,0x0223,0x0224,0x0225,0x0226,0x0227,0x3023,0x0234,
  224       0x0235,0x0236,0x0237,0x4024,0x0245,0x0246,0x0247,0x5025,
  225       0x0256,0x0257,0x6026,0x0267,0x7027,0x0333,0x0334,0x0335,
  226       0x0336,0x0337,0x4034,0x0345,0x0346,0x0347,0x5035,0x0356,
  227       0x0357,0x6036,0x0367,0x7037,0x0444,0x0445,0x0446,0x0447,
  228       0x5045,0x0456,0x0457,0x6046,0x0467,0x7047,0x0555,0x0556,
  229       0x0557,0x6056,0x0567,0x7057,0x0666,0x0667,0x7067,0x0777,
  230              0x1112,0x1113,0x1114,0x1115,0x1116,0x1117,0x2112,
  231       0x1123,0x2114,0x2115,0x2116,0x2117,0x3113,0x3114,0x3115,
  232       0x3116,0x3117,0x4114,0x4115,0x4116,0x4117,0x5115,0x5116,
  233       0x5117,0x6116,0x6117,0x7117,0x1222,0x1223,0x1224,0x1225,
  234       0x1226,0x1227,0x3123,0x1234,0x1235,0x1236,0x1237,0x4124,
  235       0x1245,0x1246,0x1247,0x5125,0x1256,0x1257,0x6126,0x1267,
  236       0x7127,0x1333,0x1334,0x1335,0x1336,0x1337,0x4134,0x1345,
  237       0x1346,0x1347,0x5135,0x1356,0x1357,0x6136,0x1367,0x7137,
  238       0x1444,0x1445,0x1446,0x1447,0x5145,0x1456,0x1457,0x6146,
  239       0x1467,0x7147,0x1555,0x1556,0x1557,0x6156,0x1567,0x7157,
  240       0x1666,0x1667,0x7167,0x1777,       0x2223,0x2224,0x2225,
  241       0x2226,0x2227,0x3223,0x3224,0x3225,0x3226,0x3227,0x4224,
  242       0x4225,0x4226,0x4227,0x5225,0x5226,0x5227,0x6226,0x6227,
  243       0x7227,0x2333,0x2334,0x2335,0x2336,0x2337,0x4234,0x2345,
  244       0x2346,0x2347,0x5235,0x2356,0x2357,0x6236,0x2367,0x7237,
  245       0x2444,0x2445,0x2446,0x2447,0x5245,0x2456,0x2457,0x6246,
  246       0x2467,0x7247,0x2555,0x2556,0x2557,0x6256,0x2567,0x7257,
  247       0x2666,0x2667,0x7267,0x2777,       0x3334,0x3335,0x3336,
  248       0x3337,0x4334,0x4335,0x4336,0x4337,0x5335,0x5336,0x5337,
  249       0x6336,0x6337,0x7337,0x3444,0x3445,0x3446,0x3447,0x5345,
  250       0x3456,0x3457,0x6346,0x3467,0x7347,0x3555,0x3556,0x3557,
  251       0x6356,0x3567,0x7357,0x3666,0x3667,0x7367,0x3777,
  252       0x4445,0x4446,0x4447,0x5445,0x5446,0x5447,0x6446,0x6447,
  253       0x7447,0x4555,0x4556,0x4557,0x6456,0x4567,0x7457,0x4666,
  254       0x4667,0x7467,0x4777,       0x5556,0x5557,0x6556,0x6557,
  255       0x7557,0x5666,0x5667,0x7567,0x5777,       0x6667,0x7667,
  256       0x6777};
  257 
  258 /*
  259  * The 3 tables below contain the red, green, and blue values (on a scale of
  260  *  0..255) of each of the 330 PaintJet colors.  These values are based on data
  261  *  generously provided by HP customer service.
  262  *       11 <- changed black's value from this, seemed wrong
  263  *         135 <- changed red's value from this
  264  *           11 <- changed blue's value from this
  265  */
  266 #ifndef XFRACT
  267 static BFCODE  pj_reds[] = {
  268         229,  2,145,  7,227,  9,136, 5,
  269              17, 10, 17, 10, 16, 10, 16, 29, 16, 32, 15, 30, 15, 31,  9,
  270          15, 10, 15,  9, 13, 37, 15, 32, 16, 36, 10, 15,  9, 13, 30, 15,
  271          31,  8, 13, 38, 62, 26, 68, 26, 63, 26, 68, 16, 35, 16, 33, 16,
  272          33, 77, 26, 69, 29, 77, 16, 31, 16, 31, 64, 27, 71, 16, 36, 81,
  273           9, 15, 10, 15,  8, 13, 37, 15, 31, 15, 33, 10, 15,  9, 13, 29,
  274          15, 28,  8, 12, 28, 98, 28, 79, 32, 94, 16, 34, 17, 35, 73, 30,
  275          82, 17, 43,101, 11, 15, 10, 13, 29, 15, 27,  9, 13, 25, 65, 27,
  276          71, 16, 35, 88,  7, 12, 39,110,     54,146, 53,136, 58,144, 29,
  277          57, 28, 53, 29, 56,159, 54,144, 61,160, 27, 51, 28, 52,135, 55,
  278         144, 30, 60,159, 14, 23, 15, 22, 14, 21, 64, 30, 58, 32, 64, 15,
  279          22, 15, 21, 54, 31, 56, 14, 22, 64,185, 59,160, 69,185, 29, 57,
  280          31, 60,145, 63,162, 33, 71,186, 15, 22, 16, 21, 50, 30, 52, 15,
  281          21, 54,134, 58,145, 30, 60,161, 15, 22, 69,187,     13,  9, 14,
  282           6, 11, 31, 14, 27, 12, 27, 10, 14,  9, 12, 24,  9, 23,  6,  9,
  283          22, 76, 23, 61, 25, 74, 15, 29, 14, 28, 55, 23, 62, 12, 30, 73,
  284          11, 15, 10, 12, 25, 14, 23,  8, 11, 20, 50, 22, 53, 13, 26, 61,
  285           5,  8, 21, 71,     71,189, 87,227, 30, 63, 32, 69,164, 76,190,
  286          37, 89,227, 15, 22, 14, 20, 54, 31, 57, 14, 21, 63,147, 67,163,
  287          33, 72,191, 13, 24, 94,228,     15, 10, 13, 26, 14, 23, 10, 13,
  288          20, 50, 23, 50, 15, 26, 52,  8, 11, 23, 65,     60,147, 32, 67,
  289         166, 14, 24, 77,194,      8, 32, 97};
  290 
  291 /*
  292  *                   11 <- changed black's value from this, seemed wrong
  293  *                           65 <- changed green from this
  294  */
  295 
  296 static BFCODE pj_greens[] = {
  297         224,  2, 20, 72,211, 10, 11, 55,
  298              12, 15, 19, 11, 11, 14, 17, 14, 18, 22, 12, 13, 16, 19, 24,
  299          29, 16, 17, 23, 27, 41, 17, 22, 29, 39, 11, 10, 14, 14, 11, 14,
  300          17, 21, 25, 40, 16, 21, 28, 14, 16, 19, 25, 28, 37, 18, 20, 26,
  301          33, 48, 20, 26, 33, 46, 13, 12, 16, 18, 14, 18, 22, 24, 30, 42,
  302          40, 49, 25, 27, 39, 50, 69, 27, 33, 48, 66, 17, 17, 24, 27, 19,
  303          28, 35, 38, 48, 68,100, 32, 46, 65, 98, 18, 22, 29, 36, 27, 39,
  304          54, 49, 71,105, 11, 10, 14, 12, 10, 14, 13, 20, 20, 25, 11, 15,
  305          18, 22, 29, 49, 36, 46, 69,111,     23, 31, 16, 19, 22, 28, 30,
  306          37, 20, 22, 28, 34, 54, 22, 29, 36, 53, 14, 15, 17, 19, 17, 19,
  307          26, 25, 32, 46, 43, 50, 27, 28, 41, 49, 68, 29, 37, 51, 68, 19,
  308          19, 25, 28, 22, 30, 36, 40, 47, 66,104, 35, 51, 68,105, 20, 24,
  309          31, 37, 30, 38, 56, 50, 69,103, 13, 12, 15, 14, 13, 15, 16, 21,
  310          21, 26, 14, 16, 22, 23, 28, 44, 35, 42, 62,102,     78, 40, 44,
  311          65, 78, 98, 43, 53, 76, 99, 26, 27, 36, 40, 29, 43, 50, 63, 75,
  312          99,136, 49, 69, 98,142, 28, 32, 42, 51, 39, 52, 73, 77,103,145,
  313          17, 17, 21, 21, 18, 22, 24, 34, 37, 43, 19, 23, 30, 40, 48, 69,
  314          62, 76,101,147,     72,113,145,218, 33, 42, 52, 71, 61, 77,116,
  315         105,148,221, 18, 17, 21, 23, 21, 26, 30, 37, 43, 64, 30, 35, 48,
  316          50, 69,115, 77, 99,149,224,     10, 13, 11, 10, 12, 11, 17, 16,
  317          15,  9, 11, 12, 17, 17, 22, 26, 27, 36, 61,     14, 18, 21, 26,
  318          48, 34, 41, 68,115,     69, 99,149};
  319 
  320 /*                    15 <- changed black's value from this, seemed wrong
  321  *                           56 <- changed green from this
  322  *                                          163 <- changed cyan from this
  323  */
  324 static BFCODE pj_blues[] = {
  325         216,  2, 34, 48, 33, 73, 64,168,
  326              18, 19, 18, 20, 19, 22, 21, 22, 24, 22, 26, 24, 27, 24, 27,
  327          24, 29, 27, 31, 29, 22, 27, 25, 30, 28, 31, 29, 33, 33, 28, 32,
  328          32, 41, 40, 46, 28, 32, 28, 34, 30, 36, 31, 35, 32, 38, 34, 41,
  329          35, 27, 35, 31, 39, 34, 40, 37, 44, 40, 34, 42, 37, 49, 47, 45,
  330          40, 36, 43, 40, 47, 43, 33, 40, 36, 45, 41, 44, 41, 49, 46, 40,
  331          49, 45, 58, 56, 58, 30, 38, 34, 44, 40, 42, 39, 49, 46, 38, 49,
  332          46, 59, 62, 67, 49, 46, 55, 52, 44, 55, 52, 64, 64, 66, 43, 55,
  333          53, 66, 70, 78, 87, 91,101,115,     39, 34, 42, 37, 43, 36, 45,
  334          38, 47, 42, 49, 43, 34, 41, 36, 44, 38, 49, 45, 52, 46, 40, 47,
  335          42, 56, 51, 45, 49, 45, 52, 48, 56, 50, 40, 47, 44, 52, 47, 54,
  336          51, 59, 55, 47, 58, 50, 66, 60, 56, 34, 44, 38, 48, 42, 52, 47,
  337          56, 50, 42, 51, 46, 64, 59, 57, 60, 56, 64, 61, 52, 61, 57, 72,
  338          67, 64, 48, 58, 53, 69, 65, 65, 87, 83, 87, 94,     53, 59, 55,
  339          64, 60, 46, 53, 49, 59, 54, 60, 56, 65, 62, 53, 62, 58, 76, 71,
  340          68, 41, 50, 45, 56, 51, 58, 53, 63, 59, 49, 60, 56, 74, 71, 71,
  341          66, 63, 73, 70, 60, 69, 67, 84, 81, 79, 55, 67, 64, 84, 81, 83,
  342         104,104,106,116,     32, 40, 53, 48, 54, 50, 61, 57, 46, 59, 56,
  343          76, 75, 80, 64, 59, 70, 67, 57, 69, 65, 83, 81, 85, 54, 68, 66,
  344          86, 88, 96,110,114,125,137,     71, 81, 78, 68, 77, 76, 93, 92,
  345          90, 65, 77, 75, 92, 93, 96,117,119,126,138,     78, 79, 98,102,
  346         110,124,131,143,157,    173,185,200};
  347 #endif
  348 
  349 static void putitem(void);
  350 static void rleputxelval(int);
  351 static void rleflush(void);
  352 static void rleputrest(void);
  353 
  354 static int LPTn;                   /* printer number we're gonna use */
  355 
  356 static FILE *PRFILE;
  357 
  358 #define TONES 17                   /* Number of PostScript halftone styles */
  359 
  360 #if 1
  361 static FCODE ht00[] = {"D mul exch D mul add 1 exch sub"};
  362 static FCODE ht01[] = {"abs exch abs 2 copy add 1 gt {1 sub D mul exch 1 sub D mul add 1 sub} {D mul exch D mul add 1 exch sub} ifelse"};
  363 static FCODE ht02[] = {"D mul exch D mul add 1 sub"};
  364 static FCODE ht03[] = {"D mul exch D mul add 0.6 exch sub abs -0.5 mul"};
  365 static FCODE ht04[] = {"D mul exch D mul add 0.6 exch sub abs 0.5 mul"};
  366 static FCODE ht05[] = {"add 2 div"};
  367 static FCODE ht06[] = {"2 exch sub exch abs 2 mul sub 3 div"};
  368 static FCODE ht07[] = {"2 copy abs exch abs gt {exch} if pop 2 mul 1 exch sub 3.5 div"};
  369 static FCODE ht08[] = {"abs exch abs add 1 exch sub"};
  370 static FCODE ht09[] = {"pop"};
  371 static FCODE ht10[] = {"/wy exch def 180 mul cos 2 div wy D D D mul mul sub mul wy add 180 mul cos"};
  372 static FCODE ht11[] = {"D 5 mul 8 div mul exch D mul exch add sqrt 1 exch sub"};
  373 static FCODE ht12[] = {"D mul D mul exch D mul D mul add 1 exch sub"};
  374 static FCODE ht13[] = {"D mul exch D mul add sqrt 1 exch sub"};
  375 static FCODE ht14[] = {"abs exch abs 2 copy gt {exch} if 1 sub D 0 eq {0.01 add} if atan 360 div"};
  376 static FCODE ht15[] = {"pop pop rand 1 add 10240 mod 5120 div 1 exch sub"};
  377 static FCODE ht16[] = {"pop abs 2 mul 1 exch sub"};
  378 #endif
  379 
  380 static FCODE *HalfTone[TONES]=  {ht00,ht01,ht02,ht03,ht04,ht05,ht06,ht07,
  381     ht08,ht09,ht10,ht11,ht12,ht13,ht14,ht15,ht16};
  382 
  383 #if 0
  384                          "D mul exch D mul add 1 exch sub",
  385                          "abs exch abs 2 copy add 1 gt {1 sub D mul exch 1 sub D mul add 1 sub} {D mul exch D mul add 1 exch sub} ifelse",
  386                          "D mul exch D mul add 1 sub",
  387                          "D mul exch D mul add 0.6 exch sub abs -0.5 mul",
  388                          "D mul exch D mul add 0.6 exch sub abs 0.5 mul",
  389                          "add 2 div",
  390                          "2 exch sub exch abs 2 mul sub 3 div",
  391                          "2 copy abs exch abs gt {exch} if pop 2 mul 1 exch sub 3.5 div",
  392                          "abs exch abs add 1 exch sub",
  393                          "pop",
  394                          "/wy exch def 180 mul cos 2 div wy D D D mul mul sub mul wy add 180 mul cos",
  395                          "D 5 mul 8 div mul exch D mul exch add sqrt 1 exch sub",
  396                          "D mul D mul exch D mul D mul add 1 exch sub",
  397                          "D mul exch D mul add sqrt 1 exch sub",
  398                          "abs exch abs 2 copy gt {exch} if 1 sub D 0 eq {0.01 add} if atan 360 div",
  399                          "pop pop rand 1 add 10240 mod 5120 div 1 exch sub",
  400                          "pop abs 2 mul 1 exch sub"
  401                         };   402 #endif
  403 
  404 #ifdef __BORLANDC__
  408 #endif
  409 
  410 static char EndOfLine[3];
  411 
  412 /* workaround for the old illicit decflaration of dstack */
  413 
  414 typedef int (*TRIPLE)[2][3][400];
  415 #define triple   (*((TRIPLE)dstack))
  416 
  417 void
  418 Print_Screen (void)
  419 {
  420     int y,j;
  421     char buff[192];             /* buffer for 192 sets of pixels  */
  422                                 /* This is very large so that we can*/
  423                                 /* get reasonable times printing  */
  424                                 /* from modes like MAXPIXELSxMAXPIXELS disk-*/
  425                                 /* video.  When this was 24, a MAXPIXELS*/
  426                                 /* by MAXPIXELS pic took over 2 hours to*/
  427                                 /* print.  It takes about 15 min now*/
  428     int BuffSiz;                /* how much of buff[] we'll use   */
  429     char far *es;               /* pointer to extraseg for buffer */
  430     int i,x,k,                  /* more indices                   */
  431         imax,                   /* maximum i value (ydots/8)      */
  432         res,                    /* resolution we're gonna' use    */
  433         high,                   /* if LPTn>10 COM == com port to use*/
  434         low,                    /* misc                           */
  435                                 /************************************/
  436         ptrid;                  /* Printer Id code.               */
  437                                 /* Currently, the following are   */
  438                                 /* assigned:                      */
  439                                 /*            1. HPLJ (all)       */
  440                                 /*               Toshiba PageLaser*/
  441                                 /*            2. IBM Graphics     */
  442                                 /*            3. Color Printer    */
  443                                 /*            4. HP PaintJet      */
  444                                 /*            5. PostScript       */
  445                                 /************************************/
  446     int pj_color_ptr[256];      /* Paintjet color translation */
  447 
  448                                 /********   SETUP VARIABLES  ********/
  449     memset(buff,0,192);
  450     i = 0;
  451 
  452     EndOfLine[0]=(char)(((Printer_CRLF==1) || (Printer_CRLF==0)) ? 0x0D : 0x0A);
  453     EndOfLine[1]=(char)((Printer_CRLF==0) ? 0x0A : 0x00);
  454     EndOfLine[2]=0x00;
  455 
  456     if (Print_To_File>0)
  457       {
  458       while ((PRFILE = fopen(PrintName,"r")) != NULL) {
  459          j = fgetc(PRFILE);
  460          fclose(PRFILE);
  461          if (j == EOF) break;
  462          updatesavename((char *)PrintName);
  463          }
  464       if ((PRFILE = fopen(PrintName,"wb")) == NULL) Print_To_File = 0;
  465       }
  466 
  467 #ifdef XFRACT
  471 #endif
  472 
  473     es=MK_FP(extraseg,0);
  474 
  475     LPTn=LPTNumber-1;
  476     if (((LPTn>2)&&(LPTn<10))||
  477         ((LPTn>13)&&(LPTn<20))||
  478         ((LPTn>21)&&(LPTn<30))||
  479         (LPTn<0)||(LPTn>31)) LPTn=0;   /* default of LPT1 (==0)          */
  480     ptrid=Printer_Type;
  481     if ((ptrid<1)||(ptrid>7)) ptrid=2; /* default of IBM/EPSON           */
  482     res=Printer_Resolution;
  483 #ifndef XFRACT
  484     if ((LPTn==20)||(LPTn==21))
  485         {
  486         k = (inp((LPTn==20) ? 0x37A : 0x27A)) & 0xF7;
  487         outp((LPTn==20) ? 0x37A : 0x27A,k);
  488         k = k & 0xFB;
  489         outp((LPTn==20) ? 0x37A : 0x27A,k);
  490         k = k | 0x0C;
  491         outp((LPTn==20) ? 0x37A : 0x27A,k);
  492         }
  493     if ((LPTn==30)||(LPTn==31))
  494         {
  495         outp((LPTn==30) ? 0x3F9 : 0x2F9,0x00);
  496         outp((LPTn==30) ? 0x3FC : 0x2FC,0x00);
  497         outp((LPTn==30) ? 0x3FC : 0x2FC,0x03);
  498         }
  499 #endif
  500 
  501     switch (ptrid) {
  502 
  503         case 1:
  504             if (res<75) res=75;
  505             if ( (res<= 75)&&(ydots> 600)) res=100;
  506             if ( (res<=100)&&(ydots> 800)) res=150;
  507             if (((res<=150)&&(ydots>1200))||(res>300)) res=300;
  508             break;
  509 
  510         case 2:
  511         case 3:
  512             if (res<60) res=60;
  513             if ((res<=60)&&(ydots>480)) res=120;
  514             if (((res<=120)&&(ydots>960))||(res>240)) res=240;
  515             break;
  516 
  517         case 4: /****** PaintJet  *****/
  518             {
  519 #ifndef XFRACT
  520             /* Pieter Branderhorst:
  521                My apologies if the numbers and approach here seem to be
  522                picked out of a hat.  They were.  They happen to result in
  523                a tolerable mapping of screen colors to printer colors on
  524                my machine.  There are two sources of error in getting colors
  525                to come out right.
  526                1) Must match some dacbox values to the 330 PaintJet dithered
  527                   colors so that they look the same.  For this we use HP's
  528                   color values in printera.asm and modify by gamma separately
  529                   for each of red/green/blue.  This mapping is ok if the
  530                   preview shown on screen is a fairly close match to what
  531                   gets printed. The defaults are what work for me.
  532                2) Must find nearest color in HP palette to each color in
  533                   current image. For this we use Lee Crocker's least sum of
  534                   differences squared approach, modified to spread the
  535                   values using gamma 1.7.  This mods was arrived at by
  536                   trial and error, just because it improves the mapping.
  537                */
  538             long ldist;
  539             int r,g,b;
  540             double gamma_val,gammadiv;
  541             BYTE convert[256];
  542             BYTE scale[64];
  543 
  544             BYTE far *table_ptr = NULL;
  545             res = (res < 150) ? 90 : 180;   /* 90 or 180 dpi */
  546             if (Printer_SetScreen == 0) {
  547                 Printer_SFrequency = 21;  /* default red gamma */
  548                 Printer_SAngle     = 19;  /*       green gamma */
  549                 Printer_SStyle     = 16;  /*        blue gamma */
  550             }
  551             /* Convert the values in printera.asm.  We might do this just   */
  552             /* once per run, but we'd need separate memory for that - can't */
  553             /* just convert table in-place cause it could be in an overlay, */
  554             /* might be paged out and then back in in original form.  Also, */
  555             /* user might change gammas with a .par file entry mid-run.     */
  556             for (j = 0; j < 3; ++j) {
  557                 switch (j) {
  558                     case 0: table_ptr = pj_reds;
  559                             i = Printer_SFrequency;
  560                             break;
  561                     case 1: table_ptr = pj_greens;
  562                             i = Printer_SAngle;
  563                             break;
  564                     case 2: table_ptr = pj_blues;
  565                             i = Printer_SStyle;
  566                     }
  567                 gamma_val = 10.0 / i;
  568                 gammadiv = pow(255,gamma_val) / 255;
  569                 for (i = 0; i < 256; ++i) { /* build gamma conversion table */
  570                     static FCODE msg[]={"Calculating color translation"};
  571                     if ((i & 15) == 15)
  572                         thinking(1,msg);
  573                     convert[i] = (BYTE)((pow((double)i,gamma_val) / gammadiv) + 0.5);
  574                     }
  575                 for (i = 0; i < 330; ++i) {
  576                     k = convert[table_ptr[i]];
  577                     if (k > 252) k = 252;
  578                     triple[0][j][i] = (k + 2) >> 2;
  579                 }
  580             }
  581             /* build comparison lookup table */
  582             gamma_val = 1.7;
  583             gammadiv = pow(63,gamma_val) / 63;
  584             for (i = 0; i < 64; ++i) {
  585                if ((j = (int)((pow((double)i,gamma_val) / gammadiv) * 4 + 0.5)) < i)
  586                   j = i;
  587                scale[i] = (char)j;
  588             }
  589             for (i = 0; i < 3; ++i) /* convert values via lookup */
  590                 for (j = 0; j < 330; ++j)
  591                     triple[1][i][j] = scale[triple[0][i][j]];
  592             /* Following code and the later code which writes to Paintjet    */
  593             /* using pj_patterns was adapted from Lee Crocker's PGIF program */
  594             for (i = 0; i < colors; ++i) { /* find nearest match colors */
  595                 r = scale[dacbox[i][0]];
  596                 g = scale[dacbox[i][1]];
  597                 b = scale[dacbox[i][2]];
  598                 ldist = 9999999L;
  599                 /* check variance vs each PaintJet color */
  600                 /* if high-res 8 color mode, consider only 1st 8 colors */
  601                 j = (res == 90) ? 330 : 8;
  602                 while (--j >= 0) {
  603                     long dist;
  604                     dist  = (unsigned)(r-triple[1][0][j]) * (r-triple[1][0][j]);
  605                     dist += (unsigned)(g-triple[1][1][j]) * (g-triple[1][1][j]);
  606                     dist += (unsigned)(b-triple[1][2][j]) * (b-triple[1][2][j]);
  607                     if (dist < ldist) {
  608                         ldist = dist;
  609                         k = j;
  610                     }
  611                 }
  612                 pj_color_ptr[i] = k; /* remember best fit */
  613             }
  614             thinking(0,NULL);
  615         /*  if (debugflag == 900 || debugflag == 902) {
  616                 color_test();
  617                 return;
  618             }  */
  619             if (dotmode != 11) { /* preview */
  620                 static char far msg[] = {"Preview. Enter=go, Esc=cancel, k=keep"};
  621                 memcpy(triple[1],dacbox,768);
  622                 for (i = 0; i < colors; ++i)
  623                     for (j = 0; j < 3; ++j)
  624                         dacbox[i][j] = (BYTE)triple[0][j][pj_color_ptr[i]];
  625                 spindac(0,1);
  626                 texttempmsg(msg);
  627                 i = getakeynohelp();
  628                 if (i == 'K' || i == 'k') {
  629                     return;
  630                 }
  631                 memcpy(dacbox,triple[1],768);
  632                 spindac(0,1);
  633                 if (i == 0x1B) {
  634                     return;
  635                 }
  636             }
  637             break;
  638 #endif
  639             }
  640 
  641         case 5:
  642         case 6: /***** PostScript *****/
  643             if ( res < 10 && res != 0 ) res = 10; /* PostScript scales... */
  644             if ( res > 600 ) res = 600; /* it can handle any range! */
  645             if ((Printer_SStyle < 0) || (Printer_SStyle >= TONES))
  646                 Printer_SStyle = 0;
  647             break;
  648     }
  649 
  650     /*****  Set up buffer size for immediate user gratification *****/
  651     /*****    AKA, if we don't have to, don't buffer the data   *****/
  652     BuffSiz=8;
  653     if (xdots>1024) BuffSiz=192;
  654 
  655     /*****   Initialize printer  *****/
  656     if (Print_To_File < 1) {
  657         printer_reset();
  658         /* wait a bit, some printers need time after reset */
  659         delay((ptrid == 4) ? 2000 : 500);
  660     }
  661 
  662     /******  INITIALIZE GRAPHICS MODES  ******/
  663 
  664     graphics_init(ptrid,res,EndOfLine);
  665 
  666     if (keypressed()) {         /* one last chance before we start...*/
  667         return;
  668         }
  669 
  670     memset(buff,0,192);
  671 
  672                                 /*****  Get And Print Screen **** */
  673     switch (ptrid) {
  674 
  675         case 1:                        /* HP LaserJet (et al)            */
  676             imax=(ydots/8)-1;
  677             for (x=0;((x<xdots)&&(!keypressed()));x+=BuffSiz) {
  678                 for (i=imax;((i>=0)&&(!keypressed()));i--) {
  679                     for (y=7;((y>=0)&&(!keypressed()));y--) {
  680                         for (j=0;j<BuffSiz;j++) {
  681                             if ((x+j)<xdots) {
  682                                 buff[j]<<=1;
  683                                 buff[j]=(char)(buff[j]+(char)(getcolor(x+j,i*8+y)&1));
  684                                 }
  685                             }
  686                         }
  687                     for (j=0;j<BuffSiz;j++) {
  688                         *(es+j+BuffSiz*i)=buff[j];
  689                         buff[j]=0;
  690                         }
  691                     }
  692                 for (j=0;((j<BuffSiz)&&(!keypressed()));j++) {
  693                     if ((x+j)<xdots) {
  694                         PRINTER_PRINTF2("\033*b%iW",imax+1);
  695                         for (i=imax;((i>=0)&&(!keypressed()));i--) {
  696                             printer(*(es+j+BuffSiz*i));
  697                             }
  698                         }
  699                     }
  700                 }
  701             if (!keypressed()) PRINTER_PRINTF1("\033*rB\014");
  702             break;
  703 
  704         case 2:                        /* IBM Graphics/Epson             */
  705             for (x=0;((x<xdots)&&(!keypressed()));x+=8) {
  706                 switch (res) {
  707                     case 60:  Printer_printf("\033K"); break;
  708                     case 120: Printer_printf("\033L"); break;
  709                     case 240: Printer_printf("\033Z"); break;
  710                     }
  711                 high=ydots/256;
  712                 low=ydots-(high*256);
  713                 printer(low);
  714                 printer(high);
  715                 for (y=ydots-1;(y>=0);y--) {
  716                     buff[0]=0;
  717                     for (i=0;i<8;i++) {
  718                         buff[0]<<=1;
  719                         buff[0]=(char)(buff[0]+(char)(getcolor(x+i,y)&1));
  720                         }
  721                     printer(buff[0]);
  722                     }
  723                 if (keypressed()) break;
  724                 Printer_printf(EndOfLine);
  725                 }
  726             if (!keypressed()) printer(12);
  727             break;
  728 
  729         case 3:                        /* IBM Graphics/Epson Color      */
  730             high=ydots/256;
  731             low=ydots%256;
  732             for (x=0;((x<xdots)&&(!keypressed()));x+=8)
  733                 {
  734                 for (k=0; k<8; k++)  /* colors */
  735                     {
  736                     Printer_printf("\033r%d",k); /* set printer color */
  737                     switch (res)
  738                         {
  739                         case 60:  Printer_printf("\033K"); break;
  740                         case 120: Printer_printf("\033L"); break;
  741                         case 240: Printer_printf("\033Z"); break;
  742                         }
  743                     printer(low);
  744                     printer(high);
  745                     for (y=ydots-1;y>=0;y--)
  746                         {
  747                         buff[0]=0;
  748                         for (i=0;i<8;i++)
  749                             {
  750                             buff[0]<<=1;
  751                             if ((getcolor(x+i,y)%8)==k)
  752                                 buff[0]++;
  753                             }
  754                         printer(buff[0]);
  755                         }
  756                     if (Printer_CRLF<2) printer(13);
  757                     }
  758                 if ((Printer_CRLF==0) || (Printer_CRLF==2)) printer(10);
  759                 }
  760             printer(12);
  761             printer(12);
  762             printer_reset();
  763             break;
  764 
  765         case 4:                       /* HP PaintJet       */
  766             {
  767             unsigned int fetchrows,fetched;
  768             BYTE far *pixels = NULL, far *nextpixel = NULL;
  769             /* for reasonable speed when using disk video, try to fetch
  770                and store the info for 8 columns at a time instead of
  771                doing getcolor calls down each column in separate passes */
  772             fetchrows = 16;
  773             for(;;) {
  774                 if ((pixels = (BYTE far *)farmemalloc((long)(fetchrows)*ydots)) != NULL)
  775                    break;
  776                 if ((fetchrows >>= 1) == 0) {
  777                     static char far msg[]={"insufficient memory"};
  778                     stopmsg(0,msg);
  779                     break;
  780                 }
  781             }
  782             if (!pixels) break;
  783             fetched = 0;
  784             for (x = 0; (x < xdots && !keypressed()); ++x) {
  785                 if (fetched == 0) {
  786                     if ((fetched = xdots-x) > fetchrows)
  787                         fetched = fetchrows;
  788                     for (y = ydots-1; y >= 0; --y) {
  789                         if (debugflag == 602) /* flip image */
  790                             nextpixel = pixels + y;
  791                         else                  /* reverse order for unflipped */
  792                             nextpixel = pixels + ydots-1 - y;
  793                         for (i = 0; i < (int)fetched; ++i) {
  794                             *nextpixel = (BYTE)getcolor(x+i,y);
  795                             nextpixel += ydots;
  796                         }
  797                     }
  798                     nextpixel = pixels;
  799                 }
  800                 --fetched;
  801                 if (res == 180) { /* high-res 8 color mode */
  802                     int offset;
  803                     BYTE bitmask;
  804                     offset = -1;
  805                     bitmask = 0;
  806                     for (y = ydots - 1; y >= 0; --y) {
  807                         BYTE color;
  808                         if ((bitmask >>= 1) == 0) {
  809                             ++offset;
  810                             triple[0][0][offset] = triple[0][1][offset]
  811                                                  = triple[0][2][offset] = 0;
  812                             bitmask = 0x80;
  813                         }
  814                         /* translate 01234567 to 70123456 */
  815                         color = (BYTE)(pj_color_ptr[*(nextpixel++)] - 1);
  816                         if ((color & 1)) triple[0][0][offset] += bitmask;
  817                         if ((color & 2)) triple[0][1][offset] += bitmask;
  818                         if ((color & 4)) triple[0][2][offset] += bitmask;
  819                     }
  820                 }
  821                 else { /* 90 dpi, build 2 lines, 2 dots per pixel */
  822                     int bitct,offset;
  823                     bitct = offset = 0;
  824                     for (y = ydots - 1; y >= 0; --y) {
  825                         unsigned int color;
  826                         color = pj_patterns[pj_color_ptr[*(nextpixel++)]];
  827                         for (i = 0; i < 3; ++i) {
  828                             BYTE *bufptr;
  829                             bufptr = (BYTE *)&triple[0][i][offset];
  830                             *bufptr <<= 2;
  831                             if ((color & 0x1000)) *bufptr += 2;
  832                             if ((color & 0x0100)) ++*bufptr;
  833                             bufptr = (BYTE *)&triple[1][i][offset];
  834                             *bufptr <<= 2;
  835                             if ((color & 0x0010)) *bufptr += 2;
  836                             if ((color & 0x0001)) ++*bufptr;
  837                             color >>= 1;
  838                         }
  839                         if (++bitct == 4) {
  840                             bitct = 0;
  841                             ++offset;
  842                         }
  843                     }
  844                 }
  845                 for (i = 0; i < ((res == 90) ? 2 : 1); ++i) {
  846                     for (j = 0; j < 3; ++j) {
  847                         BYTE *bufptr,*bufend;
  848                         Printer_printf((j < 2) ? "\033*b%dV" : "\033*b%dW",
  849                                        pj_width);
  850                         bufend = pj_width + (bufptr = (BYTE *)(triple[i][j]));
  851                         do {
  852                             while (printer(*bufptr)) { }
  853                         } while (++bufptr < bufend);
  854                     }
  855                 }
  856             }
  857             PRINTER_PRINTF1("\033*r0B"); /* end raster graphics */
  858             if (!keypressed()) {
  859                if (debugflag != 600)
  860                   printer(12); /* form feed */
  861                else
  862                   Printer_printf("\n\n");
  863             }
  864             farmemfree(pixels);
  865             break;
  866             }
  867 
  868         case 5:
  869         case 6:         /***** PostScript Portrait & Landscape *****/
  870             {
  871             char convert[513];
  872             if (!ColorPS) {
  873               for (i=0; i<256; ++i)
  874                 if (Printer_Compress) {
  875                     convert[i] = (char)((.3*255./63. * (double)dacbox[i][0])+
  876                                         (.59*255./63. * (double)dacbox[i][1])+
  877                                         (.11*255./63. * (double)dacbox[i][2]));
  878                 } else
  879                 {
  880                     sprintf(&convert[2*i], "%02X",
  881                               (int)((.3*255./63. * (double)dacbox[i][0])+
  882                                     (.59*255./63. * (double)dacbox[i][1])+
  883                                     (.11*255./63. * (double)dacbox[i][2])));
  884                 }
  885             }
  886             i=0;
  887             j=0;
  888             for (y=0;((y<ydots)&&(!keypressed()));y++)
  889             {   unsigned char bit8 = 0;
  890                 if (Printer_Compress) {
  891                     if (ColorPS) {
  892                         for (x=0;x<xdots;x++) {
  893                             k=getcolor(x,y);
  894                             rleputxelval((int)dacbox[k][0]<<2);
  895                         }
  896                         rleflush();
  897                         for (x=0;x<xdots;x++) {
  898                             k=getcolor(x,y);
  899                             rleputxelval((int)dacbox[k][1]<<2);
  900                         }
  901                         rleflush();
  902                         for (x=0;x<xdots;x++) {
  903                             k=getcolor(x,y);
  904                             rleputxelval((int)dacbox[k][2]<<2);
  905                         }
  906                         rleflush();
  907                      } else {
  908                         if (Printer_ColorXlat==-2 || Printer_ColorXlat==2) {
  909                            for (x=0;x<xdots;x++) {
  910                               k=getcolor(x,y);
  911                               k=getcolor(x,y) & 1;
  912                               if (x % 8 == 0) {
  913                                  if (x) rleputxelval((int)bit8);
  914                                  if (k) bit8 = 1; else bit8 = 0;
  915                               }
  916                               else
  917                                  bit8 = (unsigned char)((bit8 << 1) + ((k) ? 1 : 0));
  918                            }
  919                            if (xdots % 8) bit8 <<= (8 - (xdots % 8));
  920                            rleputxelval((int)bit8);
  921                            rleflush();
  922                         } else {
  923                            for (x=0;x<xdots;x++) {
  924                               k=getcolor(x,y);
  925                               rleputxelval((int)(unsigned char)convert[k]);
  926                            }
  927                            rleflush();
  928                         }
  929                      }
  930                 } else
  931                 {
  932                     for (x=0;x<xdots;x++)
  933                     {
  934                         k=getcolor(x,y);
  935                         if (ColorPS)
  936                           {
  937                           sprintf(&buff[i], "%02X%02X%02X", dacbox[k][0]<<2,
  938                                                             dacbox[k][1]<<2,
  939                                                             dacbox[k][2]<<2);
  940                           i+=6;
  941                           }
  942                         else
  943                           {
  944                           k*=2;
  945                           buff[i++]=convert[k];
  946                           buff[i++]=convert[k+1];
  947                           }
  948                         if (i>=64)
  949                         {
  950                             strcpy(&buff[i],"  ");
  951                             Printer_printf("%s%s",buff,EndOfLine);
  952                             i=0;
  953                             j++;
  954                             if (j>9)
  955                             {
  956                                 j=0;
  957                                 Printer_printf(EndOfLine);
  958                             }
  959                         }
  960                     }
  961                 }
  962             }
  963             if (Printer_Compress) {
  964                 rleputrest();
  965             } else {
  966                 strcpy(&buff[i],"  ");
  967                 Printer_printf("%s%s",buff,EndOfLine);
  968                 i=0;
  969                 j++;
  970                 if (j>9)
  971                 {
  972                     j=0;
  973                     Printer_printf(EndOfLine);
  974                 }
  975             }
  976             if ( (EPSFileType > 0) && (EPSFileType <3) )
  977             {
  978                 PRINTER_PRINTF4("%s%%%%Trailer%sEPSFsave restore%s",EndOfLine,
  979                         EndOfLine,EndOfLine);
  980             }
  981             else
  982             {
  983 #ifndef XFRACT
  984                 PRINTER_PRINTF4("%sshowpage%s%c",EndOfLine,EndOfLine,4);
  987 #endif
  988             }
  989             break;
  990             }
  991 
  992         case 7: /* HP Plotter */
  993             {
  994             double parm1=0,parm2=0;
  995             for (i=0;i<3;i++)
  996             {
  997               PRINTER_PRINTF4("%sSP %d;%s\0",EndOfLine,(i+1),EndOfLine);
  998               for (y=0;(y<ydots)&&(!keypressed());y++)
  999               {
 1000                 for (x=0;x<xdots;x++)
 1001                 {
 1002                   j=dacbox[getcolor(x,y)][i];
 1003                   if (j>0)
 1004                   {
 1005                     switch(Printer_SStyle)
 1006                     {
 1007                       case 0:
 1008                         ci=0.004582144*(double)j;
 1009                         ck= -.007936057*(double)j;
 1010                         parm1 = (double)x+.5+ci+(((double)i-1.0)/3);
 1011                         parm2 = (double)y+.5+ck;
 1012                         break;
 1013                       case 1:
 1014                         ci= -.004582144*(double)j+(((double)i+1.0)/8.0);
 1015                         ck= -.007936057*(double)j;
 1016                         parm1 = (double)x+.5+ci;
 1017                         parm2 = (double)y+.5+ck;
 1018                         break;
 1019                       case 2:
 1020                         ci= -.0078125*(double)j+(((double)i+1.0)*.003906250);
 1021                         ck= -.0078125*(double)j;
 1022                         parm1 = (double)x+.5+ci;
 1023                         parm2 = (double)y+.5+ck;
 1024                         break;
 1025                     }
 1026                     PRINTER_PRINTF5("PA %f,%f;PD;PR %f,%f;PU;\0",
 1027                         parm1,parm2, ci*((double)-2), ck*((double)-2));
 1028                   }
 1029                 }
 1030               }
 1031             }
 1032             PRINTER_PRINTF3("%s;SC;PA 0,0;SP0;%s\0",EndOfLine,EndOfLine);
 1033             PRINTER_PRINTF2(";;SP 0;%s\0",EndOfLine);
 1034             break;
 1035             }
 1036     }
 1037 
 1038     if (Print_To_File > 0) fclose(PRFILE);
 1039 #ifndef XFRACT
 1040     if ((LPTn==30)||(LPTn==31))
 1041         {
 1042         for (x=0;x<2000;x++);
 1043         outp((LPTn==30) ? 0x3FC : 0x2FC,0x00);
 1044         outp((LPTn==30) ? 0x3F9 : 0x2F9,0x00);
 1045         }
 1048 #endif
 1049 }
 1050 
 1051 
 1052 static void _fastcall graphics_init(int ptrid,int res,char *EndOfLine)
 1053 {
 1054     int i,j;
 1055 
 1056     switch (ptrid) {
 1057 
 1058         case 1:
 1059             print_title(ptrid,res,EndOfLine);
 1060             PRINTER_PRINTF2("\033*t%iR\033*r0A",res);/* HP           */
 1061             break;
 1062 
 1063         case 2:
 1064         case 3:
 1065             print_title(ptrid,res,EndOfLine);
 1066             PRINTER_PRINTF1("\033\063\030");/* IBM                   */
 1067             break;
 1068 
 1069         case 4: /****** PaintJet *****/
 1070             print_title(ptrid,res,EndOfLine);
 1071             pj_width = ydots;
 1072             if (res == 90) pj_width <<= 1;
 1073             PRINTER_PRINTF2("\033*r0B\033*t180R\033*r3U\033*r%dS\033*b0M\033*r0A",
 1074                 pj_width);
 1075             pj_width >>= 3;
 1076             break;
 1077 
 1078         case 5:   /***** PostScript *****/
 1079         case 6:   /***** PostScript Landscape *****/
 1080             if (!((EPSFileType > 0) && (ptrid==5)))
 1081                 PRINTER_PRINTF2("%%!PS-Adobe%s",EndOfLine);
 1082             if ((EPSFileType > 0) &&     /* Only needed if saving to .EPS */
 1083                 (ptrid == 5))
 1084                 {
 1085                 PRINTER_PRINTF2("%%!PS-Adobe-1.0 EPSF-2.0%s",EndOfLine);
 1086 
 1087                 if (EPSFileType==1)
 1088                     i=xdots+78;
 1089                 else
 1090                     i=(int)((double)xdots * (72.0 / (double)res))+78;
 1091 
 1092                 if (Printer_Titleblock==0)
 1093                     {
 1094                     if (EPSFileType==1) { j = ydots + 78; }
 1095                     else { j = (int)(((double)ydots * (72.0 / (double)res) / (double)finalaspectratio)+78); }
 1096                     }
 1097                 else
 1098                     {
 1099                     if (EPSFileType==1) { j = ydots + 123; }
 1100                     else { j = (int)(((double)ydots * (72.0 / (double)res))+123); }
 1101                     }
 1102                 PRINTER_PRINTF4("%%%%TemplateBox: 12 12 %d %d%s",i,j,EndOfLine);
 1103                 PRINTER_PRINTF4("%%%%BoundingBox: 12 12 %d %d%s",i,j,EndOfLine);
 1104                 PRINTER_PRINTF4("%%%%PrinterRect: 12 12 %d %d%s",i,j,EndOfLine);
 1105                 PRINTER_PRINTF2("%%%%Creator: Fractint PostScript%s",EndOfLine);
 1106                 PRINTER_PRINTF5("%%%%Title: A %s fractal - %s - Fractint EPSF Type %d%s",
 1107                                        curfractalspecific->name[0]=='*' ?
 1108                                        &curfractalspecific->name[1] :
 1109                                        curfractalspecific->name,
 1110                                        PrintName,
 1111                                        EPSFileType,
 1112                                        EndOfLine);
 1113                 if (Printer_Titleblock==1)
 1114                     PRINTER_PRINTF2("%%%%DocumentFonts: Helvetica%s",EndOfLine);
 1115                 PRINTER_PRINTF2("%%%%EndComments%s",EndOfLine);
 1116                 PRINTER_PRINTF2("/EPSFsave save def%s",EndOfLine);
 1117                 PRINTER_PRINTF2("0 setgray 0 setlinecap 1 setlinewidth 0 setlinejoin%s",EndOfLine);
 1118                 PRINTER_PRINTF2("10 setmiterlimit [] 0 setdash newpath%s",EndOfLine);
 1119                 }
 1120 
 1121             /* Common code for all PostScript */
 1122             PRINTER_PRINTF2("/Tr {translate} def%s",EndOfLine);
 1123             PRINTER_PRINTF2("/Mv {moveto} def%s",EndOfLine);
 1124             PRINTER_PRINTF2("/D {dup} def%s",EndOfLine);
 1125             PRINTER_PRINTF2("/Rh {readhexstring} def%s",EndOfLine);
 1126             PRINTER_PRINTF2("/Cf {currentfile} def%s",EndOfLine);
 1127             PRINTER_PRINTF2("/Rs {readstring} def%s",EndOfLine);
 1128 
 1129             if (Printer_Compress) {
 1130                 rleprolog(xdots,ydots);
 1131             } else
 1132             {
 1133                 PRINTER_PRINTF3("/picstr %d string def%s",
 1134                         ColorPS?xdots*3:xdots,EndOfLine);
 1135                 PRINTER_PRINTF7("/dopic { gsave %d %d 8 [%d 0 0 %d 0 %d]%s",
 1136                                          xdots, ydots, xdots, -ydots, ydots,
 1137                                          EndOfLine);
 1138                 PRINTER_PRINTF2("{ Cf picstr Rh pop }%s", EndOfLine);
 1139                 if (ColorPS)
 1140                 {
 1141                     PRINTER_PRINTF2(" false 3 colorimage grestore } def%s",
 1142                      EndOfLine);
 1143                 }
 1144                 else
 1145                 {
 1146                     PRINTER_PRINTF2(" image grestore } def%s", EndOfLine);
 1147                 }
 1148             }
 1149             if (Printer_Titleblock==1)
 1150                 {
 1151                 PRINTER_PRINTF2("/Helvetica findfont 8 scalefont setfont%s",EndOfLine);
 1152                 if (ptrid==5) {PRINTER_PRINTF1("30 60 Mv ");}
 1153                 else          {PRINTER_PRINTF1("552 30 Mv 90 rotate ");}
 1154                 print_title(ptrid,res,EndOfLine);
 1155                 if (ptrid==6) {PRINTER_PRINTF1("-90 rotate ");}
 1156                 }
 1157 
 1158             if (EPSFileType != 1) /* Do not use on a WELL BEHAVED .EPS */
 1159               {
 1160               if (ptrid == 5 && EPSFileType==2
 1161                              && (Printer_ColorXlat || Printer_SetScreen))
 1162                         PRINTER_PRINTF2("%%%%BeginFeature%s",EndOfLine);
 1163               if (ColorPS)
 1164                 {
 1165                 if (Printer_ColorXlat==1)
 1166                     PRINTER_PRINTF2("{1 exch sub} D D D setcolortransfer%s",EndOfLine);
 1167                 if (Printer_ColorXlat>1)
 1168                     PRINTER_PRINTF4("{%d mul round %d div} D D D setcolortransfer%s",
 1169                                        Printer_ColorXlat,Printer_ColorXlat,EndOfLine);
 1170                 if (Printer_ColorXlat<-1)
 1171                     PRINTER_PRINTF4("{%d mul round %d div 1 exch sub} D D D setcolortransfer",
 1172                                        Printer_ColorXlat,Printer_ColorXlat,EndOfLine);
 1173 
 1174                 if (Printer_SetScreen==1)
 1175                     {
 1176 #ifndef XFRACT
 1177                     static char far fmt_str[] = "%d %d {%Fs}%s";
 1178 #else
 1179                     static char fmt_str[] = "%d %d {%s}%s";  1180 #endif
 1181                     Printer_printf(fmt_str,
 1182                                        Printer_RFrequency,
 1183                                        Printer_RAngle,
 1184                                        (char far *)HalfTone[Printer_RStyle],
 1185                                        EndOfLine);
 1186                     Printer_printf(fmt_str,
 1187                                        Printer_GFrequency,
 1188                                        Printer_GAngle,
 1189                                        (char far *)HalfTone[Printer_GStyle],
 1190                                        EndOfLine);
 1191                     Printer_printf(fmt_str,
 1192                                        Printer_BFrequency,
 1193                                        Printer_BAngle,
 1194                                        (char far *)HalfTone[Printer_BStyle],
 1195                                        EndOfLine);
 1196                     Printer_printf(fmt_str,
 1197                                        Printer_SFrequency,
 1198                                        Printer_SAngle,
 1199                                        (char far *)HalfTone[Printer_SStyle],
 1200                                        EndOfLine);
 1201                     PRINTER_PRINTF2("setcolorscreen%s", EndOfLine);
 1202                     }
 1203                 }
 1204               else
 1205               {
 1206                  if (Printer_ColorXlat!=-2 && Printer_ColorXlat!=2) {
 1207                     /* b&w case requires no mask building */
 1208                    if (Printer_ColorXlat==1)
 1209                       PRINTER_PRINTF2("{1 exch sub} settransfer%s",EndOfLine);
 1210                    if (Printer_ColorXlat>1)
 1211                       PRINTER_PRINTF4("{%d mul round %d div} settransfer%s",
 1212                                       Printer_ColorXlat,Printer_ColorXlat,EndOfLine);
 1213                    if (Printer_ColorXlat<-1)
 1214                       PRINTER_PRINTF4("{%d mul round %d div 1 exch sub} settransfer",
 1215                                       Printer_ColorXlat,Printer_ColorXlat,EndOfLine);
 1216 
 1217                    if (Printer_SetScreen==1)
 1218                    {
 1219 #ifndef XFRACT
 1220                       PRINTER_PRINTF5("%d %d {%Fs} setscreen%s",
 1221                                      Printer_SFrequency,
 1222                                      Printer_SAngle,
 1223                                      (char far *)HalfTone[Printer_SStyle],
 1224                                      EndOfLine);
 1231 #endif
 1232                    }
 1233                 }
 1234               }
 1235 
 1236               if (ptrid == 5)
 1237                  {
 1238                     if ((EPSFileType==2) && (Printer_ColorXlat || Printer_SetScreen))
 1239                         PRINTER_PRINTF2("%%%%EndFeature%s",EndOfLine);
 1240                     if (res == 0)
 1241                     {
 1242                         PRINTER_PRINTF2("30 191.5 Tr 552 %4.1f",
 1243                                         (552.0*(double)finalaspectratio));
 1244                     }
 1245                     else
 1246                     {
 1247                         PRINTER_PRINTF4("30 %d Tr %f %f",
 1248                                      75 - ((Printer_Titleblock==1) ? 0 : 45),
 1249                                      ((double)xdots*(72.0/(double)res)),
 1250                                      ((double)xdots*(72.0/(double)res)*(double)finalaspectratio));
 1251                     }
 1252                   }
 1253                 else                         /* For Horizontal PostScript */
 1254                 {
 1255                     if (res == 0)
 1256                     {
 1257                         PRINTER_PRINTF2("582 30 Tr 90 rotate 732 %4.1f",
 1258                                         (732.0*(double)finalaspectratio));
 1259                     }
 1260                     else
 1261                     {
 1262                         PRINTER_PRINTF4("%d 30 Tr 90 rotate %f %f",
 1263                                      537 + ((Printer_Titleblock==1) ? 0 : 45),
 1264                                      ((double)xdots*(72.0/(double)res)),
 1265                                      ((double)xdots*(72.0/(double)res)*(double)finalaspectratio));
 1266                     }
 1267                 }
 1268                 PRINTER_PRINTF2(" scale%s",EndOfLine);
 1269               }
 1270 
 1271             else if (ptrid == 5)       /* To be used on WELL-BEHAVED .EPS */
 1272                 PRINTER_PRINTF5("30 %d Tr %d %d scale%s",
 1273                                     75 - ((Printer_Titleblock==1) ? 0 : 45),
 1274                                     xdots,ydots,EndOfLine);
 1275 
 1276             PRINTER_PRINTF2("dopic%s",EndOfLine);
 1277             break;
 1278 
 1279         case 7: /* HP Plotter */
 1280             if (res<1) res=1;
 1281             if (res>10) res=10;
 1282             ci = (((double)xdots*((double)res-1.0))/2.0);
 1283             ck = (((double)ydots*((double)res-1.0))/2.0);
 1284             PRINTER_PRINTF6(";IN;SP0;SC%d,%d,%d,%d;%s\0",
 1285                 (int)(-ci),(int)((double)xdots+ci),
 1286                 (int)((double)ydots+ck),(int)(-ck),EndOfLine);
 1287             break;
 1288         }
 1289 }
 1290 
 1291 
 1292 static void _fastcall print_title(int ptrid,int res,char *EndOfLine)
 1293 {
 1294     char buff[80];
 1295     int postscript;
 1296     if (Printer_Titleblock == 0)
 1297         return;
 1298     postscript = (ptrid == 5 || ptrid ==6);
 1299     if (!postscript)
 1300         Printer_printf(EndOfLine);
 1301     else
 1302         Printer_printf("(");
 1303     Printer_printf((curfractalspecific->name[0]=='*')
 1304                      ? &curfractalspecific->name[1]
 1305                      : curfractalspecific->name);
 1306     if (fractype == FORMULA || fractype == FFORMULA)
 1307         Printer_printf(" %s",FormName);
 1308     if (fractype == LSYSTEM)
 1309         Printer_printf(" %s",LName);
 1310     if (fractype == IFS || fractype == IFS3D)
 1311         Printer_printf(" %s",IFSName);
 1312     PRINTER_PRINTF4(" - %dx%d - %d DPI", xdots, ydots, res);
 1313     if (!postscript)
 1314         Printer_printf(EndOfLine);
 1315     else {
 1316         PRINTER_PRINTF2(") show%s",EndOfLine);
 1317         if (ptrid==5) {PRINTER_PRINTF1("30 50 moveto (");}
 1318         else          PRINTER_PRINTF1("-90 rotate 562 30 moveto 90 rotate (");
 1319         }
 1320     PRINTER_PRINTF5("Corners: Top-Left=%.16g/%.16g Bottom-Right=%.16g/%.16g",
 1321                    xxmin,yymax,xxmax,yymin);
 1322     if (xx3rd != xxmin || yy3rd != yymin) {
 1323         if (!postscript)
 1324             Printer_printf("%s        ",EndOfLine);
 1325         PRINTER_PRINTF3(" Bottom-Left=%4.4f/%4.4f",xx3rd,yy3rd);
 1326         }
 1327     if (!postscript)
 1328         Printer_printf(EndOfLine);
 1329     else {
 1330         PRINTER_PRINTF2(") show%s",EndOfLine);
 1331         if (ptrid==5) {PRINTER_PRINTF1("30 40 moveto (");}
 1332         else          PRINTER_PRINTF1("-90 rotate 572 30 moveto 90 rotate (");
 1333         }
 1334     showtrig(buff);
 1335     PRINTER_PRINTF6("Parameters: %4.4f/%4.4f/%4.4f/%4.4f %s",
 1336                    param[0],param[1],param[2],param[3],buff);
 1337     if (!postscript)
 1338         Printer_printf(EndOfLine);
 1339     else
 1340         PRINTER_PRINTF2(") show%s",EndOfLine);
 1341 }
 1342 
 1343 /* This function prints a string to the the printer with BIOS calls. */
 1344 
 1345 #ifndef USE_VARARGS
 1346 static void Printer_printf(char far *fmt,...)
 1350 #endif
 1351 {
 1352 int i;
 1353 char s[500];
 1354 int x=0;
 1355 va_list arg;
 1356 
 1357 #ifndef USE_VARARGS
 1358 va_start(arg,fmt);
 1363 #endif
 1364 
 1365 {
 1366    /* copy far to near string */
 1367    char fmt1[100];
 1368    i=0;
 1369    while(fmt[i]) {
 1370      fmt1[i] = fmt[i];
 1371      i++;
 1372    }
 1373    fmt1[i] = '\0';
 1374    vsprintf(s,fmt1,arg);
 1375 }
 1376 
 1377 if (Print_To_File>0)    /* This is for printing to file */
 1378     fprintf(PRFILE,"%s",s);
 1379 else                    /* And this is for printing to printer */
 1380     while (s[x])
 1381         if (printer(s[x++]) != 0)
 1382             while (!keypressed()) { if (printer(s[x-1])==0) break; }
 1383 }
 1384 
 1385 /* This function standardizes both _bios_printer and _bios_serialcom
 1386  * in one function.  It takes its arguments and rearranges them and calls
 1387  * the appropriate bios call.  If it then returns result !=0, there is a
 1388  * problem with the printer.
 1389  */
 1390 static int _fastcall printer(int c)
 1391 {
 1392     if (Print_To_File>0) return ((fprintf(PRFILE,"%c",c))<1);
 1393 #ifndef XFRACT
 1394     if (LPTn<9)  return (((_bios_printer(0,LPTn,c))+0x0010)&0x0010);
 1395     if (LPTn<19) return ((_bios_serialcom(1,(LPTn-10),c))&0x9E00);
 1396     if ((LPTn==20)||(LPTn==21))
 1397         {
 1398         int PS=0;
 1399         while ((PS & 0xF8) != 0xD8)
 1400             { PS = inp((LPTn==20) ? 0x379 : 0x279);
 1401               if (keypressed()) return(1); }
 1402         outp((LPTn==20) ? 0x37C : 0x27C,c);
 1403         PS = inp((LPTn==20) ? 0x37A : 0x27A);
 1404         outp((LPTn==20) ? 0x37A : 0x27A,(PS | 0x01));
 1405         outp((LPTn==20) ? 0x37A : 0x27A,PS);
 1406         return(0);
 1407         }
 1408     if ((LPTn==30)||(LPTn==31))
 1409         {
 1410         while (((inp((LPTn==30) ? 0x3FE : 0x2FE)&0x30)!=0x30) ||
 1411                ((inp((LPTn==30) ? 0x3FD : 0x2FD)&0x60)!=0x60))
 1412             { if (keypressed()) return (1); }
 1413         outp((LPTn==30) ? 0x3F8 : 0x2F8,c);
 1414         return(0);
 1415         }
 1416 #endif
 1417 
 1418     /* MCP 7-7-91, If we made it down to here, we may as well error out. */
 1419     return(-1);
 1420 }
 1421 
 1422 #ifdef __BORLANDC__
 1426 #endif
 1427 
 1428 static void printer_reset(void)
 1429 {
 1430 #ifndef XFRACT
 1431     if (Print_To_File < 1)
 1432         if (LPTn<9)       _bios_printer(1,LPTn,0);
 1433         else if (LPTn<19) _bios_serialcom(3,(LPTn-10),0);
 1434 #endif
 1435 }
 1436 
 1437 
 1438 /** debug code for pj_ color table checkout
 1439 color_test()
 1440 {
 1441    int x,y,color,i,j,xx,yy;
 1442    int bw,cw,bh,ch;
 1443    setvideomode(videoentry.videomodeax,
 1444                 videoentry.videomodebx,
 1445                 videoentry.videomodecx,
 1446                 videoentry.videomodedx);
 1447    bw = xdots/25; cw = bw * 2 / 3;
 1448    bh = ydots/10; ch = bh * 2 / 3;
 1449    dacbox[0][0] = dacbox[0][1] = dacbox[0][2] = 60;
 1450    if (debugflag == 902)
 1451       dacbox[0][0] = dacbox[0][1] = dacbox[0][2] = 0;
 1452    for (x = 0; x < 25; ++x)
 1453       for (y = 0; y < 10; ++y) {
 1454          if (x < 11) i = (32 - x) * 10 + y;
 1455              else    i = (24 - x) * 10 + y;
 1456          color = x * 10 + y + 1;
 1457          dacbox[color][0] = triple[0][0][i];
 1458          dacbox[color][1] = triple[0][1][i];
 1459          dacbox[color][2] = triple[0][2][i];
 1460          for (i = 0; i < cw; ++i) {
 1461             xx = x * bw + bw / 6 + i;
 1462             yy = y * bh + bh / 6;
 1463             for (j = 0; j < ch; ++j)
 1464                putcolor(xx,yy++,color);
 1465             }
 1466          }
 1467    spindac(0,1);
 1468    getakey();
 1469 }
 1470 **/
 1471 
 1472 
 1473 /*
 1474  * The following code for compressed PostScript is based on pnmtops.c.  It is
 1475  * copyright (C) 1989 by Jef Poskanzer, and carries the following notice:
 1476  * "Permission to use, copy, modify, and distribute this software and its
 1477  *  documentation for any purpose and without fee is hereby granted, provided
 1478  *  that the above copyright notice appear in all copies and that both that
 1479  *  copyright notice and this permission notice appear in supporting
 1480  *  documentation.  This software is provided "as is" without express or
 1481  *  implied warranty."
 1482  */
 1483 
 1484 
 1485 static void rleprolog(int x,int y)
 1486 {
 1487     itemsperline = 0;
 1488     items = 0;
 1489     bitspersample = 8;
 1490     repeat = 1;
 1491     rlebitsperitem = 0;
 1492     rlebitshift = 0;
 1493     count = 0;
 1494 
 1495     PRINTER_PRINTF2( "/rlestr1 1 string def%s", EndOfLine );
 1496     PRINTER_PRINTF2( "/rdrlestr {%s", EndOfLine );      /* s -- nr */
 1497     PRINTER_PRINTF2( "  /rlestr exch def%s", EndOfLine );    /* - */
 1498     PRINTER_PRINTF2( "  Cf rlestr1 Rh pop%s", EndOfLine );  /* s1 */
 1499     PRINTER_PRINTF2( "  0 get%s", EndOfLine );                     /* c */
 1500     PRINTER_PRINTF2( "  D 127 le {%s", EndOfLine );              /* c */
 1501     PRINTER_PRINTF2( "    Cf rlestr 0%s", EndOfLine );    /* c f s 0 */
 1502     PRINTER_PRINTF2( "    4 3 roll%s", EndOfLine );                /* f s 0 c */
 1503     PRINTER_PRINTF2( "    1 add  getinterval%s", EndOfLine );      /* f s */
 1504     PRINTER_PRINTF2( "    Rh pop%s", EndOfLine );       /* s */
 1505     PRINTER_PRINTF2( "    length%s", EndOfLine );                  /* nr */
 1506     PRINTER_PRINTF2( "  } {%s", EndOfLine );                       /* c */
 1507     PRINTER_PRINTF2( "    256 exch sub D%s", EndOfLine );        /* n n */
 1508     PRINTER_PRINTF2( "    Cf rlestr1 Rh pop%s", EndOfLine );/* n n s1 */
 1509     PRINTER_PRINTF2( "    0 get%s", EndOfLine );                   /* n n c */
 1510     PRINTER_PRINTF2( "    exch 0 exch 1 exch 1 sub {%s", EndOfLine );           /* n c 0 1 n-1*/
 1511     PRINTER_PRINTF2( "      rlestr exch 2 index put%s", EndOfLine );
 1512     PRINTER_PRINTF2( "    } for%s", EndOfLine );                   /* n c */
 1513     PRINTER_PRINTF2( "    pop%s", EndOfLine );                     /* nr */
 1514     PRINTER_PRINTF2( "  } ifelse%s", EndOfLine );                  /* nr */
 1515     PRINTER_PRINTF2( "} bind def%s", EndOfLine );
 1516     PRINTER_PRINTF2( "/Rs {%s", EndOfLine );               /* s -- s */
 1517     PRINTER_PRINTF2( "  D length 0 {%s", EndOfLine );            /* s l 0 */
 1518     PRINTER_PRINTF2( "    3 copy exch%s", EndOfLine );          /* s l n s n l*/
 1519     PRINTER_PRINTF2( "    1 index sub%s", EndOfLine );          /* s l n s n r*/
 1520     PRINTER_PRINTF2( "    getinterval%s", EndOfLine );          /* s l n ss */
 1521     PRINTER_PRINTF2( "    rdrlestr%s", EndOfLine );        /* s l n nr */
 1522     PRINTER_PRINTF2( "    add%s", EndOfLine );                     /* s l n */
 1523     PRINTER_PRINTF2( "    2 copy le { exit } if%s", EndOfLine );   /* s l n */
 1524     PRINTER_PRINTF2( "  } loop%s", EndOfLine );                    /* s l l */
 1525     PRINTER_PRINTF2( "  pop pop%s", EndOfLine );                   /* s */
 1526     PRINTER_PRINTF2( "} bind def%s", EndOfLine );
 1527     if (ColorPS) {
 1528         PRINTER_PRINTF3( "/rpicstr %d string def%s", x,EndOfLine );
 1529         PRINTER_PRINTF3( "/gpicstr %d string def%s", x,EndOfLine );
 1530         PRINTER_PRINTF3( "/bpicstr %d string def%s", x,EndOfLine );
 1531     } else {
 1532         PRINTER_PRINTF3( "/picstr %d string def%s", x,EndOfLine );
 1533     }
 1534     PRINTER_PRINTF2( "/dopic {%s", EndOfLine);
 1535     PRINTER_PRINTF2( "/gsave%s", EndOfLine);
 1536     if (ColorPS) {
 1537        PRINTER_PRINTF4( "%d %d 8%s", x, y, EndOfLine);
 1538     } else { /* b&w */
 1539        if (Printer_ColorXlat==-2) {
 1540           PRINTER_PRINTF4( "%d %d true%s", x, y, EndOfLine);
 1541        } else if (Printer_ColorXlat==2) {
 1542           PRINTER_PRINTF4( "%d %d false%s", x, y, EndOfLine);
 1543        } else {
 1544           PRINTER_PRINTF4( "%d %d 8%s", x, y, EndOfLine);
 1545        }
 1546     }
 1547     PRINTER_PRINTF5( "[%d 0 0 %d 0 %d]%s", x, -y, y, EndOfLine);
 1548     if (ColorPS) {
 1549         PRINTER_PRINTF2( "{rpicstr Rs}%s", EndOfLine);
 1550         PRINTER_PRINTF2( "{gpicstr Rs}%s", EndOfLine);
 1551         PRINTER_PRINTF2( "{bpicstr Rs}%s", EndOfLine);
 1552         PRINTER_PRINTF2( "true 3 colorimage%s", EndOfLine);
 1553     } else {
 1554        if (Printer_ColorXlat==-2 || Printer_ColorXlat==2) {
 1555           /* save file space and printing time (if scaling is right) */
 1556           PRINTER_PRINTF2( "{picstr Rs} imagemask%s", EndOfLine);
 1557        } else {
 1558           PRINTER_PRINTF2( "{picstr Rs} image%s", EndOfLine);
 1559        }
 1560     }
 1561     PRINTER_PRINTF2( "} def%s", EndOfLine);
 1562 }
 1563 
 1564 static void
 1565 rleputbuffer(void)
 1566     {
 1567     int i;
 1568 
 1569     if ( repeat )
 1570         {
 1571         item = 256 - count;
 1572         putitem();
 1573         item = repeatitem;
 1574         putitem();
 1575         }
 1576     else
 1577         {
 1578         item = count - 1;
 1579         putitem();
 1580         for ( i = 0; i < count; ++i )
 1581             {
 1582             item = itembuf[i];
 1583             putitem();
 1584             }
 1585         }
 1586     repeat = 1;
 1587     count = 0;
 1588     }
 1589 
 1590 static void
 1591 rleputitem(void)
 1592     {
 1593     int i;
 1594 
 1595     if ( count == 128 )
 1596         rleputbuffer();
 1597 
 1598     if ( repeat && count == 0 )
 1599         { /* Still initializing a repeat buf. */
 1600         itembuf[count] = repeatitem = rleitem;
 1601         ++count;
 1602         }
 1603     else if ( repeat )
 1604         { /* Repeating - watch for end of run. */
 1605         if ( rleitem == repeatitem )
 1606             { /* Run continues. */
 1607             itembuf[count] = rleitem;
 1608             ++count;
 1609             }
 1610         else
 1611             { /* Run ended - is it long enough to dump? */
 1612             if ( count > 2 )
 1613                 { /* Yes, dump a repeat-mode buffer and start a new one. */
 1614                 rleputbuffer();
 1615                 itembuf[count] = repeatitem = rleitem;
 1616                 ++count;
 1617                 }
 1618             else
 1619                 { /* Not long enough - convert to non-repeat mode. */
 1620                 repeat = 0;
 1621                 itembuf[count] = repeatitem = rleitem;
 1622                 ++count;
 1623                 repeatcount = 1;
 1624                 }
 1625             }
 1626         }
 1627     else
 1628         { /* Not repeating - watch for a run worth repeating. */
 1629         if ( rleitem == repeatitem )
 1630             { /* Possible run continues. */
 1631             ++repeatcount;
 1632             if ( repeatcount > 3 )
 1633                 { /* Long enough - dump non-repeat part and start repeat. */
 1634                 count = count - ( repeatcount - 1 );
 1635                 rleputbuffer();
 1636                 count = repeatcount;
 1637                 for ( i = 0; i < count; ++i )
 1638                     itembuf[i] = rleitem;
 1639                 }
 1640             else
 1641                 { /* Not long enough yet - continue as non-repeat buf. */
 1642                 itembuf[count] = rleitem;
 1643                 ++count;
 1644                 }
 1645             }
 1646         else
 1647             { /* Broken run. */
 1648             itembuf[count] = repeatitem = rleitem;
 1649             ++count;
 1650             repeatcount = 1;
 1651             }
 1652         }
 1653 
 1654     rleitem = 0;
 1655     rlebitsperitem = 0;
 1656     }
 1657 
 1658 static void
 1659 putitem (void)
 1660     {
 1661     char* hexits = "0123456789abcdef";
 1662 
 1663     if ( itemsperline == 30 )
 1664         {
 1665         Printer_printf("%s",EndOfLine);
 1666         itemsperline = 0;
 1667         }
 1668     Printer_printf("%c%c", hexits[item >> 4], hexits[item & 15] );
 1669     ++itemsperline;
 1670     ++items;
 1671     item = 0;
 1672     /* bitsperitem = 0; */
 1673     bitshift2 = 8 - bitspersample;
 1674     }
 1675 
 1676 static void
 1677 rleputxelval( int xv )
 1678     {
 1679     if ( rlebitsperitem == 8 )
 1680         rleputitem();
 1681     rleitem += xv<<bitshift2;
 1682     rlebitsperitem += bitspersample;
 1683     rlebitshift -= bitspersample;
 1684     }
 1685 
 1686 static void
 1687 rleflush(void)
 1688     {
 1689     if ( rlebitsperitem > 0 )
 1690         rleputitem();
 1691     if ( count > 0 )
 1692         rleputbuffer();
 1693     }
 1694 
 1695 static void
 1696 rleputrest(void)
 1697     {
 1698     rleflush();
 1699     Printer_printf( "%s",EndOfLine );
 1700     Printer_printf( "grestore%s",EndOfLine );
 1701     }
 1702