Return to BSD News archive
Path: sserve!newshost.anu.edu.au!munnari.oz.au!constellation!convex!news.oc.com!news.kei.com!eff!news.umbc.edu!haven.umd.edu!ames!pacbell.com!toad.com!curt From: curt@mofo.toad.com (Curt mayer) Newsgroups: comp.os.386bsd.questions Subject: Re: Filter file for HP Deskjet/LaserJet Message-ID: <45129@toad.com> Date: 12 Feb 94 23:30:25 GMT References: <CKwK9K.3I8@cpccspc.cphk.hk> Sender: news@toad.com Distribution: world Organization: Nebula Consultants in San Francisco Lines: 1574 Nntp-Posting-Host: mofo.toad.com here's what I use: # This is a shell archive. Save it in a file, remove anything before # this line, and then unpack it by entering "sh file". Note, it may # create directories; files and directories will be owned by you and # have default permissions. # # This archive contains: # # hp # hp/README # hp/printcap # hp/print # hp/print/Makefile # hp/print/README # hp/print/print.1 # hp/print/print.c # hp/filters # hp/filters/Makefile # hp/filters/hpf # hp/filters/hpf/Makefile # hp/filters/hpf/README # hp/filters/hpf/hpf.c # hp/filters/hprast # hp/filters/hprast/Makefile # hp/filters/hprast/hprast.c # echo c - hp mkdir hp > /dev/null 2>&1 echo x - hp/README sed 's/^X//' >hp/README << 'END-of-hp/README' Xthis package is what I use to make my laserjet clone go. Xit consists of 3 components: X Xa printcap file that should be installed in /etc/printcap X it defines 3 printers: X one laserjet, and 2 different postscript emulations using X ghostscript. X X2 print filters, X one for sun rasterfiles that you can get at via lpr -v, X and one for everything else X Xa 2-up print program that emulates enscript a bit. END-of-hp/README echo x - hp/printcap sed 's/^X//' >hp/printcap << 'END-of-hp/printcap' X# X# hp laserjet and clone printcap X# X X# X# for laserjet 2 and bad laserjet 3 clones. X# Xps0|crippled postscript emulation:\ X :lp=/dev/lpa0:sd=/var/spool/lpd:lf=/var/log/lpd-errs:\ X :if=/usr/libexec/lpr/ps2lj:sh:mx#0:sf: X X# X# for laserjet 3 and good laserjet 3 clones. X# Xps|postscript emulation:\ X :lp=/dev/lpa0:sd=/var/spool/lpd:lf=/var/log/lpd-errs:\ X :if=/usr/libexec/lpr/ps2lj3:sh:mx#0:sf: X X# X# for native stuff, plus sun rasterfiles via lpr -v X# Xlp|epson|lj|local line printer:\ X :lp=/dev/lpa0:sd=/var/spool/lpd:lf=/var/log/lpd-errs:\ X :vf=/usr/libexec/lpr/hprast:\ X :if=/usr/libexec/lpr/hpf:\ X :df=/usr/local/bin/dvi2lj:\ X :sh:mx#0:pw#80: END-of-hp/printcap echo c - hp/print mkdir hp/print > /dev/null 2>&1 echo x - hp/print/Makefile sed 's/^X//' >hp/print/Makefile << 'END-of-hp/print/Makefile' XPROG= print X X.include <bsd.prog.mk> END-of-hp/print/Makefile echo x - hp/print/README sed 's/^X//' >hp/print/README << 'END-of-hp/print/README' Xthis directory contains a PCL4 + PCL5 print formatter that prints 2 up. Xit has been tested on FreeBSD and NetBSD Xit is free software. Xall rites reversed. Xjust don't claim you wrote it. END-of-hp/print/README echo x - hp/print/print.1 sed 's/^X//' >hp/print/print.1 << 'END-of-hp/print/print.1' X.\" X.Dd November 18, 1993 X.Dt PRINT 1 X.Os X.Sh NAME X.Nm print X.Nd queue text files to PCL4 printer. X.Sh SYNOPSIS X.Nm print X.Op Fl s X.Op Fl l X.Op Fl t Ar tabwidth X.Op Fl p Ar printer_name X.Op Ar text_file ... X.Sh DESCRIPTION X.Nm Print Xprints files 2 pages side by side on 1 piece of paper on PCL4 printer. XIf no files are specified, it reads stdin. X.Nm Print Xusually does the right thing with nroff output. It fakes boldface rather well. X.Pp XOptions: X.Bl -tag -width Ds X.It Fl s XSpecify graphically simple output, without the gaudy borders. X.It Fl l XSpecify formatting for 60 lines per page, instead of the default 66. X.It Fl t XSpecify the tab width. The default of 4 may irritate purists. X.It Fl p XSpecify the printer to spool to. The default printer is named X.Em lj. X.Sh ENVIRONMENT XIf the following environment variables exist, they are used by X.Nm print: X.Bl -tag -width PAGELENGTH X.It Ev PRINTER XSpecifies an alternate printer. X.It Ev TABWIDTH XSpecifies the tab stop width. X.It Ev PAGELENGTH XSpecifies the page length. it may take the value of 60 or 66. X.Sh AUTHOR Xcurt@toad.com X.Sh BUGS XThere is no way to communicate a jobname to lpr. XThis is really a bug with BSD, since it has no printer access library. END-of-hp/print/print.1 echo x - hp/print/print.c sed 's/^X//' >hp/print/print.c << 'END-of-hp/print/print.c' X/* X * take a list of filenames, and print the files 2 up on a PCL4 printer X * Author: X * Curt Mayer: curt@toad.com X * TODO: X * parameterize all fonts, so can do easily do 4 up someday. X * X * this source has tabs set at 4. X */ X#include <stdio.h> X#include <sys/types.h> X#include <sys/stat.h> X X/* X * mess with these numbers at your own peril - they are the result of X * much jiggery-pokery X */ X X/* size of printable region in dots */ X#define DOTSHIGH 2320 X#define DOTSWIDE 3120 X X/* these are in units of vmi and hmi of the page font */ X#define TOPOFF 4 X#define LEFTMARGIN 6 X#define STARTSIDE1 87 X#define CONTOFF 2 X X/* height of shaded region in dots */ X#define TOPLINE 80 X X/* offset of printable region in dots */ X#define TOPDOTS 50 X#define LEFTDOTS 50 X X/* width of rule lines on page in dots */ X#define LINEWIDTH 2 X X/* header font */ X#define HFONTPOINTS 12 X#define HFONTPITCH 10 X X/* the header font size in dots */ X#define HFONTHEIGHT ((HFONTPOINTS * 100) / 24) X#define HFONTWIDTH (300 / HFONTPITCH) X X/* offset from left and right of header strings in dots */ X#define TEXTMARGIN 50 X X/* these are for the page font */ X#define VMI_66 "5.5" X#define VMI_60 "6.1" X#define HMI "7.2" X#define BOLDOFF "0.6" X X#define CONTCHAR '+' X#define LPRCMD "lpr -P%s -h >/dev/null 2>&1" X X#define LP_DEFAULT "lj" X#define TAB_DEFAULT 4 X#define PAGELEN_DEFAULT 66 X Xchar cmdbuf[80]; X Xchar *printer = LP_DEFAULT; Xint tabstop = TAB_DEFAULT; Xint pagelen = PAGELEN_DEFAULT; X Xchar *vmi; Xint gaudy = 1; Xint line; Xint side; Xint col; Xint pagenum; X XFILE *pp; Xchar *filename; Xtime_t now; X Xextern FILE *popen(), *fopen(); Xextern char *ctime(); Xextern char *getenv(); X Xextern char *optarg; Xextern int optind; Xextern int opterr; Xextern int getopt(); X Xmain(argc, argv) Xint argc; Xchar *argv[]; X{ X FILE *fp; X struct stat statb; X int i, c; X char *e; X X time(&now); X X if (e = getenv("PRINTER")) { X printer = e; X } X X if (e = getenv("TABWIDTH")) { X tabstop = atoi(e); X } X X if (e = getenv("PAGELEN")) { X pagelen = atoi(e); X } X X opterr = 0; X while ((c = getopt(argc, argv, "slt:p:")) != EOF) { X switch(c) { X case 'l': X pagelen = 60; X break; X case 's': X gaudy = 0; X break; X case 't': X tabstop = atoi(optarg); X break; X case 'p': X printer = optarg; X break; X case '?': X default: X fprintf(stderr, X "%s: [-sl] [-t <tabstop>] [-p <printer>] [<file> ...]\n", X argv[0]); X exit(-1); X } X } X X if (tabstop == 0) { X tabstop = TAB_DEFAULT; X } X X switch (pagelen) { X X case 66: X#if PAGELEN_DEFAULT == 66 X default: X#endif X vmi = VMI_66; X pagelen = 66; X break; X X case 60: X#if PAGELEN_DEFAULT == 60 X default: X#endif X vmi = VMI_60; X pagelen = 60; X break; X } X X argc -= optind; X argv += optind; X X if (argc == 0) { X filename = "stdin"; X sendjob(stdin); X } else { X for (i = 0; i < argc; i++) { X filename = argv[i]; X X if (stat(filename, &statb) != 0) { X perror(filename); X continue; X } X X if ((statb.st_mode & S_IFMT) != S_IFREG) { X fprintf(stderr, "print: %s not a regular file\n", filename); X continue; X } X X fp = fopen(filename, "r"); X if (fp == NULL) { X fprintf(stderr, "print: can't open %s\n", filename); X continue; X } X X sendjob(fp); X fclose(fp); X } X } X if (pp) X pclose(pp); X exit (0); X} X Xsendjob(fp) XFILE *fp; X{ X int c; X int lastc; X X if (!pp) { X sprintf(cmdbuf, LPRCMD, printer); X pp = popen(cmdbuf, "w"); X if (pp == NULL) { X fprintf(stderr, "print: can't pipe to line printer\n"); X exit(1); X } X } X X line = 0; X side = 0; X col = 0; X pagenum = 1; X X fprintf(pp, "\033E"); X fprintf(pp, "\033&k2G"); X fprintf(pp, "\033&l1O"); X fprintf(pp, "\033(s0P"); X fprintf(pp, "\033&l0L"); X fprintf(pp, "\0339"); X fprintf(pp, "\033&l0E"); X X drawpage(); X fprintf(pp, "\033&a%dr%dC", TOPOFF + line, LEFTMARGIN + side * STARTSIDE1); X X while ((c = getc(fp)) != EOF) { X switch (c) { X case 0x0c: X c = getc(fp); X if (c != EOF) { X line = pagelen - 1; X do_newline(0); X } X ungetc(c, fp); X break; X case '\n': X do_newline(0); X break; X case '\t': X do { X putc(' ', pp); X } while (++col % tabstop); X break; X case 0x8: X if (col) { X col--; X fprintf(pp, "\033&a%dr%dC", X TOPOFF + line, LEFTMARGIN + side * STARTSIDE1 + col); X c = getc(fp); X if (c == lastc) { X fprintf(pp, "\033&k%sH \033&k%sH%c", BOLDOFF, HMI, c); X col++; X fprintf(pp, "\033&a%dr%dC", X TOPOFF + line, LEFTMARGIN + side * STARTSIDE1 + col); X } else { X ungetc(c, fp); X } X } X break; X default: X if (col >= 80) { X do_newline(1); X } X if (c < ' ') X c = 0x7f; X putc(c, pp); X col++; X lastc = c; X break; X } X } X fprintf(pp, "\033E"); X} X Xdo_newline(wrap) Xint wrap; X{ X putc('\n', pp); X if (++line == pagelen) { X if (side == 1) { X side = 0; X pagenum++; X fprintf(pp, "\014"); X drawpage(); X } else { X side = 1; X } X line = 0; X } X if (wrap) { X fprintf(pp, "\033&a%dr%dC%c", TOPOFF + line, X LEFTMARGIN + side * STARTSIDE1 - CONTOFF, CONTCHAR); X } X fprintf(pp, "\033&a%dr%dC", TOPOFF + line, X LEFTMARGIN + side * STARTSIDE1); X col = 0; X} X Xdrawpage() X{ X char page[5]; X X sprintf(page, "%d", pagenum); X X /* draw vertical line */ X fprintf(pp, "\033*p%dx%dY", (DOTSWIDE / 2) + LEFTDOTS, TOPLINE + TOPDOTS); X fprintf(pp, "\033*c%da%dB", LINEWIDTH, DOTSHIGH); X fprintf(pp, "\033*c0P"); X X if (gaudy) { X /* draw filled horizontal rectangle */ X fprintf(pp, "\033*p%dx%dY", LEFTDOTS, TOPDOTS); X fprintf(pp, "\033*c%da%dB", DOTSWIDE, TOPLINE); X fprintf(pp, "\033*c8G"); X fprintf(pp, "\033*c2P"); X X /* top line */ X fprintf(pp, "\033*p%dx%dY", LEFTDOTS, TOPDOTS); X fprintf(pp, "\033*c%da%dB", DOTSWIDE, LINEWIDTH); X fprintf(pp, "\033*c0P"); X X /* middle line */ X fprintf(pp, "\033*p%dx%dY", LEFTDOTS, TOPLINE + TOPDOTS); X fprintf(pp, "\033*c%da%dB", DOTSWIDE, LINEWIDTH); X fprintf(pp, "\033*c0P"); X X /* left line */ X fprintf(pp, "\033*p%dx%dY", LEFTDOTS, TOPDOTS); X fprintf(pp, "\033*c%da%dB", LINEWIDTH, DOTSHIGH + TOPLINE); X fprintf(pp, "\033*c0P"); X X /* right line */ X fprintf(pp, "\033*p%dx%dY", DOTSWIDE + LEFTDOTS, TOPDOTS); X fprintf(pp, "\033*c%da%dB", LINEWIDTH, DOTSHIGH + TOPLINE); X fprintf(pp, "\033*c0P"); X X /* bottom line */ X fprintf(pp, "\033*p%dx%dY", LEFTDOTS, DOTSHIGH + TOPLINE + TOPDOTS); X fprintf(pp, "\033*c%da%dB", DOTSWIDE, LINEWIDTH); X fprintf(pp, "\033*c0P"); X } else { X /* draw horizontal line */ X fprintf(pp, "\033*p%dx%dY", LEFTDOTS, TOPLINE + TOPDOTS); X fprintf(pp, "\033*c%db%dB", DOTSWIDE, LINEWIDTH); X fprintf(pp, "\033*c0P"); X } X X /* set header font */ X fprintf(pp, "\033(s3T"); X fprintf(pp, "\033(s3S"); X fprintf(pp, "\033(s%dV", HFONTPOINTS); X fprintf(pp, "\033(s%dH", HFONTPITCH); X X /* print header line */ X fprintf(pp, "\033*p%dX", LEFTDOTS + TEXTMARGIN); X fprintf(pp, "\033*p%dY", TOPDOTS + TOPLINE - (HFONTHEIGHT / 2)); X fputs(ctime(&now), pp); X X fprintf(pp, "\033*p%dX", X LEFTDOTS + (DOTSWIDE / 2) - ((strlen(page) * HFONTWIDTH) / 2)); X fprintf(pp, "\033*p%dY", TOPDOTS + TOPLINE - (HFONTHEIGHT / 2)); X fputs(page, pp); X X fprintf(pp, "\033*p%dX", X LEFTDOTS + DOTSWIDE - (strlen(filename) * HFONTWIDTH) - TEXTMARGIN); X fprintf(pp, "\033*p%dY", TOPDOTS + TOPLINE - (HFONTHEIGHT / 2)); X fputs(filename, pp); X X /* set page font */ X fprintf(pp, "\033(s0T"); X fprintf(pp, "\033(s8.5V"); X fprintf(pp, "\033(s16.6H"); X fprintf(pp, "\033&l%df%sC", pagelen, vmi); X} END-of-hp/print/print.c echo c - hp/filters mkdir hp/filters > /dev/null 2>&1 echo x - hp/filters/Makefile sed 's/^X//' >hp/filters/Makefile << 'END-of-hp/filters/Makefile' XSUBDIR= hpf hprast X X.include <bsd.subdir.mk> X END-of-hp/filters/Makefile echo c - hp/filters/hpf mkdir hp/filters/hpf > /dev/null 2>&1 echo x - hp/filters/hpf/Makefile sed 's/^X//' >hp/filters/hpf/Makefile << 'END-of-hp/filters/hpf/Makefile' X# @(#)Makefile 5.9 (Berkeley) 5/13/90 X XPROG= hpf XNOMAN= noman XBINDIR= /usr/libexec/lpr X X.include <bsd.prog.mk> END-of-hp/filters/hpf/Makefile echo x - hp/filters/hpf/README sed 's/^X//' >hp/filters/hpf/README << 'END-of-hp/filters/hpf/README' Xthis directory needs to go into /usr/src/usr.sbin/lpr/filters Xit makes an hp printer do the right thing. Xyou also need to tweak the makefile in /usr/src/usr.sbin/lpr/filters Xappropriately END-of-hp/filters/hpf/README echo x - hp/filters/hpf/hpf.c sed 's/^X//' >hp/filters/hpf/hpf.c << 'END-of-hp/filters/hpf/hpf.c' X#include "stdio.h" X#include <signal.h> X#include <sys/file.h> X#include <sys/ioctl.h> X#include <sgtty.h> X Xmain(ac, av) Xint ac; Xchar **av; X{ X int c; X struct sgttyb nbuf; X unsigned long lbits; X X setbuf(stdout, NULL); X lbits = LDECCTQ | LPASS8 | LLITOUT; X ioctl(fileno(stdout), TIOCLSET, &lbits); X ioctl(fileno(stdout), TIOCGETP, &nbuf); X nbuf.sg_flags &= ~(ECHO | XTABS | CRMOD); X ioctl(fileno(stdout), TIOCSETP, &nbuf); X X fputs("\033E\033&k2G", stdout); X X while (1) { X if ((c = getchar()) != EOF) { X putchar(c); X } else { X break; X } X } X X fputs("\033&l0H", stdout); X X exit(0); X} X END-of-hp/filters/hpf/hpf.c echo c - hp/filters/hprast mkdir hp/filters/hprast > /dev/null 2>&1 echo x - hp/filters/hprast/Makefile sed 's/^X//' >hp/filters/hprast/Makefile << 'END-of-hp/filters/hprast/Makefile' X# @(#)Makefile 5.9 (Berkeley) 5/13/90 X XPROG= hprast XNOMAN= noman XBINDIR= /usr/libexec/lpr X.include <bsd.prog.mk> END-of-hp/filters/hprast/Makefile echo x - hp/filters/hprast/hprast.c sed 's/^X//' >hp/filters/hprast/hprast.c << 'END-of-hp/filters/hprast/hprast.c' X/* X * given a sun rasterfile, translate it into an hp laserjet raster graphic X * it automatically sets the resolution of the laser printer to give the X * largest image possible. X * X * Author: X * Curt Mayer: curt@toad.com X * X * TODO: X * A4 and other paper sizes. X * X * NB: X * this source has tabs set at 4. X */ X X#define VERBOSE /* chatter into line printer log */ X X#include "stdio.h" X#include <signal.h> X#include <sys/file.h> X#include <sys/ioctl.h> X#include <sgtty.h> X Xstruct rasterfile { X int ras_magic; X int ras_width; X int ras_height; X int ras_depth; X int ras_length; X int ras_type; X int ras_maptype; X int ras_maplength; X}; X X#define RAS_MAGIC 0x59a66a95 X#define RT_OLD 0 X#define RT_STANDARD 1 X Xextern char *malloc(); X X/* assume 8.5 by 11 inch paper */ X X#define MAX_75_WIDTH 600 X#define MAX_75_HEIGHT 788 X X#define MAX_150_WIDTH 1200 X#define MAX_150_HEIGHT 1575 X X#define MAX_300_WIDTH 2400 X#define MAX_300_HEIGHT 3150 X Xmain(ac, av) Xint ac; Xchar **av; X{ X int c; X struct sgttyb nbuf; X unsigned long lbits; X struct rasterfile rasthead; X int width; X int resolution = 300; X int row; X int col; X int ret; X X ret = fread(&rasthead, 1, sizeof(rasthead), stdin); X if (ret != sizeof(rasthead)) { X fprintf(stderr, "fread returned %d\n", ret); X exit(-1); X } X X /* check magic number */ X if (rasthead.ras_magic != RAS_MAGIC) { X /* maybe byte swapped? */ X swaplong(&rasthead.ras_magic); X swaplong(&rasthead.ras_width); X swaplong(&rasthead.ras_height); X swaplong(&rasthead.ras_depth); X swaplong(&rasthead.ras_length); X swaplong(&rasthead.ras_type); X swaplong(&rasthead.ras_maptype); X swaplong(&rasthead.ras_maplength); X if (rasthead.ras_magic != RAS_MAGIC) { X fprintf(stderr, "bogus magic number %x expected %x\n", X rasthead.ras_magic, RAS_MAGIC); X exit(-2); X } X } X X#ifdef VERBOSE X fprintf(stderr, "hprast: %x %dx%d %d %d %d %d %d\n", X rasthead.ras_magic, rasthead.ras_width, rasthead.ras_height, X rasthead.ras_depth, rasthead.ras_length, rasthead.ras_type, X rasthead.ras_maptype, rasthead.ras_maplength); X#endif X X /* only monochrome */ X if (rasthead.ras_depth != 1) { X fprintf(stderr, "only supports monochrome rasterfiles\n"); X exit(-3); X } X X /* find appropriate resolution */ X /* must be small enough */ X if ((rasthead.ras_width <= MAX_75_WIDTH) && X (rasthead.ras_height <= MAX_75_HEIGHT)) { X resolution = 75; X } else if ((rasthead.ras_width <= MAX_150_WIDTH) && X (rasthead.ras_height <= MAX_150_HEIGHT)) { X resolution = 150; X } else if ((rasthead.ras_width <= MAX_300_WIDTH) && X (rasthead.ras_height <= MAX_300_HEIGHT)) { X resolution = 300; X } else { X fprintf(stderr, "too big at %dx%d\n", X rasthead.ras_width, rasthead.ras_height); X } X X /* finally, must be right type */ X if ((rasthead.ras_type != RT_OLD) && (rasthead.ras_type != RT_STANDARD)) { X fprintf(stderr, "type %d not supported\n", rasthead.ras_type); X exit(-6); X } X X width = ((rasthead.ras_width + 15) / 16) * 2; X X#ifdef notdef X setbuf(stdout, NULL); X lbits = LDECCTQ | LPASS8 | LLITOUT; X ioctl(fileno(stdout), TIOCLSET, &lbits); X ioctl(fileno(stdout), TIOCGETP, &nbuf); X nbuf.sg_flags &= ~(ECHO | XTABS | CRMOD); X ioctl(fileno(stdout), TIOCSETP, &nbuf); X#endif X /* set graphics mode */ X fputs("\033E\033&k2G", stdout); X fprintf(stdout, "\033*p%dx%dY", resolution/4, resolution/4); X fprintf(stdout, "\033*t%dR", resolution); X fputs("\033*r1a", stdout); X X for (row = 0; row < rasthead.ras_height; row++) { X X fprintf(stdout, "\033*b%dW", width); X for (col = 0; col < width; col++) { X c = getchar(); X if (c == EOF) { X fprintf(stderr, "early end at row %d col %d\n", row, col); X /* finish the line, abort */ X while (col++ < width) { X putchar(0); X } X row = rasthead.ras_height; X } else { X putchar(c); X } X } X } X X /* mark the end of graphics */ X fputs("\033*rB", stdout); X X fputs("\033&l0H", stdout); X X exit(0); X} X Xswaplong(lp) Xint *lp; X{ X unsigned int temp; X temp = *lp; X *lp = ((temp & 0xff) << 24) | X ((temp & 0xff00) << 8) | X ((temp >> 8) & 0xff00) | X ((temp >> 24) & 0xff); X} END-of-hp/filters/hprast/hprast.c exit -- curt mayer curt@toad.com 415-387-0217 home Newsgroups: comp.os.386bsd.questions From: curt@mofo.toad.com (Curt mayer) Path: mofo.toad.com!curt Distribution: world Followup-To: References: <CKwK9K.3I8@cpccspc.cphk.hk> Organization: Subject: Re: Filter file for HP Deskjet/LaserJet Keywords: here's what I use: # This is a shell archive. Save it in a file, remove anything before # this line, and then unpack it by entering "sh file". Note, it may # create directories; files and directories will be owned by you and # have default permissions. # # This archive contains: # # hp # hp/README # hp/printcap # hp/print # hp/print/Makefile # hp/print/README # hp/print/print.1 # hp/print/print.c # hp/filters # hp/filters/Makefile # hp/filters/hpf # hp/filters/hpf/Makefile # hp/filters/hpf/README # hp/filters/hpf/hpf.c # hp/filters/hprast # hp/filters/hprast/Makefile # hp/filters/hprast/hprast.c # echo c - hp mkdir hp > /dev/null 2>&1 echo x - hp/README sed 's/^X//' >hp/README << 'END-of-hp/README' Xthis package is what I use to make my laserjet clone go. Xit consists of 3 components: X Xa printcap file that should be installed in /etc/printcap X it defines 3 printers: X one laserjet, and 2 different postscript emulations using X ghostscript. X X2 print filters, X one for sun rasterfiles that you can get at via lpr -v, X and one for everything else X Xa 2-up print program that emulates enscript a bit. END-of-hp/README echo x - hp/printcap sed 's/^X//' >hp/printcap << 'END-of-hp/printcap' X# X# hp laserjet and clone printcap X# X X# X# for laserjet 2 and bad laserjet 3 clones. X# Xps0|crippled postscript emulation:\ X :lp=/dev/lpa0:sd=/var/spool/lpd:lf=/var/log/lpd-errs:\ X :if=/usr/libexec/lpr/ps2lj:sh:mx#0:sf: X X# X# for laserjet 3 and good laserjet 3 clones. X# Xps|postscript emulation:\ X :lp=/dev/lpa0:sd=/var/spool/lpd:lf=/var/log/lpd-errs:\ X :if=/usr/libexec/lpr/ps2lj3:sh:mx#0:sf: X X# X# for native stuff, plus sun rasterfiles via lpr -v X# Xlp|epson|lj|local line printer:\ X :lp=/dev/lpa0:sd=/var/spool/lpd:lf=/var/log/lpd-errs:\ X :vf=/usr/libexec/lpr/hprast:\ X :if=/usr/libexec/lpr/hpf:\ X :df=/usr/local/bin/dvi2lj:\ X :sh:mx#0:pw#80: END-of-hp/printcap echo c - hp/print mkdir hp/print > /dev/null 2>&1 echo x - hp/print/Makefile sed 's/^X//' >hp/print/Makefile << 'END-of-hp/print/Makefile' XPROG= print X X.include <bsd.prog.mk> END-of-hp/print/Makefile echo x - hp/print/README sed 's/^X//' >hp/print/README << 'END-of-hp/print/README' Xthis directory contains a PCL4 + PCL5 print formatter that prints 2 up. Xit has been tested on FreeBSD and NetBSD Xit is free software. Xall rites reversed. Xjust don't claim you wrote it. END-of-hp/print/README echo x - hp/print/print.1 sed 's/^X//' >hp/print/print.1 << 'END-of-hp/print/print.1' X.\" X.Dd November 18, 1993 X.Dt PRINT 1 X.Os X.Sh NAME X.Nm print X.Nd queue text files to PCL4 printer. X.Sh SYNOPSIS X.Nm print X.Op Fl s X.Op Fl l X.Op Fl t Ar tabwidth X.Op Fl p Ar printer_name X.Op Ar text_file ... X.Sh DESCRIPTION X.Nm Print Xprints files 2 pages side by side on 1 piece of paper on PCL4 printer. XIf no files are specified, it reads stdin. X.Nm Print Xusually does the right thing with nroff output. It fakes boldface rather well. X.Pp XOptions: X.Bl -tag -width Ds X.It Fl s XSpecify graphically simple output, without the gaudy borders. X.It Fl l XSpecify formatting for 60 lines per page, instead of the default 66. X.It Fl t XSpecify the tab width. The default of 4 may irritate purists. X.It Fl p XSpecify the printer to spool to. The default printer is named X.Em lj. X.Sh ENVIRONMENT XIf the following environment variables exist, they are used by X.Nm print: X.Bl -tag -width PAGELENGTH X.It Ev PRINTER XSpecifies an alternate printer. X.It Ev TABWIDTH XSpecifies the tab stop width. X.It Ev PAGELENGTH XSpecifies the page length. it may take the value of 60 or 66. X.Sh AUTHOR Xcurt@toad.com X.Sh BUGS XThere is no way to communicate a jobname to lpr. XThis is really a bug with BSD, since it has no printer access library. END-of-hp/print/print.1 echo x - hp/print/print.c sed 's/^X//' >hp/print/print.c << 'END-of-hp/print/print.c' X/* X * take a list of filenames, and print the files 2 up on a PCL4 printer X * Author: X * Curt Mayer: curt@toad.com X * TODO: X * parameterize all fonts, so can do easily do 4 up someday. X * X * this source has tabs set at 4. X */ X#include <stdio.h> X#include <sys/types.h> X#include <sys/stat.h> X X/* X * mess with these numbers at your own peril - they are the result of X * much jiggery-pokery X */ X X/* size of printable region in dots */ X#define DOTSHIGH 2320 X#define DOTSWIDE 3120 X X/* these are in units of vmi and hmi of the page font */ X#define TOPOFF 4 X#define LEFTMARGIN 6 X#define STARTSIDE1 87 X#define CONTOFF 2 X X/* height of shaded region in dots */ X#define TOPLINE 80 X X/* offset of printable region in dots */ X#define TOPDOTS 50 X#define LEFTDOTS 50 X X/* width of rule lines on page in dots */ X#define LINEWIDTH 2 X X/* header font */ X#define HFONTPOINTS 12 X#define HFONTPITCH 10 X X/* the header font size in dots */ X#define HFONTHEIGHT ((HFONTPOINTS * 100) / 24) X#define HFONTWIDTH (300 / HFONTPITCH) X X/* offset from left and right of header strings in dots */ X#define TEXTMARGIN 50 X X/* these are for the page font */ X#define VMI_66 "5.5" X#define VMI_60 "6.1" X#define HMI "7.2" X#define BOLDOFF "0.6" X X#define CONTCHAR '+' X#define LPRCMD "lpr -P%s -h >/dev/null 2>&1" X X#define LP_DEFAULT "lj" X#define TAB_DEFAULT 4 X#define PAGELEN_DEFAULT 66 X Xchar cmdbuf[80]; X Xchar *printer = LP_DEFAULT; Xint tabstop = TAB_DEFAULT; Xint pagelen = PAGELEN_DEFAULT; X Xchar *vmi; Xint gaudy = 1; Xint line; Xint side; Xint col; Xint pagenum; X XFILE *pp; Xchar *filename; Xtime_t now; X Xextern FILE *popen(), *fopen(); Xextern char *ctime(); Xextern char *getenv(); X Xextern char *optarg; Xextern int optind; Xextern int opterr; Xextern int getopt(); X Xmain(argc, argv) Xint argc; Xchar *argv[]; X{ X FILE *fp; X struct stat statb; X int i, c; X char *e; X X time(&now); X X if (e = getenv("PRINTER")) { X printer = e; X } X X if (e = getenv("TABWIDTH")) { X tabstop = atoi(e); X } X X if (e = getenv("PAGELEN")) { X pagelen = atoi(e); X } X X opterr = 0; X while ((c = getopt(argc, argv, "slt:p:")) != EOF) { X switch(c) { X case 'l': X pagelen = 60; X break; X case 's': X gaudy = 0; X break; X case 't': X tabstop = atoi(optarg); X break; X case 'p': X printer = optarg; X break; X case '?': X default: X fprintf(stderr, X "%s: [-sl] [-t <tabstop>] [-p <printer>] [<file> ...]\n", X argv[0]); X exit(-1); X } X } X X if (tabstop == 0) { X tabstop = TAB_DEFAULT; X } X X switch (pagelen) { X X case 66: X#if PAGELEN_DEFAULT == 66 X default: X#endif X vmi = VMI_66; X pagelen = 66; X break; X X case 60: X#if PAGELEN_DEFAULT == 60 X default: X#endif X vmi = VMI_60; X pagelen = 60; X break; X } X X argc -= optind; X argv += optind; X X if (argc == 0) { X filename = "stdin"; X sendjob(stdin); X } else { X for (i = 0; i < argc; i++) { X filename = argv[i]; X X if (stat(filename, &statb) != 0) { X perror(filename); X continue; X } X X if ((statb.st_mode & S_IFMT) != S_IFREG) { X fprintf(stderr, "print: %s not a regular file\n", filename); X continue; X } X X fp = fopen(filename, "r"); X if (fp == NULL) { X fprintf(stderr, "print: can't open %s\n", filename); X continue; X } X X sendjob(fp); X fclose(fp); X } X } X if (pp) X pclose(pp); X exit (0); X} X Xsendjob(fp) XFILE *fp; X{ X int c; X int lastc; X X if (!pp) { X sprintf(cmdbuf, LPRCMD, printer); X pp = popen(cmdbuf, "w"); X if (pp == NULL) { X fprintf(stderr, "print: can't pipe to line printer\n"); X exit(1); X } X } X X line = 0; X side = 0; X col = 0; X pagenum = 1; X X fprintf(pp, "\033E"); X fprintf(pp, "\033&k2G"); X fprintf(pp, "\033&l1O"); X fprintf(pp, "\033(s0P"); X fprintf(pp, "\033&l0L"); X fprintf(pp, "\0339"); X fprintf(pp, "\033&l0E"); X X drawpage(); X fprintf(pp, "\033&a%dr%dC", TOPOFF + line, LEFTMARGIN + side * STARTSIDE1); X X while ((c = getc(fp)) != EOF) { X switch (c) { X case 0x0c: X c = getc(fp); X if (c != EOF) { X line = pagelen - 1; X do_newline(0); X } X ungetc(c, fp); X break; X case '\n': X do_newline(0); X break; X case '\t': X do { X putc(' ', pp); X } while (++col % tabstop); X break; X case 0x8: X if (col) { X col--; X fprintf(pp, "\033&a%dr%dC", X TOPOFF + line, LEFTMARGIN + side * STARTSIDE1 + col); X c = getc(fp); X if (c == lastc) { X fprintf(pp, "\033&k%sH \033&k%sH%c", BOLDOFF, HMI, c); X col++; X fprintf(pp, "\033&a%dr%dC", X TOPOFF + line, LEFTMARGIN + side * STARTSIDE1 + col); X } else { X ungetc(c, fp); X } X } X break; X default: X if (col >= 80) { X do_newline(1); X } X if (c < ' ') X c = 0x7f; X putc(c, pp); X col++; X lastc = c; X break; X } X } X fprintf(pp, "\033E"); X} X Xdo_newline(wrap) Xint wrap; X{ X putc('\n', pp); X if (++line == pagelen) { X if (side == 1) { X side = 0; X pagenum++; X fprintf(pp, "\014"); X drawpage(); X } else { X side = 1; X } X line = 0; X } X if (wrap) { X fprintf(pp, "\033&a%dr%dC%c", TOPOFF + line, X LEFTMARGIN + side * STARTSIDE1 - CONTOFF, CONTCHAR); X } X fprintf(pp, "\033&a%dr%dC", TOPOFF + line, X LEFTMARGIN + side * STARTSIDE1); X col = 0; X} X Xdrawpage() X{ X char page[5]; X X sprintf(page, "%d", pagenum); X X /* draw vertical line */ X fprintf(pp, "\033*p%dx%dY", (DOTSWIDE / 2) + LEFTDOTS, TOPLINE + TOPDOTS); X fprintf(pp, "\033*c%da%dB", LINEWIDTH, DOTSHIGH); X fprintf(pp, "\033*c0P"); X X if (gaudy) { X /* draw filled horizontal rectangle */ X fprintf(pp, "\033*p%dx%dY", LEFTDOTS, TOPDOTS); X fprintf(pp, "\033*c%da%dB", DOTSWIDE, TOPLINE); X fprintf(pp, "\033*c8G"); X fprintf(pp, "\033*c2P"); X X /* top line */ X fprintf(pp, "\033*p%dx%dY", LEFTDOTS, TOPDOTS); X fprintf(pp, "\033*c%da%dB", DOTSWIDE, LINEWIDTH); X fprintf(pp, "\033*c0P"); X X /* middle line */ X fprintf(pp, "\033*p%dx%dY", LEFTDOTS, TOPLINE + TOPDOTS); X fprintf(pp, "\033*c%da%dB", DOTSWIDE, LINEWIDTH); X fprintf(pp, "\033*c0P"); X X /* left line */ X fprintf(pp, "\033*p%dx%dY", LEFTDOTS, TOPDOTS); X fprintf(pp, "\033*c%da%dB", LINEWIDTH, DOTSHIGH + TOPLINE); X fprintf(pp, "\033*c0P"); X X /* right line */ X fprintf(pp, "\033*p%dx%dY", DOTSWIDE + LEFTDOTS, TOPDOTS); X fprintf(pp, "\033*c%da%dB", LINEWIDTH, DOTSHIGH + TOPLINE); X fprintf(pp, "\033*c0P"); X X /* bottom line */ X fprintf(pp, "\033*p%dx%dY", LEFTDOTS, DOTSHIGH + TOPLINE + TOPDOTS); X fprintf(pp, "\033*c%da%dB", DOTSWIDE, LINEWIDTH); X fprintf(pp, "\033*c0P"); X } else { X /* draw horizontal line */ X fprintf(pp, "\033*p%dx%dY", LEFTDOTS, TOPLINE + TOPDOTS); X fprintf(pp, "\033*c%db%dB", DOTSWIDE, LINEWIDTH); X fprintf(pp, "\033*c0P"); X } X X /* set header font */ X fprintf(pp, "\033(s3T"); X fprintf(pp, "\033(s3S"); X fprintf(pp, "\033(s%dV", HFONTPOINTS); X fprintf(pp, "\033(s%dH", HFONTPITCH); X X /* print header line */ X fprintf(pp, "\033*p%dX", LEFTDOTS + TEXTMARGIN); X fprintf(pp, "\033*p%dY", TOPDOTS + TOPLINE - (HFONTHEIGHT / 2)); X fputs(ctime(&now), pp); X X fprintf(pp, "\033*p%dX", X LEFTDOTS + (DOTSWIDE / 2) - ((strlen(page) * HFONTWIDTH) / 2)); X fprintf(pp, "\033*p%dY", TOPDOTS + TOPLINE - (HFONTHEIGHT / 2)); X fputs(page, pp); X X fprintf(pp, "\033*p%dX", X LEFTDOTS + DOTSWIDE - (strlen(filename) * HFONTWIDTH) - TEXTMARGIN); X fprintf(pp, "\033*p%dY", TOPDOTS + TOPLINE - (HFONTHEIGHT / 2)); X fputs(filename, pp); X X /* set page font */ X fprintf(pp, "\033(s0T"); X fprintf(pp, "\033(s8.5V"); X fprintf(pp, "\033(s16.6H"); X fprintf(pp, "\033&l%df%sC", pagelen, vmi); X} END-of-hp/print/print.c echo c - hp/filters mkdir hp/filters > /dev/null 2>&1 echo x - hp/filters/Makefile sed 's/^X//' >hp/filters/Makefile << 'END-of-hp/filters/Makefile' XSUBDIR= hpf hprast X X.include <bsd.subdir.mk> X END-of-hp/filters/Makefile echo c - hp/filters/hpf mkdir hp/filters/hpf > /dev/null 2>&1 echo x - hp/filters/hpf/Makefile sed 's/^X//' >hp/filters/hpf/Makefile << 'END-of-hp/filters/hpf/Makefile' X# @(#)Makefile 5.9 (Berkeley) 5/13/90 X XPROG= hpf XNOMAN= noman XBINDIR= /usr/libexec/lpr X X.include <bsd.prog.mk> END-of-hp/filters/hpf/Makefile echo x - hp/filters/hpf/README sed 's/^X//' >hp/filters/hpf/README << 'END-of-hp/filters/hpf/README' Xthis directory needs to go into /usr/src/usr.sbin/lpr/filters Xit makes an hp printer do the right thing. Xyou also need to tweak the makefile in /usr/src/usr.sbin/lpr/filters Xappropriately END-of-hp/filters/hpf/README echo x - hp/filters/hpf/hpf.c sed 's/^X//' >hp/filters/hpf/hpf.c << 'END-of-hp/filters/hpf/hpf.c' X#include "stdio.h" X#include <signal.h> X#include <sys/file.h> X#include <sys/ioctl.h> X#include <sgtty.h> X Xmain(ac, av) Xint ac; Xchar **av; X{ X int c; X struct sgttyb nbuf; X unsigned long lbits; X X setbuf(stdout, NULL); X lbits = LDECCTQ | LPASS8 | LLITOUT; X ioctl(fileno(stdout), TIOCLSET, &lbits); X ioctl(fileno(stdout), TIOCGETP, &nbuf); X nbuf.sg_flags &= ~(ECHO | XTABS | CRMOD); X ioctl(fileno(stdout), TIOCSETP, &nbuf); X X fputs("\033E\033&k2G", stdout); X X while (1) { X if ((c = getchar()) != EOF) { X putchar(c); X } else { X break; X } X } X X fputs("\033&l0H", stdout); X X exit(0); X} X END-of-hp/filters/hpf/hpf.c echo c - hp/filters/hprast mkdir hp/filters/hprast > /dev/null 2>&1 echo x - hp/filters/hprast/Makefile sed 's/^X//' >hp/filters/hprast/Makefile << 'END-of-hp/filters/hprast/Makefile' X# @(#)Makefile 5.9 (Berkeley) 5/13/90 X XPROG= hprast XNOMAN= noman XBINDIR= /usr/libexec/lpr X.include <bsd.prog.mk> END-of-hp/filters/hprast/Makefile echo x - hp/filters/hprast/hprast.c sed 's/^X//' >hp/filters/hprast/hprast.c << 'END-of-hp/filters/hprast/hprast.c' X/* X * given a sun rasterfile, translate it into an hp laserjet raster graphic X * it automatically sets the resolution of the laser printer to give the X * largest image possible. X * X * Author: X * Curt Mayer: curt@toad.com X * X * TODO: X * A4 and other paper sizes. X * X * NB: X * this source has tabs set at 4. X */ X X#define VERBOSE /* chatter into line printer log */ X X#include "stdio.h" X#include <signal.h> X#include <sys/file.h> X#include <sys/ioctl.h> X#include <sgtty.h> X Xstruct rasterfile { X int ras_magic; X int ras_width; X int ras_height; X int ras_depth; X int ras_length; X int ras_type; X int ras_maptype; X int ras_maplength; X}; X X#define RAS_MAGIC 0x59a66a95 X#define RT_OLD 0 X#define RT_STANDARD 1 X Xextern char *malloc(); X X/* assume 8.5 by 11 inch paper */ X X#define MAX_75_WIDTH 600 X#define MAX_75_HEIGHT 788 X X#define MAX_150_WIDTH 1200 X#define MAX_150_HEIGHT 1575 X X#define MAX_300_WIDTH 2400 X#define MAX_300_HEIGHT 3150 X Xmain(ac, av) Xint ac; Xchar **av; X{ X int c; X struct sgttyb nbuf; X unsigned long lbits; X struct rasterfile rasthead; X int width; X int resolution = 300; X int row; X int col; X int ret; X X ret = fread(&rasthead, 1, sizeof(rasthead), stdin); X if (ret != sizeof(rasthead)) { X fprintf(stderr, "fread returned %d\n", ret); X exit(-1); X } X X /* check magic number */ X if (rasthead.ras_magic != RAS_MAGIC) { X /* maybe byte swapped? */ X swaplong(&rasthead.ras_magic); X swaplong(&rasthead.ras_width); X swaplong(&rasthead.ras_height); X swaplong(&rasthead.ras_depth); X swaplong(&rasthead.ras_length); X swaplong(&rasthead.ras_type); X swaplong(&rasthead.ras_maptype); X swaplong(&rasthead.ras_maplength); X if (rasthead.ras_magic != RAS_MAGIC) { X fprintf(stderr, "bogus magic number %x expected %x\n", X rasthead.ras_magic, RAS_MAGIC); X exit(-2); X } X } X X#ifdef VERBOSE X fprintf(stderr, "hprast: %x %dx%d %d %d %d %d %d\n", X rasthead.ras_magic, rasthead.ras_width, rasthead.ras_height, X rasthead.ras_depth, rasthead.ras_length, rasthead.ras_type, X rasthead.ras_maptype, rasthead.ras_maplength); X#endif X X /* only monochrome */ X if (rasthead.ras_depth != 1) { X fprintf(stderr, "only supports monochrome rasterfiles\n"); X exit(-3); X } X X /* find appropriate resolution */ X /* must be small enough */ X if ((rasthead.ras_width <= MAX_75_WIDTH) && X (rasthead.ras_height <= MAX_75_HEIGHT)) { X resolution = 75; X } else if ((rasthead.ras_width <= MAX_150_WIDTH) && X (rasthead.ras_height <= MAX_150_HEIGHT)) { X resolution = 150; X } else if ((rasthead.ras_width <= MAX_300_WIDTH) && X (rasthead.ras_height <= MAX_300_HEIGHT)) { X resolution = 300; X } else { X fprintf(stderr, "too big at %dx%d\n", X rasthead.ras_width, rasthead.ras_height); X } X X /* finally, must be right type */ X if ((rasthead.ras_type != RT_OLD) && (rasthead.ras_type != RT_STANDARD)) { X fprintf(stderr, "type %d not supported\n", rasthead.ras_type); X exit(-6); X } X X width = ((rasthead.ras_width + 15) / 16) * 2; X X#ifdef notdef X setbuf(stdout, NULL); X lbits = LDECCTQ | LPASS8 | LLITOUT; X ioctl(fileno(stdout), TIOCLSET, &lbits); X ioctl(fileno(stdout), TIOCGETP, &nbuf); X nbuf.sg_flags &= ~(ECHO | XTABS | CRMOD); X ioctl(fileno(stdout), TIOCSETP, &nbuf); X#endif X /* set graphics mode */ X fputs("\033E\033&k2G", stdout); X fprintf(stdout, "\033*p%dx%dY", resolution/4, resolution/4); X fprintf(stdout, "\033*t%dR", resolution); X fputs("\033*r1a", stdout); X X for (row = 0; row < rasthead.ras_height; row++) { X X fprintf(stdout, "\033*b%dW", width); X for (col = 0; col < width; col++) { X c = getchar(); X if (c == EOF) { X fprintf(stderr, "early end at row %d col %d\n", row, col); X /* finish the line, abort */ X while (col++ < width) { X putchar(0); X } X row = rasthead.ras_height; X } else { X putchar(c); X } X } X } X X /* mark the end of graphics */ X fputs("\033*rB", stdout); X X fputs("\033&l0H", stdout); X X exit(0); X} X Xswaplong(lp) Xint *lp; X{ X unsigned int temp; X temp = *lp; X *lp = ((temp & 0xff) << 24) | X ((temp & 0xff00) << 8) | X ((temp >> 8) & 0xff00) | X ((temp >> 24) & 0xff); X} END-of-hp/filters/hprast/hprast.c exit -- curt mayer curt@toad.com 415-387-0217 home