Printer interface program examples
Jeffery Small
jeff at cjsa.WA.COM
Mon Mar 20 14:35:46 AEST 1989
# This is a shell archive. Remove anything before this line
# then unpack it by saving it in a file and typing "sh file"
# (Files unpacked will be owned by you and have default permissions).
# This archive contains the following files:
# ./README
# ./Quantex.c
# ./Daisy.c
# ./list
# ./Remote
#
if `test ! -s ./README`
then
echo "extracting ./README ..."
sed 's/^X//' > ./README << 'END__of_the__FILE'
XI got a number of requests to post the sample printer interface programs
Xwhich I mentioned in a previous article - so here they are.
X
XThese programs are of no immediate use to anyone since they were written
Xfor my two specific printers and contain a lot of local idiomatic stuff
Xwhich would be "junk" to anyone else. However, I hope they may serve as
Xsome kind of guide and starting point for others who are interested in
Xtackling the task of writing their own interface.
X
XWhat you get:
X
XREADME - This file
X
XQuantex.c - Interface script for the Quantex Model 7065 Dot Matrix printer
X attached to the parallel port. This is a real nice multi-mode
X printer with lots of options. Get out your printer manual and
X find out what codes you need to send to get your printer to
X perform tricks. I can assure you that none of the Quantex codes
X will be anything like what your printer wants.
X
XDaisy.c - Interface script for the Dataproducts DP-20 printer connected to
X the serial port. This is a nasty little 20 cps Daisy Wheel
X printer which has a lot of personality problems. I included this
X script because: (1) It shows control over the serial port which
X differs from the parallel port and (2) this printer emulates a
X lot of the Diablo630 control codes which many people will find
X more familiar - albeit a lot more confusing than the Quantex
X codes.
X
X If you create you own interface script - compile it and install
X it in the /usr/spool/lp/interface directory. Make SURE you
X set the owner to "lp", the group to "other" and mode to "755".
X
Xlist - A Bourne shell script which I use to "list" (ie: send listings)
X of files to the various printers while setting the printer
X options. This script acts as a front-end to the interface
X programs above. It assembles print options and filenames,
X builds a command string in the proper format and then issues
X the lp request. I use this approach because:
X
X 1: It's easy to modify the script when I want to add an option.
X (for example - the option -8ss set everything up to be able
X to print Smart Spreadsheet files in compressed pitch on
X 8-1/2" wide paper - filtering the spreadsheet through
X my DtoU (DOS to UNIX) filter on the way. - Very handy
X type of thing to put into the script.)
X
X 2: It's easier to give the list options then construct the
X lp command string.
X
X 3: I can specify my own desired default behavior.
X
X 4: lp doesn't give you and informative error messages when it
X fails - and I was real sick of that.
X
X Once again, this script is chock full of local stuff (like
X printing on our letterhead) which won't be of any use to you.
X Rip this thing apart and reassemble to your heart's content.
X
XRemote: - In my last posting I also mentioned that remote printing with
X the default scripts does not work properly. If you have two
X UNIX-PCs attached with a serial or phone cable and configure
X one to remote print on the other across the line, lp requests
X work OK until you try to send an option string like:
X
X lp -s -dDaisy -o"lq 12cpi 8lpi" file1 file2
X
X The multiple options get lost during the uucp transfer and I
X could find no way to quote the string to get them to come
X across intact. Thus, I modified the dumb-remote interface
X script to transpose option requests into a string like:
X
X -o lq -o 12cpi -o 8lpi
X
X which works fine. "Remote" shows the modifications required.
X
X
XHope some of you find this info. helpful.
X--
XJeffery Small (206) 485-5596 uw-beaver!uw-nsr!uw-warp
XC. Jeffery Small and Associates !cjsa!jeff
X19112 152nd Ave NE - Woodinville, WA 98072 uunet!nwnexus
END__of_the__FILE
if test `wc -c < ./README` -ne 3811
then
echo "\tWAIT A MINUTE ... Expecting file size of 3811 bytes"
echo "\t but got a file size of `wc -c < ./README` bytes"
echo "\tWARNING ......... Suggest you check file contents."
fi
else
echo "will not over write ./README"
fi
if `test ! -s ./Quantex.c`
then
echo "extracting ./Quantex.c ..."
sed 's/^X//' > ./Quantex.c << 'END__of_the__FILE'
X#ifndef lint
Xstatic char sccsid[] = "@(#) Quantex.c 1.1 3/19/89";
X#endif lint
X
X/************************************************************************/
X/* */
X/* SYNOPSIS */
X/* Quantex id spooler title copies options file1 [ file2 ... ] */
X/* */
X/* ARGUMENTS */
X/* id is: spooler_job_ID (assigned by lp spooler) */
X/* spooler is: spooler_name (typically "lp") */
X/* title is: header_title (assigned with lp -t flag) */
X/* copies is: No. of copies (assigned with lp -n flag) */
X/* options is: print_options (assigned with lp -o flag) */
X/* file1 is: file_name (name of file to be printed) */
X/* file2 ... : file_name(s) (additional files for printing) */
X/* */
X/* DESCRIPTION */
X/* This is the line printer interface for the Quantex Model #7065 */
X/* dot matrix printer. Output is directed to "stdout". It is */
X/* left up to the caller (or calling program) to redirect "stdout" */
X/* to the proper printer port as the lp spooler automatically does.*/
X/* Nevertheless, the knowledge that the printer is hardwired to */
X/* the parallel port is hard-coded into this program in setport(), */
X/* so moving the printer will require modifications to this prog. */
X/* For information related to the serial port, see the Daisy */
X/* interface. */
X/* */
X/* NOTES */
X/* * "id" (argv[1]) and "spooler" (argv[2]) are always ignored. */
X/* * Unknown "option" arguments are silently ignored. */
X/* * Command line arguments have been emperically determined by */
X/* looking at the model interface scripts. In particular, it */
X/* is unclear how argument No. 6 "-raw" is ever set using the */
X/* lp spooler. Therefore, we implement our own "raw" argument */
X/* as a -o option. */
X/* */
X/* BUGS */
X/* * The printer and the lp-driver maintain different "ideas" */
X/* about what top & bottom margins and page length mean. This */
X/* results in the need for "pagelen" & "activelines". (UGH). */
X/* */
X/* INSTALLATION (at least on the 3B1) */
X/* cc -c -O Quantex.c */
X/* ld -s Quantex.o $(SHAREDLIB) -o Quantex */
X/* install -o lp -g other -m 755 Quantex /usr/spool/lp/interface */
X/* */
X/************************************************************************/
X
X#include <stdio.h>
X#include <termio.h>
X#include <string.h>
X#include <sys/lprio.h>
X#include <fcntl.h>
X#include <ctype.h>
X#include <time.h>
X
X#define NULLCHR (char) 0
X#define NULLPTR (char *) 0
X
X#define OFF 0
X#define ON 1
X
X#define PITCH_CNT 5
X
X#define PITCH_10 0
X#define PITCH_12 1
X#define PITCH_13 2
X#define PITCH_15 3
X#define PITCH_17 4
X
X#define PAPER_CNT 3
X
X#define LTRHEAD 0
X#define PAPER_8 1
X#define PAPER_14 2
X
Xstatic char *options; /* points to printing options */
Xstatic short formfeed = ON; /* issue formfeed at end of doc.*/
Xstatic short printhdr = OFF; /* print date & filename header */
Xstatic short pitch; /* horizontal pitch indicator */
Xstatic short paper; /* paper size indicator */
Xstatic short tpmargin; /* top margin lines from top */
Xstatic short bmmargin; /* bottom margin lines from bot */
Xstatic short ltmargin; /* left margin column number */
Xstatic short rtmargin; /* right margin column number */
Xstatic short pagelen; /* length of page in lines */
Xstatic short activelines; /* length of page for lp-driver */
X
Xstatic short maxcol[PITCH_CNT][PAPER_CNT] = { { 76, 80, 136 },
X { 91, 96, 163 },
X { 100, 106, 180 },
X { 114, 120, 204 },
X { 129, 136, 232 } };
Xmain(argc, argv)
X
Xint argc;
Xchar *argv[];
X{
X short copies, i;
X char buf[BUFSIZ], *ctime(), *date, *fgets(), *filename;
X long clock, time();
X void do_opts(), exit(), setprinter();
X FILE *fopen(), *source;
X
X if (argc < 7) {
X (void) fprintf(stderr,
X "%s: Error in argument count. Nothing to print.\n", argv[0]);
X exit(1);
X }
X
X (void) time(&clock);
X date = ctime(&clock);
X
X copies = ( (i = atoi(argv[4])) > 0 ) ? i : 1;
X options = argv[5];
X
X setprinter(); /* set default printer options */
X
X do_opts(); /* set specified print options */
X
X if (strlen(argv[3]) > 0) { /* print title page if specified */
X
X (void) fputs("\n\n\n\n\n\n", stdout);
X (void) fputs("\n\n== Date Printed: =====================", stdout);
X (void) fputs("======================================\n\n", stdout);
X (void) fputs(date, stdout);
X (void) fputs("\n\n======================================", stdout);
X (void) fputs("======================================\n\n", stdout);
X (void) fputs("\n\n== Title: ============================", stdout);
X (void) fputs("======================================\n\n", stdout);
X (void) fputs(argv[3], stdout);
X (void) fputs("\n\n======================================", stdout);
X (void) fputs("======================================\f", stdout);
X }
X
X while (copies--) { /* loop for multiple copies */
X
X if (! strcmp(argv[6], "-raw")) { /* just in case it arrives! */
X formfeed = OFF;
X i = 7;
X } else {
X i = 6;
X }
X
X for ( ; i < argc; i++) { /* loop to process each file */
X
X if ( (source = fopen(argv[i], "r")) == (FILE *) 0 ) {
X (void) fprintf(stderr, "%s: Cannot open file <%s> for reading.\n",
X argv[0], argv[i]);
X } else {
X
X /* a nice little four-line file ID header option */
X
X if (printhdr) {
X if ( (filename = strrchr(argv[i], '/')) == NULLPTR ) {
X filename = argv[i];
X } else {
X filename++; /* get file basename */
X }
X (void) printf("File: %s\nDate: %s\n\n", filename, date);
X }
X
X while ( fgets(buf, BUFSIZ, source) != NULLPTR ) {
X (void) fputs(buf, stdout);
X }
X
X if ( (copies == 0) && (i == (argc - 1)) ) {
X setprinter(); /* reset default printer options */
X }
X
X if (formfeed) {
X (void) putchar('\f'); /* formfeed at end of each file */
X }
X } /* end if-else */
X
X (void) fclose(source);
X } /* end for loop */
X } /* end while */
X exit(0);
X /*NOTREACHED*/
X} /* end main() */
X
X/************************************************************************/
X/* void setprinter () */
X/* */
X/* Initialize the printer to the following default settings: */
X/* */
X/* Option Init. string Description */
X/* ------------ ----------------- ------------------------------- */
X/* nlq ^[[2!p near-letter-quality print speed */
X/* 8in ^[[1!z 8" paper width */
X/* 12cpi ^[[2w 12 char/inch horizontal pitch */
X/* 6lpi ^[[1z 6 lines/inch vertical pitch */
X/* nops ^[[0!y proportional spacing off */
X/* pglen 66 ^[[66t set page length to 66 lines */
X/* lm 1 rm 96 ^[[1;96s margin col: left = 1, rt = 96 */
X/* -- ^[[2g clear all horizontal tabs */
X/* -- ^[[9;17;...;...u set new tab stops every 8 sp. */
X/************************************************************************/
X
Xvoid setprinter()
X{
X extern short activelines, pagelen, paper, pitch;
X extern short tpmargin, bmmargin, ltmargin, rtmargin;
X extern short maxcol[PITCH_CNT][PAPER_CNT];
X
X (void) fputs("\033[2!p\033[1!z\033[2w\033[1z\033[0!y\033[66t\015", stdout);
X (void) fputs("\033[1;96s\033[2g\033[9;17;25;33;41;49;57;65;73u\015", stdout);
X (void) fputs("\033[81;89;97;105;113;121;129;137;145;153;161u\015", stdout);
X (void) fputs("\033[169;177;185;193;201;209;217;225;233;241;249u\015",stdout);
X
X paper = PAPER_8; /* export current settings */
X pitch = PITCH_12;
X tpmargin = 0;
X bmmargin = 0;
X ltmargin = 1;
X rtmargin = 96;
X pagelen = activelines = 66;
X
X return;
X}
X
X/************************************************************************/
X/* void do_opts () */
X/* */
X/* Process all of the options contained in the external *option string */
X/* which was passed to main() as argv[5]. Options are processed in the */
X/* order received so it is up to the caller to insure that the desired */
X/* effect is achieved. (ie: set horiz. pitch prior to setting margins, */
X/* etc.) */
X/************************************************************************/
X
Xvoid do_opts()
X{
X extern short activelines, pagelen, paper, pitch;
X extern short tpmargin, bmmargin, ltmargin, rtmargin;
X extern short printhdr, maxcol[PITCH_CNT][PAPER_CNT];
X char *nextarg(), *op;
X short temp;
X void setport();
X
X while ( *(op = nextarg()) != NULLCHR ) { /* quit on NULL option */
X
X if (! strcmp(op, "lq")) { /* 2-pass LQ - 40cps */
X (void) fputs("\033[3!p", stdout);
X
X } else if (! strcmp(op, "nlq")) { /* 1-pass NLQ - 80cps */
X (void) fputs("\033[2!p", stdout);
X
X } else if (! strcmp(op, "dp")) { /* data-proc. - 250cps */
X (void) fputs("\033[1!p", stdout);
X
X } else if (! strcmp(op, "draft")) { /* draft mode - 300cps */
X (void) fputs("\033[0!p", stdout);
X
X } else if (! strcmp(op, "8in")) { /* 8" wide paper */
X paper = PAPER_8;
X rtmargin = maxcol[pitch][paper];
X (void) printf("\033[1!z\033[;%ds\015", rtmargin);
X
X } else if (! strcmp(op, "14in")) { /* 13-7/8" wide paper */
X paper = PAPER_14;
X rtmargin = maxcol[pitch][paper];
X (void) printf("\033[0!z\033[;%ds\015", rtmargin);
X
X } else if (! strcmp(op, "10cpi")) { /* 10 cpi horiz. pitch */
X pitch = PITCH_10;
X rtmargin = maxcol[pitch][paper];
X (void) printf("\033[1w\033[;%ds\015", rtmargin);
X
X } else if (! strcmp(op, "12cpi")) { /* 12 cpi horiz. pitch */
X pitch = PITCH_12;
X rtmargin = maxcol[pitch][paper];
X (void) printf("\033[2w\033[;%ds\015", rtmargin);
X
X } else if (! strcmp(op, "13cpi")) { /* 13.3 cpi horiz pitch */
X pitch = PITCH_13;
X rtmargin = maxcol[pitch][paper];
X (void) printf("\033[3w\033[;%ds\015", rtmargin);
X
X } else if (! strcmp(op, "15cpi")) { /* 15 cpi horiz. pitch */
X pitch = PITCH_15;
X rtmargin = maxcol[pitch][paper];
X (void) printf("\033[5w\033[;%ds\015", rtmargin);
X
X } else if (! strcmp(op, "17cpi")) { /* 17.1 cpi horiz pitch */
X pitch = PITCH_17;
X rtmargin = maxcol[pitch][paper];
X (void) printf("\033[4w\033[;%ds\015", rtmargin);
X
X } else if (! strcmp(op, "2lpi")) { /* 2 lpi vert. pitch */
X activelines = pagelen = 22;
X (void) printf("\033[4z\033[%dt\015", pagelen);
X
X } else if (! strcmp(op, "3lpi")) { /* 3 lpi vert. pitch */
X activelines = pagelen = 33;
X (void) printf("\033[5z\033[%dt\015", pagelen);
X
X } else if (! strcmp(op, "4lpi")) { /* 4 lpi vert. pitch */
X activelines = pagelen = 44;
X (void) printf("\033[6z\033[%dt\015", pagelen);
X
X } else if (! strcmp(op, "6lpi")) { /* 6 lpi vert. pitch */
X activelines = pagelen = 66;
X (void) printf("\033[1z\033[%dt\015", pagelen);
X
X } else if (! strcmp(op, "8lpi")) { /* 8 lpi vert. pitch */
X activelines = pagelen = 88;
X (void) printf("\033[2z\033[%dt\015", pagelen);
X
X } else if (! strcmp(op, "12lpi")) { /* 12 lpi vert. pitch */
X activelines = pagelen = 132;
X (void) printf("\033[3z\033[%dt\015", pagelen);
X
X } else if (! strcmp(op, "pglen")) { /* overall page length */
X if ( *(op = nextarg()) != NULLCHR ) {
X if ( (temp = atoi(op)) > 0 ) {
X tpmargin = 0; /* setting pglen auto. */
X bmmargin = 0; /* resets tm & bm to 0 */
X activelines = pagelen = temp;
X (void) printf("\033[%dt\015", pagelen);
X }
X }
X
X } else if (! strcmp(op, "tm")) { /* set top margin */
X if ( *(op = nextarg()) != NULLCHR ) {
X if ( ((temp = atoi(op)) > 0) && (temp <= activelines) ) {
X tpmargin = temp;
X (void) printf("\033[%dr\015", tpmargin);
X activelines -= (tpmargin - 1);
X }
X }
X
X } else if (! strcmp(op, "bm")) { /* set bottom margin */
X if ( *(op = nextarg()) != NULLCHR ) {
X if ( ((temp = atoi(op)) > 0) && (temp <= activelines) ) {
X bmmargin = temp;
X (void) printf("\033[;%dr\015", ((pagelen - bmmargin) + 1));
X activelines -= (bmmargin - 1);
X }
X }
X
X } else if (! strcmp(op, "lm")) { /* set left margin & tabs */
X if ( *(op = nextarg()) != NULLCHR ) {
X if ( ((temp = atoi(op)) > 0) && (temp < rtmargin) ) {
X ltmargin = temp;
X (void) printf("\033[%ds\033[2g\015", ltmargin);
X
X for (temp = (ltmargin + 8); temp < 237; temp += 8) {
X (void) printf("\033[%du\015", temp);
X }
X }
X }
X
X } else if (! strcmp(op, "rm")) { /* set right margin */
X if ( *(op = nextarg()) != NULLCHR ) {
X if ( ((temp = atoi(op)) > 0) && (temp > ltmargin) ) {
X rtmargin = (temp <= maxcol[pitch][paper]) ? temp :
X maxcol[pitch][paper];
X (void) printf("\033[;%ds\015", rtmargin);
X }
X }
X
X } else if (! strcmp(op, "cjsa")) { /* set for CJSA ltrhead */
X paper = LTRHEAD;
X pitch = PITCH_12;
X ltmargin = 17;
X rtmargin = maxcol[pitch][paper];
X tpmargin = 12;
X (void) printf("\033[2w\033[17s\033[12r\033[;%ds\015", rtmargin);
X
X } else if (! strcmp(op, "cjsa2")) { /* CJSA ltrhd 2nd shts */
X paper = LTRHEAD;
X pitch = PITCH_12;
X ltmargin = 17;
X rtmargin = maxcol[pitch][paper];
X tpmargin = 1;
X (void) printf("\033[2w\033[17s\033[1r\033[;%ds\015", rtmargin);
X
X } else if (! strcmp(op, "matrix")) { /* set for Matrix ltrhd */
X paper = LTRHEAD;
X pitch = PITCH_12;
X ltmargin = 10;
X rtmargin = maxcol[pitch][paper];
X tpmargin = 12;
X (void) printf("\033[2w\033[10s\033[12r\033[;%ds\015", rtmargin);
X
X } else if (! strcmp(op, "matrix2")) { /* Matrix ltrhd 2nd shts */
X paper = LTRHEAD;
X pitch = PITCH_12;
X ltmargin = 10;
X rtmargin = maxcol[pitch][paper];
X tpmargin = 1;
X (void) printf("\033[2w\033[10s\033[1r\033[;%ds\015", rtmargin);
X
X } else if (! strcmp(op, "ps")) { /* proportional sp. ON */
X (void) fputs("\033[1!y\015", stdout);
X
X } else if (! strcmp(op, "nops")) { /* proportional sp. OFF */
X (void) fputs("\033[0!y\015", stdout);
X
X } else if (! strcmp(op, "header")) { /* print file header */
X printhdr = ON;
X
X } else if (! strcmp(op, "raw")) { /* raw mode: */
X formfeed = OFF; /* do not issue '\f' */
X printhdr = OFF; /* do not print header */
X (void) printf("\033[1;%dr\015", pagelen);
X activelines = pagelen; /* tm = 1, bm = pagelen */
X
X } /* end if-else */
X } /* end while loop */
X
X setport(activelines); /* set ioctl on port */
X
X return;
X} /* end do_opts();
X
X/************************************************************************/
X/* char *nextarg () */
X/* */
X/* Return a pointer to the next option argument located in the static */
X/* *option string. A pointer to a NULL string will indicate the end */
X/* of the options. */
X/************************************************************************/
X
Xchar *nextarg()
X{
X extern char *options;
X static char opbuf[128];
X int i;
X
X while ( isspace(*options) ) { /* skip white space */
X options++;
X }
X
X i = 0;
X while ( (*options != NULLCHR) && (! isspace(*options)) ) {
X opbuf[i++] = *(options++);
X }
X opbuf[i] = NULLCHR;
X
X return(opbuf);
X}
X
X/************************************************************************/
X/* void setport (lines) */
X/* */
X/* Adjust the parallel printer port (/dev/lp - not /dev/rawlp) to */
X/* perform zero indentation, provide a column width of 237 characters */
X/* maximum (for Quantex printing at 17.1 cpi on 13-7/8" paper), and set */
X/* the number of active lines per page to the value specified in the */
X/* "lines" argument. */
X/* */
X/* Note that you can circumvent this requirement if you use /dev/rawlp, */
X/* but this setup makes the use of /dev/lp possible if you want to */
X/* utilize some element of the driver's post-processing control. */
X/************************************************************************/
X
Xvoid setport(lines)
X
Xshort lines;
X{
X struct lprio store;
X
X store.ind = 0;
X store.col = 237;
X store.line = lines;
X
X (void) ioctl(1, LPRSET, &store);
X
X return;
X}
END__of_the__FILE
if test `wc -c < ./Quantex.c` -ne 16046
then
echo "\tWAIT A MINUTE ... Expecting file size of 16046 bytes"
echo "\t but got a file size of `wc -c < ./Quantex.c` bytes"
echo "\tWARNING ......... Suggest you check file contents."
fi
else
echo "will not over write ./Quantex.c"
fi
if `test ! -s ./Daisy.c`
then
echo "extracting ./Daisy.c ..."
sed 's/^X//' > ./Daisy.c << 'END__of_the__FILE'
X#ifndef lint
Xstatic char sccsid[] = "@(#) Daisy.c 1.1 3/19/89";
X#endif lint
X
X/************************************************************************/
X/* */
X/* SYNOPSIS */
X/* Daisy id spooler title copies options file1 [ file2 ... ] */
X/* */
X/* ARGUMENTS */
X/* id is: spooler_job_ID (assigned by lp spooler) */
X/* spooler is: spooler_name (typically "lp") */
X/* title is: header_title (assigned with lp -t flag) */
X/* copies is: No. of copies (assigned with lp -n flag) */
X/* options is: print_options (assigned with lp -o flag) */
X/* file1 is: file_name (name of file to be printed) */
X/* file2 ... : file_name(s) (additional files for printing) */
X/* */
X/* DESCRIPTION */
X/* This is the line printer interface for the Dataproducts DP-20 */
X/* daisy wheel printer. Output is directed to "stdout". It is */
X/* left up to the caller (or calling program) to redirect "stdout" */
X/* to the proper printer port as the lp spooler automatically does.*/
X/* This interface is for a printer connected to a serial port. */
X/* For information related to the parallel port, see the Quantex */
X/* interface. */
X/* */
X/* NOTES */
X/* * The DP-20 is similar to a Diablo630 in its control codes. */
X/* * "id" (argv[1]), "spooler" (argv[2]) and "title" (argv[3]) */
X/* are always ignored. */
X/* * Unknown "option" arguments are silently ignored. */
X/* * Command line arguments have been emperically determined by */
X/* looking at the model interface scripts. In particular, it */
X/* is unclear how argument No. 6 "-raw" is ever set using the */
X/* lp spooler. */
X/* */
X/* BUGS */
X/* * The title option (argv[3]) is not implemented as this would */
X/* generate a title page on a printer which generally will be */
X/* hand fed single sheets of paper. */
X/* * The "bm" bottom margin option is not implemented since this */
X/* printer requires that you index down to the point in order */
X/* to set the margin - ouch - The "Diablo" interface model */
X/* is a particularly stupid implementation and extremely */
X/* non-intuitive. */
X/* * So, after many months of screwing around, we finally figure */
X/* out that the DP-20 can actually keep up with 300 baud! 450 */
X/* was just a little too fast for its sensitive character. */
X/* Junk the sucker... Oh yeah, watch out ... 300 baud is */
X/* hardwired into this programin setport(). */
X/* */
X/* INSTALLATION (at least on the 3B1) */
X/* cc -c -O Daisy.c */
X/* ld -s Daisy.o $(SHAREDLIB) -o Daisy */
X/* install -o lp -g other -m 755 Daisy /usr/spool/lp/interface */
X/* */
X/************************************************************************/
X
X#include <stdio.h>
X#include <termio.h>
X#include <fcntl.h>
X#include <ctype.h>
X
X#define NULLCHR (char) 0
X#define NULLPTR (char *) 0
X
X#define SET(variable, bits) ((variable) |= (bits))
X#define CLEAR(variable, bits) ((variable) &= ~(bits))
X
X#define PITCH_CNT 5
X
X#define PITCH_10 0
X#define PITCH_12 1
X#define PITCH_13 2
X#define PITCH_15 3
X#define PITCH_17 4
X
X#define PAPER_CNT 3
X
X#define LTRHEAD 0
X#define PAPER_8 1
X#define PAPER_14 2
X
X#define RAW 0
X#define NORMAL 1
X#define SPEED 2
X
Xstatic char *options; /* points to printing options */
Xstatic short pitch; /* horizontal pitch indicator */
Xstatic short paper; /* paper size indicator */
Xstatic short rtmargin; /* right margin column number */
X
Xstatic short maxcol[PITCH_CNT][PAPER_CNT] = { { 76, 80, 136 },
X { 91, 96, 163 },
X { 100, 106, 180 },
X { 114, 120, 204 },
X { 129, 136, 232 } };
X
Xstatic float pval[PITCH_CNT] = { 10.0, 12.0, 13.3, 15.0, 17.1 };
X
Xstatic char hmi_n[PITCH_CNT] = { '\015', '\013', '\012', '\011', '\010' };
X
Xmain(argc, argv)
X
Xint argc;
Xchar *argv[];
X{
X short copies, i;
X char buf[BUFSIZ];
X void do_opts(), exit(), setport(), setprinter();
X FILE *fopen(), *source;
X
X setport(SPEED); /* set port speed to 300 baud */
X
X if (argc < 7) {
X (void) fprintf(stderr,
X "%s: Error in argument count. Nothing to print.\n", argv[0]);
X exit(1);
X }
X
X copies = ( (i = atoi(argv[4])) > 0 ) ? i : 1;
X options = argv[5];
X
X setport(RAW); /* turn off port output processing */
X
X setprinter(); /* set default printer options */
X
X do_opts(); /* set specified print options */
X
X setport(NORMAL); /* turn on port output processing */
X
X while (copies--) { /* loop for multiple copies */
X
X for (i = 6 ; i < argc; i++) { /* loop to process each file */
X
X if ( (source = fopen(argv[i], "r")) == (FILE *) 0 ) {
X (void) fprintf(stderr, "%s: Cannot open file <%s> for reading.\n",
X argv[0], argv[i]);
X } else {
X
X (void) putchar('\r'); /* insure carriage is at left margin */
X
X while ( fgets(buf, BUFSIZ, source) != NULLPTR ) {
X (void) fputs(buf, stdout);
X }
X (void) putchar('\f'); /* formfeed at end of each file */
X } /* end if-else */
X
X (void) fclose(source);
X } /* end for loop */
X } /* end while */
X
X setport(RAW); /* turn off port output processing */
X setprinter(); /* reset default printer options */
X setport(NORMAL); /* turn on port output processing */
X (void) putchar('\r'); /* leave carriage at left margin */
X
X exit(0);
X /*NOTREACHED*/
X} /* end main() */
X
X/************************************************************************/
X/* void setport (type) */
X/* */
X/* Adjust the serial printer port (stdout set by lp spooler) to the */
X/* appropriate values. If "type" is SPEED, the required 300-baud rate */
X/* is established. If "type" is RAW, then output post-processing is */
X/* disabled so that non-printing control codes can be issued to the */
X/* printer. If "type" is NORMAL, then xon/xoff flow control, tab, */
X/* NL/CR and output post-processing is re-enabled in preparation of */
X/* sending the test file(s) to the printer. */
X/* */
X/* The RAW mode is required while sending control-codes or else the */
X/* embeded tabs '\011' and newlines '\012' will be converted to spaces/ */
X/* carriage-returns and the control functions will not be implemented. */
X/************************************************************************/
X
Xvoid setport(type)
X
Xint type;
X{
X struct termio port;
X int fd;
X
X fd = dup(1);
X
X (void) ioctl(fd, TCGETA, &port);
X
X switch (type) {
X
X case SPEED:
X CLEAR(port.c_cflag, CBAUD|HUPCL);
X SET(port.c_cflag, B300|CLOCAL);
X break;
X
X case RAW:
X CLEAR(port.c_oflag, OPOST);
X break;
X
X case NORMAL:
X SET(port.c_iflag, IXON);
X SET(port.c_oflag, OPOST|ONLCR|TAB3);
X break;
X }
X
X (void) ioctl(fd, TCSETAW, &port);
X return;
X}
X
X/************************************************************************/
X/* void setprinter () */
X/* */
X/* Initialize the printer to the following default settings: */
X/* */
X/* Option Init. string Description */
X/* ------------ ----------------- ------------------------------- */
X/* -- ^[2 clear all horizontal tabs */
X/* 12cpi ^[^_{11} 12 char/inch horizontal pitch */
X/* lm 1 ^[\t{1}^[9 set left margin to column 1 */
X/* rm 96 ^[\t{96}^[0 set right margin to column 96 */
X/* -- ^[C clear top and bottom margins */
X/************************************************************************/
X
Xvoid setprinter()
X{
X extern short paper, pitch, rtmargin;
X extern short maxcol[PITCH_CNT][PAPER_CNT];
X
X (void) fputs("\033\062\033\037\013\033\011\001\033\071", stdout);
X (void) fputs("\033\011\140\033\060\033\103", stdout);
X
X paper = PAPER_8; /* export current settings */
X pitch = PITCH_12;
X rtmargin = maxcol[pitch][paper];
X
X return;
X}
X
X/************************************************************************/
X/* void do_opts () */
X/* */
X/* Process all of the options contained in the external *option string */
X/* which was passed to main() as argv[5]. Options are processed in the */
X/* order received so it is up to the caller to insure that the desired */
X/* effect is achieved. (ie: set horiz. pitch prior to setting margins, */
X/* etc.) */
X/************************************************************************/
X
Xvoid do_opts()
X{
X extern short paper, pitch, rtmargin;
X extern char hmi_n[PITCH_CNT];
X extern float pval[PITCH_CNT];
X extern short maxcol[PITCH_CNT][PAPER_CNT];
X char Bchar, *nextarg(), *op;
X short col, line;
X
X while ( *(op = nextarg()) != NULLCHR ) { /* quit on NULL option */
X
X if (! strcmp(op, "10cpi")) { /* 10 cpi horiz. pitch */
X pitch = PITCH_10;
X rtmargin = maxcol[pitch][paper];
X (void) fputs("\033\037\015", stdout);
X
X } else if (! strcmp(op, "12cpi")) { /* 12 cpi horiz. pitch */
X pitch = PITCH_12;
X rtmargin = maxcol[pitch][paper];
X (void) fputs("\033\037\013", stdout);
X
X } else if (! strcmp(op, "13cpi")) { /* 13.3 cpi horiz pitch */
X pitch = PITCH_13;
X rtmargin = maxcol[pitch][paper];
X (void) fputs("\033\037\012", stdout);
X
X } else if (! strcmp(op, "15cpi")) { /* 15 cpi horiz. pitch */
X pitch = PITCH_15;
X rtmargin = maxcol[pitch][paper];
X (void) fputs("\033\037\011", stdout);
X
X } else if (! strcmp(op, "17cpi")) { /* 17.1 cpi horiz pitch */
X pitch = PITCH_17;
X rtmargin = maxcol[pitch][paper];
X (void) fputs("\033\037\010", stdout);
X
X } else if (! strcmp(op, "tm")) { /* set top margin */
X if ( *(op = nextarg()) != NULLCHR ) {
X if ( (line = atoi(op)) > 0 ) {
X while ( line-- ) {
X (void) putchar('\n');
X }
X (void) fputs("\033T", stdout);
X }
X }
X
X /* DP-20 can't take ascii val. */
X /* over 126! - hunk of junk! */
X } else if (! strcmp(op, "lm")) {
X if ( *(op = nextarg()) != NULLCHR ) {
X if ( ((col = atoi(op)) > 0) && (col < rtmargin)
X && (col <= 126) ) {
X Bchar = (char) col;
X (void) fputs("\033\011", stdout);
X (void) fwrite(&Bchar, sizeof(Bchar), 1, stdout);
X (void) fputs("\033\071", stdout);
X }
X }
X
X } else if (! strcmp(op, "rm")) { /* set right margin */
X if ( *(op = nextarg()) != NULLCHR ) {
X if ( (col = atoi(op)) > 0 ) {
X rtmargin = (col <= maxcol[pitch][paper]) ? col :
X maxcol[pitch][paper];
X col = (((rtmargin/pval[pitch]) * 4.0) + 0.85);
X Bchar = (char) col;
X (void) fputs("\033\037\037\033\011", stdout);
X (void) fwrite(&Bchar, sizeof(Bchar), 1, stdout);
X (void) fputs("\033\060\033\037", stdout);
X (void) fwrite(&hmi_n[pitch], sizeof(hmi_n[pitch]), 1, stdout);
X }
X }
X
X } else if ( (! strcmp(op, "cjsa")) || /* set for CJSA ltrhead */
X (! strcmp(op, "cjsa2")) ) {
X paper = LTRHEAD;
X pitch = PITCH_12;
X rtmargin = maxcol[pitch][paper];
X (void) fputs("\033\103\033\037\013", stdout);
X (void) fputs("\033\011\014\033\071\033\011\133\033\060", stdout);
X
X } else if ( (! strcmp(op, "matrix")) || /* set for Matrix ltrhd */
X (! strcmp(op, "matrix2")) ) {
X paper = LTRHEAD;
X pitch = PITCH_12;
X rtmargin = maxcol[pitch][paper];
X (void) fputs("\033\103\033\037\013", stdout);
X (void) fputs("\033\011\001\033\071\033\011\133\033\060", stdout);
X
X } else if (! strcmp(op, "8in")) { /* 8" wide paper */
X paper = PAPER_8;
X rtmargin = maxcol[pitch][paper];
X (void) fputs("\033\037\037\033\011\041\033\060\033\037", stdout);
X (void) fwrite(&hmi_n[pitch], sizeof(hmi_n[pitch]), 1, stdout);
X
X } else if (! strcmp(op, "14in")) { /* 13-7/8" wide paper */
X paper = PAPER_14;
X rtmargin = maxcol[pitch][paper];
X (void) fputs("\033\037\037\033\011\067\033\060\033\037", stdout);
X (void) fwrite(&hmi_n[pitch], sizeof(hmi_n[pitch]), 1, stdout);
X
X } else if (! strcmp(op, "ps")) { /* proportional sp. ON */
X (void) fputs("\033P", stdout);
X
X } else if (! strcmp(op, "nops")) { /* proportional sp. OFF */
X (void) fputs("\033Q", stdout);
X
X } /* end if-else */
X } /* end while loop */
X
X return;
X} /* end do_opts();
X
X/************************************************************************/
X/* char *nextarg () */
X/* */
X/* Return a pointer to the next option argument located in the static */
X/* *option string. A pointer to a NULL string will indicate the end */
X/* of the options. */
X/************************************************************************/
X
Xchar *nextarg()
X{
X extern char *options;
X static char opbuf[128];
X int i;
X
X while ( isspace(*options) ) { /* skip white space */
X options++;
X }
X
X i = 0;
X while ( (*options != NULLCHR) && (! isspace(*options)) ) {
X opbuf[i++] = *(options++);
X }
X opbuf[i] = NULLCHR;
X
X return(opbuf);
X}
END__of_the__FILE
if test `wc -c < ./Daisy.c` -ne 12876
then
echo "\tWAIT A MINUTE ... Expecting file size of 12876 bytes"
echo "\t but got a file size of `wc -c < ./Daisy.c` bytes"
echo "\tWARNING ......... Suggest you check file contents."
fi
else
echo "will not over write ./Daisy.c"
fi
if `test ! -s ./list`
then
echo "extracting ./list ..."
sed 's/^X//' > ./list << 'END__of_the__FILE'
X#! /bin/sh
X#
X# sccsid = "@(#) list 1.1 3/19/89"
X
X#########################################################################
X# #
X#SYNOPSIS #
X# list [-options] file1 [ file2 ... ] #
X# #
X# DESCRIPTION #
X# This Bourne shell script acts as a front end to the printer #
X# interface programs written for the Quantex (#7065) and Daisy #
X# (Dataproducts DP-20) printers. List makes "listings" of the #
X# specified files, setting the appropriate printer interface #
X# options in their correct order. Default values have been #
X# assigned, all of which may be overridden. #
X# #
X# OPTIONS #
X# See the case statment below. Note that options must be #
X# seperated by space including options which require an argument. #
X# eg: #
X# #
X# list -lq -14in -co 2 -15cpi -8lpi -lm 10 -rm 72 /etc/passwd #
X# #
X# BUGS #
X# You could build all this into the printer interface programs #
X# but its much easier to keep modifying this script. #
X# #
X#########################################################################
X
XTMP=/tmp/LIST$$
X
Xtrap "/bin/rm -f $TMP ; trap 0; exit 1" 1 2 3 15
Xtrap "/bin/rm -f $TMP ; exit 0" 0
X
XDTOU=""
XOPTS=""
XFILES=""
XPTR="Quantex"
XSPEED="nlq"
XPAPER="8in"
XHPITCH="12cpi"
XVPITCH="6lpi"
XPROPSP="OFF"
XPGLEN="66"
XTM="3"
XBM="3"
XLM="10"
XRM="96"
XHEADER="OFF"
XLTRHEAD=""
XCOPIES="1"
X
Xif [ "$#" = "0" ]
Xthen
X echo "usage: $0 [-options] file1 [ file2 ... ]"
X exit 1
Xfi
X
Xwhile [ $# -gt 0 ]
Xdo
X case $1 in
X -quantex | -Quantex | -QUANTEX) # Quantex printer
X PTR="Quantex";;
X -daisy | -Daisy | -DAISY) # Daisy wheel printer
X PTR="Daisy"
X TM="0";;
X -epson | -Epson | -EPSON) # Epson mode - Quantex printer
X PTR="Epson";;
X -diablo* | -Diablo* | -DIABLO*) # Diablo interface to Daisy
X PTR="Diablo630"
X TM="0";;
X -lq) # 2-pass LQ print
X SPEED="lq";;
X -nlq) # Single pass NLQ print
X SPEED="nlq";;
X -dp) # Data-processing print
X SPEED="dp";;
X -draft) # Draft print (300 cps)
X SPEED="draft";;
X -8in) # 8" wide paper
X RM="136"
X PAPER="8in";;
X -14in) # 13-7/8" wide paper
X RM="232"
X PAPER="14in";;
X -10cpi) # 10 cpi horizontal pitch
X if [ "$PAPER" = "8in" ] ; then
X RM=80
X else
X RM=136
X fi
X HPITCH="10cpi";;
X -12cpi) # 12 cpi horizontal pitch
X if [ "$PAPER" = "8in" ] ; then
X RM=96
X else
X RM=163
X fi
X HPITCH="12cpi";;
X -13cpi) # 13 cpi horizontal pitch
X if [ "$PAPER" = "8in" ] ; then
X RM=104
X else
X RM=176
X fi
X HPITCH="13cpi";;
X -15cpi) # 15 cpi horizontal pitch
X if [ "$PAPER" = "8in" ] ; then
X RM=120
X else
X RM=204
X fi
X HPITCH="15cpi";;
X -17cpi) # 17 cpi horizontal pitch
X if [ "$PAPER" = "8in" ] ; then
X RM=136
X else
X RM=232
X fi
X HPITCH="17cpi";;
X -2lpi) # 2 lpi vertical pitch
X PGLEN="22"
X VPITCH="2lpi";;
X -3lpi) # 3 lpi vertical pitch
X PGLEN="33"
X VPITCH="3lpi";;
X -4lpi) # 4 lpi vertical pitch
X PGLEN="44"
X VPITCH="4lpi";;
X -6lpi) # 6 lpi vertical pitch
X PGLEN="66"
X VPITCH="6lpi";;
X -8lpi) # 8 lpi vertical pitch
X PGLEN="88"
X VPITCH="8lpi";;
X -12lpi) # 12 lpi vertical pitch
X PGLEN="132"
X VPITCH="12lpi";;
X -ps) # Proportional spacing on
X PROPSP="ON";;
X -pglen) # Set page length
X PGLEN="$2"
X TM="1"
X BM="1"
X shift;;
X -tm) # Set top margin
X TM="$2"
X shift;;
X -bm) # Set bottom margin
X BM="$2"
X shift;;
X -lm) # Set left margin
X LM="$2"
X shift;;
X -rm) # Set right margin
X RM="$2"
X shift;;
X -h | -header) # Turn header printing on
X HEADER="ON";;
X -noh | -noheader) # Turn header printing off
X HEADER="OFF";;
X -noi | -noindent) # Turn indenting off
X LM="1";;
X -novm) # Turn vert margin off
X TM="1"
X BM="1";;
X -cjsa | -CJSA) # Set for CJSA letterhead
X LTRHEAD="cjsa";;
X -cjsa2 | -CJSA2) # CJSA letterhead 2nd sheets
X LTRHEAD="cjsa2";;
X -matrix | -Matrix | -MATRIX) # Set for Matrix letterhead
X LTRHEAD="matrix";;
X -matrix2 | -Matrix2 | -MATRIX2) # Matrix letterhead 2nd sheets
X LTRHEAD="matrix2";;
X -copies | -co | -c | -n) # Number of copies to print
X COPIES="$2"
X shift;;
X -raw) # No trailing formfeeds
X TM="1"
X BM="1"
X HEADER="OFF"
X LTRHEAD=""
X OPTS="${OPTS}raw ";;
X -8ss) # Printing Smart Spreadsheet
X DTOU="YES"
X SPEED="dp"
X PAPER="8in"
X HPITCH="17cpi"
X VPITCH="8lpi"
X PGLEN="88"
X TM="1"
X BM="1"
X LM="10"
X RM="136"
X HEADER="OFF"
X PROPSP="OFF"
X OPTS="${OPTS}raw ";;
X -*) # Bad argument
X echo "$0: '"$1"' Unknown argument!"
X exit 2;;
X *) # Should be a file argument
X if test -r "$1"
X then
X if [ "$DTOU" = "YES" ]
X then
X DtoU $1 $TMP # DtoU is a DOS to UNIX
X if [ "$?" != "0" ] # filter to strip ^Ms & ^Zs
X then
X echo "$0: Cannot 'DtoU' this file!"
X else
X mv $TMP $1
X if [ "$?" != "0" ]
X then
X echo "$0: Cannot 'DtoU' this file!"
X fi
X fi
X fi
X
X FILES="${FILES}$1 "
X else
X echo "$0: Can not open file $1"
X fi
X ;;
X esac
X shift
Xdone
X
Xif [ "x${FILES}" != "x" ] # Are there files to print?
Xthen
X
X if [ "x${LTRHEAD}" != "x" ] # If letterhead specified ...
X then
X OPTS="${OPTS}$SPEED $LTRHEAD " # put OPTS in proper order
X else
X OPTS="${OPTS}$SPEED $PAPER $HPITCH $VPITCH pglen $PGLEN "
X OPTS="${OPTS}tm $TM bm $BM lm $LM rm $RM "
X
X if [ "PROPSP" = "ON" ]
X then
X OPTS="${OPTS}ps "
X fi
X
X if [ "$HEADER" = "ON" ]
X then
X OPTS="${OPTS}header "
X fi
X fi
X
X lp -s -d$PTR -n$COPIES -o"$OPTS" $FILES # Spool file(s)
X
X exit 0
Xelse
X echo "$0: No file(s) specified for printing."
X exit 3
Xfi
END__of_the__FILE
if test `wc -c < ./list` -ne 5633
then
echo "\tWAIT A MINUTE ... Expecting file size of 5633 bytes"
echo "\t but got a file size of `wc -c < ./list` bytes"
echo "\tWARNING ......... Suggest you check file contents."
fi
else
echo "will not over write ./list"
fi
if `test ! -s ./Remote`
then
echo "extracting ./Remote ..."
sed 's/^X//' > ./Remote << 'END__of_the__FILE'
X#sccs "@(#)lp/model:dumb-remote 1.7"
X#
X# Modified by Jeffery Small on 09-15-88 to properly handle -o arguments
X#
X#
X# lp interface for printer in remote mode
X#
X#
X. /usr/spool/lp/interface/remote
XTITLE=$3
XCOPIES=$4
XOPTS=$5
XRAW=$6
Xshift; shift; shift; shift; shift
X
Xif [ "$RAW" = "-raw" ]
Xthen
X PTYPE=${PTYPE}_R
X shift
X for F in $*
X do
X cp $F /usr/spool/uucppublic/`basename $F`.g
X FILES=$FILES"/usr/spool/uucppublic/`basename $F`.g "
X done
Xelse
X for F in $*
X do
X cp $F /usr/spool/uucppublic/`basename $F`.:
X FILES=$FILES"/usr/spool/uucppublic/`basename $F`.: "
X done
Xfi
X
XOPTIONS=""
Xfor i in $OPTS
Xdo
X OPTIONS=$OPTIONS"-o$i "
Xdone
X
Xuux -r -n "$MACHINE!lp -d$PTYPE -t$TITLE $OPTIONS -n$COPIES $FILES"
Xuucp $FILES $MACHINE!/usr/spool/uucppublic
Xexit 0
END__of_the__FILE
if test `wc -c < ./Remote` -ne 754
then
echo "\tWAIT A MINUTE ... Expecting file size of 754 bytes"
echo "\t but got a file size of `wc -c < ./Remote` bytes"
echo "\tWARNING ......... Suggest you check file contents."
fi
else
echo "will not over write ./Remote"
fi
echo "Finished archive 1 of 1"
# if you want to concatenate archives, remove anything after this line
exit
More information about the Unix-pc.sources
mailing list