summaryrefslogtreecommitdiff
path: root/support/word2x/html-embed.cc
diff options
context:
space:
mode:
authorNorbert Preining <norbert@preining.info>2019-09-02 13:46:59 +0900
committerNorbert Preining <norbert@preining.info>2019-09-02 13:46:59 +0900
commite0c6872cf40896c7be36b11dcc744620f10adf1d (patch)
tree60335e10d2f4354b0674ec22d7b53f0f8abee672 /support/word2x/html-embed.cc
Initial commit
Diffstat (limited to 'support/word2x/html-embed.cc')
-rw-r--r--support/word2x/html-embed.cc381
1 files changed, 381 insertions, 0 deletions
diff --git a/support/word2x/html-embed.cc b/support/word2x/html-embed.cc
new file mode 100644
index 0000000000..55bc9ec720
--- /dev/null
+++ b/support/word2x/html-embed.cc
@@ -0,0 +1,381 @@
+/* $Id: html-embed.cc,v 1.8 1997/03/25 23:23:04 dps Exp $ */
+/* Embed handling for *TeX output */
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif /* HAVE_CONFIG_H */
+#include <stdio.h>
+#ifdef HAVE_STRING_H
+#include <string.h>
+#endif /* HAVE_STRING_H */
+#ifdef HAVE_STRINGS_H
+#include <strings.h>
+#endif /* HAVE_STRINGS_H */
+#ifdef HAVE_CTYPE_H
+#include <ctype.h>
+#endif /* HAVE_CTYPE_H */
+#include "interface.h"
+#include "tblock.h"
+#include "fmt-html.h"
+
+
+/* Skip a term */
+const char *html_skip_to_next(const char *ptr)
+{
+ int blevel;
+ int ign_nxt;
+
+ ign_nxt=0;
+ blevel=0;
+ while(1)
+ {
+ switch(*ptr)
+ {
+ case '\\':
+ ign_nxt=1;
+ break;
+
+ case '(':
+ if (!ign_nxt)
+ blevel++;
+ break;
+
+ case ')':
+ if (!ign_nxt)
+ blevel--;
+ if (blevel<0)
+ return ptr;
+ break;
+
+ case ',':
+ if (!ign_nxt && blevel==0)
+ return ptr;
+ break;
+
+ case '\0':
+ return ptr;
+
+ default:
+ break;
+ }
+ ptr++;
+ }
+}
+
+
+
+/* For detial of this see The TeXbook p. 141) */
+typedef enum {Disp=0, DispP, Text, TextP,
+ Script, ScriptP,
+ SScript, SScriptP } style;
+
+enum TypeIndex { Op_Sup=0, Op_Sub, Op_FTop, Op_FBot };
+/* Style navigation map */
+static const style style_map[][4]=
+{
+ { Script, ScriptP, Text, TextP }, // style D
+ { ScriptP, ScriptP, TextP, TextP }, // style D'
+ { Script, ScriptP, Script, ScriptP }, // Style T
+ { ScriptP, ScriptP, ScriptP, ScriptP }, // Style T'
+ { SScript, SScriptP, SScript, SScriptP }, // Style S
+ { SScriptP, SScriptP, SScriptP, SScriptP }, // Style S'
+ { SScript, SScriptP, SScript, SScriptP }, // Style SS
+ { SScriptP, SScriptP, SScriptP, SScriptP } // Style SS'
+};
+
+/* The actual work is in this recursive procedure */
+static tblock *cvt_eqn(const char *inp, const char *stop,
+ const int mline, const style sty)
+{
+ tblock *res, *r1, *r2;
+ const char *mid, *end;
+
+
+ res=new(tblock);
+ while (inp<stop)
+ {
+ if (isspace(*inp) && *inp!='\n')
+ {
+ inp++;
+ continue;
+ }
+
+ switch (*inp)
+ {
+ case '\0':
+ return res;
+
+ case '\n':
+ if (mline)
+ res->add(" \\\\\n");
+ break;
+
+ case '<':
+ case '>':
+ case '=':
+ if (mline)
+ {
+ res->add(" & ");
+ res->add(*inp);
+ res->add(" & ");
+ }
+ else
+ res->add(*inp);
+ break;
+
+ case '\\':
+ inp++;
+ switch(*inp)
+ {
+ case '\0':
+ cerr<<"Bug: cvt_eqn as \\0\n";
+ return res; // Safety.
+
+ case '(': // Guesswork FIXME
+ res->add(" (");
+ break;
+
+ case ')': // Guesswork FIXME
+ res->add(" )");
+ break;
+
+ case 'F': // Fraction
+ if (*(++inp)=='(' &&
+ *(mid=html_skip_to_next(++inp))!='\0' &&
+ *(end=html_skip_to_next(mid+1))!='\0')
+ {
+ r1=cvt_eqn(inp, mid, mline, style_map[sty][Op_FTop]);
+ r2=cvt_eqn(mid+1, end, mline, style_map[sty][Op_FBot]);
+ res->add(' ');
+ res->add(*r1);
+ res->add(" / "); // TeX syntax
+ res->add(*r2);
+ res->add(' ');
+ delete(r1); delete(r2);
+ }
+ inp=end;
+ break;
+ default:
+ end=html_skip_to_next(inp+1);
+ r1=cvt_eqn(inp+1, end, mline, sty);
+ res->add("<TT> \\backslash "); res->add(*inp);
+ res->add("</TT> "); res->add(*r1); res->add("<TT> ");
+ delete(r1);
+ inp=end;
+ break;
+ }
+ break;
+ case '+':
+ case '-':
+ res->add(*inp);
+ break;
+ case '*':
+ res->add(" * ");
+ break;
+
+ case ' ':
+ res->add(" ");
+ break;
+
+ case '_':
+ res->add("_");
+ break;
+
+ default:
+ int flg=0;
+ const char *scn;
+
+ /*
+ * This section is meant to catch 72 dpi and render it as
+ * \hbox{72 dpi} but not catch 12 * 18 (which should become
+ * 12\times 18).
+ */
+ if (isdigit(*inp) || *inp=='-' || *inp=='+')
+ {
+
+ /* Scan forward to see what comes text */
+ scn=inp;
+ if (*scn=='-' || *scn=='+')
+ scn++; // Skip sign
+ while (scn<stop && isdigit(*scn))
+ scn++; // Skip number
+ if (*scn=='.')
+ {
+ scn++;
+ while (scn<stop && isdigit(*scn))
+ scn++; // Hanlde decimals number
+ }
+
+ /* Now start looking at what comes next */
+ while (scn<stop)
+ {
+ if (isspace(*scn))
+ {
+ scn++;
+ continue;
+ }
+ if (isupper(*scn) || islower(*scn))
+ flg=1;
+ else
+ flg=0;
+ break;
+ }
+ }
+
+ /*
+ * This section is meant to catch strings and render them nicely
+ * in a mbox.
+ */
+ if (islower(*inp) || isupper(*inp) || flg)
+ {
+ res->add("\\text{");
+ if (flg) // If flag set then add everything up to scn
+ {
+ while (inp<scn)
+ {
+ res->add(*inp);
+ inp++;
+ }
+ }
+
+ flg=0; // Re-use flg
+ while (inp<stop && (islower(*inp) || isupper(*inp)
+ || isspace(*inp)
+ || *inp=='_'
+ || *inp=='^'))
+ {
+ if (isspace(*inp))
+ {
+ flg=1;
+ inp++;
+ continue; // If space, just set the flag
+ }
+ if (flg)
+ res->add(' '); // If skiped a space, add one
+ flg=0; // Clear flag
+ if (*inp=='_' || *inp=='^')
+ res->add('\\');
+ res->add(*inp);
+ inp++;
+ }
+ res->add("} ");
+ inp--;
+ break;
+ }
+ res->add(*inp);
+ break;
+ }
+ inp++;
+ }
+ return res;
+}
+
+/* Equations --- need more examples here */
+static void equation(const char *txt, const docfmt *fmt, FILE *out,
+ void *d)
+{
+
+ static const cmap comment_map[]={ { '\n', "\n% (contd) % " } };
+ struct html_data *dp;
+ tblock *cvt, eqn, *op;
+ const char *s;
+ int mline;
+
+ dp=(struct html_data *) d;
+ cvt=map_string(txt, comment_map);
+ fprintf(out, "%%\n%% EMBED %s\n", (const char *) (*cvt));
+ delete(cvt);
+
+ for (mline=0, s=txt; *s!='\0'; s++)
+ {
+ if (*s=='\n')
+ {
+ mline=1;
+ break;
+ }
+ }
+ if (!mline)
+ eqn.add((dp->par_flg) ? "$" : "$$");
+ else
+ eqn.add("\\begin{eqnarray*}\n");
+ cvt=cvt_eqn(txt+3, txt+strlen(txt), mline, (dp->par_flg) ? Disp : Text);
+ eqn.add(*cvt);
+ delete(cvt);
+
+ if (!mline)
+ eqn.add((dp->par_flg) ? "$" : "$$%");
+ else
+ eqn.add("\n\\end{eqnarray*}\n");
+
+ op=word_wrap(eqn, "\n", "\n", fmt->maxline);
+ fputs((const char *) (*op), out);
+ fputc('\n', out);
+ delete(op);
+}
+
+
+
+/* Table of contents entries, used as a cue for stuff like sections */
+/* This code jus stashes it away for the paragraph code */
+static void add_contents(const char *txt, const docfmt *fmt, FILE *out,
+ void *d)
+{
+ const char *open, *close;
+ tblock entry;
+ struct html_data *dp;
+
+ fmt=fmt;
+ out=out;
+ dp=(struct html_data *) d;
+ for (open=txt; *open!='"'; open++)
+ {
+ if (*open=='\0')
+ {
+ cerr<<"Found tc entry but no openning quote\n";
+ return;
+ }
+ }
+
+ for (close=open+1; *close!='"'; close++)
+ {
+ if (*close=='\0')
+ {
+ cerr<<"Found tc entry but no closing quote\n";
+ return;
+ }
+ }
+
+ if (close-open==1)
+ {
+ cerr<<"Ignoring empty table of contents entry\n";
+ return;
+ }
+
+ while (++open<close)
+ entry.add(*open);
+ if (dp->last_tc!=NULL)
+ free((void *) dp->last_tc);
+ dp->last_tc=strdup(entry);
+
+}
+
+static struct embed emb[]=
+{
+ { "tc ", 3, add_contents }, // Table of contents line
+ { "eq ", 3, equation }, // Equations
+};
+
+void html_embed(const tok_seq::tok *t, const docfmt *fmt, FILE *out,
+ void *d)
+{
+ int i;
+
+ for (i=0; (unsigned) i<N(emb); i++)
+ {
+ if (strncmp(t->data.d, emb[i].key, emb[i].key_len)==0)
+ {
+ (emb[i].handle)(t->data.d, fmt, out, d);
+ return;
+ }
+ }
+ fprintf(out, "%%\n%% %s\n", t->data.d);
+}