/********************************************************/
/*							*/
/*	ro_proc.c	various procedures 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.60	*/
/*	(c) 1983, 4 by Ernest E. Bergmann		*/
/*		Physics, Building #16			*/
/*		Lehigh University			*/
/*		Bethlehem, Pa. 18015			*/
/*							*/
/*	Contains portions of ROFF4, Version 1.61	*/
/*	(c) 1985 by Konrad Kwok				*/
/*		20 3rd Street, Section M		*/
/*		Fariview Park,				*/
/*		Hong Kong				*/
/*							*/
/*	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"

/**********************************************************
Removes white-space characters at start of string.
***********************************************************/

skip_blanks ( string )
	char *string;	 /* cursor to original string */
	{
	char *p;	 /* cursor to 'final' string */
	for(p=string;*string==BLANK||*string==TAB||*string==NEWLINE;
		string++);
		while(*(p++) = *(string++));
	}

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

int comtyp (line)
	char *line;
	{
	char let1, let2;
	let1 = line[1];
	let2 = line[2];

	if ( let1==COMMAND )		return( EM ); /* end macro or comment */
	if ( let1=='f' && let2=='i')	return( FI ); /* fill		      */
	if ( let1=='t' && let2=='i')	return( TI ); /* temp. left indent    */
	if ( let1=='b' && let2=='p')	return( BP ); /* break, page #	      */
	if ( let1=='b' && let2=='r')	return( BR ); /* break		      */
	if ( let1=='c' && let2=='e')	return( CE ); /* center line(s)	      */
	if ( let1=='i' && let2=='n')	return( IN ); /* left indent	      */
	if ( let1=='l' && let2=='l')	return( LL ); /* right margin	      */
	if ( let1=='l' && let2=='s')	return( LS ); /* line spacing	      */
	if ( let1=='n' && let2=='f')	return( NF ); /* no fill	      */
	if ( let1=='p' && let2=='l')	return( PL ); /* page length	      */
	if ( let1=='s' && let2=='p')	return( SP ); /* output blank lines   */
	if ( let1=='n' && let2=='e')	return( NE ); /* need vertical spaces */
	if ( let1=='t' && let2=='a')	return( TA ); /* tab size	      */
	if ( let1=='t' && let2=='c')	return( TC ); /* tab character	      */
	if ( let1=='t' && let2=='r')	return( TR ); /* translate chars      */
	if ( let1=='a' && let2=='d')	return( AD ); /* adjust output lines  */
	if ( let1=='n' && let2=='a')	return( NA ); /* no adjust output     */
	if ( let1=='e' && let2=='m')	return( EM ); /* end macro	      */
	if ( let1=='d' && let2=='e')	return( DE ); /* define macro	      */
	if ( let1=='d' && let2=='s')	return( DS ); /* define string	      */
	if ( let1=='n' && let2=='r')	return( NR ); /* number register      */
	if ( let1=='d' && let2=='i')	return( DI ); /* divert output	      */
	if ( let1=='s' && let2=='o')	return( SO ); /* source from file     */
	if ( let1=='p' && let2=='m')	return( PM ); /* print macros         */
	if ( let1=='e' && let2=='x')	return( EX ); /* exit (abort)	      */
	if ( let1=='i' && let2=='g')	return( IG ); /* ignore -- comment    */
	if ( let1=='t' && let2=='m')	return( TM ); /* message to terminal  */
	if ( let1=='f' && let2=='t')	return( FT ); /* set font	      */
	if ( let1=='p' && let2=='o')	return( PO ); /* page offset 	      */

#ifdef	NOTYET
	if ( let1=='w' && let2=='h')	return( WH ); /* set trap 	      */
#endif

#ifdef	NONROFF
	if ( let1=='F' && let2=='O')	return( FO ); /* footer for title     */
	if ( let1=='H' && let2=='E')	return( HE ); /* header for title     */
	if ( let1=='S' && let2=='T')	return( ST ); /* stop between pages   */
	if ( let1=='F' && let2=='F')	return( FF ); /* form feed	      */
	if ( let1=='S' && let2=='C')	return( SC ); /* space character      */
	if ( let1=='O' && let2=='H')	return( OH ); /* odd-page header      */
	if ( let1=='O' && let2=='F')	return( OF ); /* odd-page footer      */
	if ( let1=='E' && let2=='H')	return( EH ); /* even-page header     */
	if ( let1=='E' && let2=='F')	return( EF ); /* even-page footer     */
	if ( let1=='C' && let2=='F')	return( CF ); /* trans. char. flag    */
	if ( let1=='I' && let2=='C')	return( IC ); /* insert character     */
	if ( let1=='B' && let2=='J')	return( BJ ); /* break, justified     */
	if ( let1=='S' && let2=='S')    return( SS ); /* show strings */
	if ( let1=='S' && let2=='R')    return( SR ); /* show registers    */
	if ( let1=='M')
		{ 
		if (let2=='1')		return( M1 );
		if (let2=='2')		return( M2 );
		if (let2=='3')		return( M3 );
		if (let2=='4')		return( M4 );
		}
	if ( let1=='D' && let2=='B')	return( DB ); /* debug on			 */
#endif

	return( UNKNOWN );			/* no match */
	}

