/* $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("",out);
fputs(dp->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
}
} ;