/********************************************************/
/*							*/
/*	ro_text.c	text-handling routines for ro	*/
/*							*/
/*	ro version 1.00					*/
/*							*/
/*	Portions copyright (c) 1989 by Ted A. Campbell	*/
/*		Bywater Software			*/
/*		P. O. Box 4023				*/
/*		Duke Station				*/
/*		Durham, NC  27706			*/
/*							*/
/*	Contains portions of ROFF4, Version 1.61	*/
/*      (c) 1985 by Konrad Kwok                         */
/*		20 3rd Street, Section M		*/
/*		Fariview Park,				*/
/*		Hong Kong				*/
/*							*/
/*      Contains portions of ROFF4, Version 1.60        */
/*      (c) 1983, 4 by Ernest E. Bergmann               */
/*              Physics, Building #16                   */
/*              Lehigh University                       */
/*              Bethlehem, Pa. 18015                    */
/*                                                      */
/*	ro and its predecessor ROFF4 are based on 	*/
/*	the ROFF text processor described in Kernigan	*/
/*	and Plauger's now-classic text <Software Tools> */
/*							*/
/* Permission is hereby granted for all commercial and	*/
/* non-commercial reproduction and distribution of this */
/* material provided this notice is included.		*/
/*							*/
/********************************************************/

#include "ro.h"

/**************************************************
handles case of leading blanks or tabs; empty lines 
***************************************************/

leadbl( line )
	char *line;
	{
	int i, j, white;
	ro_brk();
	for ( white = 0, i = 0; line[i] == ' ' || line[i] == '\t'; i++ )
		{
		if (line[i] == ' ')
			white++;
		else
			white = ro_min( ro_rmval[0], ro_tabsiz[0]*(1+white/ro_tabsiz[0]));
		}

	if ( line[i] != NEWLINE )
		ro_tival += white;

	/* move line to left */
	for( j = 0; (line[j] = line[i]) != '\0'; j++, i++ );
	}

/*****************************************
puts out page header
******************************************/

phead()
	{
	exchange();
	ro_uf=ro_xf=FALSE;
	ro_mcnt=1;
	ro_curpag = ro_newpag++;
	preregister( "%", ro_curpag );
	if((ro_curpag<ro_firstpage)||(ro_curpag>ro_lastpage))
		ro_suppress=TRUE;
	else
		ro_suppress=FALSE;
	ro_oldln=-1;
	if( ro_pagestop )
		{
		fprintf( stderr, "%cPAGE:  Please type <RETURN> to continue:  ",
			BELL );
		getchar(); 		/* wait until char typed at console */ 
		}
	ro_plineno=0;
	ro_pflineno=0;
	if (ro_m1val[0] > 0 )
		{ 
		ro_vlineno = ro_m1val[0]-1;
		if (ro_curpag % 2) puttl3 ( ro_ohead, ro_oh2, ro_oh3, ro_curpag );
		else puttl3 ( ro_ehead, ro_eh2, ro_eh3, ro_curpag );
		}
	ro_vlineno = ro_m1val[0]+ro_m2val[0]; 
	ro_vflineno=0;
	exchange();
	}

/**************************************
puts out page footer
***************************************/

pfoot()
	{
	exchange();
	ro_uf=ro_xf=FALSE;
	ro_mcnt=1;
	ro_vlineno = ro_bottom+ro_m3val[0]; 
	ro_vflineno=0;
	if ( ro_m4val[0] > 0 )
		{ 
		if(ro_curpag % 2)puttl3 ( ro_ofoot,ro_of2,ro_of3, ro_curpag );
		else puttl3(ro_efoot,ro_ef2,ro_ef3,ro_curpag);
		}
	ro_vlineno = ro_plval[0];
	ro_vflineno=0;
	if (ro_useff) putchar(FORMF);
	else padv();
	ro_oldbot=ro_plineno=ro_pflineno=0; /*printer at start of newpage*/
	ro_oldln=-1;
	exchange();
	}

/**********************************************
space n lines or to bottom of the page
***********************************************/

do_space( n )
	int n;
	{
	ro_brk(); /* flush out last unfilled line */
	if ( ro_vlineno >= ro_bottom)	
		{
		return; /* end of page */
		}
	if ( ro_vlineno < 0) 
		{
		phead(); /* top of page */
		}
	ro_vlineno += n;

	if ( ro_vlineno >= ro_bottom ) 
		{
		pfoot(); /* print footer if bottom */
		}
	}

/*******************************************************/

