summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRoland Mainz <roland.mainz@nrubsig.org>2004-10-31 02:14:06 +0000
committerRoland Mainz <roland.mainz@nrubsig.org>2004-10-31 02:14:06 +0000
commit9a961d11bea6be64c6f51b4f0829ff4fe2999c4a (patch)
tree57cfce3fd2b08d2e200ea4566f36021b93b607ff
Fix for https://freedesktop.org/bugzilla/show_bug.cgi?id=631 - Uploading
"xpr" and "pclcomp" as they are needed for the RASTER and PCL drivers on some platforms.
-rw-r--r--lncmd.h52
-rw-r--r--pmp.h66
-rw-r--r--x2jet.c1577
-rw-r--r--x2pmp.c363
-rw-r--r--xdpr.man137
-rw-r--r--xdpr.script166
-rw-r--r--xpr.c1915
-rw-r--r--xpr.h33
-rw-r--r--xpr.man338
9 files changed, 4647 insertions, 0 deletions
diff --git a/lncmd.h b/lncmd.h
new file mode 100644
index 0000000..ac8a344
--- /dev/null
+++ b/lncmd.h
@@ -0,0 +1,52 @@
+/* $XConsortium: lncmd.h,v 10.8 94/04/17 20:44:03 rws Exp $ */
+/*
+
+Copyright (c) 1985 X Consortium
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice shall be included
+in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+IN NO EVENT SHALL THE X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR
+OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+OTHER DEALINGS IN THE SOFTWARE.
+
+Except as contained in this notice, the name of the X Consortium shall
+not be used in advertising or otherwise to promote the sale, use or
+other dealings in this Software without prior written authorization
+from the X Consortium.
+
+*/
+
+
+/* lncmd.h - Command sequences DEC printers, in particular LN0x laser
+ printers */
+
+/*
+#define LN_RIS "\033c" Obsolete; causes LN03+ problems
+*/
+#define LN_STR "\033[!p"
+#define LN_SSU "\033[%d I"
+#define LN_PUM_SET "\033[11h"
+#define LN_PFS "\033[%s J"
+#define LN_DECSLRM "\033[%d;%ds"
+#define LN_HPA "\033[%d`"
+#define LN_VPA "\033[%dd"
+#define LN_SIXEL_GRAPHICS "\033P%d;%d;%dq"
+#define LN_ST "\033\\"
+#define LN_DECOPM_SET "\033[?52h"
+#define LN_DECOPM_RESET "\033[?52I"
+#define LN_SGR "\033[1%dm"
+#define LN_PUM "\033[11I"
+#define LN_LNM "\033[20h"
diff --git a/pmp.h b/pmp.h
new file mode 100644
index 0000000..09b1a32
--- /dev/null
+++ b/pmp.h
@@ -0,0 +1,66 @@
+/*
+ * $XConsortium: pmp.h,v 1.5 91/02/19 22:13:33 converse Exp $
+ */
+
+/* Written by Jose' J. Capo' */
+/* (jjc@comet.lcs.mit.edu), June 1987 */
+
+/* WARNING!!!: Include this header after the standard headers (like */
+ /* <stdio.h>) of the following might cause another header to */
+ /* redefine BUFSIZ */
+#ifndef BUFSIZ
+#define BUFSIZ 1024
+#endif
+
+#define MAX_FRAME_LEN 512
+#define MAX_VECTOR_LEN 65535
+
+#define DBG(cond) if (dbg cond)
+#define DEBUG(cond) if (debug cond)
+#define min(a,b) ((a) < (b)? (a) : (b))
+
+#define pel2inch(pels) ((float) ((pels) / PPI))
+#define ppmask(rounded,thickness) (0x20 * (rounded) + (thickness))
+
+
+#define min(a,b) ((a) < (b)? (a) : (b))
+#define lo(x) ((x) & 0xFF)
+#define hi(x) (((x) & 0xFF00) >>8)
+#define hi2(x) (((x) & 0xFF0000) >>16)
+#define p_wput(w, f) {\
+ (void) putc(hi(w), (f)); \
+ (void) putc(lo(w), (f));\
+ }
+#define PMP(f, len) { fprintf(f, "\033[C"); \
+ p_putlh(f, len);\
+ }
+#define p_putlh(f, w) {\
+ (void) putc(lo(w), (f));\
+ (void) putc(hi(w), (f)); \
+ }
+
+/* hi-lo 2-byte integer */
+/* int hl2int(unsigned char *) */
+#define hl2int(hl2) ((int) (0x100 * *(hl2) + *((hl2)+1)))
+
+/* putlh2(FILE *, int) */
+#define puthl2(i, f) { (void) putc(hi((i)), (f));\
+ (void) putc(lo((i)), (f));\
+ }
+
+/* hi-lo 3-byte integer */
+/* long hl3long(unsigned char *) */
+#define hl3long(hl3) ((long) (0x10000 * *(hl3) + \
+ 0x100 * *((hl3)+1) + *((hl3)+2)))
+
+/* puthl3(FILE *, long) */
+#define puthl3(l, f) { (void) putc(hi2((l)), (f));\
+ (void) putc(hi((l)), (f));\
+ (void) putc(lo((l)), (f));\
+ }
+
+/* int int2sgn(int) */
+#define int2sgn(i) (((i) > 0x8000 - 1)? (i)- 0x10000: (i))
+
+/* int long3sgn(long) */
+#define long3sgn(l) (((l) > 0x800000 - 1)? (l) - 0x1000000 : (l))
diff --git a/x2jet.c b/x2jet.c
new file mode 100644
index 0000000..62a0305
--- /dev/null
+++ b/x2jet.c
@@ -0,0 +1,1577 @@
+/* $XConsortium: x2jet.c,v 1.6 94/04/17 20:44:03 rws Exp $ */
+
+/* -*-C-*-
+********************************************************************************
+*
+* File: x2jet.c
+* RCS: x2jet.c,v 1.23 89/07/17 12:02:51 lori Exp
+* Description: xpr support for HP LaserJet and PaintJet printers
+* Author: Larry Rupp, HP Graphics Technology Division
+* Created: Fri Jul 15 15:22:26 1988
+* Modified: Thu Sep 15 11:59:34 1988 (Larry Rupp) ler@hpfcler
+* Tue Dec 6 10:04:43 PST 1988 (Marc Ayotte) marca@hp-pcd
+* Language: C
+* Package: N/A
+* Status: Released to MIT
+*
+* (c) Copyright 1988, Hewlett-Packard Company.
+*
+********************************************************************************
+*/
+
+
+
+
+
+/********************************************************
+
+Copyright (c) 1988 by Hewlett-Packard Company
+
+Permission to use, copy, modify, and distribute this software
+and its documentation for any purpose and without fee is hereby
+granted, provided that the above copyright notice appear in all
+copies and that both that copyright notice and this permission
+notice appear in supporting documentation, and that
+Hewlett-Packard not be used in advertising or publicity
+pertaining to distribution of the software without specific, written
+prior permission.
+
+********************************************************/
+/*
+
+Copyright (c) 1988 X Consortium
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice shall be included
+in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+IN NO EVENT SHALL THE X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR
+OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+OTHER DEALINGS IN THE SOFTWARE.
+
+Except as contained in this notice, the name of the X Consortium shall
+not be used in advertising or otherwise to promote the sale, use or
+other dealings in this Software without prior written authorization
+from the X Consortium.
+
+*/
+
+
+#include <stdio.h>
+#include <X11/Xlib.h>
+#include <X11/XWDFile.h>
+
+#include "xpr.h"
+
+#ifdef NLS16
+#ifndef NLS
+#define NLS
+#endif
+#endif
+
+#ifndef NLS
+#define catgets(i, sn,mn,s) (s)
+#else /* NLS */
+#define NL_SETN 2 /* set number */
+#include <nl_types.h>
+
+extern char *catgets();
+extern nl_catd nlmsg_fd;
+
+#endif /* NLS */
+
+#ifndef TRUE
+# define FALSE 0
+# define TRUE 1
+#endif
+
+/* default printable page area (inches) */
+#define STDWIDTH 8.0
+#define STDHEIGHT 10.5
+
+/* header & trailer character cell size (centipoints) */
+#define CHARWIDTH 720
+#define CHARHEIGHT 1200
+
+#define XWDHEADERSIZE (sizeof(XWDFileHeader))
+#define XCOLORSIZE (sizeof(XColor))
+
+
+typedef struct { long width, height; } Area;
+typedef struct { long x, y; } Location;
+
+
+static Area limit; /* image clip limits (dots) */
+static Area page; /* printable page size (centipoints) */
+
+static Location headerloc; /* centipoint location of header string */
+static Location trailerloc; /* centipoint location of trailer string */
+static Location imageloc; /* centipoint location of image */
+
+static int headerlimit; /* number of chars which will printed for */
+static int trailerlimit; /* the image's header/trailer strings */
+
+static XWDFileHeader xwd_header;
+
+static XColor *xwd_colors;
+
+static char *xwd_image;
+
+static unsigned long Z_pixel_mask;
+
+static int true_scale;
+
+extern char *progname;
+
+void fatal_err();
+void fatal_err2();
+
+/* Computes the centipoint width of one printer dot. */
+#define dot_centipoints(s,d) ((7200.0 * s) / d)
+
+
+void set_image_limits (scale, density, orient, print_area)
+int scale, density;
+enum orientation orient;
+Area print_area;
+{
+ Area print_dots;
+ double dotsize;
+
+ /* Set dotsize to the centipoint width of one printer dot. */
+ dotsize = dot_centipoints(scale, density);
+
+ if (orient == PORTRAIT) {
+ print_dots.width = print_area.width / dotsize;
+ print_dots.height = print_area.height / dotsize;
+ } else {
+ print_dots.height = print_area.width / dotsize;
+ print_dots.width = print_area.height / dotsize;
+ }
+
+ limit.width = (print_dots.width < xwd_header.pixmap_width)
+ ? print_dots.width : xwd_header.pixmap_width;
+ limit.height = (print_dots.height < xwd_header.pixmap_height)
+ ? print_dots.height : xwd_header.pixmap_height;
+
+ if ((limit.width != xwd_header.pixmap_width)
+ || (limit.height != xwd_header.pixmap_height))
+ fprintf(stderr,(catgets(nlmsg_fd,NL_SETN,1, "%s: Warning: %ld x %ld image clipped to %ld x %ld.\n")),
+ progname,
+ xwd_header.pixmap_width, xwd_header.pixmap_height,
+ limit.width, limit.height);
+}
+
+
+
+void set_header_trailer_limits (header, trailer, printwidth)
+char *header, *trailer;
+long printwidth;
+{
+ /* Determine the number of header and trailer characters
+ * that will fit into the available printing area.
+ */
+ headerlimit = header ? (((strlen(header) * CHARWIDTH) <= printwidth)
+ ? strlen(header) : (printwidth / CHARWIDTH))
+ : 0;
+ if (header && headerlimit != strlen(header)) {
+ fprintf(stderr,(catgets(nlmsg_fd,NL_SETN,2,
+ "%s: Warning: Header string clipped to %d characters.\n")),
+ progname, headerlimit);
+ header[headerlimit] = '\0';
+ }
+
+ trailerlimit = trailer ? (((strlen(trailer) * CHARWIDTH) <= printwidth)
+ ? strlen(trailer) : (printwidth / CHARWIDTH))
+ : 0;
+ if (trailer && trailerlimit != strlen(trailer)) {
+ fprintf(stderr,(catgets(nlmsg_fd,NL_SETN,3,
+ "%s: Warning: Trailer string clipped to %d characters.\n")),
+ progname, trailerlimit);
+ trailer[headerlimit] = '\0';
+ }
+}
+
+
+void set_print_locations (scale, density, top, left,
+ header, trailer, orient, position_on_page)
+int scale, density;
+int top, left;
+char *header, *trailer;
+enum orientation orient;
+int position_on_page;
+{
+ Area image;
+ double dotsize;
+
+ /* Set dotsize to the centipoint width of one printer dot. */
+ dotsize = dot_centipoints(scale, density);
+
+ /* Compute the centipoint size of the clipped image area. */
+ if (orient == PORTRAIT) {
+ image.width = limit.width * dotsize;
+ image.height = limit.height * dotsize;
+ } else {
+ image.height = limit.width * dotsize;
+ image.width = limit.height * dotsize;
+ }
+
+ if (position_on_page) {
+ /* set vertical positions */
+ imageloc.y = (top >= 0)
+ ? top * 24 + ((header) ? CHARHEIGHT : 0)
+ : ((page.height - ((header) ? CHARHEIGHT : 0)
+ - image.height - ((trailer) ? CHARHEIGHT : 0)) / 2)
+ + ((header) ? CHARHEIGHT : 0);
+ headerloc.y = imageloc.y - CHARHEIGHT / 4;
+ trailerloc.y = imageloc.y + image.height + (3 * CHARHEIGHT) / 4;
+
+ /* set horizontal positions */
+ if (left >= 0)
+ headerloc.x = imageloc.x = trailerloc.x = left * 24;
+ else {
+ headerloc.x = (page.width - headerlimit * CHARWIDTH) / 2;
+ imageloc.x = (page.width - image.width) / 2;
+ trailerloc.x = (page.width - trailerlimit * CHARWIDTH) / 2;
+ }
+ }
+}
+
+
+int scale_raster (density, orient, print_area)
+int density;
+enum orientation orient;
+Area print_area;
+{
+ Area image;
+ int h_scale, v_scale;
+
+ /* Set the image dimensions to the number of centipoints that would be
+ * required for printing at the selected density.
+ */
+ if (orient == PORTRAIT) {
+ image.width = xwd_header.pixmap_width * 7200 / density;
+ image.height = xwd_header.pixmap_height * 7200 / density;
+ } else {
+ image.height = xwd_header.pixmap_width * 7200 / density;
+ image.width = xwd_header.pixmap_height * 7200 / density;
+ }
+
+ /* Calculate the maximum image multiplier along
+ * the horizontal and vertical dimensions.
+ */
+ h_scale = print_area.width / image.width;
+ v_scale = print_area.height / image.height;
+
+ /* If the image can be expanded, return the lesser of the horizontal and
+ * vertical multipliers. Otherwise, the image will not completely fit
+ * the available print area, so just return 1 as the expansion factor.
+ */
+ return (((h_scale > 0) && (v_scale > 0))
+ ? ((h_scale<v_scale) ? h_scale : v_scale)
+ : 1);
+}
+
+
+scale_and_orient_image (scale, density, width, height, left, top,
+ header, trailer,
+ orient, position_on_page, device)
+int *scale, *density;
+int width, height, left, top; /* in 300ths of an inch */
+char *header, *trailer;
+enum orientation *orient;
+int position_on_page;
+enum device device;
+{
+ Area usable;
+
+ /* Determine printable area expressed in centipoints. There are 7200
+ * centipoints to the inch. The width and height parameters passed in
+ * are expressed in 300ths of an inch, therefore a 24x conversion factor
+ * is used on the parameter values. The default page dimensions STDWIDTH
+ * and STDHEIGHT are expressed in inches so must be multiplied by 7200
+ * to convert to centipoints.
+ */
+ page.width = (width >= 0) ? width * 24 : STDWIDTH * 7200;
+ page.height = (height >= 0) ? height * 24 : STDHEIGHT * 7200;
+
+ /* Paintjet Xl has a mechanical form feed, not a strip feed. It has
+ * a slop of about 1/4 to 1/2 of an inch at the top and bottom.
+ * deduct it from the page height.
+ */
+ if (device == PJETXL)
+ page.height = page.height - 7200;
+
+ /* Determine the area usable for the image. This area will be smaller
+ * than the total printable area if margins or header/trailer strings
+ * have been specified. Margins, like width and height discussed above,
+ * are expressed in 300ths of an inch and must be converted to centipoints.
+ * Header and trailer strings each reduce the available image height
+ * by 1/6 inch, or 1200 centipoints (aka CHARHEIGHT).
+ */
+ usable.width = page.width - ((left > 0) ? (left * 24) : 0);
+ usable.height = page.height - ((top > 0) ? (top * 24) : 0)
+ - ((header) ? CHARHEIGHT : 0)
+ - ((trailer) ? CHARHEIGHT : 0);
+
+ /* Quit here if there is no usable image space. */
+ if ((usable.width <= 0) || (usable.height <= 0)) {
+ fatal_err((catgets(nlmsg_fd,NL_SETN,4,
+ "No space available on page for image.")));
+ }
+
+ /* Determine image orientation. The orientation will only be changed if
+ * it was not specified by a command line option. Portrait mode will be
+ * used if either the usable printing area or the image area are square.
+ * Portrait mode will also be used if the long dimensions of the usable
+ * printing area and the image area match, otherwise landscape mode is
+ * used. Portrait mode really means "don't rotate" and landscape mode
+ * means "rotate".
+ */
+ if (*orient == UNSPECIFIED) {
+ if ((usable.width == usable.height)
+ || (xwd_header.pixmap_width == xwd_header.pixmap_height))
+ *orient = PORTRAIT;
+ else
+ *orient = ((usable.width < usable.height)
+ == (xwd_header.pixmap_width < xwd_header.pixmap_height))
+ ? PORTRAIT : LANDSCAPE;
+ }
+
+ /* Set the dots-per-inch print density if it was not specified */
+ if (*density <= 0) {
+ switch(device) {
+ case LJET: *density = 300;
+ break;
+ case PJET: *density = 90;
+ break;
+ case PJETXL: *density = 180;
+ break;
+ }
+ }
+
+ /* Fit image to available area if scale was not specified */
+ if (*scale <= 0)
+ *scale = scale_raster(*density, *orient, usable);
+
+ /* Determine image clipping limits */
+ set_image_limits(*scale, *density, *orient, usable);
+
+ /* Determine header/trailer string length clipping */
+ set_header_trailer_limits(header, trailer, usable.width);
+
+ /* Calculate locations for page layout */
+ set_print_locations(*scale, *density, top, left,
+ header, trailer, *orient, position_on_page);
+
+}
+
+
+unsigned short fullintensity;
+
+#define BLACK 1
+#define WHITE 0
+#define EMPTY -1
+#define MAX_PJ_COLOR 16
+
+#define RGBmatch(r,g,b,i) (r == i) && (g == i) && (b == i)
+
+
+/* Colormap array is used to map from the Xcolor array (xwd_colors) index
+ * numbers into a pjcolor index number. This style of mapping is done when
+ * interpreting non-Direct/TrueColor visual types.
+ */
+long *colormap;
+
+
+/* Pjcolor array is used to hold the scaled RGB triple values
+ * programmed into the printer.
+ */
+long pjcolor[MAX_PJ_COLOR];
+
+
+static int color_warning_given = FALSE;
+
+
+/* Global visual type indicator, used to select color interpretation method. */
+char Direct_or_TrueColor;
+
+
+typedef struct {
+ unsigned long Rmask, Gmask, Bmask;
+ int Rshift, Gshift, Bshift;
+} RGBshiftmask;
+
+
+/* Color index element definition, these are linked into a circular list
+ * for interpretation of DirectColor or TrueColor visual types.
+ */
+typedef struct colorindex {
+ long index;
+ long pjcolor_index;
+ struct colorindex *next;
+} COLORINDEX;
+
+
+/* Global data for color interpretation. This structure serves as a home
+ * for the color index lists (only used when processing DirectColor or
+ * TrueColor visual types). It also holds color processing switches and a
+ * pointer to the output file to reduce parameter passing overhead.
+ */
+struct {
+ int PaintJet;
+ int Invert;
+ unsigned int CutOff;
+ FILE *OutFile;
+ COLORINDEX *indexchain, *freechain;
+ RGBshiftmask sm;
+} color;
+
+
+void setup_RGBshiftmask (sm, rmask, gmask, bmask)
+RGBshiftmask *sm;
+unsigned long rmask, gmask, bmask;
+{
+ sm->Rmask = rmask; sm->Gmask = gmask; sm->Bmask = bmask;
+ sm->Rshift = 0; sm->Gshift = 0; sm->Bshift = 0;
+
+ if (!rmask)
+ fatal_err((catgets(nlmsg_fd,NL_SETN,5, "red mask for visual is zero.")));
+ if (!gmask)
+ fatal_err((catgets(nlmsg_fd,NL_SETN,6, "green mask for visual is zero.")));
+ if (!bmask)
+ fatal_err((catgets(nlmsg_fd,NL_SETN,7, "blue mask for visual is zero.")));
+
+ for (; !(rmask & 1); sm->Rshift++)
+ rmask >>= 1;
+ for (; !(gmask & 1); sm->Gshift++)
+ gmask >>= 1;
+ for (; !(bmask & 1); sm->Bshift++)
+ bmask >>= 1;
+}
+
+
+
+void swap_black_and_white ()
+{
+ /* Reverse black and white in the Xcolor structure array. */
+
+ XColor *color;
+ int n;
+
+ for (n=xwd_header.ncolors, color=xwd_colors; n>0; n--, color++)
+ if (RGBmatch((color->red & fullintensity), (color->green & fullintensity),
+ (color->blue & fullintensity), fullintensity))
+ color->red = color->green = color->blue = 0;
+ else if (RGBmatch(color->red, color->green, color->blue, 0))
+ color->red = color->green = color->blue = fullintensity;
+}
+
+
+void reset_color_mapping ()
+{
+ int n;
+ long *cmap;
+ COLORINDEX *splice;
+
+ for (n=0; n<MAX_PJ_COLOR; n++)
+ pjcolor[n] = EMPTY;
+
+ if (!color.PaintJet) {
+ /* preload for monochrome output */
+ pjcolor[0] = WHITE;
+ pjcolor[1] = BLACK;
+ }
+
+ if (Direct_or_TrueColor) {
+ /* move color index chain cells onto the free list */
+ if (color.indexchain != NULL) {
+ splice = color.indexchain->next;
+ color.indexchain->next = color.freechain;
+ color.freechain = splice;
+ color.indexchain = NULL;
+ }
+ } else if (color.PaintJet)
+ for (n=xwd_header.ncolors, cmap=colormap; n>0; n--, cmap++)
+ *cmap = EMPTY;
+}
+
+
+#define Intensity(r,g,b) ((r) * 0.30 + (g) * 0.59 + (b) * 0.11)
+
+
+void prepare_color_mapping (invert, paintjet, cutoff, out)
+int invert, paintjet;
+unsigned int cutoff;
+FILE *out;
+{
+ int n;
+ long *cmap;
+ XColor *xcolor;
+
+ for (n = xwd_header.bits_per_rgb, fullintensity = 0; n > 0; n--)
+ fullintensity = (fullintensity << 1) | 1;
+ for (n = sizeof(short) * 8 - xwd_header.bits_per_rgb; n > 0; n--)
+ fullintensity = (fullintensity << 1);
+
+ Direct_or_TrueColor = (xwd_header.visual_class == DirectColor
+ || xwd_header.visual_class == TrueColor);
+ color.PaintJet = paintjet;
+ color.Invert = invert;
+ color.CutOff = cutoff;
+ color.OutFile = out;
+ color.indexchain = NULL;
+ color.freechain = NULL;
+
+ if (Direct_or_TrueColor)
+ setup_RGBshiftmask(&color.sm, xwd_header.red_mask,
+ xwd_header.green_mask, xwd_header.blue_mask);
+ else {
+ if (!(colormap = (long *) malloc(xwd_header.ncolors * sizeof(long))))
+ fatal_err((catgets(nlmsg_fd,NL_SETN,24,
+ "Could not allocate memory for X-to-printer colormap.")));
+
+ /* For PaintJet, color map assignment will be done one line at a time.
+ * So for now just interchange the Xcolor structure's black and white
+ * if the -rv command line option was specified.
+ */
+ if (paintjet && invert)
+ swap_black_and_white();
+
+ /* For LaserJet, map each color to black or white based upon the
+ * combined intensity of the RGB components. Note that the normal
+ * non-reversed (-rv) LaserJet mapping will represent light areas
+ * of the screen as black on the paper.
+ */
+ if (!paintjet)
+ for (n=xwd_header.ncolors, xcolor=xwd_colors, cmap=colormap; n>0;
+ n--, xcolor++, cmap++)
+ *cmap = (Intensity(xcolor->red, xcolor->green, xcolor->blue) < cutoff)
+ ? (invert ? BLACK : WHITE)
+ : (invert ? WHITE : BLACK);
+ }
+ reset_color_mapping();
+}
+
+
+/* On a PaintJet printer, the programmable color intensity ranges are:
+ *
+ * red: 4..90 green: 4..88 blue: 6..85
+ *
+ * The following macros map the 0..65535 intensity ranges of X colors
+ * into the PaintJet's ranges.
+ */
+
+#define fixred(x) (x / 762 + 4)
+#define fixgreen(x) (x / 780 + 4)
+#define fixblue(x) (x / 829 + 6)
+
+#define is_grey(r,g,b) ((r == g) && (r == b))
+
+
+
+void select_grey (level, r, g, b)
+int level, *r, *g, *b;
+{
+ /* Forced selection of a grey. This is done since the PaintJet does
+ * not do very well when picking greys, they tend to become pink!
+ */
+ if (level > 66) { /* white */
+ *r = 90; *g = 88; *b = 85;
+ } else if (level > 35) {
+ *r = 43; *g = 43; *b = 45;
+ } else if (level > 21) {
+ *r = 25; *g = 25; *b = 33;
+ } else if (level > 15) {
+ *r = 15; *g = 16; *b = 18;
+ } else if (level > 11) {
+ *r = 14; *g = 14; *b = 18;
+ } else if (level > 6) {
+ *r = 6; *g = 7; *b = 8;
+ } else { /* black */
+ *r = 4; *g = 4; *b = 6;
+ }
+}
+
+
+long find_nearest_programmed_color ();
+
+int load_printer_color (index, nearmatch, device) /* for non Direct/TrueColor */
+long index;
+int nearmatch;
+enum device device;
+{
+ int n, red, blue, green, xred, xgreen, xblue;
+ long compositeRGB;
+
+ if (colormap[index] != EMPTY)
+ /* printer has already been programmed for this color index */
+ return(1); /* "success" */
+ else {
+ xred = xwd_colors[index].red;
+ xgreen = xwd_colors[index].green;
+ xblue = xwd_colors[index].blue;
+ /* determine the scaled RGB PaintJet color values */
+ if (device == PJET) {
+ red = fixred(xred);
+ green = fixgreen(xgreen);
+ blue = fixblue(xblue);
+ if (is_grey(xred, xgreen, xblue)) /* assist grey selection */
+ select_grey(red, &red, &green, &blue);
+ }
+ compositeRGB = (red << 16) | (green << 8) | blue;
+ /* search for a matching or unused PaintJet mapping entry */
+ for (n=0; n<MAX_PJ_COLOR; n++) {
+ if (pjcolor[n] == compositeRGB) {
+ /* record mapping for this index */
+ colormap[index] = n;
+ /* return "success" */
+ return(1);
+ } else if (pjcolor[n] == EMPTY) {
+ /* download color to printer */
+ fprintf(color.OutFile,"\033*v%dA", red);
+ fprintf(color.OutFile,"\033*v%dB", green);
+ fprintf(color.OutFile,"\033*v%dC", blue);
+ fprintf(color.OutFile,"\033*v%dI", n);
+ /* record that this is now programmed */
+ pjcolor[n] = compositeRGB;
+ colormap[index] = n;
+ /* return "success" */
+ return(1);
+ }
+ }
+ /* unable to find or program this color */
+ if (nearmatch)
+ colormap[index] = find_nearest_programmed_color(compositeRGB);
+ }
+ return(0); /* "failure" */
+}
+
+
+/* Lookup the image color index on the color.indexchain list. If found
+ * return the corresponding printer color index, otherwise -1. The index
+ * chain is a singly linked circular list. Its head pointer is left at
+ * the last cell matched on the theory that this will allow faster lookup
+ * for runs of color.
+ */
+int lookup_color_index (i)
+long i;
+{
+ COLORINDEX *start, *current;
+
+ start = current = color.indexchain;
+
+ if (current == NULL)
+ return(-1); /* not found */
+
+ do {
+ if (current->index == i) {
+ color.indexchain = current;
+ return(current->pjcolor_index); /* found */
+ }
+ current = current->next;
+ } while (current != start);
+
+ return(-1); /* not found */
+}
+
+
+/* Calculate the individual and composite printer RGB values. (Only the
+ * composite value is set for monochrome output.)
+ */
+void select_printer_color (index, red, green, blue, compositeRGB, device)
+long index;
+int *red, *green, *blue;
+long *compositeRGB;
+enum device device;
+{
+ int xred, xgreen, xblue;
+
+ xred = xwd_colors[((index & color.sm.Rmask) >> color.sm.Rshift)].red;
+ xgreen = xwd_colors[((index & color.sm.Gmask) >> color.sm.Gshift)].green;
+ xblue = xwd_colors[((index & color.sm.Bmask) >> color.sm.Bshift)].blue;
+
+ if (color.PaintJet) {
+ if (color.Invert) {
+ if (RGBmatch((xred & fullintensity), (xgreen & fullintensity),
+ (xblue & fullintensity), fullintensity))
+ xred = xgreen = xblue = 0;
+ else if (RGBmatch(xred, xgreen, xblue, 0))
+ xred = xgreen = xblue = fullintensity;
+ }
+ /* determine the scaled RGB PaintJet color values */
+ if (device == PJET) {
+ *red = fixred(xred);
+ *green = fixgreen(xgreen);
+ *blue = fixblue(xblue);
+ if (is_grey(xred, xgreen, xblue)) /* assist grey selection */
+ select_grey(*red, red, green, blue);
+ }
+ if (device == PJETXL) {
+ *red = xred >> 8;
+ *green = xgreen >> 8;
+ *blue = xblue >> 8;
+ }
+ *compositeRGB = (*red << 16) | (*green << 8) | *blue;
+ } else /* monochrome */
+ *compositeRGB = (Intensity(xred, xgreen, xblue) < color.CutOff)
+ ? (color.Invert ? BLACK : WHITE)
+ : (color.Invert ? WHITE : BLACK);
+}
+
+
+
+/* Search for a color matching the compositeRGB value in the array of
+ * colors already programmed into the printer. Returns 1 if found,
+ * 0 otherwise. The matching array index is returned in pindex.
+ */
+int color_already_in_printer (compositeRGB, pindex)
+long compositeRGB, *pindex;
+{
+ int n;
+
+ for (n=0; n<MAX_PJ_COLOR; n++)
+ if (pjcolor[n] == EMPTY)
+ return(0); /* not found */
+ else if (pjcolor[n] == compositeRGB) {
+ *pindex = n;
+ return(1); /* found */
+ }
+ return(0); /* not found */
+}
+
+
+int program_new_printer_color (red, green, blue, compositeRGB, pindex)
+int red, green, blue;
+long compositeRGB;
+long *pindex;
+{
+ int n;
+
+ for (n=0; n<MAX_PJ_COLOR; n++)
+ if (pjcolor[n] == EMPTY) {
+ /* download color to printer */
+ fprintf(color.OutFile,"\033*v%dA", red);
+ fprintf(color.OutFile,"\033*v%dB", green);
+ fprintf(color.OutFile,"\033*v%dC", blue);
+ fprintf(color.OutFile,"\033*v%dI", n);
+ /* record that this is now programmed */
+ pjcolor[n] = compositeRGB;
+ *pindex = n;
+ /* return "success" */
+ return(1);
+ }
+ /* unable to program this color, return "failure" */
+ return(0);
+}
+
+
+
+long composite_diff (x, y)
+long x, y;
+{
+ long r = (x >> 16 & 0xFF) - (y >> 16 & 0xFF);
+ long g = (x >> 8 & 0xFF) - (y >> 8 & 0xFF);
+ long b = (x & 0xFF) - (y & 0xFF);
+
+ return(r*r + g*g + b*b);
+}
+
+
+
+long find_nearest_programmed_color (compositeRGB)
+long compositeRGB;
+{
+ int n, nearest = 0;
+ long neardiff = composite_diff(pjcolor[0], compositeRGB);
+ long diff;
+
+ for (n=1; n<MAX_PJ_COLOR; n++) {
+ diff = composite_diff(pjcolor[n], compositeRGB);
+ if (diff < neardiff) {
+ neardiff = diff;
+ nearest = n;
+ }
+ }
+ return(nearest);
+}
+
+
+void add_index_to_chain (cindex, pindex)
+long cindex;
+long pindex;
+{
+ COLORINDEX *new;
+
+ /* Get a new cell for the color index chain. Take it from the free list
+ * if possible, otherwise malloc space.
+ */
+ if (color.freechain == NULL) {
+ if (!(new = (COLORINDEX *) malloc(sizeof(COLORINDEX))))
+ fatal_err((catgets(nlmsg_fd,NL_SETN,8,
+ "Could not allocate memory for color translation.")));
+ } else {
+ new = color.freechain;
+ color.freechain = color.freechain->next;
+ }
+
+ /* put index values in the new cell */
+ new->index = cindex;
+ new->pjcolor_index = pindex;
+
+ /* link the new cell into the chain */
+ if (color.indexchain == NULL)
+ new->next = new;
+ else {
+ new->next = color.indexchain->next;
+ color.indexchain->next = new;
+ }
+ /* leave head pointer at the new cell */
+ color.indexchain = new;
+}
+
+
+
+int load_printer_color_DT (index, nearmatch, device) /* for Direct/TrueColor */
+long index;
+int nearmatch;
+enum device device;
+{
+ int pjred, pjgreen, pjblue;
+ long compositeRGB;
+ long pindex;
+
+ if (lookup_color_index(index) >= 0)
+ return(1); /* "success" */
+ else {
+ select_printer_color(index, &pjred, &pjgreen, &pjblue, &compositeRGB,
+ device);
+ if (color_already_in_printer(compositeRGB, &pindex)) {
+ add_index_to_chain(index, pindex);
+ return(1); /* success */
+ } else if (program_new_printer_color(pjred, pjgreen, pjblue,
+ compositeRGB, &pindex)) {
+ add_index_to_chain(index, pindex);
+ return(1); /* success */
+ } else if (nearmatch) {
+ add_index_to_chain(index, find_nearest_programmed_color(compositeRGB));
+ return(0); /* failure, sorta... */
+ }
+ }
+ return(0); /* failure */
+}
+
+
+int load_line_colors (line, length, nearmatch, device)
+long *line;
+int length, nearmatch;
+enum device device;
+{
+ int result = 1; /* initialized to "success" */
+
+ for (; length>0; length--, line++) {
+ result &= Direct_or_TrueColor
+ ? load_printer_color_DT(*line, nearmatch, device)
+ : load_printer_color(*line, nearmatch, device);
+ if (!(nearmatch || result))
+ break;
+ }
+ return(result);
+}
+
+
+
+void download_colors (line, length, device)
+long *line;
+int length;
+enum device device;
+{
+ /* For the first attempt at loading the colors for a line only exact
+ * color matches are accepted. If this fails, the closest colors are
+ * accepted on the second attempt.
+ *
+ * Note: The first "if" test below bypasses the initial color loading
+ * attempt for monochrome output (which will only come here for Direct
+ * or TrueColor mono). This forces reset_color_mapping which is
+ * necessary to keep the color index chain down to a tolerable length.
+ */
+ if (!color.PaintJet || !load_line_colors(line, length, FALSE, device)) {
+ reset_color_mapping();
+ if (!load_line_colors(line, length, TRUE, device) &&
+ !color_warning_given) {
+ fprintf(stderr,(catgets(nlmsg_fd,NL_SETN,9,
+ "%s: Warning: Cannot print all image colors.\n")),
+ progname);
+ color_warning_given = TRUE;
+ }
+ }
+}
+
+
+void validate_visual()
+{
+ int depth = xwd_header.pixmap_depth;
+ char *errmsg = catgets(nlmsg_fd,NL_SETN,25,
+ "%d bit deep %s bitmap not supported.\n");
+
+ switch (xwd_header.visual_class) {
+ case GrayScale:
+ if (depth > 8) fatal_err2(errmsg, depth, "GrayScale"); break;
+ case StaticGray:
+ if (depth > 8) fatal_err2(errmsg, depth, "StaticGray"); break;
+ case PseudoColor:
+ if (depth > 8) fatal_err2(errmsg, depth, "PseudoColor"); break;
+ case StaticColor:
+ if (depth > 8) fatal_err2(errmsg, depth, "StaticColor"); break;
+ case DirectColor:
+ case TrueColor:
+ if (depth != 12 && depth != 24)
+ fatal_err2(errmsg, depth, (xwd_header.visual_class == DirectColor)
+ ? "DirectColor" : "TrueColor");
+ break;
+ default:
+ fatal_err2((catgets(nlmsg_fd,NL_SETN,26,
+ "visual class #%d not supported.\n")), xwd_header.visual_class);
+ }
+}
+
+void read_xwd_data (in)
+FILE *in;
+{
+# define WINDOW_NAME_ALLOC 32
+ unsigned long swaptest = 1;
+ int window_name_size;
+ int image_size;
+ int n;
+ char window_name [WINDOW_NAME_ALLOC];
+
+ /* Read in XWDFileHeader structure */
+ if (fread((char*) &xwd_header, 1, XWDHEADERSIZE, in) != XWDHEADERSIZE)
+ fatal_err((catgets(nlmsg_fd,NL_SETN,10,
+ "Could not read xwd file's header.")));
+
+ if (*(char *) &swaptest)
+ _swaplong((char *) &xwd_header, XWDHEADERSIZE);
+
+ validate_visual();
+
+ /* Skip over window name */
+ window_name_size = xwd_header.header_size - XWDHEADERSIZE;
+ while (window_name_size > 0) {
+ n = window_name_size > WINDOW_NAME_ALLOC
+ ? WINDOW_NAME_ALLOC : window_name_size;
+ if (fread(window_name, 1, n, in) != n)
+ fatal_err((catgets(nlmsg_fd,NL_SETN,11,
+ "Could not read xwd file's window name.")));
+ window_name_size -= n;
+ }
+
+ /* Allocate space for xwd color structures */
+ if (!(xwd_colors = (XColor*) malloc(sizeof(XColor) * xwd_header.ncolors)))
+ fatal_err((catgets(nlmsg_fd,NL_SETN,12,
+ "Could not allocate memory for xwdfile color table.")));
+
+ /* Read in xwd color structures */
+ for (n = 0; n < xwd_header.ncolors; n++)
+ if (fread(&xwd_colors[n], 1, XCOLORSIZE, in) != XCOLORSIZE)
+ fatal_err((catgets(nlmsg_fd,NL_SETN,13,
+ "Could not read xwd file's color table.")));
+
+ if (*(char *) &swaptest) {
+ for (n = 0; n < xwd_header.ncolors; n++) {
+ _swaplong((char *) &xwd_colors[n].pixel, sizeof(long));
+ _swapshort((char *) &xwd_colors[n].red, 3 * sizeof(short));
+ }
+ }
+
+ /* Allocate space for xwd image */
+ if (xwd_header.pixmap_format == ZPixmap)
+ image_size = 1;
+ else if (xwd_header.pixmap_format == XYPixmap)
+ image_size = xwd_header.pixmap_depth;
+ else
+ fatal_err((catgets(nlmsg_fd,NL_SETN,14,
+ "Image in xwd file is not in Z or XY pixmap format.")));
+ image_size *= xwd_header.bytes_per_line * xwd_header.pixmap_height;
+ if (!(xwd_image = malloc(image_size)))
+ fatal_err((catgets(nlmsg_fd,NL_SETN,15,
+ "Could not allocate memory for xwd file's image.")));
+
+ /* Read in xwd image */
+ if (fread(xwd_image, 1, image_size, in) != image_size)
+ fatal_err((catgets(nlmsg_fd,NL_SETN,16,
+ "Could not read xwd file's image.")));
+
+}
+
+
+write_image_prefix (out, scale, density, header, device, position_on_page,
+ initial_formfeed, orient, gamma, render, slide)
+FILE *out;
+int scale, density;
+char *header;
+enum device device;
+int position_on_page, initial_formfeed;
+enum orientation orient;
+float gamma;
+int render;
+int slide;
+{
+ if (initial_formfeed)
+ fprintf(out,"\014");
+
+ /* Write out header & positioning commands */
+ if (header) {
+ if (position_on_page)
+ fprintf(out,"\033&a%dH\033&a%dV",
+ /* headerloc x & y are written in decipoints */
+ (int) headerloc.x / 10, (int) headerloc.y / 10);
+ fprintf(out,"%s\n", header);
+ }
+
+ /* Prepare printer for raster graphics: */
+
+ /* Write image positioning commands */
+ if (position_on_page)
+ fprintf(out,"\033&a%dH\033&a%dV",
+ /* imageloc x & y are written in decipoints */
+ (int) imageloc.x / 10, (int) imageloc.y / 10);
+
+ /* If doing transparencies, tell the printer before raster graphics */
+ if (slide && device != LJET)
+ fprintf(out, "\033&k3W");
+
+ /* Set printer resolution */
+ fprintf(out,"\033*t%dR", density);
+
+ /*
+ * do device dependent escape sequences
+ */
+ if (device == PJET) {
+ /* Enable all four "planes" for PaintJet */
+ fprintf(out,"\033*r4U");
+
+ /* Set picture width for PaintJet */
+ fprintf(out,"\033*r%dS",
+ ((int) (orient == PORTRAIT) ? limit.width : limit.height)
+ * scale);
+ }
+
+ /* Enable various options for PaintJet XL */
+ if (device == PJETXL) {
+ double dotsize;
+ int n;
+
+ /* Speed up printing by telling that there
+ * will be no negative positioning
+ */
+ fprintf(out, "\033&a1N");
+
+ if (gamma > 0.009)
+ fprintf(out, "\033*t%.2fI", gamma);
+
+ if (render > 0)
+ fprintf(out, "\033*t%dJ", render);
+
+ if (Direct_or_TrueColor)
+ /* Enable direct by pixel for PaintJet XL */
+ fwrite("\033*v6W\000\003\010\010\010\010", 1, 11, out);
+ else {
+ /* Enable index by pixel for PaintJet XL */
+ fwrite("\033*v6W\000\001\010\010\010\010", 1, 11, out);
+
+ /* Program the palette */
+ for (n = 0; n < xwd_header.ncolors; n++) {
+ fprintf(out,"\033*v%dA", (xwd_colors[n].red >> 8));
+ fprintf(out,"\033*v%dB", (xwd_colors[n].green >> 8));
+ fprintf(out,"\033*v%dC", (xwd_colors[n].blue >> 8));
+ fprintf(out,"\033*v%dI", n);
+ }
+ }
+
+ /****************************************
+ * *
+ * PaintJet XL will do its own scaling *
+ * *
+ * Set picture width for PaintJet XL *
+ ****************************************/
+ fprintf(out,"\033*r%dS",
+ ((int) (orient == PORTRAIT) ? xwd_header.pixmap_width
+ : xwd_header.pixmap_height));
+ fprintf(out,"\033*r%dT",
+ ((int) (orient == PORTRAIT) ? xwd_header.pixmap_height
+ : xwd_header.pixmap_width));
+
+ dotsize = dot_centipoints(scale, density);
+
+ fprintf(out,"\033*t%dH",
+ (int)(((orient == PORTRAIT) ? xwd_header.pixmap_width
+ : xwd_header.pixmap_height)
+ * dotsize / 10));
+
+ fprintf(out,"\033*t%dV",
+ (int)(((orient == PORTRAIT) ? xwd_header.pixmap_height
+ : xwd_header.pixmap_width)
+ * dotsize / 10));
+ }
+
+ /* Switch to raster graphics mode */
+ if (device != PJETXL)
+ fprintf(out,"\033*r1A");
+ else
+ fprintf(out,"\033*r3A");
+
+}
+
+
+write_image_suffix (out, trailer, position_on_page, slide, render, device)
+FILE *out;
+char *trailer;
+int position_on_page;
+int slide, render;
+enum device device;
+{
+ /* Exit raster graphics mode */
+ if (device == PJETXL)
+ fprintf(out,"\033*rC");
+ else
+ fprintf(out,"\033*rB");
+
+ /* If doing transparencies, tell it to stop */
+ if (slide && device != LJET)
+ fprintf(out, "\033&k1W");
+
+ if (device == PJETXL) {
+ /* If selected a rendering algorithm, tell it to stop */
+ if (render)
+ fprintf(out, "\033*t3J");
+ fprintf(out, "\033&a0N");
+ }
+
+ /* Write out trailer & positioning commands */
+ if (trailer) {
+ if (position_on_page)
+ fprintf(out,"\033&a%dH\033&a%dV",
+ /* trailerloc x & y are written in decipoints */
+ (int) trailerloc.x / 10, (int) trailerloc.y / 10);
+ fprintf(out,"%s\n", trailer);
+ }
+}
+
+
+unsigned long Z_image_pixel (x, y)
+int x, y;
+{
+ int pixel_bytes, offset;
+ unsigned char *image;
+ unsigned long pixel;
+
+ pixel_bytes = xwd_header.bits_per_pixel >> 3;
+ offset = ((xwd_header.bits_per_pixel == 4) ? (x / 2)
+ : ((xwd_header.bits_per_pixel == 1) ? (x / 8)
+ : (x * pixel_bytes)))
+ + (y * xwd_header.bytes_per_line);
+
+ image = (unsigned char *) &xwd_image[offset];
+
+ switch (pixel_bytes) {
+ case 0: /* pixel per nibble or bit per pixel packing */
+ if (xwd_header.bits_per_pixel == 1) {
+ if (xwd_header.byte_order == MSBFirst)
+ pixel = *image >> (7 - (x % 8));
+ else
+ pixel = *image >> (x % 8);
+ } else { /* xwd_header.bits_per_pixel == 4 */
+ if (xwd_header.byte_order == MSBFirst)
+ pixel = (x & 1) ? *image : (*image >> 4);
+ else
+ pixel = (x & 1) ? (*image >> 4) : *image;
+ }
+ break;
+ case 1:
+ pixel = *image;
+ break;
+ case 2:
+ pixel = (xwd_header.byte_order == MSBFirst)
+ ? ((unsigned long)*image << 8 | *(image + 1))
+ : (*image | (unsigned long)*(image + 1) << 8);
+ break;
+ case 3:
+ pixel = (xwd_header.byte_order == MSBFirst)
+ ? ((unsigned long)*image << 16 |
+ (unsigned long)*(image + 1) << 8 |
+ (unsigned long)*(image + 2))
+ : (*image |
+ (unsigned long)*(image + 1) << 8 |
+ (unsigned long)*(image + 2) << 16);
+ break;
+ case 4:
+ pixel = (xwd_header.byte_order == MSBFirst)
+ ? ((unsigned long)*image << 24 |
+ (unsigned long)*(image+1) << 16 |
+ (unsigned long)*(image+2) << 8 |
+ *(image+3))
+ : (*image |
+ (unsigned long)*(image+1) << 8 |
+ (unsigned long)*(image+2) << 16 |
+ (unsigned long)*(image+3) << 24);
+ break;
+ }
+ return (pixel & Z_pixel_mask);
+}
+
+
+unsigned long XY_image_pixel (x, y)
+int x, y;
+{
+ int plane_start, line_start, bytes_per_bitmap_unit, bitmap_unit_start,
+ byte_within_bitmap_unit, offset, byte_mask;
+
+ plane_start = (xwd_header.pixmap_depth - 1) * xwd_header.pixmap_height
+ * xwd_header.bytes_per_line;
+ line_start = xwd_header.bytes_per_line * y;
+ bytes_per_bitmap_unit = xwd_header.bitmap_unit >> 3;
+ bitmap_unit_start = (x / xwd_header.bitmap_unit) * bytes_per_bitmap_unit;
+ byte_within_bitmap_unit = (xwd_header.byte_order == MSBFirst)
+ ? (x % xwd_header.bitmap_unit) >> 3
+ : bytes_per_bitmap_unit - ((x % xwd_header.bitmap_unit) >> 3) - 1;
+
+ offset = plane_start + line_start + bitmap_unit_start
+ + byte_within_bitmap_unit;
+
+ byte_mask = (xwd_header.bitmap_bit_order == MSBFirst)
+ ? 0x80 >> (x % 8) : 0x01 << (x % 8);
+
+ return(xwd_image[offset] & byte_mask ? 1 : 0);
+}
+
+
+void direct_by_pixel(out, line, length, device)
+FILE *out;
+long *line;
+int length;
+enum device device;
+{
+ int red, green, blue;
+ long compositeRGB;
+
+ fprintf(out, "\033*b%dW", length * 3);
+ for (; length>0; length--, line++) {
+ select_printer_color(*line, &red, &green, &blue, &compositeRGB, device);
+ fprintf(out, "%c%c%c", (char) red, (char) green, (char) blue);
+ }
+}
+
+
+void index_by_pixel(out, line, length)
+FILE *out;
+long *line;
+int length;
+{
+ register int n;
+ long *lp;
+ char *line_pixels;
+ register char *lc;
+
+ if (!(line_pixels = malloc(length)))
+ fatal_err((catgets(nlmsg_fd,NL_SETN,17,
+ "Could not allocate raster line memory.")));
+
+ for (n=0, lc=line_pixels, lp=line; n<length; n++)
+ *lc++ = (char) *lp++;
+
+ fprintf(out, "\033*b%dW", length);
+ fwrite(line_pixels, 1, length, out);
+
+ free(line_pixels);
+}
+
+
+void write_raster_line (out, scale, device, line, length)
+FILE *out;
+int scale;
+enum device device;
+long *line;
+int length;
+{
+ int planes = (device == PJET) ? 4 : 1;
+ int raster_bytes = (length * scale + 7) / 8;
+ register int bytebits, n, p, e, bit;
+ long *lp;
+ char *line_colors, *raster_line;
+ register char *lc, *rl, byte = 0;
+
+ if (device == PJETXL) {
+ if (Direct_or_TrueColor)
+ direct_by_pixel(out, line, length, device);
+ else
+ index_by_pixel(out, line, length);
+ return;
+ }
+
+ if (!(line_colors = malloc(length))
+ || !(raster_line = malloc(raster_bytes * planes)))
+ fatal_err((catgets(nlmsg_fd,NL_SETN,17,
+ "Could not allocate raster line memory.")));
+
+ if (device == PJET || Direct_or_TrueColor)
+ download_colors(line, length, device);
+
+ /* Map the line's colors into output color index numbers */
+ if (Direct_or_TrueColor)
+ for (n=0, lc=line_colors, lp=line; n<length; n++)
+ *lc++ = (char) lookup_color_index(*lp++);
+ else
+ for (n=0, lc=line_colors, lp=line; n<length; n++)
+ *lc++ = (char) colormap[*lp++];
+
+ for (p=0; p<planes; p++) {
+ bytebits = 0;
+ n = length;
+ lc = line_colors;
+ rl = &raster_line[raster_bytes * p];
+ while (n-- > 0) {
+ bit = (*lc++ >> p) & 0x01;
+ e = scale;
+ while (e--) {
+ byte = (byte << 1) | bit;
+ bytebits++;
+ if (bytebits == 8) {
+ *rl++ = byte;
+ bytebits = 0;
+ }
+ }
+ }
+ if (bytebits)
+ *rl = byte << (8 - bytebits);
+ }
+
+ e = scale;
+ while (e--) {
+ for (p=0; p<planes; p++) {
+ fprintf(out,"\033*b%d%c", raster_bytes, (p+1 == planes) ? 'W' : 'V');
+ fwrite(&raster_line[raster_bytes * p], 1, raster_bytes, out);
+ }
+ }
+
+ free(line_colors);
+ free(raster_line);
+}
+
+
+void write_portrait_Z_image (out, scale, device)
+FILE *out;
+int scale;
+enum device device;
+{
+ int x, y;
+ int width = limit.width;
+ int height = limit.height;
+ long *line, *lp;
+
+ if (!(line = (long *) malloc(width * sizeof(long))))
+ fatal_err((catgets(nlmsg_fd,NL_SETN,18,
+ "Could not allocate memory for image line buffer.")));
+
+ for (y=0; y<height; y++) {
+
+ for (x=0, lp=line; x<width; x++)
+ *lp++ = Z_image_pixel(x,y);
+
+ write_raster_line(out, scale, device, line, width);
+ }
+}
+
+
+
+void write_landscape_Z_image (out, scale, device)
+FILE *out;
+int scale;
+enum device device;
+{
+ int x, y;
+ int width = limit.height;
+ int height = limit.width;
+ long *line, *lp;
+
+ if (!(line = (long *) malloc(width * sizeof(long))))
+ fatal_err((catgets(nlmsg_fd,NL_SETN,19,
+ "Could not allocate memory for image line buffer.")));
+
+ for (x=0; x<height; x++) {
+
+ for (y=width-1, lp=line; y>=0; y--)
+ *lp++ = Z_image_pixel(x,y);
+
+ write_raster_line(out, scale, device, line, width);
+ }
+}
+
+
+void write_portrait_XY_image (out, scale, device)
+FILE *out;
+int scale;
+enum device device;
+{
+ int x, y;
+ int width = limit.width;
+ int height = limit.height;
+ long *line, *lp;
+
+ if (!(line = (long *) malloc(width * sizeof(long))))
+ fatal_err((catgets(nlmsg_fd,NL_SETN,20,
+ "Could not allocate memory for image line buffer.")));
+
+ for (y=0; y<height; y++) {
+
+ for (x=0, lp=line; x<width; x++)
+ *lp++ = XY_image_pixel(x,y);
+
+ write_raster_line(out, scale, device, line, width);
+ }
+}
+
+
+
+void write_landscape_XY_image (out, scale, device)
+FILE *out;
+int scale;
+enum device device;
+{
+ int x, y;
+ int width = limit.height;
+ int height = limit.width;
+ long *line, *lp;
+
+ if (!(line = (long *) malloc(width * sizeof(long))))
+ fatal_err((catgets(nlmsg_fd,NL_SETN,21,
+ "Could not allocate memory for image line buffer.")));
+
+ for (x=0; x<height; x++) {
+
+ for (y=width-1, lp=line; y>=0; y--)
+ *lp++ = XY_image_pixel(x,y);
+
+ write_raster_line(out, scale, device, line, width);
+ }
+}
+
+
+void write_Z_image (out, scale, orient, device)
+FILE *out;
+int scale;
+enum orientation orient;
+enum device device;
+{
+ if (orient == PORTRAIT) {
+ write_portrait_Z_image(out, scale, device);
+ } else
+ write_landscape_Z_image(out, scale, device);
+}
+
+
+
+void write_XY_image (out, scale, orient, device)
+FILE *out;
+int scale;
+enum orientation orient;
+enum device device;
+{
+ if (xwd_header.pixmap_depth > 1)
+ fatal_err((catgets(nlmsg_fd,NL_SETN,22,
+ "XY format image, multiplane images must be Z format.")));
+
+ if (orient == PORTRAIT) {
+ write_portrait_XY_image(out, scale, device);
+ } else
+ write_landscape_XY_image(out, scale, device);
+}
+
+
+
+void write_image (out, scale, orient, device)
+FILE *out;
+int scale;
+enum orientation orient;
+enum device device;
+{
+ switch (xwd_header.pixmap_format) {
+ case XYPixmap:
+ write_XY_image(out, scale, orient, device); break;
+ case ZPixmap:
+ write_Z_image(out, scale, orient, device); break;
+ default:
+ fatal_err((catgets(nlmsg_fd,NL_SETN,23, "image not in XY or Z format.")));
+ }
+}
+
+
+void x2jet(in, out, scale, density, width, height, left, top,
+ header, trailer, orient, invert,
+ initial_formfeed, position_on_page, slide,
+ device, cutoff, gamma, render)
+FILE *in, *out;
+int scale, density;
+int width, height, left, top; /* in 300ths of an inch */
+char *header, *trailer;
+enum orientation orient;
+int invert, initial_formfeed, position_on_page, slide;
+enum device device;
+unsigned int cutoff;
+float gamma;
+int render;
+{
+ int paintjet = FALSE;
+
+ true_scale = scale;
+
+ if (device != LJET)
+ paintjet = TRUE;
+
+ read_xwd_data(in);
+
+ Z_pixel_mask = ~(0xFFFFFFFFL << xwd_header.pixmap_depth);
+
+ prepare_color_mapping(invert, paintjet, cutoff, out);
+
+ scale_and_orient_image(&scale, &density, width, height, left, top,
+ header, trailer,
+ &orient, position_on_page, device);
+
+ write_image_prefix(out, scale, density, header, device, position_on_page,
+ initial_formfeed, orient, gamma, render, slide);
+
+ write_image(out, scale, orient, device);
+
+ write_image_suffix(out, trailer, position_on_page, slide, render, device);
+
+ fclose(out);
+}
+
+
+void fatal_err (s)
+char * s;
+{
+ fprintf(stderr, "%s: %s\n", progname, s);
+ exit(1);
+}
+
+void fatal_err2 (s, a1, a2, a3)
+char *s;
+char *a1, *a2, *a3;
+{
+ fprintf(stderr, "%s: ", progname);
+ fprintf(stderr, s, a1, a2, a3);
+ exit(1);
+}
diff --git a/x2pmp.c b/x2pmp.c
new file mode 100644
index 0000000..9ce465d
--- /dev/null
+++ b/x2pmp.c
@@ -0,0 +1,363 @@
+/*
+ * $XConsortium: x2pmp.c,v 1.13 91/07/25 17:56:32 rws Exp $
+ */
+
+/* x2pmp.c: Translate xwd window dump format into PMP format for the
+ * IBM 3812 PagePrinter.
+ */
+#include <stdio.h>
+#include <math.h>
+#include <X11/Xlib.h>
+#include <X11/XWDFile.h>
+#include <X11/Xfuncs.h>
+#include <errno.h>
+
+#include "pmp.h"
+#include "xpr.h"
+
+#define max_(a, b) (a) > (b) ? (a) : (b)
+#define min_(a, b) (a) < (b) ? (a) : (b)
+#define abs_(a) (a) < 0 ? -(a) : (a)
+
+static void leave();
+static bits_set();
+static unsigned char *magnification_table();
+
+/* global variables set by main() and used by x2pmp() */
+extern char *progname;
+extern int debug;
+
+static plane = 0;
+#define FONT_HEIGHT 40
+#define FONT_HEIGHT_PIXELS (FONT_HEIGHT*75/PPI)
+#define FONT_WIDTH 24
+
+void x2pmp(in, out, scale, p_width, p_length, x_pos, y_pos,
+ head, foot, orient, invert)
+FILE *in, *out;
+int scale;
+int p_width, p_length, x_pos, y_pos; /* in pels (units of PPI) */
+char *head, *foot;
+enum orientation orient;
+int invert;
+{
+ unsigned char *buffer, *win_name;
+ unsigned int win_name_size, width, height, ncolors;
+ unsigned int buffer_size, one_plane_size, byte_width, fixed_width;
+ int no_of_bits;
+ unsigned long swaptest = 1;
+ XWDFileHeader header;
+
+ /* Read header from file */
+ if (fread((char *)&header, sizeof(header), 1, in) != 1)
+ if (feof(in))
+ return;
+ else
+ leave("fread");
+ if (*(char *) &swaptest)
+ _swaplong((char *) &header, sizeof(header));
+
+ if (header.file_version != XWD_FILE_VERSION) {
+ fprintf(stderr,"%s: file format version %d, not %d\n", progname,
+ header.file_version, XWD_FILE_VERSION);
+ }
+
+ win_name_size = abs_(header.header_size - sizeof(header));
+ if ((win_name = (unsigned char *)
+ calloc(win_name_size, (unsigned) sizeof(char))) == NULL)
+ leave("Can't calloc window name storage.");
+
+ /* Read window name from file */
+ if (fread((char *) win_name, sizeof(char), (int) win_name_size, in) !=
+ win_name_size)
+ leave("Unable to read window name from dump file.");
+ DEBUG(>= 1)
+ fprintf(stderr,"win_name =%s\n", win_name);
+
+ width = header.pixmap_width;
+ height = header.pixmap_height;
+ fixed_width = 8 * (byte_width = header.bytes_per_line);
+ one_plane_size = byte_width * height;
+ buffer_size = one_plane_size *
+ ((header.pixmap_format == ZPixmap)? header.pixmap_depth: 1);
+
+ /* Determine orientation and scale if not specified */
+ if (orient == UNSPECIFIED)
+ orient = (fixed_width <= height)? PORTRAIT: LANDSCAPE;
+ if (scale <= 0) {
+ int real_height = height;
+ if (head) real_height += FONT_HEIGHT_PIXELS << 1;
+ if (foot) real_height += FONT_HEIGHT_PIXELS << 1;
+ switch(orient) {
+ case PORTRAIT:
+ case UPSIDE_DOWN:
+ scale = min_((p_width - 2*x_pos) / fixed_width,
+ (p_length - 2*y_pos) / real_height);
+ break;
+ case LANDSCAPE:
+ case LANDSCAPE_LEFT:
+ scale = min_((p_length - 2*y_pos) / fixed_width,
+ (p_width - 2*x_pos) / real_height);
+ break;
+ }
+ if (scale <= 0)
+ leave("PixMap doesn't fit on page.");
+ else DEBUG(>1)
+ fprintf(stderr, "scaling by %d to yield %d x %d image\n",
+ scale, fixed_width*scale, height*scale);
+ }
+
+ ncolors = header.ncolors;
+ if (ncolors) {
+ int i;
+ XColor *colors = (XColor *)malloc((unsigned) (header.ncolors * sizeof(XColor)));
+
+ if (fread((char *)colors, sizeof(XColor), ncolors, in) != ncolors)
+ leave("Unable to read colormap from dump file.");
+
+ if (*(char *) &swaptest) {
+ for (i = 0; i < ncolors; i++) {
+ _swaplong((char *) &colors[i].pixel, (long)sizeof(long));
+ _swapshort((char *) &colors[i].red, (long) (3 * sizeof(short)));
+ }
+ }
+ if (ncolors == 2 && INTENSITY(&colors[0]) > INTENSITY(&colors[1]))
+ invert = !invert;
+ free( colors );
+ }
+
+ invert = !invert; /* 3812 puts ink (i.e. black) on 1-bits */
+
+ if ((buffer = (unsigned char *) calloc(buffer_size, 1)) == NULL)
+ leave("Can't calloc data buffer.");
+ bzero((char *) buffer, (int) buffer_size);
+
+ /* Read bitmap from file */
+ if (fread((char *) buffer, sizeof(char), (int) buffer_size, in)
+ != buffer_size)
+ leave("Unable to read pixmap from dump file.");
+
+ if (header.bitmap_bit_order == LSBFirst)
+ {
+ unsigned char bitswap[256], *bp;
+ int c;
+ for(c = 256; c--;) {
+ bitswap[c] = ((c & 01) << 7) + ((c & 02) << 5) + ((c & 04) << 3) +
+ ((c & 010) << 1) + ((c & 020) >> 1) + ((c & 040) >> 3) +
+ ((c & 0100) >> 5) + ((c & 0200) >> 7);
+ if (invert)
+ bitswap[c] = ~bitswap[c];
+ }
+ /* Here's where we do the bitswapping. */
+ for(bp = buffer+buffer_size; bp-- > buffer;)
+ *bp = bitswap[*bp];
+ }
+ else if (invert) {
+ unsigned char *bp;
+ for(bp = buffer+buffer_size; bp-- > buffer;)
+ *bp = ~*bp;
+ }
+
+ /* we don't want the last bits up to the byte/word alignment set */
+ if (no_of_bits = fixed_width - width) {
+ int i, j, mask = ~bits_set(no_of_bits % 8);
+ for(i = 0; i < height; i++) {
+ unsigned char *s = buffer + (i+1) * byte_width ;
+
+ for(j = no_of_bits / 8; j--;)
+ *--s = 0;
+ *--s &= mask;
+ }
+ }
+
+ DEBUG(>= 1)
+ fprintf(stderr,"read %d bytes for a %d (%d bytes) x %d image\n",
+ buffer_size, (int) width, byte_width, (int) height);
+ /* Scale the bitmap */
+ if (scale > 1) {
+ unsigned char *tbl = magnification_table(scale);
+ unsigned char *scale_buf;
+ int i, j, k;
+
+ if ((scale_buf = (unsigned char *)
+ calloc((unsigned) (buffer_size *= scale*scale), sizeof(char)))
+ == NULL)
+ leave("Can't calloc scaled buffer.");
+ for(i = 0; i < height; i++) {
+ unsigned char *src, *ss;
+ src = buffer + i * byte_width ;
+ ss = scale_buf + i * scale * scale * byte_width;
+ for(j = 0; j < byte_width; j++) {
+ unsigned char *dst = ss+j*scale;
+ unsigned char *expansion = tbl+scale*src[j];
+ for(k = 0; k < scale; k++, dst += byte_width*scale) {
+ bcopy((char *) expansion, (char *) dst, scale);
+ }
+ }
+ }
+ free((char *) buffer);
+ free((char *) tbl);
+ buffer = scale_buf;
+ byte_width *= scale;
+ width *= scale;
+ fixed_width *= scale;
+ height *= scale;
+ one_plane_size *= scale*scale;
+ }
+ DEBUG(==3) {
+ int i, j, k;
+ unsigned char *s;
+
+ fprintf(stderr, "dumping %d x %d grid\n", fixed_width, height);
+ for(i = 0; i < height; i++) {
+ s = buffer + i * byte_width ;
+ for(j = 0; j < byte_width; j++)
+ for(k = 8; k--;)
+ (void) putc((s[j] & 1<<k)? '*': '-', stderr);
+ (void) putc('\n', stderr);
+ }
+ }
+ p_set_orientation(out, orient);
+ p_restore_cursor(out, 0);
+ p_save_cursor(out, 3);
+ if (head != NULL) {
+ p_move_abs( out, x_pos + (width - strlen(foot)*FONT_WIDTH) >> 1,
+ y_pos - FONT_HEIGHT );
+ fprintf(out, "%s\n", head);
+ }
+ if (foot != NULL) {
+ p_move_abs( out, x_pos + (width - strlen(foot)*FONT_WIDTH) >> 1,
+ y_pos + height + (FONT_HEIGHT << 1) );
+ fprintf(out, "%s\n", foot);
+ }
+ p_move_abs(out, x_pos, y_pos);
+ p_bitmap(out, height, fixed_width, (unsigned long) one_plane_size,
+ buffer + plane * one_plane_size);
+ free((char *) win_name);
+ free((char *) buffer);
+}
+
+static unsigned char *magnification_table(scale)
+int scale;
+{
+ unsigned char *tbl;
+ int c;
+
+ if ((tbl = (unsigned char *)
+ calloc((unsigned) (scale*256), sizeof(char))) == NULL)
+ leave("Can't calloc magnification table.");
+ bzero((char *) tbl, scale*256);
+ for(c = 256; c--;) {
+ int b = c, bit;
+ unsigned char *entry = tbl+c*scale;
+
+ while (b) {
+ int i, last, mask;
+ bit = 1;
+ mask = b;
+ while (! (mask & 1)) {
+ bit++;
+ mask = mask >> 1;
+ }
+ last = scale*(bit-1);
+ for(i = scale*bit; i-- > last ;)
+ entry[(scale - 1) - i / 8] |= 1 << (i % 8);
+ b &= ~(1 << bit-1);
+ }
+ }
+ return tbl;
+}
+
+/* returns 2^n-1, i.e. a number with bits n-1 through 0 set.
+ * (zero for n == 0) */
+static bits_set(n)
+int n;
+{
+ int ans = 0;
+ while(n--)
+ ans |= 1 << n;
+ return ans;
+}
+
+static void leave(s)
+char *s;
+{
+ extern int errno;
+
+ fprintf(stderr, "\n%s: ", progname);
+ if (errno != 0)
+ perror(s);
+ else
+ fprintf(stderr, "%s", s);
+ fprintf(stderr, "\n");
+ exit(1);
+}
+
+/* move to coordinates x, y (in pels) */
+p_move_abs(p, x, y)
+FILE *p;
+int x, y;
+{
+ if (x >= 0) {
+ PMP(p, 3);
+ (void) putc('\340', p);
+ p_wput(x, p);
+ }
+ if (y >= 0) {
+ PMP(p, 3);
+ (void) putc('\341', p);
+ p_wput(y, p);
+ }
+}
+
+/* save current cursor position into (printer) register reg */
+p_save_cursor(p, reg)
+FILE *p;
+int reg;
+{
+ PMP(p, 1);
+ (void) putc(reg + '\200', p);
+}
+
+/* restore current cursor position from (printer) register reg */
+p_restore_cursor(p, reg)
+FILE *p;
+int reg;
+{
+ PMP(p, 1);
+ (void) putc(reg + '\220', p);
+}
+
+/* set the page orientation to orient (see pmp.h) */
+p_set_orientation(p, orient)
+FILE *p;
+enum orientation orient;
+{
+ PMP(p, 2);
+ fprintf(p, "\322%c", (int) orient);
+}
+
+/* generate bitmap */
+p_bitmap(p, h, w, buflen, buf)
+FILE *p;
+unsigned int h, w;
+unsigned long buflen;
+unsigned char *buf;
+{
+ PMP(p, 9);
+ (void) fwrite("\365\0", 1, 2, p);
+ puthl2(h, p);
+ puthl2(w, p);
+ puthl3(buflen, p);
+
+ while(buflen) {
+ int len;
+
+ len = min(buflen, MAX_VECTOR_LEN);
+ PMP(p, len);
+ (void) fwrite((char *) buf, 1, len, p);
+ buf += len;
+ buflen -= len;
+ }
+ (void) fflush(p);
+}
diff --git a/xdpr.man b/xdpr.man
new file mode 100644
index 0000000..79a5844
--- /dev/null
+++ b/xdpr.man
@@ -0,0 +1,137 @@
+.\" $XConsortium: xdpr.man,v 1.15 94/04/17 20:44:04 gildea Exp $
+.TH XDPR 1 "Release 6" "X Version 11"
+.SH NAME
+xdpr \- dump an X window directly to a printer
+.SH SYNOPSIS
+.B xdpr
+[
+.I filename
+]
+[
+.B \-display
+.I host:display
+]
+[
+.B \-P\fIprinter\fP
+]
+[
+.B \-device
+.I devtype
+]
+[
+.I option
+\&.\|.\|.
+]
+
+.SH DESCRIPTION
+.I Xdpr
+uses the commands
+.I xwd,
+.I xpr,
+and
+.I lpr
+or
+.I lp
+to dump an X window, process it for a particular printer type, and
+print it out on the printer of your choice. This is the easiest way
+to get a printout of a window. \fIXdpr\fP by default will print the
+largest possible representation of the window on the output page.
+.PP
+The options for \fIxdpr\fP are the same as those for \fIxpr\fP,
+\fIxwd\fP, and \fIlpr\fP or \fIlp\fP.
+The most commonly-used options are described
+below; see the manual pages for these commands for
+more detailed descriptions of the many options available.
+.SH OPTIONS
+.TP
+.I filename
+Specifies a file containing a window dump (created by \fIxwd\fP) to be
+printed instead of selecting an X window.
+.TP
+.B \-P\fIprinter\fP
+Specifies a printer to send the output to. If a printer name is not
+specified here, \fIxdpr\fP (really, \fIlpr\fP or \fIlp\fP)
+will send your output to the
+printer specified by the \fIPRINTER\fP environment variable.
+Be sure that type of the printer matches the type specified
+with the \fI\-device\fP option.
+.TP
+.B \-display \fIhost:display\fP[\fI.screen\fP]
+.cm .IB host : display
+Normally,
+.I xdpr
+gets the host and display number to use from the environment
+variable ``DISPLAY.''
+One can, however, specify them explicitly; see \fIX\fP(1).
+.TP
+.B \-device \fIdevtype\fP
+Specifies the device on which the file will be printed. Currently supported:
+.RS 12
+.PD 0
+.TP
+.B la100
+Digital LA100
+.TP
+.B ljet
+\s-1HP\s+1 LaserJet series and other monochrome PCL devices
+such as ThinkJet, QuietJet, RuggedWriter, \s-1HP\s+12560 series,
+and \s-1HP\s+12930 series printers
+.TP
+.B ln03
+Digital LN03
+.TP
+.B pjet
+HP PaintJet (color mode)
+.TP
+.B pjetxl
+HP HP PaintJet XL Color Graphics Printer (color mode)
+.TP
+.B pp
+IBM PP3812
+.TP
+.B ps
+PostScript printer
+.PD
+.RE
+.IP
+The default is PostScript.
+\fB\-device lw\fP (LaserWriter) is equivalent to \fB\-device ps\fP and is
+provided only for backwards compatibility.
+.TP
+.B \-help
+This option displays the list of options known to
+.I xdpr.
+.PP
+Any other arguments
+will be passed to the
+.I xwd,
+.I xpr,
+and
+.I lpr
+or
+.I lp
+commands as appropriate for each.
+.SH SEE ALSO
+.IR xwd (1),
+.IR xpr (1),
+.IR lpr (1),
+.IR lp (1),
+.IR xwud (1),
+.IR X (1)
+.SH ENVIRONMENT
+.TP 10
+DISPLAY
+which display to use by default.
+.TP 10
+PRINTER
+which printer to use by default.
+.SH COPYRIGHT
+Copyright ([\d,\s]*) X Consortium
+.br
+See \fIX(1)\fP for a full statement of rights and permissions.
+.SH AUTHORS
+Paul Boutin, MIT Project Athena
+.br
+Michael R. Gretzinger, MIT Project Athena
+.br
+Jim Gettys, MIT Project Athena
diff --git a/xdpr.script b/xdpr.script
new file mode 100644
index 0000000..3ca4eb2
--- /dev/null
+++ b/xdpr.script
@@ -0,0 +1,166 @@
+#! /bin/sh
+# Copyright 1985,1988 Massacusetts Institute of Technology.
+# $XConsortium: xdpr.script /main/10 1995/12/08 11:10:59 swick $
+# origin: William Kucharski, Solbourne Computer, Inc. 3/24/90
+# translated from csh script xdpr.script "paul 4/12/88"
+
+# initialize variables
+
+display="$DISPLAY"
+header=
+bsdlprv=
+lprv=
+out=
+svlprv=
+trailer=
+xprv=
+xwdv=
+
+usage="Usage: xdpr [filename] [-out filename ] \
+[-display host:display] [[-Pprinter] | [-dprinter]] [-device devtype] \
+[{-root | -id <id> | -name <name>}] [-nobdrs] [-xy] \
+[-scale scale] [-height inches] [-width inches] [-left inches] \
+[-top inches] [-split n] [-header string] [-trailer string] \
+[-landscape] [-portrait] [-rv] [-compact] [-noff] [-frame] \
+[-plane number] [-gray number] [-psfig] [-density dpi] \
+[-cutoff level] [-noposition] [-gamma correction] [-render algorithm] \
+[-slide] [-add value] [-help]"
+
+# Guess if we are BSD or System V
+
+if [ -x /usr/ucb/lpr -o -x /usr/bin/lpr -o -x /bin/lpr -o -x /usr/bsd/lpr ]
+then
+ LP=lpr
+ BSD=1
+elif [ -x /usr/bin/lp -o -x /bin/lp ]
+then
+ LP=lp
+ BSD=0
+else
+ LP=lpr
+ BSD=1
+fi
+
+# parse arguments...
+
+while [ $1 ]; do
+ case "$1" in
+
+# ...arguments interpreted by xdpr itself...
+
+ -help)
+ echo $usage;
+ exit 0;;
+
+# ...arguments to xwd...
+
+ -nobdrs|-root|-xy|-frame)
+ xwdv="$xwdv $1";;
+ -display)
+ display=$2
+ xwdv="$xwdv $1 $2";
+ shift;;
+ -id|-name)
+ xwdv="$xwdv $1 $2";
+ shift;;
+ -out|-add)
+ out=true
+ xwdv="$xwdv $1 $2";
+ shift;;
+
+# ...arguments to xpr...
+
+ -scale|-height|-width|-left|-top|-split|-device)
+ xprv="$xprv $1 $2";
+ shift;;
+ -plane|-gray|-density|-cutoff|-gamma|-render)
+ xprv="$xprv $1 $2";
+ shift;;
+ -header)
+ shift;
+ header="$1";;
+ -trailer)
+ shift;
+ trailer="$1";;
+ -landscape|-portrait|-rv|-compact|-noff|-psfig|-noposition|-slide)
+ xprv="$xprv $1";;
+
+# ...arguments to lp[r]...
+
+ -P*|-#?*|-C?*|-J?*|-h|-m)
+ bsdlprv="$lprv $1";;
+
+ -d*|-H*|-q*|-n*|-o*|-w)
+ svlprv="$svlprv $1";;
+
+# ...disallow other arguments; print usage message
+
+ -*)
+ echo "xdpr: Unknown option $1";
+ echo $usage;
+ exit 1;;
+
+# ...input filename...
+
+ *)
+ if [ ! "$infile" ]; then
+ infile=true
+ xprv="$xprv $1"
+ else
+ echo "xdpr: Invalid argument "$1""
+ echo $usage
+ exit 1
+ fi
+ esac
+ shift
+done
+
+# quit if there is no DISPLAY specified
+
+if [ ! "$display" ]; then
+ echo "xdpr: DISPLAY variable must be set or a display specified."
+ exit
+fi
+
+# Command lines:
+
+# Set up lp[r] options...
+
+if [ $BSD -eq 0 ]
+then
+ lprv=$svlprv
+else
+ lprv=$bsdlprv
+fi
+
+# disallow concurrent input and -out arguments
+if [ "$out" -a "$infile" ]; then
+ echo "xdpr: -out <filename> cannot be used if an input file is also specified."
+ exit 0
+fi
+
+# dump only
+if [ "$out" ]; then
+ if [ "$xprv" -o "$lprv" ]; then
+ echo "xdpr: The following arguments will be ignored:"
+ echo $xprv $lprv
+ fi
+ xwd $xwdv
+ exit 0
+fi
+
+# print only
+if [ "$infile" ]; then
+ if [ "$xwdv" ]; then
+ echo "xdpr: The following arguments will be ignored:"
+ echo $xwdv
+ fi
+ xpr -header "$header" -trailer "$trailer" $xprv | $LP $lprv
+ exit 0
+fi
+
+# dump & print (default)
+xwd $xwdv | xpr -header "$header" -trailer "$trailer" $xprv | $LP $lprv
+exit 0
+
+# EOF
diff --git a/xpr.c b/xpr.c
new file mode 100644
index 0000000..c40415d
--- /dev/null
+++ b/xpr.c
@@ -0,0 +1,1915 @@
+/* $XConsortium: xpr.c,v 1.59 94/10/14 21:22:08 kaleb Exp $ */
+/*
+
+Copyright (c) 1985 X Consortium
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice shall be included
+in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+IN NO EVENT SHALL THE X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR
+OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+OTHER DEALINGS IN THE SOFTWARE.
+
+Except as contained in this notice, the name of the X Consortium shall
+not be used in advertising or otherwise to promote the sale, use or
+other dealings in this Software without prior written authorization
+from the X Consortium.
+
+*/
+
+/*
+ * XPR - process xwd(1) files for various printers
+ *
+ * Author: Michael R. Gretzinger, MIT Project Athena
+ *
+ * Modified by Marvin Solomon, Univeristy of Wisconsin, to handle Apple
+ * Laserwriter (PostScript) devices (-device ps).
+ * Also accepts the -compact flag that produces more compact output
+ * by using run-length encoding on white (1) pixels.
+ * This version does not (yet) support the following options
+ * -append -dump -noff -nosixopt -split
+ *
+ * Changes
+ * Copyright 1986 by Marvin Solomon and the University of Wisconsin
+ *
+ * Permission to use, copy, modify, and distribute this
+ * software and its documentation for any purpose and without
+ * fee is hereby granted, provided that the above copyright
+ * notice appear in all copies and that both that copyright
+ * notice and this permission notice appear in supporting
+ * documentation, and that the names of Marvin Solomon and
+ * the University of Wisconsin not be used in
+ * advertising or publicity pertaining to distribution of the
+ * software without specific, written prior permission.
+ * Neither Marvin Solomon nor the University of Wisconsin
+ * makes any representations about the suitability of
+ * this software for any purpose. It is provided "as is"
+ * without express or implied warranty.
+ *
+ * Modified by Bob Scheifler for 2x2 grayscale, then ...
+ * Modified by Angela Bock and E. Mike Durbin, Rich Inc., to produce output
+ * using 2x2, 3x3, or 4x4 grayscales. This version modifies the grayscale
+ * conversion option of -gray to accept an input of 2, 3, or 4 to signify
+ * the gray level desired. The output is produced, using 5, 10, or 17-level
+ * gray scales, respectively.
+ *
+ * Modifications by Larry Rupp, Hewlett-Packard Company, to support HP
+ * LaserJet, PaintJet, and other PCL printers. Added "ljet" and "pjet"
+ * to devices recognized. Also added -density, -cutoff, and -noposition
+ * command line options.
+ *
+ */
+
+#include <X11/Xos.h>
+#include <X11/Xfuncs.h>
+#include <X11/Xlib.h>
+#include <X11/Xutil.h>
+#include <stdio.h>
+#ifndef WIN32
+#include <pwd.h>
+#endif
+#include "lncmd.h"
+#include "xpr.h"
+#include <X11/XWDFile.h>
+#include <X11/Xmu/SysUtil.h>
+#ifndef O_BINARY
+#define O_BINARY 0
+#endif
+
+#ifdef NLS16
+#ifndef NLS
+#define NLS
+#endif
+#endif
+
+#ifndef NLS
+#define catgets(i, sn,mn,s) (s)
+#else /* NLS */
+#define NL_SETN 1 /* set number */
+#include <nl_types.h>
+
+nl_catd nlmsg_fd;
+#endif /* NLS */
+
+int debug = 0;
+
+#define W_MAX 2400
+#define H_MAX 3150
+#define W_MARGIN 75
+#define H_MARGIN 37
+#define W_PAGE 2550
+#define H_PAGE 3225
+
+#ifdef NOINLINE
+#define min(x,y) (((x)<(y))?(x):(y))
+#endif /* NOINLINE */
+
+#define F_PORTRAIT 1
+#define F_LANDSCAPE 2
+#define F_DUMP 4
+#define F_NOSIXOPT 8
+#define F_APPEND 16
+#define F_NOFF 32
+#define F_REPORT 64
+#define F_COMPACT 128
+#define F_INVERT 256
+#define F_GRAY 512
+#define F_NPOSITION 1024
+#define F_SLIDE 2048
+
+#define DEFAULT_CUTOFF ((unsigned int) (0xFFFF * 0.50))
+
+char *infilename = NULL;
+char *progname;
+
+char *convert_data();
+
+typedef struct _grayRec {
+ int level;
+ int sizeX, sizeY; /* 2x2, 3x3, 4x4 */
+ unsigned long *grayscales; /* pointer to the encoded pixels */
+} GrayRec, *GrayPtr;
+
+unsigned long grayscale2x2[] =
+ {0, 1, 9, 11, 15};
+unsigned long grayscale3x3[] =
+ {0, 16, 68, 81, 325, 341, 349, 381, 383, 511};
+unsigned long grayscale4x4[] =
+ {0, 64, 4160, 4161, 20545, 21057, 23105,
+ 23113, 23145, 24169, 24171, 56939, 55275, 55279,
+ 57327, 65519, 65535};
+
+GrayRec gray2x2 = {sizeof(grayscale2x2)/sizeof(long), 2, 2, grayscale2x2};
+GrayRec gray3x3 = {sizeof(grayscale3x3)/sizeof(long), 3, 3, grayscale3x3};
+GrayRec gray4x4 = {sizeof(grayscale4x4)/sizeof(long), 4, 4, grayscale4x4};
+
+main(argc, argv)
+char **argv;
+{
+ unsigned long swaptest = 1;
+ XWDFileHeader win;
+ register unsigned char (*sixmap)[];
+ register int i;
+ register int iw;
+ register int ih;
+ register int sixel_count;
+ char *w_name;
+ int scale, width, height, flags, split;
+ int left, top;
+ int top_margin, left_margin;
+ int hpad;
+ char *header, *trailer;
+ int plane;
+ int density, render;
+ unsigned int cutoff;
+ float gamma;
+ GrayPtr gray;
+ char *data;
+ long size;
+ enum orientation orientation;
+ enum device device;
+ XColor *colors = (XColor *)NULL;
+
+ if (!(progname = argv[0]))
+ progname = "xpr";
+#ifdef NLS
+ nlmsg_fd = catopen("xpr", 0);
+#endif
+ parse_args (argc, argv, &scale, &width, &height, &left, &top, &device,
+ &flags, &split, &header, &trailer, &plane, &gray,
+ &density, &cutoff, &gamma, &render);
+
+ if (device == PP) {
+ x2pmp(stdin, stdout, scale,
+ width >= 0? inch2pel((float)width/300.0): X_MAX_PELS,
+ height >= 0? inch2pel((float)height/300.0): Y_MAX_PELS,
+ left >= 0? inch2pel((float)left/300.0): inch2pel(0.60),
+ top >= 0? inch2pel((float)top/300.0): inch2pel(0.70),
+ header, trailer,
+ (flags & F_PORTRAIT)? PORTRAIT:
+ ((flags & F_LANDSCAPE)? LANDSCAPE: UNSPECIFIED),
+ (flags & F_INVERT));
+ exit(0);
+ } else if ((device == LJET) || (device == PJET) || (device == PJETXL)) {
+ x2jet(stdin, stdout, scale, density, width, height, left, top,
+ header, trailer,
+ (flags & F_PORTRAIT)? PORTRAIT:
+ ((flags & F_LANDSCAPE)? LANDSCAPE: UNSPECIFIED),
+ (flags & F_INVERT),
+ ((flags & F_APPEND) && !(flags & F_NOFF)),
+ !(flags & F_NPOSITION),
+ (flags & F_SLIDE),
+ device, cutoff, gamma, render);
+ exit(0);
+ }
+
+ /* read in window header */
+ fullread(0, (char *)&win, sizeof win);
+ if (*(char *) &swaptest)
+ _swaplong((char *) &win, (long)sizeof(win));
+
+ if (win.file_version != XWD_FILE_VERSION) {
+ fprintf(stderr,"xpr: file format version missmatch.\n");
+ exit(1);
+ }
+ if (win.header_size < sizeof(win)) {
+ fprintf(stderr,"xpr: header size is too small.\n");
+ exit(1);
+ }
+
+ w_name = malloc((unsigned)(win.header_size - sizeof win));
+ fullread(0, w_name, (int) (win.header_size - sizeof win));
+
+ if(win.ncolors) {
+ XWDColor xwdcolor;
+ colors = (XColor *)malloc((unsigned) (win.ncolors * sizeof(XColor)));
+ for (i = 0; i < win.ncolors; i++) {
+ fullread(0, (char*)&xwdcolor, (int) sizeof xwdcolor);
+ colors[i].pixel = xwdcolor.pixel;
+ colors[i].red = xwdcolor.red;
+ colors[i].green = xwdcolor.green;
+ colors[i].blue = xwdcolor.blue;
+ colors[i].flags = xwdcolor.flags;
+ }
+ if (*(char *) &swaptest) {
+ for (i = 0; i < win.ncolors; i++) {
+ _swaplong((char *) &colors[i].pixel, (long)sizeof(long));
+ _swapshort((char *) &colors[i].red, (long) (3 * sizeof(short)));
+ }
+ }
+ if ((win.ncolors == 2) &&
+ (INTENSITY(&colors[0]) > INTENSITY(&colors[1])))
+ flags ^= F_INVERT;
+ }
+ if (plane >= (long)win.pixmap_depth) {
+ fprintf(stderr,"xpr: plane number exceeds image depth\n");
+ exit(1);
+ }
+ size = win.bytes_per_line * win.pixmap_height;
+ if (win.pixmap_format == XYPixmap)
+ size *= win.pixmap_depth;
+ data = malloc((unsigned)size);
+ fullread(0, data, (int)size);
+ if ((win.pixmap_depth > 1) || (win.byte_order != win.bitmap_bit_order)) {
+ data = convert_data(&win, data, plane, gray, colors, flags);
+ size = win.bytes_per_line * win.pixmap_height;
+ }
+ if (win.bitmap_bit_order == MSBFirst) {
+ _swapbits((unsigned char *)data, size);
+ win.bitmap_bit_order = LSBFirst;
+ }
+ if (flags & F_INVERT)
+ _invbits((unsigned char *)data, size);
+
+ /* calculate orientation and scale */
+ setup_layout(device, (int) win.pixmap_width, (int) win.pixmap_height,
+ flags, width, height, header, trailer, &scale, &orientation);
+
+ if (device == PS) {
+ iw = win.pixmap_width;
+ ih = win.pixmap_height;
+ } else {
+ /* calculate w and h cell count */
+ iw = win.pixmap_width;
+ ih = (win.pixmap_height + 5) / 6;
+ hpad = (ih * 6) - win.pixmap_height;
+
+ /* build pixcells from input file */
+ sixel_count = iw * ih;
+ sixmap = (unsigned char (*)[])malloc((unsigned)sixel_count);
+ build_sixmap(iw, ih, sixmap, hpad, &win, data);
+ }
+
+ /* output commands and sixel graphics */
+ if (device == LN03) {
+/* ln03_grind_fonts(sixmap, iw, ih, scale, &pixmap); */
+ ln03_setup(iw, ih, orientation, scale, left, top,
+ &left_margin, &top_margin, flags, header, trailer);
+ ln03_output_sixels(sixmap, iw, ih, (flags & F_NOSIXOPT), split,
+ scale, top_margin, left_margin);
+ ln03_finish();
+ } else if (device == LA100) {
+ la100_setup(iw, ih, scale);
+ la100_output_sixels(sixmap, iw, ih, (flags & F_NOSIXOPT));
+ la100_finish();
+ } else if (device == PS) {
+ ps_setup(iw, ih, orientation, scale, left, top,
+ flags, header, trailer, w_name);
+ ps_output_bits(iw, ih, flags, orientation, &win, data);
+ ps_finish();
+ } else {
+ fprintf(stderr, "xpr: device not supported\n");
+ }
+
+ /* print some statistics */
+ if (flags & F_REPORT) {
+ fprintf(stderr, "Name: %s\n", w_name);
+ fprintf(stderr, "Width: %d, Height: %d\n", win.pixmap_width,
+ win.pixmap_height);
+ fprintf(stderr, "Orientation: %s, Scale: %d\n",
+ (orientation==PORTRAIT) ? "Portrait" : "Landscape", scale);
+ }
+ if (((device == LN03) || (device == LA100)) && (flags & F_DUMP))
+ dump_sixmap(sixmap, iw, ih);
+ exit(0);
+}
+
+usage()
+{
+ fprintf(stderr, "usage: %s [options] [file]\n", progname);
+ fprintf(stderr, " -append <file> -noff -output <file>\n");
+ fprintf(stderr, " -compact\n");
+ fprintf(stderr, " -device {ln03 | la100 | ps | lw | pp | ljet | pjet | pjetxl}\n");
+ fprintf(stderr, " -dump\n");
+ fprintf(stderr, " -gamma <correction>\n");
+ fprintf(stderr, " -gray {2 | 3 | 4}\n");
+ fprintf(stderr, " -height <inches> -width <inches>\n");
+ fprintf(stderr, " -header <string> -trailer <string>\n");
+ fprintf(stderr, " -landscape -portrait\n");
+ fprintf(stderr, " -left <inches> -top <inches>\n");
+ fprintf(stderr, " -noposition\n");
+ fprintf(stderr, " -nosixopt\n");
+ fprintf(stderr, " -plane <n>\n");
+ fprintf(stderr, " -psfig\n");
+ fprintf(stderr, " -render <type>\n");
+ fprintf(stderr, " -report\n");
+ fprintf(stderr, " -rv\n");
+ fprintf(stderr, " -scale <scale>\n");
+ fprintf(stderr, " -slide\n");
+ fprintf(stderr, " -split <n-pages>\n");
+ exit(1);
+}
+
+parse_args(argc, argv, scale, width, height, left, top, device, flags,
+ split, header, trailer, plane, gray, density, cutoff, gamma, render)
+register int argc;
+register char **argv;
+int *scale;
+int *width;
+int *height;
+int *left;
+int *top;
+enum device *device;
+int *flags;
+int *split;
+char **header;
+char **trailer;
+int *plane;
+GrayPtr *gray;
+int *density;
+unsigned int *cutoff;
+float *gamma;
+int *render;
+{
+ register char *output_filename;
+ register int f;
+ register int len;
+ register int pos;
+#ifdef X_NOT_STDC_ENV
+ double atof();
+ int atoi();
+#endif
+
+ output_filename = NULL;
+ *device = PS; /* default */
+ *flags = 0;
+ *scale = 0;
+ *split = 1;
+ *width = -1;
+ *height = -1;
+ *top = -1;
+ *left = -1;
+ *header = NULL;
+ *trailer = NULL;
+ *plane = -1;
+ *gray = (GrayPtr)NULL;
+ *density = 0;
+ *cutoff = DEFAULT_CUTOFF;
+ *gamma = -1.0;
+ *render = 0;
+
+ for (argc--, argv++; argc > 0; argc--, argv++) {
+ if (argv[0][0] != '-') {
+ infilename = *argv;
+ continue;
+ }
+ len = strlen(*argv);
+ switch (argv[0][1]) {
+ case 'a': /* -append <filename> */
+ if (!bcmp(*argv, "-append", len)) {
+ argc--; argv++;
+ if (argc == 0) usage();
+ output_filename = *argv;
+ *flags |= F_APPEND;
+ } else
+ usage();
+ break;
+
+ case 'c': /* -compact | -cutoff <intensity> */
+ if (len <= 2 )
+ usage();
+ if (!bcmp(*argv, "-compact", len)) {
+ *flags |= F_COMPACT;
+ } else if (!bcmp(*argv, "-cutoff", len)) {
+ argc--; argv++;
+ if (argc == 0) usage();
+ *cutoff = min((atof(*argv) / 100.0 * 0xFFFF), 0xFFFF);
+ } else
+ usage();
+ break;
+
+ case 'd': /* -density <num> | -device <dev> | -dump */
+ if (len <= 2)
+ usage();
+ if (!bcmp(*argv, "-dump", len)) {
+ *flags |= F_DUMP;
+ } else if (len <= 3) {
+ usage();
+ } else if (!bcmp(*argv, "-density", len)) {
+ argc--; argv++;
+ if (argc == 0) usage();
+ *density = atoi(*argv);
+ } else if (!bcmp(*argv, "-device", len)) {
+ argc--; argv++;
+ if (argc == 0) usage();
+ len = strlen(*argv);
+ if (len < 2)
+ usage();
+ if (!bcmp(*argv, "ln03", len)) {
+ *device = LN03;
+ } else if (!bcmp(*argv, "la100", len)) {
+ *device = LA100;
+ } else if (!bcmp(*argv, "ps", len)) {
+ *device = PS;
+ } else if (!bcmp(*argv, "lw", len)) {
+ *device = PS;
+ } else if (!bcmp(*argv, "pp", len)) {
+ *device = PP;
+ } else if (!bcmp(*argv, "ljet", len)) {
+ *device = LJET;
+ } else if (!bcmp(*argv, "pjet", len)) {
+ *device = PJET;
+ } else if (!bcmp(*argv, "pjetxl", len)) {
+ *device = PJETXL;
+ } else
+ usage();
+ } else
+ usage();
+ break;
+
+ case 'g': /* -gamma <float> | -gray <num> */
+ if (len <= 2)
+ usage();
+ if (!bcmp(*argv, "-gamma", len)) {
+ argc--; argv++;
+ if (argc == 0) usage();
+ *gamma = atof(*argv);
+ } else if (!bcmp(*argv, "-gray", len) ||
+ !bcmp(*argv, "-grey", len)) {
+ argc--; argv++;
+ if (argc == 0) usage();
+ switch (atoi(*argv)) {
+ case 2:
+ *gray = &gray2x2;
+ break;
+ case 3:
+ *gray = &gray3x3;
+ break;
+ case 4:
+ *gray = &gray4x4;
+ break;
+ default:
+ usage();
+ }
+ *flags |= F_GRAY;
+ } else
+ usage();
+ break;
+
+ case 'h': /* -height <inches> | -header <string> */
+ if (len <= 3)
+ usage();
+ if (!bcmp(*argv, "-height", len)) {
+ argc--; argv++;
+ if (argc == 0) usage();
+ *height = (int)(300.0 * atof(*argv));
+ } else if (!bcmp(*argv, "-header", len)) {
+ argc--; argv++;
+ if (argc == 0) usage();
+ *header = *argv;
+ } else
+ usage();
+ break;
+
+ case 'l': /* -landscape | -left <inches> */
+ if (len <= 2)
+ usage();
+ if (!bcmp(*argv, "-landscape", len)) {
+ *flags |= F_LANDSCAPE;
+ } else if (!bcmp(*argv, "-left", len)) {
+ argc--; argv++;
+ if (argc == 0) usage();
+ *left = (int)(300.0 * atof(*argv));
+ } else
+ usage();
+ break;
+
+ case 'n': /* -nosixopt | -noff | -noposition */
+ if (len <= 3)
+ usage();
+ if (!bcmp(*argv, "-nosixopt", len)) {
+ *flags |= F_NOSIXOPT;
+ } else if (!bcmp(*argv, "-noff", len)) {
+ *flags |= F_NOFF;
+ } else if (!bcmp(*argv, "-noposition", len)) {
+ *flags |= F_NPOSITION;
+ } else
+ usage();
+ break;
+
+ case 'o': /* -output <filename> */
+ if (!bcmp(*argv, "-output", len)) {
+ argc--; argv++;
+ if (argc == 0) usage();
+ output_filename = *argv;
+ } else
+ usage();
+ break;
+
+ case 'p': /* -portrait | -plane <n> */
+ if (len <= 2)
+ usage();
+ if (!bcmp(*argv, "-portrait", len)) {
+ *flags |= F_PORTRAIT;
+ } else if (!bcmp(*argv, "-plane", len)) {
+ argc--; argv++;
+ if (argc == 0) usage();
+ *plane = atoi(*argv);
+ } else if (!bcmp(*argv, "-psfig", len)) {
+ *flags |= F_NPOSITION;
+ } else
+ usage();
+ break;
+
+ case 'r': /* -render <type> | -report | -rv */
+ if (len <= 2)
+ usage();
+ if (!bcmp(*argv, "-rv", len)) {
+ *flags |= F_INVERT;
+ } else if (len <= 3) {
+ usage();
+ } else if (!bcmp(*argv, "-render", len)) {
+ argc--; argv++;
+ if (argc == 0) usage();
+ *render = atoi(*argv);
+ } else if (!bcmp(*argv, "-report", len)) {
+ *flags |= F_REPORT;
+ } else
+ usage();
+ break;
+
+ case 's': /* -scale <scale> | -slide | -split <n-pages> */
+ if (len <= 2)
+ usage();
+ if (!bcmp(*argv, "-scale", len)) {
+ argc--; argv++;
+ if (argc == 0) usage();
+ *scale = atoi(*argv);
+ } else if (!bcmp(*argv, "-slide", len)) {
+ *flags |= F_SLIDE;
+ } else if (!bcmp(*argv, "-split", len)) {
+ argc--; argv++;
+ if (argc == 0) usage();
+ *split = atoi(*argv);
+ } else
+ usage();
+ break;
+
+ case 't': /* -top <inches> | -trailer <string> */
+ if (len <= 2)
+ usage();
+ if (!bcmp(*argv, "-top", len)) {
+ argc--; argv++;
+ if (argc == 0) usage();
+ *top = (int)(300.0 * atof(*argv));
+ } else if (!bcmp(*argv, "-trailer", len)) {
+ argc--; argv++;
+ if (argc == 0) usage();
+ *trailer = *argv;
+ } else
+ usage();
+ break;
+
+ case 'w': /* -width <inches> */
+ if (!bcmp(*argv, "-width", len)) {
+ argc--; argv++;
+ if (argc == 0) usage();
+ *width = (int)(300.0 * atof(*argv));
+ } else
+ usage();
+ break;
+
+ default:
+ usage();
+ break;
+ }
+ }
+
+ if (infilename) {
+ f = open(infilename, O_RDONLY|O_BINARY, 0);
+ if (f < 0) {
+ fprintf(stderr, "xpr: error opening \"%s\" for input\n",
+ infilename);
+ perror("");
+ exit(1);
+ }
+ dup2(f, 0);
+ close(f);
+ } else
+ infilename = "stdin";
+
+ if (output_filename != NULL) {
+ if (!(*flags & F_APPEND)) {
+ f = open(output_filename, O_CREAT|O_WRONLY|O_TRUNC, 0664);
+ } else {
+ f = open(output_filename, O_WRONLY, 0);
+ }
+ if (f < 0) {
+ fprintf(stderr, "xpr: error opening \"%s\" for output\n",
+ output_filename);
+ perror("xpr");
+ exit(1);
+ }
+ if (*flags & F_APPEND) {
+ pos = lseek(f, 0, 2); /* get eof position */
+ if ((*flags & F_NOFF) &&
+ !(*device == LJET || *device == PJET || *device == PJETXL))
+ pos -= 3; /* set position before trailing */
+ /* formfeed and reset */
+ lseek(f, pos, 0); /* set pointer */
+ }
+ dup2(f, 1);
+ close(f);
+ }
+}
+
+setup_layout(device, win_width, win_height, flags, width, height,
+ header, trailer, scale, orientation)
+enum device device;
+int win_width;
+int win_height;
+int flags;
+int width;
+int height;
+char *header;
+char *trailer;
+int *scale;
+enum orientation *orientation;
+{
+ register int w_scale;
+ register int h_scale;
+ register int iscale = *scale;
+ register int w_max;
+ register int h_max;
+
+ if (header != NULL) win_height += 75;
+ if (trailer != NULL) win_height += 75;
+
+ /* check maximum width and height; set orientation and scale*/
+ if (device == LN03 || device == PS) {
+ if ((win_width < win_height || (flags & F_PORTRAIT)) &&
+ !(flags & F_LANDSCAPE)) {
+ *orientation = PORTRAIT;
+ w_max = (width > 0)? width : W_MAX;
+ h_max = (height > 0)? height : H_MAX;
+ w_scale = w_max / win_width;
+ h_scale = h_max / win_height;
+ *scale = min(w_scale, h_scale);
+ } else {
+ *orientation = LANDSCAPE;
+ w_max = (width > 0)? width : H_MAX;
+ h_max = (height > 0)? height : W_MAX;
+ w_scale = w_max / win_width;
+ h_scale = h_max / win_height;
+ *scale = min(w_scale, h_scale);
+ }
+ } else { /* device == LA100 */
+ *orientation = PORTRAIT;
+ *scale = W_MAX / win_width;
+ }
+ if (*scale == 0) *scale = 1;
+ if (*scale > 6) *scale = 6;
+ if (iscale > 0 && iscale < *scale) *scale = iscale;
+}
+
+char *
+convert_data(win, data, plane, gray, colors, flags)
+ register XWDFileHeader *win;
+ char *data;
+ int plane;
+ register GrayPtr gray;
+ XColor *colors;
+ int flags;
+{
+ XImage in_image_struct, out_image_struct;
+ register XImage *in_image, *out_image;
+ register int x, y;
+
+ if ((win->pixmap_format == XYPixmap) && (plane >= 0)) {
+ data += win->bytes_per_line * win->pixmap_height *
+ (win->pixmap_depth - (plane + 1));
+ win->pixmap_format = XYBitmap;
+ win->pixmap_depth = 1;
+ return data;
+ }
+
+ /* initialize the input image */
+
+ in_image = &in_image_struct;
+ in_image->byte_order = win->byte_order;
+ in_image->bitmap_unit = win->bitmap_unit;
+ in_image->bitmap_bit_order = win->bitmap_bit_order;
+ in_image->depth = win->pixmap_depth;
+ in_image->bits_per_pixel = win->bits_per_pixel;
+ in_image->format = win->pixmap_format,
+ in_image->xoffset = win->xoffset,
+ in_image->data = data;
+ in_image->width = win->pixmap_width;
+ in_image->height = win->pixmap_height;
+ in_image->bitmap_pad = win->bitmap_pad;
+ in_image->bytes_per_line = win->bytes_per_line;
+ in_image->red_mask = win->red_mask;
+ in_image->green_mask = win->green_mask;
+ in_image->blue_mask = win->blue_mask;
+ in_image->obdata = NULL;
+ if (!XInitImage(in_image)) {
+ fprintf(stderr,"xpr: bad input image header data.\n");
+ exit(1);
+ }
+ if ((flags & F_GRAY) && (in_image->depth > 1) && (plane < 0)) {
+ win->pixmap_width *= gray->sizeX;
+ win->pixmap_height *= gray->sizeY;
+ }
+ win->xoffset = 0;
+ win->pixmap_format = XYBitmap;
+ win->byte_order = LSBFirst;
+ win->bitmap_unit = 8;
+ win->bitmap_bit_order = LSBFirst;
+ win->bitmap_pad = 8;
+ win->pixmap_depth = 1;
+ win->bits_per_pixel = 1;
+ win->bytes_per_line = (win->pixmap_width + 7) >> 3;
+
+ out_image = &out_image_struct;
+ out_image->byte_order = win->byte_order;
+ out_image->bitmap_unit = win->bitmap_unit;
+ out_image->bitmap_bit_order = win->bitmap_bit_order;
+ out_image->depth = win->pixmap_depth;
+ out_image->bits_per_pixel = win->bits_per_pixel;
+ out_image->format = win->pixmap_format;
+ out_image->xoffset = win->xoffset,
+ out_image->width = win->pixmap_width;
+ out_image->height = win->pixmap_height;
+ out_image->bitmap_pad = win->bitmap_pad;
+ out_image->bytes_per_line = win->bytes_per_line;
+ out_image->red_mask = 0;
+ out_image->green_mask = 0;
+ out_image->blue_mask = 0;
+ out_image->obdata = NULL;
+ out_image->data = malloc((unsigned)out_image->bytes_per_line *
+ out_image->height);
+ if (!XInitImage(out_image)) {
+ fprintf(stderr,"xpr: bad output image header data.\n");
+ exit(1);
+ }
+
+ if ((in_image->depth > 1) && (plane > 0)) {
+ for (y = 0; y < in_image->height; y++)
+ for (x = 0; x < in_image->width; x++)
+ XPutPixel(out_image, x, y,
+ (XGetPixel(in_image, x, y) >> plane) & 1);
+ } else if (plane == 0) {
+ for (y = 0; y < in_image->height; y++)
+ for (x = 0; x < in_image->width; x++)
+ XPutPixel(out_image, x, y, XGetPixel(in_image, x, y));
+ } else if ((in_image->depth > 1) &&
+ ((win->visual_class == TrueColor) ||
+ (win->visual_class == DirectColor))) {
+ XColor color;
+ int direct = 0;
+ unsigned long rmask, gmask, bmask;
+ int rshift = 0, gshift = 0, bshift = 0;
+
+ rmask = win->red_mask;
+ while (!(rmask & 1)) {
+ rmask >>= 1;
+ rshift++;
+ }
+ gmask = win->green_mask;
+ while (!(gmask & 1)) {
+ gmask >>= 1;
+ gshift++;
+ }
+ bmask = win->blue_mask;
+ while (!(bmask & 1)) {
+ bmask >>= 1;
+ bshift++;
+ }
+ if ((win->ncolors == 0) || (win->visual_class == DirectColor))
+ direct = 1;
+ if (flags & F_GRAY) {
+ register int ox, oy;
+ int ix, iy;
+ unsigned long bits;
+ for (y = 0, oy = 0; y < in_image->height; y++, oy += gray->sizeY)
+ for (x = 0, ox = 0; x < in_image->width; x++, ox += gray->sizeX)
+ {
+ color.pixel = XGetPixel(in_image, x, y);
+ color.red = (color.pixel >> rshift) & rmask;
+ color.green = (color.pixel >> gshift) & gmask;
+ color.blue = (color.pixel >> bshift) & bmask;
+ if (!direct) {
+ color.red = colors[color.red].red;
+ color.green = colors[color.green].green;
+ color.blue = colors[color.blue].blue;
+ }
+ bits = gray->grayscales[(int)(gray->level *
+ INTENSITY(&color)) /
+ (INTENSITYPER(100) + 1)];
+ for (iy = 0; iy < gray->sizeY; iy++)
+ for (ix = 0; ix < gray->sizeX; ix++, bits >>= 1)
+ XPutPixel(out_image, ox + ix, oy + iy, bits);
+ }
+ } else {
+ for (y = 0; y < in_image->height; y++)
+ for (x = 0; x < in_image->width; x++) {
+ color.pixel = XGetPixel(in_image, x, y);
+ color.red = (color.pixel >> rshift) & rmask;
+ color.green = (color.pixel >> gshift) & gmask;
+ color.blue = (color.pixel >> bshift) & bmask;
+ if (!direct) {
+ color.red = colors[color.red].red;
+ color.green = colors[color.green].green;
+ color.blue = colors[color.blue].blue;
+ }
+ XPutPixel(out_image, x, y,
+ INTENSITY(&color) > HALFINTENSITY);
+ }
+ }
+ } else if (flags & F_GRAY) {
+ register int ox, oy;
+ int ix, iy;
+ unsigned long bits;
+
+ if (win->ncolors == 0) {
+ fprintf(stderr, "no colors in data, can't remap\n");
+ exit(1);
+ }
+ for (x = 0; x < win->ncolors; x++) {
+ register XColor *color = &colors[x];
+
+ color->pixel = gray->grayscales[(gray->level * INTENSITY(color)) /
+ (INTENSITYPER(100) + 1)];
+ }
+ for (y = 0, oy = 0; y < in_image->height; y++, oy += gray->sizeY)
+ for (x = 0, ox = 0; x < in_image->width; x++, ox += gray->sizeX) {
+ bits = colors[XGetPixel(in_image, x, y)].pixel;
+ for (iy = 0; iy < gray->sizeY; iy++)
+ for (ix = 0; ix < gray->sizeX; ix++, bits >>= 1)
+ XPutPixel(out_image, ox + ix, oy + iy, bits);
+ }
+ } else {
+ if (win->ncolors == 0) {
+ fprintf(stderr, "no colors in data, can't remap\n");
+ exit(1);
+ }
+ for (x = 0; x < win->ncolors; x++) {
+ register XColor *color = &colors[x];
+ color->pixel = (INTENSITY(color) > HALFINTENSITY);
+ }
+ for (y = 0; y < in_image->height; y++)
+ for (x = 0; x < in_image->width; x++)
+ XPutPixel(out_image, x, y,
+ colors[XGetPixel(in_image, x, y)].pixel);
+ }
+ free(data);
+ return (out_image->data);
+}
+
+dump_sixmap(sixmap, iw, ih)
+register unsigned char (*sixmap)[];
+int iw;
+int ih;
+{
+ register int i, j;
+ register unsigned char *c;
+
+ c = (unsigned char *)sixmap;
+ fprintf(stderr, "Sixmap:\n");
+ for (i = 0; i < ih; i++) {
+ for (j = 0; j < iw; j++) {
+ fprintf(stderr, "%02X ", *c++);
+ }
+ fprintf(stderr, "\n\n");
+ }
+}
+
+build_sixmap(iw, ih, sixmap, hpad, win, data)
+int ih;
+int iw;
+unsigned char (*sixmap)[];
+int hpad;
+XWDFileHeader *win;
+char *data;
+{
+ int iwb = win->bytes_per_line;
+ unsigned char *line[6];
+ register unsigned char *c;
+ register int i, j;
+#ifdef NOINLINE
+ register int w;
+#endif
+ register int sixel;
+ unsigned char *buffer = (unsigned char *)data;
+
+ c = (unsigned char *)sixmap;
+
+
+ while (--ih >= 0) {
+ for (i = 0; i <= 5; i++) {
+ line[i] = buffer;
+ buffer += iwb;
+ }
+ if ((ih == 0) && (hpad > 0)) {
+ unsigned char *ffbuf;
+
+ ffbuf = (unsigned char *)malloc((unsigned)iwb);
+ for (j = 0; j < iwb; j++)
+ ffbuf[j] = 0xFF;
+ for (; --hpad >= 0; i--)
+ line[i] = ffbuf;
+ }
+
+#ifndef NOINLINE
+ for (i = 0; i < iw; i++) {
+ sixel = extzv(line[0], i, 1);
+ sixel |= extzv(line[1], i, 1) << 1;
+ sixel |= extzv(line[2], i, 1) << 2;
+ sixel |= extzv(line[3], i, 1) << 3;
+ sixel |= extzv(line[4], i, 1) << 4;
+ sixel |= extzv(line[5], i, 1) << 5;
+ *c++ = sixel;
+ }
+#else
+ for (i = 0, w = iw; w > 0; i++) {
+ for (j = 0; j <= 7; j++) {
+ sixel = ((line[0][i] >> j) & 1);
+ sixel |= ((line[1][i] >> j) & 1) << 1;
+ sixel |= ((line[2][i] >> j) & 1) << 2;
+ sixel |= ((line[3][i] >> j) & 1) << 3;
+ sixel |= ((line[4][i] >> j) & 1) << 4;
+ sixel |= ((line[5][i] >> j) & 1) << 5;
+ *c++ = sixel;
+ if (--w == 0) break;
+ }
+ }
+#endif
+ }
+}
+
+build_output_filename(name, device, oname)
+register char *name, *oname;
+enum device device;
+{
+ while (*name && *name != '.') *oname++ = *name++;
+ switch (device) {
+ case LN03: bcopy(".ln03", oname, 6); break;
+ case LA100: bcopy(".la100", oname, 7); break;
+ }
+}
+
+/*
+ln03_grind_fonts(sixmap, iw, ih, scale, pixmap)
+unsigned char (*sixmap)[];
+int iw;
+int ih;
+int scale;
+struct pixmap (**pixmap)[];
+{
+}
+*/
+
+ln03_setup(iw, ih, orientation, scale, left, top, left_margin, top_margin,
+ flags, header, trailer)
+int iw;
+int ih;
+enum orientation orientation;
+int scale;
+int left;
+int top;
+int *left_margin;
+int *top_margin;
+int flags;
+char *header;
+char *trailer;
+{
+ register int i;
+ register int lm, tm, xm;
+ char buf[256];
+ register char *bp = buf;
+
+ if (!(flags & F_APPEND)) {
+ sprintf(bp, LN_STR); bp += 4;
+ sprintf(bp, LN_SSU, 7); bp += 5;
+ sprintf(bp, LN_PUM_SET); bp += sizeof LN_PUM_SET - 1;
+ }
+
+ if (orientation == PORTRAIT) {
+ lm = (left > 0)? left : (((W_MAX - scale * iw) / 2) + W_MARGIN);
+ tm = (top > 0)? top : (((H_MAX - scale * ih * 6) / 2) + H_MARGIN);
+ sprintf(bp, LN_PFS, "?20"); bp += 7;
+ sprintf(bp, LN_DECOPM_SET); bp += sizeof LN_DECOPM_SET - 1;
+ sprintf(bp, LN_DECSLRM, lm, W_PAGE - lm); bp += strlen(bp);
+ } else {
+ lm = (left > 0)? left : (((H_MAX - scale * iw) / 2) + H_MARGIN);
+ tm = (top > 0)? top : (((W_MAX - scale * ih * 6) / 2) + W_MARGIN);
+ sprintf(bp, LN_PFS, "?21"); bp += 7;
+ sprintf(bp, LN_DECOPM_SET); bp += sizeof LN_DECOPM_SET - 1;
+ sprintf(bp, LN_DECSLRM, lm, H_PAGE - lm); bp += strlen(bp);
+ }
+
+ if (header != NULL) {
+ sprintf(bp, LN_VPA, tm - 100); bp += strlen(bp);
+ i = strlen(header);
+ xm = (((scale * iw) - (i * 30)) / 2) + lm;
+ sprintf(bp, LN_HPA, xm); bp += strlen(bp);
+ sprintf(bp, LN_SGR, 3); bp += strlen(bp);
+ bcopy(header, bp, i);
+ bp += i;
+ }
+ if (trailer != NULL) {
+ sprintf(bp, LN_VPA, tm + (scale * ih * 6) + 75); bp += strlen(bp);
+ i = strlen(trailer);
+ xm = (((scale * iw) - (i * 30)) / 2) + lm;
+ sprintf(bp, LN_HPA, xm); bp += strlen(bp);
+ sprintf(bp, LN_SGR, 3); bp += strlen(bp);
+ bcopy(trailer, bp, i);
+ bp += i;
+ }
+
+ sprintf(bp, LN_HPA, lm); bp += strlen(bp);
+ sprintf(bp, LN_VPA, tm); bp += strlen(bp);
+ sprintf(bp, LN_SIXEL_GRAPHICS, 9, 0, scale); bp += strlen(bp);
+ sprintf(bp, "\"1;1"); bp += 4; /* Pixel aspect ratio */
+ write(1, buf, bp-buf);
+ *top_margin = tm;
+ *left_margin = lm;
+}
+
+
+ln03_finish()
+{
+ char buf[256];
+ register char *bp = buf;
+
+ sprintf(bp, LN_DECOPM_RESET); bp += sizeof LN_DECOPM_SET - 1;
+ sprintf(bp, LN_LNM); bp += 5;
+ sprintf(bp, LN_PUM); bp += 5;
+ sprintf(bp, LN_PFS, "?20"); bp += 7;
+ sprintf(bp, LN_SGR, 0); bp += strlen(bp);
+ sprintf(bp, LN_HPA, 1); bp += strlen(bp);
+ sprintf(bp, LN_VPA, 1); bp += strlen(bp);
+
+
+ write(1, buf, bp-buf);
+
+}
+
+/*ARGSUSED*/
+la100_setup(iw, ih, scale)
+{
+ char buf[256];
+ register char *bp;
+ int lm, tm;
+
+ bp = buf;
+ lm = ((80 - (int)((double)iw / 6.6)) / 2) - 1;
+ if (lm < 1) lm = 1;
+ tm = ((66 - (int)((double)ih / 2)) / 2) - 1;
+ if (tm < 1) tm = 1;
+ sprintf(bp, "\033[%d;%ds", lm, 81-lm); bp += strlen(bp);
+ sprintf(bp, "\033[?7l"); bp += 5;
+ sprintf(bp, "\033[%dd", tm); bp += strlen(bp);
+ sprintf(bp, "\033[%d`", lm); bp += strlen(bp);
+ sprintf(bp, "\033P0q"); bp += 4;
+ write(1, buf, bp-buf);
+}
+
+#define LA100_RESET "\033[1;80s\033[?7h"
+
+la100_finish()
+{
+ write(1, LA100_RESET, sizeof LA100_RESET - 1);
+}
+
+#define COMMENTVERSION "PS-Adobe-1.0"
+
+#ifdef XPROLOG
+/* for debugging, get the prolog from a file */
+dump_prolog(flags) {
+ char *fname=(flags & F_COMPACT) ? "prolog.compact" : "prolog";
+ FILE *fi = fopen(fname,"r");
+ char buf[1024];
+
+ if (fi==NULL) {
+ perror(fname);
+ exit(1);
+ }
+ while (fgets(buf,1024,fi)) fputs(buf,stdout);
+ fclose(fi);
+}
+
+#else /* XPROLOG */
+/* postscript "programs" to unpack and print the bitmaps being sent */
+
+char *ps_prolog_compact[] = {
+ "%%Pages: 1",
+ "%%EndProlog",
+ "%%Page: 1 1",
+ "",
+ "/bitgen",
+ " {",
+ " /nextpos 0 def",
+ " currentfile bufspace readhexstring pop % get a chunk of input",
+ " % interpret each byte of the input",
+ " {",
+ " flag { % if the previous byte was FF",
+ " /len exch def % this byte is a count",
+ " result",
+ " nextpos",
+ " FFstring 0 len getinterval % grap a chunk of FF's",
+ " putinterval % and stuff them into the result",
+ " /nextpos nextpos len add def",
+ " /flag false def",
+ " }{ % otherwise",
+ " dup 255 eq { % if this byte is FF",
+ " /flag true def % just set the flag",
+ " pop % and toss the FF",
+ " }{ % otherwise",
+ " % move this byte to the result",
+ " result nextpos",
+ " 3 -1 roll % roll the current byte back to the top",
+ " put",
+ " /nextpos nextpos 1 add def",
+ " } ifelse",
+ " } ifelse",
+ " } forall",
+ " % trim unused space from end of result",
+ " result 0 nextpos getinterval",
+ " } def",
+ "",
+ "",
+ "/bitdump % stk: width, height, iscale",
+ " % dump a bit image with lower left corner at current origin,",
+ " % scaling by iscale (iscale=1 means 1/300 inch per pixel)",
+ " {",
+ " % read arguments",
+ " /iscale exch def",
+ " /height exch def",
+ " /width exch def",
+ "",
+ " % scale appropriately",
+ " width iscale mul height iscale mul scale",
+ "",
+ " % data structures:",
+ "",
+ " % allocate space for one line of input",
+ " /bufspace 36 string def",
+ "",
+ " % string of FF's",
+ " /FFstring 256 string def",
+ " % for all i FFstring[i]=255",
+ " 0 1 255 { FFstring exch 255 put } for",
+ "",
+ " % 'escape' flag",
+ " /flag false def",
+ "",
+ " % space for a chunk of generated bits",
+ " /result 4590 string def",
+ "",
+ " % read and dump the image",
+ " width height 1 [width 0 0 height neg 0 height]",
+ " { bitgen }",
+ " image",
+ " } def",
+ 0
+};
+
+char *ps_prolog[] = {
+ "%%Pages: 1",
+ "%%EndProlog",
+ "%%Page: 1 1",
+ "",
+ "/bitdump % stk: width, height, iscale",
+ "% dump a bit image with lower left corner at current origin,",
+ "% scaling by iscale (iscale=1 means 1/300 inch per pixel)",
+ "{",
+ " % read arguments",
+ " /iscale exch def",
+ " /height exch def",
+ " /width exch def",
+ "",
+ " % scale appropriately",
+ " width iscale mul height iscale mul scale",
+ "",
+ " % allocate space for one scanline of input",
+ " /picstr % picstr holds one scan line",
+ " width 7 add 8 idiv % width of image in bytes = ceiling(width/8)",
+ " string",
+ " def",
+ "",
+ " % read and dump the image",
+ " width height 1 [width 0 0 height neg 0 height]",
+ " { currentfile picstr readhexstring pop }",
+ " image",
+ "} def",
+ 0
+};
+
+dump_prolog(flags) {
+ char **p = (flags & F_COMPACT) ? ps_prolog_compact : ps_prolog;
+ while (*p) printf("%s\n",*p++);
+}
+#endif /* XPROLOG */
+
+#define PAPER_WIDTH 85*30 /* 8.5 inches */
+#define PAPER_LENGTH 11*300 /* 11 inches */
+
+static int
+points(n)
+{
+ /* scale n from pixels (1/300 inch) to points (1/72 inch) */
+ n *= 72;
+ return n/300;
+}
+
+static char *
+escape(s)
+char *s;
+{
+ /* make a version of s in which control characters are deleted and
+ * special characters are escaped.
+ */
+ static char buf[200];
+ char *p = buf;
+
+ for (;*s;s++) {
+ if (*s < ' ' || *s > 0176) continue;
+ if (*s==')' || *s=='(' || *s == '\\') {
+ sprintf(p,"\\%03o",*s);
+ p += 4;
+ }
+ else *p++ = *s;
+ }
+ *p = 0;
+ return buf;
+}
+
+ps_setup(iw, ih, orientation, scale, left, top,
+ flags, header, trailer, name)
+int iw;
+int ih;
+enum orientation orientation;
+int scale;
+int left;
+int top;
+int flags;
+char *header;
+char *trailer;
+char *name;
+{
+ char hostname[256];
+#ifdef WIN32
+ char *username;
+#else
+ struct passwd *pswd;
+#endif
+ long clock;
+ int lm, bm; /* left (bottom) margin */
+
+ /* calculate margins */
+ if (orientation==PORTRAIT) {
+ lm = (left > 0)? left : ((PAPER_WIDTH - scale * iw) / 2);
+ bm = (top > 0)? (PAPER_LENGTH - top - scale * ih)
+ : ((PAPER_LENGTH - scale * ih) / 2);
+ } else { /* orientation == LANDSCAPE */
+ lm = (top > 0)? (PAPER_WIDTH - top - scale * ih)
+ : ((PAPER_WIDTH - scale * ih) / 2);
+ bm = (left > 0)? (PAPER_LENGTH - left - scale * iw)
+ : ((PAPER_LENGTH - scale * iw) / 2);
+ }
+ printf ("%%!%s\n", COMMENTVERSION);
+ printf ("%%%%BoundingBox: %d %d %d %d\n",
+ (flags & F_NPOSITION) ? points(lm) : 0,
+ (flags & F_NPOSITION) ? points(bm) : 0,
+ points(iw * scale), points(ih * scale));
+ (void) XmuGetHostname (hostname, sizeof hostname);
+#ifdef WIN32
+ username = getenv("USERNAME");
+ printf ("%%%%Creator: %s:%s\n", hostname,
+ username ? username : "unknown");
+#else
+ pswd = getpwuid (getuid ());
+ printf ("%%%%Creator: %s:%s (%s)\n", hostname,
+ pswd->pw_name, pswd->pw_gecos);
+#endif
+ printf ("%%%%Title: %s (%s)\n", infilename,name);
+ printf ("%%%%CreationDate: %s",
+ (time (&clock), ctime (&clock)));
+ printf ("%%%%EndComments\n");
+
+ dump_prolog(flags);
+
+ if (orientation==PORTRAIT) {
+ if (header || trailer) {
+ printf("gsave\n");
+ printf("/Times-Roman findfont 15 scalefont setfont\n");
+ /* origin at bottom left corner of image */
+ printf("%d %d translate\n",points(lm),points(bm));
+ if (header) {
+ char *label = escape(header);
+ printf("%d (%s) stringwidth pop sub 2 div %d moveto\n",
+ points(iw*scale), label, points(ih*scale) + 10);
+ printf("(%s) show\n",label);
+ }
+ if (trailer) {
+ char *label = escape(trailer);
+ printf("%d (%s) stringwidth pop sub 2 div -20 moveto\n",
+ points(iw*scale), label);
+ printf("(%s) show\n",label);
+ }
+ printf("grestore\n");
+ }
+ /* set resolution to device units (300/inch) */
+ printf("72 300 div dup scale\n");
+ /* move to lower left corner of image */
+ if (!(flags & F_NPOSITION))
+ printf("%d %d translate\n",lm,bm);
+ /* dump the bitmap */
+ printf("%d %d %d bitdump\n",iw,ih,scale);
+ } else { /* orientation == LANDSCAPE */
+ if (header || trailer) {
+ printf("gsave\n");
+ printf("/Times-Roman findfont 15 scalefont setfont\n");
+ /* origin at top left corner of image */
+ printf("%d %d translate\n",points(lm),points(bm + scale * iw));
+ /* rotate to print the titles */
+ printf("-90 rotate\n");
+ if (header) {
+ char *label = escape(header);
+ printf("%d (%s) stringwidth pop sub 2 div %d moveto\n",
+ points(iw*scale), label, points(ih*scale) + 10);
+ printf("(%s) show\n",label);
+ }
+ if (trailer) {
+ char *label = escape(trailer);
+ printf("%d (%s) stringwidth pop sub 2 div -20 moveto\n",
+ points(iw*scale), label);
+ printf("(%s) show\n",label);
+ }
+ printf("grestore\n");
+ }
+ /* set resolution to device units (300/inch) */
+ printf("72 300 div dup scale\n");
+ /* move to lower left corner of image */
+ if (!(flags & F_NPOSITION))
+ printf("%d %d translate\n",lm,bm);
+ /* dump the bitmap */
+ printf("%d %d %d bitdump\n",ih,iw,scale);
+ }
+}
+
+char *ps_epilog[] = {
+ "",
+ "showpage",
+ "%%Trailer",
+ 0
+};
+
+ps_finish()
+{
+ char **p = ps_epilog;
+
+ while (*p) printf("%s\n",*p++);
+}
+
+ln03_alter_background(sixmap, iw, ih)
+unsigned char (*sixmap)[];
+int iw;
+int ih;
+{
+ register unsigned char *c, *stopc;
+ register unsigned char *startc;
+ register int n;
+
+ c = (unsigned char *)sixmap;
+ stopc = c + (iw * ih);
+ n = 0;
+ while (c < stopc) {
+ switch (*c) {
+ case 0x08: case 0x11: case 0x04: case 0x22:
+ case 0x20: case 0x21: case 0x24: case 0x00:
+ if (n == 0) startc = c;
+ n++;
+ break;
+
+ default:
+ if (n >= 2) {
+ while (n-- > 0) *startc++ = 0x00;
+ } else {
+ n = 0;
+ }
+ break;
+ }
+ c++;
+ }
+}
+
+ln03_output_sixels(sixmap, iw, ih, nosixopt, split, scale, top_margin,
+ left_margin)
+unsigned char (*sixmap)[];
+int iw;
+int ih;
+int nosixopt;
+int split;
+int top_margin;
+int left_margin;
+{
+ unsigned char *buf;
+ register unsigned char *bp;
+ int i;
+ int j;
+ register int k;
+ register unsigned char *c;
+ register int lastc;
+ register int count;
+ char snum[6];
+ register char *snp;
+
+ bp = (unsigned char *)malloc((unsigned)(iw*ih+512));
+ buf = bp;
+ count = 0;
+ lastc = -1;
+ c = (unsigned char *)sixmap;
+ split = ih / split; /* number of lines per page */
+
+ iw--; /* optimization */
+ for (i = 0; i < ih; i++) {
+ for (j = 0; j <= iw; j++) {
+ if (!nosixopt) {
+ if (*c == lastc && j < iw) {
+ count++;
+ c++;
+ continue;
+ }
+ if (count >= 3) {
+ bp--;
+ count++;
+ *bp++ = '!';
+ snp = snum;
+ while (count > 0) {
+ k = count / 10;
+ *snp++ = count - (k * 10) + '0';
+ count = k;
+ }
+ while (--snp >= snum) *bp++ = *snp;
+ *bp++ = (~lastc & 0x3F) + 0x3F;
+ } else if (count > 0) {
+ lastc = (~lastc & 0x3F) + 0x3F;
+ do {
+ *bp++ = lastc;
+ } while (--count > 0);
+ }
+ }
+ lastc = *c++;
+ *bp++ = (~lastc & 0x3F) + 0x3F;
+ }
+ *bp++ = '-'; /* New line */
+ lastc = -1;
+ if ((i % split) == 0 && i != 0) {
+ sprintf((char *)bp, LN_ST); bp += sizeof LN_ST - 1;
+ *bp++ = '\f';
+ sprintf((char *)bp, LN_VPA, top_margin + (i * 6 * scale));
+ bp += strlen((char *)bp);
+ sprintf((char *)bp, LN_HPA, left_margin);
+ bp += strlen((char *)bp);
+ sprintf((char *)bp, LN_SIXEL_GRAPHICS, 9, 0, scale);
+ bp += strlen((char *)bp);
+ sprintf((char *)bp, "\"1;1"); bp += 4;
+ }
+ }
+
+ sprintf((char *)bp, LN_ST); bp += sizeof LN_ST - 1;
+ write(1, (char *)buf, bp-buf);
+}
+
+/*ARGSUSED*/
+la100_output_sixels(sixmap, iw, ih, nosixopt)
+unsigned char (*sixmap)[];
+int iw;
+int ih;
+int nosixopt;
+{
+ unsigned char *buf;
+ register unsigned char *bp;
+ int i;
+ register int j, k;
+ register unsigned char *c;
+ register int lastc;
+ register int count;
+ char snum[6];
+
+ bp = (unsigned char *)malloc((unsigned)(iw*ih+512));
+ buf = bp;
+ count = 0;
+ lastc = -1;
+ c = (unsigned char *)sixmap;
+
+ for (i = 0; i < ih; i++) {
+ for (j = 0; j < iw; j++) {
+ if (*c == lastc && (j+1) < iw) {
+ count++;
+ c++;
+ continue;
+ }
+ if (count >= 2) {
+ bp -= 2;
+ count = 2 * (count + 1);
+ *bp++ = '!';
+ k = 0;
+ while (count > 0) {
+ snum[k++] = (count % 10) + '0';
+ count /= 10;
+ }
+ while (--k >= 0) *bp++ = snum[k];
+ *bp++ = (~lastc & 0x3F) + 0x3F;
+ count = 0;
+ } else if (count > 0) {
+ lastc = (~lastc & 0x3F) + 0x3F;
+ do {
+ *bp++ = lastc;
+ *bp++ = lastc;
+ } while (--count > 0);
+ }
+ lastc = (~*c & 0x3F) + 0x3F;
+ *bp++ = lastc;
+ *bp++ = lastc;
+ lastc = *c++;
+ }
+ *bp++ = '-'; /* New line */
+ lastc = -1;
+ }
+
+ sprintf((char *)bp, LN_ST); bp += sizeof LN_ST - 1;
+ *bp++ = '\f';
+ write(1, (char *)buf, bp-buf);
+}
+
+#define LINELEN 72 /* number of CHARS (bytes*2) per line of bitmap output */
+
+ps_output_bits(iw, ih, flags, orientation, win, data)
+int iw;
+int ih;
+int flags;
+XWDFileHeader *win;
+enum orientation orientation;
+char *data;
+{
+ unsigned long swaptest = 1;
+ int iwb = win->bytes_per_line;
+ register int i;
+ int bytes;
+ unsigned char *buffer = (unsigned char *)data;
+ register int ocount=0;
+ extern char hex1[],hex2[];
+ static char hex[] = "0123456789abcdef";
+
+ if (orientation == LANDSCAPE) {
+ /* read in and rotate the entire image */
+ /* The Postscript language has a rotate operator, but using it
+ * seem to make printing (at least on the Apple Laserwriter
+ * take about 10 times as long (40 minutes for a 1024x864 full-screen
+ * dump)! Therefore, we rotate the image here.
+ */
+ int ocol = ih;
+ int owidth = (ih+31)/32; /* width of rotated image, in bytes */
+ int oheight = (iw+31)/32; /* height of rotated image, in scanlines */
+ register char *p, *q;
+ char *obuf;
+ unsigned char *ibuf;
+ owidth *= 4;
+ oheight *= 32;
+
+ /* Allocate buffer for the entire rotated image (output).
+ * Owidth and Oheight are rounded up to a multiple of 32 bits,
+ * to avoid special cases at the boundaries
+ */
+ obuf = malloc((unsigned)(owidth*oheight));
+ if (obuf==0) {
+ fprintf(stderr,"xpr: cannot allocate %d bytes\n",owidth*oheight);
+ exit(1);
+ }
+ bzero(obuf,owidth*oheight);
+
+ ibuf = (unsigned char *)malloc((unsigned)(iwb + 3));
+ for (i=0;i<ih;i++) {
+ bcopy((char *)buffer, (char *)ibuf, iwb);
+ buffer += iwb;
+ if (!(*(char *) &swaptest))
+ _swaplong((char *)ibuf,(long)iwb);
+ ps_bitrot(ibuf,iw,--ocol,owidth,obuf);
+ }
+ if (!(*(char *) &swaptest))
+ _swaplong(obuf,(long)(iw*owidth));
+ q = &obuf[iw*owidth];
+ bytes = (ih+7)/8;
+ for (p=obuf;p<q;p+=owidth)
+ ocount = ps_putbuf((unsigned char *)p,bytes,ocount,flags&F_COMPACT);
+ }
+ else {
+ for (i=0;i<ih;i++) {
+ ocount = ps_putbuf(buffer,(iw+7)/8,ocount,flags&F_COMPACT);
+ buffer += iwb;
+ }
+ }
+ if (flags & F_COMPACT) {
+ if (ocount) {
+ /* pad to an integral number of lines */
+ while (ocount++ < LINELEN)
+ /* for debugging, pad with a "random" value */
+ putchar(hex[ocount&15]);
+ putchar('\n');
+ }
+ }
+}
+
+unsigned char _reverse_byte[0x100] = {
+ 0x00, 0x80, 0x40, 0xc0, 0x20, 0xa0, 0x60, 0xe0,
+ 0x10, 0x90, 0x50, 0xd0, 0x30, 0xb0, 0x70, 0xf0,
+ 0x08, 0x88, 0x48, 0xc8, 0x28, 0xa8, 0x68, 0xe8,
+ 0x18, 0x98, 0x58, 0xd8, 0x38, 0xb8, 0x78, 0xf8,
+ 0x04, 0x84, 0x44, 0xc4, 0x24, 0xa4, 0x64, 0xe4,
+ 0x14, 0x94, 0x54, 0xd4, 0x34, 0xb4, 0x74, 0xf4,
+ 0x0c, 0x8c, 0x4c, 0xcc, 0x2c, 0xac, 0x6c, 0xec,
+ 0x1c, 0x9c, 0x5c, 0xdc, 0x3c, 0xbc, 0x7c, 0xfc,
+ 0x02, 0x82, 0x42, 0xc2, 0x22, 0xa2, 0x62, 0xe2,
+ 0x12, 0x92, 0x52, 0xd2, 0x32, 0xb2, 0x72, 0xf2,
+ 0x0a, 0x8a, 0x4a, 0xca, 0x2a, 0xaa, 0x6a, 0xea,
+ 0x1a, 0x9a, 0x5a, 0xda, 0x3a, 0xba, 0x7a, 0xfa,
+ 0x06, 0x86, 0x46, 0xc6, 0x26, 0xa6, 0x66, 0xe6,
+ 0x16, 0x96, 0x56, 0xd6, 0x36, 0xb6, 0x76, 0xf6,
+ 0x0e, 0x8e, 0x4e, 0xce, 0x2e, 0xae, 0x6e, 0xee,
+ 0x1e, 0x9e, 0x5e, 0xde, 0x3e, 0xbe, 0x7e, 0xfe,
+ 0x01, 0x81, 0x41, 0xc1, 0x21, 0xa1, 0x61, 0xe1,
+ 0x11, 0x91, 0x51, 0xd1, 0x31, 0xb1, 0x71, 0xf1,
+ 0x09, 0x89, 0x49, 0xc9, 0x29, 0xa9, 0x69, 0xe9,
+ 0x19, 0x99, 0x59, 0xd9, 0x39, 0xb9, 0x79, 0xf9,
+ 0x05, 0x85, 0x45, 0xc5, 0x25, 0xa5, 0x65, 0xe5,
+ 0x15, 0x95, 0x55, 0xd5, 0x35, 0xb5, 0x75, 0xf5,
+ 0x0d, 0x8d, 0x4d, 0xcd, 0x2d, 0xad, 0x6d, 0xed,
+ 0x1d, 0x9d, 0x5d, 0xdd, 0x3d, 0xbd, 0x7d, 0xfd,
+ 0x03, 0x83, 0x43, 0xc3, 0x23, 0xa3, 0x63, 0xe3,
+ 0x13, 0x93, 0x53, 0xd3, 0x33, 0xb3, 0x73, 0xf3,
+ 0x0b, 0x8b, 0x4b, 0xcb, 0x2b, 0xab, 0x6b, 0xeb,
+ 0x1b, 0x9b, 0x5b, 0xdb, 0x3b, 0xbb, 0x7b, 0xfb,
+ 0x07, 0x87, 0x47, 0xc7, 0x27, 0xa7, 0x67, 0xe7,
+ 0x17, 0x97, 0x57, 0xd7, 0x37, 0xb7, 0x77, 0xf7,
+ 0x0f, 0x8f, 0x4f, 0xcf, 0x2f, 0xaf, 0x6f, 0xef,
+ 0x1f, 0x9f, 0x5f, 0xdf, 0x3f, 0xbf, 0x7f, 0xff
+};
+
+_invbits (b, n)
+ register unsigned char *b;
+ register long n;
+{
+ do {
+ *b = ~*b;
+ b++;
+ } while (--n > 0);
+
+}
+
+/* copied from lib/X/XPutImage.c */
+
+_swapbits (b, n)
+ register unsigned char *b;
+ register long n;
+{
+ do {
+ *b = _reverse_byte[*b];
+ b++;
+ } while (--n > 0);
+
+}
+
+_swapshort (bp, n)
+ register char *bp;
+ register long n;
+{
+ register char c;
+ register char *ep = bp + n;
+ do {
+ c = *bp;
+ *bp = *(bp + 1);
+ bp++;
+ *bp = c;
+ bp++;
+ }
+ while (bp < ep);
+}
+
+_swaplong (bp, n)
+ register char *bp;
+ register long n;
+{
+ register char c;
+ register char *ep = bp + n;
+ register char *sp;
+ do {
+ sp = bp + 3;
+ c = *sp;
+ *sp = *bp;
+ *bp++ = c;
+ sp = bp + 1;
+ c = *sp;
+ *sp = *bp;
+ *bp++ = c;
+ bp += 2;
+ }
+ while (bp < ep);
+}
+
+/* Dump some bytes in hex, with bits in each byte reversed
+ * Ocount is number of chacters that have been written to the current
+ * output line. It's new value is returned as the result of the function.
+ * Ocount is ignored (and the return value is meaningless) if compact==0.
+ */
+int
+ps_putbuf(s, n, ocount, compact)
+register unsigned char *s; /* buffer to dump */
+register int n; /* number of BITS to dump */
+register int ocount; /* position on output line for next char */
+int compact; /* if non-zero, do compaction (see below) */
+{
+ register int ffcount = 0;
+ extern char hex1[],hex2[];
+ static char hex[] = "0123456789abcdef";
+#define PUT(c) { putchar(c); if (++ocount>=LINELEN) \
+ { putchar('\n'); ocount=0; }}
+
+ if (compact) {
+ /* The following loop puts out the bits of the image in hex,
+ * compressing runs of white space (represented by one bits)
+ * according the the following simple algorithm: A run of n
+ * 'ff' bytes (i.e., bytes with value 255--all ones), where
+ * 1<=n<=255, is represented by a single 'ff' byte followed by a
+ * byte containing n.
+ * On a typical dump of a full screen pretty much covered by
+ * black-on-white text windows, this compression decreased the
+ * size of the file from 223 Kbytes to 63 Kbytes.
+ * Of course, another factor of two could be saved by sending
+ * the bytes 'as is' rather than in hex, using some sort of
+ * escape convention to avoid problems with control characters.
+ * Another popular encoding is to pack three bytes into 4 'sixels'
+ * as in the LN03, etc, but I'm too lazy to write the necessary
+ * PostScript code to unpack fancier representations.
+ */
+ while (n--) {
+ if (*s == 0xff) {
+ if (++ffcount == 255) {
+ PUT('f'); PUT('f');
+ PUT('f'); PUT('f');
+ ffcount = 0;
+ }
+ }
+ else {
+ if (ffcount) {
+ PUT('f'); PUT('f');
+ PUT(hex[ffcount >> 4]);
+ PUT(hex[ffcount & 0xf]);
+ ffcount = 0;
+ }
+ PUT(hex1[*s]);
+ PUT(hex2[*s]);
+ }
+ s++;
+ }
+ if (ffcount) {
+ PUT('f'); PUT('f');
+ PUT(hex[ffcount >> 4]);
+ PUT(hex[ffcount & 0xf]);
+ ffcount = 0;
+ }
+ }
+ else { /* no compaction: just dump the image in hex (bits reversed) */
+ while (n--) {
+ putchar(hex1[*s]);
+ putchar(hex2[*s++]);
+ }
+ putchar('\n');
+ }
+ return ocount;
+}
+
+ps_bitrot(s,n,col,owidth,obuf)
+unsigned char *s;
+register int n;
+int col;
+register int owidth;
+char *obuf;
+/* s points to a chunk of memory and n is its width in bits.
+ * The algorithm is, roughly,
+ * for (i=0;i<n;i++) {
+ * OR the ith bit of s into the ith row of the
+ * (col)th column of obuf
+ * }
+ * Assume VAX bit and byte ordering for s:
+ * The ith bit of s is s[j]&(1<<k) where i=8*j+k.
+ * It can also be retrieved as t[j]&(1<<k), where t=(int*)s and i=32*j+k.
+ * Also assume VAX bit and byte ordering for each row of obuf.
+ * Ps_putbuf() takes care of converting to Motorola 68000 byte and bit
+ * ordering. The following code is very carefully tuned to yield a very
+ * tight loop on the VAX, since it easily dominates the entire running
+ * time of this program. In particular, iwordp is declared last, since
+ * there aren't enough registers, and iwordp is referenced only once
+ * every 32 times through the loop.
+ */
+{
+ register int mask = 1<<(col%32);
+ register int iword; /* current input word (*iwordp) */
+ register int b = 0; /* number of bits in iword left to examine */
+ register char *opos = obuf + (col/32)*4;
+ /* pointer to word of obuf to receive next output bit */
+ register int *iwordp = (int *) s; /* pointer to next word of s */
+
+ while (--n>=0) {
+ if (--b < 0) {
+ iword = *iwordp++;
+ b = 31;
+ }
+ if (iword & 1) {
+ *(int *)opos |= mask;
+ }
+ opos += owidth;
+ iword >>= 1;
+ }
+}
+
+/* fullread() is the same as read(), except that it guarantees to
+ read all the bytes requested. */
+
+fullread (file, data, nbytes)
+ int file;
+ char *data;
+ int nbytes;
+ {
+ int bytes_read;
+ while ((bytes_read = read(file, data, nbytes)) != nbytes) {
+ if (bytes_read < 0) {
+ perror ("error while reading standard input");
+ return;
+ }
+ else if (bytes_read == 0) {
+ fprintf (stderr, "xpr: premature end of file\n");
+ return;
+ }
+ nbytes -= bytes_read;
+ data += bytes_read;
+ }
+ }
+
+/* mapping tables to map a byte in to the hex representation of its
+ * bit-reversal
+ */
+char hex1[]="084c2a6e195d3b7f084c2a6e195d3b7f084c2a6e195d3b7f084c2a6e195d3b7f\
+084c2a6e195d3b7f084c2a6e195d3b7f084c2a6e195d3b7f084c2a6e195d3b7f\
+084c2a6e195d3b7f084c2a6e195d3b7f084c2a6e195d3b7f084c2a6e195d3b7f\
+084c2a6e195d3b7f084c2a6e195d3b7f084c2a6e195d3b7f084c2a6e195d3b7f";
+
+char hex2[]="000000000000000088888888888888884444444444444444cccccccccccccccc\
+2222222222222222aaaaaaaaaaaaaaaa6666666666666666eeeeeeeeeeeeeeee\
+111111111111111199999999999999995555555555555555dddddddddddddddd\
+3333333333333333bbbbbbbbbbbbbbbb7777777777777777ffffffffffffffff";
+
diff --git a/xpr.h b/xpr.h
new file mode 100644
index 0000000..9a2565f
--- /dev/null
+++ b/xpr.h
@@ -0,0 +1,33 @@
+#ifndef X_NOT_STDC_ENV
+#include <stdlib.h>
+#else
+char *malloc(), *realloc(), *calloc();
+#endif
+#if defined(macII) && !defined(__STDC__) /* stdlib.h fails to define these */
+char *malloc(), *realloc(), *calloc();
+#endif /* macII */
+
+/* 3812 PagePrinter macros */
+#define PPI 240
+#define inch2pel(inches) ((int) ((inches) * PPI))
+#define DEFAULT_WIDTH 8.5
+#define X_MAX_PELS inch2pel(DEFAULT_WIDTH)
+#define DEFAULT_LENGTH 11
+#define Y_MAX_PELS inch2pel(DEFAULT_LENGTH)
+
+#define INTENSITY(color) (30L*(int)(color)->red + \
+ 59L*(int)(color)->green + \
+ 11L*(int)(color)->blue)
+
+#define INTENSITYPER(per) (((1<<16)-1)*((long)per))
+#define HALFINTENSITY INTENSITYPER(50)
+
+enum orientation {
+ UNSPECIFIED = -1,
+ PORTRAIT = 0,
+ LANDSCAPE = 1,
+ UPSIDE_DOWN = 2,
+ LANDSCAPE_LEFT = 3
+ };
+
+enum device {LN01, LN03, LA100, PS, PP, LJET, PJET, PJETXL};
diff --git a/xpr.man b/xpr.man
new file mode 100644
index 0000000..63693e4
--- /dev/null
+++ b/xpr.man
@@ -0,0 +1,338 @@
+.\" $XConsortium: xpr.man,v 1.22 94/04/17 20:44:06 gildea Exp $
+.TH XPR 1 "Release 6" "X Version 11"
+.SH NAME
+xpr \- print an X window dump
+.SH SYNOPSIS
+.B xpr
+[
+.B \-device
+.I devtype
+] [
+.B \-scale
+.I scale
+] [
+.B \-height
+.I inches
+] [
+.B \-width
+.I inches
+] [
+.B \-left
+.I inches
+] [
+.B \-top
+.I inches
+] [
+.B \-header
+.I string
+] [
+.B \-trailer
+.I string
+] [
+.B \-landscape
+] [
+.B \-portrait
+] [
+.B \-plane
+.I number
+] [
+.B \-gray
+] [
+.B \-rv
+] [
+.B \-compact
+] [
+.B \-output
+.I filename
+] [
+.B \-append
+.I filename
+] [
+.B \-noff
+] [
+.B \-split
+.I n
+] [
+.B \-psfig
+] [
+.B \-density
+.I dpi
+] [
+.B \-cutoff
+.I level
+] [
+.B \-noposition
+] [
+.B \-gamma
+.I correction
+] [
+.B \-render
+.I algorithm
+] [
+.B \-slide
+] [
+.I filename
+]
+.SH DESCRIPTION
+
+.I xpr
+takes as input a window dump file produced by
+.IR xwd(1)
+and formats it for output on PostScript printers, the Digital LN03 or LA100,
+the IBM PP3812 page printer, the HP LaserJet (or other PCL printers),
+or the HP PaintJet. If no file
+argument is given, the standard input is used. By default, \fIxpr\fP
+prints the largest possible representation of the window on the
+output page. Options allow the user to add headers and trailers,
+specify margins, adjust the scale and orientation, and append
+multiple window dumps to a single output file. Output is to
+standard output unless
+.B \-output
+is specified.
+.sp 1
+.ne 8
+.B Command Options
+.sp 1
+.IP "\fB\-device\fP \fIdevtype\fP"
+Specifies the device on which the file will be printed. Currently supported:
+.RS 12
+.PD 0
+.TP
+.B la100
+Digital LA100
+.TP
+.B ljet
+\s-1HP\s+1 LaserJet series and other monochrome PCL devices
+such as ThinkJet, QuietJet, RuggedWriter, \s-1HP\s+12560 series,
+and \s-1HP\s+12930 series printers
+.TP
+.B ln03
+Digital LN03
+.TP
+.B pjet
+HP PaintJet (color mode)
+.TP
+.B pjetxl
+HP HP PaintJet XL Color Graphics Printer (color mode)
+.TP
+.B pp
+IBM PP3812
+.TP
+.B ps
+PostScript printer
+.PD
+.RE
+.IP
+The default is PostScript.
+\fB-device lw\fP (LaserWriter) is equivalent to -device ps and is
+provided only for backwards compatibility.
+.IP "\fB\-scale\fP \fIscale\fP"
+Affects the size of the window on the page. The PostScript, LN03, and HP
+printers are able to
+translate each bit in a window pixel map into a grid of a specified size.
+For example each bit might translate into a 3x3 grid. This would be
+specified by \fB\-scale\fP \fI3\fP. By default a window is printed
+with the largest scale that will fit onto the page for the specified
+orientation.
+.IP "\fB\-height\fP \fIinches\fP"
+Specifies the maximum height of the page.
+.IP "\fB\-width\fP \fIinches\fP"
+Specifies the maximum width of the page.
+.IP "\fB\-left\fP \fIinches\fP"
+Specifies the left margin in inches. Fractions
+are allowed. By default the window is centered in the page.
+.IP "\fB\-top\fP \fIinches\fP"
+Specifies the top margin for the picture in inches. Fractions are
+allowed.
+.IP "\fB\-header\fP \fIstring\fP"
+Specifies a header string to be printed above the window.
+.IP "\fB\-trailer\fP \fIstring\fP"
+Specifies a trailer string to be printed below the window.
+.IP "\fB\-landscape\fP"
+Forces the window to printed in landscape mode. By default
+a window is printed such that its longest side follows the long side of
+the paper.
+.IP "\fB\-plane\fP \fInumber\fP"
+Specifies which bit plane to use in an image. The default is to use the
+entire image and map values into black and white based on color intensities.
+.IP "\fB\-gray\fP \fI 2 | 3 | 4\fP"
+Uses a simple 2x2, 3x3, or 4x4 gray scale conversion on a color image,
+rather than mapping to strictly black and white. This doubles,
+triples, or quadruples the effective width and height of the image.
+.IP "\fB\-portrait\fP"
+Forces the window to be printed in portrait mode. By default
+a window is printed such that its longest side follows the long side of
+the paper.
+.IP "\fB\-rv\fP"
+Forces the window to be printed in reverse video.
+.IP "\fB\-compact\fP"
+Uses simple run-length encoding for compact representation of windows
+with lots of white pixels.
+.IP "\fB\-output\fP \fIfilename\fP"
+Specifies an output file name. If this option is not specified, standard
+output is used.
+.IP "\fB\-append\fP \fIfilename\fP"
+Specifies a filename previously produced by \fIxpr\fP to which the window
+is to be appended.
+.IP "\fB\-noff\fP"
+When specified in conjunction with \fB\-append\fP, the window will appear
+on the same page as the previous window.
+.IP "\fB\-split\fP \fIn\fP"
+This option allows the user to split a window onto several pages.
+This might be necessary for very large windows that would otherwise
+cause the printer to overload and print the page in an obscure manner.
+.IP "\fB\-psfig\fP"
+Suppress translation of the PostScript picture to the center of the page.
+.IP "\fB\-density\fP \fIdpi\fP"
+Indicates what dot-per-inch density should be used by the HP printer.
+.IP "\fB\-cutoff\fP \fIlevel\fP"
+Changes the intensity level where colors are mapped to either black or
+white for monochrome output on a LaserJet printer.
+The \fIlevel\fP is expressed as percentage of
+full brightness. Fractions are allowed.
+.IP "\fB\-noposition\fP"
+This option causes header, trailer, and image positioning command
+generation to be bypassed for LaserJet, PaintJet and
+PaintJet XL printers.
+.IP "\fB\-gamma\fP \fIcorrection\fP"
+This changes the intensity of the colors printed by
+PaintJet XL printer. The \fIcorrection\fP is
+a floating point value in the range 0.00 to 3.00.
+Consult the operator's manual to determine the correct value for
+the specific printer.
+.IP "\fB\-render\fP \fIalgorithm\fP"
+This allows PaintJet XL printer to render the
+image with the best quality versus performance tradeoff.
+Consult the operator's manual to determine which \fIalgorithm\fPs
+are available.
+.IP "\fB\-slide\fP"
+This option allows overhead transparencies to be printed
+using the PaintJet and PaintJet XL printers.
+
+.SH SEE ALSO
+xwd(1), xwud(1), X(1)
+.SH LIMITATIONS
+
+The current version of \fIxpr\fP can generally print out on the LN03
+most X windows that are not larger than two-thirds of the screen.
+For example, it will be able to print out a large Emacs window, but
+it will usually fail when trying to print out the entire screen. The
+LN03 has memory limitations that can cause it to incorrectly print
+very large or complex windows. The two most common errors
+encountered are ``band too complex'' and ``page memory exceeded.''
+In the first case, a window may have a particular six pixel row that
+contains too many changes (from black to white to black). This will
+cause the printer to drop part of the line and possibly parts of the
+rest of the page. The printer will flash the number `1' on its front
+panel when this problem occurs. A possible solution to this problem
+is to increase the scale of the picture, or to split the picture onto
+two or more pages. The second problem, ``page memory exceeded,''
+will occur if the picture contains too much black, or if the picture
+contains complex half-tones such as the background color of a
+display. When this problem occurs the printer will automatically
+split the picture into two or more pages. It may flash the number
+`5' on its from panel. There is no easy solution to this problem.
+It will probably be necessary to either cut and paste, or to rework the
+application to produce a less complex picture.
+
+There are several limitations on the LA100 support:
+the picture will always be printed in
+portrait mode, there is no scaling,
+and the aspect ratio will be slightly off.
+
+Support for PostScript output currently cannot handle the \fB-append\fP,
+\fB-noff\fP or \fB-split\fP options.
+
+The \fB-compact\fP option is
+.I only
+supported for PostScript output.
+It compresses white space but not black space, so it is not useful for
+reverse-video windows.
+
+For color images, should map directly to PostScript image support.
+
+.SH "HP PRINTERS"
+
+If no \fB\-density\fP is specified on the command line 300 dots per inch
+will be assumed for \fIljet\fP and 90 dots per inch for \fIpjet\fP.
+Allowable \fIdensity\fP values for a LaserJet printer are 300, 150, 100,
+and 75 dots per inch. Consult the operator's manual to determine densities
+supported by other printers.
+
+If no \fB\-scale\fP is specified the image will be expanded to fit the
+printable page area.
+
+The default printable page area is 8x10.5 inches. Other paper sizes can
+be accommodated using the \fB\-height\fP and \fB\-width\fP options.
+
+Note that a 1024x768 image fits the default printable area when processed
+at 100 dpi with scale=1, the same image can also be printed using 300 dpi
+with scale=3 but will require considerably more data be transferred to the
+printer.
+
+\fIxpr\fP may be tailored for use with monochrome PCL printers other than
+the LaserJet. To print on a ThinkJet (\s-1HP\s+12225A) \fIxpr\fP could be
+invoked as:
+.sp
+.RS 4
+xpr -density 96 -width 6.667 \fIfilename\fP
+.RE
+.sp
+or for black-and-white output to a PaintJet:
+.sp
+.RS 4
+xpr -density 180 \fIfilename\fP
+.RE
+
+The monochrome intensity of a pixel is computed as 0.30*R + 0.59*G
++ 0.11*B.
+If a pixel's computed intensity is less than the \fB\-cutoff\fP
+level it will print as white. This maps light-on-dark display images
+to black-on-white hardcopy. The default cutoff intensity is 50% of full
+brightness. Example: specifying \fB\-cutoff 87.5\fP moves the
+white/black intensity point to 87.5% of full brightness.
+
+A LaserJet printer must be configured with sufficient memory to handle the
+image. For a full page at 300 dots per inch approximately 2MB of printer
+memory is required.
+
+Color images are produced on the PaintJet
+at 90 dots per inch. The
+PaintJet is limited to sixteen colors from its 330 color palette on each
+horizontal print line. \fIxpr\fP will issue a warning message if more than
+sixteen colors are encountered on a line. \fIxpr\fP will program the
+PaintJet for the first sixteen colors encountered on each line and use the
+nearest matching programmed value for other colors present on the line.
+
+Specifying the \fB\-rv\fP, reverse video, option for the PaintJet will
+cause black and white to be interchanged on the output image. No other
+colors are changed.
+
+Multiplane images must be recorded by \fIxwd\fP in \fIZPixmap\fP format.
+Single plane (monochrome) images may be in either \fIXYPixmap\fP or
+\fIZPixmap\fP format.
+
+Some PCL printers do not recognize image positioning commands. Output for
+these printers will not be centered on the page and header and trailer
+strings may not appear where expected.
+
+The \fB\-gamma\fP and \fB-render\fP options are supported only on
+the PaintJet XL printers.
+
+The \fB\-slide\fP option is not supported for LaserJet printers.
+
+The \fB\-split\fP option is not supported for HP printers.
+
+The \fB\-gray\fP option is not supported for HP or IBM printers.
+.br
+Copyright 1986, Marvin Solomon and the University of Wisconsin.
+.br
+Copyright 1988, Hewlett Packard Company.
+.br
+See \fIX(1)\fP for a full statement of rights and permissions.
+.SH AUTHORS
+Michael R. Gretzinger, MIT Project Athena,
+Jose Capo, MIT Project Athena (PP3812 support),
+Marvin Solomon, University of Wisconsin,
+Bob Scheifler, MIT, Angela Bock and E. Mike Durbin, Rich Inc. (grayscale),
+Larry Rupp, HP (HP printer support).