home *** CD-ROM | disk | FTP | other *** search
/ InfoMagic Source Code 1993 July / THE_SOURCE_CODE_CD_ROM.iso / X / mit / clients / xpr / xpr.c < prev    next >
Encoding:
C/C++ Source or Header  |  1991-07-18  |  49.7 KB  |  1,884 lines

  1. /* $XConsortium: xpr.c,v 1.54 91/07/18 11:55:34 rws Exp $ */
  2.  
  3. /*
  4.  * XPR - process xwd(1) files for various printers
  5.  *
  6.  * Author: Michael R. Gretzinger, MIT Project Athena
  7.  * Copyright (C) 1985, Massachusetts Institute of Technology
  8.  *
  9.  * Modified by Marvin Solomon, Univeristy of Wisconsin, to handle Apple
  10.  * Laserwriter (PostScript) devices (-device ps).
  11.  * Also accepts the -compact flag that produces more compact output
  12.  * by using run-length encoding on white (1) pixels.
  13.  * This version does not (yet) support the following options
  14.  *   -append -dump -noff -nosixopt -split
  15.  * 
  16.  * Changes
  17.  * Copyright 1986 by Marvin Solomon and the University of Wisconsin
  18.  * 
  19.  * Permission to use, copy, modify, and distribute this
  20.  * software and its documentation for any purpose and without
  21.  * fee is hereby granted, provided that the above copyright
  22.  * notice appear in all copies and that both that copyright
  23.  * notice and this permission notice appear in supporting
  24.  * documentation, and that the names of Marvin Solomon and
  25.  * the University of Wisconsin not be used in
  26.  * advertising or publicity pertaining to distribution of the
  27.  * software without specific, written prior permission.
  28.  * Neither Marvin Solomon nor the University of Wisconsin
  29.  * makes any representations about the suitability of
  30.  * this software for any purpose.  It is provided "as is"
  31.  * without express or implied warranty.
  32.  * 
  33.  * Modified by Bob Scheifler for 2x2 grayscale, then ...
  34.  * Modified by Angela Bock and E. Mike Durbin, Rich Inc., to produce output
  35.  * using 2x2, 3x3, or 4x4 grayscales. This version modifies the grayscale
  36.  * conversion option of -gray to accept an input of  2, 3, or 4 to signify
  37.  * the gray level desired.  The output is produced, using 5, 10, or 17-level
  38.  * gray scales, respectively.
  39.  *
  40.  * Modifications by Larry Rupp, Hewlett-Packard Company, to support HP
  41.  * LaserJet, PaintJet, and other PCL printers.  Added "ljet" and "pjet"
  42.  * to devices recognized.  Also added -density, -cutoff, and -noposition
  43.  * command line options.
  44.  *
  45.  */
  46.  
  47. #include <X11/Xos.h>
  48. #include <X11/Xfuncs.h>
  49. #include <X11/Xlib.h>
  50. #include <X11/Xutil.h>
  51. #include <stdio.h>
  52. #include <pwd.h>
  53. #include "lncmd.h"
  54. #include "xpr.h"
  55. #include <X11/XWDFile.h>
  56. #include <X11/Xmu/SysUtil.h>
  57.  
  58. #ifdef    NLS16
  59. #ifndef NLS
  60. #define    NLS
  61. #endif
  62. #endif
  63.  
  64. #ifndef NLS
  65. #define catgets(i, sn,mn,s) (s)
  66. #else /* NLS */
  67. #define NL_SETN 1    /* set number */
  68. #include <nl_types.h>
  69.  
  70. nl_catd nlmsg_fd;
  71. #endif /* NLS */
  72.  
  73. int debug = 0;
  74.  
  75. #define W_MAX 2400
  76. #define H_MAX 3150
  77. #define W_MARGIN 75
  78. #define H_MARGIN 37
  79. #define W_PAGE 2550
  80. #define H_PAGE 3225
  81.  
  82. #ifdef NOINLINE
  83. #define min(x,y) (((x)<(y))?(x):(y))
  84. #endif /* NOINLINE */
  85.  
  86. #define F_PORTRAIT 1
  87. #define F_LANDSCAPE 2
  88. #define F_DUMP 4
  89. #define F_NOSIXOPT 8
  90. #define F_APPEND 16
  91. #define F_NOFF 32
  92. #define F_REPORT 64
  93. #define F_COMPACT 128
  94. #define F_INVERT 256
  95. #define F_GRAY 512
  96. #define F_NPOSITION 1024
  97. #define F_SLIDE 2048
  98.  
  99. #define DEFAULT_CUTOFF ((unsigned int) (0xFFFF * 0.50))
  100.  
  101. char *infilename = NULL;
  102. char *progname;
  103.  
  104. char *convert_data();
  105.  
  106. typedef struct _grayRec {
  107.     int level;
  108.     int sizeX, sizeY;        /* 2x2, 3x3, 4x4 */
  109.     unsigned long *grayscales;    /* pointer to the encoded pixels */
  110. } GrayRec, *GrayPtr;
  111.  
  112. unsigned long grayscale2x2[] =
  113.     {0, 1, 9, 11, 15};
  114. unsigned long grayscale3x3[] =
  115.     {0, 16, 68, 81, 325, 341, 349, 381, 383, 511};
  116. unsigned long grayscale4x4[] =
  117.     {0, 64, 4160, 4161, 20545, 21057, 23105,
  118.      23113, 23145, 24169, 24171, 56939, 55275, 55279,
  119.      57327, 65519, 65535};
  120.  
  121. GrayRec gray2x2 = {sizeof(grayscale2x2)/sizeof(long), 2, 2, grayscale2x2};
  122. GrayRec gray3x3 = {sizeof(grayscale3x3)/sizeof(long), 3, 3, grayscale3x3};
  123. GrayRec gray4x4 = {sizeof(grayscale4x4)/sizeof(long), 4, 4, grayscale4x4};
  124.  
  125. main(argc, argv)
  126. char **argv;
  127. {
  128.     unsigned long swaptest = 1;
  129.     XWDFileHeader win;
  130.     register unsigned char (*sixmap)[];
  131.     register int i;
  132.     register int iw;
  133.     register int ih;
  134.     register int sixel_count;
  135.     char *w_name;
  136.     int scale, width, height, flags, split;
  137.     int left, top;
  138.     int top_margin, left_margin;
  139.     int hpad;
  140.     char *header, *trailer;
  141.     int plane;
  142.     int density, render;
  143.     unsigned int cutoff;
  144.     float gamma;
  145.     GrayPtr gray;
  146.     char *data;
  147.     long size;
  148.     enum orientation orientation;
  149.     enum device device;
  150.     XColor *colors = (XColor *)NULL;
  151.     
  152.     if (!(progname = argv[0]))
  153.       progname = "xpr";
  154. #ifdef    NLS
  155.     nlmsg_fd = catopen("xpr", 0);
  156. #endif
  157.     parse_args (argc, argv, &scale, &width, &height, &left, &top, &device, 
  158.         &flags, &split, &header, &trailer, &plane, &gray,
  159.         &density, &cutoff, &gamma, &render);
  160.     
  161.     if (device == PP) {
  162.     x2pmp(stdin, stdout, scale,
  163.           width >= 0? inch2pel((float)width/300.0): X_MAX_PELS,
  164.           height >= 0? inch2pel((float)height/300.0): Y_MAX_PELS,
  165.           left >= 0? inch2pel((float)left/300.0): inch2pel(0.60),
  166.           top >= 0? inch2pel((float)top/300.0): inch2pel(0.70),
  167.           header, trailer,
  168.           (flags & F_PORTRAIT)? PORTRAIT:
  169.           ((flags & F_LANDSCAPE)? LANDSCAPE: UNSPECIFIED),
  170.           (flags & F_INVERT));
  171.     exit(0);
  172.     } else if ((device == LJET) || (device == PJET) || (device == PJETXL)) {
  173.         x2jet(stdin, stdout, scale, density, width, height, left, top,
  174.           header, trailer,
  175.           (flags & F_PORTRAIT)? PORTRAIT:
  176.           ((flags & F_LANDSCAPE)? LANDSCAPE: UNSPECIFIED),
  177.           (flags & F_INVERT),
  178.           ((flags & F_APPEND) && !(flags & F_NOFF)),
  179.           !(flags & F_NPOSITION),
  180.           (flags & F_SLIDE),
  181.           device, cutoff, gamma, render);
  182.     exit(0);
  183.     }
  184.  
  185.     /* read in window header */
  186.     fullread(0, (char *)&win, sizeof win);
  187.     if (*(char *) &swaptest)
  188.     _swaplong((char *) &win, (long)sizeof(win));
  189.  
  190.     if (win.file_version != XWD_FILE_VERSION) {
  191.     fprintf(stderr,"xpr: file format version missmatch.\n");
  192.     exit(1);
  193.     }
  194.     if (win.header_size < sizeof(win)) {
  195.     fprintf(stderr,"xpr: header size is too small.\n");
  196.     exit(1);
  197.     }
  198.  
  199.     w_name = malloc((unsigned)(win.header_size - sizeof win));
  200.     fullread(0, w_name, (int) (win.header_size - sizeof win));
  201.     
  202.     if(win.ncolors) {
  203.     colors = (XColor *)malloc((unsigned) (win.ncolors * sizeof(XColor)));
  204.     fullread(0, (char *)colors, (int) (win.ncolors * sizeof(XColor)));
  205.     if (*(char *) &swaptest) {
  206.         for (i = 0; i < win.ncolors; i++) {
  207.         _swaplong((char *) &colors[i].pixel, (long)sizeof(long));
  208.         _swapshort((char *) &colors[i].red, (long) (3 * sizeof(short)));
  209.         }
  210.     }
  211.     if ((win.ncolors == 2) &&
  212.         (INTENSITY(&colors[0]) > INTENSITY(&colors[1])))
  213.         flags ^= F_INVERT;
  214.     }
  215.     if (plane >= (long)win.pixmap_depth) {
  216.     fprintf(stderr,"xpr: plane number exceeds image depth\n");
  217.     exit(1);
  218.     }
  219.     size = win.bytes_per_line * win.pixmap_height;
  220.     if (win.pixmap_format == XYPixmap)
  221.     size *= win.pixmap_depth;
  222.     data = malloc((unsigned)size);
  223.     fullread(0, data, (int)size);
  224.     if ((win.pixmap_depth > 1) || (win.byte_order != win.bitmap_bit_order)) {
  225.     data = convert_data(&win, data, plane, gray, colors, flags);
  226.     size = win.bytes_per_line * win.pixmap_height;
  227.     }
  228.     if (win.bitmap_bit_order == MSBFirst) {
  229.     _swapbits((unsigned char *)data, size);
  230.     win.bitmap_bit_order = LSBFirst;
  231.     }
  232.     if (flags & F_INVERT)
  233.     _invbits((unsigned char *)data, size);
  234.  
  235.     /* calculate orientation and scale */
  236.     setup_layout(device, (int) win.pixmap_width, (int) win.pixmap_height,
  237.          flags, width, height, header, trailer, &scale, &orientation);
  238.  
  239.     if (device == PS) {
  240.     iw = win.pixmap_width;
  241.     ih = win.pixmap_height;
  242.     } else {
  243.     /* calculate w and h cell count */
  244.     iw = win.pixmap_width;
  245.     ih = (win.pixmap_height + 5) / 6;
  246.     hpad = (ih * 6) - win.pixmap_height;
  247.  
  248.     /* build pixcells from input file */
  249.     sixel_count = iw * ih;
  250.     sixmap = (unsigned char (*)[])malloc((unsigned)sixel_count);
  251.     build_sixmap(iw, ih, sixmap, hpad, &win, data);
  252.     }
  253.  
  254.     /* output commands and sixel graphics */
  255.     if (device == LN03) {
  256. /*    ln03_grind_fonts(sixmap, iw, ih, scale, &pixmap); */
  257.     ln03_setup(iw, ih, orientation, scale, left, top,
  258.            &left_margin, &top_margin, flags, header, trailer);
  259.     ln03_output_sixels(sixmap, iw, ih, (flags & F_NOSIXOPT), split, 
  260.                scale, top_margin, left_margin);
  261.     ln03_finish();
  262.     } else if (device == LA100) {
  263.     la100_setup(iw, ih, scale);
  264.     la100_output_sixels(sixmap, iw, ih, (flags & F_NOSIXOPT));
  265.     la100_finish();
  266.     } else if (device == PS) {
  267.     ps_setup(iw, ih, orientation, scale, left, top,
  268.            flags, header, trailer, w_name);
  269.     ps_output_bits(iw, ih, flags, orientation, &win, data);
  270.     ps_finish();
  271.     } else {
  272.     fprintf(stderr, "xpr: device not supported\n");
  273.     }
  274.     
  275.     /* print some statistics */
  276.     if (flags & F_REPORT) {
  277.     fprintf(stderr, "Name: %s\n", w_name);
  278.     fprintf(stderr, "Width: %d, Height: %d\n", win.pixmap_width, 
  279.         win.pixmap_height);
  280.     fprintf(stderr, "Orientation: %s, Scale: %d\n", 
  281.         (orientation==PORTRAIT) ? "Portrait" : "Landscape", scale);
  282.     }
  283.     if (((device == LN03) || (device == LA100)) && (flags & F_DUMP))
  284.     dump_sixmap(sixmap, iw, ih);
  285.     exit(0);
  286. }
  287.  
  288. usage()
  289. {
  290.     fprintf(stderr, "usage: %s [options] [file]\n", progname);
  291.     fprintf(stderr, "    -append <file>  -noff  -output <file>\n");
  292.     fprintf(stderr, "    -compact\n");
  293.     fprintf(stderr, "    -device {ln03 | la100 | ps | lw | pp | ljet | pjet | pjetxl}\n");
  294.     fprintf(stderr, "    -dump\n");
  295.     fprintf(stderr, "    -gamma <correction>\n");
  296.     fprintf(stderr, "    -gray {2 | 3 | 4}\n");
  297.     fprintf(stderr, "    -height <inches>  -width <inches>\n");
  298.     fprintf(stderr, "    -header <string>  -trailer <string>\n");
  299.     fprintf(stderr, "    -landscape  -portrait\n");
  300.     fprintf(stderr, "    -left <inches>  -top <inches>\n");
  301.     fprintf(stderr, "    -noposition\n");
  302.     fprintf(stderr, "    -nosixopt\n");
  303.     fprintf(stderr, "    -plane <n>\n");
  304.     fprintf(stderr, "    -psfig\n");
  305.     fprintf(stderr, "    -render <type>\n");
  306.     fprintf(stderr, "    -report\n");
  307.     fprintf(stderr, "    -rv\n");
  308.     fprintf(stderr, "    -scale <scale>\n");
  309.     fprintf(stderr, "    -slide\n");
  310.     fprintf(stderr, "    -split <n-pages>\n");
  311.     exit(1);
  312. }
  313.  
  314. parse_args(argc, argv, scale, width, height, left, top, device, flags, 
  315.        split, header, trailer, plane, gray, density, cutoff, gamma, render)
  316. register int argc;
  317. register char **argv;
  318. int *scale;
  319. int *width;
  320. int *height;
  321. int *left;
  322. int *top;
  323. enum device *device;
  324. int *flags;
  325. int *split;
  326. char **header;
  327. char **trailer;
  328. int *plane;
  329. GrayPtr *gray;
  330. int *density;
  331. unsigned int *cutoff;
  332. float *gamma;
  333. int *render;
  334. {
  335.     register char *output_filename;
  336.     register int f;
  337.     register int len;
  338.     register int pos;
  339. #ifdef X_NOT_STDC_ENV
  340.     double atof();
  341.     int atoi();
  342. #endif
  343.  
  344.     output_filename = NULL;
  345.     *device = PS;    /* default */
  346.     *flags = 0;
  347.     *scale = 0;
  348.     *split = 1;
  349.     *width = -1;
  350.     *height = -1;
  351.     *top = -1;
  352.     *left = -1;
  353.     *header = NULL;
  354.     *trailer = NULL;
  355.     *plane = -1;
  356.     *gray = (GrayPtr)NULL;
  357.     *density = 0;
  358.     *cutoff = DEFAULT_CUTOFF;
  359.     *gamma = -1.0;
  360.     *render = 0;
  361.  
  362.     for (argc--, argv++; argc > 0; argc--, argv++) {
  363.     if (argv[0][0] != '-') {
  364.         infilename = *argv;
  365.         continue;
  366.     }
  367.     len = strlen(*argv);
  368.     switch (argv[0][1]) {
  369.     case 'a':        /* -append <filename> */
  370.         if (!bcmp(*argv, "-append", len)) {
  371.         argc--; argv++;
  372.         if (argc == 0) usage();
  373.         output_filename = *argv;
  374.         *flags |= F_APPEND;
  375.         } else
  376.         usage();
  377.         break;
  378.  
  379.     case 'c':        /* -compact | -cutoff <intensity> */
  380.         if (len <= 2 )
  381.         usage();
  382.         if (!bcmp(*argv, "-compact", len)) {
  383.         *flags |= F_COMPACT;
  384.         } else if (!bcmp(*argv, "-cutoff", len)) {
  385.         argc--; argv++;
  386.         if (argc == 0) usage();
  387.         *cutoff = min((atof(*argv) / 100.0 * 0xFFFF), 0xFFFF);
  388.         } else
  389.         usage();
  390.         break;
  391.  
  392.     case 'd':    /* -density <num> | -device <dev> | -dump */
  393.         if (len <= 2)
  394.         usage();
  395.         if (!bcmp(*argv, "-dump", len)) {
  396.         *flags |= F_DUMP;
  397.         } else if (len <= 3) {
  398.         usage();
  399.         } else if (!bcmp(*argv, "-density", len)) {
  400.         argc--; argv++;
  401.         if (argc == 0) usage();
  402.         *density = atoi(*argv);
  403.         } else if (!bcmp(*argv, "-device", len)) {
  404.         argc--; argv++;
  405.         if (argc == 0) usage();
  406.         len = strlen(*argv);
  407.         if (len < 2)
  408.             usage();
  409.         if (!bcmp(*argv, "ln03", len)) {
  410.             *device = LN03;
  411.         } else if (!bcmp(*argv, "la100", len)) {
  412.             *device = LA100;
  413.         } else if (!bcmp(*argv, "ps", len)) {
  414.             *device = PS;
  415.         } else if (!bcmp(*argv, "lw", len)) {
  416.             *device = PS;
  417.         } else if (!bcmp(*argv, "pp", len)) {
  418.             *device = PP;
  419.         } else if (!bcmp(*argv, "ljet", len)) {
  420.             *device = LJET;
  421.         } else if (!bcmp(*argv, "pjet", len)) {
  422.             *device = PJET;
  423.         } else if (!bcmp(*argv, "pjetxl", len)) {
  424.             *device = PJETXL;
  425.         } else
  426.             usage();
  427.         } else
  428.         usage();
  429.         break;
  430.  
  431.     case 'g':        /* -gamma <float> | -gray <num> */
  432.         if (len <= 2)
  433.         usage();
  434.         if (!bcmp(*argv, "-gamma", len)) {
  435.         argc--; argv++;
  436.         if (argc == 0) usage();
  437.         *gamma = atof(*argv);
  438.         } else if (!bcmp(*argv, "-gray", len) ||
  439.         !bcmp(*argv, "-grey", len)) {
  440.         argc--; argv++;
  441.         if (argc == 0) usage();
  442.         switch (atoi(*argv)) {
  443.         case 2:
  444.             *gray = &gray2x2;
  445.             break;
  446.         case 3:
  447.             *gray = &gray3x3;
  448.             break;
  449.         case 4:
  450.             *gray = &gray4x4;
  451.             break;
  452.         default:
  453.             usage();
  454.         }
  455.         *flags |= F_GRAY;
  456.         } else
  457.         usage();
  458.         break;
  459.  
  460.     case 'h':        /* -height <inches> | -header <string> */
  461.         if (len <= 3)
  462.         usage();
  463.         if (!bcmp(*argv, "-height", len)) {
  464.         argc--; argv++;
  465.         if (argc == 0) usage();
  466.         *height = (int)(300.0 * atof(*argv));
  467.         } else if (!bcmp(*argv, "-header", len)) {
  468.         argc--; argv++;
  469.         if (argc == 0) usage();
  470.         *header = *argv;
  471.         } else
  472.         usage();
  473.         break;
  474.  
  475.     case 'l':        /* -landscape | -left <inches> */
  476.         if (len <= 2)
  477.         usage();
  478.         if (!bcmp(*argv, "-landscape", len)) {
  479.         *flags |= F_LANDSCAPE;
  480.         } else if (!bcmp(*argv, "-left", len)) {
  481.         argc--; argv++;
  482.         if (argc == 0) usage();
  483.         *left = (int)(300.0 * atof(*argv));
  484.         } else
  485.         usage();
  486.         break;
  487.  
  488.     case 'n':        /* -nosixopt | -noff | -noposition */
  489.         if (len <= 3)
  490.         usage();
  491.         if (!bcmp(*argv, "-nosixopt", len)) {
  492.         *flags |= F_NOSIXOPT;
  493.         } else if (!bcmp(*argv, "-noff", len)) {
  494.         *flags |= F_NOFF;
  495.         } else if (!bcmp(*argv, "-noposition", len)) {
  496.         *flags |= F_NPOSITION;
  497.         } else
  498.         usage();
  499.         break;
  500.  
  501.     case 'o':        /* -output <filename> */
  502.         if (!bcmp(*argv, "-output", len)) {
  503.         argc--; argv++;
  504.         if (argc == 0) usage();
  505.         output_filename = *argv;
  506.         } else
  507.         usage();
  508.         break;
  509.  
  510.     case 'p':        /* -portrait | -plane <n> */
  511.         if (len <= 2)
  512.         usage();
  513.         if (!bcmp(*argv, "-portrait", len)) {
  514.         *flags |= F_PORTRAIT;
  515.         } else if (!bcmp(*argv, "-plane", len)) {
  516.         argc--; argv++;
  517.         if (argc == 0) usage();
  518.         *plane = atoi(*argv);
  519.         } else if (!bcmp(*argv, "-psfig", len)) {
  520.         *flags |= F_NPOSITION;
  521.         } else
  522.         usage();
  523.         break;
  524.  
  525.     case 'r':        /* -render <type> | -report | -rv */
  526.         if (len <= 2)
  527.         usage();
  528.         if (!bcmp(*argv, "-rv", len)) {
  529.         *flags |= F_INVERT;
  530.         } else if (len <= 3) {
  531.         usage();
  532.         } else if (!bcmp(*argv, "-render", len)) {
  533.         argc--; argv++;
  534.         if (argc == 0) usage();
  535.         *render = atoi(*argv);
  536.         } else if (!bcmp(*argv, "-report", len)) {
  537.         *flags |= F_REPORT;
  538.         } else
  539.         usage();
  540.         break;
  541.  
  542.     case 's':    /* -scale <scale> | -slide | -split <n-pages> */
  543.         if (len <= 2)
  544.         usage();
  545.         if (!bcmp(*argv, "-scale", len)) {
  546.         argc--; argv++;
  547.         if (argc == 0) usage();
  548.         *scale = atoi(*argv);
  549.         } else if (!bcmp(*argv, "-slide", len)) {
  550.         *flags |= F_SLIDE;
  551.         } else if (!bcmp(*argv, "-split", len)) {
  552.         argc--; argv++;
  553.         if (argc == 0) usage();
  554.         *split = atoi(*argv);
  555.         } else
  556.         usage();
  557.         break;
  558.  
  559.     case 't':        /* -top <inches> | -trailer <string> */
  560.         if (len <= 2)
  561.         usage();
  562.         if (!bcmp(*argv, "-top", len)) {
  563.         argc--; argv++;
  564.         if (argc == 0) usage();
  565.         *top = (int)(300.0 * atof(*argv));
  566.         } else if (!bcmp(*argv, "-trailer", len)) {
  567.         argc--; argv++;
  568.         if (argc == 0) usage();
  569.         *trailer = *argv;
  570.         } else
  571.         usage();
  572.         break;
  573.  
  574.     case 'w':        /* -width <inches> */
  575.         if (!bcmp(*argv, "-width", len)) {
  576.         argc--; argv++;
  577.         if (argc == 0) usage();
  578.         *width = (int)(300.0 * atof(*argv));
  579.         } else
  580.         usage();
  581.         break;
  582.  
  583.     default:
  584.         usage();
  585.         break;
  586.     }
  587.     }
  588.  
  589.     if (infilename) {
  590.     f = open(infilename, O_RDONLY, 0);
  591.     if (f < 0) {
  592.         fprintf(stderr, "xpr: error opening \"%s\" for input\n",
  593.             infilename);
  594.         perror("");
  595.         exit(1);
  596.     }
  597.     dup2(f, 0);
  598.     close(f);
  599.     } else
  600.     infilename = "stdin";
  601.  
  602.     if (output_filename != NULL) {
  603.     if (!(*flags & F_APPEND)) {
  604.         f = open(output_filename, O_CREAT|O_WRONLY|O_TRUNC, 0664);
  605.     } else {
  606.         f = open(output_filename, O_WRONLY, 0);
  607.     }
  608.     if (f < 0) {
  609.         fprintf(stderr, "xpr: error opening \"%s\" for output\n", 
  610.             output_filename);
  611.         perror("xpr");
  612.         exit(1);
  613.     }
  614.     if (*flags & F_APPEND) {
  615.         pos = lseek(f, 0, 2);          /* get eof position */
  616.         if ((*flags & F_NOFF) &&
  617.         !(*device == LJET || *device == PJET || *device == PJETXL))
  618.         pos -= 3; /* set position before trailing */
  619.                   /*     formfeed and reset */
  620.         lseek(f, pos, 0);              /* set pointer */
  621.     }
  622.     dup2(f, 1);
  623.     close(f);
  624.     }
  625. }
  626.  
  627. setup_layout(device, win_width, win_height, flags, width, height, 
  628.          header, trailer, scale, orientation)
  629. enum device device;
  630. int win_width;
  631. int win_height;
  632. int flags;
  633. int width;
  634. int height;
  635. char *header;
  636. char *trailer;
  637. int *scale;
  638. enum orientation *orientation;
  639. {
  640.     register int w_scale;
  641.     register int h_scale;
  642.     register int iscale = *scale;
  643.     register int w_max;
  644.     register int h_max;
  645.  
  646.     if (header != NULL) win_height += 75;
  647.     if (trailer != NULL) win_height += 75;
  648.  
  649.     /* check maximum width and height; set orientation and scale*/
  650.     if (device == LN03 || device == PS) {
  651.     if ((win_width < win_height || (flags & F_PORTRAIT)) && 
  652.         !(flags & F_LANDSCAPE)) {
  653.         *orientation = PORTRAIT;
  654.         w_max = (width > 0)? width : W_MAX;
  655.         h_max = (height > 0)? height : H_MAX;
  656.         w_scale = w_max / win_width;
  657.         h_scale = h_max / win_height;
  658.         *scale = min(w_scale, h_scale);
  659.     } else {
  660.         *orientation = LANDSCAPE;
  661.         w_max = (width > 0)? width : H_MAX;
  662.         h_max = (height > 0)? height : W_MAX;
  663.         w_scale = w_max / win_width;
  664.         h_scale = h_max / win_height;
  665.         *scale = min(w_scale, h_scale);
  666.     }
  667.     } else {            /* device == LA100 */
  668.     *orientation = PORTRAIT;
  669.     *scale = W_MAX / win_width;
  670.     }
  671.     if (*scale == 0) *scale = 1;
  672.     if (*scale > 6) *scale = 6;
  673.     if (iscale > 0 && iscale < *scale) *scale = iscale;
  674. }
  675.  
  676. char *
  677. convert_data(win, data, plane, gray, colors, flags)
  678.     register XWDFileHeader *win;
  679.     char *data;
  680.     int plane;
  681.     register GrayPtr gray;
  682.     XColor *colors;
  683.     int flags;
  684. {
  685.     register XImage *in_image, *out_image;
  686.     register int x, y;
  687.  
  688.     if ((win->pixmap_format == XYPixmap) && (plane >= 0)) {
  689.     data += win->bytes_per_line * win->pixmap_height *
  690.         (win->pixmap_depth - (plane + 1));
  691.     win->pixmap_format = XYBitmap;
  692.     win->pixmap_depth = 1;
  693.     return data;
  694.     }
  695.  
  696.     /* initialize the input image */
  697.  
  698.     /* This is a crock.  Xlib does not provide a way to create an
  699.      * arbitrary image and get the internal image functions correctly
  700.      * initialized.  So, we cheat.
  701.      */
  702.     {
  703.     Display fakedpy;
  704.     ScreenFormat fakefmt;
  705.  
  706.     fakedpy.byte_order = (int) win->byte_order;
  707.     fakedpy.bitmap_unit = (int) win->bitmap_unit;
  708.     fakedpy.bitmap_bit_order = (int) win->bitmap_bit_order;
  709.     fakedpy.pixmap_format = &fakefmt;
  710.     fakedpy.nformats = 1;
  711.     fakefmt.depth = (int) win->pixmap_depth;
  712.     fakefmt.bits_per_pixel = (int) win->bits_per_pixel;
  713.  
  714.     in_image = XCreateImage(&fakedpy, NULL,
  715.                 (int) win->pixmap_depth,
  716.                 (int) win->pixmap_format,
  717.                 (int) win->xoffset, data,
  718.                 (int) win->pixmap_width,
  719.                 (int) win->pixmap_height,
  720.                 (int) win->bitmap_pad,
  721.                 (int) win->bytes_per_line);
  722.     }
  723.  
  724.     in_image->red_mask = win->red_mask;
  725.     in_image->green_mask = win->green_mask;
  726.     in_image->blue_mask = win->blue_mask;
  727.     in_image->obdata = NULL;
  728.  
  729.     if ((flags & F_GRAY) && (in_image->depth > 1) && (plane < 0)) {
  730.     win->pixmap_width *= gray->sizeX;
  731.     win->pixmap_height *= gray->sizeY;
  732.     }
  733.     win->xoffset = 0;
  734.     win->pixmap_format = XYBitmap;
  735.     win->byte_order = LSBFirst;
  736.     win->bitmap_unit = 8;
  737.     win->bitmap_bit_order = LSBFirst;
  738.     win->bitmap_pad = 8;
  739.     win->pixmap_depth = 1;
  740.     win->bits_per_pixel = 1;
  741.     win->bytes_per_line = (win->pixmap_width + 7) >> 3;
  742.  
  743.     /* This is a crock.  Xlib does not provide a way to create an
  744.      * arbitrary image and get the internal image functions correctly
  745.      * initialized.  So, we cheat.
  746.      */
  747.     {
  748.     Display fakedpy;
  749.     ScreenFormat fakefmt;
  750.  
  751.     fakedpy.byte_order = (int) win->byte_order;
  752.     fakedpy.bitmap_unit = (int) win->bitmap_unit;
  753.     fakedpy.bitmap_bit_order = (int) win->bitmap_bit_order;
  754.     fakedpy.pixmap_format = &fakefmt;
  755.     fakedpy.nformats = 1;
  756.     fakefmt.depth = (int) win->pixmap_depth;
  757.     fakefmt.bits_per_pixel = (int) win->bits_per_pixel;
  758.  
  759.     out_image = XCreateImage(&fakedpy, NULL,
  760.                  (int) win->pixmap_depth,
  761.                  (int) win->pixmap_format,
  762.                  (int) win->xoffset, NULL,
  763.                  (int) win->pixmap_width,
  764.                  (int) win->pixmap_height,
  765.                  (int) win->bitmap_pad,
  766.                  (int) win->bytes_per_line);
  767.     }
  768.  
  769.     out_image->red_mask = 0;
  770.     out_image->green_mask = 0;
  771.     out_image->blue_mask = 0;
  772.     out_image->obdata = NULL;
  773.     out_image->data = malloc((unsigned)out_image->bytes_per_line *
  774.                       out_image->height);
  775.  
  776.     if ((in_image->depth > 1) && (plane > 0)) {
  777.     for (y = 0; y < in_image->height; y++)
  778.         for (x = 0; x < in_image->width; x++)
  779.         XPutPixel(out_image, x, y,
  780.               (XGetPixel(in_image, x, y) >> plane) & 1);
  781.     } else if (plane == 0) {
  782.     for (y = 0; y < in_image->height; y++)
  783.         for (x = 0; x < in_image->width; x++)
  784.         XPutPixel(out_image, x, y, XGetPixel(in_image, x, y));
  785.     } else if ((in_image->depth > 1) &&
  786.            ((win->visual_class == TrueColor) ||
  787.         (win->visual_class == DirectColor))) {
  788.     XColor color;
  789.     int direct = 0;
  790.     unsigned long rmask, gmask, bmask;
  791.     int rshift = 0, gshift = 0, bshift = 0;
  792.  
  793.     rmask = win->red_mask;
  794.     while (!(rmask & 1)) {
  795.         rmask >>= 1;
  796.         rshift++;
  797.     }
  798.     gmask = win->green_mask;
  799.     while (!(gmask & 1)) {
  800.         gmask >>= 1;
  801.         gshift++;
  802.     }
  803.     bmask = win->blue_mask;
  804.     while (!(bmask & 1)) {
  805.         bmask >>= 1;
  806.         bshift++;
  807.     }
  808.     if ((win->ncolors == 0) || (win->visual_class == DirectColor))
  809.         direct = 1;
  810.     if (flags & F_GRAY) {
  811.         register int ox, oy;
  812.         int ix, iy;
  813.         unsigned long bits;
  814.         for (y = 0, oy = 0; y < in_image->height; y++, oy += gray->sizeY)
  815.         for (x = 0, ox = 0; x < in_image->width; x++, ox += gray->sizeX)
  816.         {
  817.             color.pixel = XGetPixel(in_image, x, y);
  818.             color.red = (color.pixel >> rshift) & rmask;
  819.             color.green = (color.pixel >> gshift) & gmask;
  820.             color.blue = (color.pixel >> bshift) & bmask;
  821.             if (!direct) {
  822.             color.red = colors[color.red].red;
  823.             color.green = colors[color.green].green;
  824.             color.blue = colors[color.blue].blue;
  825.             }
  826.             bits = gray->grayscales[(int)(gray->level *
  827.                           INTENSITY(&color)) /
  828.                         (INTENSITYPER(100) + 1)];
  829.             for (iy = 0; iy < gray->sizeY; iy++)
  830.             for (ix = 0; ix < gray->sizeX; ix++, bits >>= 1)
  831.                 XPutPixel(out_image, ox + ix, oy + iy, bits);
  832.         }
  833.     } else {
  834.         for (y = 0; y < in_image->height; y++)
  835.         for (x = 0; x < in_image->width; x++) {
  836.             color.pixel = XGetPixel(in_image, x, y);
  837.             color.red = (color.pixel >> rshift) & rmask;
  838.             color.green = (color.pixel >> gshift) & gmask;
  839.             color.blue = (color.pixel >> bshift) & bmask;
  840.             if (!direct) {
  841.             color.red = colors[color.red].red;
  842.             color.green = colors[color.green].green;
  843.             color.blue = colors[color.blue].blue;
  844.             }
  845.             XPutPixel(out_image, x, y,
  846.                   INTENSITY(&color) > HALFINTENSITY);
  847.         }
  848.     }
  849.     } else if (flags & F_GRAY) {
  850.     register int ox, oy;
  851.     int ix, iy;
  852.     unsigned long bits;
  853.  
  854.     if (win->ncolors == 0) {
  855.         fprintf(stderr, "no colors in data, can't remap\n");
  856.         exit(1);
  857.     }
  858.     for (x = 0; x < win->ncolors; x++) {
  859.         register XColor *color = &colors[x];
  860.  
  861.         color->pixel = gray->grayscales[(gray->level * INTENSITY(color)) /
  862.                         (INTENSITYPER(100) + 1)];
  863.     }
  864.     for (y = 0, oy = 0; y < in_image->height; y++, oy += gray->sizeY)
  865.         for (x = 0, ox = 0; x < in_image->width; x++, ox += gray->sizeX) {
  866.         bits = colors[XGetPixel(in_image, x, y)].pixel;
  867.             for (iy = 0; iy < gray->sizeY; iy++)
  868.             for (ix = 0; ix < gray->sizeX; ix++, bits >>= 1)
  869.             XPutPixel(out_image, ox + ix, oy + iy, bits);
  870.         }
  871.     } else {
  872.     if (win->ncolors == 0) {
  873.         fprintf(stderr, "no colors in data, can't remap\n");
  874.         exit(1);
  875.     }
  876.     for (x = 0; x < win->ncolors; x++) {
  877.         register XColor *color = &colors[x];
  878.         color->pixel = (INTENSITY(color) > HALFINTENSITY);
  879.     }
  880.     for (y = 0; y < in_image->height; y++)
  881.         for (x = 0; x < in_image->width; x++)
  882.         XPutPixel(out_image, x, y,
  883.               colors[XGetPixel(in_image, x, y)].pixel);
  884.     }
  885.     free(data);
  886.     return (out_image->data);
  887. }
  888.  
  889. dump_sixmap(sixmap, iw, ih)
  890. register unsigned char (*sixmap)[];
  891. int iw;
  892. int ih;
  893. {
  894.     register int i, j;
  895.     register unsigned char *c;
  896.  
  897.     c = (unsigned char *)sixmap;
  898.     fprintf(stderr, "Sixmap:\n");
  899.     for (i = 0; i < ih; i++) {
  900.     for (j = 0; j < iw; j++) {
  901.         fprintf(stderr, "%02X ", *c++);
  902.     }
  903.     fprintf(stderr, "\n\n");
  904.     }
  905. }
  906.  
  907. build_sixmap(iw, ih, sixmap, hpad, win, data)
  908. int ih;
  909. int iw;
  910. unsigned char (*sixmap)[];
  911. int hpad;
  912. XWDFileHeader *win;
  913. char *data;
  914. {
  915.     int iwb = win->bytes_per_line;
  916.     unsigned char *line[6];
  917.     register unsigned char *c;
  918.     register int i, j;
  919. #ifdef NOINLINE
  920.     register int w;
  921. #endif
  922.     register int sixel;
  923.     unsigned char *buffer = (unsigned char *)data;
  924.  
  925.     c = (unsigned char *)sixmap;
  926.  
  927.  
  928.     while (--ih >= 0) {
  929.         for (i = 0; i <= 5; i++) {
  930.         line[i] = buffer;
  931.         buffer += iwb;
  932.         }
  933.     if ((ih == 0) && (hpad > 0)) {
  934.         unsigned char *ffbuf;
  935.  
  936.         ffbuf = (unsigned char *)malloc((unsigned)iwb);
  937.         for (j = 0; j < iwb; j++)
  938.         ffbuf[j] = 0xFF;
  939.         for (; --hpad >= 0; i--)
  940.         line[i] = ffbuf;
  941.     }
  942.  
  943. #ifndef NOINLINE
  944.     for (i = 0; i < iw; i++) {
  945.         sixel =  extzv(line[0], i, 1);
  946.         sixel |= extzv(line[1], i, 1) << 1;
  947.         sixel |= extzv(line[2], i, 1) << 2;
  948.         sixel |= extzv(line[3], i, 1) << 3;
  949.         sixel |= extzv(line[4], i, 1) << 4;
  950.         sixel |= extzv(line[5], i, 1) << 5;
  951.         *c++ = sixel;
  952.     }
  953. #else
  954.     for (i = 0, w = iw; w > 0; i++) {
  955.         for (j = 0; j <= 7; j++) {
  956.         sixel =  ((line[0][i] >> j) & 1);
  957.         sixel |= ((line[1][i] >> j) & 1) << 1;
  958.         sixel |= ((line[2][i] >> j) & 1) << 2;
  959.         sixel |= ((line[3][i] >> j) & 1) << 3;
  960.         sixel |= ((line[4][i] >> j) & 1) << 4;
  961.         sixel |= ((line[5][i] >> j) & 1) << 5;
  962.         *c++ = sixel;
  963.         if (--w == 0) break;
  964.         }
  965.     }
  966. #endif
  967.     }
  968. }
  969.  
  970. build_output_filename(name, device, oname)
  971. register char *name, *oname;
  972. enum device device;
  973. {
  974.     while (*name && *name != '.') *oname++ = *name++;
  975.     switch (device) {
  976.     case LN03:    bcopy(".ln03", oname, 6); break;
  977.     case LA100:    bcopy(".la100", oname, 7); break;
  978.     }
  979. }
  980.  
  981. /*
  982. ln03_grind_fonts(sixmap, iw, ih, scale, pixmap)
  983. unsigned char (*sixmap)[];
  984. int iw;
  985. int ih;
  986. int scale;
  987. struct pixmap (**pixmap)[];
  988. {
  989. }
  990. */
  991.  
  992. ln03_setup(iw, ih, orientation, scale, left, top, left_margin, top_margin, 
  993.        flags, header, trailer)
  994. int iw;
  995. int ih;
  996. enum orientation orientation;
  997. int scale;
  998. int left;
  999. int top;
  1000. int *left_margin;
  1001. int *top_margin;
  1002. int flags;
  1003. char *header;
  1004. char *trailer;
  1005. {
  1006.     register int i;
  1007.     register int lm, tm, xm;
  1008.     char buf[256];
  1009.     register char *bp = buf;
  1010.     
  1011.     if (!(flags & F_APPEND)) {
  1012.     sprintf(bp, LN_STR); bp += 4;
  1013.     sprintf(bp, LN_SSU, 7); bp += 5;
  1014.     sprintf(bp, LN_PUM_SET); bp += sizeof LN_PUM_SET - 1;
  1015.     }
  1016.  
  1017.     if (orientation == PORTRAIT) {
  1018.     lm = (left > 0)? left : (((W_MAX - scale * iw) / 2) + W_MARGIN);
  1019.     tm = (top > 0)? top : (((H_MAX - scale * ih * 6) / 2) + H_MARGIN);
  1020.     sprintf(bp, LN_PFS, "?20"); bp += 7;
  1021.     sprintf(bp, LN_DECOPM_SET); bp += sizeof LN_DECOPM_SET - 1;
  1022.     sprintf(bp, LN_DECSLRM, lm, W_PAGE - lm); bp += strlen(bp);
  1023.     } else {
  1024.     lm = (left > 0)? left : (((H_MAX - scale * iw) / 2) + H_MARGIN);
  1025.     tm = (top > 0)? top : (((W_MAX - scale * ih * 6) / 2) + W_MARGIN);
  1026.     sprintf(bp, LN_PFS, "?21"); bp += 7;
  1027.     sprintf(bp, LN_DECOPM_SET); bp += sizeof LN_DECOPM_SET - 1;
  1028.     sprintf(bp, LN_DECSLRM, lm, H_PAGE - lm); bp += strlen(bp);
  1029.     }
  1030.  
  1031.     if (header != NULL) {
  1032.     sprintf(bp, LN_VPA, tm - 100); bp += strlen(bp);
  1033.     i = strlen(header);
  1034.     xm = (((scale * iw) - (i * 30)) / 2) + lm;
  1035.     sprintf(bp, LN_HPA, xm); bp += strlen(bp);
  1036.     sprintf(bp, LN_SGR, 3); bp += strlen(bp);
  1037.     bcopy(header, bp, i);
  1038.     bp += i;
  1039.     }
  1040.     if (trailer != NULL) {
  1041.     sprintf(bp, LN_VPA, tm + (scale * ih * 6) + 75); bp += strlen(bp);
  1042.     i = strlen(trailer);
  1043.     xm = (((scale * iw) - (i * 30)) / 2) + lm;
  1044.     sprintf(bp, LN_HPA, xm); bp += strlen(bp);
  1045.     sprintf(bp, LN_SGR, 3); bp += strlen(bp);
  1046.     bcopy(trailer, bp, i);
  1047.     bp += i;
  1048.     }
  1049.  
  1050.     sprintf(bp, LN_HPA, lm); bp += strlen(bp);
  1051.     sprintf(bp, LN_VPA, tm); bp += strlen(bp);
  1052.     sprintf(bp, LN_SIXEL_GRAPHICS, 9, 0, scale); bp += strlen(bp);
  1053.     sprintf(bp, "\"1;1"); bp += 4; /* Pixel aspect ratio */
  1054.     write(1, buf, bp-buf);
  1055.     *top_margin = tm;
  1056.     *left_margin = lm;
  1057. }
  1058.  
  1059.  
  1060. ln03_finish()
  1061. {
  1062.     char buf[256];
  1063.     register char *bp = buf;
  1064.  
  1065.     sprintf(bp, LN_DECOPM_RESET); bp += sizeof LN_DECOPM_SET - 1;
  1066.     sprintf(bp, LN_LNM); bp += 5;
  1067.     sprintf(bp, LN_PUM); bp += 5;
  1068.     sprintf(bp, LN_PFS, "?20"); bp += 7; 
  1069.     sprintf(bp, LN_SGR, 0); bp += strlen(bp);   
  1070.     sprintf(bp, LN_HPA, 1); bp += strlen(bp);
  1071.     sprintf(bp, LN_VPA, 1); bp += strlen(bp);
  1072.  
  1073.  
  1074.     write(1, buf, bp-buf);    
  1075.  
  1076. }
  1077.  
  1078. /*ARGSUSED*/
  1079. la100_setup(iw, ih, scale)
  1080. {
  1081.     char buf[256];
  1082.     register char *bp;
  1083.     int lm, tm;
  1084.  
  1085.     bp = buf;
  1086.     lm = ((80 - (int)((double)iw / 6.6)) / 2) - 1;
  1087.     if (lm < 1) lm = 1;
  1088.     tm = ((66 - (int)((double)ih / 2)) / 2) - 1;
  1089.     if (tm < 1) tm = 1;
  1090.     sprintf(bp, "\033[%d;%ds", lm, 81-lm); bp += strlen(bp);
  1091.     sprintf(bp, "\033[?7l"); bp += 5;
  1092.     sprintf(bp, "\033[%dd", tm); bp += strlen(bp);
  1093.     sprintf(bp, "\033[%d`", lm); bp += strlen(bp);
  1094.     sprintf(bp, "\033P0q"); bp += 4;
  1095.     write(1, buf, bp-buf);
  1096. }
  1097.  
  1098. #define LA100_RESET "\033[1;80s\033[?7h"
  1099.  
  1100. la100_finish()
  1101. {
  1102.     write(1, LA100_RESET, sizeof LA100_RESET - 1);
  1103. }
  1104.  
  1105. #define COMMENTVERSION "PS-Adobe-1.0"
  1106.  
  1107. #ifdef XPROLOG
  1108. /* for debugging, get the prolog from a file */
  1109. dump_prolog(flags) {
  1110.     char *fname=(flags & F_COMPACT) ? "prolog.compact" : "prolog";
  1111.     FILE *fi = fopen(fname,"r");
  1112.     char buf[1024];
  1113.  
  1114.     if (fi==NULL) {
  1115.     perror(fname);
  1116.     exit(1);
  1117.     }
  1118.     while (fgets(buf,1024,fi)) fputs(buf,stdout);
  1119.     fclose(fi);
  1120. }
  1121.  
  1122. #else /* XPROLOG */
  1123. /* postscript "programs" to unpack and print the bitmaps being sent */
  1124.  
  1125. char *ps_prolog_compact[] = {
  1126.     "%%Pages: 1",
  1127.     "%%EndProlog",
  1128.     "%%Page: 1 1",
  1129.     "",
  1130.     "/bitgen",
  1131.     "    {",
  1132.     "        /nextpos 0 def",
  1133.     "        currentfile bufspace readhexstring pop % get a chunk of input",
  1134.     "        % interpret each byte of the input",
  1135.     "        {",
  1136.     "            flag { % if the previous byte was FF",
  1137.     "                /len exch def % this byte is a count",
  1138.     "                result",
  1139.     "                nextpos",
  1140.     "                FFstring 0 len getinterval % grap a chunk of FF's",
  1141.     "                    putinterval % and stuff them into the result",
  1142.     "                /nextpos nextpos len add def",
  1143.     "                /flag false def",
  1144.     "            }{ % otherwise",
  1145.     "                dup 255 eq { % if this byte is FF",
  1146.     "                    /flag true def % just set the flag",
  1147.     "                    pop % and toss the FF",
  1148.     "                }{ % otherwise",
  1149.     "                    % move this byte to the result",
  1150.     "                    result nextpos",
  1151.     "                        3 -1 roll % roll the current byte back to the top",
  1152.     "                        put",
  1153.     "                    /nextpos nextpos 1 add def",
  1154.     "                } ifelse",
  1155.     "            } ifelse",
  1156.     "        } forall",
  1157.     "        % trim unused space from end of result",
  1158.     "        result 0 nextpos getinterval",
  1159.     "    } def",
  1160.     "",
  1161.     "",
  1162.     "/bitdump % stk: width, height, iscale",
  1163.     "    % dump a bit image with lower left corner at current origin,",
  1164.     "    % scaling by iscale (iscale=1 means 1/300 inch per pixel)",
  1165.     "    {",
  1166.     "        % read arguments",
  1167.     "        /iscale exch def",
  1168.     "        /height exch def",
  1169.     "        /width exch def",
  1170.     "",
  1171.     "        % scale appropriately",
  1172.     "        width iscale mul height iscale mul scale",
  1173.     "",
  1174.     "        % data structures:",
  1175.     "",
  1176.     "        % allocate space for one line of input",
  1177.     "        /bufspace 36 string def",
  1178.     "",
  1179.     "        % string of FF's",
  1180.     "        /FFstring 256 string def",
  1181.     "        % for all i FFstring[i]=255",
  1182.     "        0 1 255 { FFstring exch 255 put } for",
  1183.     "",
  1184.     "        % 'escape' flag",
  1185.     "        /flag false def",
  1186.     "",
  1187.     "        % space for a chunk of generated bits",
  1188.     "        /result 1000 string def",
  1189.     "",
  1190.     "        % read and dump the image",
  1191.     "        width height 1 [width 0 0 height neg 0 height]",
  1192.     "            { bitgen }",
  1193.     "            image",
  1194.     "    } def",
  1195.     0
  1196. };
  1197.  
  1198. char *ps_prolog[] = {
  1199.     "%%Pages: 1",
  1200.     "%%EndProlog",
  1201.     "%%Page: 1 1",
  1202.     "",
  1203.     "/bitdump % stk: width, height, iscale",
  1204.     "% dump a bit image with lower left corner at current origin,",
  1205.     "% scaling by iscale (iscale=1 means 1/300 inch per pixel)",
  1206.     "{",
  1207.     "    % read arguments",
  1208.     "    /iscale exch def",
  1209.     "    /height exch def",
  1210.     "    /width exch def",
  1211.     "",
  1212.     "    % scale appropriately",
  1213.     "    width iscale mul height iscale mul scale",
  1214.     "",
  1215.     "    % allocate space for one scanline of input",
  1216.     "    /picstr % picstr holds one scan line",
  1217.     "        width 7 add 8 idiv % width of image in bytes = ceiling(width/8)",
  1218.     "        string",
  1219.     "        def",
  1220.     "",
  1221.     "    % read and dump the image",
  1222.     "    width height 1 [width 0 0 height neg 0 height]",
  1223.     "    { currentfile picstr readhexstring pop }",
  1224.     "    image",
  1225.     "} def",
  1226.     0
  1227. };
  1228.  
  1229. dump_prolog(flags) {
  1230.     char **p = (flags & F_COMPACT) ? ps_prolog_compact : ps_prolog;
  1231.     while (*p) printf("%s\n",*p++);
  1232. }
  1233. #endif /* XPROLOG */
  1234.  
  1235. #define PAPER_WIDTH 85*30 /* 8.5 inches */
  1236. #define PAPER_LENGTH 11*300 /* 11 inches */
  1237.  
  1238. static int
  1239. points(n)
  1240. {
  1241.     /* scale n from pixels (1/300 inch) to points (1/72 inch) */
  1242.     n *= 72;
  1243.     return n/300;
  1244. }
  1245.  
  1246. static char *
  1247. escape(s)
  1248. char *s;
  1249. {
  1250.     /* make a version of s in which control characters are deleted and
  1251.      * special characters are escaped.
  1252.      */
  1253.     static char buf[200];
  1254.     char *p = buf;
  1255.  
  1256.     for (;*s;s++) {
  1257.     if (*s < ' ' || *s > 0176) continue;
  1258.     if (*s==')' || *s=='(' || *s == '\\') {
  1259.         sprintf(p,"\\%03o",*s);
  1260.         p += 4;
  1261.     }
  1262.     else *p++ = *s;
  1263.     }
  1264.     *p = 0;
  1265.     return buf;
  1266. }
  1267.  
  1268. ps_setup(iw, ih, orientation, scale, left, top, 
  1269.        flags, header, trailer, name)
  1270. int iw;
  1271. int ih;
  1272. enum orientation orientation;
  1273. int scale;
  1274. int left;
  1275. int top;
  1276. int flags;
  1277. char *header;
  1278. char *trailer;
  1279. char *name;
  1280. {
  1281.     char    hostname[256];
  1282.     struct passwd  *pswd;
  1283.     long    clock;
  1284.     int lm, bm; /* left (bottom) margin */
  1285.  
  1286.     /* calculate margins */
  1287.     if (orientation==PORTRAIT) {
  1288.     lm = (left > 0)? left : ((PAPER_WIDTH - scale * iw) / 2);
  1289.     bm = (top > 0)? (PAPER_LENGTH - top - scale * ih)
  1290.         : ((PAPER_LENGTH - scale * ih) / 2);
  1291.     } else { /* orientation == LANDSCAPE */
  1292.     lm = (top > 0)? (PAPER_WIDTH - top - scale * ih)
  1293.         : ((PAPER_WIDTH - scale * ih) / 2);
  1294.     bm = (left > 0)? (PAPER_LENGTH - left - scale * iw)
  1295.         : ((PAPER_LENGTH - scale * iw) / 2);
  1296.     }
  1297.     printf ("%%!%s\n", COMMENTVERSION);
  1298.     printf ("%%%%BoundingBox: %d %d %d %d\n",
  1299.         (flags & F_NPOSITION) ? points(lm) : 0,
  1300.         (flags & F_NPOSITION) ? points(bm) : 0,
  1301.         points(iw * scale), points(ih * scale));
  1302.     pswd = getpwuid (getuid ());
  1303.     (void) XmuGetHostname (hostname, sizeof hostname);
  1304.     printf ("%%%%Creator: %s:%s (%s)\n", hostname,
  1305.         pswd->pw_name, pswd->pw_gecos);
  1306.     printf ("%%%%Title: %s (%s)\n", infilename,name);
  1307.     printf ("%%%%CreationDate: %s",
  1308.         (time (&clock), ctime (&clock)));
  1309.     printf ("%%%%EndComments\n");
  1310.  
  1311.     dump_prolog(flags);
  1312.  
  1313.     if (orientation==PORTRAIT) {
  1314.     if (header || trailer) {
  1315.         printf("gsave\n");
  1316.         printf("/Times-Roman findfont 15 scalefont setfont\n");
  1317.         /* origin at bottom left corner of image */
  1318.         printf("%d %d translate\n",points(lm),points(bm));
  1319.         if (header) {
  1320.         char *label = escape(header);
  1321.         printf("%d (%s) stringwidth pop sub 2 div %d moveto\n",
  1322.             points(iw*scale), label, points(ih*scale) + 10);
  1323.         printf("(%s) show\n",label);
  1324.         }
  1325.         if (trailer) {
  1326.         char *label = escape(trailer);
  1327.         printf("%d (%s) stringwidth pop sub 2 div -20 moveto\n",
  1328.             points(iw*scale), label);
  1329.         printf("(%s) show\n",label);
  1330.         }
  1331.         printf("grestore\n");
  1332.     }
  1333.     /* set resolution to device units (300/inch) */
  1334.     printf("72 300 div dup scale\n");
  1335.     /* move to lower left corner of image */
  1336.     if (!(flags & F_NPOSITION))
  1337.         printf("%d %d translate\n",lm,bm);
  1338.     /* dump the bitmap */
  1339.     printf("%d %d %d bitdump\n",iw,ih,scale);
  1340.     } else { /* orientation == LANDSCAPE */
  1341.     if (header || trailer) {
  1342.         printf("gsave\n");
  1343.         printf("/Times-Roman findfont 15 scalefont setfont\n");
  1344.         /* origin at top left corner of image */
  1345.         printf("%d %d translate\n",points(lm),points(bm + scale * iw));
  1346.         /* rotate to print the titles */
  1347.         printf("-90 rotate\n");
  1348.         if (header) {
  1349.         char *label = escape(header);
  1350.         printf("%d (%s) stringwidth pop sub 2 div %d moveto\n",
  1351.             points(iw*scale), label, points(ih*scale) + 10);
  1352.         printf("(%s) show\n",label);
  1353.         }
  1354.         if (trailer) {
  1355.         char *label = escape(trailer);
  1356.         printf("%d (%s) stringwidth pop sub 2 div -20 moveto\n",
  1357.             points(iw*scale), label);
  1358.         printf("(%s) show\n",label);
  1359.         }
  1360.         printf("grestore\n");
  1361.     }
  1362.     /* set resolution to device units (300/inch) */
  1363.     printf("72 300 div dup scale\n");
  1364.     /* move to lower left corner of image */
  1365.     if (!(flags & F_NPOSITION))
  1366.         printf("%d %d translate\n",lm,bm);
  1367.     /* dump the bitmap */
  1368.     printf("%d %d %d bitdump\n",ih,iw,scale);
  1369.     }
  1370. }
  1371.  
  1372. char *ps_epilog[] = {
  1373.     "",
  1374.     "showpage",
  1375.     "%%Trailer",
  1376.     0
  1377. };
  1378.  
  1379. ps_finish()
  1380. {
  1381.     char **p = ps_epilog;
  1382.  
  1383.     while (*p) printf("%s\n",*p++);
  1384. }
  1385.  
  1386. ln03_alter_background(sixmap, iw, ih)
  1387. unsigned char (*sixmap)[];
  1388. int iw;
  1389. int ih;
  1390. {
  1391.     register unsigned char *c, *stopc;
  1392.     register unsigned char *startc;
  1393.     register int n;
  1394.  
  1395.     c = (unsigned char *)sixmap;
  1396.     stopc = c + (iw * ih);
  1397.     n = 0;
  1398.     while (c < stopc) {
  1399.     switch (*c) {
  1400.     case 0x08: case 0x11: case 0x04: case 0x22:
  1401.     case 0x20: case 0x21: case 0x24: case 0x00:
  1402.         if (n == 0) startc = c;
  1403.         n++;
  1404.         break;
  1405.  
  1406.     default:
  1407.         if (n >= 2) {
  1408.         while (n-- > 0) *startc++ = 0x00;
  1409.         } else {
  1410.         n = 0;
  1411.         }
  1412.         break;
  1413.     }
  1414.     c++;
  1415.     }
  1416. }
  1417.  
  1418. ln03_output_sixels(sixmap, iw, ih, nosixopt, split, scale, top_margin, 
  1419.            left_margin)
  1420. unsigned char (*sixmap)[];
  1421. int iw;
  1422. int ih;
  1423. int nosixopt;
  1424. int split;
  1425. int top_margin;
  1426. int left_margin;
  1427. {
  1428.     unsigned char *buf;
  1429.     register unsigned char *bp;
  1430.     int i;
  1431.     int j;
  1432.     register int k;
  1433.     register unsigned char *c;
  1434.     register int lastc;
  1435.     register int count;
  1436.     char snum[6];
  1437.     register char *snp;
  1438.  
  1439.     bp = (unsigned char *)malloc((unsigned)(iw*ih+512));
  1440.     buf = bp;
  1441.     count = 0;
  1442.     lastc = -1;
  1443.     c = (unsigned char *)sixmap;
  1444.     split = ih / split;        /* number of lines per page */
  1445.  
  1446.     iw--;            /* optimization */
  1447.     for (i = 0; i < ih; i++) {
  1448.     for (j = 0; j <= iw; j++) {
  1449.         if (!nosixopt) {
  1450.         if (*c == lastc && j < iw) {
  1451.             count++;
  1452.             c++;
  1453.             continue;
  1454.         }
  1455.         if (count >= 3) {
  1456.             bp--;
  1457.             count++;
  1458.             *bp++ = '!';
  1459.             snp = snum;
  1460.             while (count > 0) {
  1461.             k = count / 10;
  1462.             *snp++ = count - (k * 10) + '0';
  1463.             count = k;
  1464.             }
  1465.             while (--snp >= snum) *bp++ = *snp;
  1466.             *bp++ = (~lastc & 0x3F) + 0x3F;
  1467.         } else if (count > 0) {
  1468.             lastc = (~lastc & 0x3F) + 0x3F;
  1469.             do {
  1470.             *bp++ = lastc;
  1471.             } while (--count > 0);
  1472.         }
  1473.         }
  1474.         lastc = *c++;
  1475.         *bp++ = (~lastc & 0x3F) + 0x3F;
  1476.     }
  1477.     *bp++ = '-';        /* New line */
  1478.     lastc = -1;
  1479.     if ((i % split) == 0 && i != 0) {
  1480.         sprintf((char *)bp, LN_ST); bp += sizeof LN_ST - 1;
  1481.         *bp++ = '\f';
  1482.         sprintf((char *)bp, LN_VPA, top_margin + (i * 6 * scale));
  1483.         bp += strlen((char *)bp);
  1484.         sprintf((char *)bp, LN_HPA, left_margin);
  1485.         bp += strlen((char *)bp);
  1486.         sprintf((char *)bp, LN_SIXEL_GRAPHICS, 9, 0, scale);
  1487.         bp += strlen((char *)bp);
  1488.         sprintf((char *)bp, "\"1;1"); bp += 4;
  1489.     }
  1490.     }
  1491.  
  1492.     sprintf((char *)bp, LN_ST); bp += sizeof LN_ST - 1;
  1493.     write(1, (char *)buf, bp-buf);
  1494. }
  1495.  
  1496. /*ARGSUSED*/
  1497. la100_output_sixels(sixmap, iw, ih, nosixopt)
  1498. unsigned char (*sixmap)[];
  1499. int iw;
  1500. int ih;
  1501. int nosixopt;
  1502. {
  1503.     unsigned char *buf;
  1504.     register unsigned char *bp;
  1505.     int i;
  1506.     register int j, k;
  1507.     register unsigned char *c;
  1508.     register int lastc;
  1509.     register int count;
  1510.     char snum[6];
  1511.  
  1512.     bp = (unsigned char *)malloc((unsigned)(iw*ih+512));
  1513.     buf = bp;
  1514.     count = 0;
  1515.     lastc = -1;
  1516.     c = (unsigned char *)sixmap;
  1517.  
  1518.     for (i = 0; i < ih; i++) {
  1519.     for (j = 0; j < iw; j++) {
  1520.         if (*c == lastc && (j+1) < iw) {
  1521.         count++;
  1522.         c++;
  1523.         continue;
  1524.         }
  1525.         if (count >= 2) {
  1526.         bp -= 2;
  1527.         count = 2 * (count + 1);
  1528.         *bp++ = '!';
  1529.         k = 0;
  1530.         while (count > 0) {
  1531.             snum[k++] = (count % 10) + '0';
  1532.             count /= 10;
  1533.         }
  1534.         while (--k >= 0) *bp++ = snum[k];
  1535.         *bp++ = (~lastc & 0x3F) + 0x3F;
  1536.         count = 0;
  1537.         } else if (count > 0) {
  1538.         lastc = (~lastc & 0x3F) + 0x3F;
  1539.         do {
  1540.             *bp++ = lastc;
  1541.             *bp++ = lastc;
  1542.         } while (--count > 0);
  1543.         }
  1544.         lastc = (~*c & 0x3F) + 0x3F;
  1545.         *bp++ = lastc;
  1546.         *bp++ = lastc;
  1547.         lastc = *c++;
  1548.     }
  1549.     *bp++ = '-';        /* New line */
  1550.     lastc = -1;
  1551.     }
  1552.  
  1553.     sprintf((char *)bp, LN_ST); bp += sizeof LN_ST - 1;
  1554.     *bp++ = '\f';
  1555.     write(1, (char *)buf, bp-buf);
  1556. }
  1557.  
  1558. #define LINELEN 72 /* number of CHARS (bytes*2) per line of bitmap output */
  1559.  
  1560. ps_output_bits(iw, ih, flags, orientation, win, data)
  1561. int iw;
  1562. int ih;
  1563. int flags;
  1564. XWDFileHeader *win;
  1565. enum orientation orientation;
  1566. char *data;
  1567. {
  1568.     unsigned long swaptest = 1;
  1569.     int iwb = win->bytes_per_line;
  1570.     register int i;
  1571.     int bytes;
  1572.     unsigned char *buffer = (unsigned char *)data;
  1573.     register int ocount=0;
  1574.     extern char hex1[],hex2[];
  1575.     static char hex[] = "0123456789abcdef";
  1576.  
  1577.     if (orientation == LANDSCAPE) {
  1578.     /* read in and rotate the entire image */
  1579.     /* The Postscript language has a rotate operator, but using it
  1580.      * seem to make printing (at least on the Apple Laserwriter
  1581.      * take about 10 times as long (40 minutes for a 1024x864 full-screen
  1582.      * dump)!  Therefore, we rotate the image here.
  1583.      */
  1584.     int ocol = ih;
  1585.     int owidth = (ih+31)/32; /* width of rotated image, in bytes */
  1586.     int oheight = (iw+31)/32; /* height of rotated image, in scanlines */
  1587.     register char *p, *q;
  1588.     char *obuf;
  1589.     unsigned char *ibuf;
  1590.     owidth *= 4;
  1591.     oheight *= 32;
  1592.  
  1593.     /* Allocate buffer for the entire rotated image (output).
  1594.      * Owidth and Oheight are rounded up to a multiple of 32 bits,
  1595.      * to avoid special cases at the boundaries
  1596.      */
  1597.     obuf = malloc((unsigned)(owidth*oheight));
  1598.     if (obuf==0) {
  1599.         fprintf(stderr,"xpr: cannot allocate %d bytes\n",owidth*oheight);
  1600.         exit(1);
  1601.     }
  1602.     bzero(obuf,owidth*oheight);
  1603.  
  1604.     ibuf = (unsigned char *)malloc((unsigned)(iwb + 3));
  1605.     for (i=0;i<ih;i++) {
  1606.         bcopy((char *)buffer, (char *)ibuf, iwb);
  1607.         buffer += iwb;
  1608.         if (!(*(char *) &swaptest))
  1609.         _swaplong((char *)ibuf,(long)iwb);
  1610.         ps_bitrot(ibuf,iw,--ocol,owidth,obuf);
  1611.     }
  1612.     if (!(*(char *) &swaptest))
  1613.         _swaplong(obuf,(long)(iw*owidth));
  1614.     q = &obuf[iw*owidth];
  1615.     bytes = (ih+7)/8;
  1616.     for (p=obuf;p<q;p+=owidth)
  1617.         ocount = ps_putbuf((unsigned char *)p,bytes,ocount,flags&F_COMPACT);
  1618.     }
  1619.     else {
  1620.     for (i=0;i<ih;i++) {
  1621.         ocount = ps_putbuf(buffer,(iw+7)/8,ocount,flags&F_COMPACT);
  1622.         buffer += iwb;
  1623.     }
  1624.     }
  1625.     if (flags & F_COMPACT) {
  1626.     if (ocount) {
  1627.         /* pad to an integral number of lines */
  1628.         while (ocount++ < LINELEN)
  1629.         /* for debugging, pad with a "random" value */
  1630.         putchar(hex[ocount&15]);
  1631.         putchar('\n');
  1632.     }
  1633.     }
  1634. }
  1635.  
  1636. unsigned char _reverse_byte[0x100] = {
  1637.     0x00, 0x80, 0x40, 0xc0, 0x20, 0xa0, 0x60, 0xe0,
  1638.     0x10, 0x90, 0x50, 0xd0, 0x30, 0xb0, 0x70, 0xf0,
  1639.     0x08, 0x88, 0x48, 0xc8, 0x28, 0xa8, 0x68, 0xe8,
  1640.     0x18, 0x98, 0x58, 0xd8, 0x38, 0xb8, 0x78, 0xf8,
  1641.     0x04, 0x84, 0x44, 0xc4, 0x24, 0xa4, 0x64, 0xe4,
  1642.     0x14, 0x94, 0x54, 0xd4, 0x34, 0xb4, 0x74, 0xf4,
  1643.     0x0c, 0x8c, 0x4c, 0xcc, 0x2c, 0xac, 0x6c, 0xec,
  1644.     0x1c, 0x9c, 0x5c, 0xdc, 0x3c, 0xbc, 0x7c, 0xfc,
  1645.     0x02, 0x82, 0x42, 0xc2, 0x22, 0xa2, 0x62, 0xe2,
  1646.     0x12, 0x92, 0x52, 0xd2, 0x32, 0xb2, 0x72, 0xf2,
  1647.     0x0a, 0x8a, 0x4a, 0xca, 0x2a, 0xaa, 0x6a, 0xea,
  1648.     0x1a, 0x9a, 0x5a, 0xda, 0x3a, 0xba, 0x7a, 0xfa,
  1649.     0x06, 0x86, 0x46, 0xc6, 0x26, 0xa6, 0x66, 0xe6,
  1650.     0x16, 0x96, 0x56, 0xd6, 0x36, 0xb6, 0x76, 0xf6,
  1651.     0x0e, 0x8e, 0x4e, 0xce, 0x2e, 0xae, 0x6e, 0xee,
  1652.     0x1e, 0x9e, 0x5e, 0xde, 0x3e, 0xbe, 0x7e, 0xfe,
  1653.     0x01, 0x81, 0x41, 0xc1, 0x21, 0xa1, 0x61, 0xe1,
  1654.     0x11, 0x91, 0x51, 0xd1, 0x31, 0xb1, 0x71, 0xf1,
  1655.     0x09, 0x89, 0x49, 0xc9, 0x29, 0xa9, 0x69, 0xe9,
  1656.     0x19, 0x99, 0x59, 0xd9, 0x39, 0xb9, 0x79, 0xf9,
  1657.     0x05, 0x85, 0x45, 0xc5, 0x25, 0xa5, 0x65, 0xe5,
  1658.     0x15, 0x95, 0x55, 0xd5, 0x35, 0xb5, 0x75, 0xf5,
  1659.     0x0d, 0x8d, 0x4d, 0xcd, 0x2d, 0xad, 0x6d, 0xed,
  1660.     0x1d, 0x9d, 0x5d, 0xdd, 0x3d, 0xbd, 0x7d, 0xfd,
  1661.     0x03, 0x83, 0x43, 0xc3, 0x23, 0xa3, 0x63, 0xe3,
  1662.     0x13, 0x93, 0x53, 0xd3, 0x33, 0xb3, 0x73, 0xf3,
  1663.     0x0b, 0x8b, 0x4b, 0xcb, 0x2b, 0xab, 0x6b, 0xeb,
  1664.     0x1b, 0x9b, 0x5b, 0xdb, 0x3b, 0xbb, 0x7b, 0xfb,
  1665.     0x07, 0x87, 0x47, 0xc7, 0x27, 0xa7, 0x67, 0xe7,
  1666.     0x17, 0x97, 0x57, 0xd7, 0x37, 0xb7, 0x77, 0xf7,
  1667.     0x0f, 0x8f, 0x4f, 0xcf, 0x2f, 0xaf, 0x6f, 0xef,
  1668.     0x1f, 0x9f, 0x5f, 0xdf, 0x3f, 0xbf, 0x7f, 0xff
  1669. };
  1670.  
  1671. _invbits (b, n)
  1672.     register unsigned char *b;
  1673.     register long n;
  1674. {
  1675.     do {
  1676.         *b = ~*b;
  1677.         b++;
  1678.         } while (--n > 0);
  1679.     
  1680. }
  1681.  
  1682. /* copied from lib/X/XPutImage.c */
  1683.  
  1684. _swapbits (b, n)
  1685.     register unsigned char *b;
  1686.     register long n;
  1687. {
  1688.     do {
  1689.         *b = _reverse_byte[*b];
  1690.         b++;
  1691.         } while (--n > 0);
  1692.     
  1693. }
  1694.  
  1695. _swapshort (bp, n)
  1696.      register char *bp;
  1697.      register long n;
  1698. {
  1699.     register char c;
  1700.     register char *ep = bp + n;
  1701.     do {
  1702.         c = *bp;
  1703.         *bp = *(bp + 1);
  1704.         bp++;
  1705.         *bp = c;
  1706.         bp++;
  1707.     }
  1708.     while (bp < ep);
  1709. }
  1710.  
  1711. _swaplong (bp, n)
  1712.      register char *bp;
  1713.      register long n;
  1714. {
  1715.     register char c;
  1716.     register char *ep = bp + n;
  1717.     register char *sp;
  1718.     do {
  1719.           sp = bp + 3;
  1720.         c = *sp;
  1721.         *sp = *bp;
  1722.         *bp++ = c;
  1723.         sp = bp + 1;
  1724.         c = *sp;
  1725.         *sp = *bp;
  1726.         *bp++ = c;
  1727.         bp += 2;
  1728.     }
  1729.     while (bp < ep);
  1730. }
  1731.  
  1732. /* Dump some bytes in hex, with bits in each byte reversed
  1733.  * Ocount is number of chacters that have been written to the current
  1734.  * output line.  It's new value is returned as the result of the function.
  1735.  * Ocount is ignored (and the return value is meaningless) if compact==0.
  1736.  */
  1737. int
  1738. ps_putbuf(s, n, ocount, compact)
  1739. register unsigned char *s;    /* buffer to dump */
  1740. register int n;            /* number of BITS to dump */
  1741. register int ocount;        /* position on output line for next char */
  1742. int compact;            /* if non-zero, do compaction (see below) */
  1743. {
  1744.     register int ffcount = 0;
  1745.     extern char hex1[],hex2[];
  1746.     static char hex[] = "0123456789abcdef";
  1747. #define PUT(c) { putchar(c); if (++ocount>=LINELEN) \
  1748.     { putchar('\n'); ocount=0; }}
  1749.  
  1750.     if (compact) {
  1751.     /* The following loop puts out the bits of the image in hex,
  1752.      * compressing runs of white space (represented by one bits)
  1753.      * according the the following simple algorithm:  A run of n
  1754.      * 'ff' bytes (i.e., bytes with value 255--all ones), where
  1755.      * 1<=n<=255, is represented by a single 'ff' byte followed by a
  1756.      * byte containing n.
  1757.      * On a typical dump of a full screen pretty much covered by
  1758.      * black-on-white text windows, this compression decreased the
  1759.      * size of the file from 223 Kbytes to 63 Kbytes.
  1760.      * Of course, another factor of two could be saved by sending
  1761.      * the bytes 'as is' rather than in hex, using some sort of
  1762.      * escape convention to avoid problems with control characters.
  1763.      * Another popular encoding is to pack three bytes into 4 'sixels'
  1764.      * as in the LN03, etc, but I'm too lazy to write the necessary
  1765.      * PostScript code to unpack fancier representations.
  1766.      */
  1767.     while (n--) {
  1768.         if (*s == 0xff) {
  1769.         if (++ffcount == 255) {
  1770.             PUT('f'); PUT('f');
  1771.             PUT('f'); PUT('f');
  1772.             ffcount = 0;
  1773.         }
  1774.         }
  1775.         else {
  1776.         if (ffcount) {
  1777.             PUT('f'); PUT('f');
  1778.             PUT(hex[ffcount >> 4]);
  1779.             PUT(hex[ffcount & 0xf]);
  1780.             ffcount = 0;
  1781.         }
  1782.         PUT(hex1[*s]);
  1783.         PUT(hex2[*s]);
  1784.         }
  1785.         s++;
  1786.     }
  1787.     if (ffcount) {
  1788.         PUT('f'); PUT('f');
  1789.         PUT(hex[ffcount >> 4]);
  1790.         PUT(hex[ffcount & 0xf]);
  1791.         ffcount = 0;
  1792.     }
  1793.     }
  1794.     else { /* no compaction: just dump the image in hex (bits reversed) */
  1795.     while (n--) {
  1796.         putchar(hex1[*s]);
  1797.         putchar(hex2[*s++]);
  1798.     }
  1799.     putchar('\n');
  1800.     }
  1801.     return ocount;
  1802. }
  1803.  
  1804. ps_bitrot(s,n,col,owidth,obuf)
  1805. unsigned char *s;
  1806. register int n;
  1807. int col;
  1808. register int owidth;
  1809. char *obuf;
  1810. /* s points to a chunk of memory and n is its width in bits.
  1811.  * The algorithm is, roughly,
  1812.  *    for (i=0;i<n;i++) {
  1813.  *        OR the ith bit of s into the ith row of the
  1814.  *        (col)th column of obuf
  1815.  *    }
  1816.  * Assume VAX bit and byte ordering for s:
  1817.  *    The ith bit of s is s[j]&(1<<k) where i=8*j+k.
  1818.  *    It can also be retrieved as t[j]&(1<<k), where t=(int*)s and i=32*j+k.
  1819.  * Also assume VAX bit and byte ordering for each row of obuf.
  1820.  * Ps_putbuf() takes care of converting to Motorola 68000 byte and bit
  1821.  * ordering.  The following code is very carefully tuned to yield a very
  1822.  * tight loop on the VAX, since it easily dominates the entire running
  1823.  * time of this program.  In particular, iwordp is declared last, since
  1824.  * there aren't enough registers, and iwordp is referenced only once
  1825.  * every 32 times through the loop.
  1826.  */
  1827. {
  1828.     register int mask = 1<<(col%32);
  1829.     register int iword; /* current input word (*iwordp) */
  1830.     register int b = 0; /* number of bits in iword left to examine */
  1831.     register char *opos = obuf + (col/32)*4;
  1832.     /* pointer to word of obuf to receive next output bit */
  1833.     register int *iwordp = (int *) s; /* pointer to next word of s */
  1834.  
  1835.     while (--n>=0) {
  1836.     if (--b < 0) {
  1837.         iword = *iwordp++;
  1838.         b = 31;
  1839.     }
  1840.     if (iword & 1) {
  1841.         *(int *)opos |= mask;
  1842.     }
  1843.     opos += owidth;
  1844.     iword >>= 1;
  1845.     }
  1846. }
  1847.  
  1848. /* fullread() is the same as read(), except that it guarantees to 
  1849.    read all the bytes requested. */
  1850.  
  1851. fullread (file, data, nbytes)
  1852.     int file;
  1853.     char *data;
  1854.     int nbytes;
  1855.     {
  1856.     int bytes_read;
  1857.     while ((bytes_read = read(file, data, nbytes)) != nbytes) {
  1858.     if (bytes_read < 0) {
  1859.         perror ("error while reading standard input");
  1860.         return;
  1861.         }
  1862.     else if (bytes_read == 0) {
  1863.         fprintf (stderr, "xpr: premature end of file\n");
  1864.         return;
  1865.         }
  1866.     nbytes -= bytes_read;
  1867.     data += bytes_read;
  1868.     }
  1869.     }
  1870.  
  1871. /* mapping tables to map a byte in to the hex representation of its
  1872.  * bit-reversal
  1873.  */
  1874. char hex1[]="084c2a6e195d3b7f084c2a6e195d3b7f084c2a6e195d3b7f084c2a6e195d3b7f\
  1875. 084c2a6e195d3b7f084c2a6e195d3b7f084c2a6e195d3b7f084c2a6e195d3b7f\
  1876. 084c2a6e195d3b7f084c2a6e195d3b7f084c2a6e195d3b7f084c2a6e195d3b7f\
  1877. 084c2a6e195d3b7f084c2a6e195d3b7f084c2a6e195d3b7f084c2a6e195d3b7f";
  1878.  
  1879. char hex2[]="000000000000000088888888888888884444444444444444cccccccccccccccc\
  1880. 2222222222222222aaaaaaaaaaaaaaaa6666666666666666eeeeeeeeeeeeeeee\
  1881. 111111111111111199999999999999995555555555555555dddddddddddddddd\
  1882. 3333333333333333bbbbbbbbbbbbbbbb7777777777777777ffffffffffffffff";
  1883.  
  1884.