diff options
Diffstat (limited to 'app/help/prochelp.c')
-rw-r--r-- | app/help/prochelp.c | 2178 |
1 files changed, 2178 insertions, 0 deletions
diff --git a/app/help/prochelp.c b/app/help/prochelp.c new file mode 100644 index 0000000..d1dd256 --- /dev/null +++ b/app/help/prochelp.c @@ -0,0 +1,2178 @@ + +/* XTrkCad - Model Railroad CAD + * Copyright (C) 2005 Dave Bullis + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#include <stdio.h> +#include <string.h> +#include <math.h> +#include <stdlib.h> +#if defined (__sun) && defined (__SVR4) +#include <ctype.h> +#endif +#include "readpng.h" + +#define PROGNAME "prochelp" + +char line[1024]; +int lineNum; +FILE * ifile; +FILE * ofile; +int wordwrap = 1; +int listLevel = -1; +int listType[10]; +int listCount[10]; +int lineWidth = 80; +int listWidth = 80; +int verbose = 0; +int toc = 0; +char * dirs[10] = { "." }; +char ** dirList = &dirs[1]; +int FontSize = 22; +double MarginTop = -1; +double MarginBottom = -1; +double MarginLeft = -1; +double MarginRight = -1; +double MarginGutter = -1; + +#define LISTNONE (0) +#define LISTBULLET (1) +#define LISTDASH (2) +#define LISTNUMBER (3) + +int USE_BMP = 0; + + +typedef struct { + void (*start)( char *, char * ); + void (*finish)( void ); + void (*newParagraph)( void ); + void (*startLine)( int ); + void (*doBold)( char * ); + void (*doItalic)( char * ); + void (*doXref)( char *, char *, char * ); + void (*doPicture)( char *, int ); + void (*endLine)( void ); + void (*putChar)( char ); + void (*doSection)( char, char *, char *, char *, char *, int ); + void (*doHeader)( char * ); + void (*doStartDisplay)( void ); + void (*doEndDisplay)( void ); + void (*doThread)( char * ); + void (*doListStart)( void ); + void (*doListItem)( void ); + void (*doListEnd)( void ); + void (*page)( void ); + + } dispatchTable; +dispatchTable *curMode; + +struct tocList_t; +typedef struct tocList_t * tocList_p; +typedef struct tocList_t { + tocList_p next; + char section; + long num; + char * title; + } tocList_t; +tocList_p tocHead = NULL; +tocList_p tocTail = NULL; +long tocNum = 37061946; + + +void no_op( void ) +{ +} +FILE * openFile( char * filename ) +{ + FILE * f; + char tmp[1024]; + char ** d; + + for ( d=dirs; *d; d++ ) { + sprintf( tmp, "%s/%s", *d, filename ); + f = fopen( tmp, "r" ); + if (f) + return f; + } + fprintf( stderr, "Can't open %s\n", filename ); + exit(1); +} + +void normalStart( char * inName, char * outName ) +{ + ifile = openFile( inName ); + if ( strcmp( outName, "-" ) == 0 ) { + ofile = stdout; + } else { + ofile = fopen( outName, "w" ); + if (ofile == NULL) { + perror( outName ); + exit( 1 ); + } + } +} +void normalFinish( void ) +{ + if (ofile) + fclose( ofile ); +} +void process( FILE * ); + +/****************************************************************************** + * + * COMMON RTF + * + *****************************************************************************/ + +int rtfNeedPar = FALSE; +int rtfNeedGap = FALSE; +int rtfNeedFI0 = FALSE; +int rtfGapHeight = -1; +int rtfBigGap = 60; + +void rtfFlushParagraph( void ) +{ + if ( rtfNeedPar ) { + if ( rtfNeedGap==TRUE && rtfGapHeight!=rtfBigGap ) { + fprintf( ofile, "\\sb%d", rtfBigGap ); + rtfGapHeight = rtfBigGap; + } + if ( rtfNeedGap==FALSE && rtfGapHeight!=0 ) { + fprintf( ofile, "\\sb0" ); + rtfGapHeight = 0; + } + fprintf( ofile, "\\par\n" ); + if ( rtfNeedFI0 ) + fprintf( ofile, "\\fi0\n" ); + rtfNeedPar = FALSE; + rtfNeedGap = FALSE; + rtfNeedFI0 = FALSE; + } +} + + +void rtfPutChar( char ch ) +{ + if ( ((ch) & 0x80) ){ + fprintf( ofile, "\\'%2.2X", (unsigned char)ch ); + } else if ( (ch) == '\\' ){ + fprintf( ofile, "\\\\" ); + } else { + fputc( ch, ofile ); + } + rtfNeedPar = TRUE; +} +void rtfPutString( char * cp ) +{ + while (*cp) { + rtfPutChar( *cp++ ); + } +} +void rtfNewParagraph( void ) +{ + if ( wordwrap ) { + rtfFlushParagraph(); +#ifdef LATER + if ( listLevel < 0 ) { + rtfFlushParagraph(); + rtfNeedGap = 1; + } else { + if ( rtfNeedPar ) { + fprintf( ofile, "\\line\r\n" ); + rtfNeedPar = FALSE; + } + } +#endif + } +} +void rtfStartLine( int lastBlank ) +{ + if ( !wordwrap ) { + fprintf( ofile, "\\tab\r\n" ); + } else if ( lastBlank ) { + rtfFlushParagraph(); + } +} +void rtfBold( char * name ) +{ + fprintf( ofile, "{\\b " ); + rtfPutString( name ); + fprintf( ofile, "}" ); +} +void rtfItalic( char * name ) +{ + fprintf( ofile, "{\\i " ); + rtfPutString( name ); + fprintf( ofile, "}" ); +} +void rtfEndLine( void ) +{ + if ( !wordwrap ) { + rtfNeedPar = TRUE; + rtfFlushParagraph(); + } +} +void rtfStartDisplay( void ) +{ + rtfFlushParagraph(); +} +void rtfListStart( void ) +{ + rtfFlushParagraph(); + if (listLevel>0) { + fprintf( ofile, "\\pard" ); +/* + if ( rtfNeedGap ) { + fprintf( ofile, "\\sb%d", rtfBigGap ); + rtfGapHeight = rtfBigGap; + rtfNeedGap = FALSE; + } +*/ + rtfGapHeight = -1; + } + fprintf( ofile, "\\tx360\\li%d\r\n", 360*(listLevel+1) ); +} +void rtfListItem( void ) +{ + /*if (listLevel == 0 || listCount[listLevel] > 1)*/ + rtfFlushParagraph(); + fprintf( ofile, "\\fi-360 " ); + rtfNeedFI0 = TRUE; + switch (listType[listLevel]) { + case LISTNONE: +#ifdef LATER + if ( listCount[listLevel] > 0 ) + fprintf( ofile, "\\fi-360 " ); + rtfNeedFI0 = TRUE; +#endif + break; + case LISTBULLET: + fprintf( ofile, "{\\f1\\'B7}\\tab" ); + break; + case LISTDASH: + fprintf( ofile, "{\\b -}\\tab" ); + break; + case LISTNUMBER: + fprintf( ofile, "{\\b %d}\\tab", listCount[listLevel] ); + break; + } + fprintf( ofile, "\r\n" ); +} +void rtfListEnd( void ) +{ + if (listLevel == -1) + fprintf( ofile, "\\par\\pard\r\n" ); + else + fprintf( ofile, "\\par\\pard\\tx360\\li%d\\fi-360\r\n", 360*(listLevel+1) ); + rtfNeedPar = FALSE; + rtfGapHeight = -1; + rtfNeedGap = FALSE; +} + +void rtfPage( void ) +{ + rtfFlushParagraph(); + fprintf( ofile, "\\page\r\n" ); +} + +/****************************************************************************** + * + * MSW-HELP + * + *****************************************************************************/ + +int pageCnt = 0; + +struct { + char * name; + int count; + } threads[100]; +int threadCnt = 0; + + +char * remap_minus( char * cp ) +{ + char * cp0 = cp; + for ( ; *cp; cp++ ) + if ( *cp == '-' ) + *cp = '_'; + return cp0; +} + +int lookupThread( char * name ) +{ + int inx; + if (!name) { + fprintf( stderr, "%d: NULL thread string\n", lineNum ); + return 0; + } + for (inx=0;inx<threadCnt;inx++) { + if (strcmp(threads[inx].name,name)==0) { + return ++(threads[inx].count); + } + } + threads[threadCnt].name = strdup( name ); + threads[threadCnt].count = 1; + threadCnt++; + return 1; +} + +void mswhelpXref( char * name, char * ref1, char * ref2 ) +{ + fprintf( ofile, "{\\uldb " ); + rtfPutString( name ); + fprintf( ofile, "}{\\v %s}", ref1 ); +} +void mswhelpPicture( char * name, int inLine ) +{ + if (inLine) { + fprintf( ofile, "\\{bml %s.shg\\}\\tab", name ); + rtfNeedPar = TRUE; + } else { + fprintf( ofile, "{\\qc\\{bmc %s.shg\\}\\par\\pard}\r\n", name ); + rtfNeedPar = FALSE; + rtfNeedGap = FALSE; + rtfGapHeight = -1; + } +} +void mswhelpSection( char section, char * title, char * context, char * picture, char * keywords, int newpage ) +{ + if (pageCnt != 0 && newpage) + fprintf( ofile, "\\page\r\n" ); + pageCnt++; + if (context && context[0] != '\0') + fprintf( ofile, "#{\\footnote %s}\r\n", remap_minus(context) ); + if (newpage && title && title[0] != '\0') { + fprintf( ofile, "${\\footnote %s}\r\n", title ); + } + if (keywords && keywords[0] != '\0') + fprintf( ofile, "K{\\footnote %s}\r\n", keywords ); + if (picture && picture[0] != '\0') { + mswhelpPicture( picture, 1 ); + } + if (title && title[0] != '\0') + fprintf( ofile, "{\\b\\fs30 %s}\r\n", title ); + fprintf( ofile, "\\par\r\n" ); + rtfNeedPar = FALSE; +} +void mswhelpHeader( char * line ) +{ + if ( line[0] == '*' ) + return; + fprintf( ofile, "#{\\footnote %s}\r\n", remap_minus(line) ); +} +void mswhelpThread( char * thread ) +{ + int threadCnt; + threadCnt = lookupThread( thread ); + fprintf( ofile, " +{\\footnote %s:%02d}\r\n", thread, threadCnt ); +} +dispatchTable mswhelpTable = { + normalStart, + normalFinish, + rtfNewParagraph, + rtfStartLine, + rtfBold, + rtfItalic, + mswhelpXref, + mswhelpPicture, + rtfEndLine, + rtfPutChar, + mswhelpSection, + mswhelpHeader, + rtfStartDisplay, + (void*)no_op, + mswhelpThread, + rtfListStart, + rtfListItem, + rtfListEnd, + (void*)no_op + }; + +/****************************************************************************** + * + * MSW-WORD + * + *****************************************************************************/ + + +struct BMFH { + char type[2]; + short size[2]; + short rsvd1; + short rsvd2; + short off[2]; + }; + +struct BMIH { + long size; + long width; + long height; + short planes; + short colors; + long comp; + long imageSize; + long xPelsPerMeter; + long yPelsPerMeter; + long clrUsed; + long clrImportant; + }; + +struct BMIH2 { + long size; + short width; + short height; + short planes; + short colors; + }; + +unsigned short S( short val ) +{ + union { + short inVal; + unsigned char outVal[2]; + } convShort; + short ret; + convShort.inVal = val; + ret = (((short)convShort.outVal[0])<<8) + ((short)convShort.outVal[1]); + return ret; +} + + +long L( long val ) +{ + union { + long inVal; + unsigned char outVal[4]; + } convLong; + long ret; + convLong.inVal = val; + ret = (((long)convLong.outVal[0])<<24) + (((long)convLong.outVal[1])<<16) + (((long)convLong.outVal[2])<<8) + ((long)convLong.outVal[3]); + return ret; +} + + +void dumpBytes( char * buff, long size, FILE * outF ) +{ + long inx, off, rc; + for (inx=0, off=1; inx<size; inx++,off++) { + fprintf( outF, "%0.2x", (unsigned char)buff[inx] ); + if (off >= 40) { + fprintf( outF, "\n" ); + off = 0; + } + } + if (off != 1) + fprintf( outF, "\n" ); +} + + +void conv24to8( long * colorTab, unsigned char * buff, int channels, int width24, int width8, int height ) +{ + long * lastColor, *cp; + long color; + unsigned char * ip; + unsigned char *op; + int h, w; + lastColor = colorTab; + memset( colorTab, 0, 1024 ); + op = buff; + for (h=0; h<height; h++) { + ip = buff+(width24*h); + op = buff+(width8*h); + for (w=0; w<width24; w+=channels,op++ ) { + color = ((long)(ip[0]))<<16; + color += ((long)(ip[1]))<<8; + color += ((long)(ip[2])); + ip += channels; + for ( cp=colorTab; cp<lastColor; cp++ ) { + if (color == *cp) { + *op = (unsigned char)(cp-colorTab); + goto nextPixel; + } + } + if (lastColor < &colorTab[256]) { + *op = (unsigned char)(lastColor-colorTab); + *lastColor++ = color; + } else { + *op = 0; + } +nextPixel: + ; + } + *op++ = 0; + *op++ = 0; + } +} + + +void dumpBmp( char * bmpName, FILE * outF ) +{ + long rc; + long size; + long fullSize; + long scanWidth, width8; + long h; + long picw, pich; + long fileSize, maxRecSize; + struct BMFH bmfh; + struct BMIH bmih; + struct BMIH2 bmih2; + char * buff; + long * colorTab; + long bmfhSize, bmfhOff; + FILE * bmpF; + int colormapOff; + int i, j; + + bmpF = openFile( bmpName ); + rc = fread( &bmfh, 1, sizeof bmfh, bmpF ); + rc = fread( &bmih, 1, sizeof bmih, bmpF ); + colormapOff = sizeof bmfh + sizeof bmih; + if (bmih.size == 12L) { + fseek( bmpF, sizeof bmfh, SEEK_SET ); + rc = fread( &bmih2, 1, sizeof bmih2, bmpF ); + bmih.width = bmih2.width; + bmih.height = bmih2.height; + bmih.planes = bmih2.planes; + bmih.colors = bmih2.colors; + bmih.comp = 0; + bmih.imageSize = 0; + bmih.xPelsPerMeter = 0; + bmih.yPelsPerMeter = 0; + bmih.clrUsed = 0; + bmih.clrImportant = 0; + colormapOff = sizeof bmfh + sizeof bmih2; + } +#ifdef LATER + bmfh.size = L(bmfh.size); + bmfh.off = L(bmfh.off); + bmih.size = L(bmih.size); + bmih.width = L(bmih.width); + bmih.height = L(bmih.height); + bmih.planes = S(bmih.planes); + bmih.colors = S(bmih.colors); + bmih.comp = L(bmih.comp); + bmih.imageSize = L(bmih.imageSize); + bmih.xPelsPerMeter = L(bmih.xPelsPerMeter); + bmih.yPelsPerMeter = L(bmih.yPelsPerMeter); + bmih.clrUsed = L(bmih.clrUsed); + bmih.clrImportant = L(bmih.clrImportant); +#endif + bmfhSize = ((unsigned short)bmfh.size[0]) + (((long)bmfh.size[1])<<16); + bmfhOff = ((unsigned short)bmfh.off[0]) + (((long)bmfh.off[1])<<16); + if (verbose) { + fprintf( stdout, "BMFH type %c%c, size %ld, off %ld\n", + bmfh.type[0], bmfh.type[1], bmfhSize, bmfhOff ); + fprintf( stdout, "BMIH size %ld, width %ld, height %ld, planes %d, colors %d\n comp %ld, imageSize %ld, xDPM %ld, yDPM %ld, clrUsed %ld, clrImportant %ld\n", + bmih.size, bmih.width, bmih.height, bmih.planes, bmih.colors, + bmih.comp, bmih.imageSize, bmih.xPelsPerMeter, bmih.yPelsPerMeter, + bmih.clrUsed, bmih.clrImportant ); + } + scanWidth = (bmih.width*bmih.colors+7)/8; + scanWidth = ((scanWidth+3)/4)*4; + fullSize = size = bmfhSize - bmfhOff; + if ( fullSize != bmih.height*scanWidth ) { + fprintf( stderr, "%s: height*scanWidth(%ld)(%ld) != fullSize(%ld)\n", bmpName, scanWidth, bmih.height*scanWidth, fullSize ); + return; + } + if ( bmih.colors != 24 && bmih.colors != 8 && bmih.colors != 4 && bmih.colors != 1) { + return; + } + if ( bmih.planes != 1 ) { + fprintf( stderr, "%s: planes(%d) != 1\n", bmpName, bmih.planes ); + return; + } + if ( bmih.comp != 0 ) { + fprintf( stderr, "%s: comp(%d) != 0\n", bmpName, bmih.comp ); + return; + } + + if (bmih.colors != 8) { + size = (((bmih.width+3)/4)*4) * bmih.height; + } + fileSize = (size+1024)/2 + 70; + maxRecSize = (size+1024)/2 + 34; + + picw = bmih.width*26L; + pich = bmih.height*26L; + if ( outF ) { + buff = NULL; + fprintf( outF, "{\\pict\\wmetafile8\\picw%ld\\pich%ld\\picwgoal%ld\\pichgoal%ld\\picbmp\\picbpp%d\n", + picw, pich, bmih.width*15L, bmih.height*15L, 8/*bmih.colors*/ ); + fprintf( outF, "010009000003%0.8lx0000%0.8lx0000\n", + L(fileSize), L(maxRecSize) ); + fprintf( outF, "050000000b0200000000\n" ); /* SetWindowOrg(0,0) */ + fprintf( outF, "050000000c02%0.4x%0.4x\n", S((short)bmih.height), S((short)bmih.width) ); + fprintf( outF, "05000000090200000000\n" ); /* SetTextColor( 0 ) */ + fprintf( outF, "050000000102d8d0c800\n" ); /* SetBkColor( 0 ) */ + fprintf( outF, "0400000007010300\n" ); /* SetStretchBltMode(0300) */ + fprintf( outF, "%0.8lx430f\n", L(maxRecSize) ); + fprintf( outF, "2000cc000000%0.4x%0.4x00000000%0.4x%0.4x00000000\n", + S((short)bmih.height), S((short)bmih.width), S((short)bmih.height), S((short)bmih.width) ); + fprintf( outF, "28000000%0.8lx%0.8lx%0.4x%0.4x000000000000000000000000000000000000000000000000\n", + L(bmih.width), L(bmih.height), S(bmih.planes), S(8/*bmih.colors*/) ); + switch ( bmih.colors ) { + case 8: + buff = (char*)malloc(1024); + fseek( bmpF, colormapOff, 0 ); + rc = fread( buff, 1024, 1, bmpF ); + if (bmih.size == 12L) { + for (h=255; h>=0; h--) { + for (i=3; i>=0; i--) + buff[h*4+i] = buff[h*3+i]; + buff[h*4+3] = 0; + } + } + dumpBytes( buff, 1024, outF ); + rc = fseek( bmpF, bmfhOff, 0 ); + buff = (char*)realloc( buff, (int)scanWidth ); + for ( h=0; h<bmih.height; h++ ) { + rc = fread( buff, (int)scanWidth, 1, bmpF ); + dumpBytes( buff, scanWidth, outF ); + } + break; + case 4: + buff = (char*)malloc(1024); + fseek( bmpF, colormapOff, 0 ); + memset( buff, 0, 1024 ); + rc = fread( buff, 3*16, 1, bmpF ); + for (h=15; h>=0; h--) { + for (i=3; i>=0; i--) + buff[h*4+i] = buff[h*3+i]; + buff[h*4+3] = 0; + } + dumpBytes( buff, 1024, outF ); + rc = fseek( bmpF, bmfhOff, 0 ); + buff = (char*)realloc( buff, (int)scanWidth*2+10 ); + width8 = (bmih.width+3)/4*4; + for ( h=0; h<bmih.height; h++ ) { + rc = fread( buff, (int)scanWidth, 1, bmpF ); + for (i=scanWidth-1; i>=0; i--) { + buff[i*2+1] = buff[i]&0xF; + buff[i*2] = (buff[i]>>4)&0xF; + } + dumpBytes( buff, width8, outF ); + } + break; + case 1: + buff = (char*)malloc(1024); + fseek( bmpF, colormapOff, 0 ); + memset( buff, 0, 1024 ); + rc = fread( buff, 3*2, 1, bmpF ); + for (h=1; h>=0; h--) { + for (i=3; i>=0; i--) + buff[h*4+i] = buff[h*3+i]; + buff[h*4+3] = 0; + } + dumpBytes( buff, 1024, outF ); + rc = fseek( bmpF, bmfhOff, 0 ); + buff = (char*)realloc( buff, (int)scanWidth*8+10 ); + width8 = (bmih.width+3)/4*4; + for ( h=0; h<bmih.height; h++ ) { + rc = fread( buff, (int)scanWidth, 1, bmpF ); + for (i=scanWidth-1; i>=0; i--) { + for (j=7; j>=0; j--) { + buff[i*8+j] = (buff[i]&(128>>j))?1:0; + } + } + dumpBytes( buff, width8, outF ); + } + break; + case 24: + buff = (char*)malloc( (int)(fullSize) ); + rc = fread( buff, (int)(fullSize), 1, bmpF ); + colorTab = (long*)malloc( 1024 ); + width8 = ((bmih.width+3)/4)*4; + conv24to8( colorTab, buff, (int)scanWidth, 3, (int)width8, (int)bmih.height ); + dumpBytes( (char*)colorTab, 1024, outF ); + for ( h=0; h<bmih.height; h++ ) { + dumpBytes( buff, (int)width8, outF ); + buff += (int)width8; + } + break; + default: + fprintf( stderr, "%s: colors(%d) != 24|8|4|1\n", bmpName, bmih.colors ); + return; + } + fprintf( outF, "030000000000\n" ); + fprintf( outF, "}\n" ); + } + fclose( bmpF ); +} + + +void dumpPng( + char * fileName, + FILE * outF ) +{ + FILE * pngF; + int rc; + unsigned long image_rowbytes, width8, h; + long image_width, image_height; + int image_channels; + unsigned char * image_data; + double display_exponent = 1.0; + + int bmih_colors = 24; + int bmih_planes = 1; + + long size, fileSize, maxRecSize; + long colorTab[1024]; + char pathName[1024]; + char ** dir; + + for ( dir=dirs; *dir; dir++ ) { + sprintf( pathName, "%s/%s", *dir, fileName ); + pngF = fopen( pathName, "r" ); + if ( pngF != NULL ) + break; + } + + if ( pngF == NULL ) { + perror( fileName ); + return; + } + if ((rc = readpng_init(pngF, (long *) &image_width, (long *) &image_height)) != 0) { + switch (rc) { + case 1: + fprintf(stderr, PROGNAME + ": [%s] is not a PNG file: incorrect signature\n", + pathName); + break; + case 2: + fprintf(stderr, PROGNAME + ": [%s] has bad IHDR (libpng longjmp)\n", + pathName); + break; + case 4: + fprintf(stderr, PROGNAME ": insufficient memory\n"); + break; + default: + fprintf(stderr, PROGNAME + ": unknown readpng_init() error\n"); + break; + } + return; + } + + image_data = readpng_get_image(display_exponent, &image_channels, &image_rowbytes); + width8 = ((image_width+3)/4)*4; + size = width8*image_height; + fileSize = (size+1024)/2 + 70; + maxRecSize = (size+1024)/2 + 34; + + fprintf( outF, "{\\pict\\wmetafile8\\picw%ld\\pich%ld\\picwgoal%ld\\pichgoal%ld\\picbmp\\picbpp%d\n", + image_width*26L, image_height*26L, image_width*15L, image_height*15L, 8/*bmih_colors*/ ); + fprintf( outF, "010009000003%0.8lx0000%0.8lx0000\n", + L(fileSize), L(maxRecSize) ); + fprintf( outF, "050000000b0200000000\n" ); /* SetWindowOrg(0,0) */ + fprintf( outF, "050000000c02%0.4x%0.4x\n", S((short)image_height), S((short)image_width) ); + fprintf( outF, "05000000090200000000\n" ); /* SetTextColor( 0 ) */ + fprintf( outF, "050000000102d8d0c800\n" ); /* SetBkColor( 0 ) */ + fprintf( outF, "0400000007010300\n" ); /* SetStretchBltMode(0300) */ + fprintf( outF, "%0.8lx430f\n", L(maxRecSize) ); + fprintf( outF, "2000cc000000%0.4x%0.4x00000000%0.4x%0.4x00000000\n", + S((short)image_height), S((short)image_width), S((short)image_height), S((short)image_width) ); + fprintf( outF, "28000000%0.8lx%0.8lx%0.4x%0.4x000000000000000000000000000000000000000000000000\n", + L(image_width), L(image_height), S(bmih_planes), S(8/*bmih.colors*/) ); + width8 = ((image_width+3)/4)*4; + conv24to8( colorTab, (char *) image_data, image_channels, image_width*image_channels, width8, image_height ); + dumpBytes( (char *)colorTab, 1024, outF ); + for ( h=0; h<image_height; h++ ) { + dumpBytes( (char *) image_data+(h)*width8, (int)width8, outF ); + } + fprintf( outF, "030000000000\n" ); + fprintf( outF, "}\n" ); + + readpng_cleanup(0); + fclose( pngF ); + free( image_data ); + +} + +void mswwordXref( char * name, char * ref1, char * ref2 ) +{ + rtfBold( name ); +} +void mswwordPicture( char * name, int inLine ) +{ + char tmp[80]; + if (!inLine) { + rtfFlushParagraph(); + fprintf( ofile, "{\\qc\\sb%d", rtfNeedGap?rtfBigGap:0 ); + } + if ( USE_BMP ) { + sprintf( tmp, "%s.bmp", name ); + dumpBmp( tmp, ofile ); + } else { + sprintf( tmp, "%s.png", name ); + dumpPng( tmp, ofile ); + } + if (inLine) { + /*fprintf( ofile, "\\tab " );*/ + rtfNeedPar = TRUE; + } else { + fprintf( ofile, "\\par\\pard}\n" ); + rtfNeedPar = FALSE; + rtfNeedGap = FALSE; + rtfGapHeight = -1; + } +} +int sectionNum[3] = { 0, 0, 0 }; +void mswwordSection( char section, char * title, char * context, char * picture, char * keywords, int newpage ) +{ + char tmp[1024]; + char sectionNumS[20]; + rtfFlushParagraph(); + if (pageCnt != 0 && newpage) { + fprintf( ofile, "\\page\n" ); + } + pageCnt++; + if (toc) { + fprintf( ofile, "{\\*\\bkmkstart _Toc%ld}\n", tocNum ); + } + fprintf( ofile,"\ +{\\pntext\\pard\\plain\\b\\f5\\fs28\\kerning28 \ +" ); + switch ( section ) { + case 'A': + sprintf( sectionNumS, "%d. ", ++sectionNum[0] ); + sectionNum[1] = sectionNum[2] = 0; + break; + case 'B': + sprintf( sectionNumS, "%d.%d ", sectionNum[0], ++sectionNum[1] ); + sectionNum[2] = 0; + break; + case 'C': +#ifdef LATER + sprintf( sectionNumS, "%d.%d.%d ", sectionNum[0], sectionNum[1], ++sectionNum[2] ); +#else + sprintf( sectionNumS, "" ); +#endif + break; + default: + sprintf( sectionNumS, "bad section (%c) ", section ); + } + fprintf( ofile, "\ +%s\\tab}\ +\\pard\\plain \\s%d\\sb240\\sa60\\keepn\\widctlpar\ +{\\*\\pn \\pnlvl%d\\pndec\\pnprev1\\pnstart1\\pnindent720\\pnhang\ +{\\pntxta .}\ +}\ +\\b\\f5\\fs28\\kerning28 %s\ +", sectionNumS, section-'A'+1, section-'A'+1, title ); + if (picture && picture[0] != '\0') { + fprintf( ofile, " " ); + mswwordPicture( picture, 1 ); + } + if (toc) { + fprintf( ofile, "{\\*\\bkmkend _Toc%ld}\n", tocNum ); + } + fprintf( ofile, "\ +\\par \ +\\pard\\plain \\widctlpar \\f4\\fs%d \ +\n", FontSize ); + if (toc) { + tocList_p tl; + tl = (tocList_p)malloc( sizeof *tl ); + tl->section = section; + tl->title = (char*)malloc( strlen(sectionNumS) + strlen(title) + 1 ); + sprintf( tl->title, "%s%s", sectionNumS, title ); + tl->num = tocNum++; + tl->next = NULL; + if (tocHead == NULL) + tocHead = tl; + else + tocTail->next = tl; + tocTail = tl; + } + rtfNeedPar = FALSE; + rtfNeedGap = TRUE; + rtfGapHeight = -1; +} + +void mswwordStart( char * inName, char * outName ) +{ + normalStart( inName, outName ); + if ( MarginGutter >= 0.0 ) + fprintf( ofile, "\\margmirror\\gutter%d\n", (int)(MarginGutter*1440.0) ); + if (MarginTop >= 0.0) + fprintf( ofile, "\\margt%d\n", (int)(MarginTop*1440.0) ); + if (MarginBottom >= 0.0) + fprintf( ofile, "\\margb%d\n", (int)(MarginBottom*1440.0) ); + if (MarginRight >= 0.0) + fprintf( ofile, "\\margr%d\n", (int)(MarginRight*1440.0) ); + if (MarginLeft >= 0.0) + fprintf( ofile, "\\margl%d\n", (int)(MarginLeft*1440.0) ); +} + +void mswwordFinish( void ) +{ + char lastSection = 'A'; + tocList_p tl; + rtfFlushParagraph(); + if (toc) { + fprintf( ofile, "\ +\\sect \\sectd \\pgnrestart\\pgnlcrm\\linex0\\endnhere\ +\\pard\\plain \\qc\\widctlpar \\f4\\fs22 \ +{\\b\\fs36\\lang1024\\kerning28 Contents \\par \\par }\ +\\pard\\plain \\s17\\widctlpar\\tqr\\tldot\\tx8640 \\f4\\fs%d\n", FontSize ); + for ( tl=tocHead; tl; tl=tl->next ) { + if ( tl->section != lastSection ) { + fprintf( ofile, "\ +\\pard\\plain \\s%d\\li%d\\widctlpar\\tqr\\tldot\\tx8640 \\f4\\fs%d\n", + tl->section-'A'+17, + (tl->section-'A')*200, FontSize ); + lastSection = tl->section; + } + fprintf( ofile, "\ +{\\lang1024\\kerning28 %s}{\\lang1024 \\tab }\ +{\\field{\\*\\fldinst {\\lang1024 GOTOBUTTON _Toc%ld }\n\ +{\\field{\\*\\fldinst {\\lang1024 PAGEREF _Toc%ld }}\ +{\\fldrslt {\\lang1024 3}}}}}{\\lang1024 \\par }\n", + tl->title, tl->num, tl->num); + } + fprintf( ofile, +"\\pard\\plain \\widctlpar \\f4\\fs%d\n}\n}\n" +/*\\pard\\plain \*/ +"\\widctlpar \\f4\\fs%d\n" , FontSize, FontSize); + } + normalFinish(); +} + + +dispatchTable mswwordTable = { + mswwordStart, + mswwordFinish, + rtfNewParagraph, + rtfStartLine, + rtfBold, + rtfItalic, + mswwordXref, + mswwordPicture, + rtfEndLine, + rtfPutChar, + mswwordSection, + (void*)no_op, + rtfStartDisplay, + (void*)no_op, + (void*)no_op, + rtfListStart, + rtfListItem, + rtfListEnd, + rtfPage + }; + +/****************************************************************************** + * + * TEXT + * + *****************************************************************************/ + +char textBuff[1024]; +char *textBuffP = textBuff; +int textNewLine = 1; +int textIndent = 0; +int textAllowLeadingBlanks = 0; +int textNoIndent = 0; +int textLineLength; + +void textPutChar( char ch ) +{ + char *cp, *cq; + int indent; + int width; + + if (textNewLine) { + textLineLength = 0; + if (ch == ' ' && !textAllowLeadingBlanks) { + return; + } + if (!textNoIndent) { + for (indent=0; indent<textIndent; indent++) { + memmove( textBuffP, " ", 4 ); + textBuffP += 4; + textLineLength += 4; + } + } + } + textNewLine = 0; + *textBuffP++ = ch; + if (ch == '\010') + textLineLength--; + else + textLineLength++; + width = (textIndent>0?listWidth:lineWidth); + if ( wordwrap && width > 0 && textLineLength > width ) { + for (cp = textBuffP-1; *cp != ' ' && cp>textBuff+lineWidth/2; cp-- ); + while ( *cp == ' ' && cp>textBuff+lineWidth/2 ) cp--; + cp++; + fwrite( textBuff, cp-textBuff, 1, ofile ); + fwrite( "\n", 1, 1, ofile ); + textNewLine = 1; + while (*cp == ' ' && cp<textBuffP) cp++; + if (textBuffP!=cp) { + cq = textBuff+textIndent*4; + memmove( cq, cp, textBuffP-cp ); + cq = textBuff; + for (indent=0; indent<textIndent; indent++) { + memmove( cq, " ", 4 ); + cq += 4; + } + textBuffP = cq + (textBuffP-cp); + textNewLine = 0; + for ( cp=textBuff,textLineLength=0; cp<textBuffP; cp++ ) { + if (*cp == '\010') + textLineLength--; + else + textLineLength++; + } + } else { + textBuffP = textBuff; + } + } else if (textBuffP - textBuff >= sizeof textBuff ) { + fwrite( textBuff, textBuffP-textBuff, 1, ofile ); + textBuffP = textBuff; + textLineLength = 0; + } +} +void textBreakLine( void ) +{ + if ( !textNewLine ) { + fwrite( textBuff, textBuffP-textBuff, 1, ofile ); + fwrite( "\n", 1, 1, ofile ); + textNewLine = 1; + textBuffP = textBuff; + textLineLength = 0; + } +} +void textSaveLine( char * tmp ) +{ + if (!textNewLine) { + int len = textBuffP-textBuff; + memcpy( tmp, textBuff, len ); + tmp[len] = '\0'; + textNewLine = 1; + textBuffP = textBuff; + textLineLength = 0; + } else { + tmp[0] = '\0'; + } +} +void textRestoreLine( char * tmp ) +{ + int len = strlen( tmp ); + if (len > 0) { + memcpy( textBuffP, tmp, len ); + textBuffP += len; + textLineLength += len; + textNewLine = 0; + } +} +void textFinish( void ) +{ + textBreakLine(); + normalFinish(); +} +void textPutString( char * cp ) +{ + while (*cp) + textPutChar( *cp++ ); +} +void textNewParagraph( void ) +{ + textBreakLine(); + if (wordwrap) { + fwrite( "\n", 1, 1, ofile ); + } +} +void textStartLine( int lastlineblank ) +{ +} +void textBold( char * name ) +{ + char * cp; + /*textPutChar( '<' );*/ + for ( cp = name; *cp; cp++ ) { + textPutChar( *cp ); + if (*cp != ' ') { + textPutChar( '\010' ); + textPutChar( *cp ); + } + } + /*textPutString( name );*/ + /*textPutChar( '>' );*/ +} +void textItalic( char * name ) +{ + char * cp; + /*textPutChar( '<' );*/ + for ( cp = name; *cp; cp++ ) { + textPutChar( *cp ); + if (*cp != ' ') { + textPutChar( '\010' ); + textPutChar( *cp ); + } + } + /*textPutString( name );*/ + /*textPutChar( '>' );*/ +} +void textXref( char * name, char * ref1, char * ref2 ) +{ + textBold( name ); + /*textPutChar( '<' ); + textPutString( name ); + textPutChar( '>' );*/ + if (ref2) { + textPutString( " (See " ); + textPutString( ref2 ); + textPutString( " for Details)" ); + } +} +void textPicture( char * picture, int inLine ) +{ + textPutString( "<<" ); + textPutString( picture ); + textPutString( ">>" ); + if (inLine) { + textPutString( " " ); + } else { + textBreakLine(); + fwrite( "\n", 1, 1, ofile ); + } +} +void textEndLine( void ) +{ + if ( !wordwrap ) + textBreakLine(); +} +void textSection( char section, char * title, char * context, char * picture, char * keywords, int newpage ) +{ + int len; + textBreakLine(); + if (pageCnt > 0 && newpage) { + fwrite( "\014\n", 1, 2, ofile ); + } + pageCnt++; + textBold( title ); + /*textPutString( title );*/ + textBreakLine(); + for ( len = strlen(title); len>0; len-- ) { + textBold( "=" ); + /*fwrite( "=", 1, 1, ofile );*/ + } + textBreakLine(); + fwrite( "\n", 1, 1, ofile ); +} +void textHeader( char * line ) +{ +} +void textStartIndent( void ) +{ + textBreakLine(); + textIndent++; +} +void textEndIndent( void ) +{ + textBreakLine(); + if (textIndent < 0) { + fprintf( stderr, "%d: textIndent < 0\n", lineNum ); + textIndent = 0; + } else { + textIndent--; + } +} +void textListItem( void ) +{ + char num[4]; + textBreakLine(); + textIndent--; + textAllowLeadingBlanks = 1; + switch( listType[listLevel] ) { + case LISTNONE: + default: + textPutString( " " ); + break; + case LISTBULLET: + textPutString( " o " ); + break; + case LISTDASH: + textPutString( " - " ); + break; + case LISTNUMBER: + sprintf( num, "%3.3d", listCount[listLevel] ); + textPutString( num ); + textPutChar( ' ' ); + break; + } + textAllowLeadingBlanks = 0; + textIndent++; +} +void textPage( void ) +{ + fwrite( "\014\n", 1, 2, ofile ); +} +dispatchTable textTable = { + normalStart, + textFinish, + textNewParagraph, + textStartLine, + textBold, + textItalic, + textXref, + textPicture, + textEndLine, + textPutChar, + textSection, + textHeader, + textStartIndent, + textEndIndent, + (void*)no_op, + textStartIndent, + textListItem, + textEndIndent, + textPage + }; + +/****************************************************************************** + * + * XVIEW + * + *****************************************************************************/ + + +void xviewStart( char * inName, char * outName ) +{ + normalStart( inName, outName ); + lineWidth = 0; +} + +void xviewBold( char * name ) +{ + char * cp; + textPutChar( '<' ); + textPutString( name ); + textPutChar( '>' ); +} +void xviewItalic( char * name ) +{ + char * cp; + textPutChar( '<' ); + textPutString( name ); + textPutChar( '>' ); +} +void xviewXref( char * name, char * ref1, char * ref2 ) +{ + xviewBold( name ); + if (ref2) { + textPutString( " (See " ); + textPutString( ref2 ); + textPutString( " for Details)" ); + } +} +void xviewSection( char section, char * title, char * context, char * picture, char * keywords, int newpage ) +{ + int indent; + int len; + + static char * stars = "************"; + indent = line[1]-'A'+1; + textBreakLine(); + if (pageCnt > 0 && newpage) { + fwrite( "\n", 1, 1, ofile ); + } + if ( newpage ) { + pageCnt++; + textNoIndent = 1; + textPutChar( ':' ); + textPutString( stars+strlen(stars)-indent ); + textPutChar( '-' ); + textPutString( title ); + textBreakLine(); + if (context) { + textPutChar( ':' ); + textPutString( context ); + textPutChar( ' ' ); + textBreakLine(); + } + } + textNoIndent = 0; + xviewBold( title ); + textBreakLine(); + for ( len = strlen(title); len>0; len-- ) + fwrite( "=", 1, 1, ofile ); + fwrite( "\n\n", 1, 2, ofile ); +} +void xviewHeader( char * line ) +{ + char tmp[1024]; + textSaveLine( tmp ); + textNoIndent = 1; + textPutChar( ':' ); + textPutString( line ); + textPutChar( ' ' ); + textBreakLine(); + textNoIndent = 0; + textRestoreLine( tmp ); +} +dispatchTable xviewTable = { + xviewStart, + normalFinish, + textNewParagraph, + textStartLine, + xviewBold, + xviewItalic, + xviewXref, + (void*)no_op, /* picture */ + textEndLine, + textPutChar, + xviewSection, + xviewHeader, + textStartIndent, /* startDisplay */ + textEndIndent, /* endDisplay */ + (void*)no_op, + textStartIndent, /* listStart */ + textListItem, + textEndIndent, /* listEnd */ + (void*)no_op + }; + +/****************************************************************************** + * + * HTML + * + *****************************************************************************/ + +char * htmlName; +char htmlFileName[1024]; + +struct { + char * name; + int index; + int section; + } links[500]; +int linkCnt = 0; + +void setLink( char * name, int sectionNumber ) +{ + links[linkCnt].name = strdup( name ); + links[linkCnt].section = sectionNumber; + linkCnt++; +} + + +void getLinks( int sectionNumber, int * prev, int * next ) +{ + int cur, inx; + + *prev = -1; + *next = -1; + for ( cur = 0; cur < linkCnt; cur++ ) { + if ( links[cur].section == sectionNumber ) { + for (inx = cur-1; inx >= 0; inx-- ) { + if ( strcmp( links[cur].name, links[inx].name ) == 0 ) { + *prev = links[inx].section; + break; + } + } + for (inx = cur+1; inx < linkCnt; inx++ ) { + if ( strcmp( links[cur].name, links[inx].name ) == 0 ) { + *next = links[inx].section; + break; + } + } + } + } + +} + + +struct { + char * name; + int sectionNumber; + int subSection; + } sections[500]; +int sectionCnt = 0; +int lastSection = 0; +int curSection = 0; +int subSection = 0; + + +void defineSection( char * name, int sectionNumber ) +{ + if (!name) { + fprintf( stderr, "%d: NULL context string\n", lineNum ); + return; + } + sections[sectionCnt].name = strdup( name ); + sections[sectionCnt].sectionNumber = sectionNumber; + if (lastSection != sectionNumber) { + subSection = 0; + } + sections[sectionCnt].subSection = subSection++; + sectionCnt++; +} + + +int lookupSection( char * name, int *subSection ) +{ + int inx; + if (!name) { + return -1; + } + for (inx=0; inx<sectionCnt; inx++) { + if (strcmp( name, sections[inx].name ) == 0) { + *subSection = sections[inx].subSection; + return sections[inx].sectionNumber; + } + } + fprintf( stderr, "%d: undefined reference to %s\n", lineNum, name ); + return -1; +} + + +void genHtmlLinks( int sectionNumber, int begin ) +{ + int prev, next; + int comma = 0; + + if (ofile) { + if (sectionNumber != 0) { + if (!begin) fprintf( ofile, "\n<p></p><p></p><hr><p>" ); + fprintf( ofile, "<a href=%s.html><b>Return to Contents</b></a>", + htmlName ); + comma = 1; + } + getLinks( sectionNumber, &prev, &next ); + if (prev > 0) { + if (comma) + fprintf( ofile, ", " ); + else + if (!begin) fprintf( ofile, "\n<p></p><p></p><hr><p>" ); + fprintf( ofile, "<a href=%s-%d.html><b>Previous Page</b></a>", + htmlName, prev ); + comma = 1; + } + if (next > 0) { + if (comma) + fprintf( ofile, ", " ); + else + if (!begin) fprintf( ofile, "\n<p></p><p></p><hr><p>" ); + fprintf( ofile, "<a href=%s-%d.html><b>Next Page</b></a>", + htmlName, next ); + comma = 1; + } + if (comma) + if (begin) + fprintf( ofile, "</p><hr><p></p>\n" ); + else + fprintf( ofile, "</p>\n" ); + } +} + +int preHtmlSectionNumber = -1; +void preHtmlSection( char section, char * title, char * context, char * picture, char * keywords, int newpage ) +{ + if ( !newpage ) + return; + preHtmlSectionNumber++; + defineSection( context, preHtmlSectionNumber ); +} +void preHtmlHeader( char * line ) +{ + if ( line[0] == '*' ) + return; + defineSection( line, preHtmlSectionNumber ); +} +void preHtmlThread( char * thread ) +{ + setLink( thread, preHtmlSectionNumber ); +} +dispatchTable preHtmlTable = { + (void*)no_op, + (void*)no_op, + (void*)no_op, + (void*)no_op, + (void*)no_op, + (void*)no_op, + (void*)no_op, + (void*)no_op, + (void*)no_op, + (void*)no_op, + preHtmlSection, + preHtmlHeader, + (void*)no_op, + (void*)no_op, + preHtmlThread, + (void*)no_op, + (void*)no_op, + (void*)no_op, + (void*)no_op + }; + +dispatchTable htmlTable; + +void htmlStart( char * inName, char * outName ) +{ + curMode = &preHtmlTable; + ifile = openFile( inName ); + process( ifile ); + fclose( ifile ); + curMode = &htmlTable; + + ifile = openFile( inName ); + htmlName = outName; + sprintf( htmlFileName, "%s.html", htmlName ); + ofile = fopen( htmlFileName, "w" ); + if (ofile == NULL) { + perror( outName ); + exit( 1 ); + } +} +void htmlFinish( void ) +{ + genHtmlLinks( curSection, 0 ); +} +void htmlNewParagraph( void ) +{ + if (wordwrap) { + if ( listLevel < 0 ) + fprintf( ofile, "<p>" ); + else + fprintf( ofile, "<br>" ); + } else { + fprintf( ofile, "\n" ); + } +} +void htmlStartLine( int lastBlank ) +{ + if (wordwrap) + fprintf( ofile, "\n" ); + else + fprintf( ofile, "\t" ); +} +void htmlBold( char * name ) +{ + fprintf( ofile, "<b>%s</b>", name ); +} +void htmlItalic( char * name ) +{ + fprintf( ofile, "<i>%s</i>", name ); +} +void htmlXref( char * name, char * ref1, char * ref2 ) +{ + int sectionNumber, subSection; + sectionNumber = lookupSection( ref1, &subSection ); + if (sectionNumber < 0) + return; + fprintf( ofile, "<a href=%s", htmlName ); + if (sectionNumber != 0) + fprintf( ofile, "-%d", sectionNumber ); + fprintf( ofile, ".html" ); + if (subSection != 0) + fprintf( ofile, "#%d", subSection ); + fprintf( ofile, ">%s</a>", name ); +} +void htmlPicture( char * name, int inLine ) +{ + fprintf( ofile, "<img src=%s.png>", name ); + if (inLine) + fprintf( ofile, "\t" ); + else + fprintf( ofile, "<p></p>\n" ); +} +void htmlEndLine( void ) +{ + if ( !wordwrap ) + fprintf( ofile, "\n" ); +} +void htmlPutChar( char ch ) +{ + if ( ch == '<' ) + fprintf( ofile, "<" ); + else if ( ch == '>' ) + fprintf( ofile, ">" ); + else + fputc( ch, ofile ); +} +void htmlSection( char section, char * title, char * context, char * picture, char * keywords, int newpage ) +{ + int sectionNumber, subSection; + if ( newpage ) { + /*if (line[1] == 'A')*/ + sectionNumber = curSection; + curSection = lookupSection( context, &subSection ); + if (curSection > 0) { + genHtmlLinks( sectionNumber, 0 ); + if (ofile) + fclose( ofile ); + sprintf( htmlFileName, "%s-%d.html", htmlName, curSection ); + ofile = fopen( htmlFileName, "w" ); + if (ofile == NULL) { + perror( htmlFileName ); + exit(1); + } + } + fprintf( ofile, "<title>%s</title>\n", title ); + genHtmlLinks( curSection, 1 ); + } + if (picture && picture[0] != '\0') + fprintf( ofile, "<img src=%s.png> ", picture ); + fprintf( ofile, "<h%d>%s</h%d>\n", + line[1]-'A'+1, title, line[1]-'A'+1 ); +} +void htmlHeader( char * line ) +{ + int sectionNumber, subSection; + if ( line[0] == '*' ) + return; + sectionNumber = lookupSection( line, &subSection ); + if (sectionNumber < 0) + return; + fprintf( ofile, "<A Name=\"%d\">\n", sectionNumber ); +} +void htmlStartDisplay( void ) +{ + fprintf( ofile, "<p>\n<pre>" ); +} +void htmlEndDisplay( void ) +{ + fprintf( ofile, "</pre>\n" ); +} +void htmlListStart( void ) +{ + fprintf( ofile, "<ul>" ); +} +void htmlListItem( void ) +{ + fprintf( ofile, "<li>" ); +} +void htmlListEnd( void ) +{ + fprintf( ofile, "</ul>\n" ); +} +dispatchTable htmlTable = { + htmlStart, + htmlFinish, + htmlNewParagraph, + htmlStartLine, + htmlBold, + htmlItalic, + htmlXref, + htmlPicture, + htmlEndLine, + htmlPutChar, + htmlSection, + htmlHeader, + htmlStartDisplay, + htmlEndDisplay, + (void*)no_op, + htmlListStart, + htmlListItem, + htmlListEnd, + (void*)no_op + }; + + +/****************************************************************************** + * + * DEFINES + * + *****************************************************************************/ +struct { + char * name; + int refCount; + int lineNum; + } defs[500]; +int defCnt = 0; + +void lookupDef( char * name, int def ) +{ + int inx; + if (!name) { + fprintf( stderr, "%d: NULL context string\n", lineNum ); + return; + } + for (inx=0;inx<defCnt;inx++) { + if (strcmp(defs[inx].name,name)==0) { + if (def) { + if (defs[inx].lineNum <= 0) + defs[inx].lineNum = lineNum; + else + fprintf( stderr, "%d: %s redefined (previous %d)\n", + lineNum, name, defs[inx].lineNum ); + } else { + defs[inx].refCount++; + } + return; + } + } + if (defCnt >= 499) { + if (defCnt == 499) { + fprintf( stderr, "%d: too many defines\n", lineNum ); + defCnt++; + } + return; + } else { + defs[defCnt].name = strdup( name ); + defs[defCnt].lineNum = (def?lineNum:-1); + defs[defCnt].refCount = 0; + defCnt++; + } +} + +void defsFinish( void ) +{ + int inx; + for ( inx=0; inx<defCnt; inx++ ) + fprintf( ofile, "%5d: %s [%d]\n", + defs[inx].lineNum, defs[inx].name, defs[inx].refCount ); + fclose(ofile); +} +void defsSection( char section, char * title, char * context, char * picture, char * keywords, int newpage ) +{ + lookupDef( context, 1 ); +} +void defsHeader( char * line ) +{ + if ( line[0] == '*' ) + return; + lookupDef( line, 1 ); +} +void defsXref( char * name, char * ref1, char * ref2 ) +{ + lookupDef( ref1, 0 ); +} + +dispatchTable defsTable = { + normalStart, + defsFinish, + (void*)no_op, + (void*)no_op, + (void*)no_op, + (void*)no_op, + defsXref, + (void*)no_op, + (void*)no_op, + (void*)no_op, + defsSection, + defsHeader, + (void*)no_op, + (void*)no_op, + (void*)no_op, + (void*)no_op, + (void*)no_op, + (void*)no_op, + (void*)no_op + }; + +/****************************************************************************** + * + * PARSE + * + *****************************************************************************/ + +char * skipChars( char * cp ) +{ + for ( ; *cp; cp++ ) { + if ( *cp != '$' ) + continue; + if ( cp[1] == '{' ) + continue; + break; + } + return cp; +} + +static int lastlineblank = 0; +void putline( char * line ) +{ + int len; + char * cp, * cq; + char * name; + char * mswhelpref; + char * xvref; + int sectionNumber; + int subSection; + + len = strlen(line); + if (len > 0 && line[len-1] == '\n') + line[--len] = '\0'; + if (len > 0 && line[len-1] == '\r') + line[--len] = '\0'; + if (len <= 0) { + if (lastlineblank) + return; + curMode->newParagraph(); + lastlineblank = 1; + return; + } else { + curMode->startLine( lastlineblank ); + lastlineblank = 0; + } + +#ifndef LATER + if (wordwrap) { + if (line[len-1] != ' ') { + line[len++] = ' '; + if (line[len-2] == '.') + line[len++] = ' '; + } + line[len] = '\0'; + } +#endif + + for ( cp=line; *cp; cp++ ) { + if (*cp == '$') { + cp++; + switch (*cp) { + case '?': + case '$': + curMode->putChar( *cp ); + break; + case '{': + curMode->putChar( '$' ); + curMode->putChar( '{' ); + break; + case 'B': + name = ++cp; + cp = skipChars( cp ); + if (*cp=='\0') + break; + *cp = '\0'; + curMode->doBold( name ); + break; + case 'I': + name = ++cp; + cp = skipChars( cp ); + if (*cp=='\0') + break; + *cp = '\0'; + curMode->doItalic( name ); + break; + case 'X': + name = ++cp; + while (*cp && *cp != '|') cp++; + if (*cp=='\0') + break; + *cp++ = '\0'; + mswhelpref = cp; + while (*cp && *cp != '|' && *cp != '$') cp++; + if (*cp=='\0') + break; + if (*cp == '|') { + *cp++ = '\0'; + xvref = cp; + while (*cp && *cp != '$') cp++; + if (*cp=='\0') + break; + for (cq=xvref; cq<cp; cq++) + if (*cq==',') + *cq = '|'; + } else + xvref = NULL; + *cp = '\0'; + curMode->doXref( name, mswhelpref, xvref ); + break; + case 'G': + name = ++cp; + while (*cp && *cp != '$') cp++; + if (*cp=='\0') + break; + *cp = '\0'; + curMode->doPicture( name, 1 ); + break; + default: + fprintf( stderr, "%d Invalid $ command - %c\n", lineNum, *cp ); + break; + } + } else { + if (*cp != '\014') + curMode->putChar( *cp ); + } + } + curMode->endLine(); +} + + +char * conds[100]; +char **condPtr = conds; + +void addCond( char * name ) +{ + *condPtr++ = name; +} +int lookupCond( char * name ) +{ + char ** p; + int ret = 1; + if (strlen(name) == 0) + return 1; + if (*name == '!') { + ret = 0; + name++; + } + for (p=conds; p<condPtr; p++) { + if (strcmp( *p, name )==0) + return ret; + } + return !ret; +} + +void process( FILE * f ) +{ + char key; + char * title; + char * context; + char * fileName; + char * keywords; + char * cp; + char tmp[1024]; + int indent; + FILE * newFile; + int lineNum0; + int threadCnt; + int sectionNumber; + int subSection; + int valid; + int sectionNewPage; + int noSectionNewPage; + + lineNum0 = lineNum; + lineNum = 0; + while (fgets( line, sizeof line, f ) != NULL) { + lineNum++; + line[strlen(line)-1] = '\0'; + if (line[0] == '?' && line[1] == '?') { + cp = line+2; + while (isblank(*cp)) cp++; + if ( strcmp(cp, "else") == 0 ) + valid = !valid; + else + valid = lookupCond( cp ); + continue; + } + if (!valid) { + continue; + } + if (line[0] == '\014') + continue; + if (line[0] != '?') { + putline( line ); + continue; + } + sectionNewPage = 1; + switch (line[1]) { + case '#': + break; + case '+': + newFile = openFile( line+2 ); + process( newFile ); + fclose( newFile ); + break; + case 'a': case 'b': case 'c': + line[1] += 'A'-'a'; + sectionNewPage = 0; + case 'A': case 'B': case 'C': + if ( noSectionNewPage ) { + sectionNewPage = 0; + noSectionNewPage = 0; + } + context = fileName = keywords = NULL; + title = cp = line+2; + while (*cp && *cp != '|') cp++; + if (*cp) { + *cp++ = '\0'; + if (*cp!='|') + context = cp; + } + while (*cp && *cp != '|') cp++; + if (*cp) { + *cp++ = '\0'; + if (*cp!='|') + fileName = cp; + } + while (*cp && *cp != '|') cp++; + if (*cp) { + *cp++ = '\0'; + if (*cp!='|') + keywords = cp; + } + curMode->doSection( line[1], title, context, fileName, keywords, sectionNewPage ); + lastlineblank = 0; + break; + case 'H': + curMode->doHeader( line+2 ); + break; + case 'W': + if (line[2] == '+') { + curMode->doEndDisplay(); + wordwrap = 1; + } else if (line[2] == '-') { + curMode->doStartDisplay(); + wordwrap = 0; + } else { + fprintf( stderr, "%d: Bad ?W command\n", lineNum); + exit(1); + } + lastlineblank = 0; + break; + case 'G': + curMode->doPicture( line+2, 0 ); + lastlineblank = 0; + break; + case 'T': + curMode->doThread( line+2 ); + break; + case 'L': + switch (line[2]) { + case 'S': + listLevel++; + listCount[listLevel] = 0; + switch (line[3]) { + case 'o': + listType[listLevel] = LISTBULLET; + break; + case '-': + listType[listLevel] = LISTDASH; + break; + case '1': + listType[listLevel] = LISTNUMBER; + break; + default: + listType[listLevel] = LISTNONE; + } + curMode->doListStart(); + break; + case 'I': + if (listLevel<0) { + fprintf( stderr, "%d: ?LI not in list\n", lineNum ); + break; + } + listCount[listLevel]++; + curMode->doListItem(); + break; + case 'E': + listLevel--; + curMode->doListEnd(); + break; + } + lastlineblank = 0; + break; + case 'P': + curMode->page(); + lastlineblank = 0; + break; + case 'Q': + noSectionNewPage = 1; + break; + default: + fprintf( stderr, "%d: Invalid ? command: %c\n", lineNum, line[1] ); + } + } + lineNum = lineNum0; +} + + +/****************************************************************************** + * + * MAIN + * + *****************************************************************************/ + +int main ( int argc, char * argv[] ) +{ + int inx; + + curMode = NULL; + argv++; argc--; + while ( argc > 1 && argv[0][0] == '-' ) { + if ( strcmp( argv[0], "-xv" ) == 0 ) { + curMode = &xviewTable; + addCond( "xv" ); + } else if ( strcmp( argv[0], "-mswhelp" ) == 0 ) { + curMode = &mswhelpTable; + addCond( "mswhelp" ); + } else if ( strcmp( argv[0], "-mswword" ) == 0 ) { + curMode = &mswwordTable; + addCond( "mswword" ); + } else if ( strcmp( argv[0], "-html" ) == 0 ) { + curMode = &htmlTable; + addCond( "html" ); + } else if ( strcmp( argv[0], "-def" ) == 0 ) { + curMode = &defsTable; + addCond( "def" ); + } else if ( strcmp( argv[0], "-text" ) == 0 ) { + curMode = &textTable; + addCond( "text" ); + } else if ( strncmp( argv[0], "-C", 2 ) == 0 ) { + argv++; argc--; + addCond( argv[0] ); + } else if ( strncmp( argv[0], "-v", 2 ) == 0 ) { + verbose = 1; + } else if ( strncmp( argv[0], "-d", 2 ) == 0 ) { + argv++; argc--; + *dirList++ = argv[0]; + } else if ( strncmp( argv[0], "-width", 2 ) == 0 ) { + argv++; argc--; + listWidth = lineWidth = atoi(argv[0]); + if (lineWidth < 10) { + fprintf( stderr, "Invalid linewidth %s\n", argv[0] ); + exit(1); + } + } else if ( strncmp( argv[0], "-mt", 3 ) == 0 ) { + argv++; argc--; + MarginTop = atof( *argv ); + } else if ( strncmp( argv[0], "-mb", 3 ) == 0 ) { + argv++; argc--; + MarginBottom = atof( *argv ); + } else if ( strncmp( argv[0], "-mr", 3 ) == 0 ) { + argv++; argc--; + MarginRight = atof( *argv ); + } else if ( strncmp( argv[0], "-ml", 3 ) == 0 ) { + argv++; argc--; + MarginLeft = atof( *argv ); + } else if ( strncmp( argv[0], "-mg", 3 ) == 0 ) { + argv++; argc--; + MarginGutter = atof( *argv ); + } else if ( strncmp( argv[0], "-toc", 4 ) == 0 ) { + toc++; + } else { + fprintf( stderr, "unrecognized option: %s\n", argv[0] ); + exit( 1 ); + } + argv++;argc--; + } + + if (curMode == NULL) { + fprintf( stderr, "Must spec either -mswhelp or -xv\n" ); + exit(1); + } + if ( argc != 2 ) { + fprintf( stderr, "Usage: prochelp [-mswhelp|-xv] <INF> <OUTF>\n" ); + exit( 1 ); + } + + curMode->start( argv[0], argv[1] ); + process( ifile ); + fclose( ifile ); + curMode->finish(); + + exit(0); +} |