diff options
author | Norbert Preining <norbert@preining.info> | 2019-09-02 13:46:59 +0900 |
---|---|---|
committer | Norbert Preining <norbert@preining.info> | 2019-09-02 13:46:59 +0900 |
commit | e0c6872cf40896c7be36b11dcc744620f10adf1d (patch) | |
tree | 60335e10d2f4354b0674ec22d7b53f0f8abee672 /support/rtf2html |
Initial commit
Diffstat (limited to 'support/rtf2html')
-rw-r--r-- | support/rtf2html/Makefile | 12 | ||||
-rw-r--r-- | support/rtf2html/ReadMe | 22 | ||||
-rw-r--r-- | support/rtf2html/Sample.rtf | 18 | ||||
-rw-r--r-- | support/rtf2html/rtf2html.c | 477 |
4 files changed, 529 insertions, 0 deletions
diff --git a/support/rtf2html/Makefile b/support/rtf2html/Makefile new file mode 100644 index 0000000000..ad61d9a097 --- /dev/null +++ b/support/rtf2html/Makefile @@ -0,0 +1,12 @@ +#Genmake v1.03 pl2 11/12/91 Copyright(c) 1990, 1991 by Kyle Saunders +CC= cc +CFLAGS= -g +OFILES= \ + rtf2html.o +# +rtf2html: $(OFILES) + $(CC) $(CFLAGS) -o rtf2html $(OFILES) + +rtf2html.o: rtf2html.c + $(CC) $(CFLAGS) -c rtf2html.c + diff --git a/support/rtf2html/ReadMe b/support/rtf2html/ReadMe new file mode 100644 index 0000000000..f2c021b396 --- /dev/null +++ b/support/rtf2html/ReadMe @@ -0,0 +1,22 @@ +rtf2html - a RTF to HTML conversion program + +This is the first cut at a RTF to HTML converter. It has several limitations +that users should be aware of. First, unless you want to make some changes +to tables within the source, you need to use the style sheet that is +defined in Sample.rtf to format your Word documents. It's easiest to just +start with Sample.rtf as your basic document and cut out what you don't +need. + +rtf2html is dependent on the style numbers in the style sheet matching those +in the conversion table in the code. This is an UGLY hack, but I really +didn't want to parse the style sheet. Hey, it's free. + +To build the code, type "make". This code should build on anything with a +C compiler. It was written on a Mac using Think C and moved to Unix with +no changes. + +Please send any comments or suggestions to cshotton@oac.hsc.uth.tmc.edu. + +Chuck Shotton +Ass't Director, Academic Computing +U. of Texas Houston Health Science Center diff --git a/support/rtf2html/Sample.rtf b/support/rtf2html/Sample.rtf new file mode 100644 index 0000000000..9dd2b34951 --- /dev/null +++ b/support/rtf2html/Sample.rtf @@ -0,0 +1,18 @@ +{\rtf1\mac\deff2 {\fonttbl{\f0\fswiss Chicago;}{\f2\froman New York;}{\f3\fswiss Geneva;}{\f4\fmodern Monaco;}{\f11\fnil Cairo;}{\f13\fnil Zapf Dingbats;}{\f14\fnil Bookman;}{\f15\fnil N Helvetica Narrow;}{\f16\fnil Palatino;}{\f18\fnil Zapf Chancery;} +{\f20\froman Times;}{\f21\fswiss Helvetica;}{\f22\fmodern Courier;}{\f23\ftech Symbol;}{\f33\fnil Avant Garde;}{\f34\fnil New Century Schlbk;}{\f1297\fnil GoudyHundred;}{\f1602\fnil BlackChancery;}{\f2515\fnil MT Extra;}{\f4950\fnil TTYFont;} +{\f11132\fnil InsigniaLQmono;}{\f11133\fnil InsigniaLQprop;}{\f32500\fnil VT320;}{\f32525\fnil VT100;}}{\colortbl\red0\green0\blue0;\red0\green0\blue255;\red0\green255\blue255;\red0\green255\blue0;\red255\green0\blue255;\red255\green0\blue0; +\red255\green255\blue0;\red255\green255\blue255;}{\stylesheet{\s250\li720 \f21\fs20\ul \sbasedon0\snext0 heading 6;}{\s251\li720 \b\f21\fs20 \sbasedon0\snext0 heading 5;}{\s252\li360 \f21\ul \sbasedon0\snext0 heading 4;}{\s253\li360 \b\f21 +\sbasedon0\snext0 heading 3;}{\s254\sb120 \b\f21 \sbasedon0\snext0 heading 2;}{\s255\sb240 \b\f21\ul \sbasedon0\snext0 heading 1;}{\f21 \sbasedon222\snext0 Normal;}{\s2 \b\f21\cf1 \sbasedon0\snext2 Anchor;}}{\info{\author Chuck Shotton}} +\margl720\margr720\ftnbj\fracwidth \sectd \sbknone\linemod0\linex0\cols1\endnhere \pard\plain \s255\sb240 \b\f21\ul Heading 1\par +\pard\plain \f21 This is the first normal paragraph!\par +\pard\plain \s254\sb120 \b\f21 Heading 2\par +\pard\plain \s253\li360 \b\f21 Heading 3\par +\pard\plain \s252\li360 \f21\ul Heading 4\par +\pard\plain \s251\li720 \b\f21\fs20 Heading 5\par +\pard\plain \s250\li720 \f21\fs20\ul Heading 6\par +\pard\plain \f21 This is a chunk of normal text.\par +This is a chunk of normal text with specials, &, <, and >.\par +This is a second paragraph.\par +This is text with embedded {\b bold}, {\i italic}, and {\ul underline} styles.\par +Here is the {\cf1 anchor} style. And here is the {\cf5 Image} style.\par +}
\ No newline at end of file diff --git a/support/rtf2html/rtf2html.c b/support/rtf2html/rtf2html.c new file mode 100644 index 0000000000..22b4209e52 --- /dev/null +++ b/support/rtf2html/rtf2html.c @@ -0,0 +1,477 @@ +/*RTF2HTML.c, Chuck Shotton - 6/21/93 */ +/************************************************************************ + * This program takes a stab at converting RTF (Rich Text Format) files + * into HTML. There are some limitations that keep RTF from being able to + * easily represent things like in-line images and anchors as styles. In + * particular, RTF styles apply to entire "paragraphs", so anchors or + * images in the middle of a text stream can't easily be represented by + * styles. The intent is to ultimately use something like embedded text + * color changes to represent these constructs. + * + * In the meantime, you can take existing Word documents, apply the + * correct style sheet, and convert them to HTML with this tool. + * + * AUTHOR: Chuck Shotton, UT-Houston Academic Computing, + * cshotton@oac.hsc.uth.tmc.edu + * + * USAGE: rtf2html [rtf_filename] + * + * BEHAVIOR: + * rtf2html will open the specified RTF input file or read from + * standard input, writing converted HTML to standard output. + * + * NOTES: + * The RTF document must be formatted with a style sheet that has + * style numberings that conform to the style_mappings table + * defined in this source file. + * + * MODIFICATIONS: + * 6/21/93 : Chuck Shotton - created version 1.0. + * + ************************************************************************/ + +/* Note, the source is formated with 4 character tabs */ + +#include <stdio.h> +#include <string.h> + +#ifdef THINK_C +#include <console.h> +#endif + +#ifndef TRUE +#define TRUE -1 +#define FALSE 0 +#endif + +#define MAX_LEVELS 20 /*defines the # of nested in-line styles (pairs of {})*/ +#define MAX_STYLES 12 +#define MAX_INLINE_STYLES 4 /*defines # of in-line styles, bold, italic, etc.*/ + +typedef enum {s_plain, s_bold, s_italic, s_underline, /*in-line styles*/ + s_para, /*pseudo style*/ + s_h0, s_h1, s_h2, s_h3, s_h4, s_h5, s_h6 /*heading styles*/ +} StyleState; + +char *styles[MAX_STYLES][2] = { /*HTML Start and end tags for styles*/ + {"", ""}, + {"<b>", "</b>"}, + {"<i>", "</i>"}, + {"<em>", "</em>"}, + {"<p>", ""}, + {"", ""}, + {"<h1>", "</h1>"}, + {"<h2>", "</h2>"}, + {"<h3>", "</h3>"}, + {"<h4>", "</h4>"}, + {"<h5>", "</h5>"}, + {"<h6>", "</h6>"} +}; + +/* style_mappings maps the style numbers in a RTF style sheet into one of the*/ +/* (currently) six paragraph-oriented HTML styles (i.e. heading 1 through 6.)*/ +/* Additional styles for lists, etc. should be added here. Style info */ +/* ultimately should be read from some sort of config file into these tables.*/ + +char *style_mappings[7] = { + "", "255", "254", "253", "252", "251", "250" +}; + +/* RTF tokens that mean something to the parser. All others are ignored. */ + +typedef enum {t_start,t_fonttbl, t_colortbl, t_stylesheet, t_info, + t_s, t_b, t_u, t_i, t_plain, t_par, t_end} TokenIndex; + +char *tokens[] = { + "###", + "fonttbl", + "colortbl", + "stylesheet", + "info", + "s", + "b", + "ul", + "i", + "plain", + "par", + "###" +}; + +char style_state[MAX_LEVELS][MAX_INLINE_STYLES], curr_style[MAX_INLINE_STYLES]; +short curr_heading; + +short level, /*current {} nesting level*/ + skip_to_level,/*{} level to which parsing should skip (used to skip */ + /* font tables, style sheets, color tables, etc.) */ + gobble, /*Flag set to indicate all input should be discarded */ + ignore_styles;/*Set to ignore inline style expansions after style use*/ + +/**************************************/ + +char RTF_GetChar(f) +FILE *f; +{ + return fgetc(f); +} + +/**************************************/ + +void RTF_PutStr(s) +char *s; +{ + if (gobble) return; + fputs(s, stdout); +} + +/**************************************/ + +void RTF_PutChar(ch) +char ch; +{ + if (gobble) return; + switch (ch) { + case '<': + RTF_PutStr("<"); + break; + + case '>': + RTF_PutStr(">"); + break; + + case '&': + RTF_PutStr("&"); + break; + + default: + fputc(ch, stdout); + } +} + + +/**************************************/ + +void RTF_PlainStyle (s) +char *s; +{ +int j; + for (j=0;j<MAX_INLINE_STYLES;j++) + s[j] = (char) 0; +} + +/**************************************/ + +void RTF_CopyStyle (s, d) +char *s, *d; +{ +int j; + for (j=0;j<MAX_INLINE_STYLES;j++) + d[j] = s[j]; +} + +/**************************************/ + +void RTF_PushState(level) +short *level; +{ + RTF_CopyStyle (curr_style, style_state[*level]); + (*level)++; +} + +/**************************************/ + +void RTF_PopState(level) +short *level; +{ +int j; + /*close off any in-line styles*/ + for (j=0;j<MAX_INLINE_STYLES;j++) { + if (curr_style[j]) + RTF_PutStr(styles[j][1]); + } + + (*level)--; + RTF_CopyStyle (style_state[*level], curr_style); + + if (*level == skip_to_level) { + skip_to_level = -1; + gobble = FALSE; + } +} + +/**************************************/ + +void RTF_Title(s) +char *s; +{ + fprintf (stdout, "<title>%s</title>", s); +} + +/**************************************/ + +void RTF_BuildToken (token, ch) +char *token; +char ch; +{ + strncat (token, &ch, 1); +} + +/**************************************/ +/* Map a style number into a HTML heading */ + +short RTF_MapStyle(s) +char *s; +{ +int i; + for (i=0;i<7;i++) + if (!strcmp(style_mappings[i], s)) + return (i); + return (0); +} + +/**************************************/ +/* Perform actions for RTF control words */ + +void RTF_DoControl (control, arg) +char *control, *arg; +{ +TokenIndex i; +short style; + + if (gobble) return; + + for (i=t_start; i<t_end; i++) { + if (!strcmp(control, tokens[i])) + break; + } + + switch (i) { + case t_fonttbl: /*skip all of these and their contents!*/ + case t_colortbl: + case t_stylesheet: + case t_info: + gobble = TRUE; /*perform no output, ignore commands 'til level-1*/ + skip_to_level = level-1; + break; + + case t_s: /*Style*/ + style = RTF_MapStyle (arg); + curr_heading = s_h0 + style; + RTF_PutStr(styles[curr_heading][0]); + ignore_styles = TRUE; + break; + + case t_b: /*Bold*/ + if (!ignore_styles) { + RTF_PutStr(styles[s_bold][0]); + curr_style[s_bold] = TRUE; + } + break; + + case t_u: /*Underline, maps to "emphasis" HTML style*/ + if (!ignore_styles) { + RTF_PutStr(styles[s_underline][0]); + curr_style[s_underline] = TRUE; + } + break; + + case t_i: /*Italic*/ + if (!ignore_styles) { + RTF_PutStr(styles[s_italic][0]); + curr_style[s_italic] = TRUE; + } + break; + + case t_par: /*Paragraph*/ + if (curr_heading) { + RTF_PutStr(styles[curr_heading][1]); + curr_heading = s_plain; + } + else { + RTF_PutStr(styles[s_para][0]); + } + ignore_styles = FALSE; + break; + + case t_plain: /*reset inline styles*/ + RTF_PlainStyle(curr_style); + break; + } + +} + +/**************************************/ +/* RTF_Parse is a crude, ugly state machine that understands enough of */ +/* the RTF syntax to be dangerous. */ + +typedef enum {plaintext, control, argument, backslash} ParseState; + +int RTF_Parse (filename) +char *filename; +{ +FILE *f; +char ch; +ParseState state; +char token[40], arg[40]; + + if (filename) { + if (!(f = fopen (filename, "r"))) { + fprintf (stderr, "\nError: Input file %s not found.\n", filename); + return (-1); + } + RTF_Title(filename); + } + else { + f = stdin; + RTF_Title("STDIN"); + } + + state = plaintext; + level = 0; + skip_to_level = -1; + gobble = FALSE; + ignore_styles = FALSE; + + while (!feof(f)) { + /*get a character*/ + ch = RTF_GetChar(f); + + switch (state) { + + case plaintext: /*this is just normal user content*/ + switch (ch) { + case '\\': + state = backslash; + break; + + case '{': + RTF_PushState(&level); + break; + + case '}': + RTF_PopState(&level); + break; + + default: + RTF_PutChar(ch); + break; + } + break; + + case backslash: /*something special like a command or escape*/ + switch (ch) { + case '\\': + case '{': + case '}': + RTF_PutChar(ch); + state = plaintext; + break; + + default: + if (isalpha(ch)) { + state = control; + token[0]='\0'; + RTF_BuildToken(token, ch); + } + else { + fprintf(stderr, "\nRTF Error: unexpected '%c' after \\.\n", ch); + } + break; + } + break; + + case control: /*collecting the command token*/ + if (isalpha(ch)) { + RTF_BuildToken(token, ch); + } + else if (isdigit(ch)) { + state = argument; + arg[0]='\0'; + RTF_BuildToken(arg, ch); + } + else { + RTF_DoControl (token, ""); + state = plaintext; + + switch (ch) { + case '\\': + state = backslash; + break; + + case '{': + RTF_PushState(&level); + break; + + case '}': + RTF_PopState(&level); + break; + + default: + if (!isspace(ch)) RTF_PutChar(ch); + break; + } + } + break; + + case argument: /*collecting the optional command argument*/ + if (isdigit(ch)) { + RTF_BuildToken(arg, ch); + } + else { + state = plaintext; + RTF_DoControl (token, arg); + switch (ch) { + case '\\': + state = backslash; + break; + + case '{': + RTF_PushState(&level); + break; + + case '}': + RTF_PopState(&level); + break; + + default: + if (!isspace(ch)) RTF_PutChar(ch); + break; + } + } + break; + }/*switch*/ + }/*while*/ + + fclose (f); +} + +/**************************************/ + +void Initialize() +{ +int i,j; + + for (i=0;i<MAX_LEVELS;i++) + for (j=0;j<MAX_STYLES;j++) + RTF_PlainStyle(style_state[i]); + + RTF_PlainStyle(curr_style); + curr_heading = s_plain; +} + +/**************************************/ + +main(argc, argv) +int argc; +char **argv; +{ +#ifdef THINK_C + argc = ccommand (&argv); +#endif + + Initialize(); + + if (argc>1) + return (RTF_Parse(argv[1])); + else + return (RTF_Parse(NULL)); +} |