/* $Id: html-fmt.cc,v 1.1 1997/04/23 00:45:06 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 "html-table.h" #include "fmt-html.h" static const cmap html_map[]= { { '\n', "
\n" }, // Newline { 0x1E, "-" }, // Unbreakable join { 0x1F, "\\-" }, // Soft hypen { '<', "<" }, // # { '>', ">" }, // $ { '&', "&" }, // & { 0x85, "..." }, // 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, "(TM)" }, // Trademark { 0xA0, " " }, // Unbreakable space { 0xA3, "<=" }, // <= came out as A3, also pounds { 0xA9, "(C)" }, // Copyright { 0xAB, "<<" }, // Openning << quotes (25th element) { 0xAE, "(R)" }, // reserved sign { 0xB3, ">=" }, // Greater than or = came out as B3 { 0xBB, ">>" }, // Closing >> quotes (28th element) { 0xDF, "ß" }, // beta { 0xE4, "ä" }, // a with umlualt { 0xE9, "è" }, // e grave?? { 0xF1, "&ntidle" }, // n bar { 0xF6, "ö" }, // o with umlualt { 0xFA, "\\.u" }, // u with dot? { 0xFC, "ü" }, // u with umlualt. }; tblock *__html_do_map(const char *s) { tblock *out; out = map_string(s, html_map); return out; } /* Preamble */ static void h_preamble(const tok_seq::tok *t, const docfmt *fmt, FILE *out, void *d) { time_t now; struct stat st; char *tnow, *tdoc; t=t; d=d; now=time(NULL); tnow=(fmt->date)(now); if (fstat(fileno(out), &st)==-1) st.st_mtime=now; tdoc=fmt->date(st.st_mtime); fprintf(out, "\n" "\n" "\n" "\n" " Word document from %s" "\n" "\n", tnow, tdoc); free(tnow); free(tdoc); } /* Postamble */ static void h_postamble(const tok_seq::tok *t, const docfmt *fmt, FILE *out, void *d) { struct html_data *dp; fmt=fmt; t=t; dp=(struct html_data *) d; fputs("\n", out); } /* Allocate local data */ static void *allocate_html(void) { struct html_data *tdata; int i; tdata = new(struct html_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_html(void *d) { struct html_data *tdata; tdata=(struct html_data *) d; if (tdata->tabl!=NULL) delete(tdata->tabl); } static void html_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
\n", out); break; default: break; } } struct list_info { const char *ltype; // List type from reader const char *start; // Start tag const char *end; // End tag }; static const struct list_info *ltype_info(const char *type) { static const struct list_info list_inf[]= { { "listAlpha", "
    ", "
" }, // Netscape extension { "listalpha", "
    ", "
" }, // Netscape extension { "enumerate", "
    ", "
" }, // Standard { "itemize", "
    ", "
" }, // Standard }; unsigned i; for (i=0; ilist_flg=1; } /* start list, have to convert from *TeX types... */ static void html_list(const tok_seq::tok *t, const docfmt *fmt, FILE *out, void *d) { const struct list_info *linf; const char *s; fmt=fmt; d=d; linf=ltype_info(t->data.d); if (linf==NULL) { cerr<<"Unknown list type "<data.d<<" treated as bulleted list\n"; s="
    "; } else { s=linf->start; } fprintf(out, "\n%s\n", s); } /* end list, have to convert from *TeX types... */ static void html_end_list(const tok_seq::tok *t, const docfmt *fmt, FILE *out, void *d) { const struct list_info *linf; const char *s; fmt=fmt; d=d; fmt=fmt; d=d; linf=ltype_info(t->data.d); if (linf==NULL) { cerr<<"Unknown list type "<data.d<<" treated as bulleted list\n"; s="
"; } else s=linf->end; fprintf(out, "\n%s\n", s); } /* * 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, *unit_html="P"; struct html_data *dp; int has_num, i, j; struct unit_number u_num; static const char *const sects[]= { "H1", "H2", "H3", "H4" }; static const char *const sects_english[]= { "chapter", "section", "subsection", "subsubsection" }; dp = (struct html_data *) d; /* Even this much is under 100%!! */ pt=(tok->data.d); if (*pt=='\0' && dp->list_flg==1) return; if (dp->last_tc != NULL) { if (strcmp(dp->last_tc, pt)==0) { unit_html=sects[dp->unit_d.unit_type]; } 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_english); i++) { if (strncasecmp(dp->last_tc, sects_english[i], strlen(sects_english[i]))==0) break; } t = dp->last_tc+strlen(sects_english[i]); has_num = get_part_num(t,s); unit_html=sects[i]; // Set the section type /* Update the control data */ 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; } } free((void *) dp->last_tc); dp->last_tc=NULL; } else { if (dp->list_flg) { op.add("
  • "); } else { if (strlen(pt)>0 && strlen(pt)unit_d.unit_type= (dp->unit_d.unit_number[0]==-1) ? 1 : 0; /* Output the heading level */ unit_html=sects[dp->unit_d.unit_type]; 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; for (j=dp->unit_d.unit_type+1; j<(int) N(sects); j++) dp->unit_d.unit_number[j]=0; } else { u_num=n_unit_probe(pt, &(dp->unit_d)); if (u_num.unit_num!=-1) { i=u_num.offset; unit_html=sects[u_num.unit_num]; } } } } dp->list_flg=0; } /* Record the unit type started */ dp->unit_html=unit_html; /* Insert the start tag and eneter paragraoh if not in one */ if (!dp->par_flg) { dp->par_flg = 1; op.add("<"); op.add(unit_html); op.add('>'); } /* Add the text */ ts = map_string(pt, html_map); op.add(*ts); delete(ts); /* fold the line */ b = word_wrap(op, "\n", "\n", fmt->maxline, 0); fputs((*b), out); delete(b); } /* End of paragraph, outputs the end tag */ static void end_para(const tok_seq::tok *tok, const docfmt *fmt, FILE *out, void *d) { struct html_data *dp; tok=tok; fmt=fmt; dp=(struct html_data *) d; dp->par_flg=0; fputs("unit_html, out); 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 html_data *tdata; out=out; fmt=fmt; tdata=(struct html_data *) d; tdata->col=0; tdata->row=0; tdata->tabl=new(html_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 html_data *tdata; t=t; tdata=(struct html_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 html_data *tdata; out=out; fmt=fmt; t=t; tdata=(struct html_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 html_data *tdata; fmt=fmt; t=t; out=out; tdata=(struct html_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 html_data *tdata; tdata=(struct html_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 html_data *tdata; out=out; fmt=fmt; t=t; tdata=(struct html_data *) d; tdata->col++; } /* pointers to the functions that do the work */ docfmt htmlfmt= { { 1 }, // Keep page breaks 76, // Width "\n", // Use \n as line ends allocate_html, // Allocate space free_html, // Free text { { h_preamble, h_postamble }, // End and start of document { 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 { html_embed, null_proc }, // Throw away embed messages { html_list, html_end_list }, // Start/end list { html_item, null_proc }, // Start/end item { html_code, null_proc }, // Code ends do not occur { null_proc, null_proc } // Do not understanding anything else } } ;