koreth@panarthea.ebay.sun.com (Steven Grimm) (11/15/89)
Submitted-by: rosenkra@hall.cray.com (Bill Rosenkranz)
Posting-number: Volume 3, Issue 9
Archive-name: nroff/part02
part02/03
-bill
rosenkra@hall.cray.com
------------cut here----------------cut here---------------------------------
#!/bin/sh
# This is a shell archive. Remove anything before this line,
# then unpack it by saving it in a file and typing "sh file".
#
# Wrapped by hall!rosenkra on Sun Nov 12 16:35:33 CST 1989
# Contents: main.c command.c text.c io.c
echo x - main.c
sed 's/^@//' > "main.c" <<'@//E*O*F main.c//'
/*
* main.c - main for nroff word processor
*
* similar to Unix(tm) nroff or RSX-11M RNO. adaptation of text processor
* given in "Software Tools", Kernighan and Plauger.
*
* adapted for atariST/TOS by Bill Rosenkranz 11/89
* net: rosenkra@hall.cray.com
* CIS: 71460,17
* GENIE: W.ROSENKRANZ
*
* original author:
*
* Stephen L. Browning
* 5723 North Parker Avenue
* Indianapolis, Indiana 46220
*
* history:
*
* - Originally written in BDS C;
* - Adapted for standard C by W. N. Paul
* - Heavily hacked up to conform to "real" nroff by Bill Rosenkranz
*/
#define NRO_MAIN /* to define globals in nro.h */
#include <stdio.h>
#ifdef ATARIST
#include <sys\types.h>
#include <sys\time.h>
#else
#include <sys/types.h>
#include <sys/time.h>
#endif
#include "nroff.h"
main (argc, argv)
int argc;
char *argv[];
{
register int i;
int swflg;
int ifp = 0;
swflg = FALSE;
hold_screen = FALSE;
debugging = FALSE;
pout = stdout;
err_stream = stderr;
dbg_stream = stderr;
/*
* initialize structures (defaults)
*/
init ();
/*
* parse cmdline flags
*/
for (i = 1; i < argc; ++i)
{
if (*argv[i] == '-' || *argv[i] == '+')
{
if (pswitch (argv[i], argv[i+1], &swflg) == ERR)
err_exit (-1);
}
}
/*
* loop on files
*/
for (i = 1; i < argc; ++i)
{
if (*argv[i] != '-' && *argv[i] != '+')
{
/*
* open this file...
*/
if ((sofile[0] = fopen (argv[i], "r")) == NULL)
{
fprintf (err_stream,
"***%s: unable to open file %s\n",
myname, argv[i]);
err_exit (-1);
}
else
{
/*
* do it for this file...
*/
ifp = 1;
profile ();
fclose (sofile[0]);
}
}
else if (*argv[i] == '-' && *(argv[i]+1) == 0)
{
/*
* - means read stdin
*/
sofile[0] = stdin;
ifp = 1;
profile ();
}
}
/*
* if no files, usage
*/
if ((ifp == 0 && swflg == FALSE) || argc <= 1)
{
usage ();
err_exit (-1);
}
/*
* if not going to stdout (-l)
*/
if (pout != stdout)
{
fflush (pout);
fclose (pout);
}
err_exit (0);
}
/*------------------------------*/
/* usage */
/*------------------------------*/
usage ()
{
/*
* note: -l not documented
*/
fprintf (stderr, "Usage: %s [options] file [...]\n", myname);
fprintf (stderr, "Options:\n");
fprintf (stderr, "-a font changes\n");
fprintf (stderr, "-b backspace\n");
fprintf (stderr, "-h hold screen\n");
/* fprintf (stderr, "-l output to printer\n");*/
fprintf (stderr, "-m<name> macro file (e.g. -man)\n");
fprintf (stderr, "-o file error log file\n");
fprintf (stderr, "-po<n> page offset\n");
fprintf (stderr, "-pn<n> initial page number\n");
fprintf (stderr, "-v version\n");
fprintf (stderr, "+<n> first page to do\n");
fprintf (stderr, "-<n> last page to do\n");
fprintf (stderr, "- use stdin\n");
}
/*------------------------------*/
/* init */
/*------------------------------*/
init ()
{
/*
* initialize parameters for nro word processor
*/
register long i;
#ifdef ALCYON
time_t dum = 0;
#else
extern long time ();
time_t dum = time (0);
#endif
char *ctim;
dc.fill = YES;
dc.dofnt = YES;
dc.lsval = 1;
dc.inval = 0;
dc.rmval = PAGEWIDTH - 1;
dc.llval = PAGEWIDTH - 1;
dc.ltval = PAGEWIDTH - 1;
dc.tival = 0;
dc.ceval = 0;
dc.ulval = 0;
dc.cuval = 0;
dc.juval = YES;
dc.adjval = ADJ_BOTH;
dc.boval = 0;
dc.bsflg = FALSE;
dc.prflg = TRUE;
dc.sprdir = 0;
dc.flevel = 0;
dc.lastfnt = 1;
dc.thisfnt = 1;
dc.escon = YES;
dc.pgchr = '%';
dc.cmdchr = '.';
dc.escchr = '\\';
dc.nobrchr = '\'';
for (i = 0; i < 26; ++i)
dc.nr[i] = 0;
for (i = 0; i < 26; ++i)
dc.nrauto[i] = 1;
for (i = 0; i < 26; ++i)
dc.nrfmt[i] = '1';
/*
* initialize internal regs. first zero out...
*/
for (i = 0; i < MAXREGS; i++)
{
rg[i].rname[0] = rg[i].rname[1] = rg[i].rname[2] = rg[i].rname[3] = '\0';
rg[i].rauto = 1;
rg[i].rval = 0;
rg[i].rflag = RF_READ;
rg[i].rfmt = '1';
}
/*
* this should be checked...
*/
ctim = ctime (&dum);
/*
* predefined regs. these are read/write:
*/
i = 0;
strcpy (rg[i].rname, "%"); /* current page */
rg[i].rauto = 1;
rg[i].rval = 0;
rg[i].rflag = RF_READ | RF_WRITE;
rg[i].rfmt = '1';
i++;
strcpy (rg[i].rname, "ct"); /* character type */
rg[i].rauto = 1;
rg[i].rval = 0;
rg[i].rflag = RF_READ | RF_WRITE;
rg[i].rfmt = '1';
i++;
strcpy (rg[i].rname, "dl"); /* width of last complete di */
rg[i].rauto = 1;
rg[i].rval = 0;
rg[i].rflag = RF_READ | RF_WRITE;
rg[i].rfmt = '1';
i++;
strcpy (rg[i].rname, "dn"); /* height of last complete di */
rg[i].rauto = 1;
rg[i].rval = 0;
rg[i].rflag = RF_READ | RF_WRITE;
rg[i].rfmt = '1';
i++;
strcpy (rg[i].rname, "dw"); /* day of week (1-7) */
rg[i].rval = 0;
if (!strncmp (&ctim[0], "Sun", 3))
rg[i].rval = 1;
else if (!strncmp (&ctim[0], "Mon", 3))
rg[i].rval = 2;
else if (!strncmp (&ctim[0], "Tue", 3))
rg[i].rval = 3;
else if (!strncmp (&ctim[0], "Wed", 3))
rg[i].rval = 4;
else if (!strncmp (&ctim[0], "Thu", 3))
rg[i].rval = 5;
else if (!strncmp (&ctim[0], "Fri", 3))
rg[i].rval = 6;
else if (!strncmp (&ctim[0], "Sat", 3))
rg[i].rval = 7;
rg[i].rauto = 1;
rg[i].rflag = RF_READ | RF_WRITE;
rg[i].rfmt = '1';
i++;
strcpy (rg[i].rname, "dy"); /* day of month (1-31) */
rg[i].rauto = 1;
rg[i].rval = atoi (&ctim[8]);
rg[i].rflag = RF_READ | RF_WRITE;
rg[i].rfmt = '1';
i++;
strcpy (rg[i].rname, "hp"); /* current h pos on input */
rg[i].rauto = 1;
rg[i].rval = 0;
rg[i].rflag = RF_READ | RF_WRITE;
rg[i].rfmt = '1';
i++;
strcpy (rg[i].rname, "ln"); /* output line num */
rg[i].rauto = 1;
rg[i].rval = 0;
rg[i].rflag = RF_READ | RF_WRITE;
rg[i].rfmt = '1';
i++;
strcpy (rg[i].rname, "mo"); /* current month (1-12) */
rg[i].rval = 0;
if (!strncmp (&ctim[4], "Jan", 3))
rg[i].rval = 1;
else if (!strncmp (&ctim[4], "Feb", 3))
rg[i].rval = 2;
else if (!strncmp (&ctim[4], "Mar", 3))
rg[i].rval = 3;
else if (!strncmp (&ctim[4], "Apr", 3))
rg[i].rval = 4;
else if (!strncmp (&ctim[4], "May", 3))
rg[i].rval = 5;
else if (!strncmp (&ctim[4], "Jun", 3))
rg[i].rval = 6;
else if (!strncmp (&ctim[4], "Jul", 3))
rg[i].rval = 7;
else if (!strncmp (&ctim[4], "Aug", 3))
rg[i].rval = 8;
else if (!strncmp (&ctim[4], "Sep", 3))
rg[i].rval = 9;
else if (!strncmp (&ctim[4], "Oct", 3))
rg[i].rval = 10;
else if (!strncmp (&ctim[4], "Nov", 3))
rg[i].rval = 11;
else if (!strncmp (&ctim[4], "Dec", 3))
rg[i].rval = 12;
rg[i].rauto = 1;
rg[i].rflag = RF_READ | RF_WRITE;
rg[i].rfmt = '1';
i++;
strcpy (rg[i].rname, "nl"); /* v pos of last base-line */
rg[i].rauto = 1;
rg[i].rval = 0;
rg[i].rflag = RF_READ | RF_WRITE;
rg[i].rfmt = '1';
i++;
strcpy (rg[i].rname, "sb"); /* depth of str below base */
rg[i].rauto = 1;
rg[i].rval = 0;
rg[i].rflag = RF_READ | RF_WRITE;
rg[i].rfmt = '1';
i++;
strcpy (rg[i].rname, "st"); /* height of str above base */
rg[i].rauto = 1;
rg[i].rval = 0;
rg[i].rflag = RF_READ | RF_WRITE;
rg[i].rfmt = '1';
i++;
strcpy (rg[i].rname, "yr"); /* last 2 dig of current year*/
rg[i].rauto = 1;
rg[i].rval = atoi (&ctim[22]);
rg[i].rflag = RF_READ | RF_WRITE;
rg[i].rfmt = '1';
i++;
/*
* these are read only:
*/
strcpy (rg[i].rname, ".$"); /* num of args at current macro*/
rg[i].rauto = 1;
rg[i].rval = 0;
rg[i].rflag = RF_READ;
rg[i].rfmt = '1';
i++;
strcpy (rg[i].rname, ".A"); /* 1 for nroff */
rg[i].rauto = 1;
rg[i].rval = 1;
rg[i].rflag = RF_READ;
rg[i].rfmt = '1';
i++;
strcpy (rg[i].rname, ".H"); /* hor resolution */
rg[i].rauto = 1;
rg[i].rval = 1;
rg[i].rflag = RF_READ;
rg[i].rfmt = '1';
i++;
strcpy (rg[i].rname, ".T"); /* 1 for troff */
rg[i].rauto = 0;
rg[i].rval = 0;
rg[i].rflag = RF_READ;
rg[i].rfmt = '1';
i++;
strcpy (rg[i].rname, ".V"); /* vert resolution */
rg[i].rauto = 1;
rg[i].rval = 1;
rg[i].rflag = RF_READ;
rg[i].rfmt = '1';
i++;
strcpy (rg[i].rname, ".a");
rg[i].rauto = 1;
rg[i].rval = 0;
rg[i].rflag = RF_READ;
rg[i].rfmt = '1';
i++;
strcpy (rg[i].rname, ".c");
rg[i].rauto = 1;
rg[i].rval = 0;
rg[i].rflag = RF_READ;
rg[i].rfmt = '1';
i++;
strcpy (rg[i].rname, ".d");
rg[i].rauto = 1;
rg[i].rval = 0;
rg[i].rflag = RF_READ;
rg[i].rfmt = '1';
i++;
strcpy (rg[i].rname, ".f"); /* current font (1-4) */
rg[i].rauto = 1;
rg[i].rval = 1;
rg[i].rflag = RF_READ;
rg[i].rfmt = '1';
i++;
strcpy (rg[i].rname, ".h");
rg[i].rauto = 1;
rg[i].rval = 0;
rg[i].rflag = RF_READ;
rg[i].rfmt = '1';
i++;
strcpy (rg[i].rname, ".i"); /* current indent */
rg[i].rauto = 1;
rg[i].rval = 0;
rg[i].rflag = RF_READ;
rg[i].rfmt = '1';
i++;
strcpy (rg[i].rname, ".l"); /* current line length */
rg[i].rauto = 1;
rg[i].rval = PAGEWIDTH - 1;
rg[i].rflag = RF_READ;
rg[i].rfmt = '1';
i++;
strcpy (rg[i].rname, ".n");
rg[i].rauto = 1;
rg[i].rval = 0;
rg[i].rflag = RF_READ;
rg[i].rfmt = '1';
i++;
strcpy (rg[i].rname, ".o"); /* current offset */
rg[i].rauto = 1;
rg[i].rval = 0;
rg[i].rflag = RF_READ;
rg[i].rfmt = '1';
i++;
strcpy (rg[i].rname, ".p"); /* current page len */
rg[i].rauto = 1;
rg[i].rval = PAGELEN;
rg[i].rflag = RF_READ;
rg[i].rfmt = '1';
i++;
strcpy (rg[i].rname, ".s"); /* current point size */
rg[i].rauto = 1;
rg[i].rval = 1;
rg[i].rflag = RF_READ;
rg[i].rfmt = '1';
i++;
strcpy (rg[i].rname, ".t");
rg[i].rauto = 1;
rg[i].rval = 0;
rg[i].rflag = RF_READ;
rg[i].rfmt = '1';
i++;
strcpy (rg[i].rname, ".u");
rg[i].rauto = 1;
rg[i].rval = 0;
rg[i].rflag = RF_READ;
rg[i].rfmt = '1';
i++;
strcpy (rg[i].rname, ".v"); /* current v line spacing */
rg[i].rauto = 1;
rg[i].rval = 1;
rg[i].rflag = RF_READ;
rg[i].rfmt = '1';
i++;
strcpy (rg[i].rname, ".w"); /* width of prev char */
rg[i].rauto = 1;
rg[i].rval = 1;
rg[i].rflag = RF_READ;
rg[i].rfmt = '1';
i++;
strcpy (rg[i].rname, ".x");
rg[i].rauto = 1;
rg[i].rval = 0;
rg[i].rflag = RF_READ;
rg[i].rfmt = '1';
i++;
strcpy (rg[i].rname, ".y");
rg[i].rauto = 1;
rg[i].rval = 0;
rg[i].rflag = RF_READ;
rg[i].rfmt = '1';
i++;
strcpy (rg[i].rname, ".z");
rg[i].rauto = 1;
rg[i].rval = 0;
rg[i].rflag = RF_READ;
rg[i].rfmt = '1';
pg.curpag = 0;
pg.newpag = 1;
pg.lineno = 0;
pg.plval = PAGELEN;
pg.m1val = 2;
pg.m2val = 2;
pg.m3val = 2;
pg.m4val = 2;
pg.bottom = pg.plval - pg.m4val - pg.m3val;
pg.offset = 0;
pg.frstpg = 0;
pg.lastpg = 30000;
pg.ehead[0] = pg.ohead[0] = '\n';
pg.efoot[0] = pg.ofoot[0] = '\n';
for (i = 1; i < MAXLINE; ++i)
{
pg.ehead[i] = pg.ohead[i] = EOS;
pg.efoot[i] = pg.ofoot[i] = EOS;
}
pg.ehlim[LEFT] = pg.ohlim[LEFT] = dc.inval;
pg.eflim[LEFT] = pg.oflim[LEFT] = dc.inval;
pg.ehlim[RIGHT] = pg.ohlim[RIGHT] = dc.rmval;
pg.eflim[RIGHT] = pg.oflim[RIGHT] = dc.rmval;
co.outp = 0;
co.outw = 0;
co.outwds = 0;
co.lpr = FALSE;
for (i = 0; i < MAXLINE; ++i)
co.outbuf[i] = EOS;
for (i = 0; i < MXMDEF; ++i)
mac.mnames[i] = NULL;
for (i = 0; i < MACBUF; ++i)
mac.mb[i] = '\0';
for (i = 0; i < MAXLINE; ++i)
mac.pbb[i] = '\0';
mac.lastp = 0;
mac.emb = &mac.mb[0];
mac.ppb = NULL;
}
/*------------------------------*/
/* pswitch */
/*------------------------------*/
pswitch (p, p2, q)
register char *p;
register char *p2;
register int *q;
{
/*
* process switch values from command line
*/
int swgood;
char mfile[128];
char *ptmac;
swgood = TRUE;
if (*p == '-')
{
/*
* since is STILL use the goofy atari/dri xmain code, i
* look for both upper and lower case. if you use dLibs
* (and if its startup code does not ucase the cmd line),
* you can probably look for just lower case. gulam and
* other shells typically don't change case of cmd line.
*/
switch (*++p)
{
case 0: /* stdin */
break;
case 'a': /* font changes */
case 'A':
dc.dofnt = NO;
break;
case 'b': /* backspace */
case 'B':
dc.bsflg = TRUE;
break;
case 'd': /* debug mode */
case 'D':
dbg_stream = fopen (dbgfile, "w");
debugging = TRUE;
break;
case 'h': /* hold screen */
case 'H':
hold_screen = TRUE;
break;
case 'l': /* to lpr (was P) */
case 'L':
pout = fopen (printer, "w");
co.lpr = TRUE;
break;
case 'm': /* macro file */
case 'M':
/*
* build macro file name. start with lib
*
* put c:\lib\tmac in environment so we can
* read it here. else use default. if you want
* file from cwd, "setenv TMACDIR ." from shell.
*
* we want file names like "tmac.an" (for -man)
*/
if (ptmac = getenv ("TMACDIR"))
{
/*
* this is the lib path (e.g. "c:\lib\tmac")
*/
strcpy (mfile, ptmac);
/*
* this is the prefix (i.e. "\tmac.")
*/
strcat (mfile, TMACPRE);
}
else
/*
* use default lib/prefix (i.e.
* "c:\lib\tmac\tmac.")
*/
strcpy (mfile, TMACFULL);
/*
* finally, add extension (e.g. "an")
*/
strcat (mfile, ++p);
/*
* open file and read it
*/
if ((sofile[0] = fopen (mfile, "r")) == NULL)
{
fprintf (stderr,
"***%s: unable to open macro file %s\n",
myname, mfile);
err_exit (-1);
}
profile ();
fclose (sofile[0]);
break;
case 'o': /* output error log */
case 'O':
if (!p2)
{
fprintf (stderr,
"***%s: no error file specified\n",
myname);
err_exit (-1);
}
if ((err_stream = fopen (p2, "w")) == NULL)
{
fprintf (stderr,
"***%s: unable to open error file %s\n",
myname, p2);
err_exit (-1);
}
break;
case 'p': /* .po, .pn */
case 'P':
if (*(p+1) == 'o' || *(p+1) == 'O') /* -po___ */
{
p += 2;
set (&pg.offset, ctod (p), '1', 0, 0, HUGE);
set_ireg (".o", pg.offset, 0);
}
else if (*(p+1) == 'n' || *(p+1) == 'N')/* -pn___ */
{
p += 2;
set (&pg.curpag, ctod (p) - 1, '1', 0, -HUGE, HUGE);
pg.newpag = pg.curpag + 1;
set_ireg ("%", pg.newpag, 0);
}
else /* -p___ */
{
set (&pg.offset, ctod (++p), '1', 0, 0, HUGE);
set_ireg (".o", pg.offset, 0);
}
break;
case 'v': /* version */
case 'V':
printf ("%s\n", version);
*q = TRUE;
break;
case '0': /* last page */
case '1':
case '2':
case '3':
case '4':
case '5':
case '6':
case '7':
case '8':
case '9':
pg.lastpg = ctod (p);
break;
default: /* illegal */
swgood = FALSE;
break;
}
}
else if (*p == '+') /* first page */
{
pg.frstpg = ctod (++p);
}
else /* illegal */
{
swgood = FALSE;
}
if (swgood == FALSE)
{
fprintf (stderr, "***%s: illegal switch %s\n", myname, p);
return (ERR);
}
return (OK);
}
/*------------------------------*/
/* profile */
/*------------------------------*/
profile ()
{
/*
* process input files from command line
*/
char ibuf[MAXLINE];
/*
* handle nesting of includes (.so)
*/
for (dc.flevel = 0; dc.flevel >= 0; dc.flevel -= 1)
{
while (getlin (ibuf, sofile[dc.flevel]) != EOF)
{
/*
* if line is a command or text
*/
if (ibuf[0] == dc.cmdchr)
{
comand (ibuf);
}
else
{
/*
* this is a text line. first see if
* first char is space. if it is, break
* line.
*/
if (ibuf[0] == ' ')
robrk ();
text (ibuf);
}
}
/*
* close included file
*/
if (dc.flevel > 0)
fclose (sofile[dc.flevel]);
}
if (pg.lineno > 0)
space (HUGE);
}
@//E*O*F main.c//
chmod u=rw,g=r,o=r main.c
echo x - command.c
sed 's/^@//' > "command.c" <<'@//E*O*F command.c//'
/*
* command.c - command input parser/processor for nroff text processor
*
* adapted for atariST/TOS by Bill Rosenkranz 11/89
* net: rosenkra@hall.cray.com
* CIS: 71460,17
* GENIE: W.ROSENKRANZ
*
* original author:
*
* Stephen L. Browning
* 5723 North Parker Avenue
* Indianapolis, Indiana 46220
*
* history:
*
* - Originally written in BDS C;
* - Adapted for standard C by W. N. Paul
* - Heavily hacked up to conform to "real" nroff by Bill Rosenkranz
*/
#undef NRO_MAIN /* extern globals */
#include <stdio.h>
#include "nroff.h"
/*------------------------------*/
/* comand */
/*------------------------------*/
comand (p)
register char *p;
{
/*
* main command processor
*/
register int i;
register int ct;
register int val;
register int indx;
int newval;
int spval;
char argtyp;
char name[MAXLINE];
char macexp[MXMLEN];
int tmp;
char *pfs;
char fs[20];
/*
* get command code
*/
ct = comtyp (p, macexp);
/*
* error?
*/
if (ct == UNKNOWN)
{
fprintf (err_stream,
"***%s: unrecognized command %s\n", myname, p);
return;
}
/*
* ignore comments
*/
if (ct == COMMENT)
return;
/*
* do escape expansion on command line args
*/
expesc (p, name);
/*
* get value of command
*/
val = getval (p, &argtyp);
/*
* do the command
*/
switch (ct)
{
/* set (¶m, val, type, defval, minval, maxval) */
case FC:
/*
* field delim/pad chars
*
* .fc [delim] [pad]
*/
fprintf (err_stream, "***%s: .fc not available\n", myname);
break;
case TR:
/*
* translate
*
* .tr ab...
*/
fprintf (err_stream, "***%s: .tr not available\n", myname);
break;
case AD:
/*
* adjust
*
* .ad [mode]
*/
p = skipwd (p);
p = skipbl (p);
switch (*p)
{
case 'l':
dc.adjval = ADJ_LEFT;
dc.juval = YES;
break;
case 'r':
dc.adjval = ADJ_RIGHT;
dc.juval = YES;
break;
case 'c':
dc.adjval = ADJ_CENTER;
dc.juval = YES;
break;
case 'b':
case 'n':
dc.adjval = ADJ_BOTH;
dc.juval = YES;
break;
default:
break;
}
break;
case AF:
/*
* assign format to number reg
*
* .af R {1,a,A,i,I,0...1}
*/
p = skipwd (p);
p = skipbl (p);
if (!isalpha (*p))
{
fprintf (err_stream,
"***%s: invalid or missing number register name\n",
myname);
}
else
{
/*
* number register format is 1,a,A,i,I,0...1
* default is 1. for 0001 format, store num dig
* or'ed with 0x80, up to 8 digits.
*/
indx = tolower (*p) - 'a';
p = skipwd (p);
p = skipbl (p);
if (*p == '1')
dc.nrfmt[indx] = '1';
else if (*p == 'a')
dc.nrfmt[indx] = 'a';
else if (*p == 'A')
dc.nrfmt[indx] = 'A';
else if (*p == 'i')
dc.nrfmt[indx] = 'i';
else if (*p == 'I')
dc.nrfmt[indx] = 'I';
else if (*p == '0')
{
for (i = 0; isdigit (p[i]); i++)
;
dc.nrfmt[indx] = (char) (i);
if (dc.nrfmt[indx] <= 0)
dc.nrfmt[indx] = '1';
else if (dc.nrfmt[indx] > 8)
{
dc.nrfmt[indx] = 8;
dc.nrfmt[indx] |= 0x80;
}
else
dc.nrfmt[indx] |= 0x80;
}
else
dc.nrfmt[indx] = '1';
}
break;
case BO:
/*
* bold face
*
* .bo [N]
*/
set (&dc.boval, val, argtyp, 1, 0, HUGE);
dc.cuval = dc.ulval = 0;
break;
case BP:
/*
* begin page
*
* .bp [+/-N]
*/
if (pg.lineno > 0)
space (HUGE);
set (&pg.curpag, val, argtyp, pg.curpag + 1, -HUGE, HUGE);
pg.newpag = pg.curpag;
set_ireg ("%", pg.newpag, 0);
break;
case BR:
/*
* break (page)
*
* .br
*/
robrk ();
break;
case BS:
/*
* backspc in output
*
* .bs [N]
*/
set (&dc.bsflg, val, argtyp, 1, 0, 1);
break;
case C2:
/*
* nobreak char
*
* .c2 [c=']
*/
if (argtyp == '\r' || argtyp == '\n')
dc.nobrchr = '\'';
else
dc.nobrchr = argtyp;
break;
case CC:
/*
* command character
*
* .cc [c=.]
*/
if (argtyp == '\r' || argtyp == '\n')
dc.cmdchr = '.';
else
dc.cmdchr = argtyp;
break;
case CE:
/*
* center
*
* .ce [N]
*/
robrk ();
set (&dc.ceval, val, argtyp, 1, 0, HUGE);
break;
case CU:
/*
* continuous underline
*
* .cu [N]
*/
set (&dc.cuval, val, argtyp, 1, 0, HUGE);
dc.ulval = dc.boval = 0;
break;
case DE:
/*
* define macro
*
* .de name [end]
*/
defmac (p, sofile[dc.flevel]);
break;
case DS:
/*
* define string
*
* .ds name string
*/
defstr (p);
break;
case EC:
/*
* escape char
*
* .ec [c=\]
*/
if (argtyp == '\r' || argtyp == '\n')
dc.escchr = '\\';
else
dc.escchr = argtyp;
dc.escon = YES;
break;
case EF:
/*
* even footer
*
* .ef "a" "b" "c"
*/
gettl (p, pg.efoot, &pg.eflim[0]);
break;
case EH:
/*
* even header
*
* .eh "a" "b" "c"
*/
gettl (p, pg.ehead, &pg.ehlim[0]);
break;
case EN:
/*
* end macro def (should not get one here...)
*
* .en or ..
*/
fprintf (err_stream, "***%s: missing .de command\n", myname);
break;
case EO:
/*
* escape off
*
* .eo
*/
dc.escon = NO;
break;
case FI:
/*
* fill
*
* .fi
*/
robrk ();
dc.fill = YES;
break;
case FL:
/*
* flush NOW
*
* .fl
*/
fflush (pout);
break;
case FO:
/*
* footer
*
* .fo "a" "b" "c"
*/
gettl (p, pg.efoot, &pg.eflim[0]);
gettl (p, pg.ofoot, &pg.oflim[0]);
break;
case FT:
/*
* font change
*
* .ft {R,I,B,S,P}
*
* the way it's implemented here, it causes a break
* rather than be environmental...
*/
p = skipwd (p);
p = skipbl (p);
if (!isalpha (*p))
{
fprintf (err_stream,
"***%s: invalid or missing font name\n",
myname);
}
else
{
pfs = &fs[0];
fontchange (*p, pfs);
robrk ();
fflush (pout);
fprintf (pout, "%s", pfs);
fflush (pout);
}
break;
case TL:
case HE:
/*
* header (both are currently identical. .he is -me)
*
* .tl "a" "b" "c"
* .he "a" "b" "c"
*/
gettl (p, pg.ehead, &pg.ehlim[0]);
gettl (p, pg.ohead, &pg.ohlim[0]);
break;
case IN:
/*
* indenting
*
* .in [+/-N]
*/
set (&dc.inval, val, argtyp, 0, 0, dc.rmval - 1);
set_ireg (".i", dc.inval, 0);
dc.tival = dc.inval;
break;
case JU:
/*
* justify
*
* .ju
*/
dc.juval = YES;
break;
case LL:
/*
* line length
*
* .ll [+/-N]
* .rm [+/-N]
*/
set (&dc.rmval, val, argtyp, PAGEWIDTH, dc.tival + 1, HUGE);
set (&dc.llval, val, argtyp, PAGEWIDTH, dc.tival + 1, HUGE);
set_ireg (".l", dc.llval, 0);
break;
case LS:
/*
* line spacing
*
* .ls [+/-N=+1]
*/
set (&dc.lsval, val, argtyp, 1, 1, HUGE);
set_ireg (".v", dc.lsval, 0);
break;
case LT:
/*
* title length
*
* .lt N
*/
set (&dc.ltval, val, argtyp, PAGEWIDTH, 0, HUGE);
pg.ehlim[RIGHT] = dc.ltval;
pg.ohlim[RIGHT] = dc.ltval;
break;
case M1:
/*
* topmost margin
*
* .m1 N
*/
set (&pg.m1val, val, argtyp, 2, 0, HUGE);
break;
case M2:
/*
* second top margin
*
* .m2 N
*/
set (&pg.m2val, val, argtyp, 2, 0, HUGE);
break;
case M3:
/*
* 1st bottom margin
*
* .m3 N
*/
set (&pg.m3val, val, argtyp, 2, 0, HUGE);
pg.bottom = pg.plval - pg.m4val - pg.m3val;
break;
case M4:
/*
* bottom-most marg
*
* .m4 N
*/
set (&pg.m4val, val, argtyp, 2, 0, HUGE);
pg.bottom = pg.plval - pg.m4val - pg.m3val;
break;
case MACRO:
/*
* macro expansion
*
* (internal)
*/
maceval (p, macexp);
break;
case NA:
/*
* no adjust
*
* .na
*/
dc.adjval = ADJ_OFF;
dc.juval = NO;
break;
case NE:
/*
* need n lines
*
* .ne N
*/
robrk ();
if ((pg.bottom - pg.lineno + 1) < (val * dc.lsval))
{
space (HUGE);
}
break;
case NF:
/*
* no fill
*
* .nf
*/
robrk ();
dc.fill = NO;
break;
case NJ:
/*
* no justify
*
* .nj
*/
dc.juval = NO;
break;
case NR:
/*
* set number reg
*
* .nr R +/-N M
*/
p = skipwd (p);
p = skipbl (p);
if (!isalpha (*p))
{
fprintf (err_stream,
"***%s: invalid or missing number register name\n",
myname);
}
else
{
/*
* indx is the register, R, and val is the final
* value (default = 0). getval does skipwd,skipbl
*/
indx = tolower (*p) - 'a';
val = getval (p, &argtyp);
set (&dc.nr[indx], val, argtyp, 0, -INFINITE, INFINITE);
/*
* now get autoincrement M, if any (default = 1).
* getval does skipwd,skipbl
*/
p = skipwd (p);
p = skipbl (p);
val = getval (p, &argtyp);
set (&dc.nrauto[indx], val, '1', 1, -INFINITE, INFINITE);
}
break;
case OF:
/*
* odd footer
*
* .of "a" "b" "c"
*/
gettl (p, pg.ofoot, &pg.oflim[0]);
break;
case OH:
/*
* odd header
*
* .oh "a" "b" "c"
*/
gettl (p, pg.ohead, &pg.ohlim[0]);
break;
case PC:
/*
* page number char
*
* .pc [c=NULL]
*/
if (argtyp == '\r' || argtyp == '\n')
dc.pgchr = EOS;
else
dc.pgchr = argtyp;
break;
case PL:
/*
* page length
*
* .pl N
*/
set (&pg.plval,
val,
argtyp,
PAGELEN,
pg.m1val + pg.m2val + pg.m3val + pg.m4val + 1,
HUGE);
set_ireg (".p", pg.plval, 0);
pg.bottom = pg.plval - pg.m3val - pg.m4val;
break;
case PM:
/*
* print macro names and sizes
*
* .pm [t]
*/
if (argtyp == '\r' || argtyp == '\n')
printmac (0);
else if (argtyp == 't')
printmac (1);
else if (argtyp == 'T')
printmac (2);
else
printmac (0);
break;
case PN:
/*
* page number
*
* .pn N
*/
tmp = pg.curpag;
set (&pg.curpag, val - 1, argtyp, tmp, -HUGE, HUGE);
pg.newpag = pg.curpag + 1;
set_ireg ("%", pg.newpag, 0);
break;
case PO:
/*
* page offset
*
* .po N
*/
set (&pg.offset, val, argtyp, 0, 0, HUGE);
set_ireg (".o", pg.offset, 0);
break;
case RR:
/*
* unset number reg
*
* .rr R
*/
p = skipwd (p);
p = skipbl (p);
if (!isalpha (*p))
{
fprintf (err_stream,
"***%s: invalid or missing number register name\n",
myname);
}
else
{
indx = tolower (*p) - 'a';
val = 0;
set (&dc.nr[indx], val, argtyp, 0, -HUGE, HUGE);
}
break;
case SO:
/*
* source file
*
* .so name
*/
p = skipwd (p);
p = skipbl (p);
if (getwrd (p, name) == 0)
break;
if (dc.flevel + 1 >= Nfiles)
{
fprintf (err_stream,
"***%s: .so commands nested too deeply\n",
myname);
err_exit (-1);
}
if ((sofile[dc.flevel + 1] = fopen (name, "r")) == NULL)
{
fprintf (err_stream,
"***%s: unable to open %s\n", myname, name);
err_exit (-1);
}
dc.flevel += 1;
break;
case SP:
/*
* space
*
* .sp [N=1]
*/
set (&spval, val, argtyp, 1, 0, HUGE);
space (spval);
break;
case TI:
/*
* temporary indent
*
* .ti [+/-N]
*/
robrk ();
set (&dc.tival, val, argtyp, 0, 0, dc.rmval);
break;
case UL:
/*
* underline
*
* .ul [N]
*/
set (&dc.ulval, val, argtyp, 0, 1, HUGE);
dc.cuval = dc.boval = 0;
break;
}
}
/*------------------------------*/
/* comtyp */
/*------------------------------*/
comtyp (p, m)
register char *p;
char *m;
{
/*
* decodes nro command and returns its associated
* value.
*/
register char c1;
register char c2;
char *s;
char macnam[MNLEN];
/*
* skip past dot and any whitespace
*/
p++;
while (*p && (*p == ' ' || *p == '\t'))
p++;
if (*p == '\0')
return (COMMENT);
/*
* First check to see if the command is a macro.
* If it is, truncate to two characters and return
* expansion in m. Note that upper and lower case
* characters are handled differently.
*/
getwrd (p, macnam);
macnam[2] = EOS;
if ((s = getmac (macnam)) != NULL)
{
strcpy (m, s);
return (MACRO);
}
c1 = *p++;
c2 = *p;
if (c1 == '\\' && c2 == '\"') return (COMMENT);
if (c1 == 'a' && c2 == 'f') return (AF);
if (c1 == 'a' && c2 == 'd') return (AD);
if (c1 == 'b' && c2 == 'o') return (BO);
if (c1 == 'b' && c2 == 'p') return (BP);
if (c1 == 'b' && c2 == 'r') return (BR);
if (c1 == 'b' && c2 == 's') return (BS);
if (c1 == 'c' && c2 == 'c') return (CC);
if (c1 == 'c' && c2 == 'e') return (CE);
if (c1 == 'c' && c2 == 'u') return (CU);
if (c1 == 'd' && c2 == 'e') return (DE);
if (c1 == 'd' && c2 == 's') return (DS);
if (c1 == 'e' && c2 == 'f') return (EF);
if (c1 == 'e' && c2 == 'c') return (EC);
if (c1 == 'e' && c2 == 'h') return (EH);
if (c1 == 'e' && c2 == 'n') return (EN);
if (c1 == '.') return (EN);
if (c1 == 'e' && c2 == 'o') return (EO);
if (c1 == 'f' && c2 == 'i') return (FI);
if (c1 == 'f' && c2 == 'l') return (FL);
if (c1 == 'f' && c2 == 'o') return (FO);
if (c1 == 'f' && c2 == 't') return (FT);
if (c1 == 'h' && c2 == 'e') return (HE);
if (c1 == 'i' && c2 == 'n') return (IN);
if (c1 == 'j' && c2 == 'u') return (JU);
if (c1 == 'l' && c2 == 'l') return (LL);
if (c1 == 'l' && c2 == 's') return (LS);
if (c1 == 'm' && c2 == '1') return (M1);
if (c1 == 'm' && c2 == '2') return (M2);
if (c1 == 'm' && c2 == '3') return (M3);
if (c1 == 'm' && c2 == '4') return (M4);
if (c1 == 'n' && c2 == 'a') return (NA);
if (c1 == 'n' && c2 == 'e') return (NE);
if (c1 == 'n' && c2 == 'f') return (NF);
if (c1 == 'n' && c2 == 'j') return (NJ);
if (c1 == 'n' && c2 == 'r') return (NR);
if (c1 == 'o' && c2 == 'f') return (OF);
if (c1 == 'o' && c2 == 'h') return (OH);
if (c1 == 'p' && c2 == 'c') return (PC);
if (c1 == 'p' && c2 == 'l') return (PL);
if (c1 == 'p' && c2 == 'm') return (PM);
if (c1 == 'p' && c2 == 'o') return (PO);
if (c1 == 'r' && c2 == 'm') return (RM);
if (c1 == 'r' && c2 == 'r') return (RR);
if (c1 == 's' && c2 == 'o') return (SO);
if (c1 == 's' && c2 == 'p') return (SP);
if (c1 == 't' && c2 == 'i') return (TI);
if (c1 == 't' && c2 == 'l') return (TL);
if (c1 == 'u' && c2 == 'l') return (UL);
if (c1 == 'p' && c2 == 'n') return (PN);
if (c1 == 'r' && c2 == 'r') return (RR);
if (c1 == 'c' && c2 == '2') return (C2);
if (c1 == 't' && c2 == 'r') return (TR);
if (c1 == 'l' && c2 == 't') return (LT);
if (c1 == 'f' && c2 == 'c') return (FC);
return (UNKNOWN);
}
/*------------------------------*/
/* gettl */
/*------------------------------*/
gettl (p, q, limit)
register char *p;
register char *q;
int limit[];
{
/*
* get header or footer title
*/
/*
* skip forward a word...
*/
p = skipwd (p);
p = skipbl (p);
/*
* copy and set limits
*/
strcpy (q, p);
limit[LEFT] = dc.inval;
limit[RIGHT] = dc.rmval;
}
/*------------------------------*/
/* getval */
/*------------------------------*/
getval (p, p_argt)
register char *p;
register char *p_argt;
{
/*
* retrieves optional argument following nro command.
* returns positive integer value with sign (if any)
* saved in character addressed by p_argt.
*/
p = skipwd (p);
p = skipbl (p);
*p_argt = *p;
if ((*p == '+') || (*p == '-'))
++p;
return (ctod (p));
}
/*------------------------------*/
/* set */
/*------------------------------*/
set (param, val, type, defval, minval, maxval)
register int *param;
register int val;
register char type;
register int defval;
register int minval;
register int maxval;
{
/*
* set parameter and check range. this is for basically all commands
* which take interger args
*
* no param (i.e. \r or \n) means reset default
* + means param += val (increment)
* - means param -= val (decrement)
* anything else makes an assignment within the defined numerical limits
*
* examples:
*
* .nr a 14 set register 'a' to 14
* .nr a +1 increment register 'a' by 1
* .nr a reset register 'a' to default value (0)
*/
switch (type)
{
case '\r':
case '\n':
*param = defval;
break;
case '+':
*param += val;
break;
case '-':
*param -= val;
break;
default:
*param = val;
break;
}
*param = min (*param, maxval);
*param = max (*param, minval);
}
/*------------------------------*/
/* set_ireg */
/*------------------------------*/
set_ireg (name, val, opt)
register char *name;
register int val;
register int opt; /* 0=internal, 1=user set */
{
/*
* set internal register "name" to val. ret 0 if ok, else -1 if reg not
* found or 1 if read only
*/
register int nreg;
nreg = findreg (name);
if (nreg < 0)
return (-1);
if ((rg[nreg].rflag & RF_WRITE) || (opt == 0))
{
rg[nreg].rval = val;
return (0);
}
return (1);
}
@//E*O*F command.c//
chmod u=rw,g=r,o=r command.c
echo x - text.c
sed 's/^@//' > "text.c" <<'@//E*O*F text.c//'
/*
* text.c - text output processing portion of nroff word processor
*
* adapted for atariST/TOS by Bill Rosenkranz 11/89
* net: rosenkra@hall.cray.com
* CIS: 71460,17
* GENIE: W.ROSENKRANZ
*
* original author:
*
* Stephen L. Browning
* 5723 North Parker Avenue
* Indianapolis, Indiana 46220
*
* history:
*
* - Originally written in BDS C;
* - Adapted for standard C by W. N. Paul
* - Heavily hacked up to conform to "real" nroff by Bill Rosenkranz
*/
#undef NRO_MAIN /* extern globals */
#include <stdio.h>
#include "nroff.h"
/*------------------------------*/
/* text */
/*------------------------------*/
text (p)
register char *p;
{
/*
* main text processing
*/
register int i;
char wrdbuf[MAXLINE];
/*
* skip over leading blanks if in fill mode. we indent later.
* since leadbl does a robrk, do it if in .nf mode
*/
if (dc.fill == YES)
{
if (*p == ' ' || *p == '\n' || *p == '\r')
leadbl (p);
}
else
robrk ();
/*
* expand escape sequences
*/
expesc (p, wrdbuf);
/*
* test for how to output
*/
if (dc.ulval > 0)
{
/*
* underline (.ul)
*
* Because of the way underlining is handled,
* MAXLINE should be declared to be three times
* larger than the longest expected input line
* for underlining. Since many of the character
* buffers use this parameter, a lot of memory
* can be allocated when it may not really be
* needed. A MAXLINE of 180 would allow about
* 60 characters in the output line to be
* underlined (remember that only alphanumerics
* get underlined - no spaces or punctuation).
*/
underl (p, wrdbuf, MAXLINE);
--dc.ulval;
}
if (dc.cuval > 0)
{
/*
* continuous underline (.cu)
*/
underl (p, wrdbuf, MAXLINE);
--dc.cuval;
}
if (dc.boval > 0)
{
/*
* bold (.bo)
*/
bold (p, wrdbuf, MAXLINE);
--dc.boval;
}
if (dc.ceval > 0)
{
/*
* centered (.ce)
*/
center (p);
put (p);
--dc.ceval;
}
else if ((*p == '\r' || *p == '\n') && dc.fill == NO)
{
/*
* all blank line
*/
put (p);
}
else if (dc.fill == NO)
{
/*
* unfilled (.nf)
*/
put (p);
}
else
{
/*
* anything else...
*
* init escape char counter for this line...
*/
co.outesc = 0;
/*
* get a word and put it out. increment ptr to the next
* word.
*/
while ((i = getwrd (p, wrdbuf)) > 0)
{
co.outesc += countesc (wrdbuf);
putwrd (wrdbuf);
p += i;
}
}
}
/*------------------------------*/
/* bold */
/*------------------------------*/
bold (p0, p1, size)
register char *p0;
register char *p1;
int size;
{
/*
* insert bold face text (by overstriking)
*/
register int i;
register int j;
j = 0;
for (i = 0; (p0[i] != '\n') && (j < size - 1); ++i)
{
if (isalpha (p0[i]) || isdigit (p0[i]))
{
p1[j++] = p0[i];
p1[j++] = '\b';
}
p1[j++] = p0[i];
}
p1[j++] = '\n';
p1[j] = EOS;
while (*p1 != EOS)
*p0++ = *p1++;
*p0 = EOS;
}
/*------------------------------*/
/* center */
/*------------------------------*/
center (p)
register char *p;
{
/*
* center a line by setting tival
*/
dc.tival = max ((dc.rmval + dc.tival - width (p)) >> 1, 0);
}
/*------------------------------*/
/* expand */
/*------------------------------*/
expand (p0, c, s)
register char *p0;
char c;
register char *s;
{
/*
* expand title buffer to include character string
*/
register char *p;
register char *q;
register char *r;
char tmp[MAXLINE];
p = p0;
q = tmp;
while (*p != EOS)
{
if (*p == c)
{
r = s;
while (*r != EOS)
*q++ = *r++;
}
else
*q++ = *p;
++p;
}
*q = EOS;
strcpy (p0, tmp); /* copy it back */
}
/*------------------------------*/
/* justcntr */
/*------------------------------*/
justcntr (p, q, limit)
register char *p;
char *q;
int limit[];
{
/*
* center title text into print buffer
*/
register int len;
len = width (p);
q = &q[(limit[RIGHT] + limit[LEFT] - len) >> 1];
while (*p != EOS)
*q++ = *p++;
}
/*------------------------------*/
/* justleft */
/*------------------------------*/
justleft (p, q, limit)
register char *p;
char *q;
int limit;
{
/*
* left justify title text into print buffer
*/
q = &q[limit];
while (*p != EOS)
*q++ = *p++;
}
/*------------------------------*/
/* justrite */
/*------------------------------*/
justrite (p, q, limit)
register char *p;
char *q;
int limit;
{
/*
* right justify title text into print buffer
*/
register int len;
len = width (p);
q = &q[limit - len];
while (*p != EOS)
*q++ = *p++;
}
/*------------------------------*/
/* leadbl */
/*------------------------------*/
leadbl (p)
register char *p;
{
/*
* delete leading blanks, set tival
*/
register int i;
register int j;
/*
* end current line and reset co struct
*/
robrk ();
/*
* skip spaces
*/
for (i = 0; p[i] == ' ' || p[i] == '\t'; ++i)
;
/*
* if not end of line, reset current temp indent
*/
if (p[i] != '\n' && p[i] != '\r')
dc.tival = i;
/*
* shift string
*/
for (j = 0; p[i] != EOS; ++j)
p[j] = p[i++];
p[j] = EOS;
}
/*------------------------------*/
/* pfoot */
/*------------------------------*/
pfoot ()
{
/*
* put out page footer
*/
if (dc.prflg == TRUE)
{
skip (pg.m3val);
if (pg.m4val > 0)
{
if ((pg.curpag % 2) == 0)
{
puttl (pg.efoot, pg.eflim, pg.curpag);
}
else
{
puttl (pg.ofoot, pg.oflim, pg.curpag);
}
skip (pg.m4val - 1);
}
}
}
/*------------------------------*/
/* phead */
/*------------------------------*/
phead ()
{
/*
* put out page header
*/
pg.curpag = pg.newpag;
if (pg.curpag >= pg.frstpg && pg.curpag <= pg.lastpg)
{
dc.prflg = TRUE;
}
else
{
dc.prflg = FALSE;
}
++pg.newpag;
set_ireg ("%", pg.newpag, 0);
if (dc.prflg == TRUE)
{
if (pg.m1val > 0)
{
skip (pg.m1val - 1);
if ((pg.curpag % 2) == 0)
{
puttl (pg.ehead, pg.ehlim, pg.curpag);
}
else
{
puttl (pg.ohead, pg.ohlim, pg.curpag);
}
}
skip (pg.m2val);
}
/*
* initialize lineno for the next page
*/
pg.lineno = pg.m1val + pg.m2val + 1;
set_ireg ("ln", pg.lineno, 0);
}
/*------------------------------*/
/* puttl */
/*------------------------------*/
puttl (p, lim, pgno)
register char *p;
int lim[];
int pgno;
{
/*
* put out title or footer
*/
register int i;
char pn[8];
char t[MAXLINE];
char h[MAXLINE];
char delim;
itoda (pgno, pn, 6);
for (i = 0; i < MAXLINE; ++i)
h[i] = ' ';
delim = *p++;
p = getfield (p, t, delim);
expand (t, dc.pgchr, pn);
justleft (t, h, lim[LEFT]);
p = getfield (p, t, delim);
expand (t, dc.pgchr, pn);
justcntr (t, h, lim);
p = getfield (p, t, delim);
expand (t, dc.pgchr, pn);
justrite (t, h, lim[RIGHT]);
for (i = MAXLINE - 4; h[i] == ' '; --i)
h[i] = EOS;
h[++i] = '\n';
h[++i] = '\r';
h[++i] = EOS;
if (strlen (h) > 2)
{
for (i = 0; i < pg.offset; ++i)
prchar (' ', pout);
}
putlin (h, pout);
}
/*------------------------------*/
/* putwrd */
/*------------------------------*/
putwrd (wrdbuf)
register char *wrdbuf;
{
/*
* put word in output buffer
*/
register char *p0;
register char *p1;
int w;
int last;
int llval;
int nextra;
/*
* check if this word puts us over the limit
*/
w = width (wrdbuf);
last = strlen (wrdbuf) + co.outp;
llval = dc.rmval - dc.tival;
if (((co.outp > 0) && ((co.outw + w) > llval))
|| (last > MAXLINE))
{
/*
* last word exceeds limit so prepare to break line, print
* it, and reset outbuf.
*/
last -= co.outp;
if (dc.juval == YES)
{
nextra = llval - co.outw + 1;
/*
* Check whether last word was end of
* sentence and modify counts so that
* it is right justified.
*/
if (co.outbuf[co.outp - 2] == ' ')
{
--co.outp;
++nextra;
}
spread (co.outbuf, co.outp - 1, nextra, co.outwds, co.outesc);
if ((nextra > 0) && (co.outwds > 1))
{
co.outp += (nextra - 1);
}
/* if (co.outesc > 0)
{
co.outp += co.outesc;
}
*/
}
/*
* break line, output it, and reset all co members. reset
* esc count.
*/
robrk ();
co.outesc = countesc (wrdbuf);
}
/*
* copy the current word to the out buffer which may have been
* reset
*/
p0 = wrdbuf;
p1 = co.outbuf + co.outp;
while (*p0 != EOS)
*p1++ = *p0++;
co.outp = last;
co.outbuf[co.outp++] = ' ';
co.outw += w + 1;
co.outwds += 1;
}
/*------------------------------*/
/* skip */
/*------------------------------*/
skip (n)
register int n;
{
/*
* skips the number of lines specified by n.
*/
register int i;
if (dc.prflg == TRUE && n > 0)
{
for (i = 0; i < n; ++i)
{
prchar ('\n', pout);
}
prchar ('\r', pout);
}
}
/*------------------------------*/
/* spread */
/*------------------------------*/
spread (p, outp, nextra, outwds, escapes)
register char *p;
int outp;
int nextra;
int outwds;
int escapes;
{
/*
* spread words to justify right margin
*/
register int i;
register int j;
register int nb;
register int ne;
register int nholes;
int jmin;
/*
* quick sanity check...
*/
if ((nextra <= 0) || (outwds <= 1))
return;
/*fflush (pout); fprintf (err_stream, "in spread: escapes = %d\n", escapes); fflush (err_stream);*/
/*
* set up for the spread and do it...
*/
dc.sprdir = ~dc.sprdir;
ne = nextra;
nholes = outwds - 1; /* holes between words */
i = outp - 1; /* last non-blank character */
j = min (MAXLINE - 3, i + ne); /* leave room for CR,LF,EOS */
/*
j += escapes;
if (p[i-1] == 27)
j += 2;
j = min (j, MAXLINE - 3);
*/
while (i < j)
{
p[j] = p[i];
if (p[i] == ' ')
{
if (dc.sprdir == 0)
nb = (ne - 1) / nholes + 1;
else
nb = ne / nholes;
ne -= nb;
--nholes;
for (; nb > 0; --nb)
{
--j;
p[j] = ' ';
}
}
--i;
--j;
}
}
/*------------------------------*/
/* strkovr */
/*------------------------------*/
strkovr (p, q)
register char *p;
register char *q;
{
/*
* split overstrikes (backspaces) into seperate buffer
*/
register char *pp;
int bsflg;
bsflg = FALSE;
pp = p;
while (*p != EOS)
{
*q = ' ';
*pp = *p;
++p;
if (*p == '\b')
{
if (*pp >= ' ' && *pp <= '~')
{
bsflg = TRUE;
*q = *pp;
++p;
*pp = *p;
++p;
}
}
++q;
++pp;
}
*q++ = '\r';
*q = *pp = EOS;
return (bsflg);
}
/*------------------------------*/
/* underl */
/*------------------------------*/
underl (p0, p1, size)
register char *p0;
register char *p1;
int size;
{
/*
* underline a line
*/
register int i;
register int j;
j = 0;
for (i = 0; (p0[i] != '\n') && (j < size - 1); ++i)
{
if (p0[i] >= ' ' && p0[i] <= '~')
{
if (isalpha (p0[i]) || isdigit (p0[i]) || dc.cuval > 0)
{
p1[j++] = '_';
p1[j++] = '\b';
}
}
p1[j++] = p0[i];
}
p1[j++] = '\n';
p1[j] = EOS;
while (*p1 != EOS)
*p0++ = *p1++;
*p0 = EOS;
}
/*------------------------------*/
/* width */
/*------------------------------*/
width (s)
register char *s;
{
/*
* compute width of character string
*/
register int w;
w = 0;
while (*s != EOS)
{
if (*s == '\b')
--w;
else if (*s != '\n' && *s != '\r')
++w;
++s;
}
return (w);
}
@//E*O*F text.c//
chmod u=rw,g=r,o=r text.c
echo x - io.c
sed 's/^@//' > "io.c" <<'@//E*O*F io.c//'
/*
* io.c - low level I/O processing portion of nroff word processor
*
* adapted for atariST/TOS by Bill Rosenkranz 11/89
* net: rosenkra@hall.cray.com
* CIS: 71460,17
* GENIE: W.ROSENKRANZ
*
* original author:
*
* Stephen L. Browning
* 5723 North Parker Avenue
* Indianapolis, Indiana 46220
*
* history:
*
* - Originally written in BDS C;
* - Adapted for standard C by W. N. Paul
* - Heavily hacked up to conform to "real" nroff by Bill Rosenkranz
*/
#undef NRO_MAIN /* extern globals */
#include <stdio.h>
#include "nroff.h"
/*------------------------------*/
/* getlin */
/*------------------------------*/
getlin (p, in_buf)
char *p;
FILE *in_buf;
{
/*
* retrieve one line of input text
*/
register char *q;
register int i;
int c;
int nreg;
q = p;
for (i = 0; i < MAXLINE - 1; ++i)
{
c = ngetc (in_buf);
if (c == EOF)
{
*q = EOS;
c = strlen (p);
return (c == 0 ? EOF : c);
}
*q++ = c;
if (c == '\n')
break;
}
*q = EOS;
nreg = findreg (".c");
if (nreg > 0)
set_ireg (".c", rg[nreg].rval + 1, 0);
return (strlen (p));
}
/*------------------------------*/
/* ngetc */
/*------------------------------*/
ngetc (infp)
FILE *infp;
{
/*
* get character from input file or push back buffer
*/
register int c;
if (mac.ppb >= &mac.pbb[0])
c = *mac.ppb--;
else
c = getc (infp);
return (c);
}
/*------------------------------*/
/* pbstr */
/*------------------------------*/
pbstr (p)
char p[];
{
/*
* Push back string into input stream
*/
register int i;
/*
* if string is null, we do nothing
*/
for (i = strlen (p) - 1; i >= 0; --i)
{
putbak (p[i]);
}
}
/*------------------------------*/
/* putbak */
/*------------------------------*/
putbak (c)
char c;
{
/*
* Push character back into input stream. we use the push-back buffer
* stored with macros.
*/
if (mac.ppb < &(mac.pbb[0]))
{
mac.ppb = &(mac.pbb[0]);
*mac.ppb = c;
}
else
{
if (mac.ppb >= &mac.pbb[MAXLINE - 1])
{
fprintf (err_stream,
"***%s: push back buffer overflow\n", myname);
err_exit (-1);
}
*++(mac.ppb) = c;
}
}
/*------------------------------*/
/* prchar */
/*------------------------------*/
prchar (c, fp)
char c;
FILE *fp;
{
/*
* print character with test for printer
*/
putc (c, fp);
}
/*------------------------------*/
/* put */
/*------------------------------*/
put (p)
char *p;
{
/*
* put out line with proper spacing and indenting
*/
register int j;
char os[MAXLINE];
if (pg.lineno == 0 || pg.lineno > pg.bottom)
{
phead ();
}
if (dc.prflg == TRUE)
{
if (!dc.bsflg)
{
if (strkovr (p, os) == TRUE)
{
for (j = 0; j < pg.offset; ++j)
prchar (' ', pout);
for (j = 0; j < dc.tival; ++j)
prchar (' ', pout);
putlin (os, pout);
}
}
for (j = 0; j < pg.offset; ++j)
prchar (' ', pout);
for (j = 0; j < dc.tival; ++j)
prchar (' ', pout);
putlin (p, pout);
}
dc.tival = dc.inval;
skip (min (dc.lsval - 1, pg.bottom - pg.lineno));
pg.lineno = pg.lineno + dc.lsval;
set_ireg ("ln", pg.lineno, 0);
if (pg.lineno > pg.bottom)
pfoot ();
}
/*------------------------------*/
/* putlin */
/*------------------------------*/
putlin (p, pbuf)
register char *p;
FILE *pbuf;
{
/*
* output a null terminated string to the file
* specified by pbuf.
*/
while (*p != EOS)
prchar (*p++, pbuf);
}
@//E*O*F io.c//
chmod u=rw,g=r,o=r io.c
exit 0