Annotation of researchv9/X11/src/X.V11R1/clients/xpr/xpr.c, revision 1.1.1.1

1.1       root        1: #include <X11/copyright.h>
                      2: 
                      3: /*
                      4:  * XPR - process xwd(1) files for the LN03 or LA100 printer
                      5:  *
                      6:  * Author: Michael R. Gretzinger, MIT Project Athena
                      7:  * Copyright (C) 1985, Massachusetts Institute of Technology
                      8:  *
                      9:  * Modified by Marvin Solomon, Univeristy of Wisconsin, to handle Apple
                     10:  * Laserwriter (PostScript) devices (-device ps).
                     11:  * Also accepts the -compact flag that produces more compact output
                     12:  * by using run-length encoding on white (1) pixels.
                     13:  * This version does not (yet) support the following options
                     14:  *   -append -dump -noff -nosixopt -split
                     15:  * 
                     16:  * Changes
                     17:  * Copyright 1986 by Marvin Solomon and the University of Wisconsin
                     18:  * 
                     19:  * Permission to use, copy, modify, and distribute this
                     20:  * software and its documentation for any purpose and without
                     21:  * fee is hereby granted, provided that the above copyright
                     22:  * notice appear in all copies and that both that copyright
                     23:  * notice and this permission notice appear in supporting
                     24:  * documentation, and that the names of Marvin Solomon and
                     25:  * the University of Wisconsin not be used in
                     26:  * advertising or publicity pertaining to distribution of the
                     27:  * software without specific, written prior permission.
                     28:  * Neither Marvin Solomon nor the University of Wisconsin
                     29:  * makes any representations about the suitability of
                     30:  * this software for any purpose.  It is provided "as is"
                     31:  * without express or implied warranty.
                     32:  * 
                     33:  */
                     34: 
                     35: #ifndef lint
                     36: static char *rcsid_xpr_c = "$Header: xpr.c,v 1.18 87/09/11 20:02:55 toddb Exp $";
                     37: #endif
                     38: 
                     39: #include <sys/types.h>
                     40: #include <sys/file.h>
                     41: #include <sys/uio.h>
                     42: #include <stdio.h>
                     43: #include <pwd.h>
                     44: #include "lncmd.h"
                     45: #include <X11/Xlib.h>
                     46: #include "X11/XWDFile.h"
                     47: 
                     48: int debug = 0;
                     49: 
                     50: enum device {LN01, LN03, LA100, PS};
                     51: enum orientation {PORTRAIT, LANDSCAPE};
                     52: 
                     53: #define W_MAX 2400
                     54: #define H_MAX 3150
                     55: #define W_MARGIN 75
                     56: #define H_MARGIN 37
                     57: #define W_PAGE 2550
                     58: #define H_PAGE 3225
                     59: 
                     60: #ifdef NOINLINE
                     61: #define min(x,y) (((x)<(y))?(x):(y))
                     62: #endif NOINLINE
                     63: 
                     64: #define F_PORTRAIT 1
                     65: #define F_LANDSCAPE 2
                     66: #define F_DUMP 4
                     67: #define F_NOSIXOPT 8
                     68: #define F_APPEND 16
                     69: #define F_NOFF 32
                     70: #define F_REPORT 64
                     71: #define F_COMPACT 128
                     72: 
                     73: char *infilename = "stdin";
                     74: 
                     75: main(argc, argv)
                     76: char **argv;
                     77: {
                     78:     unsigned long swaptest = 1;
                     79:     XWDFileHeader win;
                     80:     register unsigned char (*sixmap)[];
                     81:     register int i;
                     82:     register int iw;
                     83:     register int ih;
                     84:     register int sixel_count;
                     85:     char *w_name;
                     86:     char *filename;
                     87:     char *output_filename;
                     88:     int scale, width, height, flags, split;
                     89:     int left, top;
                     90:     int top_margin, left_margin;
                     91:     int hpad;
                     92:     char *header, *trailer;
                     93:     enum orientation orientation;
                     94:     enum device device;
                     95:     
                     96:     parse_args (argc, argv, &scale, &width, &height, &left, &top, &device, 
                     97:                &flags, &split, &header, &trailer);
                     98: 
                     99:     /* read in window header */
                    100:     read(0, &win, sizeof win);
                    101:     if (*(char *) &swaptest)
                    102:        _swaplong((char *) &win, sizeof(win));
                    103: 
                    104:     if (win.file_version != XWD_FILE_VERSION) {
                    105:        fprintf(stderr,"xpr: file format version missmatch.\n");
                    106:        exit(1);
                    107:     }
                    108:     if (win.header_size < sizeof(win)) {
                    109:        fprintf(stderr,"xpr: header size is too small.\n");
                    110:        exit(1);
                    111:     }
                    112: 
                    113:     if (win.pixmap_depth != 1 && win.pixmap_format != XYPixmap) {
                    114:         fprintf(stderr,"xpr: image is not in XY format");
                    115:        exit(1);
                    116:     }
                    117: 
                    118:     if (win.byte_order != win.bitmap_bit_order)
                    119:         fprintf(stderr,"xpr: image will be incorrect, byte swapping required but not performed.\n");
                    120: 
                    121:     w_name = (char *)malloc(win.header_size - sizeof win);
                    122:     read(0, w_name, win.header_size - sizeof win);
                    123:     
                    124:     if(win.ncolors)
                    125:        read(0,
                    126:             malloc(win.ncolors * sizeof(XColor)),
                    127:             win.ncolors * sizeof(XColor));
                    128: 
                    129:     /* calculate orientation and scale */
                    130:     setup_layout(device, win.pixmap_width, win.pixmap_height, flags, width, 
                    131:                 height, header, trailer, &scale, &orientation);
                    132: 
                    133:     if (device == PS) {
                    134:        iw = win.pixmap_width;
                    135:        ih = win.pixmap_height;
                    136:     } else {
                    137:        /* calculate w and h cell count */
                    138:        iw = win.pixmap_width;
                    139:        ih = (win.pixmap_height + 5) / 6;
                    140:        hpad = (ih * 6) - win.pixmap_height;
                    141: 
                    142:        /* build pixcells from input file */
                    143:        sixel_count = iw * ih;
                    144:        sixmap = (unsigned char (*)[])malloc(sixel_count);
                    145:        build_sixmap(iw, ih, sixmap, hpad, &win);
                    146:     }
                    147: 
                    148:     /* output commands and sixel graphics */
                    149:     if (device == LN03) {
                    150: /*     ln03_grind_fonts(sixmap, iw, ih, scale, &pixmap); */
                    151:        ln03_setup(iw, ih, orientation, scale, left, top,
                    152:                   &left_margin, &top_margin, flags, header, trailer);
                    153:        ln03_output_sixels(sixmap, iw, ih, (flags & F_NOSIXOPT), split, 
                    154:                           scale, top_margin, left_margin);
                    155:        ln03_finish();
                    156:     } else if (device == LA100) {
                    157:        la100_setup(iw, ih, scale);
                    158:        la100_output_sixels(sixmap, iw, ih, (flags & F_NOSIXOPT));
                    159:        la100_finish();
                    160:     } else if (device == PS) {
                    161:        ps_setup(iw, ih, orientation, scale, left, top,
                    162:                   flags, header, trailer, w_name);
                    163:        ps_output_bits(iw, ih, flags, orientation, &win);
                    164:        ps_finish();
                    165:     } else {
                    166:        fprintf(stderr, "xpr: device not supported\n");
                    167:     }
                    168:     
                    169:     /* print some statistics */
                    170:     if (flags & F_REPORT) {
                    171:        fprintf(stderr, "Name: %s\n", w_name);
                    172:        fprintf(stderr, "Width: %d, Height: %d\n", win.pixmap_width, 
                    173:                win.pixmap_height);
                    174:        fprintf(stderr, "Orientation: %s, Scale: %d\n", 
                    175:                (orientation==PORTRAIT) ? "Portrait" : "Landscape", scale);
                    176:     }
                    177:     if (device != PS && (flags & F_DUMP)) dump_sixmap(sixmap, iw, ih);
                    178: }
                    179: 
                    180: parse_args(argc, argv, scale, width, height, left, top, device, flags, 
                    181:           split, header, trailer)
                    182: register int argc;
                    183: register char **argv;
                    184: int *scale;
                    185: int *width;
                    186: int *height;
                    187: int *left;
                    188: int *top;
                    189: enum device *device;
                    190: int *flags;
                    191: int *split;
                    192: char **header;
                    193: char **trailer;
                    194: {
                    195:     register char *output_filename;
                    196:     register int f;
                    197:     register int len;
                    198:     register int pos;
                    199:     double atof();
                    200:     int atoi();
                    201: 
                    202:     output_filename = NULL;
                    203:     *device = LN03;    /* default */
                    204:     *flags = 0;
                    205:     *split = 1;
                    206:     *width = -1;
                    207:     *height = -1;
                    208:     *top = -1;
                    209:     *left = -1;
                    210:     *header = NULL;
                    211:     *trailer = NULL;
                    212:     
                    213:     argc--;
                    214:     argv++;
                    215: 
                    216:     while (argc > 0 && argv[0][0] == '-') {
                    217:        len = strlen(*argv);
                    218:        switch (argv[0][1]) {
                    219:        case 'a':               /* -append <filename> */
                    220:            if (!bcmp(*argv, "-append", len)) {
                    221:                argc--; argv++;
                    222:                output_filename = *argv;
                    223:                *flags |= F_APPEND;
                    224:            }
                    225:            break;
                    226: 
                    227:        case 'd':               /* -device {ln03 | la100 | ps | lw} | -dump */
                    228:            if (len <= 2) {
                    229:                fprintf(stderr, "xpr: ambiguous option: \"%s\"\n", *argv);
                    230:                exit(1);
                    231:            }
                    232:            if (!bcmp(*argv, "-device", len)) {
                    233:                argc--; argv++;
                    234:                len = strlen(*argv);
                    235:                if (!bcmp(*argv, "ln03", len)) {
                    236:                    *device = LN03;
                    237:                } else if (!bcmp(*argv, "la100", len)) {
                    238:                    *device = LA100;
                    239:                } else if (!bcmp(*argv, "ps", len)) {
                    240:                    *device = PS;
                    241:                } else if (!bcmp(*argv, "lw", len)) {
                    242:                    *device = PS;
                    243:                } else {
                    244:                    fprintf(stderr, 
                    245:                            "xpr: device \"%s\" not supported\n", *argv);
                    246:                    exit(1);
                    247:                }
                    248:            } else if (!bcmp(*argv, "-dump", len)) {
                    249:                *flags |= F_DUMP;
                    250:            }
                    251:            break;
                    252: 
                    253:        case 'h':               /* -height <inches> */
                    254:            if (len <= 3) {
                    255:                fprintf(stderr, "xpr: ambiguous option: \"%s\"\n", *argv);
                    256:                exit(1);
                    257:            }
                    258:            if (!bcmp(*argv, "-height", len)) {
                    259:                argc--; argv++;
                    260:                *height = (int)(300.0 * atof(*argv));
                    261:            } else if (!bcmp(*argv, "-header", len)) {
                    262:                argc--; argv++;
                    263:                *header = *argv;
                    264:            }
                    265:            break;
                    266: 
                    267:        case 'l':               /* -landscape | -left <inches> */
                    268:            if (!bcmp(*argv, "-landscape", len)) {
                    269:                *flags |= F_LANDSCAPE;
                    270:            } else if (!bcmp(*argv, "-left", len)) {
                    271:                argc--; argv++;
                    272:                *left = (int)(300.0 * atof(*argv));
                    273:            }
                    274:            break;
                    275: 
                    276:        case 'n':               /* -nosixopt | -noff */
                    277:            if (len <= 3) {
                    278:                fprintf(stderr, "xpr: ambiguous option: \"%s\"\n", *argv);
                    279:                exit(1);
                    280:            }
                    281:            if (!bcmp(*argv, "-nosixopt", len)) {
                    282:                *flags |= F_NOSIXOPT;
                    283:            } else if (!bcmp(*argv, "-noff", len)) {
                    284:                *flags |= F_NOFF;
                    285:            }
                    286:            break;
                    287: 
                    288:        case 'o':               /* -output <filename> */
                    289:            if (!bcmp(*argv, "-output", len)) {
                    290:                argc--; argv++;
                    291:                output_filename = *argv;
                    292:            }
                    293:            break;
                    294: 
                    295:        case 'p':               /* -portrait */
                    296:            if (!bcmp(*argv, "-portrait", len)) {
                    297:                *flags |= F_PORTRAIT;
                    298:            }
                    299:            break;
                    300: 
                    301:        case 'c':               /* -compact */
                    302:            if (!bcmp(*argv, "-compact", len)) {
                    303:                *flags |= F_COMPACT;
                    304:            }
                    305:            break;
                    306: 
                    307:        case 'r':               /* -report */
                    308:            if (!bcmp(*argv, "-report", len)) {
                    309:                *flags |= F_REPORT;
                    310:            }
                    311:            break;
                    312: 
                    313:        case 's':               /* -scale <scale> | -split <n-pages> */
                    314:            if (!bcmp(*argv, "-scale", len)) {
                    315:                argc--; argv++;
                    316:                *scale = atoi(*argv);
                    317:            } else if (!bcmp(*argv, "-split", len)) {
                    318:                argc--; argv++;
                    319:                *split = atoi(*argv);
                    320:            }
                    321:            break;
                    322: 
                    323:        case 't':               /* -top <inches> */
                    324:            if (len <= 2) {
                    325:                fprintf(stderr, "xpr: ambigous option: \"%s\"\n", *argv);
                    326:                exit(1);
                    327:            }
                    328:            if (!bcmp(*argv, "-top", len)) {
                    329:                argc--; argv++;
                    330:                *top = (int)(300.0 * atof(*argv));
                    331:            } else if (!bcmp(*argv, "-trailer", len)) {
                    332:                argc--; argv++;
                    333:                *trailer = *argv;
                    334:            }
                    335:            break;
                    336: 
                    337:        case 'w':               /* -width <inches> */
                    338:            if (!bcmp(*argv, "-width", len)) {
                    339:                argc--; argv++;
                    340:                *width = (int)(300.0 * atof(*argv));
                    341:            }
                    342:            break;
                    343: 
                    344:        }
                    345:        argc--; argv++;
                    346:     }
                    347: 
                    348:     if (argc > 0) {
                    349:        f = open(*argv, O_RDONLY, 0);
                    350:        if (f < 0) {
                    351:            fprintf(stderr, "xpr: error opening \"%s\" for input\n", *argv);
                    352:            perror("");
                    353:            exit(1);
                    354:        }
                    355:        dup2(f, 0);
                    356:        close(f);
                    357:        infilename = *argv;
                    358: /*     if (output_filename == NULL) {
                    359:            output_filename = (char *)malloc(strlen(*argv)+10);
                    360:            build_output_filename(*argv, *device, output_filename);
                    361:        } */
                    362:     }
                    363: 
                    364:     if (output_filename != NULL) {
                    365:        if (!(*flags & F_APPEND)) {
                    366:            f = open(output_filename, O_CREAT|O_WRONLY|O_TRUNC, 0664);
                    367:        } else {
                    368:            f = open(output_filename, O_WRONLY, 0);
                    369:        }
                    370:        if (f < 0) {
                    371:            fprintf(stderr, "xpr: error opening \"%s\" for output\n", 
                    372:                    output_filename);
                    373:            perror("xpr");
                    374:            exit(1);
                    375:        }
                    376:        if (*flags & F_APPEND) {
                    377:            pos = lseek(f, 0, 2);          /* get eof position */
                    378:            if (*flags & F_NOFF) pos -= 3; /* set position before trailing */
                    379:                                           /*     formfeed and reset */
                    380:            lseek(f, pos, 0);              /* set pointer */
                    381:        }
                    382:        dup2(f, 1);
                    383:        close(f);
                    384:     }
                    385: }
                    386: 
                    387: setup_layout(device, win_width, win_height, flags, width, height, 
                    388:             header, trailer, scale, orientation)
                    389: enum device device;
                    390: int win_width;
                    391: int win_height;
                    392: int flags;
                    393: int width;
                    394: int height;
                    395: char *header;
                    396: char *trailer;
                    397: int *scale;
                    398: enum orientation *orientation;
                    399: {
                    400:     register int w_scale;
                    401:     register int h_scale;
                    402:     register int iscale = *scale;
                    403:     register int w_max;
                    404:     register int h_max;
                    405: 
                    406:     if (header != NULL) win_height += 75;
                    407:     if (trailer != NULL) win_height += 75;
                    408: 
                    409:     /* check maximum width and height; set orientation and scale*/
                    410:     if (device == LN03 || device == PS) {
                    411:        if ((win_width < win_height || (flags & F_PORTRAIT)) && 
                    412:            !(flags & F_LANDSCAPE)) {
                    413:            *orientation = PORTRAIT;
                    414:            w_max = (width > 0)? width : W_MAX;
                    415:            h_max = (height > 0)? height : H_MAX;
                    416:            w_scale = w_max / win_width;
                    417:            h_scale = h_max / win_height;
                    418:            *scale = min(w_scale, h_scale);
                    419:        } else {
                    420:            *orientation = LANDSCAPE;
                    421:            w_max = (width > 0)? width : H_MAX;
                    422:            h_max = (height > 0)? height : W_MAX;
                    423:            w_scale = w_max / win_width;
                    424:            h_scale = h_max / win_height;
                    425:            *scale = min(w_scale, h_scale);
                    426:        }
                    427:     } else {                   /* device == LA100 */
                    428:        *orientation = PORTRAIT;
                    429:        *scale = W_MAX / win_width;
                    430:     }
                    431:     if (*scale == 0) *scale = 1;
                    432:     if (*scale > 6) *scale = 6;
                    433:     if (iscale > 0 && iscale < *scale) *scale = iscale;
                    434: }
                    435: 
                    436: dump_sixmap(sixmap, iw, ih)
                    437: register unsigned char (*sixmap)[];
                    438: int iw;
                    439: int ih;
                    440: {
                    441:     register int i, j;
                    442:     register unsigned char *c;
                    443: 
                    444:     c = (unsigned char *)sixmap;
                    445:     fprintf(stderr, "Sixmap:\n");
                    446:     for (i = 0; i < ih; i++) {
                    447:        for (j = 0; j < iw; j++) {
                    448:            fprintf(stderr, "%02X ", *c++);
                    449:        }
                    450:        fprintf(stderr, "\n\n");
                    451:     }
                    452: }
                    453: 
                    454: build_sixmap(iw, ih, sixmap, hpad, win)
                    455: int ih;
                    456: int iw;
                    457: unsigned char (*sixmap)[];
                    458: int hpad;
                    459: XWDFileHeader *win;
                    460: {
                    461:     int iwb = win->bytes_per_line;
                    462:     int iww;
                    463:     int rsize, cc;
                    464:     int w, maxw;
                    465:     struct iovec linevec[6];
                    466:     unsigned char line[6][500];
                    467:     register unsigned char *c;
                    468:     register int i, j, k, m;
                    469:     register int sixel;
                    470:     static int mask[] = {~1, ~2, ~4, ~8, ~16, ~32, ~64, ~128};
                    471: 
                    472:     c = (unsigned char *)sixmap;
                    473: 
                    474:     for (i = 0; i <= 5; i++) {
                    475:        linevec[i].iov_base = (caddr_t)line[i];
                    476:        linevec[i].iov_len = iwb;
                    477:     }
                    478: 
                    479:     while (--ih >= 0) {
                    480:        if (ih > 0 || hpad == 0) {
                    481:            rsize = iwb * 6;
                    482:            while (rsize > 0) {
                    483:                cc = readv(0, linevec, 6);
                    484:                if (cc == 0) break;
                    485:                rsize -= cc;
                    486:            }
                    487:        } else {
                    488:            i = 6 - hpad;
                    489:            rsize = iwb * i;
                    490:            while (rsize > 0) {
                    491:                cc = readv(0, linevec, i);
                    492:                if (cc == 0) break;
                    493:                rsize -= cc;
                    494:            }
                    495:            for (; i < 6; i++)
                    496:                for (j = 0; j < iwb; j++) line[i][j] = 0xFF;
                    497:        }
                    498: 
                    499:        if (win->bitmap_bit_order == MSBFirst)
                    500:            for (i = 0; i <= 5; i++)
                    501:                _swapbits((char *)&line[i][0], iwb);
                    502: 
                    503: #ifndef NOINLINE
                    504:        for (i = 0; i < iw; i++) {
                    505:            sixel =  extzv(line[0], i, 1);
                    506:            sixel |= extzv(line[1], i, 1) << 1;
                    507:            sixel |= extzv(line[2], i, 1) << 2;
                    508:            sixel |= extzv(line[3], i, 1) << 3;
                    509:            sixel |= extzv(line[4], i, 1) << 4;
                    510:            sixel |= extzv(line[5], i, 1) << 5;
                    511:            *c++ = sixel;
                    512:        }
                    513: #else
                    514:        for (i = 0, w = iw; w > 0; i++) {
                    515:            for (j = 0; j <= 7; j++) {
                    516:                m = mask[j];
                    517:                k = -j;
                    518:                sixel =  ((line[0][i] & ~m) << k++);
                    519:                sixel |= ((line[1][i] & ~m) << k++);
                    520:                sixel |= ((line[2][i] & ~m) << k++);
                    521:                sixel |= ((line[3][i] & ~m) << k++);
                    522:                sixel |= ((line[4][i] & ~m) << k++);
                    523:                sixel |= ((line[5][i] & ~m) << k);
                    524:                *c++ = sixel;
                    525:                if (--w == 0) break;
                    526:            }
                    527:        }
                    528: #endif
                    529:     }
                    530: }
                    531: 
                    532: build_output_filename(name, device, oname)
                    533: register char *name, *oname;
                    534: enum device device;
                    535: {
                    536:     while (*name && *name != '.') *oname++ = *name++;
                    537:     switch (device) {
                    538:     case LN03: bcopy(".ln03", oname, 6); break;
                    539:     case LA100:        bcopy(".la100", oname, 7); break;
                    540:     }
                    541: }
                    542: 
                    543: /*
                    544: ln03_grind_fonts(sixmap, iw, ih, scale, pixmap)
                    545: unsigned char (*sixmap)[];
                    546: int iw;
                    547: int ih;
                    548: int scale;
                    549: struct pixmap (**pixmap)[];
                    550: {
                    551: }
                    552: */
                    553: 
                    554: ln03_setup(iw, ih, orientation, scale, left, top, left_margin, top_margin, 
                    555:           flags, header, trailer)
                    556: int iw;
                    557: int ih;
                    558: enum orientation orientation;
                    559: int scale;
                    560: int left;
                    561: int top;
                    562: int *left_margin;
                    563: int *top_margin;
                    564: int flags;
                    565: char *header;
                    566: char *trailer;
                    567: {
                    568:     register int i;
                    569:     register int lm, tm, xm;
                    570:     char fontname[6];
                    571:     char buf[256];
                    572:     register char *bp = buf;
                    573:        
                    574:     if (!(flags & F_APPEND)) {
                    575:        sprintf(bp, LN_RIS); bp += 2;
                    576:        sprintf(bp, LN_SSU, 7); bp += 5;
                    577:        sprintf(bp, LN_PUM_SET); bp += sizeof LN_PUM_SET - 1;
                    578:     }
                    579: 
                    580:     if (orientation == PORTRAIT) {
                    581:        lm = (left > 0)? left : (((W_MAX - scale * iw) / 2) + W_MARGIN);
                    582:        tm = (top > 0)? top : (((H_MAX - scale * ih * 6) / 2) + H_MARGIN);
                    583:        sprintf(bp, LN_PFS, "?20"); bp += 7;
                    584:        sprintf(bp, LN_DECOPM_SET); bp += sizeof LN_DECOPM_SET - 1;
                    585:        sprintf(bp, LN_DECSLRM, lm, W_PAGE - lm); bp += strlen(bp);
                    586:     } else {
                    587:        lm = (left > 0)? left : (((H_MAX - scale * iw) / 2) + H_MARGIN);
                    588:        tm = (top > 0)? top : (((W_MAX - scale * ih * 6) / 2) + W_MARGIN);
                    589:        sprintf(bp, LN_PFS, "?21"); bp += 7;
                    590:        sprintf(bp, LN_DECOPM_SET); bp += sizeof LN_DECOPM_SET - 1;
                    591:        sprintf(bp, LN_DECSLRM, lm, H_PAGE - lm); bp += strlen(bp);
                    592:     }
                    593: 
                    594:     if (header != NULL) {
                    595:        sprintf(bp, LN_VPA, tm - 100); bp += strlen(bp);
                    596:        i = strlen(header);
                    597:        xm = (((scale * iw) - (i * 30)) / 2) + lm;
                    598:        sprintf(bp, LN_HPA, xm); bp += strlen(bp);
                    599:        sprintf(bp, LN_SGR, 3); bp += strlen(bp);
                    600:        bcopy(header, bp, i);
                    601:        bp += i;
                    602:     }
                    603:     if (trailer != NULL) {
                    604:        sprintf(bp, LN_VPA, tm + (scale * ih * 6) + 75); bp += strlen(bp);
                    605:        i = strlen(trailer);
                    606:        xm = (((scale * iw) - (i * 30)) / 2) + lm;
                    607:        sprintf(bp, LN_HPA, xm); bp += strlen(bp);
                    608:        sprintf(bp, LN_SGR, 3); bp += strlen(bp);
                    609:        bcopy(trailer, bp, i);
                    610:        bp += i;
                    611:     }
                    612: 
                    613:     sprintf(bp, LN_HPA, lm); bp += strlen(bp);
                    614:     sprintf(bp, LN_VPA, tm); bp += strlen(bp);
                    615:     sprintf(bp, LN_SIXEL_GRAPHICS, 9, 0, scale); bp += strlen(bp);
                    616:     sprintf(bp, "\"1;1"); bp += 4; /* Pixel aspect ratio */
                    617:     write(1, buf, bp-buf);
                    618:     *top_margin = tm;
                    619:     *left_margin = lm;
                    620: }
                    621: 
                    622: #define LN03_RESET "\033c"
                    623: 
                    624: ln03_finish()
                    625: {
                    626:     write(1, LN03_RESET, sizeof LN03_RESET - 1);
                    627: }
                    628: 
                    629: la100_setup(iw, ih, scale)
                    630: {
                    631:     unsigned char buf[256];
                    632:     register unsigned char *bp;
                    633:     int lm, tm;
                    634: 
                    635:     bp = buf;
                    636:     lm = ((80 - (int)((double)iw / 6.6)) / 2) - 1;
                    637:     if (lm < 1) lm = 1;
                    638:     tm = ((66 - (int)((double)ih / 2)) / 2) - 1;
                    639:     if (tm < 1) tm = 1;
                    640:     sprintf(bp, "\033[%d;%ds", lm, 81-lm); bp += strlen(bp);
                    641:     sprintf(bp, "\033[?7l"); bp += 5;
                    642:     sprintf(bp, "\033[%dd", tm); bp += strlen(bp);
                    643:     sprintf(bp, "\033[%d`", lm); bp += strlen(bp);
                    644:     sprintf(bp, "\033P0q"); bp += 4;
                    645:     write(1, buf, bp-buf);
                    646: }
                    647: 
                    648: #define LA100_RESET "\033[1;80s\033[?7h"
                    649: 
                    650: la100_finish()
                    651: {
                    652:     write(1, LA100_RESET, sizeof LA100_RESET - 1);
                    653: }
                    654: 
                    655: #define COMMENTVERSION "PS-Adobe-1.0"
                    656: 
                    657: #ifdef XPROLOG
                    658: /* for debugging, get the prolog from a file */
                    659: dump_prolog(flags) {
                    660:     char *fname=(flags & F_COMPACT) ? "prolog.compact" : "prolog";
                    661:     FILE *fi = fopen(fname,"r");
                    662:     char buf[1024];
                    663: 
                    664:     if (fi==NULL) {
                    665:        perror(fname);
                    666:        exit(1);
                    667:     }
                    668:     while (fgets(buf,1024,fi)) fputs(buf,stdout);
                    669:     fclose(fi);
                    670: }
                    671: 
                    672: #else XPROLOG
                    673: /* postscript "programs" to unpack and print the bitmaps being sent */
                    674: 
                    675: char *ps_prolog_compact[] = {
                    676:     "%%Pages: 1",
                    677:     "%%EndProlog",
                    678:     "%%Page: 1 1",
                    679:     "",
                    680:     "/bitgen",
                    681:     "  {",
                    682:     "          /nextpos 0 def",
                    683:     "          currentfile bufspace readhexstring pop % get a chunk of input",
                    684:     "          % interpret each byte of the input",
                    685:     "          {",
                    686:     "                  flag { % if the previous byte was FF",
                    687:     "                          /len exch def % this byte is a count",
                    688:     "                          result",
                    689:     "                          nextpos",
                    690:     "                          FFstring 0 len getinterval % grap a chunk of FF's",
                    691:     "                                  putinterval % and stuff them into the result",
                    692:     "                          /nextpos nextpos len add def",
                    693:     "                          /flag false def",
                    694:     "                  }{ % otherwise",
                    695:     "                          dup 255 eq { % if this byte is FF",
                    696:     "                                  /flag true def % just set the flag",
                    697:     "                                  pop % and toss the FF",
                    698:     "                          }{ % otherwise",
                    699:     "                                  % move this byte to the result",
                    700:     "                                  result nextpos",
                    701:     "                                          3 -1 roll % roll the current byte back to the top",
                    702:     "                                          put",
                    703:     "                                  /nextpos nextpos 1 add def",
                    704:     "                          } ifelse",
                    705:     "                  } ifelse",
                    706:     "          } forall",
                    707:     "          % trim unused space from end of result",
                    708:     "          result 0 nextpos getinterval",
                    709:     "  } def",
                    710:     "",
                    711:     "",
                    712:     "/bitdump % stk: width, height, iscale",
                    713:     "  % dump a bit image with lower left corner at current origin,",
                    714:     "  % scaling by iscale (iscale=1 means 1/300 inch per pixel)",
                    715:     "  {",
                    716:     "          % read arguments",
                    717:     "          /iscale exch def",
                    718:     "          /height exch def",
                    719:     "          /width exch def",
                    720:     "",
                    721:     "          % scale appropriately",
                    722:     "          width iscale mul height iscale mul scale",
                    723:     "",
                    724:     "          % data structures:",
                    725:     "",
                    726:     "          % allocate space for one line of input",
                    727:     "          /bufspace 36 string def",
                    728:     "",
                    729:     "          % string of FF's",
                    730:     "          /FFstring 256 string def",
                    731:     "          % for all i FFstring[i]=255",
                    732:     "          0 1 255 { FFstring exch 255 put } for",
                    733:     "",
                    734:     "          % 'escape' flag",
                    735:     "          /flag false def",
                    736:     "",
                    737:     "          % space for a chunk of generated bits",
                    738:     "          /result 1000 string def",
                    739:     "",
                    740:     "          % read and dump the image",
                    741:     "          width height 1 [width 0 0 height neg 0 height]",
                    742:     "                  { bitgen }",
                    743:     "                  image",
                    744:     "  } def",
                    745:     0
                    746: };
                    747: 
                    748: char *ps_prolog[] = {
                    749:     "%%Pages: 1",
                    750:     "%%EndProlog",
                    751:     "%%Page: 1 1",
                    752:     "",
                    753:     "/bitdump % stk: width, height, iscale",
                    754:     "% dump a bit image with lower left corner at current origin,",
                    755:     "% scaling by iscale (iscale=1 means 1/300 inch per pixel)",
                    756:     "{",
                    757:     "  % read arguments",
                    758:     "  /iscale exch def",
                    759:     "  /height exch def",
                    760:     "  /width exch def",
                    761:     "",
                    762:     "  % scale appropriately",
                    763:     "  width iscale mul height iscale mul scale",
                    764:     "",
                    765:     "  % allocate space for one scanline of input",
                    766:     "  /picstr % picstr holds one scan line",
                    767:     "          width 7 add 8 idiv % width of image in bytes = ceiling(width/8)",
                    768:     "          string",
                    769:     "          def",
                    770:     "",
                    771:     "  % read and dump the image",
                    772:     "  width height 1 [width 0 0 height neg 0 height]",
                    773:     "  { currentfile picstr readhexstring pop }",
                    774:     "  image",
                    775:     "} def",
                    776:     0
                    777: };
                    778: 
                    779: dump_prolog(flags) {
                    780:     char **p = (flags & F_COMPACT) ? ps_prolog_compact : ps_prolog;
                    781:     while (*p) printf("%s\n",*p++);
                    782: }
                    783: #endif XPROLOG
                    784: 
                    785: #define PAPER_WIDTH 85*30 /* 8.5 inches */
                    786: #define PAPER_LENGTH 11*300 /* 11 inches */
                    787: 
                    788: static int
                    789: points(n)
                    790: {
                    791:     /* scale n from pixels (1/300 inch) to points (1/72 inch) */
                    792:     n *= 72;
                    793:     return n/300;
                    794: }
                    795: 
                    796: static char *
                    797: escape(s)
                    798: char *s;
                    799: {
                    800:     /* make a version of s in which control characters are deleted and
                    801:      * special characters are escaped.
                    802:      */
                    803:     static char buf[200];
                    804:     char *p = buf;
                    805: 
                    806:     for (;*s;s++) {
                    807:        if (*s < ' ' || *s > 0176) continue;
                    808:        if (*s==')' || *s=='(' || *s == '\\') {
                    809:            sprintf(p,"\\%03o",*s);
                    810:            p += 4;
                    811:        }
                    812:        else *p++ = *s;
                    813:     }
                    814:     *p = 0;
                    815:     return buf;
                    816: }
                    817: 
                    818: /* ARGSUSED */
                    819: ps_setup(iw, ih, orientation, scale, left, top, 
                    820:           flags, header, trailer, name)
                    821: int iw;
                    822: int ih;
                    823: enum orientation orientation;
                    824: int scale;
                    825: int left;
                    826: int top;
                    827: int flags;
                    828: char *header;
                    829: char *trailer;
                    830: char *name;
                    831: {
                    832:     char    hostname[256];
                    833:     struct passwd  *pswd;
                    834:     long    clock;
                    835:     int lm, bm; /* left (bottom) margin (paper in portrait orientation) */
                    836: 
                    837:     printf ("%%!%s\n", COMMENTVERSION);
                    838:     pswd = getpwuid (getuid ());
                    839:     (void) gethostname (hostname, sizeof hostname);
                    840:     printf ("%%%%Creator: %s:%s (%s)\n", hostname,
                    841:            pswd->pw_name, pswd->pw_gecos);
                    842:     printf ("%%%%Title: %s (%s)\n", infilename,name);
                    843:     printf ("%%%%CreationDate: %s",
                    844:                (time (&clock), ctime (&clock)));
                    845:     printf ("%%%%EndComments\n");
                    846: 
                    847:     dump_prolog(flags);
                    848: 
                    849:     if (orientation==PORTRAIT) {
                    850:        lm = (left > 0)? left : ((PAPER_WIDTH - scale * iw) / 2);
                    851:        bm = (top > 0)? (PAPER_LENGTH - top - scale * ih)
                    852:                : ((PAPER_LENGTH - scale * ih) / 2);
                    853:        if (header || trailer) {
                    854:            printf("gsave\n");
                    855:            printf("/Times-Roman findfont 15 scalefont setfont\n");
                    856:            /* origin at bottom left corner of image */
                    857:            printf("%d %d translate\n",points(lm),points(bm));
                    858:            if (header) {
                    859:                char *label = escape(header);
                    860:                printf("%d (%s) stringwidth pop sub 2 div %d moveto\n",
                    861:                    points(iw*scale), label, points(ih*scale) + 10);
                    862:                printf("(%s) show\n",label);
                    863:            }
                    864:            if (trailer) {
                    865:                char *label = escape(trailer);
                    866:                printf("%d (%s) stringwidth pop sub 2 div -20 moveto\n",
                    867:                    points(iw*scale), label);
                    868:                printf("(%s) show\n",label);
                    869:            }
                    870:            printf("grestore\n");
                    871:        }
                    872:        /* set resolution to device units (300/inch) */
                    873:        printf("72 300 div dup scale\n");
                    874:        /* move to lower left corner of image */
                    875:        printf("%d %d translate\n",lm,bm);
                    876:        /* dump the bitmap */
                    877:        printf("%d %d %d bitdump\n",iw,ih,scale);
                    878:     } else { /* orientation == LANDSCAPE */
                    879:        /* calculate margins */
                    880:        lm = (top > 0)? (PAPER_WIDTH - top - scale * ih)
                    881:                : ((PAPER_WIDTH - scale * ih) / 2);
                    882:        bm = (left > 0)? (PAPER_LENGTH - left - scale * iw)
                    883:                : ((PAPER_LENGTH - scale * iw) / 2);
                    884: 
                    885:        if (header || trailer) {
                    886:            printf("gsave\n");
                    887:            printf("/Times-Roman findfont 15 scalefont setfont\n");
                    888:            /* origin at top left corner of image */
                    889:            printf("%d %d translate\n",points(lm),points(bm + scale * iw));
                    890:            /* rotate to print the titles */
                    891:            printf("-90 rotate\n");
                    892:            if (header) {
                    893:                char *label = escape(header);
                    894:                printf("%d (%s) stringwidth pop sub 2 div %d moveto\n",
                    895:                    points(iw*scale), label, points(ih*scale) + 10);
                    896:                printf("(%s) show\n",label);
                    897:            }
                    898:            if (trailer) {
                    899:                char *label = escape(trailer);
                    900:                printf("%d (%s) stringwidth pop sub 2 div -20 moveto\n",
                    901:                    points(iw*scale), label);
                    902:                printf("(%s) show\n",label);
                    903:            }
                    904:            printf("grestore\n");
                    905:        }
                    906:        /* set resolution to device units (300/inch) */
                    907:        printf("72 300 div dup scale\n");
                    908:        /* move to lower left corner of image */
                    909:        printf("%d %d translate\n",lm,bm);
                    910:        /* dump the bitmap */
                    911:        printf("%d %d %d bitdump\n",ih,iw,scale);
                    912:     }
                    913: }
                    914: 
                    915: char *ps_epilog[] = {
                    916:        "",
                    917:        "showpage",
                    918:        "%%Trailer",
                    919:        0
                    920: };
                    921: 
                    922: ps_finish()
                    923: {
                    924:        char **p = ps_epilog;
                    925: 
                    926:        while (*p) printf("%s\n",*p++);
                    927: }
                    928: 
                    929: ln03_alter_background(sixmap, iw, ih)
                    930: unsigned char (*sixmap)[];
                    931: int iw;
                    932: int ih;
                    933: {
                    934:     register int size;
                    935:     register unsigned char *c, *stopc;
                    936:     register unsigned char *startc;
                    937:     register int n;
                    938: 
                    939:     c = (unsigned char *)sixmap;
                    940:     stopc = c + (iw * ih);
                    941:     n = 0;
                    942:     while (c < stopc) {
                    943:        switch (*c) {
                    944:        case 0x08: case 0x11: case 0x04: case 0x22:
                    945:        case 0x20: case 0x21: case 0x24: case 0x00:
                    946:            if (n == 0) startc = c;
                    947:            n++;
                    948:            break;
                    949: 
                    950:        default:
                    951:            if (n >= 2) {
                    952:                while (n-- > 0) *startc++ = 0x00;
                    953:            } else {
                    954:                n = 0;
                    955:            }
                    956:            break;
                    957:        }
                    958:        c++;
                    959:     }
                    960: }
                    961: 
                    962: ln03_output_sixels(sixmap, iw, ih, nosixopt, split, scale, top_margin, 
                    963:                   left_margin)
                    964: unsigned char (*sixmap)[];
                    965: int iw;
                    966: int ih;
                    967: int nosixopt;
                    968: int split;
                    969: int top_margin;
                    970: int left_margin;
                    971: {
                    972:     unsigned char *buf;
                    973:     register unsigned char *bp;
                    974:     int i;
                    975:     int j;
                    976:     register int k;
                    977:     register unsigned char *c;
                    978:     register int lastc;
                    979:     register int count;
                    980:     char snum[6];
                    981:     register char *snp;
                    982: 
                    983:     bp = (unsigned char *)malloc(iw*ih+512);
                    984:     buf = bp;
                    985:     count = 0;
                    986:     lastc = -1;
                    987:     c = (unsigned char *)sixmap;
                    988:     split = ih / split;                /* number of lines per page */
                    989: 
                    990:     iw--;                      /* optimization */
                    991:     for (i = 0; i < ih; i++) {
                    992:        for (j = 0; j <= iw; j++) {
                    993:            if (!nosixopt) {
                    994:                if (*c == lastc && j < iw) {
                    995:                    count++;
                    996:                    c++;
                    997:                    continue;
                    998:                }
                    999:                if (count >= 3) {
                   1000:                    bp--;
                   1001:                    count++;
                   1002:                    *bp++ = '!';
                   1003:                    snp = snum;
                   1004:                    while (count > 0) {
                   1005:                        k = count / 10;
                   1006:                        *snp++ = count - (k * 10) + '0';
                   1007:                        count = k;
                   1008:                    }
                   1009:                    while (--snp >= snum) *bp++ = *snp;
                   1010:                    *bp++ = (~lastc & 0x3F) + 0x3F;
                   1011:                } else if (count > 0) {
                   1012:                    lastc = (~lastc & 0x3F) + 0x3F;
                   1013:                    do {
                   1014:                        *bp++ = lastc;
                   1015:                    } while (--count > 0);
                   1016:                }
                   1017:            }
                   1018:            lastc = *c++;
                   1019:            *bp++ = (~lastc & 0x3F) + 0x3F;
                   1020:        }
                   1021:        *bp++ = '-';            /* New line */
                   1022:        lastc = -1;
                   1023:        if ((i % split) == 0 && i != 0) {
                   1024:            sprintf(bp, LN_ST); bp += sizeof LN_ST - 1;
                   1025:            *bp++ = '\f';
                   1026:            sprintf(bp, LN_VPA, top_margin + (i * 6 * scale)); bp += strlen(bp);
                   1027:            sprintf(bp, LN_HPA, left_margin); bp += strlen(bp);
                   1028:            sprintf(bp, LN_SIXEL_GRAPHICS, 9, 0, scale); bp += strlen(bp);
                   1029:            sprintf(bp, "\"1;1"); bp += 4;
                   1030:        }
                   1031:     }
                   1032: 
                   1033:     sprintf(bp, LN_ST); bp += sizeof LN_ST - 1;
                   1034:     *bp++ = '\f';
                   1035:     write(1, buf, bp-buf);
                   1036: }
                   1037: 
                   1038: la100_output_sixels(sixmap, iw, ih)
                   1039: unsigned char (*sixmap)[];
                   1040: int iw;
                   1041: int ih;
                   1042: {
                   1043:     unsigned char *buf;
                   1044:     register unsigned char *bp;
                   1045:     int i;
                   1046:     register int j, k;
                   1047:     register unsigned char *c;
                   1048:     register int lastc;
                   1049:     register int count;
                   1050:     char snum[6];
                   1051: 
                   1052:     bp = (unsigned char *)malloc(iw*ih+512);
                   1053:     buf = bp;
                   1054:     count = 0;
                   1055:     lastc = -1;
                   1056:     c = (unsigned char *)sixmap;
                   1057: 
                   1058:     for (i = 0; i < ih; i++) {
                   1059:        for (j = 0; j < iw; j++) {
                   1060:            if (*c == lastc && (j+1) < iw) {
                   1061:                count++;
                   1062:                c++;
                   1063:                continue;
                   1064:            }
                   1065:            if (count >= 2) {
                   1066:                bp -= 2;
                   1067:                count = 2 * (count + 1);
                   1068:                *bp++ = '!';
                   1069:                k = 0;
                   1070:                while (count > 0) {
                   1071:                    snum[k++] = (count % 10) + '0';
                   1072:                    count /= 10;
                   1073:                }
                   1074:                while (--k >= 0) *bp++ = snum[k];
                   1075:                *bp++ = (~lastc & 0x3F) + 0x3F;
                   1076:                count = 0;
                   1077:            } else if (count > 0) {
                   1078:                lastc = (~lastc & 0x3F) + 0x3F;
                   1079:                do {
                   1080:                    *bp++ = lastc;
                   1081:                    *bp++ = lastc;
                   1082:                } while (--count > 0);
                   1083:            }
                   1084:            lastc = (~*c & 0x3F) + 0x3F;
                   1085:            *bp++ = lastc;
                   1086:            *bp++ = lastc;
                   1087:            lastc = *c++;
                   1088:        }
                   1089:        *bp++ = '-';            /* New line */
                   1090:        lastc = -1;
                   1091:     }
                   1092: 
                   1093:     sprintf(bp, LN_ST); bp += sizeof LN_ST - 1;
                   1094:     *bp++ = '\f';
                   1095:     write(1, buf, bp-buf);
                   1096: }
                   1097: 
                   1098: #define LINELEN 72 /* number of CHARS (bytes*2) per line of bitmap output */
                   1099: char *obuf; /* buffer to contain entire rotated bit map */
                   1100: 
                   1101: ps_output_bits(iw, ih, flags, orientation, win)
                   1102: int iw;
                   1103: int ih;
                   1104: int flags;
                   1105: XWDFileHeader *win;
                   1106: enum orientation orientation;
                   1107: {
                   1108:     int iwb = win->bytes_per_line;
                   1109:     register int i;
                   1110:     int n,bytes;
                   1111:     unsigned char *buffer;
                   1112:     register int ocount=0;
                   1113:     extern char hex1[],hex2[];
                   1114:     static char hex[] = "0123456789abcdef";
                   1115: 
                   1116:     buffer = (unsigned char *)malloc((unsigned)(iwb + 3));
                   1117:     if (orientation == LANDSCAPE) {
                   1118:        /* read in and rotate the entire image */
                   1119:        /* The Postscript language has a rotate operator, but using it
                   1120:         * seem to make printing (at least on the Apple Laserwriter
                   1121:         * take about 10 times as long (40 minutes for a 1024x864 full-screen
                   1122:         * dump)!  Therefore, we rotate the image here.
                   1123:         */
                   1124:        int ocol = ih;
                   1125:        int owidth = (ih+31)/32; /* width of rotated image, in bytes */
                   1126:        int oheight = (iw+31)/32; /* height of rotated image, in scanlines */
                   1127:        register char *p, *q;
                   1128:        owidth *= 4;
                   1129:        oheight *= 32;
                   1130: 
                   1131:        /* Allocate buffer for the entire rotated image (output).
                   1132:         * Owidth and Oheight are rounded up to a multiple of 32 bits,
                   1133:         * to avoid special cases at the boundaries
                   1134:         */
                   1135:        obuf = (char *)malloc((unsigned)(owidth*oheight));
                   1136:        if (obuf==0) {
                   1137:            fprintf(stderr,"xpr: cannot allocate %d bytes\n",owidth*oheight);
                   1138:            exit(1);
                   1139:        }
                   1140:        bzero(obuf,owidth*oheight);
                   1141: 
                   1142:        for (i=0;i<ih;i++) {
                   1143:            n = read(0,(char *)buffer,iwb);
                   1144:            if (n<0) {
                   1145:                perror("read");
                   1146:                exit(1);
                   1147:            }
                   1148:            if (n==0) {
                   1149:                fprintf(stderr,"xpr: premature end of file\n");
                   1150:                exit(1);
                   1151:            }
                   1152:            if (win->bitmap_bit_order == MSBFirst)
                   1153:                _swapbits((char *)buffer, iwb);
                   1154:            ps_bitrot(buffer,iw,--ocol,owidth);
                   1155:        }
                   1156:        q = &obuf[iw*owidth];
                   1157:        bytes = (ih+7)/8;
                   1158:        for (p=obuf;p<q;p+=owidth)
                   1159:            ocount = ps_putbuf((unsigned char *)p,bytes,ocount,flags&F_COMPACT);
                   1160:     }
                   1161:     else {
                   1162:        for (i=0;i<ih;i++) {
                   1163:            n = read(0,(char *)buffer,iwb);
                   1164:            if (n<0) {
                   1165:                perror("read");
                   1166:                exit(1);
                   1167:            }
                   1168:            if (n==0) {
                   1169:                fprintf(stderr,"xpr: premature end of file\n");
                   1170:                exit(1);
                   1171:            }
                   1172:            if (win->bitmap_bit_order == MSBFirst)
                   1173:                _swapbits((char *)buffer, iwb);
                   1174:            ocount = ps_putbuf(buffer,iwb,ocount,flags&F_COMPACT);
                   1175:        }
                   1176:     }
                   1177:     if (flags & F_COMPACT) {
                   1178:        if (ocount) {
                   1179:            /* pad to an integral number of lines */
                   1180:            while (ocount++ < LINELEN)
                   1181:                /* for debugging, pad with a "random" value */
                   1182:                putchar(hex[ocount&15]);
                   1183:            putchar('\n');
                   1184:        }
                   1185:     }
                   1186: }
                   1187: 
                   1188: /* Dump some bytes in hex, with bits in each byte reversed
                   1189:  * Ocount is number of chacters that have been written to the current
                   1190:  * output line.  It's new value is returned as the result of the function.
                   1191:  * Ocount is ignored (and the return value is meaningless) if compact==0.
                   1192:  */
                   1193: int
                   1194: ps_putbuf(s, n, ocount, compact)
                   1195: register unsigned char *s;     /* buffer to dump */
                   1196: register int n;                        /* number of BITS to dump */
                   1197: register int ocount;           /* position on output line for next char */
                   1198: int compact;                   /* if non-zero, do compaction (see below) */
                   1199: {
                   1200:     register int ffcount = 0;
                   1201:     extern char hex1[],hex2[];
                   1202:     static char hex[] = "0123456789abcdef";
                   1203: #define PUT(c) { putchar(c); if (++ocount>=LINELEN) \
                   1204:        { putchar('\n'); ocount=0; }}
                   1205: 
                   1206:     if (compact) {
                   1207:        /* The following loop puts out the bits of the image in hex,
                   1208:         * compressing runs of white space (represented by one bits)
                   1209:         * according the the following simple algorithm:  A run of n
                   1210:         * 'ff' bytes (i.e., bytes with value 255--all ones), where
                   1211:         * 1<=n<=255, is represented by a single 'ff' byte followed by a
                   1212:         * byte containing n.
                   1213:         * On a typical dump of a full screen pretty much covered by
                   1214:         * black-on-white text windows, this compression decreased the
                   1215:         * size of the file from 223 Kbytes to 63 Kbytes.
                   1216:         * Of course, another factor of two could be saved by sending
                   1217:         * the bytes 'as is' rather than in hex, using some sort of
                   1218:         * escape convention to avoid problems with control characters.
                   1219:         * Another popular encoding is to pack three bytes into 4 'sixels'
                   1220:         * as in the LN03, etc, but I'm too lazy to write the necessary
                   1221:         * PostScript code to unpack fancier representations.
                   1222:         */
                   1223:        while (n--) {
                   1224:            if (*s == 0xff) {
                   1225:                if (++ffcount == 255) {
                   1226:                    PUT('f'); PUT('f');
                   1227:                    PUT('f'); PUT('f');
                   1228:                    ffcount = 0;
                   1229:                }
                   1230:            }
                   1231:            else {
                   1232:                if (ffcount) {
                   1233:                    PUT('f'); PUT('f');
                   1234:                    PUT(hex[ffcount >> 4]);
                   1235:                    PUT(hex[ffcount & 0xf]);
                   1236:                    ffcount = 0;
                   1237:                }
                   1238:                PUT(hex1[*s]);
                   1239:                PUT(hex2[*s]);
                   1240:            }
                   1241:            s++;
                   1242:        }
                   1243:        if (ffcount) {
                   1244:            PUT('f'); PUT('f');
                   1245:                PUT(hex[ffcount >> 4]);
                   1246:            PUT(hex[ffcount & 0xf]);
                   1247:            ffcount = 0;
                   1248:        }
                   1249:     }
                   1250:     else { /* no compaction: just dump the image in hex (bits reversed) */
                   1251:        while (n--) {
                   1252:            putchar(hex1[*s]);
                   1253:            putchar(hex2[*s++]);
                   1254:        }
                   1255:        putchar('\n');
                   1256:     }
                   1257:     return ocount;
                   1258: }
                   1259: 
                   1260: ps_bitrot(s,n,col,owidth)
                   1261: unsigned char *s;
                   1262: register int n;
                   1263: int col;
                   1264: register int owidth;
                   1265: /* s points to a chunk of memory and n is its width in bits.
                   1266:  * The algorithm is, roughly,
                   1267:  *    for (i=0;i<n;i++) {
                   1268:  *        OR the ith bit of s into the ith row of the
                   1269:  *        (col)th column of obuf
                   1270:  *    }
                   1271:  * Assume VAX bit and byte ordering for s:
                   1272:  *     The ith bit of s is s[j]&(1<<k) where i=8*j+k.
                   1273:  *     It can also be retrieved as t[j]&(1<<k), where t=(int*)s and i=32*j+k.
                   1274:  * Also assume VAX bit and byte ordering for each row of obuf.
                   1275:  * Ps_putbuf() takes care of converting to Motorola 68000 byte and bit
                   1276:  * ordering.  The following code is very carefully tuned to yield a very
                   1277:  * tight loop on the VAX, since it easily dominates the entire running
                   1278:  * time of this program.  In particular, iwordp is declared last, since
                   1279:  * there aren't enough registers, and iwordp is referenced only once
                   1280:  * every 32 times through the loop.
                   1281:  */
                   1282: {
                   1283:     register int mask = 1<<(col%32);
                   1284:     register int iword; /* current input word (*iwordp) */
                   1285:     register int b = 0; /* number of bits in iword left to examine */
                   1286:     register char *opos = obuf + (col/32)*4;
                   1287:        /* pointer to word of obuf to receive next output bit */
                   1288:     register int *iwordp = (int *) s; /* pointer to next word of s */
                   1289: 
                   1290:     while (--n>=0) {
                   1291:        if (--b < 0) {
                   1292:            iword = *iwordp++;
                   1293:            b = 31;
                   1294:        }
                   1295:        if (iword & 1) {
                   1296:            *(int *)opos |= mask;
                   1297:        }
                   1298:        opos += owidth;
                   1299:        iword >>= 1;
                   1300:     }
                   1301: }
                   1302: 
                   1303: /* mapping tables to map a byte in to the hex representation of its
                   1304:  * bit-reversal
                   1305:  */
                   1306: char hex1[]="084c2a6e195d3b7f084c2a6e195d3b7f084c2a6e195d3b7f084c2a6e195d3b7f\
                   1307: 084c2a6e195d3b7f084c2a6e195d3b7f084c2a6e195d3b7f084c2a6e195d3b7f\
                   1308: 084c2a6e195d3b7f084c2a6e195d3b7f084c2a6e195d3b7f084c2a6e195d3b7f\
                   1309: 084c2a6e195d3b7f084c2a6e195d3b7f084c2a6e195d3b7f084c2a6e195d3b7f";
                   1310: 
                   1311: char hex2[]="000000000000000088888888888888884444444444444444cccccccccccccccc\
                   1312: 2222222222222222aaaaaaaaaaaaaaaa6666666666666666eeeeeeeeeeeeeeee\
                   1313: 111111111111111199999999999999995555555555555555dddddddddddddddd\
                   1314: 3333333333333333bbbbbbbbbbbbbbbb7777777777777777ffffffffffffffff";
                   1315: 

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.