summaryrefslogtreecommitdiff
path: root/support/word2x/latex-fmt.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/latex-fmt.cc
Initial commit
Diffstat (limited to 'support/word2x/latex-fmt.cc')
-rw-r--r--support/word2x/latex-fmt.cc537
1 files changed, 537 insertions, 0 deletions
diff --git a/support/word2x/latex-fmt.cc b/support/word2x/latex-fmt.cc
new file mode 100644
index 0000000000..1caf7fb4e2
--- /dev/null
+++ b/support/word2x/latex-fmt.cc
@@ -0,0 +1,537 @@
+/* $Id: latex-fmt.cc,v 1.15 1997/04/13 13:26:38 dps Exp dps $ */
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif /* HAVE_CONFIG_H */
+#include <stdio.h>
+#include <stdlib.h>
+#include <time.h>
+#ifdef HAVE_UNISTD_H
+#include <unistd.h>
+#endif /* HAVE_UNISTD_H */
+#ifdef HAVE_CTYPE_H
+#include <ctype.h>
+#endif /* HAVE_CTYPE_H */
+#ifdef HAVE_SYS_STAT_H
+#include <sys/stat.h>
+#endif /* HAVE_SYS_STAT_H */
+#include "interface.h"
+#include "lib.h"
+#include "latex-table.h"
+#include "fmt-latex.h"
+
+static const cmap tex_map[]=
+{
+ { '\n', "\\\\\n" }, // Newline
+ { 0x1E, "-" }, // Unbreakable join
+ { 0x1F, "\\-" }, // Soft hypen
+ { '#', "{\\#}" }, // #
+ { '$', "{\\$}" }, // $
+ { '%', "{\\%}" }, // % (5th element)
+ { '&', "{\\&}" }, // &
+ { '@', "{\\@}" }, // @
+ { '\\', "$\\backslash$" }, // backslash
+ { '^', "{\\^}" }, // ^
+ { '_', "{\\_}" }, // _ (10th element)
+ { '{', "{\\{}" }, // {
+ { '}', "{\\}}" }, // }
+ { '~', "{\\~}" }, // ~
+ { CH_SUSPECT, "" }, // Delete suspect data markers
+ { 0x85, "\\unskip\\ldots" }, // Dots
+ { 0x91, "{`}" }, // 91 = left quote (15th element)
+ { 0x92, "{'}" }, // 92 = right quote
+ { 0x93, "``" }, // 93 = opening double quote
+ { 0x94, "''" }, // 94 = closing double quote
+ { 0x96, "--" }, // em-dash
+ { 0x97, "---" }, // en-dash (20th element)
+ { 0x99, "${}^{\\rm TM}$" }, // Trademark
+ { 0xA0, "~" }, // Unbreakable space
+ { 0xA3, "$\\leq$" }, // <= came out as A3, also pounds
+ { 0xA9, "{\\copyright}" }, // Copyright
+ { 0xAB, "$<\\!\\!<$" }, // Openning << quotes (25th element)
+ { 0xAE, "{\\reg}" }, // reserved sign
+ { 0xB3, "$\\geq$" }, // Greater than or = came out as B3
+ { 0xBB, "$>\\!\\!>$" }, // Closing >> quotes (28th element)
+ { 0xDF, "{\\ss}" }, // beta
+ { 0xE4, "\\\"a" }, // a with umlualt
+ { 0xE9, "\\'e" }, // e grave??
+ { 0xF1, "\\=n" }, // n bar
+ { 0xF6, "\\\"o" }, // o with umlualt
+ { 0xFA, "\\.u" }, // u with dot?
+ { 0xFC, "\\\"u" }, // u with umlualt.
+
+};
+
+tblock *__latex_do_map(const char *s)
+{
+ tblock *out;
+
+ out=map_string(s, tex_map);
+ return out;
+}
+
+/* Preamble */
+static void preamble(const tok_seq::tok *t, const docfmt *fmt, FILE *out,
+ void *d)
+{
+ time_t now;
+#ifdef HAVE_FSTAT
+ struct stat st;
+#endif
+ char *tnow, *tdoc;
+
+ t=t;
+ d=d;
+
+ now=time(NULL);
+ tnow=(fmt->date)(now);
+
+#ifdef HAVE_FSTAT
+ if (fstat(fileno(out), &st)==-1)
+ {
+ fprintf(stderr, "Warning: fstat failed\n");
+ st.st_mtime=now;
+ }
+ tdoc=fmt->date(st.st_mtime);
+#else
+ tdoc="date not known";
+#endif
+
+ fprintf(out,
+ "%% Generated by word2x on %s\n"
+ "%%\n"
+ "\\date{%s}\n"
+ "\\documentclass{article}\n"
+ "\\usepackage{amstext}\n"
+ "\\def\\reg{\\setbox0\\hbox{$\\mathchar\"20D$}%%\n"
+ "\\hbox to 0pt{\\hbox to \\wd0{\\hfill\\,\\rm R\\hfill}\\hss}%%\n"
+ "$\\mathchar\"20D$}\n"
+ "\\usepackage[latin1]{inputenc}\n"
+ "\\begin{document}\n",
+ tnow, tdoc);
+ free(tnow);
+ free(tdoc);
+}
+
+/* Postamble */
+static void postamble(const tok_seq::tok *t, const docfmt *fmt, FILE *out,
+ void *d)
+{
+ struct latex_data *dp;
+ fmt=fmt;
+ t=t;
+ dp=(struct latex_data *) d;
+
+ fputs("\\end{document}\n", out);
+}
+
+/* Allocate local data */
+static void *allocate_latex(void)
+{
+ struct latex_data *tdata;
+ int i;
+
+ tdata=new(struct latex_data);
+ tdata->tabl=NULL;
+ tdata->last_tc=NULL;
+ tdata->unit_d.unit_type=1;
+ tdata->list_flg=0;
+ for (i=0; i<4; i++)
+ tdata->unit_d.unit_number[i]=-1;
+ return tdata;
+}
+
+/* Free local data */
+static void free_latex(void *d)
+{
+ struct latex_data *tdata;
+
+ tdata=(struct latex_data *) d;
+ if (tdata->tabl!=NULL)
+ delete(tdata->tabl);
+
+}
+
+static void ltx_code(const tok_seq::tok *t, const docfmt *fmt, FILE *out,
+ void *d)
+{
+ d=d;
+ switch(*(t->data.d))
+ {
+ case CH_PAGE:
+ if (fmt->flags.new_pages)
+ fputs("%\n\\newpage%\n", out);
+ break;
+
+ default:
+ break;
+ }
+}
+
+/* item */
+static void ltx_item(const tok_seq::tok *t, const docfmt *fmt, FILE *out,
+ void *d)
+{
+ struct latex_data *dp;
+ fmt=fmt;
+ t=t;
+ out=out;
+ dp=(struct latex_data *) d;
+
+ dp->list_flg=1;
+}
+
+
+/* start list */
+static void ltx_list(const tok_seq::tok *t, const docfmt *fmt, FILE *out,
+ void *d)
+{
+ fmt=fmt;
+ d=d;
+
+ fprintf(out, "\n\\begin{%s}\n", t->data.d); // Prior argement with reader
+}
+
+/* end list */
+static void ltx_end_list(const tok_seq::tok *t, const docfmt *fmt, FILE *out,
+ void *d)
+{
+ fmt=fmt;
+ d=d;
+
+ fprintf(out, "\n\\end{%s}\n", t->data.d); // Prior argement with reader
+}
+
+
+/* Find part number and return it or -1 if no number */
+int get_part_num(const char *st, const char *fence)
+{
+ int n;
+
+ while (st<fence)
+ {
+ if (isspace(*st))
+ {
+ st++;
+ continue;
+ }
+ if (isdigit(*st))
+ {
+ n=0;
+ while (st<fence && isdigit(*st))
+ {
+ n=n*10+(*st)-'0';
+ st++;
+ }
+ if (!isspace(*st))
+ return -1;
+ else
+ return n;
+
+ }
+ if (isupper(*st) && isspace(*(st+1)))
+ return (*st)-'A'+1;
+
+ /* Nothing else understood at this time */
+ return -1;
+ }
+ return -1;
+}
+
+
+
+
+
+/*
+ * Paragraphs are easy, but get complicated due to need to work out
+ * which things are actually chapter headings, etc
+ */
+static void fold_para(const tok_seq::tok *tok, const docfmt *fmt, FILE *out,
+ void *d)
+{
+ tblock *b, *ts, op;
+ const char *s, *t, *pt;
+ struct latex_data *dp;
+ int do_add, has_num, i, j;
+
+ static const char *const sects[]=
+ {
+ "chapter", "section", "subsection", "subsubsection"
+ };
+
+ dp=(struct latex_data *) d;
+ do_add=0;
+ dp->par_flg=1;
+
+ /* Even this much is under 100%!! */
+ pt=(tok->data.d);
+
+ if (*pt=='\0')
+ return;
+
+ if (dp->last_tc!=NULL)
+ {
+ if (strcmp(dp->last_tc, pt)==0)
+ {
+ op.add("\\addcontentsline{toc}{");
+ op.add(sects[dp->unit_d.unit_type]); op.add("}{");
+ op.add(dp->last_tc); op.add("}\n\\");
+ op.add(sects[dp->unit_d.unit_type]);
+ op.add("*{");
+ do_add=1;
+ }
+
+ else
+ {
+ s=dp->last_tc+strlen(dp->last_tc)-strlen(pt);
+ if (strcmp(s, pt)==0)
+ {
+ /* Find type */
+ for (i=0; i< (int) N(sects)-1; i++)
+ {
+ if (strncasecmp(dp->last_tc, sects[i],
+ strlen(sects[i]))==0)
+ break;
+ }
+ t=dp->last_tc+strlen(sects[i]);
+ has_num=get_part_num(t,s);
+ if (has_num==-1)
+ {
+ op.add("\\addcontentsline{toc}{");
+ op.add(sects[i]); op.add("}{");
+ op.add(dp->last_tc);
+ op.add("}\n");
+ }
+ op.add('\\');
+ op.add(sects[i]);
+ op.add((has_num!=-1) ? "{" : "*{");
+ if (dp->unit_d.unit_number[i]==-1)
+ {
+ dp->unit_d.unit_number[i]=(has_num==-1) ? 1 : has_num;
+ for (j=i+1; j< (int) N(sects); j++)
+ dp->unit_d.unit_number[j]=0;
+ }
+ if (i< (int) N(sects)-1)
+ dp->unit_d.unit_type=i+1;
+ else
+ dp->unit_d.unit_type=i;
+ do_add=1;
+ }
+ }
+ free((void *) dp->last_tc);
+ dp->last_tc=NULL;
+ }
+ else
+ {
+ if (dp->list_flg)
+ {
+ op.add("\\item ");
+ }
+ else
+ {
+ if (strlen(pt)>0 && strlen(pt)<PAR_TRESHOLD_LEN)
+ {
+ if (strcasecmp(pt,"Appendix")==0)
+ {
+ op.add("\\appendix\n\\");
+ dp->unit_d.unit_type=(dp->unit_d.unit_number[0]==-1) ? 1:0;
+ op.add(sects[dp->unit_d.unit_type]);
+ op.add("{");
+ do_add=1;
+ for (j=dp->unit_d.unit_type+1; j< (int) N(sects); j++)
+ dp->unit_d.unit_number[j]=0;
+ }
+ else if (strcasecmp(pt,"Bibliography")==0)
+ {
+ dp->unit_d.unit_type= (dp->unit_d.unit_number[0]==-1) ? 1:0;
+ op.add('\\');
+ op.add(sects[dp->unit_d.unit_type]);
+ op.add("*{");
+ do_add=1;
+ for (j=dp->unit_d.unit_type+1; j< (int) N(sects); j++)
+ dp->unit_d.unit_number[j]=0;
+ }
+ else
+ {
+ int i,n,c,l, unit;
+
+ unit=dp->unit_d.unit_type-1;
+ l=strlen(pt);
+ i=0;
+ while(1)
+ {
+ n=0;
+ for (c=0; i<l && isdigit(pt[i]); i++, c++)
+ n=n*10+pt[i]-'0';
+ if (c==0)
+ break;
+ unit++;
+ if (unit>= (int) N(sects))
+ {
+ unit=N(sects)-1;
+ break;
+ }
+ if (dp->unit_d.unit_number[unit]==-1)
+ {
+ if (n>MAX_START_NUM)
+ goto out_normal;
+
+ dp->unit_d.unit_number[unit]=n;
+ for (j=unit+1; j< (int) N(sects); j++)
+ dp->unit_d.unit_number[j]=0;
+ }
+ else if (dp->unit_d.unit_number[unit]+1==n)
+ {
+ dp->unit_d.unit_number[unit]++;
+ for (j=unit+1; j< (int) N(sects); j++)
+ dp->unit_d.unit_number[j]=0;
+ }
+ else if (dp->unit_d.unit_number[unit]!=n)
+ goto out_normal;
+
+ if (pt[i]!='.')
+ break;
+ i++;
+ }
+
+ if (unit==dp->unit_d.unit_type-1)
+ goto out_normal;
+ op.add('\\');
+ op.add(sects[unit]);
+ op.add((i>0) ? "{" : "*{");
+ while(isspace(pt[i])) i++;
+ pt+=i;
+ do_add=1;
+ }
+ }
+ out_normal: ;
+ }
+ dp->list_flg=0;
+ }
+
+ ts=map_string(pt, tex_map);
+ op.add(*ts);
+ if (do_add)
+ op.add('}');
+ delete(ts);
+
+ b=word_wrap(op, "\n", "\n", fmt->maxline, 0);
+ fputs((*b), out);
+ delete(b);
+}
+
+/* End of paragraph */
+static void end_para(const tok_seq::tok *tok, const docfmt *fmt, FILE *out,
+ void *d)
+{
+ struct latex_data *dp;
+
+ tok=tok;
+ fmt=fmt;
+ dp=(struct latex_data *) d;
+ dp->par_flg=0;
+
+ fputs("\n\n", out);
+}
+
+/* Start a table === allocate table and initialise */
+static void alloc_tbl(const tok_seq::tok *t, const docfmt *fmt, FILE *out,
+ void *d)
+{
+ struct latex_data *tdata;
+
+ out=out;
+ fmt=fmt;
+ tdata=(struct latex_data *) d;
+ tdata->col=0;
+ tdata->row=0;
+ tdata->tabl=new(latex_table)(t->data.table.cols, t->data.table.rows);
+ tdata->par_flg=0;
+}
+
+
+/* End of a table==print the table */
+static void format_tbl(const tok_seq::tok *t, const docfmt *fmt, FILE *out,
+ void *d)
+{
+ struct latex_data *tdata;
+
+ t=t;
+ tdata=(struct latex_data *) d;
+ tdata->tabl->print_table(fmt->maxline, out); // Print table
+ delete(tdata->tabl);
+ tdata->tabl=NULL;
+}
+
+/* start row==set column to 0 */
+static void start_row(const tok_seq::tok *t, const docfmt *fmt, FILE *out,
+ void *d)
+{
+ struct latex_data *tdata;
+
+ out=out;
+ fmt=fmt;
+ t=t;
+ tdata=(struct latex_data *) d;
+ tdata->col=0;
+}
+
+/* end row==add one to row */
+static void inc_row(const tok_seq::tok *t, const docfmt *fmt, FILE *out,
+ void *d)
+{
+ struct latex_data *tdata;
+
+ fmt=fmt;
+ t=t;
+ out=out;
+ tdata=(struct latex_data *) d;
+ tdata->row++;
+}
+
+
+/* Start field === set field */
+static void set_field(const tok_seq::tok *t, const docfmt *fmt, FILE *out,
+ void *d)
+{
+ struct latex_data *tdata;
+
+ tdata=(struct latex_data *) d;
+ out=out;
+ fmt=fmt;
+ tdata->tabl->set(tdata->col, tdata->row, t->data.d);
+}
+
+/* end field==add one to col */
+static void inc_col(const tok_seq::tok *t, const docfmt *fmt, FILE *out,
+ void *d)
+{
+ struct latex_data *tdata;
+
+ out=out;
+ fmt=fmt;
+ t=t;
+ tdata=(struct latex_data *) d;
+ tdata->col++;
+}
+
+/* pointers to the functions that do the work */
+docfmt latexfmt=
+{
+ { 0 }, // Ignore page breaks
+ 76, // Width
+ "\n", // Use \n as line ends
+ allocate_latex, // Allocate space
+ free_latex, // Free text
+ {
+ { preamble, postamble }, // End and start of document---do nothing
+ { fold_para, end_para }, // Paragraph
+ { alloc_tbl, format_tbl }, // Start/end table
+ { set_field, inc_col }, // Start/end field
+ { start_row, inc_row }, // Start/end row
+ { ltx_embed, null_proc }, // Throw away embed messages
+ { ltx_list, ltx_end_list }, // Start/end list
+ { ltx_item, null_proc }, // Start/end item
+ { ltx_code, null_proc }, // Codes end do not happen
+ { null_proc, null_proc } // Do not understanding anything else
+ }
+};