text (line)
	char *line;
	{
	char wrdbuf [LSZ];
	int i, j, k;
	char *p1, *p2;
	if DEBUG fprintf( stderr, "DEBUG:  text: <%s> \n", line);

	if (line[0] == BLANK || line[0]==NEWLINE || line[0] == TAB)
		leadbl (line);
	if (ro_ceval > 0)
		{ 
		center(line);
		put(line);
		ro_ceval--;
		}
	else if ( ( line[0] == NEWLINE ) || ( line[0] == '\0' ))
		{
		do_space( ro_lsval[0] );
		}
	else if(!ro_fill[0])
		put(line);
	else
		while (WE_HAVE_A_WORD == getwrd (line, wrdbuf))
			putwrd (wrdbuf);
	}

/******************************************************
put out a line of text with correct indentation
underlining if specified
*******************************************************/

put (line)
	char *line;
	{
	int i, fs, minfs;
	if ((ro_vlineno < 0)||(ro_vlineno >= ro_bottom))
		{
		phead();
		}
	fs=(ro_vlineno-ro_oldln)*ro_frval;
	minfs=ro_oldbot-ro_outtop; 
	if(!(ro_oldbot&&ro_outtop))
		{
		minfs++;
		}
	while ( fs < minfs )
		{
		fs += ro_frval;
		ro_vlineno++;
		}
	need(0);
	putline(line);
	ro_tival = ro_inval[0];
	ro_vlineno += ro_lsval[0];
	if (ro_vlineno >= ro_bottom)
		{
		pfoot();
		}
	}

/***********************************************************
concatenates the word onto the end of ro_outbuf for filled text
************************************************************/

putwrd (wrdbuf) /*Nov 22: ro_sentence*/
	char *wrdbuf;
	{
	int i, j, k;
	char s[MAXLINE], ch;
	int line_len, new_out_width, wid;
	int nextra;
	skip_blanks (wrdbuf); 
	trunc_bl (wrdbuf);
	wid =1+ro_sentence+strln3(wrdbuf,TRUE,1);/*sets ro_wtop,ro_wbot*/
	line_len = ro_rmval[0] - ro_tival;
	new_out_width = ro_outw+wid;
	if (new_out_width > ro_min(line_len, MAXLINE-1))
		{ 
		nextra = ro_min(line_len, MAXLINE-1)-ro_outw+1;
		if(ro_outbuf[ro_outpos-2]==BLANK) nextra++;
		if(ro_adjust) spread(ro_outbuf,nextra,ro_outwrds);
		ro_brk();
		}
	ro_outw += wid;
	OUTcat(wrdbuf);
	OUTSP(); 
	if(ro_sentence) OUTSP();
	ro_outwrds++;
	if(ro_wtop<ro_outtop) ro_outtop=ro_wtop;
	if(ro_wbot>ro_outbot) ro_outbot=ro_wbot;
	}

/**********************************************************
a new putline routine; sends line to	OUTPUT2
***********************************************************/

putline (line)
	char *line;
	{
	char c;
	blanks ( ro_tival );
	for ( ; c = *line; line++ )
		{
		putout(c);
		}
	putout('\0');
	printout();
	}

/****************************************/

OUTcat(str)	 /*appends string to ro_outbuf*/
	char *str;
	{
	while(ro_outbuf[ro_outpos]=*(str++))
		ro_outpos++;
	}

/****************************************/

OUTSP()		 /*appends BLANK to ro_outbuf*/
	{
	ro_outbuf[ro_outpos++]=BLANK;
	ro_outbuf[ro_outpos]='\0';
	}

/****************************************/

gloss() /*prints on STDOUT a glossary of .tr chars*/
	{
	int i;
	char line[20],tcs;
	put("GLOSSARY:");
	put("USE	 <GET>");
	tcs=ro_tcval[0];
	ro_tcval[0] |= 128; /*set most significant bit*/
	for(i=1;i<19;i++) line[i]=' ';
	line[0]=tcs;
	line[8]='<';
	line[9]=ro_tcval[0];
	line[11]='>';
	line[12]='\0';
	for(i=' ';i<127;i++)
		{
		if(ro_tptr[i-' '])
			{
			line[1]=line[10]=i;
			put(line);
			}
		}
	ro_tcval[0]=tcs;
	do_space(HUGE);
	}

/***************************************/

exchange() /*maintain separate environment for headers and
		footers*/
	{
	int i;
	i=ro_mcnt2; 
	ro_mcnt2=ro_mcnt; 
	ro_mcnt=i;
	i=ro_xf2; 
	ro_xf2=ro_xf; 
	ro_xf=i;
	i=ro_uf2; 
	ro_uf2=ro_uf; 
	ro_uf=i;
	}
