/* $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 #include #include #ifdef HAVE_UNISTD_H #include #endif /* HAVE_UNISTD_H */ #ifdef HAVE_CTYPE_H #include #endif /* HAVE_CTYPE_H */ #ifdef HAVE_SYS_STAT_H #include #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 (stpar_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)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= (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 } };