/* **************************************************************************** * * 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 */
/* ***************************************************************************** * * Mnemonic: FMcenter * Abstract: This routine will put the rest of the line of text entered with * this command (.ce) in the center of the current column using * the cen macro defined in the postscript output file. * If the first two tokens are numbers then the text is centered * between these points. * Parms: None. * Returns: Nothing. * Date: 2 November 1992 * Author: E. Scott Daniels * * .ce [x1=p1 x2=p2] <text to center> <eos> * * p1 and p2 are values in points from left column edge. If p2 is negative * then the distance is from the right edge of the current column. * * Modified: 25 Mar 1993 - To accept points between which text is centered * 28 Apr 1993 - To set same y flag if move to not necessary * 08 Feb 2002 - To ditch the x1 x2 parms as it seems to always cause * issues. now accepts x1= x2= parameters if user really * wants to do this. Should cause less headaches * 06 Jul 2013 - negative p2 value now supported. * 17 Jul 2016 - Changes for better prototype generation. ***************************************************************************** */ extern void FMcenter( void ) { char *buf; /* pointer at parameters */ int i; /* length of the token */ FMflush( ); /* write what ever might be there */ flags2 |= F2_CENTER; /* make flush center rather than show */ if( (i = FMgetparm( &buf )) > 0 && strncmp( buf, "x1=", 3 ) == 0 ) { flags2 |= F2_SAMEY; /* indicate same y value */ cenx1 = cur_col->lmar + atoi( buf+3 ); /* convert first point to integer */ if( FMgetparm( &buf ) > 0 && strncmp( buf, "x2=", 3 ) == 0 ) { cenx2 = cur_col->lmar + atoi( buf+3 ); /* convert second digit */ if( cenx2 < 0 ) /* assume neg value is distance from the right edge rather than left */ cenx2 += cur_col->width; } else { FMmsg( E_MISSINGPARM, inbuf ); /* missing parameter error */ return; } if( cenx2 <= cenx1 ) /* cannot have this */ { FMmsg( E_PARMOOR, inbuf ); /* send error and exit from here */ return; } i = FMgetparm( &buf ); /* get first text parm to center */ } else /* no columns defined - center between margins */ { cenx1 = cur_col->lmar; cenx2 = cur_col->lmar + cur_col->width; /* defalult center */ } TRACE( 2, "center: x1=%d x2=%d\n", cenx1, cenx2 ); while( i > 0 ) /* until all parameters gone */ { FMaddtok( buf, i ); /* add it to the output buffer */ i = FMgetparm( &buf ); } /* end while */ FMflush( ); /* send user line on the way */ flags2 &= ~(F2_CENTER | F2_SAMEY); /* turn off flags */ } /* fmcenter */
/* **************************************************************************** * * Mnemonic: FMmain * Abstract: This routine is the driver for the FM formatter * Parms: argc - Number of parameters passed to the routine * argv - Argument vectors * [1] - input file name * [2] - Output file name * Returns: Nothing. * Date: 15 November 1988 * Author: E. Scott Daniels * Modified: 5 May 1992 - To support conversion to postscript * 29 Oct 1992 - To call command only if .xx is followed by a * blank so that token starting with a . can be * included in the text (as long as they are more * than 2 characters long.) * 27 Nov 1992 - To support as is postscript commands * 10 Dec 1992 - To use AFI routines for ansi compatability * 15 Dec 1992 - To output a newline to stdout at end of run * 21 Dec 1992 - To process the .toc file generated * 13 Apr 1992 - To no longer break when blank as first char * 19 Nov 2001 - Conversion to use FMrun() * 18 Jul 2016 - Add consistent, and sometimes modern, prototypes. ************************************************************************** */ int main( int argc, char **argv ) { int len; /* length of token */ char *buf; /* buffer pointer to token */ if( FMinit( argc, argv ) < VALID ) return 1; FMrun( ); /* run the open file */ if( tocfile >= OK ) /* if the toc file is still open */ { /* then close it, and simulate .im command on it */ len = sprintf( inbuf, ".et\n" ); AFIclose( tocfile ); /* close the toc file */ } flags2 &= ~F2_SETFONT; /* dont start a new span on final flush */ FMflush(); /* final flush */ FMele_stack( ES_POP, ET_DOC ); /* final pop of all stacked closer tags */ //sprintf( obuf, "%s</body></HTML>", need_div ? "</div>" : "" ); /* end document stuff */ AFIwrite( ofile, obuf ); AFIclose( ofile ); /* close the output file */ sprintf( obuf, "%ld\n", words ); FMmsg( I_WORDCNT, obuf ); /* write number of words message */ return 0; }
/* **************************************************************************** * * Mnemonic: FMmain * Abstract: This routine is the driver for the FM formatter * Parms: argc - Number of parameters passed to the routine * argv - Argument vectors * [1] - input file name * [2] - Output file name * Returns: Nothing. * Date: 15 November 1988 * Author: E. Scott Daniels * Modified: 5 May 1992 - To support conversion to postscript * 29 Oct 1992 - To call command only if .xx is followed by a * blank so that token starting with a . can be * included in the text (as long as they are more * than 2 characters long.) * 27 Nov 1992 - To support as is postscript commands * 10 Dec 1992 - To use AFI routines for ansi compatability * 15 Dec 1992 - To output a newline to stdout at end of run * 21 Dec 1992 - To process the .toc file generated * 13 Apr 1992 - To no longer break when blank as first char * 18 Nov 2001 - To rewrite to allow for immediate ex of .im * 18 Dec 2015 - Call pflush at end only if cury not at top. * 17 Jul 2016 - Bring decls into the modern world. ************************************************************************** */ extern int main( int argc, char **argv ) { int len; /* length of token */ char *buf; /* buffer pointer to token */ if( FMinit( argc, argv ) < VALID ) return 1; FMrun( ); /* run the open file */ if( tocfile >= OK ) /* if the toc file is still open */ { /* then close it, and simulate .im command on it */ len = sprintf( inbuf, ".et\n" ); AFIwrite( tocfile, inbuf ); flags &= ~PAGE_NUM; /* turn off page numbering */ rhead = rfoot = NULL; /* no headers or footer either */ AFIclose( tocfile ); /* close the toc file */ } /* end if toc file open */ FMflush( ); /* flush the current line to page buffer */ if( cury != topy ) { TRACE( 3, "main flushing: %d %d\n", cury, topy ); FMpflush( ); // flush the page out of the printer with headers } AFIclose( ofile ); /* close the output file */ sprintf( obuf, "%ld\n", words ); FMmsg( I_WORDCNT, obuf ); /* write number of words message */ return 0; /* assume end of file reached */ }
/* **************************************************************************** * * Mnemonic: FMcindent * Abstract: This routine causes a break and beginning with the next line * sets the left margin according to the parameter. * Parms: mar - pointer to margin to adjust (heaer or left mar ) * Returns: Nothing. * Date: 3 December 1988 * Author: E. Scott Daniels * * Modified: 5 May 1992 - To support postscript conversion. * 24 Mar 1994 - To allow amount to be specified in pts or inches * 6 Apr 1994 - To use FMgetpts routine to convert value to pts * so n can be postfixed with p (points) or i (in). * 17 Jul 2016 - Changes for better prototype generation. * .in n | +n | -n (indention not changed if n is omitted) *************************************************************************** */ extern void FMindent( int* mar ) { char *buf; /* pointer at the token */ int len; int flags = 0; len = FMgetparm( &buf ); /* is there a length? */ if( len == 0 ) /* no parameter entered by user */ return; len = FMgetpts( buf, len ); /* convert value entered to points */ if( buf[0] == '+' || buf[0] == '-' ) /* add/sub parm to/from cur setting */ /*len = *mar + len; */ /* add pos/neg value to current setting */ *mar += len; /* "add" current setting to value entered */ else { /* reset mar to specific vlaue */ if( len < 0 || len > MAX_X ) /* if out of range */ { FMmsg( E_TAKEOUT, buf ); return; } else *mar = cur_col->lmar + len; /* base on the current column */ } /* end else - +/- sign not there */ /* *mar = len; */ /* reset the line length and go */ } /* FMindent */
/* ***************************************************************************** * * Mnemonic: FMcenter * Abstract: This routine will put the rest of the line of text entered with * this command (.ce) in the center of the current column using * the cen macro defined in the postscript output file. * If the first two tokens are numbers then the text is centered * between these points. * Parms: None. * Returns: Nothing. * Date: 2 November 1992 * Author: E. Scott Daniels * * .ce [x1 x2] <text to center> <eos> * * Modified: 25 Mar 1993 - To accept points between which text is centered * 28 Apr 1993 - To set same y flag if move to not necessary * 6 Dec 1996 - To convert to hfm (ignore x1, x2 if there) * 18 Jul 2016 - Add consistent, and sometimes modern, prototypes. ***************************************************************************** */ extern void FMcenter( void ) { char *buf; /* pointer at parameters */ int i; /* length of the token */ FMflush( ); /* write what ever might be there */ strcat( obuf, "<center>" ); /* add tag to output */ optr += 8; flags2 |= F2_CENTER; /* make flush center rather than show */ if( (i = FMgetparm( &buf )) > 0 && isdigit( buf[0] ) ) { if( !(FMgetparm( &buf ) > 0 && isdigit( buf[0] )) ) { FMmsg( E_MISSINGPARM, inbuf ); /* missing parameter error */ return; } i = FMgetparm( &buf ); /* get first text parm to center */ } while( i > 0 ) /* until all parameters gone */ { FMaddtok( buf, i ); /* add it to the output buffer */ i = FMgetparm( &buf ); } /* end while */ FMflush( ); /* send user line on the way */ flags2 &= ~(F2_CENTER | F2_SAMEY); /* turn off flags */ } /* fmcenter */
/* **************************************************************************** * * Mnemonic: FMopen * Abstract: This routine processes an imbed statement and opens a new * file to process. It is also used by index generation and maybe * other functions. A file is opened and its info is stacked. * the original purpose of this routine was to stack files and * not to present and end of file until the last file on the stack * reached the end of file. The AFI routines now provide a generic * stack interface and now this function's responsibilities are * significantly reduced. * file names for error messages. * Parms: name - Pointer to the name of the file to open * Returns: ERROR if unable to open the file, otherwise VALID * Date: 15 November 1988 * Author: E. Scott Daniels * * Modified: 16 Mar 1990 - Not to use FI routines.. there is a bug in * them someplace. * 10 Dec 1992 - To use AFI routines (which use ansi std fread) * 3 Apr 1997 - To begin phase out of this routine. * 19 Oct 2001 - Cleanup - finish work started on in 97 * 5 Feb 2001 - To save name * 21 Oct 2007 - Some general doc cleanup. ************************************************************************** */ int FMopen( char *name ) { int i; /* loop index */ if( fptr == NULL ) /* if first file opened */ { fptr = (struct fblk *) malloc( sizeof( struct fblk ) ); if( fptr == NULL ) { FMmsg( E_NOMEM, "FMopen" ); return( ERROR ); } memset( fptr, 0, sizeof( struct fblk ) ); fptr->fnum = 0; if( (fptr->file = AFIopenp( name, "r", path )) == AFI_ERROR ) { FMmsg( E_CANTOPEN, name ); free( fptr ); fptr = NULL; return( ERROR ); } AFIsetsize( fptr->file, MAX_READ-1 ); /* input buffer size */ strcpy( fptr->name, name ); } else { if( AFIchain( fptr->file, name, "pr", path ) == AFI_ERROR ) { FMmsg( E_CANTOPEN, name ); return( ERROR ); } fptr->fnum = 0; } fptr->count = 0l; /* set record counter */ return OK; /* beam us up scotty */ } /* FMopen */
/* **************************************************************************** * * Mnemonic: FMsection * Abstract: Sets font and fontsize allowing html output to generate a div * * Parms: none * Returns: Nothing. * Date: 13 Jul 2011 * Author: E. Scott Daniels * * Modified: * so n can be postfixed with p (points) or i (in). * .sc start c[lass]=class-name f[ont]=font-name s[ize]=font-size (classname ignored) *************************************************************************** */ void FMsection ( ) { char *buf; /* pointer at the token */ int len; char *tok; int i; while( (len = FMgetparm( &buf )) > 0 ) { switch( *buf ) { case 'c': /* class name -- ignore */ break; case 'e': /* ignore end */ break; case 'f': if( (tok = strchr( buf, '=' )) != NULL ) { tok++; free( curfont ); curfont = strdup( tok ); FMfmt_add( ); /* add a format block to the list */ } break; case 's': if( (tok = strchr( buf, '=' )) != NULL ) /* ignore start */ { tok++; if( (i = atoi( tok )) > 5 ) /* sanity */ { textsize = i; FMfmt_add( ); } } break; default: FMmsg( E_UNKNOWNPARM, buf ); break; } } }
/* **************************************************************************** * * *** WARNING: With the additon of the fmt blocks, this is likely broken!!! * * Mnemonic: FMsetx * Abstract: This routine is responsible for adjusting the current x position * on the output page. The value entered may be specified in pts or * inches. A + or - prefix to the value indicates a relitive move, * and a value without + or - indicates an absolute position in * relation to the current column's left margin value. * Params: None. * Returns: Nothing. * Date: 3 December 1992 * Author: E. Scott Daniels * * Modified: 10 Dec 1992 - To use AFI routines for ansi compatability * 25 Mar 1992 - To accept a + for relative moves * 22 Apr 1993 - To set relmove flag initially to false * 7 Apr 1994 - To use the getpts routine allowing user to enter * x value in inches or points. * 11 Apr 1994 - To take value relative to curcol's left margin * 31 Jan 2016 - To actually allow negative relative moves. * 17 Jul 2016 - Bring decls into the modern world. ****************************************************************************** */ extern void FMsetx( void ) { char *buf; /* pointer at the parameter user has entered */ int len; /* length of parameter entered */ int i; /* new x position */ int relmove = FALSE; /* new x is relative to current x position */ char wbuf[50]; /* buffer to build string in to write to file */ if( (len = FMgetparm( &buf )) > 0 ) /* if user entered a parameter */ { if( buf[0] == '+' || buf[0] == '-' ) /* relative move? */ relmove = TRUE; /* then set local flag */ i = FMgetpts( buf, len ); if( i < cur_col->width ) /* ensure its in the column */ { if( optr == 0 ) /* if nothing currently in the buffer */ { optr = 1; obuf[0] = ' '; /* force flush to setup the current y */ obuf[1] = EOS; osize = 0; /* reset output size */ } FMflush( ); /* put out what is already there */ if( relmove == TRUE ) /* if relative move */ { osize += i; /* indicate number of points skipped over */ sprintf( wbuf, "%d 0 rmoveto\n", i ); /* ps to relative move */ } else { osize = i; /* indicate position in obuf in terms of pts */ sprintf( wbuf, "%d %d moveto\n", cur_col->lmar + i, -cury ); } AFIwrite( ofile, wbuf ); /* write to file */ } /* end if in range */ else /* generate an error message */ FMmsg( E_PARMOOR, ".sx" ); } /* end if parm entered */ } /* FMsetx */
/* **************************************************************************** * * 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; }
extern void FMgetval( void ) { char *buf; /* pointer to parameter to use */ char *ep; /* pointer to value of env var */ char *ename; /* pointer to environment var name */ char work[128]; char value[2048]; /* buffer to build .dv commands in */ char vname[128]; int m; /* parameters to get date/time in */ int d; int y; int h; int s; int i; struct col_blk *cp; *value = 0; *vname = 0; if( FMgetparm( &buf ) > 0 ) /* if there is a parameter on the line */ { iptr = 0; /* start the input pointer at beginning of buffer */ switch( *buf ) /* look at user parameter and set psuedo command */ { case 'D': /* get string formatted date */ get_mdy( &m, &d, &y ); /* get the values */ strcpy( vname, "_date" ); snprintf( value, sizeof( value ), "%d %s %d", d, mname[m], 1900 + y ); break; case 'd': /* set date value */ get_mdy( &m, &d, &y ); /* get the values */ strcpy( vname, "_date" ); snprintf( value, sizeof( value ), "%d/%d/%d", m, d, 1900 + y ); /* create value */ break; case 'E': // eurpoean date dd/mm/yyyy get_mdy( &m, &d, &y ); // values strcpy( vname, "_date" ); // variable name snprintf( value, sizeof( value ), "%d/%d/%d", d, m, 1900 + y ); // value break; case 'e': /* e env-name xfm-var-name */ if( FMgetparm( &buf ) > 0 ) /* if there is a parameter on the line */ { ename = strdup( buf ); if( FMgetparm( &buf ) > 0 ) { if( ep = getenv( ename ) ) { snprintf( vname, sizeof( vname ), "%s", buf ); snprintf( value, sizeof( value ), "%s", ep ); } } free( ename ); } break; case 'F': /* set figure number variable AND advance the counter */ if( *(buf+1) == 'i' ) { strcpy( vname, "_fig" ); if( flags & PARA_NUM ) { snprintf( value, sizeof( value ), "%d-%d", pnum[0], fig ); } else { snprintf( value, sizeof( value ), "%d", fig ); } fig++; } break; case 'f': /* set figure number or font variable */ if( *(buf+1) == 'i' ) { if( flags & PARA_NUM ) { strcpy( vname, "_fig" ); snprintf( value, sizeof( value ), "%d-%d", pnum[0], fig ); } else { strcpy( vname, "_fig" ); snprintf( value, sizeof( value ), "%d", fig ); } } else { strcpy( vname, "_font" ); snprintf( value, sizeof( value ), "%s", curfont ); } break; case 'h': /* get host name */ gethostname( work, 128 ); strcpy( vname, "_host" ); snprintf( value, sizeof( value ), "%s", work ); break; case 'i': // ISO 8601 extended date get_mdy( &m, &d, &y ); // values strcpy( vname, "_date" ); // variable name snprintf( value, sizeof( value ), "%d-%d-%d", 1900 + y, m, y ); // value break; case 'l': /* set margin variables (lmar) or lines remaining in col (lines) */ if( *(buf+1) == 'i' ) { strcpy( vname, "_lines" ); snprintf( value, sizeof( value ), "%d", (boty - cury)/(textsize + textspace) ); } else { strcpy( vname, "_lmar" ); snprintf( value, sizeof( value ), "%d", lmar ); } break; case 'm': /* set month day year */ get_mdy( &m, &d, &y ); /* get the values */ strcpy( vname, "_mon" ); snprintf( value, sizeof( value ), "%s", mname[m] ); FMset_var( vname, value ); strcpy( vname, "_day" ); snprintf( value, sizeof( value ), "%d", d ); FMset_var( vname, value ); strcpy( vname, "_year" ); snprintf( value, sizeof( value ), "%d", 1900 + y ); break; case 'p': /* set page variable */ strcpy( vname, "_page" ); snprintf( value, sizeof( value ), "%d", page+1 ); break; case 'r': /* remain | rmar */ if( *(buf+1) == 'e' ) /* assume remain - generate iremain (inches) lines */ { strcpy( vname, "_attop" ); snprintf( value, sizeof( value ), "%s", cury == topy ? "true" : "false" ); FMset_var( vname, value ); strcpy( vname, "_lremain" ); snprintf( value, sizeof( value ), "%d", (boty - cury)/(textsize + textspace) ); FMset_var( vname, value ); strcpy( vname, "_lines" ); snprintf( value, sizeof( value ), "%d", (boty - cury)/(textsize + textspace) ); FMset_var( vname, value ); strcpy( vname, "_iremain" ); snprintf( value, sizeof( value ), "%d", (boty - cury)/72 ); /* 72 points per inch */ FMset_var( vname, value ); strcpy( vname, "_premain" ); snprintf( value, sizeof( value ), "%d", (boty - cury)); /* points */ FMset_var( vname, value ); } else { strcpy( vname, "_rmar" ); snprintf( value, sizeof( value ), "%d", lmar + linelen ); } break; case 's': strcpy( vname, "_sect" ); ep = FMget_header_num(); // if numbering, get the number if( ! ep ) { ep = FMget_header_txt(); // else get the string } if( ep ) { snprintf( value, sizeof( value ), "%s", ep ); } else { return; } break; case 't': if( *(buf+1) == 'a' ) // table number { if( flags & PARA_NUM ) { strcpy( vname, "_table" ); snprintf( value, sizeof( value ), "%d-%d", pnum[0], table_number ); } else { strcpy( vname, "_table" ); snprintf( value, sizeof( value ), "%d", table_number ); } } else { strcpy( vname, "_tsize" ); snprintf( value, sizeof( value ), "%d", textsize ); } break; case 'T': if( *(buf+1) == 'a' ) // table number and advance it { if( flags & PARA_NUM ) { strcpy( vname, "_table" ); snprintf( value, sizeof( value ), "%d-%d", pnum[0], table_number ); } else { strcpy( vname, "_table" ); snprintf( value, sizeof( value ), "%d", table_number ); } table_number++; } else // set time variable { get_times( &h, &m, &s ); // current time strcpy( vname, "_time" ); snprintf( value, sizeof( value ), "%02d:%02d", h, m ); } break; case 'v': strcpy( vname, "_ver" ); snprintf( value, sizeof( value ), "%s", version ); break; case 'y': /* set current y info: current y, top y, col-number */ strcpy( vname, "_cury" ); snprintf( value, sizeof( value ), "%d", cury ); FMset_var( vname, value ); strcpy( vname, "_topy" ); snprintf( value, sizeof( value ), "%d", topy ); FMset_var( vname, value ); i = 0; for( cp = firstcol; cp && cp != cur_col; cp = cp->next ) i++; strcpy( vname, "_coln" ); snprintf( value, sizeof( value ), "%d", i ); break; default: FMmsg( E_PARMOOR, inbuf ); /* error message */ break; } /* end switch */ if( *value ) { TRACE( 2, "getval: setting: %s=%s\n", vname, value ); FMset_var( vname, value ); } else fprintf( stderr, "getval: value was emppty; nothing set for %s\n", vname ); } /* end if parameter entered */ } /* fmgetval */
/* ***************************************************************************** * * Mnemonic: fmfloat_mar * Abstract: This module contains functions that support the floating margin * capaibilities. * Date: 01 January 2016 * Author: E. Scott Daniels * Mods: * 17 Jul 2016 - Bring decls into the modern world. * * .fm [i=distance] [w=distance] l=distance [y=yvalue] * l = temp left margin indention from current left margin * w = temp column width (-value subtracts from current width) * l = distance before resetting to original values (auto at col end if l > max y) * y = sets the current y position to this value * .fm pop .** pop the current float and set y to the reset value ***************************************************************************** */ extern void FMfloat_mar( void ) { char *ebuf; // input buffer char *buf; // pointer to info in input buffer int length = 0; // length of floating margins (default to end of col) int new_lmar = 0; // temporary left margin value int new_width = 0; // temporary width value int plen; // parameter token length int top_y = 0; // top y if set woth y= FMflush( ); // ensure last bits flushed out new_width = linelen; new_lmar = lmar; while( (plen = FMgetparm( &buf )) > 0 ) { switch( buf[0] ) { case 'l': case 'L': length = FMgetpts( &buf[2], plen-2 ); // get distance break; case 'w': // line length case 'W': if( buf[2] == '+' || buf[2] == '-' ) { new_width += FMgetpts( &buf[2], plen-2 ); } else { new_width = FMgetpts( &buf[2], plen-2 ); } break; case 'i': // indention case 'I': if( buf[2] == '+' || buf[2] == '-' ) { new_lmar += FMgetpts( &buf[2], plen-2 ); } else { new_lmar = FMgetpts( &buf[2], plen-2 ); } break; case 'p': if( strncmp( buf, "pop", 3 ) == 0 ) { if( cur_col->flags & CF_TMP_MAR ) { lmar = cur_col->olmar; linelen = cur_col->olinelen; cur_col->flags &= ~ CF_TMP_MAR; // reset flag, set cury and boogie out cury = cur_col->revert_y; } return; } else { FMmsg( E_UNKNOWNPARM, buf ); FMignore( ); return; } case 'y': case 'Y': top_y = FMgetpts( &buf[2], plen-2 ); if( length == 0 ) // length not set we'll force it length = cury - top_y; cury = top_y; break; default: FMmsg( E_UNKNOWNPARM, buf ); // let them know they buggered something FMignore( ); return; } } if( cur_col->flags & CF_TMP_MAR ) { // cannot be nested FMmsg( E_PARMOOR, "floating margin is already set" ); return; } if( new_width == linelen ) { // width wasn't adjusted if( new_lmar == lmar ) return; // nothing changed, just bail silently new_width -= new_lmar - lmar; // shrink width by indention amount } if( new_width <= 0 ) { char mbuf[1024]; snprintf( mbuf, sizeof( mbuf ), "width is too small: %d", new_width ); FMmsg( E_PARMOOR, mbuf ); return; } TRACE( 1, "floating mar: cury=%d new_lmar=%d new_linelen=%d revert=%d\n", cury, new_lmar, new_width, cury+length ) cur_col->olmar = lmar; cur_col->olinelen = linelen; cur_col->flags |= CF_TMP_MAR; lmar = new_lmar; linelen = new_width; cur_col->revert_y = cury + length; return; }
/* **************************************************************************** * * Mnemonic: FMdefheader * Abstract: This routine parses the .dh command which allows the user to * define the various attributes for each of the header levels. * If the skip value is set to 0 then no skipping is done before * or after the header. * .dh <level> [f=<fontname>] supply the font for header * [p=<size.[p|i]] size of header text * [s=<skip value>] spaces skipped before/after * [i=<indent>] indention of first line after * [u=on|off] translate header to upper case * [t=on|off] put in toc * [m=<space>[p|i]] offset from hmar location * [e=p(page)|c(olumn)|n(one) ] eject type * Parms: None. * Returns: Nothing. * Date: 7 November 1992 * Author: E. Scott Daniels * * Modified: 11 Jan 1993 - To allow toc, toupper, ejectp and ejectc flags * to be set/reset. * 17 Aug 1994 - To allow for header margin relative offset value * 15 Dec 1994 - To all skip values up to 99. * 23 Oct 2007 - Corrected pars error on t= * 17 Jul 2016 - Changes for better prototype generation. ***************************************************************************** */ extern void FMdefheader( void ) { char *buf; /* pointer at next parm to parse */ int level; /* current level we are working with */ int len; /* length of the parameter read */ struct header_blk *hptr; /* pointer at current block */ if( FMgetparm( &buf ) <= 0 ) /* if no parameters entered */ { return; } level = (atoi( buf )) - 1; /* convert level to numeric */ if( level < 0 || level >= MAX_HLEVELS ) /* if out of range */ { FMmsg( E_PARMOOR, NULL ); return; } hptr = headers[level]; /* point right at what we are changing */ while( (len = FMgetparm( &buf )) > 0 ) /* while parameters left */ { switch( buf[0] ) /* act on the command */ { case 'e': /* set eject type p==page, c==column, anything else */ case 'E': /* turns off all ejects */ hptr->flags &= ~(HEJECTP + HEJECTC); /* initially turn them both off */ if( len > 2 ) if( toupper( buf[2] ) == 'P' ) /* user wants page eject */ hptr->flags |= HEJECTP; /* turn on the page eject flag */ else if( toupper( buf[2] ) == 'C' ) /* user wants column eject */ hptr->flags |= HEJECTC; /* so turn it on */ break; case 'f': /* set font for this level */ case 'F': if( len > 2 ) /* if more than f= entered */ { if( hptr->font ) free( hptr->font ); /* free previous font buffer */ hptr->font = (char *) malloc( (unsigned) len ); /* get new buffer */ strncpy( hptr->font, &buf[2], len-2 ); /* copy new font name */ hptr->font[len-2] = EOS; /* terminate the string */ } break; case 'i': /* set indent value */ case 'I': hptr->indent = atoi( &buf[2] ); /* convert to integer */ if( hptr->indent < 0 || hptr->indent > 50 ) hptr->indent = 5; /* dont let user go crazy */ break; case 'm': case 'M': /* offset from header margin for this level */ hptr->hmoffset = FMgetpts( &buf[2], len-2 ); /* cvt input to points */ break; case 'p': /* set the point size */ case 'P': hptr->size = atoi( &buf[2] ); /* convert to integer */ if( hptr->size < 0 || hptr->size > 72 ) hptr->size = 12; /* dont let user go crazy */ break; case 's': case 'S': /* set skip value */ hptr->skip = atoi( &buf[2] ); /* convert to integer */ if( hptr->skip < 0 || hptr->skip > 99 ) hptr->skip = 2; /* dont let user go crazy */ break; case 't': /* set/clear toc flag */ case 'T': if( len == 0 || toupper( buf[3] ) == 'N' ) hptr->flags |= HTOC; /* turn on the toc flag */ else hptr->flags &= ~HTOC; /* turn off the flag */ break; case 'u': case 'U': if( len == 0 || toupper( buf[3] ) == 'N' ) /* turn on or missing */ hptr->flags |= HTOUPPER; else hptr->flags &= ~HTOUPPER; /* turn off */ break; default: break; /* right now do nothing - later error message */ } } }