/*************************************************************
gets the number ( if any ) associated with any command 
*************************************************************/

get_val( line, typ )
	char *line;
	int *typ;
	{
	int i;
	char local[ MAXLINE ];
	strcpy (local, line);	 /* local copy */

	/* skip over the command line */
	for(i=1; local[i]!=' '&&local[i]!='\t'&&local[i]!='\n'
		&&local[i]!=0; i++);

	skip_blanks (&local[i]);		/* find the number */
	*typ = local[i];		/* relative or absolute */
	if ( *typ=='+' || *typ=='-' )
		{
		i++;
		}
	else if ( !isdigit( *typ ) )
		{
		return( NO_VAL );
		}
	return ( atoi( &local[i] ));
	}

/*************************************************************
 sets a non-stacked global parameter like ro_spval, ro_pagestop, etc.
 Also checks that the new value is within the range of that 
 parameter.	Assigns the default for that parameter if no value
 is specified.
*************************************************************/

set( param, val, arg_typ, defval, minval, maxval )
	int *param, val, defval, minval, maxval;
	int arg_typ;
	{
	if ( val == NO_VAL ) 
		{
		*param = defval;	 /* defaulted */
		}
	else if (arg_typ == '+') 
		{
		*param += val;	/* relative + */
		}
	else if ( arg_typ == '-' ) 
		{
		*param -= val;	/* relative - */
		}
	else	
		{
		*param = val;			 /* absolute */
		}
	*param = ro_min (*param, maxval);
	*param = ro_max (*param, minval);

	if DEBUG fprintf( stderr,"DEBUG:  set() *param = %d\n", *param);
	}

/*************************************************************
		end current filled line 
**************************************************************/

ro_brk()
	{
	int l;
	if DEBUG 
		{
		fprintf( stderr,"DEBUG:  ro_brk(): ro_outbuf=<%s>\n", ro_outbuf);
		}

	if (ro_outpos)
		{
		put( ro_outbuf );
		}
	ro_outw = ro_outpos = ro_outtop = ro_outbot = ro_outwrds = 0;
	ro_outbuf[0] = '\0';
	}

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

initxu()		/*initialize underline,overstrike variables*/
	{	 
	ro_xcol = ro_ucol = -1;
	memfill(ro_xbuf,LSZ,' ');
	memfill(ro_ubuf,LSZ,' ');
	}

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

need(n) /*test for space before footer*/
	int n;	/*whole lines*/
	{
	if (( ro_vlineno >= (ro_bottom-n) ) && ( ro_bottom >= ro_vlineno ) )
		{
		do_space( HUGE );
		ro_newpag = ++ro_curpag;
		}
	}

