--- psiconv/trunk/program/psiconv/gen_html.c 1999/10/27 15:05:03 20 +++ psiconv/trunk/program/psiconv/gen_html.c 2004/01/26 21:56:49 190 @@ -1,349 +1,357 @@ -/* - gen_html.c - Part of psiconv, a PSION 5 file formats converter - Copyright (c) 1999 Frodo Looijaard - +/* gen_html.c - Part of psiconv, a PSION 5 file formats converter + Copyright (c) 1999-2004 Frodo Looijaard + This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. - + This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. - + You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ #include "config.h" -#include + +#include +#include +#include "general.h" + #include #include -#include "data.h" -#include "list.h" -#include "gen.h" - -/* This determines for each character how it is displayed */ -static const char *char_table[0x100] = -{ - /* 0x00 */ "" ,"" ,"" ,"" ,"" ,"" ,"

","
" , - /* 0x08 */ "

" ," " ,"" ,"" ,"" ,"" ,"" ,"" , - /* 0x10 */ " " ,"" ,"" ,"" ,"" ,"" ,"" ,"" , - /* 0x18 */ "" ,"" ,"" ,"" ,"" ,"" ,"" ,"" , - /* 0x20 */ " " ,"!" ,""","#" ,"$" ,"%" ,"&","'" , - /* 0x28 */ "(" ,")" ,"*" ,"+" ,"," ,"-" ,"." ,"/" , - /* 0x30 */ "0" ,"1" ,"2" ,"3" ,"4" ,"5" ,"6" ,"7" , - /* 0x38 */ "8" ,"9" ,":" ,";" ,"<" ,"=" ,">" ,"?" , - /* 0x40 */ "@" ,"A" ,"B" ,"C" ,"D" ,"E" ,"F" ,"G" , - /* 0x48 */ "H" ,"I" ,"J" ,"K" ,"L" ,"M" ,"N" ,"O" , - /* 0x50 */ "P" ,"Q" ,"R" ,"S" ,"T" ,"U" ,"V" ,"W" , - /* 0x58 */ "X" ,"Y" ,"Z" ,"[" ,"\\" ,"]" ,"^" ,"_" , - /* 0x60 */ "`" ,"a" ,"b" ,"c" ,"d" ,"e" ,"f" ,"g" , - /* 0x68 */ "h" ,"i" ,"j" ,"k" ,"l" ,"m" ,"n" ,"o" , - /* 0x70 */ "p" ,"q" ,"r" ,"s" ,"t" ,"u" ,"v" ,"w" , - /* 0x78 */ "x" ,"y" ,"z" ,"{" ,"|" ,"}" ,"~" ,"" , - /* 0x80 */ "" ,"","&sbquot;","ƒ","„","…", - "†","‡", - /* 0x88 */ "^","‰","Š","⟨","Œ","" ,"" ,"" , - /* 0x90 */ "","‘","’","“","”", - "·","&ndash","&mdash", - /* 0x98 */ "˜","™","š","⟩","œ","","","Ÿ", - /* 0xa0 */ "","¡","¢","£", - "¤","¥","¦","§", - /* 0xa8 */ ""","©","a","«","¬","-","®","¯on;", - /* 0xb0 */ "°","±","²","³", - "&rsquot;","µn;","¶","·", - /* 0xb8 */ ",","¹","°","»", - "¼","½","¾","¿", - /* 0xc0 */ "À","Á","Â","Ã", - "Ä","Å","Æ","Ç", - /* 0xc8 */ "È","É","Ê","Ë", - "Ì","Í","Î","Ï", - /* 0xd0 */ "Ð","Ñ","Ò","Ó", - "Ô","Õ","Ö","×", - /* 0xd8 */ "Ø","Ù","Ú","Û", - "Ü","Ý","Þ","ß", - /* 0xe0 */ "à","á","â","ã", - "ä","å","æ","ç", - /* 0xe8 */ "è","é","ê","ë", - "ì","í","î","ï", - /* 0xf0 */ "ð","ñ","ò","ó", - "ô","õ","ö","÷", - /* 0xf8 */ "ø","ù","ú","û", - "ü","ý","þ","ÿ" -}; - -static psiconv_character_layout gen_base_char(const psiconv_font font, - const psiconv_color color, - const psiconv_color back_color); -static void diff_char(FILE *of, const psiconv_character_layout old, - const psiconv_character_layout new, int *flags); -static void gen_para(FILE *of, const psiconv_paragraph para, - const psiconv_character_layout base_char); - -static void psiconv_gen_html_word(FILE *of,psiconv_word_f wf); -static void psiconv_gen_html_texted(FILE *of,psiconv_texted_f tf); - -/* This is not necessarily the same as returned by basic_character_layout_status - This one is specific for the base point of HTML */ -psiconv_character_layout gen_base_char(const psiconv_font font, - const psiconv_color color, - const psiconv_color back_color) + +#ifdef DMALLOC +#include "dmalloc.h" +#endif + +#define TEMPSTR_LEN 100 + +typedef enum output_type_e { output_html, output_xhtml } output_type; + +void character_layout_diffs(const psiconv_config config, psiconv_list list, + const psiconv_character_layout new, + const psiconv_character_layout base, + const encoding enc) { - struct psiconv_character_layout base_char_struct = - { - NULL, /* color */ - NULL, /* back_color */ - 13.0, /* font_size */ - psiconv_bool_false, /* italic */ - psiconv_bool_false, /* bold */ - psiconv_normalscript, /* super_sub */ - psiconv_bool_false, /* underline */ - psiconv_bool_false, /* strike_out */ - NULL, /* font */ - }; - base_char_struct.color = color; - base_char_struct.back_color = back_color; - base_char_struct.font = font; - return psiconv_clone_character_layout(&base_char_struct); + if (new->italic != base->italic) { + output_simple_chars(config,list,"font-style:",enc); + output_simple_chars(config,list,new->italic?"italic":"normal",enc); + output_simple_chars(config,list,";",enc); + } + if ((new->underline != base->underline) || + (new->strikethrough != base->strikethrough)) { + output_simple_chars(config,list,"text-decoration:",enc); + output_simple_chars(config,list,new->underline?"underline": + new->strikethrough?"line-through": + "none",enc); + output_simple_chars(config,list,";",enc); + } + if (new->bold != base->bold) { + output_simple_chars(config,list,"font-weight:",enc); + output_simple_chars(config,list,new->bold?"bold":"normal",enc); + output_simple_chars(config,list,";",enc); + } + if (new->super_sub != base->super_sub) { + output_simple_chars(config,list,"font-style:",enc); + output_simple_chars(config,list, + new->super_sub==psiconv_superscript?"super": + new->super_sub==psiconv_subscript?"sub": + "normal",enc); + output_simple_chars(config,list,";",enc); + } } -/* flags & 1: 0 if no was yet generated. - flags & 2: 1 if at end-of-paragraph -*/ -void diff_char(FILE *of, const psiconv_character_layout old, - const psiconv_character_layout new, - int *flags) -{ - int font_set = 0; - - if ((old->font_size != new->font_size) || - (old->color->red != new->color->red) || - (old->color->green != new->color->green) || - (old->color->blue != new->color->blue) || - (strcmp(old->font->name,new->font->name)) || - (old->font->screenfont != new->font->screenfont) || - ((*flags & 0x03) == 3)) { - if (old->italic) - fputs("",of); - if (old->bold) - fputs("",of); - if (old->underline) - fputs("",of); - if (old->strike_out) - fputs("",of); - if (old->super_sub == psiconv_superscript) - fputs("",of); - if (old->super_sub == psiconv_subscript) - fputs("",of); - if ((*flags & 1) == 1) - fputs("",of); - if ((*flags & 2) == 0) { - *flags |= 1; - fputs("font_size <= 10.0) - fputs("2",of); - else if (new->font_size <= 12.0) - fputs("3",of); - else if (new->font_size <= 14.0) - fputs("4",of); - else if (new->font_size <= 18.0) - fputs("5",of); - else if (new->font_size <= 24.0) - fputs("6",of); - else - fputs("7",of); - fprintf(of," COLOR=#%02x%02x%02x",new->color->red,new->color->green, - new->color->blue); - if (new->font->screenfont == 1) - fprintf(of," FACE=\"%s, Sans-Serif\">",new->font->name); - else if (new->font->screenfont == 2) - fprintf(of," FACE=\"%s, Monospace\">",new->font-> name); - else if (new->font->screenfont == 3) - fprintf(of," FACE=\"%s, Serif\">",new->font-> name); - else - fprintf(of," FACE=\"%s, Serif\">",new->font-> name); - } - if (new->italic) - fputs("",of); - if (new->bold) - fputs("",of); - if (new->underline) - fputs("",of); - if (new->strike_out) - fputs("",of); - if (new->super_sub == psiconv_superscript) - fputs("",of); - if (new->super_sub == psiconv_subscript) - fputs("",of); - } else { - if (font_set || (old->italic != new->italic)) { - if (old->italic) - fputs("",of); - else - fputs("",of); - } - if (old->bold != new->bold) { - if (old->bold) - fputs("",of); - else - fputs("",of); - } - if (old->underline != new->underline) { - if (old->underline) - fputs("",of); - else - fputs("",of); - } - if (old->strike_out != new->strike_out) { - if (old->strike_out) - fputs("",of); - else - fputs("",of); - } - if (old->super_sub != new->super_sub) { - if (old->super_sub == psiconv_superscript) - fputs("",of); - else if (old->super_sub == psiconv_subscript) - fputs("",of); - if (new->super_sub == psiconv_superscript) - fputs("",of); - else if (new->super_sub == psiconv_subscript) - fputs("",of); - } - } +void paragraph_layout_diffs(const psiconv_config config, psiconv_list list, + const psiconv_paragraph_layout new, + const psiconv_paragraph_layout base) +{ } -void gen_para(FILE *of, const psiconv_paragraph para, - const psiconv_character_layout base_char) +void header(const psiconv_config config, psiconv_list list, + output_type type, const encoding enc) { - int i,j,loc; - psiconv_character_layout cur_char; - psiconv_in_line_layout inl; - int flags = 0; - - - fputs("base_paragraph->justify_hor == psiconv_justify_left) - fputs(" ALIGN=left",of); - else if (para->base_paragraph->justify_hor == psiconv_justify_right) - fputs(" ALIGN=right",of); - else if (para->base_paragraph->justify_hor == psiconv_justify_centre) - fputs(" ALIGN=center",of); - else if (para->base_paragraph->justify_hor == psiconv_justify_full) - fputs(" ALIGN=left",of); - fputs(">",of); - if (para->base_paragraph->bullet->on) - fputs("

  • ",of); + if (type == output_xhtml) + output_simple_chars(config,list, + "\n",enc); + output_simple_chars(config,list,"": + "\"http://www.w3.org/TR/html4/strict.dtd\">",enc); + output_simple_chars(config,list,"\n\n",enc); + output_simple_chars(config,list,"\n",enc); + output_simple_chars(config,list,"\n",enc); + output_simple_chars(config,list,"\n",enc); + output_simple_chars(config,list,"EPOC32 file " + "converted by psiconv\n",enc); + output_simple_chars(config,list,"\n",enc); + output_simple_chars(config,list,"\n",enc); +} - cur_char = base_char; +void footer(const psiconv_config config, psiconv_list list, + output_type type, const encoding enc) +{ + output_simple_chars(config,list,"\n",enc); + output_simple_chars(config,list,"\n",enc); +} - if (psiconv_list_length(para->in_lines) == 0) { - diff_char(of,cur_char,para->base_character,&flags); - cur_char = para->base_character; +void color(const psiconv_config config, psiconv_list list, + psiconv_color color, output_type type, const encoding enc) +{ + char tempstr[TEMPSTR_LEN]; + if ((color->red == 0xff) && + (color->blue == 0xff) && + (color->green == 0xff)) + output_simple_chars(config,list,"transparant",enc); + else { + snprintf(tempstr,TEMPSTR_LEN,"rgb(%d,%d,%d)", + color->red, + color->green, + color->blue); + output_simple_chars(config,list,tempstr,enc); } - loc = 0; +} - for (i = 0; i < psiconv_list_length(para->in_lines); i++) { - inl = psiconv_list_get(para->in_lines,i); - diff_char(of,cur_char,inl->layout,&flags); - cur_char = inl->layout; - for (j = loc; j < inl->length + loc; j ++) { - fputs(char_table[(unsigned char) (para->text[j])],of); - } - loc = j; +void charlayout(const psiconv_config config, psiconv_list list, + psiconv_string_t text,psiconv_character_layout layout, + output_type type, const encoding enc) +{ + char tempstr[TEMPSTR_LEN]; + if (layout->italic) + output_simple_chars(config,list,"",enc); + if (layout->bold) + output_simple_chars(config,list,"",enc); + if (layout->super_sub != psiconv_normalscript) + output_simple_chars(config,list, + layout->super_sub == psiconv_superscript?"": + layout->super_sub == psiconv_subscript?"": + "",enc); + + output_simple_chars(config,list,"underline || layout->strikethrough) { + output_simple_chars(config,list,"text-decoration:",enc); + output_simple_chars(config,list,layout->underline?"underline": + layout->strikethrough?"line-through": + "",enc); + output_simple_chars(config,list,";",enc); } - if (loc < strlen(para->text)) { - diff_char(of,cur_char,para->base_character,&flags); - cur_char = para->base_character; - for (j = loc; j < strlen(para->text); j ++) { - fputs(char_table[(unsigned char) (para->text[j])],of); + output_simple_chars(config,list,"color:",enc); + color(config,list,layout->color,type,enc); + output_simple_chars(config,list,";",enc); + + output_simple_chars(config,list,"background-color:",enc); + color(config,list,layout->back_color,type,enc); + output_simple_chars(config,list,";",enc); + + output_simple_chars(config,list,"font-size:",enc); + snprintf(tempstr,TEMPSTR_LEN,"%f",layout->font_size); + output_simple_chars(config,list,tempstr,enc); + output_simple_chars(config,list,"pt;",enc); + + output_simple_chars(config,list,"\">",enc); + + output_string(config,list,text,enc); + + output_simple_chars(config,list,"",enc); + if (layout->super_sub != psiconv_normalscript) + output_simple_chars(config,list, + layout->super_sub == psiconv_superscript?"": + layout->super_sub == psiconv_subscript?"": + "",enc); + if (layout->bold) + output_simple_chars(config,list,"",enc); + if (layout->italic) + output_simple_chars(config,list,"",enc); +} + +void paragraph(const psiconv_config config, psiconv_list list, + psiconv_paragraph para,output_type type, + const encoding enc) +{ + char tempstr[TEMPSTR_LEN]; + int i,charnr; + psiconv_string_t text; + psiconv_in_line_layout layout; + + output_simple_chars(config,list,"

    base_paragraph->back_color,type,enc); + output_simple_chars(config,list,";",enc); + + output_simple_chars(config,list,"padding-left:",enc); + snprintf(tempstr,TEMPSTR_LEN,"%f",para->base_paragraph->indent_left); + output_simple_chars(config,list,tempstr,enc); + output_simple_chars(config,list,"cm;",enc); + + output_simple_chars(config,list,"padding-right:",enc); + snprintf(tempstr,TEMPSTR_LEN,"%f",para->base_paragraph->indent_right); + output_simple_chars(config,list,tempstr,enc); + output_simple_chars(config,list,"cm;",enc); + + output_simple_chars(config,list,"text-indent:",enc); + snprintf(tempstr,TEMPSTR_LEN,"%f",para->base_paragraph->indent_left - para->base_paragraph->indent_first); + output_simple_chars(config,list,tempstr,enc); + output_simple_chars(config,list,"cm;",enc); + + output_simple_chars(config,list,"text-align:",enc); + output_simple_chars(config,list,para->base_paragraph->justify_hor==psiconv_justify_left?"left": + para->base_paragraph->justify_hor==psiconv_justify_centre?"center": + para->base_paragraph->justify_hor==psiconv_justify_right?"right": + para->base_paragraph->justify_hor==psiconv_justify_full?"justify": + "",enc); + output_simple_chars(config,list,";",enc); + + + output_simple_chars(config,list,"line-height:",enc); + snprintf(tempstr,TEMPSTR_LEN,"%f",para->base_paragraph->linespacing); + output_simple_chars(config,list,tempstr,enc); + output_simple_chars(config,list,"pt;",enc); + + output_simple_chars(config,list,"padding-top:",enc); + snprintf(tempstr,TEMPSTR_LEN,"%f",para->base_paragraph->space_above); + output_simple_chars(config,list,tempstr,enc); + output_simple_chars(config,list,"pt;",enc); + + output_simple_chars(config,list,"padding-bottom:",enc); + snprintf(tempstr,TEMPSTR_LEN,"%f",para->base_paragraph->space_below); + output_simple_chars(config,list,tempstr,enc); + output_simple_chars(config,list,"pt;",enc); + + output_simple_chars(config,list,"\">",enc); + + if (psiconv_list_length(para->in_lines) == 0) { + charlayout(config,list,para->text,para->base_character,type,enc); + } else { + charnr = 0; + for (i = 0; i < psiconv_list_length(para->in_lines); i++) { + if (!(layout = psiconv_list_get(para->in_lines,i))) { + fputs("Internal data structures corruption\n",stderr); + exit(1); + } + if (!(text = malloc(sizeof (*text) * (layout->length + 1)))) { + fputs("Out of memory error\n",stderr); + exit(1); + } + memcpy(text,para->text+charnr,layout->length * sizeof(*text)); + text[layout->length] = 0; + charlayout(config,list,text,layout->layout,type,enc); + free(text); + charnr += layout->length; } } + output_simple_chars(config,list,"

    \n",enc); +} - if (strlen(para->text) == 0) - fputs("
    ",of); +void paragraphs(const psiconv_config config, psiconv_list list, + psiconv_text_and_layout paragraphs,output_type type, + const encoding enc) +{ + int i; + psiconv_paragraph para; + for (i = 0; i < psiconv_list_length(paragraphs); i++) { + if (!(para = psiconv_list_get(paragraphs,i))) { + fputs("Internal datastructure corruption\n",stderr); + exit(1); + } + paragraph(config,list,para,type,enc); + } +} - flags |= 2; - diff_char(of,cur_char,base_char,&flags); +void gen_html_word(const psiconv_config config, psiconv_list list, + const psiconv_word_f file, output_type type, + const encoding enc) +{ + if (!file) + return; - if (para->base_paragraph->bullet->on) - fputs("
",of); - - fputs("

\n",of); + header(config,list,type,enc); + paragraphs(config,list,file->paragraphs,type,enc); + footer(config,list,type,enc); } -void psiconv_gen_html(FILE *of,psiconv_file file) + +void gen_html_texted(const psiconv_config config, psiconv_list list, + const psiconv_texted_f file, output_type type, + const encoding enc) { - if (file->type == psiconv_word_file) - psiconv_gen_html_word(of,(psiconv_word_f) file->file); - else if (file->type == psiconv_texted_file) - psiconv_gen_html_texted(of,(psiconv_texted_f) file->file); - else - return; + header(config,list,type,enc); + paragraphs(config,list,file->texted_sec->paragraphs,type,enc); + footer(config,list,type,enc); } -void psiconv_gen_html_texted(FILE *of,psiconv_texted_f tf) +int gen_html(const psiconv_config config, psiconv_list list, + const psiconv_file file, const char *dest, + const encoding enc) { - psiconv_character_layout base_char; - psiconv_paragraph para; - int i; + output_type type; - /* We have nothing better */ - base_char = psiconv_basic_character_layout(); + if (!strcmp("HTML4",dest)) + type = output_html; + else if (!strcmp("XHTML",dest)) + type = output_xhtml; + else + return -1; - fputs("", of); - fputs("\n\n\n \n", of); - fputs("\n",of); - for (i = 0; i < psiconv_list_length(tf->texted_sec->paragraphs); i++) { - para = psiconv_list_get(tf->texted_sec->paragraphs,i); - gen_para(of,para,base_char); + if (enc == ENCODING_PSION) { + fputs("Unsupported encoding\n",stderr); + return -1; } - fputs("\n\n",of); - psiconv_free_character_layout(base_char); + + if (file->type == psiconv_word_file) { + gen_html_word(config,list,(psiconv_word_f) file->file,type,enc); + return 0; + } else if (file->type == psiconv_texted_file) { + gen_html_texted(config,list,(psiconv_texted_f) file->file,type, enc); + return 0; + } else + return -1; } + + +static struct fileformat_s ffs[] = + { + { + "XHTML", + "XHTML 1.0 Strict, using CSS for formatting", + gen_html + }, + { + "HTML4", + "HTML 4.01 Strict, using CSS for formatting", + gen_html + }, + { + NULL, + NULL, + NULL + } + }; -void psiconv_gen_html_word(FILE *of,psiconv_word_f wf) +void init_html(void) { int i; - psiconv_paragraph para; - psiconv_color white,black; - psiconv_character_layout base_char; - - white = malloc(sizeof(*white)); - black = malloc(sizeof(*black)); - white->red = 0x00; - white->green = 0x00; - white->blue = 0x00; - black->red = 0xff; - black->green = 0xff; - black->blue = 0xff; - - /* To keep from generating a font desc for each line */ - base_char = gen_base_char(wf->styles_sec->normal->character->font, - black,white); - - psiconv_free_color(black); - psiconv_free_color(white); - - fputs("", of); - fputs("\n\n\n \n", of); - fputs("\n",of); - - for (i = 0; i < psiconv_list_length(wf->paragraphs); i++) { - para = psiconv_list_get(wf->paragraphs,i); - gen_para(of,para,base_char); - } - fputs("\n\n",of); - psiconv_free_character_layout(base_char); + for (i = 0; ffs[i].name; i++) + psiconv_list_add(fileformat_list,ffs+i); } - -