home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
OS/2 Shareware BBS: 5 Edit
/
05-Edit.zip
/
rconv112.zip
/
richconv
/
richconv.c
< prev
next >
Wrap
C/C++ Source or Header
|
1998-10-17
|
42KB
|
1,429 lines
/* richconv.c,v 1.12 1998-10-14 23:24:10-04 rl Exp */
/*************************************************************************
* *
* richconv.c *
* Convert text/enriched (RFC 1896) MIME emails *
* 1998-01-10, Rolf Lochbuehler *
* *
*************************************************************************/
/*
Assumptions:
(1) The original email file is of text/enriched type.
(2) The original email file has a header line saying "Content-Type: text/enriched"
(3) The original email file may be PGP signed.
(3) As specified in RFC-822, a null line marks the end of the email header.
*/
#include <ctype.h>
#include <math.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <sys/stat.h>
#include <sys/types.h>
#define AUTHOR "Rolf Lochbuehler"
#define AUTHOR_HTML "Rolf Lochbühler"
#define EMAIL "rolf@together.net"
#define PROGRAM "RichConv"
#define VERSION "1.12"
#define RET_OK 0
#define RET_HELP 1
#define RET_ARGUMENT 2
#define RET_FILE_NAME 3
#define RET_FILE_SIZE 4
#define NO 0
#define YES 1
#define OFF 0
#define ON 1
#define EQUAL 0
/* multipart/alternative */
/* Max 70 characters: .........1.........2.........3.........4.........5.........6.........7 */
#define BOUNDARY_STR "richconv_vnochcir_richconv_vnochcir_richconv_vnochcir_richconv_vnochci"
/* text/enriched */
#define BOLD_START "bold"
#define BOLD_END "/bold"
#define BIGGER_START "bigger"
#define BIGGER_END "/bigger"
#define CENTER_START "center"
#define CENTER_END "/center"
#define COLOR_START "color"
#define COLOR_END "/color"
#define EXCERPT_START "excerpt"
#define EXCERPT_END "/excerpt"
#define FIXED_START "fixed"
#define FIXED_END "/fixed"
#define FLUSHBOTH_START "flushboth"
#define FLUSHBOTH_END "/flushboth"
#define FLUSHLEFT_START "flushleft"
#define FLUSHLEFT_END "/flushleft"
#define FLUSHRIGHT_START "flushright"
#define FLUSHRIGHT_END "/flushright"
#define FONTFAMILY_START "fontfamily"
#define FONTFAMILY_END "/fontfamily"
#define ITALIC_START "italic"
#define ITALIC_END "/italic"
#define LANG_START "lang"
#define LANG_END "/lang"
#define NOFILL_START "nofill"
#define NOFILL_END "/nofill"
#define PARAINDENT_START "paraindent"
#define PARAINDENT_END "/paraindent"
#define PARAM_START "param"
#define PARAM_END "/param"
#define SMALLER_START "smaller"
#define SMALLER_END "/smaller"
#define UNDERLINE_START "underline"
#define UNDERLINE_END "/underline"
/* MIME */
#define CONTENT_TYPE "Content-Type:"
#define SUBJECT "Subject:"
/* text/html */
#define FONTSIZE_MAX 7
#define FONTSIZE_MIN 1
#define FONTSIZE_DEFAULT 3
/* Functions */
char* convcolor ( char* richcolor, char* htmlcolor );
void help ( void );
void html ( FILE* file, char* start, char* end );
void header ( FILE* file, char* start, char* end, char* boundarystr );
char* itox ( int n, char* hex );
void multipart ( FILE* file, char* start, char* end, int nohtml, int simple );
void enriched ( FILE* file, char* start, char* end );
void plain ( FILE* file, char* start, char* end, int simple );
void changefont ( FILE* file, int size, char* color, int bold, int italic, int underline, int teletype );
int xtoi ( char* hex );
/*************************************************************************
* *
* main() *
* Parse command line options and open/read/write/close files *
* *
*************************************************************************/
int main ( int argc, char** argv )
{
int c;
FILE *file;
char filename[FILENAME_MAX];
int filesize;
struct stat filebuf;
char* start;
char* end;
char* p;
int nohtml = NO;
int i;
int maxsize;
int sizelimit = NO;
int simple = NO;
if( (argc <= 1) || (7 <= argc) )
{
help();
return( RET_ARGUMENT );
}
for( i = 1; i < argc; i += 1 )
{
if( (EQUAL == stricmp(argv[i],"/h")) || (EQUAL == stricmp(argv[i],"-h")) )
{
help();
return( RET_HELP );
}
if( (EQUAL == stricmp(argv[i],"/nohtml")) || (EQUAL == stricmp(argv[i],"-nohtml")) )
nohtml = YES;
else if( (EQUAL == stricmp(argv[i],"/max")) || (EQUAL == stricmp(argv[i],"-max")) )
{
sizelimit = YES;
maxsize = atoi( argv[++i] );
if( maxsize <= 0 )
{
help();
return( RET_FILE_SIZE );
}
}
else if( (EQUAL == stricmp(argv[i],"/simple")) || (EQUAL == stricmp(argv[i],"-simple")) )
simple = YES;
else
strcpy( filename, argv[i] );
}
/* Open input file */
file = fopen( filename, "r" );
if( NULL == file )
return RET_FILE_NAME;
/* Get size of file */
fstat( fileno(file), &filebuf );
filesize = filebuf.st_size;
if( (YES == sizelimit) && (filesize > maxsize) )
{
fclose( file );
return RET_FILE_SIZE;
}
/* Allocate memory */
start = (char*) _alloca( filesize );
/* Read input file */
p = start;
while( (c = fgetc(file)) != EOF )
{
*p = (char) c;
p += 1;
}
end = p - 1;
/* Erase contents of input file */
fclose( file );
remove( filename );
file = fopen( filename, "w" );
/* Write back converted input file */
multipart( file, start, end, nohtml, simple );
/* Close input file */
fclose( file );
/* Don't need to free memory, used _alloca() */
return RET_OK;
}
/*************************************************************************
* *
* help() *
* Print help info for user *
* *
*************************************************************************/
void help ( void )
{
puts(
"\n"
PROGRAM" "VERSION", "AUTHOR" <"EMAIL">\n"
"Purpose:\n"
" Converts a text/enriched (RFC 1896) email to a multipart/alternative\n"
" (RFC 1341) email that additionally has a text/plain version of the\n"
" original text/enriched part. PMMail will display the text/plain part\n"
" of the multipart/alternative email. Additionally, a text/html version\n"
" is generated as part of the multipart/alternative email by default.\n"
"Usage:\n"
" "PROGRAM" [/h] [/nohtml] [/max N] [/simple] [File]\n"
"Arguments:\n"
" (none) Display this help info, then exit\n"
" /h, -h Display this help info, then exit\n"
" /nohtml, -nohtml Don't generate text/html part\n"
" /max N, -max N Don't convert files larger than N byte (default: no limit)\n"
" Note: space is required between /max and N\n"
" /simple, -simple Simple text/plain (default: emphasized text to uppercase)\n"
" File The email file to be converted\n"
"Note:\n"
" The input file will be substituted by the converted file, but the\n"
" original email will not be altered and will become the last part\n"
" of the multipart/alternative email."
);
return;
}
/*************************************************************************
* *
* multipart() *
* Convert email to multipart/alternative *
* *
*************************************************************************/
void multipart ( FILE* file, char* start, char* end, int nohtml, int simple )
{
char* p;
header( file, start, end, BOUNDARY_STR );
fputs( "\n--"BOUNDARY_STR"\n", file );
plain( file, start, end, simple );
fputs( "\n--"BOUNDARY_STR"\n", file );
if( NO == nohtml )
{
html( file, start, end );
fputs( "\n--"BOUNDARY_STR"\n", file );
}
enriched( file, start, end );
fputs( "\n--"BOUNDARY_STR"--\n", file );
return;
}
/*************************************************************************
* *
* header() *
* Write top level header of multipart/alternative email *
* *
*************************************************************************/
void header ( FILE* file, char* start, char* end, char* boundarystr )
{
char* p;
int strobe;
strobe = ON;
p = start;
while( ('\n' != *p) || ('\n' != *(p+1)) )
{
/* Ignore subject line */
if( ('s' == tolower(*p)) && (EQUAL == strnicmp(SUBJECT,p,strlen(SUBJECT))) )
strobe = OFF;
if( (OFF == strobe) && ('\n' == *p) )
strobe = ON;
/* Change content type */
if( (ON == strobe) && ('c' == tolower(*p)) && (EQUAL == strnicmp(CONTENT_TYPE,p,strlen(CONTENT_TYPE))) )
{
fputs( CONTENT_TYPE" multipart/alternative; boundary=", file );
fputs( boundarystr, file );
while( (';' != *p) && ('\n' != *p) )
p += 1;
continue;
}
else
fputc( *p, file );
p += 1;
}
fputs( "\nX-Filtered: Converted from text/enriched to multipart/alternative by "PROGRAM" ("VERSION", "AUTHOR" <"EMAIL">)\n", file );
fputc( '\n', file );
return;
}
/*************************************************************************
* *
* enriched() *
* Write original email file content as text/enriched part of *
* multipart/alternative email *
* *
*************************************************************************/
void enriched ( FILE* file, char* start, char* end )
{
char* p;
p = start;
while( p <= end )
{
fputc( *p, file );
p += 1;
}
return;
}
/*************************************************************************
* *
* plain() *
* Write text/plain part of multipart/alternative email *
* *
*************************************************************************/
void plain ( FILE* file, char* start, char* end, int simple )
{
char* p; /* Memory pointer */
int italic = 0; /* Level of <italic>...</italic> */
int bold = 0; /* Level of <bold>...</bold> */
int underline = 0; /* Level of <underline>...</underline> */
int excerpt = 0; /* Level of <excerpt>...</excerpt> */
int param = 0; /* Level of <param>...</param> */
int nofill = 0; /* Level of <nofill>...</nofill> */
int strobe = ON;
int linebreak = 0; /* Number of linebreaks */
int i; /* All purpose index variable */
p = start;
/* Header */
while( ('\n' != *p) || ('\n' != *(p+1)) )
{
/* Ignore subject line */
if( ('s' == tolower(*p)) && (EQUAL == strnicmp(SUBJECT,p,strlen(SUBJECT))) )
strobe = OFF;
if( (OFF == strobe) && ('\n' == *p) )
strobe = ON;
/* Change content type */
if( (ON == strobe) && ('c' == tolower(*p)) && (EQUAL == strnicmp(CONTENT_TYPE,p,strlen(CONTENT_TYPE))) )
{
fputs( CONTENT_TYPE" text/plain", file );
while( (';' != *p) && ('\n' != *p) )
p += 1;
continue;
}
else
fputc( *p, file );
p += 1;
}
fputs( "\n\n", file );
/* Go to the '\n' at the end of the empty line that marks the end of the header */
p += 1;
/* Body */
while( ++p <= end )
{
/* Line breaks */
if( nofill <= 0 )
{
if( '\n' == *p )
{
if( (p < end) && ('\n' == *(p+1)) )
{
/* Substitute N linebreaks by N-1 linebreaks */
while( (p < end) && ('\n' == *(p+1)) )
{
fputc( '\n', file );
p += 1;
}
continue;
}
else
{
if( 0 == linebreak )
/* Substitute a single linebreak by a single space character */
fputc( ' ', file );
else
{
/* Some formatting commands force a linebreak */
fputc( '\n', file );
linebreak = 0;
}
continue;
}
}
else if( linebreak > 0 )
{
fputc( '\n', file );
linebreak = 0;
/* No 'continue' here, since *p != '\n' */
}
} /* end if */
/* Formatting commands */
if( '<' == *p )
{
if( '<' == *(p+1) )
{
fputc( '<', file );
p += 1;
continue;
}
else if( EQUAL == strnicmp(p+1,BOLD_START,strlen(BOLD_START)) )
{
bold += 1;
p += 1 + strlen(BOLD_START);
continue;
}
else if( EQUAL == strnicmp(p+1,BOLD_END,strlen(BOLD_END)) )
{
bold -= 1;
p += 1 + strlen(BOLD_END);
continue;
}
else if( EQUAL == strnicmp(p+1,CENTER_START,strlen(CENTER_START)) )
{
p += 1 + strlen(CENTER_START);
if( ('\n' != *(p-1)) && ('\n' != *(p+2+strlen(CENTER_START))) )
linebreak += 1;
continue;
}
else if( EQUAL == strnicmp(p+1,CENTER_END,strlen(CENTER_END)) )
{
p += 1 + strlen(CENTER_END);
if( ('\n' != *(p-1)) && ('\n' != *(p+2+strlen(CENTER_END))) )
linebreak += 1;
continue;
}
else if( EQUAL == strnicmp(p+1,EXCERPT_START,strlen(EXCERPT_START)) )
{
excerpt += 1;
p += 1 + strlen(EXCERPT_START);
fputs( "\n\n\"...", file );
continue;
}
else if( EQUAL == strnicmp(p+1,EXCERPT_END,strlen(EXCERPT_END)) )
{
excerpt -= 1;
p += 1 + strlen(EXCERPT_END);
fputs( "...\"\n\n", file );
continue;
}
else if( EQUAL == strnicmp(p+1,FLUSHBOTH_START,strlen(FLUSHBOTH_START)) )
{
p += 1 + strlen(FLUSHBOTH_START);
if( ('\n' != *(p-1)) && ('\n' != *(p+2+strlen(FLUSHBOTH_START))) )
linebreak += 1;
continue;
}
else if( EQUAL == strnicmp(p+1,FLUSHBOTH_END,strlen(FLUSHBOTH_END)) )
{
p += 1 + strlen(FLUSHBOTH_END);
if( ('\n' != *(p-1)) && ('\n' != *(p+2+strlen(FLUSHBOTH_END))) )
linebreak += 1;
continue;
}
else if( EQUAL == strnicmp(p+1,FLUSHLEFT_START,strlen(FLUSHLEFT_START)) )
{
p += 1 + strlen(FLUSHLEFT_START);
if( ('\n' != *(p-1)) && ('\n' != *(p+2+strlen(FLUSHLEFT_START))) )
linebreak += 1;
continue;
}
else if( EQUAL == strnicmp(p+1,FLUSHLEFT_END,strlen(FLUSHLEFT_END)) )
{
p += 1 + strlen(FLUSHLEFT_END);
if( ('\n' != *(p-1)) && ('\n' != *(p+2+strlen(FLUSHLEFT_END))) )
linebreak += 1;
continue;
}
else if( EQUAL == strnicmp(p+1,FLUSHRIGHT_START,strlen(FLUSHRIGHT_START)) )
{
p += 1 + strlen(FLUSHRIGHT_START);
if( ('\n' != *(p-1)) && ('\n' != *(p+2+strlen(FLUSHRIGHT_START))) )
linebreak += 1;
continue;
}
else if( EQUAL == strnicmp(p+1,FLUSHRIGHT_END,strlen(FLUSHRIGHT_END)) )
{
p += 1 + strlen(FLUSHRIGHT_END);
if( ('\n' != *(p-1)) && ('\n' != *(p+2+strlen(FLUSHRIGHT_END))) )
linebreak += 1;
continue;
}
else if( EQUAL == strnicmp(p+1,ITALIC_START,strlen(ITALIC_START)) )
{
italic += 1;
p += 1 + strlen(ITALIC_START);
continue;
}
else if( EQUAL == strnicmp(p+1,ITALIC_END,strlen(ITALIC_END)) )
{
italic -= 1;
p += 1 + strlen(ITALIC_END);
continue;
}
else if( EQUAL == strnicmp(p+1,NOFILL_START,strlen(NOFILL_START)) )
{
nofill += 1;
p += 1 + strlen(NOFILL_START);
continue;
}
else if( EQUAL == strnicmp(p+1,NOFILL_END,strlen(NOFILL_END)) )
{
nofill -= 1;
p += 1 + strlen(NOFILL_END);
continue;
}
else if( EQUAL == strnicmp(p+1,PARAM_START,strlen(PARAM_START)) )
{
param += 1;
p += 1 + strlen(PARAM_START);
continue;
}
else if( EQUAL == strnicmp(p+1,PARAM_END,strlen(PARAM_END)) )
{
param -= 1;
p += 1 + strlen(PARAM_END);
continue;
}
else if( EQUAL == strnicmp(p+1,UNDERLINE_START,strlen(UNDERLINE_START)) )
{
underline += 1;
p += 1 + strlen(UNDERLINE_START);
continue;
}
else if( EQUAL == strnicmp(p+1,UNDERLINE_END,strlen(UNDERLINE_END)) )
{
underline -= 1;
p += 1 + strlen(UNDERLINE_END);
continue;
}
/* Ignore other commands */
else
{
while( '>' != *p )
p += 1;
continue;
}
} /* end if */
/* Ignore param sections */
if( param > 0 )
continue;
/* Convert italic, bold, or underlined text to uppercase */
if( (YES != simple) && ((italic > 0) || (bold > 0) || (underline > 0)) )
fputc( toupper(*p), file );
else
fputc( *p, file );
} /* end while */
return;
}
/*************************************************************************
* *
* html() *
* Write text/html part of multipart/alternative email *
* *
*************************************************************************/
void html ( FILE* file, char* start, char* end )
{
char* p = NULL; /* Pointer to text/enriched email in memory */
char* s = NULL; /* Auxiliary variable to set subjectend */
char* subjectstart = NULL; /* Pointer to first character of Subject string */
char* subjectend = NULL; /* Pointer to last character of Subject string */
int nofill = 0; /* Character *p is inside of <nofill>...</nofill> */
int param = 0; /* Character *p is inside of <param>...</param> */
int strobe = ON;
int fontsize = 3; /* Value for <FONT SIZE="..."> */
char fontcolor[7] = "000000"; /* Value for <FONT COLOR="#...">, format: rrggbb */
char richcolor[15] = ""; /* Text color in text/enriched format: color name or rrrr,gggg,bbbb */
int bigger = 0; /* Level of <bigger>...</bigger> */
int smaller = 0; /* Level of <smaller>...</smaller> */
int pre = 0; /* Level of <PRE>...</PRE> */
int prefont = NO; /* YES, if font change inside of <PRE>...</PRE> */
int i; /* All purpose index variable */
int bold = 0; /* Level of <bold>...</bold> */
int italic = 0; /* Level of <italic>...</italic> */
int underline = 0; /* Level of <underline>...</underline> */
int teletype = 0; /* Level of <TT>..</TT> */
int linebreak = 0; /* Minimum number of linebreaks */
/* Header */
p = start;
while( ('\n' != *p) || ('\n' != *(p+1)) )
{
/* Ignore subject line, but store subject for <TITLE> */
if( (ON == strobe) && ('s' == tolower(*p)) && (EQUAL == strnicmp(SUBJECT,p,strlen(SUBJECT))) )
{
/* Go to start of subject */
subjectstart = p + strlen(SUBJECT);
/* Strip spaces from start of subject */
while( (' ' == *subjectstart) && ('\n' != *subjectstart) )
subjectstart += 1;
/* Go to end of subject */
s = subjectstart;
while( '\n' != *s )
s += 1;
/* Strip spaces from end of subject */
while( ' ' == *(s-1) )
s -= 1;
subjectend = s - 1;
/* If empty subject, now subjectend < subjectstart */
strobe = OFF;
}
if( (OFF == strobe) && (p == subjectend) )
strobe = ON;
/* Change content type */
if( (ON == strobe) && ('c' == tolower(*p)) && (EQUAL == strnicmp(CONTENT_TYPE,p,strlen(CONTENT_TYPE))) )
{
fputs( CONTENT_TYPE" text/html", file );
while( (';' != *p) && ('\n' != *p) )
p += 1;
continue;
}
else
fputc( *p, file );
p += 1;
}
fputs( "\n\n", file );
p += 1;
/* Body */
fputs( "<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.0//EN\" \"http://www.w3.org/TR/PR-html40/strict.dtd\">\n", file );
fputs( "<!-- Converted from text/enriched to text/html by "PROGRAM" ("VERSION", "AUTHOR_HTML", "EMAIL") -->\n", file );
fputs( "<HTML>\n<HEAD>\n<TITLE>", file );
for( s = subjectstart; s <= subjectend; s += 1 )
fputc( *s, file );
fputs( "</TITLE>\n</HEAD>\n<BODY>\n<FONT SIZE=\"3\" COLOR=\"#000000\">\n<P>", file );
while( ++p <= end )
{
/* Line breaks */
if( nofill < 1 )
{
if( '\n' == *p )
{
/* Last character in email body is '\n' */
if( p == end )
{
fputs( "</P>\n", file );
continue;
}
/* Several '\n's in a row */
else if( ((p+1) <= end) && ('\n' == *(p+1)) )
{
/* Two '\n's in a row */
if( (((p+2) <= end) && ('\n' != *(p+2))) || ((p+1) == end) )
{
/* Two '\n's in a row */
fputs( "<BR>\n", file );
p += 1;
continue;
}
/* More than two '\n's in a row */
else
{
fputs( "</P>\n<P>", file );
while( (p < end) && ('\n' == *(p+1)) )
p += 1;
continue;
}
}
/* Single '\n' and no formatting command that forces a linebreak */
else if( 0 == linebreak )
{
fputc( ' ', file );
continue;
}
/* Single '\n' before or after a formatting command that forces a linebreak */
else
{
fputs( "<BR>", file );
linebreak = 0;
continue;
}
} /* end if */
/* No '\n' but a formatting command that forces a linebreak */
else if( linebreak > 0 )
{
fputs( "<BR>", file );
linebreak = 0;
/* No 'continue' here, since *p != '\n' */
}
} /* end if */
/* Formatting commands */
if( '<' == *p )
{
if( '<' == *(p+1) )
{
fputs( "<", file );
p += 1;
continue;
}
else if( EQUAL == strnicmp(p+1,BIGGER_START,strlen(BIGGER_START)) )
{
prefont = (pre > 0);
/* Ignore font changes inside of <PRE>...</PRE> */
if( NO == prefont )
{
bigger += 1;
fontsize = min( FONTSIZE_MAX, FONTSIZE_DEFAULT + bigger - smaller );
changefont( file, fontsize, fontcolor, bold, italic, underline, teletype );
}
p += 1 + strlen(BIGGER_START);
continue;
}
else if( EQUAL == strnicmp(p+1,BIGGER_END,strlen(BIGGER_END)) )
{
prefont = (pre > 0);
/* Ignore font changes inside of <PRE>...</PRE> */
if( NO == prefont )
{
bigger -= 1;
fontsize = FONTSIZE_DEFAULT + max( 0, bigger - smaller );
changefont( file, fontsize, fontcolor, bold, italic, underline, teletype );
}
p += 1 + strlen(BIGGER_END);
continue;
}
else if( EQUAL == strnicmp(p+1,BOLD_START,strlen(BOLD_START)) )
{
prefont = (pre > 0);
/* Ignore font changes inside of <PRE>...</PRE> */
if( NO == prefont )
{
bold += 1;
fputs( "<B>", file );
}
p += 1 + strlen(BOLD_START);
continue;
}
else if( EQUAL == strnicmp(p+1,BOLD_END,strlen(BOLD_END)) )
{
prefont = (pre > 0);
/* Ignore font changes inside of <PRE>...</PRE> */
if( NO == prefont )
{
bold -= 1;
fputs( "</B>", file );
}
p += 1 + strlen(BOLD_END);
continue;
}
else if( EQUAL == strnicmp(p+1,CENTER_START,strlen(CENTER_START)) )
{
/* <CENTER> will cause a line break in text/html automatically */
fputs( "<CENTER>", file );
p += 1 + strlen(CENTER_START);
continue;
}
else if( EQUAL == strnicmp(p+1,CENTER_END,strlen(CENTER_END)) )
{
/* </CENTER> will cause a line break in text/html automatically */
fputs( "</CENTER>", file );
p += 1 + strlen(CENTER_END);
continue;
}
else if( EQUAL == strnicmp(p+1,COLOR_START,strlen(COLOR_START)) )
{
/* Skip <color> */
p += 1 + strlen(COLOR_START);
/* Skip <param> */
while( '<' != *p )
p += 1;
p += strlen(PARAM_START) + 2;
i = 0;
/* Read color code and convert to text/html format */
while( '<' != *p )
{
/* Ignore spaces */
if( ' ' == *p )
{
p += 1;
continue;
}
/* Read digits and commas */
richcolor[i] = *p;
i += 1;
p += 1;
}
richcolor[i] = '\0';
/* Ignore font changes inside of <PRE>...</PRE> */
prefont = (pre > 0);
if( NO == prefont )
convcolor( richcolor, fontcolor );
/* Skip </param> */
p += 1 + strlen(PARAM_END);
/* Change font settings, but ignore font changes inside of <PRE>...</PRE> */
if( NO == prefont )
changefont( file, fontsize, fontcolor, bold, italic, underline, teletype );
continue;
}
else if( EQUAL == strnicmp(p+1,COLOR_END,strlen(COLOR_END)) )
{
strcpy( fontcolor, "000000" ); /* To be done: Should be reset to previous color, not to default */
prefont = (pre > 0);
/* Change font settings, if not inside of <PRE>...</PRE> */
if( NO == prefont )
changefont( file, fontsize, fontcolor, bold, italic, underline, teletype );
p += 1 + strlen(COLOR_END);
continue;
}
else if( EQUAL == strnicmp(p+1,EXCERPT_START,strlen(EXCERPT_START)) )
{
fputs( "<BLOCKQUOTE>", file );
p += 1 + strlen(EXCERPT_START);
continue;
}
else if( EQUAL == strnicmp(p+1,EXCERPT_END,strlen(EXCERPT_END)) )
{
fputs( "</BLOCKQUOTE>", file );
p += 1 + strlen(EXCERPT_END);
continue;
}
else if( EQUAL == strnicmp(p+1,FIXED_START,strlen(FIXED_START)) )
{
prefont = (pre > 0);
/* Ignore font changes inside of <PRE>...</PRE> */
if( NO == prefont )
{
teletype += 1;
fputs( "<TT>", file );
}
p += 1 + strlen(FIXED_START);
continue;
}
else if( EQUAL == strnicmp(p+1,FIXED_END,strlen(FIXED_END)) )
{
prefont = (pre > 0);
/* Ignore font changes inside of <PRE>...</PRE> */
if( NO == prefont )
{
teletype -= 1;
fputs( "</TT>", file );
}
p += 1 + strlen(FIXED_END);
continue;
}
else if( EQUAL == strnicmp(p+1,FLUSHBOTH_START,strlen(FLUSHBOTH_START)) )
{
p += 1 + strlen(FLUSHBOTH_START);
if( ('\n' != *(p-1)) && ('\n' != *(p+2+strlen(FLUSHBOTH_START))) )
linebreak += 1;
continue;
}
else if( EQUAL == strnicmp(p+1,FLUSHBOTH_END,strlen(FLUSHBOTH_END)) )
{
p += 1 + strlen(FLUSHBOTH_END);
if( ('\n' != *(p-1)) && ('\n' != *(p+2+strlen(FLUSHBOTH_END))) )
linebreak += 1;
continue;
}
else if( EQUAL == strnicmp(p+1,FLUSHLEFT_START,strlen(FLUSHLEFT_START)) )
{
p += 1 + strlen(FLUSHLEFT_START);
if( ('\n' != *(p-1)) && ('\n' != *(p+2+strlen(FLUSHLEFT_START))) )
linebreak += 1;
continue;
}
else if( EQUAL == strnicmp(p+1,FLUSHLEFT_END,strlen(FLUSHLEFT_END)) )
{
p += 1 + strlen(FLUSHLEFT_END);
if( ('\n' != *(p-1)) && ('\n' != *(p+2+strlen(FLUSHLEFT_END))) )
linebreak += 1;
continue;
}
else if( EQUAL == strnicmp(p+1,FLUSHRIGHT_START,strlen(FLUSHRIGHT_START)) )
{
p += 1 + strlen(FLUSHRIGHT_START);
if( ('\n' != *(p-1)) && ('\n' != *(p+2+strlen(FLUSHRIGHT_START))) )
linebreak += 1;
continue;
}
else if( EQUAL == strnicmp(p+1,FLUSHRIGHT_END,strlen(FLUSHRIGHT_END)) )
{
p += 1 + strlen(FLUSHRIGHT_END);
if( ('\n' != *(p-1)) && ('\n' != *(p+2+strlen(FLUSHRIGHT_END))) )
linebreak += 1;
continue;
}
else if( EQUAL == strnicmp(p+1,ITALIC_START,strlen(ITALIC_START)) )
{
prefont = (pre > 0);
/* Ignore font changes inside of <PRE>...</PRE> */
if( NO == prefont )
{
italic += 1;
fputs( "<I>", file );
}
p += 1 + strlen(ITALIC_START);
continue;
}
else if( EQUAL == strnicmp(p+1,ITALIC_END,strlen(ITALIC_END)) )
{
prefont = (pre > 0);
/* Ignore font changes inside of <PRE>...</PRE> */
if( NO == prefont )
{
italic -= 1;
fputs( "</I>", file );
}
p += 1 + strlen(ITALIC_END);
continue;
}
else if( EQUAL == strnicmp(p+1,NOFILL_START,strlen(NOFILL_START)) )
{
nofill += 1;
/* Write a <PRE> only for the first <nofill> */
if( 1 == nofill )
{
pre += 1;
fputs( "\n<PRE>", file );
}
p += 1 + strlen(NOFILL_START);
continue;
}
else if( EQUAL == strnicmp(p+1,NOFILL_END,strlen(NOFILL_END)) )
{
nofill -= 1;
/* Write a </PRE> only for the last <nofill> */
if( 0 == nofill )
{
pre -= 1;
fputs( "</PRE>\n", file );
}
else if( 0 < nofill )
fputs( "<BR>\n", file );
p += 1 + strlen(NOFILL_END);
continue;
}
else if( EQUAL == strnicmp(p+1,SMALLER_START,strlen(SMALLER_START)) )
{
prefont = (pre > 0);
/* Ignore font changes inside of <PRE>...</PRE> */
if( NO == prefont )
{
smaller += 1;
fontsize = max( FONTSIZE_MIN, FONTSIZE_DEFAULT - smaller + bigger );
changefont( file, fontsize, fontcolor, bold, italic, underline, teletype );
}
p += 1 + strlen(SMALLER_START);
continue;
}
else if( EQUAL == strnicmp(p+1,SMALLER_END,strlen(SMALLER_END)) )
{
prefont = (pre > 0);
/* Ignore font changes inside of <PRE>...</PRE> */
if( NO == prefont )
{
smaller -= 1;
fontsize = FONTSIZE_DEFAULT - min( 0, smaller - bigger );
changefont( file, fontsize, fontcolor, bold, italic, underline, teletype );
}
p += 1 + strlen(SMALLER_END);
continue;
}
else if( EQUAL == strnicmp(p+1,UNDERLINE_START,strlen(UNDERLINE_START)) )
{
prefont = (pre > 0);
/* Ignore font changes inside of <PRE>...</PRE> */
if( NO == prefont )
{
underline += 1;
fputs( "<U>", file );
}
p += 1 + strlen(UNDERLINE_START);
continue;
}
else if( EQUAL == strnicmp(p+1,UNDERLINE_END,strlen(UNDERLINE_END)) )
{
prefont = (pre > 0);
/* Ignore font changes inside of <PRE>...</PRE> */
if( NO == prefont )
{
underline -= 1;
fputs( "</U>", file );
}
p += 1 + strlen(UNDERLINE_END);
continue;
}
/* Ignore other <param> sections */
else if( EQUAL == strnicmp(p+1,PARAM_START,strlen(PARAM_START)) )
{
param += 1;
p += 1 + strlen(PARAM_START);
continue;
}
else if( EQUAL == strnicmp(p+1,PARAM_END,strlen(PARAM_END)) )
{
param -= 1;
p += 1 + strlen(PARAM_END);
continue;
}
/* Ignore unknown commands */
else
{
while( '>' != *p )
p += 1;
continue;
}
} /* end if */
if( param > 0 )
continue;
else if( '>' == *p )
fputs( ">", file );
else
fputc( *p, file );
} /* end while */
if( '\n' != *end )
fputs( "</P>\n", file );
fputs( "\n</FONT>\n</BODY>\n</HTML>\n", file );
return;
}
/*************************************************************************
* *
* convcolor() *
* Convert color from text/enriched format (rrrr,gggg,bbbb or *
* text/enriched color name) to text/html (rrggbb or text/html color *
* name) *
* *
*************************************************************************/
char* convcolor ( char* richcolor, char* htmlcolor )
{
char red[5];
int r;
char blue[5];
int b;
char green[5];
int g;
char s[20];
if( EQUAL == stricmp("black",richcolor) )
{
strcpy( htmlcolor, "000000" );
return htmlcolor;
}
if( EQUAL == stricmp("blue",richcolor) )
{
strcpy( htmlcolor, "0000FF" );
return htmlcolor;
}
if( EQUAL == stricmp("cyan",richcolor) )
{
strcpy( htmlcolor, "00FFFF" );
return htmlcolor;
}
if( EQUAL == stricmp("green",richcolor) )
{
strcpy( htmlcolor, "00FF00" );
return htmlcolor;
}
if( EQUAL == stricmp("magenta",richcolor) )
{
strcpy( htmlcolor, "FF00FF" );
return htmlcolor;
}
if( EQUAL == stricmp("red",richcolor) )
{
strcpy( htmlcolor, "FF0000" );
return htmlcolor;
}
if( EQUAL == stricmp("white",richcolor) )
{
strcpy( htmlcolor, "FFFFFF" );
return htmlcolor;
}
if( EQUAL == stricmp("yellow",richcolor) )
{
strcpy( htmlcolor, "FFFF00" );
return htmlcolor;
}
/*
At this point the text/enriched color is assumed to be of format rrrr,gggg,bbbb
(This is some probably not very fault tolerant code...)
*/
strcpy( red, strtok(richcolor,",") );
strcpy( green, strtok(NULL,",") );
strcpy( blue, strtok(NULL,",") );
/* Color experts may know of a better color mapping... */
r = floor( xtoi(red) / 65536.0 * 256.0 + 0.5 );
g = floor( xtoi(green) / 65536.0 * 256.0 + 0.5 );
b = floor( xtoi(blue) / 65536.0 * 256.0 + 0.5 );
strcpy( htmlcolor, itox(r,s) );
strcat( htmlcolor, itox(g,s) );
strcat( htmlcolor, itox(b,s) );
return htmlcolor;
}
/*************************************************************************
* *
* xtoi() *
* Convert 4-digit hexadecimal string to integer *
* *
*************************************************************************/
int xtoi ( char* hex )
{
int i;
int n = 0;
for( i = 0; i < strlen(hex); i += 1 )
{
n *= 16;
switch( hex[i] )
{
case '0': break;
case '1': n += 1; break;
case '2': n += 2; break;
case '3': n += 3; break;
case '4': n += 4; break;
case '5': n += 5; break;
case '6': n += 6; break;
case '7': n += 7; break;
case '8': n += 8; break;
case '9': n += 9; break;
case 'a': ;
case 'A': n += 10; break;
case 'b': ;
case 'B': n += 11; break;
case 'c': ;
case 'C': n += 12; break;
case 'd': ;
case 'D': n += 13; break;
case 'e': ;
case 'E': n += 14; break;
case 'f': ;
case 'F': n += 15; break;
default:
return 0;
}
} /* end for */
return n;
}
/*************************************************************************
* *
* itox() *
* Convert integer (0..255) to 2 character hex string *
* *
*************************************************************************/
char* itox ( int n, char* hex )
{
if( n < 0 )
{
strcpy( hex, "00" );
return hex;
}
if( n > 255 )
{
strcpy( hex, "FF" );
return hex;
}
switch( n / 16 )
{
case 0: hex[0] = '0'; break;
case 1: hex[0] = '1'; break;
case 2: hex[0] = '2'; break;
case 3: hex[0] = '3'; break;
case 4: hex[0] = '4'; break;
case 5: hex[0] = '5'; break;
case 6: hex[0] = '6'; break;
case 7: hex[0] = '7'; break;
case 8: hex[0] = '8'; break;
case 9: hex[0] = '9'; break;
case 10: hex[0] = 'A'; break;
case 11: hex[0] = 'B'; break;
case 12: hex[0] = 'C'; break;
case 13: hex[0] = 'D'; break;
case 14: hex[0] = 'E'; break;
case 15: hex[0] = 'F'; break;
}
switch( n % 16 )
{
case 0: hex[1] = '0'; break;
case 1: hex[1] = '1'; break;
case 2: hex[1] = '2'; break;
case 3: hex[1] = '3'; break;
case 4: hex[1] = '4'; break;
case 5: hex[1] = '5'; break;
case 6: hex[1] = '6'; break;
case 7: hex[1] = '7'; break;
case 8: hex[1] = '8'; break;
case 9: hex[1] = '9'; break;
case 10: hex[1] = 'A'; break;
case 11: hex[1] = 'B'; break;
case 12: hex[1] = 'C'; break;
case 13: hex[1] = 'D'; break;
case 14: hex[1] = 'E'; break;
case 15: hex[1] = 'F'; break;
}
hex[2] = '\0';
return hex;
}
/*************************************************************************
* *
* changefont() *
* Write </FONT><FONT SIZE="..." COLOR="#..."> *
* *
*************************************************************************/
void changefont ( FILE* file, int size, char* color, int bold, int italic, int underline, int teletype )
{
char dummy[2];
if( bold > 0 )
fputs( "</B>", file );
if( italic > 0 )
fputs( "</I>", file );
if( underline > 0 )
fputs( "</U>", file );
if( teletype > 0 )
fputs( "</TT>", file );
fputs( "</FONT><FONT SIZE=\"", file );
fputs( (char*)_itoa(size,dummy,10), file );
fputs( "\" COLOR=\"#", file );
fputs( color, file );
fputs( "\">", file );
if( teletype > 0 )
fputs( "<TT>", file );
if( underline > 0 )
fputs( "<U>", file );
if( italic > 0 )
fputs( "<I>", file );
if( bold > 0 )
fputs( "<B>", file );
return;
}