/* *************************************************************************** * * 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 {
/* --------------------------------------------------------------------------- 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 */ }