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/word2x/html-embed.cc |
Initial commit
Diffstat (limited to 'support/word2x/html-embed.cc')
-rw-r--r-- | support/word2x/html-embed.cc | 381 |
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); +} |