--- psiconv/trunk/program/psiconv/gen_xhtml.c 2004/01/26 21:56:49 190 +++ psiconv/trunk/program/psiconv/gen_xhtml.c 2005/11/15 14:41:26 267 @@ -21,9 +21,11 @@ #include #include #include "general.h" +#include "gen.h" #include #include +#include #ifdef DMALLOC #include "dmalloc.h" @@ -31,6 +33,76 @@ #define TEMPSTR_LEN 100 +static void text(const psiconv_config config,psiconv_list list, + psiconv_string_t data,const encoding enc); +static void color(const psiconv_config config, psiconv_list list, + psiconv_color color,int may_be_transparant, const encoding enc); +static void border(const psiconv_config config, psiconv_list list, + psiconv_border_kind_t border,const encoding enc); +static void style_name(const psiconv_config config, psiconv_list list, + const psiconv_string_t name,const encoding enc); +static int character_layout_equal(const psiconv_character_layout l1, + const psiconv_character_layout l2); +static void character_layout_diffs(const psiconv_config config, + psiconv_list list, + const psiconv_character_layout new, + const psiconv_character_layout base, + const encoding enc); +static void paragraph_layout_diffs(const psiconv_config config, + psiconv_list list, + const psiconv_paragraph_layout new, + const psiconv_paragraph_layout base, + const encoding enc); +static void style(const psiconv_config config, psiconv_list list, + const psiconv_word_style style, + const psiconv_paragraph_layout base_para, + const psiconv_character_layout base_char, + const encoding enc); +static void styles(const psiconv_config config, psiconv_list list, + const psiconv_word_styles_section styles_sec,const encoding enc); +static void header(const psiconv_config config, psiconv_list list, + const psiconv_word_styles_section styles_sec,const encoding enc); +static void footer(const psiconv_config config, psiconv_list list, + const encoding enc); +static void characters(const psiconv_config config, psiconv_list list, + const psiconv_string_t textstr, + const psiconv_character_layout layout, + const psiconv_character_layout base, + const encoding enc); +static void paragraphs(const psiconv_config config, psiconv_list list, + psiconv_text_and_layout paragraphs, + const psiconv_word_styles_section styles, + const encoding enc); +static void paragraph(const psiconv_config config, psiconv_list list, + const psiconv_paragraph para, + const psiconv_word_styles_section styles_sec, + const encoding enc); +static void gen_word(const psiconv_config config, psiconv_list list, + const psiconv_word_f file, const encoding enc); +static void gen_texted(const psiconv_config config, psiconv_list list, + const psiconv_texted_f file, const encoding enc); +static int gen_xhtml(const psiconv_config config, psiconv_list list, + const psiconv_file file, const char *dest, + const encoding enc); + + + +void text(const psiconv_config config,psiconv_list list, + psiconv_string_t data,const encoding enc) +{ + int i; + for (i = 0; i < psiconv_unicode_strlen(data); i++) { + if ((data[i] == 0x06) || (data[i] == 0x07) || (data[i] == 0x08)) + output_simple_chars(config,list,"
",enc); + else if ((data[i] == 0x0b) || (data[i] == 0x0c)) + output_simple_chars(config,list,"-",enc); + else if ((data[i] == 0x0f) || (data[i] == 0x09) || (data[i] == 0x0a)) + output_simple_chars(config,list," ",enc); + else if (data[i] >= 0x20) + output_char(config,list,data[i],enc); + } +} + void color(const psiconv_config config, psiconv_list list, psiconv_color color,int may_be_transparant, const encoding enc) { @@ -49,6 +121,19 @@ } } +void border(const psiconv_config config, psiconv_list list, + psiconv_border_kind_t border,const encoding enc) +{ + output_simple_chars(config,list, + border == psiconv_border_none?"none": + border == psiconv_border_solid?"solid": + border == psiconv_border_double?"double": + border == psiconv_border_dotted?"dotted": + border == psiconv_border_dashed?"dashed": + border == psiconv_border_dotdashed?"dashed": + border == psiconv_border_dotdotdashed?"dashed":"",enc); +} + void style_name(const psiconv_config config, psiconv_list list, const psiconv_string_t name,const encoding enc) { @@ -71,6 +156,26 @@ free(name_copy); } +/* Check whether the same layout information would be generated */ +int character_layout_equal(const psiconv_character_layout l1, + const psiconv_character_layout l2) +{ + return (l1 && l2 && + (l1->color->red == l2->color->red) && + (l1->color->green == l2->color->green) && + (l1->color->blue == l2->color->blue) && + (l1->back_color->red == l2->back_color->red) && + (l1->back_color->green == l2->back_color->green) && + (l1->back_color->blue == l2->back_color->blue) && + (l1->font_size == l2->font_size) && + (l1->italic == l2->italic) && + (l1->bold == l2->bold) && + (l1->super_sub == l2->super_sub) && + (l1->underline == l2->underline) && + (l1->strikethrough == l2->strikethrough) && + (l1->font->screenfont == l2->font->screenfont)); +} + void character_layout_diffs(const psiconv_config config, psiconv_list list, const psiconv_character_layout new, const psiconv_character_layout base, @@ -78,33 +183,6 @@ { char tempstr[TEMPSTR_LEN]; - if (!base || (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 (!base || (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 (!base || (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 (!base || (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); - } - if (!base || (new->color->red != base->color->red) || (new->color->green != base->color->green) || (new->color->blue != base->color->blue)) { @@ -127,6 +205,42 @@ output_simple_chars(config,list,tempstr,enc); output_simple_chars(config,list,"pt;",enc); } + + if (!base || (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 (!base || (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 (!base || (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); + } + if (!base || (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 (!base || (new->font->screenfont != base->font->screenfont)) { + output_simple_chars(config,list,"font-family:",enc); + output_simple_chars(config,list, + new->font->screenfont == psiconv_font_serif?"serif": + new->font->screenfont == psiconv_font_sansserif?"sans-serif": + new->font->screenfont == psiconv_font_nonprop?"monospace": + new->font->screenfont == psiconv_font_misc?"fantasy":"", + enc); + } } void paragraph_layout_diffs(const psiconv_config config, psiconv_list list, @@ -135,6 +249,27 @@ const encoding enc) { char tempstr[TEMPSTR_LEN]; + float pad_left_base=0.0,pad_left_new,text_indent_base=0.0,text_indent_new; + + if (new->bullet->on) { + pad_left_new = new->indent_left < new->indent_first? + new->indent_left:new->indent_first; + text_indent_new = 0.0; + } else { + pad_left_new = new->indent_left; + text_indent_new = new->indent_first; + } + if (base) { + if (base->bullet->on) { + pad_left_base = base->indent_left < base->indent_first? + base->indent_left:base->indent_first; + text_indent_base = 0.0; + } else { + pad_left_base = base->indent_left; + text_indent_base = base->indent_first; + } + } + if (!base || (new->back_color->red != base->back_color->red) || (new->back_color->green != base->back_color->green) || @@ -144,9 +279,9 @@ output_simple_chars(config,list,";",enc); } - if (!base || (new->indent_left != base->indent_left)) { + if (!base || (pad_left_new != pad_left_base)) { output_simple_chars(config,list,"padding-left:",enc); - snprintf(tempstr,TEMPSTR_LEN,"%f",new->indent_left); + snprintf(tempstr,TEMPSTR_LEN,"%f",pad_left_new); output_simple_chars(config,list,tempstr,enc); output_simple_chars(config,list,"cm;",enc); } @@ -158,10 +293,9 @@ output_simple_chars(config,list,"cm;",enc); } - if (!base || (new->indent_left - new->indent_first != - base->indent_left - base->indent_first)) { + if (!base || (text_indent_new != text_indent_base)) { output_simple_chars(config,list,"text-indent:",enc); - snprintf(tempstr,TEMPSTR_LEN,"%f",new->indent_right - new->indent_first); + snprintf(tempstr,TEMPSTR_LEN,"%f",text_indent_new); output_simple_chars(config,list,tempstr,enc); output_simple_chars(config,list,"cm;",enc); } @@ -177,12 +311,15 @@ output_simple_chars(config,list,";",enc); } +#if 0 + /* This gave bad output... */ if (!base || (new->linespacing != base->linespacing)) { output_simple_chars(config,list,"line-height:",enc); snprintf(tempstr,TEMPSTR_LEN,"%f",new->linespacing); output_simple_chars(config,list,tempstr,enc); output_simple_chars(config,list,"pt;",enc); } +#endif if (!base || (new->space_above != base->space_above)) { output_simple_chars(config,list,"padding-top:",enc); @@ -197,7 +334,97 @@ output_simple_chars(config,list,tempstr,enc); output_simple_chars(config,list,"pt;",enc); } - + + if (!base || (new->right_border->kind != base->right_border->kind)) { + output_simple_chars(config,list,"border-right-style:",enc); + border(config,list,new->right_border->kind,enc); + output_simple_chars(config,list,";",enc); + } + if (!base || (new->bottom_border->kind != base->bottom_border->kind)) { + output_simple_chars(config,list,"border-bottom-style:",enc); + border(config,list,new->bottom_border->kind,enc); + output_simple_chars(config,list,";",enc); + } + if (!base || (new->top_border->kind != base->top_border->kind)) { + output_simple_chars(config,list,"border-top-style:",enc); + border(config,list,new->top_border->kind,enc); + output_simple_chars(config,list,";",enc); + } + if (!base || (new->left_border->kind != base->left_border->kind)) { + output_simple_chars(config,list,"border-left-style:",enc); + border(config,list,new->left_border->kind,enc); + output_simple_chars(config,list,";",enc); + } + + if (!base || + ((new->right_border->kind != psiconv_border_none) && + (new->right_border->thickness != base->right_border->thickness))) { + output_simple_chars(config,list,"border-right-width:",enc); + snprintf(tempstr,TEMPSTR_LEN,"%f",new->right_border->thickness); + output_simple_chars(config,list,tempstr,enc); + output_simple_chars(config,list,"pt;",enc); + } + if (!base || + ((new->bottom_border->kind != psiconv_border_none) && + (new->bottom_border->thickness != base->bottom_border->thickness))) { + output_simple_chars(config,list,"border-bottom-width:",enc); + snprintf(tempstr,TEMPSTR_LEN,"%f",new->bottom_border->thickness); + output_simple_chars(config,list,tempstr,enc); + output_simple_chars(config,list,"pt;",enc); + } + if (!base || + ((new->top_border->kind != psiconv_border_none) && + ( new->top_border->thickness != base->top_border->thickness))) { + output_simple_chars(config,list,"border-top-width:",enc); + snprintf(tempstr,TEMPSTR_LEN,"%f",new->top_border->thickness); + output_simple_chars(config,list,tempstr,enc); + output_simple_chars(config,list,"pt;",enc); + } + if (!base || + ((new->left_border->kind != psiconv_border_none) && + (new->left_border->thickness != base->left_border->thickness))) { + output_simple_chars(config,list,"border-left-width:",enc); + snprintf(tempstr,TEMPSTR_LEN,"%f",new->left_border->thickness); + output_simple_chars(config,list,tempstr,enc); + output_simple_chars(config,list,"pt;",enc); + } + + if (!base || + ((new->right_border->kind != psiconv_border_none) && + ((new->right_border->color->red != base->right_border->color->red) || + (new->right_border->color->green != base->right_border->color->green)|| + (new->right_border->color->blue != base->right_border->color->blue)))) { + output_simple_chars(config,list,"border-right-color:",enc); + color(config,list,new->right_border->color,0,enc); + output_simple_chars(config,list,";",enc); + } + if (!base || + ((new->top_border->kind != psiconv_border_none) && + ((new->top_border->color->red != base->top_border->color->red) || + (new->top_border->color->green != base->top_border->color->green) || + (new->top_border->color->blue != base->top_border->color->blue)))) { + output_simple_chars(config,list,"border-top-color:",enc); + color(config,list,new->top_border->color,0,enc); + output_simple_chars(config,list,";",enc); + } + if (!base || + ((new->bottom_border->kind != psiconv_border_none) && + ((new->bottom_border->color->red != base->bottom_border->color->red) || + (new->bottom_border->color->green !=base->bottom_border->color->green)|| + (new->bottom_border->color->blue != base->bottom_border->color->blue)))){ + output_simple_chars(config,list,"border-bottom-color:",enc); + color(config,list,new->bottom_border->color,0,enc); + output_simple_chars(config,list,";",enc); + } + if (!base || + ((new->left_border->kind != psiconv_border_none) && + ((new->left_border->color->red != base->left_border->color->red) || + (new->left_border->color->green != base->left_border->color->green) || + (new->left_border->color->blue != base->left_border->color->blue)))) { + output_simple_chars(config,list,"border-left-color:",enc); + color(config,list,new->left_border->color,0,enc); + output_simple_chars(config,list,";",enc); + } } void style(const psiconv_config config, psiconv_list list, @@ -206,9 +433,9 @@ const psiconv_character_layout base_char, const encoding enc) { - output_simple_chars(config,list,"p[class=\"style_",enc); + output_simple_chars(config,list,"*.style_",enc); style_name(config,list,style->name,enc); - output_simple_chars(config,list,"\"] {",enc); + output_simple_chars(config,list," {",enc); paragraph_layout_diffs(config,list,style->paragraph,base_para,enc); character_layout_diffs(config,list,style->character,base_char,enc); output_simple_chars(config,list,"}\n",enc); @@ -293,7 +520,7 @@ } void characters(const psiconv_config config, psiconv_list list, - const psiconv_string_t text, + const psiconv_string_t textstr, const psiconv_character_layout layout, const psiconv_character_layout base, const encoding enc) @@ -315,7 +542,7 @@ output_simple_chars(config,list,"\">",enc); } - output_string(config,list,text,enc); + text(config,list,textstr,enc); if (psiconv_list_length(templist)) { output_simple_chars(config,list,"",enc); @@ -329,9 +556,9 @@ const psiconv_word_styles_section styles_sec, const encoding enc) { - int i,charnr; + int i,charnr,start,len; psiconv_string_t text; - psiconv_in_line_layout layout; + psiconv_in_line_layout layout,next_layout; psiconv_word_style style = NULL; psiconv_paragraph_layout base_para; psiconv_character_layout base_char; @@ -358,7 +585,9 @@ } } - output_simple_chars(config,list,"

base_paragraph->bullet->on?"

  • ",enc); if (psiconv_list_length(para->in_lines) == 0) { - characters(config,list,para->text,para->base_character, - para->base_character,enc); + if (psiconv_unicode_strlen(para->text)) + characters(config,list,para->text,para->base_character, + para->base_character,enc); } else { charnr = 0; + start = -1; for (i = 0; i < psiconv_list_length(para->in_lines); i++) { + if (start < 0) + start = charnr; 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); + if (i+1 < psiconv_list_length(para->in_lines)) { + if (!(next_layout = psiconv_list_get(para->in_lines,i+1))) { + fputs("Internal data structures corruption\n",stderr); + exit(1); + } + } else { + next_layout = NULL; + } + if (next_layout && + character_layout_equal(layout->layout,next_layout->layout)) { + charnr += layout->length; + continue; + } + len = charnr - start + layout->length; + if (len) { + if (!(text = malloc(sizeof (*text) * (len + 1)))) { + fputs("Out of memory error\n",stderr); + exit(1); + } + memcpy(text,para->text+start,len * sizeof(*text)); + text[len] = 0; + characters(config,list,text,layout->layout,para->base_character,enc); + free(text); } - memcpy(text,para->text+charnr,layout->length * sizeof(*text)); - text[layout->length] = 0; - characters(config,list,text,layout->layout,para->base_character,enc); - free(text); charnr += layout->length; + start = -1; } } - output_simple_chars(config,list,"

    \n",enc); + output_simple_chars(config, list, + para->base_paragraph->bullet->on?"
\n":"

\n", + enc); if (!styles_sec) { psiconv_free_paragraph_layout(base_para); psiconv_free_character_layout(base_char); @@ -424,7 +676,7 @@ } } -void gen_html_word(const psiconv_config config, psiconv_list list, +void gen_word(const psiconv_config config, psiconv_list list, const psiconv_word_f file, const encoding enc) { if (!file) @@ -436,7 +688,7 @@ } -void gen_html_texted(const psiconv_config config, psiconv_list list, +void gen_texted(const psiconv_config config, psiconv_list list, const psiconv_texted_f file, const encoding enc) { header(config,list,NULL,enc); @@ -444,44 +696,49 @@ footer(config,list,enc); } -int gen_html(const psiconv_config config, psiconv_list list, +int gen_xhtml(const psiconv_config config, psiconv_list list, const psiconv_file file, const char *dest, const encoding enc) { + encoding enc1 = enc; + if (enc == ENCODING_PSION) { fputs("Unsupported encoding\n",stderr); return -1; - } + } else if (enc == ENCODING_ASCII) + enc1 = ENCODING_ASCII_HTML; if (file->type == psiconv_word_file) { - gen_html_word(config,list,(psiconv_word_f) file->file,enc); + gen_word(config,list,(psiconv_word_f) file->file,enc1); return 0; } else if (file->type == psiconv_texted_file) { - gen_html_texted(config,list,(psiconv_texted_f) file->file,enc); + gen_texted(config,list,(psiconv_texted_f) file->file,enc1); return 0; } else return -1; } -static struct fileformat_s ffs[] = +static struct fileformat_s fileformats[] = { { "XHTML", "XHTML 1.0 Strict, using CSS for formatting", - gen_html + FORMAT_WORD | FORMAT_TEXTED, + gen_xhtml }, { NULL, NULL, + 0, NULL } }; -void init_html(void) +void init_xhtml(void) { int i; - for (i = 0; ffs[i].name; i++) - psiconv_list_add(fileformat_list,ffs+i); + for (i = 0; fileformats[i].name; i++) + psiconv_list_add(fileformat_list,fileformats+i); }