Minix1.5/commands/nroff/text.c

Compare this file to the similar file:
Show the results in this format:

/*
 *	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
 *	- Adapted the justification of lines with escape codes 
 *	  by Wim 'Blue Baron' van Dorst (wsincc@tuerc3.urc.tue.nl)
 */

#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...
		 */

		/*
		 *   get a word and put it out. increment ptr to the next
		 *   word.
		 */
		while ((i = getwrd (p, wrdbuf)) > 0)
		{
			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
	 */
#ifdef GEMDOS
	if (p[i] != '\n' && p[i] != '\r')
		dc.tival = i;
#else
	if (p[i] != '\n' && p[i] != '\r')
		dc.tival = i;
#endif

	/*
	 *   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';
#ifdef GEMDOS
	h[++i] = '\r';
#endif
	h[++i] = EOS;
	if (strlen (h) > 2)
	{
		for (i = 0; i < pg.offset; ++i)
			prchar (' ', out_stream);
	}
	putlin (h, out_stream);
}





/*------------------------------*/
/*	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;
	co.outesc += countesc (wrdbuf);
	if (((co.outp > 0) && ((co.outw + w - co.outesc) > 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;

			/*
			 *	Do not take in the escape char of the
			 * 	word that didn't fit on this line anymore
			 */
			 co.outesc -= countesc (wrdbuf);
			
			/* 
			 *	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 + co.outesc > 0) && (co.outwds > 1))
			{
				co.outp += (nextra + co.outesc - 1);
			}
		}

		/*
		 *   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', out_stream);
		}
#ifdef GEMDOS
		prchar ('\r', out_stream);
#endif
	}
}





/*------------------------------*/
/*	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 + escapes < 1) || (outwds < 2))
		return;

	/*
	 *   set up for the spread and do it...
	 */
	dc.sprdir = ~dc.sprdir;
	ne        = nextra + escapes;
	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 */

	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);
}