brown%mitre@sri-unix.UUCP (09/14/83)
From: Deborah Brown <brown@mitre> A friend is looking for an nroff driver that will support the Printronix 300 (a.k.a. LXY11) printer under Eunice. Alternatively, he'd be interested in a post processor that looks for control-H's within lines, and changes those lines so that they have the first part of the text followed by a carriage return followed by either spaces or dollar signs and the appropriate number of underscores. (He needs this cause the Printronix interprets the control-H as a "double height" command!) Responses to me please. He's not on the net. Thanks, Deb Brown (deb@mitre)
gwyn%brl-vld@sri-unix.UUCP (09/14/83)
From: Doug Gwyn (VLD/VMB) <gwyn@brl-vld> FOR Deborah Brown (deb@mitre or brown@mitre): I apologize for sending this to the mailing list, but "mitre" did not appear to be a known ARPAnet host name to our mailing system. Perhaps someone else can use this too. The following code, a module from the MDQS spooling system, does the right thing with funny characters for printers that know how to CR-overstrike. All you need now is a very small driver program to invoke the function. /* copyn - transcribe arbitrary input file to stdout (for MDQS) [ASCII line printer version] last edit: 27-Mar-1983 Douglas A. Gwyn <gwyn@BRL-VLD> Acknowledgement: Derived from John S. Quarterman's "reline" utility. Method: Uses buffered overstrike lines (text, CR, text) as necessary. Suboptimal in some ways, but works well in typical usage -- particularly for "nroff" emboldened and underlined output. The idea is to minimize overhead for simple printouts. Assumptions: ASCII host character set. Printer understands LF, FF, and CR (not true of Versatec). Configuration Notes: If all lp output passes through here (highly recommended), then your lp driver can be changed to not examine characters as they go by. This reduces kernel size and improves system loading. Hard-coded "indent" offset should be removed, since tractor positioning accomplishes the same thing more cheaply. However, if "indent" is ioctl-settable, the driver must notice LF, FF, and CR. If there is a user page quota imposed, LF and FF must be counted (note that MDQS provides a better handle for this). Perforation skipping should not be performed, as it interferes with text-processing software. It would be nice if consecutive FFs would only cause one page advance, and FF should be done on device open when not already at top of form (the latter is best done by counting LFs as well as remembering FFs). IMPORTANT! If you are using an old-fashioned UNIX, define "V7". This is not necessary for UNIX System III and later. */ /* #define V7 */ #include <ctype.h> #include <stdio.h> /* Adjustable parameters: */ #define MAXOVER 3 /* max. number of overstrikes */ #define MAXLINE 132 /* maximum printer line width */ #define PAGE 66 /* nominal page size for FF */ #define TABS 8 /* standard tab stop interval */ /* Non-spacing control characters are shown in DEC style, e.g. ^X. ASCII DEL is shown as ^?. Meta-characters (those with bit 7 set) are shown as ~X or ~^X. (Note that all these unavoidably mess up horizontal spacing.) */ #define METAPFX '~' /* meta-char prefix */ #define CTRLPFX '^' /* control-char prefix */ #define DELSYMB '?' /* DEL-char indicator */ #ifdef V7 typedef int void; #endif typedef int bool; /* boolean data type */ typedef unsigned short ushort; /* The following rules apply to the overstruck line buffers: o Higher buffers are not longer than lower ones. o High-water mark points past the last non-space slot. o 0 <= high <= MAXLINE */ typedef struct { ushort high; /* buffer dirty mark */ char buf[MAXLINE + 1]; /* character buffer */ } strike; /* overstruck line buffer */ static strike linebuf[MAXOVER + 1] = { 0 }; /* overstruck lines */ static strike *line = &linebuf[0]; /* current buffer */ static strike *last = &linebuf[0]; /* highest line used */ static ushort ccol = 0; /* current column position */ static void ctrlchar(), normchar(), outflush(); long copyn( fp, llimit ) /* returns # input lines done, no more than llimit+PAGE-1 */ register FILE *fp; /* input stream */ long llimit; /* input line limit */ { long lcount; /* counts input lines */ bool chklim; /* whether to test line limit */ register int c; /* input character */ { register strike *str; /* addresses buffers */ for ( line = last = str = &linebuf[0]; str <= &linebuf[MAXOVER]; ++str ) str->high = 0; /* initially, all lines empty */ } ccol = 0; if ( chklim = llimit != 0L ) lcount = 0L; while ( (c = getc( fp )) != EOF ) #ifdef V7 /* This test is done first because old-fashioned UNIXes don't have the large ctype table. */ if ( !isascii( c ) ) /* meta-character */ { normchar( METAPFX ); c = toascii( c ); if ( iscntrl( c ) || isspace( c ) && c != ' ' ) ctrlchar( c ); /* meta-control */ else normchar( c ); /* meta-normal */ } /* The rest of these are in descending order of expected frequency of occurrence. */ else if ( isprint( c ) || c == ' ' ) #else if ( isprint( c ) ) /* (includes SP) */ #endif normchar( c ); else if ( c == '\t' ) do normchar( ' ' );/* ++ccol side-effect */ while ( ccol % TABS != 0 ); else if ( c == '\n' ) { outflush( c ); if ( chklim && ++lcount == llimit ) return lcount; /* ran into limit */ } else if ( c == '\b' || c == '\r' ) { /* reverse pseudo-motions */ register ushort col; /* temp for `ccol' */ if ( c == '\r' ) col = 0; else /* BS */ if ( (col = ccol) != 0 ) --col; /* but not past edge */ if ( col < linebuf[MAXOVER].high ) outflush( '\r' ); /* make room */ while ( col < line->high && line < &linebuf[MAXOVER] ) { ++line; /* find clean buffer tail */ if ( line > last ) last = line; /* new buffer */ } ccol = col; } else if ( c == '\f' ) { outflush( c ); if ( chklim ) { lcount += PAGE - lcount % PAGE; if ( lcount >= llimit ) return lcount; /* limit */ } } #ifdef V7 else /* random control character */ #else else if ( iscntrl( c ) /* && not already dealt with */ ) #endif ctrlchar( c ); /* control character */ #ifndef V7 else { /* meta-character */ normchar( METAPFX ); c = toascii( c ); if ( iscntrl( c ) || isspace( c ) && c != ' ' ) ctrlchar( c ); /* meta-control */ else normchar( c ); /* meta-normal */ } #endif outflush( 0 ); /* flush leftovers */ return lcount; } static void ctrlchar( c ) /* buffer mapped control char */ int c; /* control character */ { normchar( CTRLPFX ); normchar( (c == 0177) ? DELSYMB : c + 0100 ); } static void normchar( c ) /* buffer printing char */ int c; /* character to stash */ { register ushort col = ccol++; /* initial column location */ if ( col < MAXLINE && c != ' ' /* i.e., a "dirt" char */ ) { register ushort top = line->high; while ( top < col ) line->buf[top++] = ' '; /* catch up */ line->buf[col] = c; if ( col >= line->high ) line->high = ccol; } while ( line > &linebuf[0] && ccol >= (line - 1)->high ) --line; /* previous buffer usable */ } static void outflush( c ) /* dump overstrike buffers */ int c; /* LF, FF, CR, or 0 [on EOF] */ { register strike *str; /* addresses buffers */ for ( str = &linebuf[0]; ; ++str ) { str->buf[str->high] = '\0'; (void)fputs( str->buf, stdout ); if ( str != last ) putchar( '\r' ); /* prepare overprint */ else { if ( c != 0 ) putchar( c ); /* LF, FF, or CR */ break; } } for ( str = &linebuf[0]; str <= last; ++str ) str->high = 0; /* clear used lines */ line = last = &linebuf[0]; ccol = 0; }