summaryrefslogtreecommitdiff
path: root/support/rtf2html
diff options
context:
space:
mode:
Diffstat (limited to 'support/rtf2html')
-rw-r--r--support/rtf2html/Makefile12
-rw-r--r--support/rtf2html/ReadMe22
-rw-r--r--support/rtf2html/Sample.rtf18
-rw-r--r--support/rtf2html/rtf2html.c477
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("&lt");
+ break;
+
+ case '>':
+ RTF_PutStr("&gt");
+ break;
+
+ case '&':
+ RTF_PutStr("&amp");
+ 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));
+}