chip@vector.Dallas.TX.US (Chip Rosenthal) (08/24/89)
Oh no...another printer underlining filter!! "Colpr" performs a number of filtering functions useful in printer interfaces. These include: - backspace to overstrike translation - long line folding/truncation - newline to CR/LF translation - 8-bit character generation There are probably a zillion programs in the comp.sources.all archives which perform the first three functions. Your system probably already has one or more of them. However, the last feature gives you a way to squeeze 8-bit graphic characters out of utilities which only produce 7-bit characters, e.g. old nroff. I use this feature with the SCO XENIX nroff to gain access to the full character set of the HP LaserJet printer. I mentioned my "tablj" nroff driver table for the LaserJet in comp.unix.xenix recently, and had several requests for it. Well, you need "colpr" first and here it is. With any sort of luck, I will try to get the "tablj" stuff out in a week or so. --- cut here ----------------------------------------------------------------- #! /bin/sh # this is a "shar" archive - run through "/bin/sh" to extract 4 files: # README colpr.c colpr.man Makefile # Wrapped by bin@vector on Wed Aug 23 23:04:59 CDT 1989 # Unpacking this archive requires: sed test wc (possibly mkdir) # Existing files will not be clobbered unless "-c" is specified on the cmd line. if test -f README -a "$1" != "-c" ; then echo "README: file exists - will not be overwritten" else echo "x - README (file 1 of 4, 1045 chars)" sed -e 's/^X//' << 'END_OF_FILE_README' > README XOh no...another printer underlining filter!! X X"Colpr" performs a number of filtering functions useful in printer Xinterfaces. These include: X X - backspace to overstrike translation X - long line folding/truncation X - newline to CR/LF translation X - 8-bit character generation X XThere are probably a zillion programs in the comp.sources.all archives Xwhich perform the first three functions. Your system probably already Xhas one or more of them. However, the last feature gives you a way to Xsqueeze 8-bit graphic characters out of utilities which only produce X7-bit characters, e.g. old nroff. X XI use this feature with the SCO XENIX nroff to gain access to the full Xcharacter set of the HP LaserJet printer. I mentioned my "tablj" nroff Xdriver table for the LaserJet in comp.unix.xenix recently, and had several Xrequests for it. X XWell, you need "colpr" first and here it is. With any sort of luck, I Xwill try to get the "tablj" stuff out in a week or so. X XChip Rosenthal X<chip@vector.Dallas.TX.US> X X@(#) README 1.1 89/08/23 22:58:01 END_OF_FILE_README size="`wc -c < README`" if test 1045 -ne "$size" ; then echo "README: extraction error - got $size chars" fi fi if test -f colpr.c -a "$1" != "-c" ; then echo "colpr.c: file exists - will not be overwritten" else echo "x - colpr.c (file 2 of 4, 8969 chars)" sed -e 's/^X//' << 'END_OF_FILE_colpr.c' > colpr.c X/* @(#) colpr.c 1.1 89/08/23 22:58:01 X * X * colpr - general printer output filter X * X * Wed Aug 23 22:17:46 1989 - Chip Rosenthal <chip@vector.Dallas.TX.US> X * Consolidation and cleanup for net release to alt.sources. X * Fri Dec 23 02:19:24 CST 1988 - C. Rosenthal (chip@vector.uucp) X * Original composition. X */ X X#include <stdio.h> X#include <ctype.h> X X#ifndef LINT Xstatic char SCCSID[] = "@(#) colpr.c 1.1 89/08/23 22:58:01"; X#endif X X#ifdef M_XENIX X# undef NULL X# define NULL 0 X#endif X X#define USAGE "usage: %s [-bng] [-t cols] [-f cols] [file ...]\n" X X#define BUFLEN 1024 /* maximum output line length */ X#define MAXOVER 10 /* maximum number of overstrike passes */ X#define TABSTOP 8 /* columns between tabstops */ X#define GRAPHCHAR '\177' /* special char to set MSB of next char */ X#define TRUE 1 X#define FALSE 0 X X/*define NO_INLINE_NEXTCOL /* define to suppress Nextcol() macro */ X X X/* X * Macro to calculate next tabstop from current column. Will become a X * static procedure if you've got strange tabstops. X */ X#if TABSTOP == 8 X# define Tabstop(COL) ( ((COL)&(~07)) + 8 ) X#else X static int Tabstop(COL) X int COL; X { X while ( ++COL % TABSTOP != 0 ) ; X return COL; X } X#endif X X X/* X * Macro to figure out where the column counter advances to. It is inlined X * for speed. If you or your compiler don't like that, you can define X * "NO_INLINE_NEXTCOL" to make it a static procedure. X */ X#ifndef NO_INLINE_NEXTCOL X# define Nextcol(COL,CHAR) \ X ( (CHAR) == '\b' ? ( (COL)>0 ? (COL)-1 : 0 ) : \ X ( (CHAR) == '\t' ? Tabstop(COL) : \ X ( (CHAR) == '\r' ? 0 : \ X ( (CHAR) == '\n' ? 0 : \ X (COL)+1 \ X ) \ X ) \ X ) \ X ) X#else X static int Nextcol(COL,CHAR) X int COL, CHAR; X { X switch ( CHAR ) { X case '\b': return ( (COL)>0 ? (COL)-1 : 0 ); X case '\t': return Tabstop(COL); X case '\r': return 0; X case '\n': return 0; X default: return COL+1; X } X } X#endif X X X/* X * Global configuration settings. X */ Xenum { NORMAL, FOLD, TRUNCATE } Mode_output; /* processing mode */ Xint Mode_backspace; /* convert backspaces to overstrike passes? */ Xint Mode_newline; /* convert NL to CR/LF? */ Xint Mode_graphchar; /* convert GRAPHCHAR sequence to 8-bit char? */ Xint Num_cols; /* max line width for fold/truncate */ X X X/* X * End of line terminator X */ Xchar *Newline_str; /* will be either "\r\n" or "\n". */ X X X/* X * Global printer overstrike buffers. X */ Xchar Passbuf[MAXOVER][BUFLEN]; X X Xvoid proc_line(); /* Process one line of text. */ Xint xlate_backspace(); /* Generate overstrike passes from backspaces. */ Xvoid out_buffer(); /* Output multiple overstrike passes. */ Xvoid out_line(); /* Output a line of text. */ X X Xmain(argc,argv) Xint argc; Xchar *argv[]; X{ X int i; X FILE *fp; X static char inbuf[BUFLEN]; X extern int optind; X extern char *optarg; X X /* X * Initialize. X */ X Num_cols = BUFLEN+1; /* don't truncate or file */ X Mode_output = NORMAL; /* don't truncate or fold */ X Mode_backspace = FALSE; /* leave backspaces as is */ X Mode_newline = FALSE; /* leave NL character as is */ X Mode_graphchar = FALSE; /* leave GRAPHCHAR character as is */ X X /* X * Process command line options. X */ X while ( (i=getopt(argc,argv,"bngt:f:")) != EOF ) { X switch ( i ) { X case 'b': Mode_backspace = TRUE; break; X case 'n': Mode_newline = TRUE; break; X case 'g': Mode_graphchar = TRUE; break; X case 't': Mode_output = TRUNCATE; Num_cols = atoi(optarg); break; X case 'f': Mode_output = FOLD; Num_cols = atoi(optarg); break; X default: fprintf(stderr,USAGE,argv[0]); exit(1); X } X } X if ( Mode_output != NORMAL && (Num_cols < 10 || Num_cols > BUFLEN) ) { X fprintf(stderr,"%s: bad line width specified\n",argv[0]); X exit(1); X } X X /* X * Select the proper line terminator. X */ X Newline_str = ( Mode_newline ? "\r\n" : "\n" ); X X /* X * With no other arguments, filter stdin and exit. X */ X if ( argc-optind == 0 ) { X while ( fgets(inbuf,sizeof(inbuf),stdin) != (char *) NULL ) X proc_line(inbuf); X exit(0); X } X X /* X * Filter each file. X */ X for ( i = optind ; i < argc ; ++i ) { X if ( (fp=fopen(argv[i],"r")) == (FILE *) NULL ) { X perror(argv[i]); X exit(1); X } X while ( fgets(inbuf,sizeof(inbuf),fp) != (char *) NULL ) X proc_line(inbuf); X (void) fclose(fp); X } X X exit(0); X /*NOTREACHED*/ X} X X X/* X * proc_line() - Process one line of text. X * A line is passed to this procedure to be munched on and then printed. X */ Xvoid proc_line(bufp) Xregister char *bufp; X{ X register char *c1, *c2; X X /* X * Strip trailing spaces, tabs, and newline. X */ X for ( c1 = bufp + strlen(bufp) - 1 ; c1 >= bufp && isspace(*c1) ; --c1 ) ; X *(c1+1) = '\0'; X X /* X * If the line is blank, then just print a newline and return. X */ X if ( *bufp == '\0' ) { X fputs(Newline_str,stdout); X return; X } X X /* X * Perform 8-bit character translations. Every instance of the X * two-character sequence {GRAPHCHAR,x} is replaced with the single X * character (x|0200). X */ X if ( Mode_graphchar ) { X for ( c1 = c2 = bufp ; *c1 != '\0' ; ++c1, ++c2 ) { X *c2 = ( X ( *c1 == GRAPHCHAR && *++c1 != GRAPHCHAR ) ? X ( *c1 | 0200 ) : X *c1 X ); X } X *c2 = '\0'; X } X X /* X * Print out the line. If we are doing backspace translation then first X * convert the line to multiple overstrike passes. If we aren't doing this X * translation then just print out the line. If line folding or truncation X * are required, it will be handled in the output procedure. X */ X if ( Mode_backspace ) { X out_buffer(xlate_backspace(bufp)); X } else { X out_line(bufp); X } X X} X X X X/* X * xlate_backspace - Generate overstrike passes from backspaces. X * The line is stored in global character array "Passbuf[][]". The text X * for printhead pass "n" is stored in "Passbuf[n]", where 0<=n<=MAXOVER-1. X * The number of printhead passes required to print this line (i.e. the X * number of "Passbuf[]" buffers) is returned. X */ Xint xlate_backspace(bufp) Xregister char *bufp; X{ X int bufused = -1; /* highest overstrike buffer used */ X register int col; /* current printhead column number */ X register int i; X int j; X char *c; X X /* X * Go through each character in the line. X */ X for ( col = 0 ; *bufp != '\0' ; ++bufp ) { X X /* X * Process non-printing, column movement characters. X */ X if ( isspace(*bufp) || *bufp == '\b' ) { X col = Nextcol(col,*bufp); X continue; X } X X /* X * Make sure we can store this character. X */ X if ( col > BUFLEN-2 ) { X fprintf(stderr,"panic - exceeded %d char buffer limit\n",BUFLEN-1); X exit(1); X } X X /* X * Find a buffer where this column is unused. Allocate additional X * overstrike buffers as required. Stick the character there. X */ X for ( i = 0 ; i < MAXOVER ; ++i ) { X while ( i >= bufused ) X (void) memset(Passbuf[++bufused],BUFLEN,' '); X if ( Passbuf[i][col] == ' ' ) X break; X } X if ( i < MAXOVER ) X Passbuf[i][col++] = *bufp; X X } X X /* X * Trim trailing space and terminate the overstrike buffers. X */ X for ( i = 0 ; i <= bufused ; ++i ) { X for ( c=Passbuf[i]+BUFLEN-1, j=BUFLEN ; *c == ' ' && j > 0 ; --c, --j) ; X *(c+1) = '\0'; X } X X return bufused; X} X X X/* X * out_line - Output a line of text. X * The specified line of text is printed. Line truncation or folding X * are performed if required. X */ Xvoid out_line(bufp) Xregister char *bufp; X{ X int col; X X switch ( Mode_output ) { X X case NORMAL: X fputs(bufp,stdout); X break; X X case TRUNCATE: X for ( col = 0 ; *bufp != '\0' && col < Num_cols ; ++bufp ) { X putchar(*bufp); X col = Nextcol(col,*bufp); X } X break; X X case FOLD: X for ( col = 0 ; *bufp != '\0' ; ++bufp ) { X if ( col >= Num_cols ) { X fputs(Newline_str,stdout); X col = 0; X } X putchar(*bufp); X col = Nextcol(col,*bufp); X } X break; X X } X X fputs(Newline_str,stdout); X} X X X/* X * out_buffer - Output text as multiple overstrike passes. X * Output the text stored in the "Passbuf[]" overstrike buffers. Line X * truncation or folding are performed if required. X */ Xvoid out_buffer(numbufs) Xint numbufs; X{ X char *c; X int i, n; X extern char *strcpy(); X X switch ( Mode_output ) { X X case TRUNCATE: X for ( i = 0 ; i <= numbufs ; ++i ) X Passbuf[i][Num_cols] = '\0'; X /*FALLTHRU*/ X X case NORMAL: X for ( i = 0 ; i <= numbufs ; ++i ) { X fputs(Passbuf[i],stdout); X fputs( ( i == numbufs ? Newline_str : "\r" ) ,stdout); X } X break; X X case FOLD: X do { X for ( i = 0 ; i <= numbufs ; ++i ) { X for ( X c = Passbuf[i], n = 0 ; X n < Num_cols && *c != '\0' && *c != '\r' && *c != '\n' ; X ++c, ++n X ) { X putchar(*c); X } X (void) strcpy(Passbuf[i],c); X fputs( ( i == numbufs ? Newline_str : "\r" ) ,stdout); X } X } while ( Passbuf[0][0] != '\0' ); X break; X X } X X} END_OF_FILE_colpr.c size="`wc -c < colpr.c`" if test 8969 -ne "$size" ; then echo "colpr.c: extraction error - got $size chars" fi fi if test -f colpr.man -a "$1" != "-c" ; then echo "colpr.man: file exists - will not be overwritten" else echo "x - colpr.man (file 3 of 4, 2204 chars)" sed -e 's/^X//' << 'END_OF_FILE_colpr.man' > colpr.man X''' @(#) colpr.man 1.1 89/08/23 22:58:22 X''' X''' Wed Aug 23 22:17:46 1989 - Chip Rosenthal <chip@vector.Dallas.TX.US> X''' Consolidation and cleanup for net release to alt.sources. X''' X.TH COLPR 1L X.SH NAME Xcolpr - Printer output filter. X.SH SYNOPSIS X.B colpr X[ X.B \-bng X] [ X.B \-f Xncols ] [ X.B \-t Xncols ] X[ file ... ] X.SH DESCRIPTION X.I Colpr Xperforms a variety of functions for filtering output to a printer. XWith no options specified, X.I colpr Xduplicates its input to its output. XThe options to X.I colpr Xare: X.IP "\fB\-b\fR" XBackspaces are translated into multiple print passes. This is useful Xwhen the printer cannot backspace but can carriage return. X.IP "\fB\-n\fR" XNewline filtering is enabled. Newline characters are translated to Xreturn/newline sequences. X.IP "\fB\-g\fR" XGraphic character filtering is enabled. See details below. X.IP "\fB\-f\fR" XLines longer than X.I ncols Xare folded onto subsequent lines. X.IP "\fB\-t\fR" XLines longer than X.I ncols Xare truncated to length. X.PP XThe graphic character translation allows access to 8-bit special character Xsets. Some programs, such as X.IR nroff(1) , Xcan produce only 7-bit characters. When X.B \-g Xis specified, a DEL character (octal 0177) will be stripped and the Xmost-significant bit of the following character will be set. For example, Xthe two character sequence {177,001} is replaced by the single character X{201}. The two character sequence {177,177} is converted to a single X{177} character. X.SH SEE ALSO Xcol(1), newform(1) X.SH BUGS XAttempts to overstrike one character over ten times causes Xsome of the overstrike characters to be thrown away. X.PP XTabs are expanded to spaces when X.B \-b Xis specified. There is no way to obtain an octal 377 character. The X.I nroff Xdriver table must produce 8-bit characters using the DEL quoting method Xdescribed herein. X.PP XThe graphic character function is negated by X.IR col(1) . XWhen you attempt "nroff|col|colpr|lp", X.I col Xwill eat the DEL characters produced by X.IR nroff . XWhen you attempt "nroff|colpr|col|lp", the 8-bit characters produced by X.I colpr Xwill be stripped. X.PP XLines longer than 1024 characters will probably be munged. X.SH AUTHOR XChip Rosenthal <chip@vector.Dallas.TX.US> END_OF_FILE_colpr.man size="`wc -c < colpr.man`" if test 2204 -ne "$size" ; then echo "colpr.man: extraction error - got $size chars" fi fi if test -f Makefile -a "$1" != "-c" ; then echo "Makefile: file exists - will not be overwritten" else echo "x - Makefile (file 4 of 4, 1267 chars)" sed -e 's/^X//' << 'END_OF_FILE_Makefile' > Makefile X X# @(#) Makefile 1.1 89/08/23 22:58:01 X# Makefile for "colpr" (generated by /local/bin/makemake version 1.00.08) X# Created by bin@vector on Wed Aug 23 22:21:21 CDT 1989 X XSHELL = /bin/sh XCC = cc XDEFS = XCOPTS = -O XLOPTS = XLIBS = XDEBUG = -g -DDEBUG XLINTFLAGS = -DLINT X XTARG = colpr XOTHERS = X XSRCS = colpr.c X XOBJS = colpr.o X X# Any edits below this line will be lost if "makemake" is rerun! X# Commands may be inserted after the '#%custom' line at the end of this file. X XCFLAGS = $(COPTS) $(DEFS) # $(DEBUG) XLFLAGS = $(LOPTS) # $(DEBUG) X Xall: $(TARG) $(OTHERS) Xinstall: all ; inst Install Xclean: ; rm -f $(TARG) $(OBJS) a.out core $(TARG).lint Xclobber: clean ; inst -u Install Xlint: $(TARG).lint X X$(TARG): $(OBJS) X $(CC) $(LFLAGS) -o $@ $(OBJS) $(LIBS) X X$(TARG).lint: $(TARG) X lint $(LINTFLAGS) $(DEFS) $(SRCS) $(LIBS) > $@ X Xcolpr.o: colpr.c X Xmake: ; X /local/bin/makemake -i -v1.00.08 -aMakefile \ X -DSHELL='$(SHELL)' -DCC='$(CC)' -DDEFS='$(DEFS)' \ X -DCOPTS='$(COPTS)' -DLOPTS='$(LOPTS)' -DLIBS='$(LIBS)' \ X -DDEBUG='$(DEBUG)' -DLINTFLAGS='$(LINTFLAGS)' \ X -DOTHERS='$(OTHERS)' $(TARG) $(SRCS) X X#%custom - commands below this line will be maintained if 'makemake' is rerun X Xshar: ; shar README colpr.c colpr.man Makefile > colpr.shar X END_OF_FILE_Makefile size="`wc -c < Makefile`" if test 1267 -ne "$size" ; then echo "Makefile: extraction error - got $size chars" fi fi echo "done - 4 files extracted" exit 0 -- Chip Rosenthal / chip@vector.Dallas.TX.US / Dallas Semiconductor / 214-450-5337 "I wish you'd put that starvation box down and go to bed" - Albert Collins' Mom