Example #1
0
/*
****************************************************************************
*
*  Mnemonic: FMimbed
*  Abstract: This routine is responsible for parsing the imbed string and
*            calling FMopen to open a file to process.
*  Parms:    None.
*  Returns:  Nothing.
*  Date:     15 November 1988
*  Author:   E. Scott Daniels
*  Modified: 	25 Aug 2000 - to add NF option
*				13 Nov 207 - Added run/stop command to stream to mark pop of
*					the fmrun() command and return to this function. Allows
*					this rouitine to drive the imbed which is needed
*					for things like oneject that imbed files and push/pop the
*					environment before/after the file. Basically negates the
*					AFIchain() feature where the imbed file was pushed onto
*					the stack of open files. c'est la vie!
*			17 Jul 2016 - Bring decls into the modern world.
*
* .im [nf] filename
***************************************************************************
*/
extern void FMimbed( void )
{
    char *fp = 0;
    char *buf;      /* pointer into the imput buffer of the fname token */
    int len;        /* length of the token */

    len = FMgetparm( &buf );
    if( strcmp( buf, "nf" ) == 0 )
    {
        len = FMgetparm( &buf );       /* point to the next token in the buffer */
        FMflush( );                    /* send last formatted line on its way */
        flags = flags | NOFORMAT;      /* turn no format flag on */
    }

    if( len <= 0 )
    {
        FMmsg( E_MISSINGNAME, ".IM" );
        return;
    }

    FMmsg( I_IMBED, buf );

    fp = strdup( buf );
    AFIpushtoken( fptr->file, ".sr" );  	/* push the special runstop command to mark end of imbed file */
    TRACE( 2, "imbed: starting with file %s (pushed .sr token) \n", fp );
    FMopen( buf );             		/* open the imbed file */

    FMrun( );				/* run until we hit the end of the file */

    TRACE( 2, "imbed: finished with file %s lmar=%d\n", fp, lmar );
    free( fp );
}                                 /* FMimbed */
Example #2
0
/*
* --------------------------------------------------------------------------
*  Mnemonic: fmth
*  Abstract: save a table header placed into the table now, and if we page eject
*  Date:     02 Nov 2006 - converted from hfm
*  Author:   E. Scott Daniels
* 
*  .th string
* --------------------------------------------------------------------------
*/
extern void FMth( void )
{
	struct table_mgt_blk *t;
	char	*buf;
	int	len; 
	int	totlen = 0;
	char	data[4096];

	if( ts_index <= 0 || (t = table_stack[ts_index-1]) == NULL )
	{
		while( (len = FMgetparm( &buf )) != 0 );		/* just dump the record */
		return;
	}
			
	*data = 0;
	while( (len = FMgetparm( &buf )) != 0 )
	{
		if( len + totlen + 1 < sizeof( data ) )
		{
			strcat( data, buf );
			strcat( data, " " );
		}
		totlen += len + 1;
	}

	if( t->header )
		free( t->header );
	t->header = strdup( data );

	TRACE( 2, "tab_header: header in place: %s\n", t->header );
	AFIpushtoken( fptr->file, t->header );			/* fmtr calls get parm; prevent eating things */
	
}
Example #3
0
extern void FMendtable( void )
{

	struct	table_mgt_blk *t;
	struct	col_blk *next;
	int	i;
	int 	x;
	char	obuf[1024];

	if( ts_index <= 0 || ! (t = table_stack[ts_index-1]) )
		return;

	TRACE( 1, "end_table: cury=%d rows=%d  total_depth=%d  ave_depth=%d\n", cury, t->nrows, t->tot_row_depth, t->ave_row_depth );

	AFIpushtoken( fptr->file, ":" );			/* fmtr calls get parm; prevent eating things */
	FMtr( ts_index > 1 ? 0 : 1 );				/* flush out last row (adds bottom and side borders if needed */

	if( firstcol != t->col_list ) {
		for( cur_col = firstcol; cur_col; cur_col = next )
		{
			next = cur_col->next;
			cur_col->next = NULL;		// fail if reuse is tried
			free( cur_col );
		}
	}

	TRACE( 2, "tab_end: reset first col from %p to %p\n", firstcol, t->col_list );
	TRACE( 2, "tab_end: reset cur_col from %p to %p\n", cur_col, t->cur_col );
	cur_col = t->cur_col;
	lmar = t->lmar;
	hlmar = t->hlmar;
	linelen = t->old_linelen;
	firstcol = t->col_list;

#ifdef KEEP
/* setting the temp top is up to the user as the table might be in a left column and the next 
column needs to go to the top of the physical page.  If this is a page wide table, then 
the user must setup multiple columns after .et and set the temp top.  we cannot assume this 
to be the case
*/
	if( rtopy == 0 )			/* allow for multiple columns under the table */
		rtopy = t->old_topy;

	topy = cury;
#endif

	topy = t->old_topy;
	if( t->header )
		free( t->header );
	free( t );
	table_stack[ts_index-1] = NULL;
	if( ts_index > 0 )
		ts_index--;			/* keep it from going neg */
	if( ts_index )
		topy = table_stack[ts_index-1]->topy;
}
Example #4
0
/*
*****************************************************************************
*
*    Mnemonic: FMpflush
*    Abstract: This routine causes the running header and footer to be placed
*              into the file and then issues the newp command which will issue
*              a showpage and then a translate.
*    Parms:    None.
*    Returns:  Nothing
*    Date:     1 December 1988
*    Author:   E. Scott Daniels
*
*    Modified: 22 Apr 1991 - To put header and footer and page under 2nd
*                              column if in two column mode.
*               3 May 1991 - To support two sided page format of headers.
*               4 May 1991 - To shift pages by pageshift size
*                            Broke header/footer code to FMrunout
*              13 May 1992 - Conversion to PostScript output
*              25 Oct 1992 - To call fmrunout with page and shift only.
*              27 Nov 1992 - To also set hlmar on new column
*              10 Dec 1992 - To use AFI routines for ansi compatability
*               7 Apr 1994 - To reset topy to realy if realy not 0.
*		       17 Aug 2001 - To add support for on eject command buffer
*				26 Jun 2013 - Calls colnotes_show() to show the notes before
*						doing the eject. 
*				07 Jul 2013 - Colour support changes. 
*				18 Dec 2015 - Cleaned up commented out code.
*				17 Jul 2016 - Bring decls into the modern world.
*****************************************************************************
*/
extern void FMpflush( void )
{
	int diff;                   /* difference between default lmar and cur lmar*/
	int diffh;                  /* difference between default lmar and header */
	int i;                      /* index into page number buffer */
	char tbuf[HEADFOOT_SIZE+1]; /* buf to gen page and head/foots in  */
	int len;                    /* number of characters in the string */
	int even = FALSE;           /* even/odd page number flag */
	int skip;                   /* # columns to skip before writing string */
	int shift = FALSE;          /* local flag so if stmts are executed only once */
	char *tok;

	if( cn_space  )				/* if and end note was defined, need to add it too */
	{
		TRACE( 3, "pflush: dumping column notes first, pushing .pa command back\n"  );
 		AFIpushtoken( fptr->file, ".pa" );  	/* page command to execute after the column notes are written */
			
		cn_space = 0;
		FMcolnotes_show( 0 );			/* cause the column notes to be put in before eject */
		return;							// go run all of the commands which will 'end' with the page eject we just pushed
	}

	page++;                             /* increase the page number */

	if( rtopy != 0 )          /* see if top margin reset temporarily */
	{
		topy = rtopy;               /* reset as it is good only to the end of pg*/
		rtopy = 0;                  /* indicate nothing set at this point */
	}

                              /* determine if we need to shift the page */
	if( flags2 & F2_2SIDE )      /* if in two sided mode */
	{
		if( (page % 2) != 0 )      /* and its an odd page (only shift odd pages) */
		shift = TRUE;
	}
	else                         /* page shift not 0 and one sided mode */
		shift = TRUE;               /* then EACH page is shifted */

	FMpushcolour( "#000000" );	/* push current colour and set head/foot/pagen colour (black) */
	FMrunout( page, shift );	/* put header/footer and page strings */
	FMpopcolour( );				/* restore the colour */

	AFIwrite( ofile, "newp\n" );    /* newpage ps definition "showpage" */

	diff = lmar - cur_col->lmar;  /* calculate diff in col default mar& cur mar */
	diffh = hlmar - cur_col->lmar;  /* calc diff in header left margin */
	cur_col = firstcol;           /* start point at the first column block */
	lmar = cur_col->lmar + diff;  /* set up lmar for first column */
	hlmar = cur_col->lmar +diffh; /* set up header left margin for first col */

	cury = topy + (textsize/2);                  /* reset current y to top y position */

	FMateject( 1 );		/* do page eject stuff first */
}
Example #5
0
/*
	Restart a paused table
*/
extern void FMrestart_table( void ) {
	struct	table_mgt_blk *t;

	if( ts_index <= 0 || ! (t = table_stack[ts_index-1]) ) {
		return;
	}
	if( t->paused_list == NULL ) {
		fprintf( stderr, "abort: internal mishap restarting table; no paused list\n" );
		exit( 1 );
	}

	firstcol = t->paused_list;
	cur_col = firstcol;
	lmar = cur_col->lmar - textspace - t->padding;
	firstcol->anchor =  t->paused_list->anchor;			// cary the anchor over for running head/feet
	t->maxy = cury;

	if( t->header )										// new header on resume
	{
		AFIpushtoken( fptr->file, ".tr :" );			/* must drop a table row after the header command(s) */
		AFIpushtoken( fptr->file, t->header );			/* fmtr calls get parm; prevent eating things */
	}

	// cell start emulation
	cury = topy;
	t->topy = topy;
	lmar = cur_col->lmar + t->padding;   	/* set lmar based on difference calculated */
	hlmar = cur_col->lmar + t->padding; 	/* earlier and next columns left edge */

	if( lilist != NULL )					/* if list then reset xpos for next col */
		lilist->xpos = cur_col->lmar + t->padding;

	linelen = cur_col->width;
	t->paused_list = NULL;

	if( t->border )					// add top border to start the table in next col/page
	{
		//sprintf( obuf, "%d %d moveto %d %d rlineto stroke\n", t->lmar+t->padding, -(cury - t->padding), t->border_width-t->padding, 0 );
		sprintf( obuf, "%d %d moveto %d %d rlineto stroke\n", t->lmar+t->padding, -(cury ), t->border_width-t->padding, 0 );
		AFIwrite( ofile, obuf );
	}
}
Example #6
0
/*
*****************************************************************************
*
*   Mnemonic: FMnofmt
*   Abstract: This routine is called when the noformat flag is set. It
*             reads in lines from the input file and if there is not a
*             command in the first column then it places the line of
*             text as is out to the page buffer. If a command is on the
*             input line control is returned to the caller to process the
*             command.
*   Parms:    None.
*   Returns:  Nothing.
*   Date:     8 December 1988
*   Author:   E. Scott Daniels
*
*   Modified:  7 Jul 1994 - To convert to rfm
*              4 Oct 1994 - To reduce amount skipped in y direction.
*              6 Dec 1996 - To convert for hfm
*              4 Apr 1997 - To use the new tokenizer in AFIleio!
*             15 Apr 1997 - To return if vardelim is in first col too
*******************************************************************************
*/
void FMnofmt( )
{
 char *buf;             /* work buffer */
 int status;            /* status of the read */
 int i;                 /* loop index */

 status = FMread( inbuf );        /* get the next buffer */

 while( status >= 0  &&  inbuf[0] != CMDSYM && *inbuf != vardelim ) 
  {
   for( i = 0; i < MAX_READ-1 && inbuf[i] != EOS; i++, optr++ )
    {
     switch( inbuf[i] )          /* properly escape html special chars */
      {
       case '>':
        obuf[optr] = EOS;                 /* terminate for strcat */
        strcat( obuf, "&gt;" );           /* copy in the character */
        optr += 3;                        /* incr past the html esc string */
        osize += 3;                       /* incr number of chars in output */
        break;

       case '<':
        obuf[optr] = EOS;                 /* terminate for strcat */
        strcat( obuf, "&lt;" );           /* copy in the character */
        optr += 3;                        /* incr past the html esc string */
        osize += 3;                       /* incr number of chars in output */
        break;

       case '&':
        obuf[optr] = EOS;                 /* terminate for strcat */
        strcat( obuf, "&amp;" );          /* copy in the character */
        optr += 4;                        /* incr past the html esce string */
        osize += 4;                       /* incr number of chars in output */
        break;

       default:                 /* not a special character - just copy in */
        obuf[optr] = inbuf[i];
        obuf[optr+1] = EOS;     /* terminate incase of strcat on next loop */
        break;
      }
    }                          /* end while stuff in input buffer to copy */

   if( optr == 0 )             /* if this was a blank line */
    obuf[optr++] = ' ';        /* give flush a blank to write */
   obuf[optr] = EOS;           /* terminate buffer for flush */

   FMflush( );                 /* send the line on its way */
   status = FMread( inbuf );   /* get the next line and loop back */
  }                            /* end while */

 AFIpushtoken( fptr->file, inbuf );   /* put command back into input stack */
 iptr = optr = 0;              /* return pointing at beginning */
}                              /* FMnofmt */
Example #7
0
/*
	show the col notes by closing the file and pushing an imbed 
	command onto the stack.  the last command in the file is a 
	.cn command to unlink the file (we'll leave droppings in the file
	system if the user causes us to crash, but thats low risk).

	returns true if something was pushed -- needed for the end;
*/
extern int FMcolnotes_show( int end )
{
	char	buf[1024];
	FILE	*target = NULL;
	char	*fname = NULL;
	int		status = 0;
	char	*end_cmd = "";

	if( bfile != NULL )		// target is always the b file if it's there
	{
		target = bfile;
		bfile = NULL;
		fname = bfname;
	}
	if( end )				/* end of doc (atclose) */
	{
		FMflush( );
		if( target == NULL ) {			// end and no bfile; try end file now
			target = efile;
			efile = NULL;
			fname = efname;
		}

		end_cmd = ".qu";				// needed to force end processing after our embed (might bring us back to do efile if bfile exists
	}
	
	if( target == NULL )
		return 0;

	TRACE( 2, "colnotes: showing at: %s cury=%d boty=%d page=%d\n", end ? "end of doc" : "bottom of col", cury, boty, page );
	if( cn_space > 0 )
		if( boty - cn_space > cury )
			cury = boty - cn_space;
	TRACE( 2, "colnotes: cury set to=%d\n", cury );


	fprintf( target, ".br\n.po\n" );					// add the ending commands to the file (force flush and pop)
	if( ! end )
		fprintf( target, ".cb\n" )	;					// new col only if not at end; causes extra page eject if at end
	if( flags & JUSTIFY )
		fprintf( target, ".ju on\n" );					// justify back on if needed
	fprintf( target, ".cn unlink %s\n%s\n", fname, end_cmd );

	fclose( target );
	snprintf( buf, sizeof( buf ), "\n.im %s", fname );				/* must have a guarding newline as lead (prevent accidents with .sp without optional parm etc.) */
 	status = AFIpushtoken( fptr->file, buf );  						/* push to imbed the file */
	TRACE( 2, "colnotes: pushing: stat=%d (%s)\n", status, buf );
	*fname = 0;

	return 1;
}
Example #8
0
/*
****************************************************************************
*
*  Mnemonic: FMinit
*  Abstract: This routine opens the initial input file and the output file
*            and does other necessary house keeping chores.
*  Parms:    argc - Number of arguments passed to fm from command line
*            argv - Argument vector list passed from command line
*  Returns:  Valid if all is well, ERROR if system could not be initialized.
*  Date:     17 November 1988
*  Author:   E. Scott Daniels
*
*  Modified:  22 Apr 1991 - To remove need to have dedicated page num buffer
*              3 May 1991 - To initialize flags2 variable
*              3 May 1992 - To convert for post script output
*              7 Nov 1992 - To alloc header font buffers
*             12 Nov 1992 - To add justify PS proc
*             13 Nov 1992 - To allocate current font buffer before use
*             10 Dec 1992 - To use AFIwrite for ansi compat on sun
*              6 Apr 1993 - To create a dummy variable block for psuedo
*                           commands generated by .gm and .gd commands.
*             26 May 1993 - To add stroke command to box routine.
*             13 Jun 1993 - To set the psfm variable by placing a dv command
*                           into the initial input buffer.
*             12 Jul 1993 - To set the def item list font ptr to null
*             21 Feb 1994 - To open output file just "w"
*                           To put out the PS routine rightxy for header/footer
*             22 Feb 1994 - To init figure font (ffont)
*              7 Apr 1994 - To seup for TOC now that linelen is points related
*              7 Oct 2000 - To use new AFI tokeniser
*	      		10 Oct 2001 - To add new justification PS functions
*	      		13 Jan 2001 - Added sym table support
*				08 Nov 2006 - Some cleanup and now allow default input from stdin.
*				10 Apr 2007 - Memory leak cleanup 
*				16 Sep 2007 - added page geometry argument support
*				13 Nov 2007 - Changed the imbed/run() mechanism to better support the 
*						oneject processing.
*				22 Mar 2011 - Correctly set boty when geometry (-g) is given.
*				07 Jul 2013 - Changed initialisation of text colour to use setcolour. 
*				17 Jul 2016 - Bring decls into the modern world.
*****************************************************************************
*/
extern int FMinit( int argc, char **argv )
{
	int i;               /* loop index */
	char buf[1024];
	char *ptr;           /* pointer to argument */
	char	*ifname = "stdin";
	char	*ofname = "stdout";
	int 	geomh = 0;		/* geometry from -g hxw */
	int 	geomw = 0;

	argc--;
	argv++;
	while( argc > 0 && argv[0][0] == '-' )
	{
		switch( argv[0][1] )
		{
			case 'g': 
				geomh = atoi( argv[1] ) * 72;
				if( (ptr = strchr( argv[1], 'x' )) != NULL )
					geomw = atoi( ptr + 1 ) * 72;
				argv++;
				argc--;
				break;

			case 't':
				trace = atoi( argv[1] );
				argv++;
				argc--;
				break;

			case 'v':
				flags2 |= F2_NOISY;
				break;

			case '?':
				FMmsg( ERROR, "Usage: tfm [input-file [output-file [inital command tokens]]]" );
				exit( 1 );

			default:	
				fprintf( stderr, "unrecognised option: %s\n", argv[0] );
				exit( 1 );
		}	

		argv++;
		argc--;
	}

	if( argc >= 1 )
	{
		if( *argv[0] != '-' )		/* allow - to default to stdin */
			ifname = argv[0];
	}

	if( argc > 1 )
	{
		if( *argv[1] != '-' )		/* allow - to default to stdout */
			ofname = argv[1];
	}

	if( strcmp( ifname, ofname ) == 0 )
	{
		FMmsg( ERROR, "input name cannot be same as output; this is just wrong");
		return ERROR;
	}

	if( FMopen( ifname ) < VALID )       /* open the initial input file */
		return ERROR;                     

	symtab = sym_alloc( 4999 );		/* symtab for variables */
	AFIsettoken( fptr->file, symtab, " \t", '&', '^', ":" );
	AFIsetflag( fptr->file, AFI_F_EOBSIG, AFI_SET );		/* end of buffer notifications */
#ifdef KEEP
this is dropped because imbed now puts a run/stop command into the stream to pop the call to fmrun() at end of file
	AFIsetflag( fptr->file, AFI_F_EOFSIG, AFI_SET );		/* end of file notifications -- must have so .im file .cmd works */
#endif

	ofile = AFIopen( ofname, "w" );      /* open output file */
	if( ofile < VALID )
	{
		FMmsg( E_CANTOPEN, ofname );
		FMclose( );
		return ERROR;
	}

	version = "pfm V2.8/17243"; 		/* returned by .gv v command */
	snprintf( buf, sizeof( buf ), "+PFM text formatter (%s) started", version );
	FMmsg( -1, buf );

	/* write out our postscript routines that make life easier */
	snprintf( buf, sizeof( buf ), "%%! %s generated this postscript file\n", version );
	AFIwrite( ofile, buf );
	/*AFIwrite( ofile, "%! PFM 1.1-02282 PostScript output\n" );*/
	/*AFIwrite( ofile, "% Copyright (c) 1994-2002 by E. Scott Daniels. All Rights Reserved!\n" );*/
	AFIwrite( ofile, "% A happy programme is one that generates other programmes;\n" );
	AFIwrite( ofile, "% This was generated by a happy programme!\n" );

	boty = (10 * 71);			/* default to 11" page with a 1" bottom margin */
	if( cury <= 0 )
		cury = topy = 71;			/* default to 1" top margin */
	if( top_gutter <= 0 )
		top_gutter = cury/2;		// space above first line for running matter
	pagew = MAX_X;
	pageh = MAX_Y;

	AFIwrite( ofile, "%these functions are Copyright (c) 2001-2013 by E. Scott Daniels. All Rights Reserved!\n" );
	/*  new page macro to showpage and set the origion of the 0,0 */
	if( geomh )
	{
		pagew = geomw;			/* override defaults with user setting */
		pageh = geomh;

		AFIwrite( ofile, "%%BeginSetup\n" );
		AFIwrite( ofile, "mark {\n" );
		AFIwrite( ofile, "%BeginFeature: *PageRegion C\n" );
		snprintf( buf, sizeof( buf ), "<</PageSize [%d %d]>> setpagedevice\n", pagew, pageh );
		AFIwrite( ofile, buf );
		AFIwrite( ofile, "%EndFeature\n" );
		AFIwrite( ofile, "} stopped cleartomark\n" );
 		AFIwrite( ofile, "%%EndSetup\n" );
		snprintf( buf, sizeof( buf ), "/xlate {0 %d translate} def\n/newp {showpage xlate} def\n", pageh );
		AFIwrite( ofile, buf );
		boty = pageh - 42;			/* adjust botom y based on geometry */
	}
	else
		AFIwrite( ofile, "/xlate {0 792 translate} def\n/newp {showpage xlate} def\n" );
	
	/* the remainder of the native ps that we dump on initialisation is in init.ps which is 
		parsed and compressed by a mk rule and put into init_ps.c
	*/
#include "init_ps.c"		/* easier to manage postscript functions we need */

	/* now initialize from a C point of view */

	difont = NULL;     /* initially no def list item font string defined */
	ffont = NULL;      /* no figure font defined */
	//textcolour = strdup( "000000" );
	FMsetcolour( "#000000" );					/* default to black */
	curfont = strdup( DEF_TEXTFONT );
	runfont = strdup( DEF_RUNFONT );
	FMfmt_add( );


	textspace = 2;
	iptr = 0;
	optr = 0;                 /* start at beginning of the output buffer */
	obuf = (char *) malloc( sizeof( char ) * 2048 );
	inbuf = (char *) malloc( sizeof( char ) * 2048 );
	if( ! obuf || ! inbuf )
	{
		fprintf( stderr, "malloc of obuffer failed\n" );
		return ERROR;
	}
	*obuf = (char) 0;

	sprintf( inbuf, ".dv pfm 1 : " );   /* simulate a user command - define compiler name */
	AFIpushtoken( fptr->file, inbuf );  /* and push onto the input stack */

	if( (path = getenv( "PFM_PATH" )) == NULL )
		path = getenv( "XFM_PATH" );

	cur_col = firstcol = (struct col_blk *) malloc( sizeof( struct col_blk ) );
	if( cur_col == NULL )
		return ERROR;

	cur_col->lmar = DEF_LMAR;
	cur_col->width = 550 - DEF_LMAR; /* set single column width */
	cur_col->next = NULL;          /* by default we are in single column mode */

	flags = PARA_NUM;              /* turn on paragraph numbering */


	memset( tocname, 0, sizeof(tocname ) );
	snprintf( tocname, sizeof( tocname )-5, "%s",  ifname );
	if( (ptr = strrchr( tocname, '.' )) != NULL )
		*ptr = 0;
	strcat( tocname, ".toc" );		/* same filename with .toc extension */

	memset( pnum, 0, sizeof( pnum ) );

	for( i = argc - 1; i > 2; i-- )
		AFIpushtoken( fptr->file, argv[i] );	/* whatever is after output file we use as input */


	for( i = 0; i < MAX_HLEVELS; i++ )   /* allocate and init header blks */
	{
		headers[i] = (struct header_blk *) malloc( sizeof( struct header_blk ) );
		if( headers[i] == NULL )
			return ERROR;

		headers[i]->font = (char *) malloc( (strlen( DEF_HEADFONT )) + 1 );
		strcpy( headers[i]->font, DEF_HEADFONT );  /* move in default string */
	
		headers[i]->flags = HTOC;              /* initially only TOC flag set */
		headers[i]->indent = DEF_HEADINDENT;   /* set default indention */
		headers[i]->level = i+1;               /* set the level */
		headers[i]->skip = 21;                  /* skip down 2 lines before/1after */
	}

	headers[0]->size = DEF_H1SIZE;   /* set default header text sizes */
	headers[1]->size = DEF_H2SIZE;
	headers[2]->size = DEF_H3SIZE;
	headers[3]->size = DEF_H4SIZE;
	headers[0]->flags |= HEJECTC+HTOUPPER;   /* header level 1 defaults */

	return VALID;
}
Example #9
0
/*
***************************************************************************
*
*   Mnemonic: FMcmd
*   Abstract: This routine is responsible for dispatching the proper
*             routine to handle the command that was input by the user.
*             Commands are those tokins that begin with a period and are 2
*             characters long.
*   Parms:    buf - Pointer to the command. (.aa)
*   Returns:  Nothing.
*   Date:     17 November 1988
*   Author:   E. Scott Daniels
*
*   Modified: 	1-1-89 - To support normal and definition lists
*             	4-30-98- To support user defined list item characters
*             	5-05-89- To support boxes
*             	6-10-89- To add .** as a comment line in the input file
*             	3 May 1991 - To support .ts (two sided) command
*             	4 May 1991 - To support page shifting
*             	5 May 1992 - To support postscript
*             	1 Oct 1992 - To support punctuation space command
*             	2 Nov 1992 - To add center command
*            	13 Nov 1992 - To free/malloc current font buffer
*             	3 Dec 1992 - To flush before setting font size or font
*             	6 Jun 1993 - To set y position for list item bullets higher
*            	21 Feb 1994 - To handle shift value in dlstack rather than old
*                          left margin; correct multi column problem
*                          and to call setstr for running strings
*	 			21 Oct 2007 - Added index interface
*				26 Jun 2013 - Prevents 0 text size from being set on .st command (happening
*							when .st &var and var not defined. 
*				03 Jan 2016 - Removed errant flush before FMll() and indent
*							calls.
**************************************************************************
*/
int FMcmd( char *buf )
{
	int cmd;                  /* command converted to integer for switch */
	int i;                    /* temp integer */
	struct li_blk *liptr;     /* pointer to head to delete on a .el cmd */
	char *ptr;                /* dummy pointer to skip parameters */
	int len;                  /* length of parameter returned */
	int rc = 1;		/* return code indicating command or not */
	char 	wbuf[512];
	char	*tok;

	cmd = toupper( buf[1] );
	i = toupper( buf[2] );       /* pick off and translate indiv characters */
	cmd = (cmd << 8) + i;        /* combine the characters */

	switch( cmd )
	{
	
		case C_ABORT:	exit( 1 ); break;	/* get out w/o end housekeeping */

		case C_ASIS:	flags2 |= F2_ASIS; break;

		case C_BEGDEFLST:        FMbd( ); break; 	/* definition list */

		case C_BEGLIST:          FMbeglst( ); break;

		case C_BLOCKCTR:		/* .bc {start|end} */
				if( FMgetparm( &buf ) != 0 )
				{
					FMflush( );		/* need to put out last one */
					cenx1 = cur_col->lmar;
					cenx2 = cur_col->lmar + cur_col->width;  /* defalult center */
					if( *buf == 's' || *buf == 'S' )
						flags2 |= F2_CENTER;
					else
						flags2 &= ~F2_CENTER;
				}
				break;

		case C_BOTY:	/* .by [-]x[ip] if - (neg) then thats how far UP from bottom */
				len = FMgetparm( &ptr );
				boty = FMgetpts( ptr, len );
				if( boty <= 0 )
					boty += (11 * 72)-10;
				break;
	
		case C_BREAK:           FMflush( ); break;

		case C_BOX:             FMbox( ); break;

		case C_CAPTURE:		FMcapture( ); break;

		case C_CCOL:            FMccol( 0 ); break;

		case C_COLNOTES:	FMcolnotes( ); break;

		case C_TABLECELL:	FMcell( 1 ); break;

		case C_CENTER:          FMcenter( ); break;

		case C_COLOUR:  	
				if( FMgetparm( &ptr ) > 0 )
				{
					if( strcmp( ptr, "text" ) != 0 || FMgetparm( &ptr ) > 0  )		/* hfm compatable format since it allows bg, link colours to be set */
					{
						if( textcolour )
							free( textcolour );
						FMsetcolour( ptr );			
					}
				}
				break;


		case C_COMMA:		FMcomma( ); break;

		case C_COMMENT:         FMskip( ); break;		/* skip to real end of buffer not : */

		case C_DEFHEADER:       FMdefheader( ); break;

		case C_CDEFINE:		FMcd( ); break;

		case C_EP:              FMep( ); break;

		case C_CEJECT:           
				PFMceject( );            /* eject column, flush page if in last column */
				break;

		case C_CPAGE:            FMcpage( ); break;

		case C_CSS:				/* html cascading style sheet -- meaningless here */
				FMignore( );
				break;

		case C_DEFDELIM:         /* define the variable definition delimiter */
				if( FMgetparm( &ptr ) != 0 )
					vardelim = ptr[0];    /* set the new pointer */
				break;

		case C_DEFITEM:         FMditem( ); break;

		case C_DEFVAR:          FMdv( ); break;

		case C_DOUBLESPACE:	flags = flags | DOUBLESPACE; break;

		case C_ELSE:		FMelse( ); break;

		case C_ENDDEFLST:        /* end definition list */
				if( dlstackp >= 0 )     /* valid stack pointer? */
				{
					flags2 &= ~F2_DIRIGHT;  /* turn off the right justify flag for di's */
					FMflush( );             
					i = dlstack[dlstackp].indent / PTWIDTH;     /* calc line len shift */
					lmar -= dlstack[dlstackp].indent;           /* shift margin back to left */
					linelen += dlstack[dlstackp].indent;        /* reset line len */
					dlstackp--;                          /* "pop" from the stack */
				}
				break;

		case C_ENDIF:            break; /* .fi encountered - ignore it */

		case C_ENDLIST:          /* end a list */
				if( lilist != NULL )    /* if inside of a list */
				{
					FMflush( );           /* clear anything that is there */
					FMendlist( TRUE );      /* terminate the list and delete the block */
				}
				break;


		case C_ENDTABLE: 	FMendtable( ); break;

   		case C_EVAL:                  /* evaluate expression and push result */
    				if( FMgetparm( &buf ) > 0 )  /* get parameter entered */
     					AFIpushtoken( fptr->file, buf );
    				break;

		case C_FIGURE:           FMfigure( ); break;

		case C_FLOATMAR:
					FMfloat_mar( );
					break;

		case C_FORMAT:           FMformat( ); break;

		case C_GETVALUE:         FMgetval( ); break;

		case C_GREY:             /* set grey scale for fills */
				if( FMgetparm( &buf ) > 0 )  /* get parameter entered */
				fillgrey = atoi( buf );   /* convert it to integer */
				break;

		case C_HDMARG:           FMindent( &hlmar );    break;

		case C_HLINE:			FMcline( ); break;

		case C_HN:               FMhn( );   break;

		case C_H1:              FMheader( headers[0] ); break;

		case C_H2:               FMheader( headers[1] ); break;

		case C_H3:               FMheader( headers[2] ); break;

		case C_H4:               FMheader( headers[3] ); break;

		case C_HYPHEN:		
				if( FMgetparm( &buf ) > 0 )  /* get parameter entered */
				{
					if( *(buf+1) == 'n' )	/* assume on */
						flags3 |= F3_HYPHEN;
					else
						flags3 &= ~F3_HYPHEN;
				}
				else
					flags3 |= F3_HYPHEN;
				break;

		case C_IF:               FMif( ); break;

		case C_IMBED:            FMimbed( ); break;

		case C_INDENT:           /* user indention of next line */
				FMindent( &lmar );      /* indent the left margin value */
				break;

		case C_INDEX:
				fmindex( );
				break;

		case C_JUMP: 	FMjump( ); break;

		case C_JUSTIFY:         FMsetjust( ); break;

		
		case C_LINESIZE:        /* set line size for line command */
				if( FMgetparm( &buf ) > 0 )   /* get the parameter */
				{
					linesize = atoi( buf );   /* convert to integer */
					if( linesize > 10 )
						linesize = 2;        /* dont allow them to be crazy */
				}
				break;

		case C_LISTITEM:        /* list item entered */
				if( lilist != NULL && lilist->yindex < 60 )
				{
					FMflush( );          /* output what we have so far */
					if( cury + textspace + textsize  > boty )  /* flush before marking */
					PFMceject( );
					lilist->ypos[lilist->yindex] =  (cury + textsize);
					lilist->yindex++;     /* point at next index */
				}
				break;

		case C_LL:                      /* reset line length */
				FMll( );
				break;

		case C_LINE:            FMline( );   break;

		case C_ONPAGEEJECT:	FMoneject( ); break;	/* on all eject commands */

		case C_OUTLINE:          /* use true charpath and fill instead of stroke */
				if( FMgetparm( &buf ) > 0 )  /* get the parameter on | off */
				{
					if( toupper( buf[1] ) == 'N' )
						flags2 |= F2_TRUECHAR;        /* turn on the flag */
					else
						flags2 &= ~F2_TRUECHAR;       /* turn off the flag */
				}
				break;

		case C_NOFORMAT:                /* turn formatting off */
				FMflush( );                    /* send last formatted line on its way */
				flags = flags | NOFORMAT;      /* turn no format flag on */
				break;

		case C_PAGE:            /* eject the page now */
				FMflush( );            /* terminate the line in progress */
				FMpflush();            /* and do the flush */
				break;

		case C_PAGENUM:		FMpgnum( ); break;

		case C_PAGEMAR:		FMindent( &pageshift );  break;

		case C_POP:			FMpop_state( ); break;

		case C_PUNSPACE:	flags2 ^= F2_PUNSPACE; break;
	
		case C_PUSH:		FMpush_state( ); break;

		case C_QUIT:		 
						if( !FMcolnotes_show( 1 ) )			/* push command(s) to show end notes which MUST contain another .qu! */
							AFIclose( fptr->file ); 		/* if there wasn't end commands, then safe to close and exit now */
						break;

		case C_RFOOT:		FMsetstr( &rfoot, HEADFOOT_SIZE ); break;

		case C_RHEAD:		FMsetstr( &rhead, HEADFOOT_SIZE ); break;

		case C_RESTARTTAB:	
				TRACE( 1, ">>>++++ calling restart\n" )
				FMrestart_table(); 
				break;

		case C_SECTION:		FMsection( ); break;

		case C_SETX:		FMsetx( ); break;

		case C_SETY:		FMsety( ); break;

   		case C_SHOWV:
				if( (len = FMgetparm( &buf )) > 0 )
				{
					if( strcmp( buf, "all" ) == 0 )
						FMshowvars( );
					else
					{
						if( (ptr = sym_get( symtab, buf, 0 )) )
							fprintf( stderr, "(%s @ %ld) %s = (%s)\n", fptr->name, AFIstat( fptr->file, AFI_OPS, NULL), buf, ptr );
						else
							fprintf( stderr, "(%s @ %ld) %s = UNDEFINED\n", fptr->name, AFIstat( fptr->file, AFI_OPS, NULL), buf );
					}
				}
				break;

		case C_SINGLESPACE:        /* turn off double space */
				if( flags & DOUBLESPACE )
					flags = flags & (255-DOUBLESPACE);
				break;

		case C_SKIP:            
				if( cury == topy )
					break;                 /* if not at top fall into space */

		case C_SPACE:            /* user wants blank lines */
				FMspace( );
				break;

		case C_SETFONT:           								/* set font for text (font name only parm) */
				if( (len = FMgetparm( &ptr )) != 0 )     		/* if a parameter was entered */
				{
					*wbuf = 0;

					for( tok = ptr; *tok && (isalpha( *tok ) || *tok == '-'); tok++ );
					if(  *tok != 0 )								/* found non-alpha, assume closing . or ) or somesuch */
					{
						strcpy( wbuf, tok );
						*tok = 0;
					}

					TRACE( 2, "setfont old=%s  new=%s\n", curfont, ptr );
					free( curfont );          
					curfont = strdup( ptr );
					FMfmt_add( );		/* add a format block to the list */

					//if( *wbuf )
     				//	AFIpushtoken( fptr->file, wbuf );
				}
				else
					TRACE( 2, "setfont MISSING parameter!\n" );
				break;

		case C_SETTXTSIZE:        					/* set text font size */
				if( FMgetparm( &ptr ) )     		/* must have parameter */
				{
					if( (i = atoi( ptr )) > 5 )    /* if number is ok */
					{
						TRACE( 2, "textsize set to: %d\n", i );
						textsize = i; 
						FMfmt_add( );
					}
					else
						TRACE( 2, "textsize NOT set to: %d", i );
				}
				else
					TRACE( 2, "textsize NOT, no parm" );
				break;

		case C_SMASH:	 flags2 |= F2_SMASH; break;

		case C_TABLE:	 FMtable( ); break;

		case C_TABLEHEADER:	 FMth( ); break;

		case C_TABLEROW:	 FMtr( 0 ); break;

		case C_TMPFONT:	 FMtmpfont( ); break;

		case C_TMPTOP:            FMtmpy( cmd ); break;

		case C_TOC:	 FMtc( ); break;

		case C_TOPGUT:								// set the top gutter
				if( (len = FMgetparm( &ptr )) ) 
				{
					i = FMgetpts( ptr, len );
					if( i > 0 && i < topy )
					{
						TRACE( 2, "top gutter set to: %d\n", i );
						top_gutter = i; 
					} else {
						TRACE( 2, "top gutter not set, not in range: %d  topy=%d\n", i, topy )
					}
				} else {
Example #10
0
/*
---------------------------------------------------------------------------
 Mnemonic: fmtr
 Abstract: start a new row in the current table
 Date: 		26 Oct 2001 - converted from hfml stuff
 syntax:   .tr [n] [c=bgcolour] [a=alignval] [r=reserve] [v=valignvalue] [w=weight] [l=linecount]

			w= allows the line weight (drawn between the current row and the 
			   new) to be differnt than the default.

			m= allows multiple lines to separate the row being terminated from 
			   the next. Lines are spaced fairly close together.
 			The n option prevents table cell from being called automatically
			(user needs to supply a first .cl command).

			r= (reserve) will force a column break if the desired amount of 
			space isn't remaining.

 Mods:		10 Apr 2007 -- fixed write of border to be in conditional.
---------------------------------------------------------------------------
*/
extern void FMtr( int last )
 {
	struct table_mgt_blk *t = NULL;
	char *ptr = NULL;             /* pointer at parms */
	int len = 0;
	int do_cell = 1;       /* turned off by n option */
	char colour[50];
	char align[50];
	char valign[50];
	char obuf[2048];
	int row_top = 0;		/* used to calc the depth of each row */
	int	old_cn_space = 0;
	int required = 0;		// points required for the next row; col eject if not enough
	int	tmp_lw = -1;		// temp line weight (l=)
	int lcount = 1;			// number of horizontal separating lines

	colour[0] = 0;
	align[0] = 0;
	valign[0] = 0;

	if( ts_index <= 0 || (t = table_stack[ts_index-1]) == NULL ) {
		char *b;
		while( (len = FMgetparm( &b )) != 0 );			// no table, ditch parms and scoot
		return;
	}

	if( cur_col == firstcol )			/* we've not seen a .cl command (one col table) */
		t->maxy = cury;					/* force it to be set */
	row_top = cury;

	TRACE(2, "table/tr: cury=%d textsize=%d textspace=%d font=%s boty=%d topy=%d maxy=%d\n", cury, textsize, textspace, curfont, boty, topy, table_stack[ts_index-1]->maxy );

	while( cur_col != firstcol )
		FMcell( 0 );				/* flush and calc maxy for the row */
	
	t->tot_row_depth += t->maxy - row_top;		/* add in depth of this column */
	t->nrows++;
	t->ave_row_depth = t->tot_row_depth / t->nrows; 	/* average depth of a row to predict end of page */


   while( (len = FMgetparm( &ptr )) != 0 )
    {
     switch( *ptr ) 
      {
       case 'a':
         sprintf( align, "align=%s", ptr + 2 );
         break;

       case 'c':
		if( strncmp( ptr, "class=", 6 ) == 0 )			/* ignore hfm class */
			break;

         sprintf( colour, "bgcolor=%s", ptr + 2 );
         break;

		case 'l':
			if( *(ptr+1) == '=' ) {
				lcount = atoi( ptr+2 );
			}
			break;

       case 'n':
         do_cell = 0;
         break;

		case 'r':
			required = FMgetpts( ptr + 2, len-2 );
			break;

       case 'v':
         sprintf( valign, "valign=%s", ptr + 2 );
         break;

		case 'w':
			if( *(ptr+1) == '=' ) {
				tmp_lw = atoi( ptr+2 );
			}
			break;


       default: 								// ignore anything unrecognised
         break;
      }
    }

	cury = t->maxy + t->padding;

	if( t->border ) 						// add vert lines for the row if borders are on
	{
		sprintf( obuf, "%d setlinewidth ", t->weight );
		AFIwrite( ofile, obuf );
		tab_vlines( t, 0 );					/* add vlines just for this row */
	}

	if( t->border || tmp_lw >= 0 ) {							// add a top line if borders, or a temp line width was given
		int line_y = cury;

		TRACE( 2, "table/tr-border: cury=%d lcount=%d tlw=%d\n", cury, lcount, tmp_lw );
		if( lcount && tmp_lw >= 0 ) {							// dont need if no line generated
			sprintf( obuf, "%d setlinewidth ", tmp_lw );		// need a second adjustment
			AFIwrite( ofile, obuf );
		}

		while( lcount > 0 ) {
			//sprintf( obuf, "%d %d moveto %d %d rlineto stroke\n", t->lmar+t->padding, -cury, t->border_width-t->padding, 0 ); // top border
			sprintf( obuf, "%d %d moveto %d %d rlineto stroke\n", t->lmar+t->padding, -line_y, t->border_width-t->padding, 0 ); // top border
			AFIwrite( ofile, obuf );								// bottom line for the previous row

			if( --lcount ) {										// small increase to cury if we have more to do
				line_y += 2;
			}
		}
	}

	TRACE( 1, "table/tr: required=%d cn_space=%d ard=%d cury=%d boty=%d remain=%d\n", required, cn_space, t->ave_row_depth, cury, boty, boty-cury );
	
	// ??? Do we need to prevent eject if this is the last one?
	if( (required + cury) > (boty-8)  ||  cn_space + cury + t->ave_row_depth + textsize + textspace >= (boty-8) )	// extra 8pts to have room for bottom line
	{
		FMpause_table();					// pause so we can eject to the next real column which might be a page eject
 		AFIpushtoken( fptr->file, ".rt" ); 	// must restart table;  push first so that col notes go before if needed
		old_cn_space = cn_space;			// eject will reset if set
		PFMceject(  );						// move to the top of the new col/eject page
		if( old_cn_space > 0 ) {			// if col note, must set it up and return so it is processes before new col is started
			t->maxy = topy;
			return;							// allow the col notes commands to play out first
		}

		topy = t->old_topy;
		cury = topy;
		t->maxy = t->topy;					// reset the mexy for the next col/page
	}

	t->topy = cury;
	if( ! last )
		cury += t->padding;

	topy = cury;			/* columns need to bounce back to here */
 }