Return to BSD News archive
Path: sserve!newshost.anu.edu.au!munnari.oz.au!sgiblab!pacbell.com!toad.com!curt From: curt@mofo.toad.com (Curt mayer) Newsgroups: comp.os.386bsd.apps Subject: PCL filter, file printer for HP and clones Message-ID: <42821@toad.com> Date: 27 Dec 93 19:52:58 GMT Sender: news@toad.com Followup-To: comp.os.386bsd.questions Distribution: world Organization: Mofo Lines: 591 Summary: the postscript tyranny is over Nntp-Posting-Host: mofo.toad.com -----------------------cut here--------------------- : To unbundle, sh this file mkdir . echo ./README cat >./README <<'@@@ Fin de ./README' This package makes HP PCL printers work under Freebsd. it should also work under netbsd, and others to come. to install: copy the printcap file to /etc copy the hpf subdirectory to /usr/src/usr.sbin/lpr/filters change the line in /usr/src/usr.sbin/lpr/filters/Makefile to read: SUBDIR= hpf lpf lzcat cd to /usr/src/usr.sbin/lpr/filters make ; make install then, copy the print subdirectory wherever; I have it in /usr/src/usr.bin cd there; make ; make install make sure you have the appropriate parallel driver configured. I use lpa0. enjoy. @@@ Fin de ./README mkdir ./hpf echo ./hpf/Makefile cat >./hpf/Makefile <<'@@@ Fin de ./hpf/Makefile' # @(#)Makefile 5.9 (Berkeley) 5/13/90 PROG= hpf NOMAN= noman BINDIR= /usr/libexec/lpr .include <bsd.prog.mk> @@@ Fin de ./hpf/Makefile echo ./hpf/README cat >./hpf/README <<'@@@ Fin de ./hpf/README' this directory needs to go into /usr/src/usr.sbin/lpr/filters it makes an hp printer do the right thing. you also need to tweak the makefile in /usr/src/usr.sbin/lpr appropriately @@@ Fin de ./hpf/README echo ./hpf/hpf.c cat >./hpf/hpf.c <<'@@@ Fin de ./hpf/hpf.c' #include "stdio.h" #include <signal.h> #include <sys/file.h> #include <sys/ioctl.h> int nomap = 0; main(ac, av) int ac; char **av; { while(ac > 1 && av[1][0] == '-') { switch(av[1][1]) { case 'c': nomap = 1; break; default: break; } ac--; av++; } lzinit(); hpcat(); hpdone(); exit(0); } #include <sgtty.h> lzinit() { struct sgttyb nbuf; unsigned long lbits; setbuf(stdout, NULL); lbits = LDECCTQ | LPASS8 | LLITOUT; ioctl(fileno(stdout), TIOCLSET, &lbits); ioctl(fileno(stdout), TIOCGETP, &nbuf); nbuf.sg_flags &= ~(ECHO | XTABS | CRMOD); ioctl(fileno(stdout), TIOCSETP, &nbuf); fputs("\033E\033&k2G", stdout); } hpcat() { int c, c2, cnt = 0; while((c = getchar()) != EOF) { switch (c) { case '\t': do { putchar(' '); cnt++; } while(cnt%8 != 0); break; case '\031': c2 = getchar(); if (c2 == '\001') { kill(getpid(), SIGSTOP); break; } else { ungetc(c2, stdin); } /* fall through */ default: putchar(c); if(c == '\f' || c == '\n') { cnt = 0; } else cnt++; } } } hpdone() { fputs("\033&l0H", stdout); } @@@ Fin de ./hpf/hpf.c mkdir ./print echo ./print/Makefile cat >./print/Makefile <<'@@@ Fin de ./print/Makefile' # @(#)Makefile 5.3 (Berkeley) 5/11/90 PROG= print .include <bsd.prog.mk> @@@ Fin de ./print/Makefile echo ./print/README cat >./print/README <<'@@@ Fin de ./print/README' this directory contains a PCL5 print formatter that prints 2 up. it also should work on PCL4. it has been tested on FreeBSD 1.0. it should work elsewhere. it is free software. all rites reversed. just don't claim you wrote it. @@@ Fin de ./print/README echo ./print/print.1 cat >./print/print.1 <<'@@@ Fin de ./print/print.1' .\" .Dd November 18, 1993 .Dt PRINT 1 .Os .Sh NAME .Nm print .Nd queue text files to PCL4 printer. .Sh SYNOPSIS .Nm print .Op Fl s .Op Fl l .Op Fl t Ar tabwidth .Op Fl p Ar printer_name .Op Ar text_file ... .Sh DESCRIPTION .Nm Print prints files 2 pages side by side on 1 piece of paper on PCL4 printer. If no files are specified, it reads stdin. .Nm Print usually does the right thing with nroff output. It fakes boldface rather well. .Pp Options: .Bl -tag -width Ds .It Fl s Specify graphically simple output, without the gaudy borders. .It Fl l Specify formatting for 60 lines per page, instead of the default 66. .It Fl t Specify the tab width. The default of 4 may irritate purists. .It Fl p Specify the printer to spool to. The default printer is named .Em lj. .Sh ENVIRONMENT If the following environment variables exist, they are used by .Nm print: .Bl -tag -width PAGELENGTH .It Ev PRINTER Specifies an alternate printer. .It Ev TABWIDTH Specifies the tab stop width. .It Ev PAGELENGTH Specifies the page length. it may take the value of 60 or 66. .Sh AUTHOR curt@toad.com .Sh BUGS There is no way to communicate a jobname to lpr. This is really a bug with BSD, since it has no printer access library. Hasn't been tested on a real HP laserjet. @@@ Fin de ./print/print.1 echo ./print/print.c cat >./print/print.c <<'@@@ Fin de ./print/print.c' /* * take a list of filenames, and print the files 2 up on a PCL4 printer * Author: * Curt Mayer: curt@toad.com * TODO: * parameterize all fonts, so can do easily do 4 up someday. * * this source has tabs set at 4. */ #include <stdio.h> #include <sys/types.h> #include <sys/stat.h> /* * mess with these numbers at your own peril - they are the result of * much jiggery-pokery */ /* size of printable region in dots */ #define DOTSHIGH 2320 #define DOTSWIDE 3120 /* these are in units of vmi and hmi of the page font */ #define TOPOFF 4 #define LEFTMARGIN 6 #define STARTSIDE1 87 #define CONTOFF 2 /* height of shaded region in dots */ #define TOPLINE 80 /* offset of printable region in dots */ #define TOPDOTS 50 #define LEFTDOTS 50 /* width of rule lines on page in dots */ #define LINEWIDTH 2 /* header font */ #define HFONTPOINTS 12 #define HFONTPITCH 10 /* the header font size in dots */ #define HFONTHEIGHT ((HFONTPOINTS * 100) / 24) #define HFONTWIDTH (300 / HFONTPITCH) /* offset from left and right of header strings in dots */ #define TEXTMARGIN 50 /* these are for the page font */ #define VMI_66 "5.5" #define VMI_60 "6.1" #define HMI "7.2" #define BOLDOFF "0.6" #define CONTCHAR '+' #define LPRCMD "lpr -P%s -h >/dev/null 2>&1" #define LP_DEFAULT "lj" #define TAB_DEFAULT 4 #define PAGELEN_DEFAULT 66 char cmdbuf[80]; char *printer = LP_DEFAULT; int tabstop = TAB_DEFAULT; int pagelen = PAGELEN_DEFAULT; char *vmi; int gaudy = 1; int line; int side; int col; int pagenum; FILE *pp; char *filename; time_t now; extern FILE *popen(), *fopen(); extern char *ctime(); extern char *getenv(); extern char *optarg; extern int optind; extern int opterr; extern int getopt(); main(argc, argv) int argc; char *argv[]; { FILE *fp; struct stat statb; int i, c; char *e; time(&now); if (e = getenv("PRINTER")) { printer = e; } if (e = getenv("TABWIDTH")) { tabstop = atoi(e); } if (e = getenv("PAGELEN")) { pagelen = atoi(e); } opterr = 0; while ((c = getopt(argc, argv, "slt:p:")) != EOF) { switch(c) { case 'l': pagelen = 60; break; case 's': gaudy = 0; break; case 't': tabstop = atoi(optarg); break; case 'p': printer = optarg; break; case '?': default: fprintf(stderr, "%s: [-sl] [-t <tabstop>] [-p <printer>] [<file> ...]\n", argv[0]); exit(-1); } } if (tabstop == 0) { tabstop = TAB_DEFAULT; } switch (pagelen) { case 66: #if PAGELEN_DEFAULT == 66 default: #endif vmi = VMI_66; pagelen = 66; break; case 60: #if PAGELEN_DEFAULT == 60 default: #endif vmi = VMI_60; pagelen = 60; break; } argc -= optind; argv += optind; if (argc == 0) { filename = "stdin"; sendjob(stdin); } else { for (i = 0; i < argc; i++) { filename = argv[i]; if (stat(filename, &statb) != 0) { perror(filename); continue; } if ((statb.st_mode & S_IFMT) != S_IFREG) { fprintf(stderr, "print: %s not a regular file\n", filename); continue; } fp = fopen(filename, "r"); if (fp == NULL) { fprintf(stderr, "print: can't open %s\n", filename); continue; } sendjob(fp); fclose(fp); } } if (pp) pclose(pp); exit (0); } sendjob(fp) FILE *fp; { int c; int lastc; if (!pp) { sprintf(cmdbuf, LPRCMD, printer); pp = popen(cmdbuf, "w"); if (pp == NULL) { fprintf(stderr, "print: can't pipe to line printer\n"); exit(1); } } line = 0; side = 0; col = 0; pagenum = 1; fprintf(pp, "\033E"); fprintf(pp, "\033&k2G"); fprintf(pp, "\033&l1O"); fprintf(pp, "\033(s0P"); fprintf(pp, "\033&l0L"); fprintf(pp, "\0339"); fprintf(pp, "\033&l0E"); drawpage(); fprintf(pp, "\033&a%dr%dC", TOPOFF + line, LEFTMARGIN + side * STARTSIDE1); while ((c = getc(fp)) != EOF) { switch (c) { case 0x0c: c = getc(fp); if (c != EOF) { line = pagelen - 1; do_newline(0); } ungetc(c, fp); break; case '\n': do_newline(0); break; case '\t': do { putc(' ', pp); } while (++col % tabstop); break; case 0x8: if (col) { col--; fprintf(pp, "\033&a%dr%dC", TOPOFF + line, LEFTMARGIN + side * STARTSIDE1 + col); c = getc(fp); if (c == lastc) { fprintf(pp, "\033&k%sH \033&k%sH%c", BOLDOFF, HMI, c); col++; fprintf(pp, "\033&a%dr%dC", TOPOFF + line, LEFTMARGIN + side * STARTSIDE1 + col); } else { ungetc(c, fp); } } break; default: if (col >= 80) { do_newline(1); } if (c < ' ') c = 0x7f; putc(c, pp); col++; lastc = c; break; } } fprintf(pp, "\033E"); } do_newline(wrap) int wrap; { putc('\n', pp); if (++line == pagelen) { if (side == 1) { side = 0; pagenum++; fprintf(pp, "\014"); drawpage(); } else { side = 1; } line = 0; } if (wrap) { fprintf(pp, "\033&a%dr%dC%c", TOPOFF + line, LEFTMARGIN + side * STARTSIDE1 - CONTOFF, CONTCHAR); } fprintf(pp, "\033&a%dr%dC", TOPOFF + line, LEFTMARGIN + side * STARTSIDE1); col = 0; } drawpage() { char page[5]; sprintf(page, "%d", pagenum); /* draw vertical line */ fprintf(pp, "\033*p%dx%dY", (DOTSWIDE / 2) + LEFTDOTS, TOPLINE + TOPDOTS); fprintf(pp, "\033*c%da%dB", LINEWIDTH, DOTSHIGH); fprintf(pp, "\033*c0P"); if (gaudy) { /* draw filled horizontal rectangle */ fprintf(pp, "\033*p%dx%dY", LEFTDOTS, TOPDOTS); fprintf(pp, "\033*c%da%dB", DOTSWIDE, TOPLINE); fprintf(pp, "\033*c8G"); fprintf(pp, "\033*c2P"); /* top line */ fprintf(pp, "\033*p%dx%dY", LEFTDOTS, TOPDOTS); fprintf(pp, "\033*c%da%dB", DOTSWIDE, LINEWIDTH); fprintf(pp, "\033*c0P"); /* middle line */ fprintf(pp, "\033*p%dx%dY", LEFTDOTS, TOPLINE + TOPDOTS); fprintf(pp, "\033*c%da%dB", DOTSWIDE, LINEWIDTH); fprintf(pp, "\033*c0P"); /* left line */ fprintf(pp, "\033*p%dx%dY", LEFTDOTS, TOPDOTS); fprintf(pp, "\033*c%da%dB", LINEWIDTH, DOTSHIGH + TOPLINE); fprintf(pp, "\033*c0P"); /* right line */ fprintf(pp, "\033*p%dx%dY", DOTSWIDE + LEFTDOTS, TOPDOTS); fprintf(pp, "\033*c%da%dB", LINEWIDTH, DOTSHIGH + TOPLINE); fprintf(pp, "\033*c0P"); /* bottom line */ fprintf(pp, "\033*p%dx%dY", LEFTDOTS, DOTSHIGH + TOPLINE + TOPDOTS); fprintf(pp, "\033*c%da%dB", DOTSWIDE, LINEWIDTH); fprintf(pp, "\033*c0P"); } else { /* draw horizontal line */ fprintf(pp, "\033*p%dx%dY", LEFTDOTS, TOPLINE + TOPDOTS); fprintf(pp, "\033*c%db%dB", DOTSWIDE, LINEWIDTH); fprintf(pp, "\033*c0P"); } /* set header font */ fprintf(pp, "\033(s3T"); fprintf(pp, "\033(s3S"); fprintf(pp, "\033(s%dV", HFONTPOINTS); fprintf(pp, "\033(s%dH", HFONTPITCH); /* print header line */ fprintf(pp, "\033*p%dX", LEFTDOTS + TEXTMARGIN); fprintf(pp, "\033*p%dY", TOPDOTS + TOPLINE - (HFONTHEIGHT / 2)); fputs(ctime(&now), pp); fprintf(pp, "\033*p%dX", LEFTDOTS + (DOTSWIDE / 2) - ((strlen(page) * HFONTWIDTH) / 2)); fprintf(pp, "\033*p%dY", TOPDOTS + TOPLINE - (HFONTHEIGHT / 2)); fputs(page, pp); fprintf(pp, "\033*p%dX", LEFTDOTS + DOTSWIDE - (strlen(filename) * HFONTWIDTH) - TEXTMARGIN); fprintf(pp, "\033*p%dY", TOPDOTS + TOPLINE - (HFONTHEIGHT / 2)); fputs(filename, pp); /* set page font */ fprintf(pp, "\033(s0T"); fprintf(pp, "\033(s8.5V"); fprintf(pp, "\033(s16.6H"); fprintf(pp, "\033&l%df%sC", pagelen, vmi); } @@@ Fin de ./print/print.c echo ./printcap cat >./printcap <<'@@@ Fin de ./printcap' # @(#)printcap 5.3 (Berkeley) 6/30/90 lp|lj|local line printer:\ :lp=/dev/lpa0:sd=/var/spool/lpd:lf=/var/log/lpd-errs:\ :of=/usr/libexec/lpr/hpf:if=/usr/libexec/lpr/hpf:sh:mx#0:pw#80: @@@ Fin de ./printcap exit 0 -- curt mayer curt@toad.com 415-387-0217 home