/* 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
#include
#include
#include
#if defined (__sun) && defined (__SVR4)
#include
#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= 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=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=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=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=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; hsection = 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; indent0?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= 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
" );
fprintf( ofile, "Return to Contents",
htmlName );
comma = 1;
}
getLinks( sectionNumber, &prev, &next );
if (prev > 0) {
if (comma)
fprintf( ofile, ", " );
else
if (!begin) fprintf( ofile, "\n
" );
fprintf( ofile, "Previous Page",
htmlName, prev );
comma = 1;
}
if (next > 0) {
if (comma)
fprintf( ofile, ", " );
else
if (!begin) fprintf( ofile, "\n
" );
fprintf( ofile, "Next Page",
htmlName, next );
comma = 1;
}
if (comma)
if (begin)
fprintf( ofile, "
\n" );
else
fprintf( ofile, "\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, "" );
else
fprintf( ofile, "
" );
} else {
fprintf( ofile, "\n" );
}
}
void htmlStartLine( int lastBlank )
{
if (wordwrap)
fprintf( ofile, "\n" );
else
fprintf( ofile, "\t" );
}
void htmlBold( char * name )
{
fprintf( ofile, "%s", name );
}
void htmlItalic( char * name )
{
fprintf( ofile, "%s", name );
}
void htmlXref( char * name, char * ref1, char * ref2 )
{
int sectionNumber, subSection;
sectionNumber = lookupSection( ref1, &subSection );
if (sectionNumber < 0)
return;
fprintf( ofile, "%s", name );
}
void htmlPicture( char * name, int inLine )
{
fprintf( ofile, "", name );
if (inLine)
fprintf( ofile, "\t" );
else
fprintf( ofile, "
\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, "%s\n", title );
genHtmlLinks( curSection, 1 );
}
if (picture && picture[0] != '\0')
fprintf( ofile, " ", picture );
fprintf( ofile, "%s\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, "\n", sectionNumber );
}
void htmlStartDisplay( void )
{
fprintf( ofile, "\n
" );
}
void htmlEndDisplay( void )
{
fprintf( ofile, "
\n" );
}
void htmlListStart( void )
{
fprintf( ofile, "" );
}
void htmlListItem( void )
{
fprintf( ofile, "- " );
}
void htmlListEnd( void )
{
fprintf( ofile, "
\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= 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 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; cqdoXref( 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; pdoSection( 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] \n" );
exit( 1 );
}
curMode->start( argv[0], argv[1] );
process( ifile );
fclose( ifile );
curMode->finish();
exit(0);
}