nroff for Printronix 300
gwyn%brl-vld at sri-unix.UUCP
gwyn%brl-vld at sri-unix.UUCP
Thu Sep 15 04:40:19 AEST 1983
From: Doug Gwyn (VLD/VMB) <gwyn at brl-vld>
FOR Deborah Brown (deb at mitre or brown at 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 at 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;
}
More information about the Comp.unix.wizards
mailing list