--- psiconv/trunk/lib/psiconv/gen_rtf.c 1999/10/05 15:32:10 8 +++ psiconv/trunk/lib/psiconv/gen_rtf.c 1999/10/05 15:33:38 9 @@ -68,6 +68,7 @@ }; + static void fput_text(FILE * of, const char *text, int length) { int j; @@ -76,34 +77,49 @@ } } -static void add_color(psiconv_list colors, psiconv_color color) +static int length_to_twips(psiconv_length_t len) +{ + return 1440.0 / 2.54 * len; +} + +static int lookup_color(psiconv_list colors,psiconv_color color) { int i; psiconv_color comp; - if (color) { - for (i = 0; i < psiconv_list_length(colors); i ++) { - comp = * (psiconv_color *) psiconv_list_get(colors,i); - if ((comp->red == color->red) && (comp->green == color->green) && - (comp->blue == color->blue)) - return; - } - psiconv_list_add(colors,&color); + for (i = 0; i < psiconv_list_length(colors); i ++) { + comp = * (psiconv_color *) psiconv_list_get(colors,i); + if ((comp->red == color->red) && (comp->green == color->green) && + (comp->blue == color->blue)) + return i; } + return -1; } -static void add_font(psiconv_list fonts, psiconv_font font) +static void add_color(psiconv_list colors, psiconv_color color) +{ + if (color) + if (lookup_color(colors,color) < 0) + psiconv_list_add(colors,&color); +} + +static int lookup_font(psiconv_list fonts,psiconv_font font) { int i; psiconv_font comp; - if (font) { - for (i = 0; i < psiconv_list_length(fonts); i ++) { - comp = *(psiconv_font *) psiconv_list_get(fonts,i); - if ((comp->screenfont == font->screenfont) && - ! strcmp(comp->name,font->name)) - return; - } - psiconv_list_add(fonts,&font); + for (i = 0; i < psiconv_list_length(fonts); i ++) { + comp = *(psiconv_font *) psiconv_list_get(fonts,i); + if ((comp->screenfont == font->screenfont) && + ! strcmp(comp->name,font->name)) + return i; } + return -1; +} + +static void add_font(psiconv_list fonts, psiconv_font font) +{ + if (font) + if (lookup_font(fonts,font) < 0) + psiconv_list_add(fonts,&font); } static void scan_border(psiconv_list colors,psiconv_list fonts, @@ -268,7 +284,7 @@ } } -static gen_font_table(FILE *of,psiconv_list fonts) +static void gen_font_table(FILE *of,psiconv_list fonts) { int i; psiconv_font *font; @@ -290,7 +306,7 @@ fprintf(of,"}\n"); } -static gen_color_table(FILE *of, psiconv_list colors) +static void gen_color_table(FILE *of, psiconv_list colors) { int i; psiconv_color *color; @@ -304,6 +320,166 @@ fprintf(of,"}\n"); } +/* This is not necessarily the same as returned by basic_character_layout_status + This one is specific for the base point of RTF */ +static psiconv_character_layout + gen_base_char(psiconv_list colors, psiconv_list fonts) +{ + struct psiconv_color white = { 0,0,0 }; + struct psiconv_color black = { 0xff,0xff,0xff }; + struct psiconv_font font = { strdup(""),-1 }; /* Pseudo - not added! */ + + struct psiconv_character_layout base_char_struct = + { + &black, /* color */ + &white, /* 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 */ + &font, /* font */ + }; + + add_color(colors,&white); + add_color(colors,&black); + + return psiconv_clone_character_layout(&base_char_struct); +} + +void diff_char(FILE *of,psiconv_list colors, psiconv_list fonts, + const psiconv_character_layout old, + const psiconv_character_layout new) +{ + if ((old->font->screenfont != new->font->screenfont) || + strcmp(old->font->name,new->font->name)) + fprintf(of,"\\f%d",lookup_font(fonts,new->font)); + if (old->font_size != new->font_size) + fprintf(of,"\\fs%d",(int) (new->font_size * 2)); + if (old->super_sub != new->super_sub) { + if (new->super_sub == psiconv_normalscript) + fprintf(of,"\\nosupersub"); + else if (new->super_sub == psiconv_superscript) + fprintf(of,"\\super"); + else if (new->super_sub == psiconv_subscript) + fprintf(of,"\\sub"); + } + if (old->bold != new->bold) + fprintf(of,"\\b%s",new->bold?"":"0"); + if (old->italic != new->italic) + fprintf(of,"\\i%s",new->italic?"":"0"); + if (old->underline != new->underline) + fprintf(of,"\\ul%s",new->underline?"":"0"); + if (old->strike_out != new->strike_out) + fprintf(of,"\\strike%s",new->strike_out?"":"0"); + if ((old->color->red != new->color->red) || + (old->color->green != new->color->green) || + (old->color->blue != new->color->blue)) + fprintf(of,"\\cf%d",lookup_color(colors,new->color)); + if ((old->back_color->red != new->back_color->red) || + (old->back_color->green != new->back_color->green) || + (old->back_color->blue != new->back_color->blue)) + fprintf(of,"\\cb%d",lookup_color(colors,new->back_color)); +} + + +/* Note: this generates also some character formatting; Psion Word and + RTF do not agree on what is paragraph-level formatting and what is + character-level formatting. The character-level formatting is put + at the end. This should work out. */ +static void gen_paragraph_codes(FILE *of, psiconv_list colors, + psiconv_list fonts, + psiconv_paragraph_layout para) +{ + if (para->indent_first != 0.0) + fprintf(of,"\\fl%d",length_to_twips( para->indent_first)); + if (para->indent_left != 0.0) + fprintf(of,"\\ll%d",length_to_twips(para->indent_left)); + if (para->indent_right != 0.0) + fprintf(of,"\\rl%d",length_to_twips(para->indent_right)); + if (para->justify_hor != psiconv_justify_left) { + if (para->justify_hor == psiconv_justify_right) + fprintf(of,"\\qr"); + else if (para->justify_hor == psiconv_justify_centre) + fprintf(of,"\\qc"); + else if (para->justify_hor == psiconv_justify_full) + fprintf(of,"\\qj"); +/* + else if (para->justify_hor == psiconv_justify_left) + fprintf(of,"\\ql"); +*/ + } + if (para->interline != 0.0) + fprintf(of,"\\sl%d",(para->interline_exact?-1:1) * + length_to_twips(para->interline)); + if (para->top_space != 0.0) + fprintf(of,"\\sb%d",length_to_twips(para->top_space)); + if (para->bottom_space != 0.0) + fprintf(of,"\\sa%d",length_to_twips(para->bottom_space)); + if (para->on_one_page) + fprintf(of,"\\keep"); + if (para->together_with) + fprintf(of,"\\keepn"); + if (!para->on_next_page) + fprintf(of,"pagebb"); + if (!para->no_widow_protection) + fprintf(of,"\\nowidctlpar"); +} + + +static void gen_para(FILE *of, psiconv_list colors, psiconv_list fonts, + psiconv_paragraph para) +{ + psiconv_character_layout cur_char,base_char; + psiconv_in_line_layout inl; + int loc,i,j; + + fprintf(of,"\\par\\pard"); + gen_paragraph_codes(of,colors,fonts,para->base_paragraph); + + base_char = gen_base_char(colors,fonts); + cur_char = base_char; + + if (psiconv_list_length(para->in_lines) == 0) { + diff_char(of,colors,fonts,cur_char,para->base_character); + cur_char = para->base_character; + } + loc = 0; + + for (i = 0; i < psiconv_list_length(para->in_lines); i++) { + inl = psiconv_list_get(para->in_lines,i); + diff_char(of,colors,fonts,cur_char,inl->layout); + cur_char = inl->layout; + for (j = loc; j < inl->length + loc; j ++) { + fputs(char_table[(unsigned char) (para->text[j])],of); + } + loc = j; + } + + if (loc < strlen(para->text)) { + diff_char(of,colors,fonts,cur_char,para->base_character); + cur_char = para->base_character; + for (j = loc; j < strlen(para->text); j ++) { + fputs(char_table[(unsigned char) (para->text[j])],of); + } + } + + psiconv_free_character_layout(base_char); +} + +static void gen_text(FILE *of, psiconv_list colors, psiconv_list fonts, + psiconv_text_and_layout paragraphs) +{ + int i; + psiconv_paragraph para; + fprintf(of,"\\sect"); + for (i = 0; i < psiconv_list_length(paragraphs); i++) { + para = psiconv_list_get(paragraphs,i); + gen_para(of,colors,fonts,para); + } +} + static void psiconv_gen_rtf_word(FILE * of, psiconv_word_f wf) { psiconv_list fonts; @@ -316,6 +492,7 @@ fputs("{\\rtf1\\ansi\n",of); gen_font_table(of,fonts); gen_color_table(of,colors); + gen_text(of,colors,fonts,wf->paragraphs); fputs("}\n",of); psiconv_list_free(fonts); @@ -335,6 +512,7 @@ fputs("{\\rtf1\\ansi\n",of); gen_font_table(of,fonts); gen_color_table(of,colors); + gen_text(of,colors,fonts,tf->texted_sec->paragraphs); fputs("}\n",of); psiconv_list_free(fonts);