--- psiconv/trunk/lib/psiconv/generate_common.c 2000/12/25 00:26:53 76 +++ psiconv/trunk/lib/psiconv/generate_common.c 2004/01/06 20:15:01 184 @@ -25,57 +25,73 @@ #include "generate_routines.h" #include "error.h" +#ifdef DMALLOC +#include +#endif + +static int psiconv_write_layout_section(const psiconv_config config, + psiconv_buffer buf, int lev, + const psiconv_text_and_layout value, + const psiconv_word_styles_section styles, + int with_styles); /* Maybe use a psiconv_header_section variable instead? */ -int psiconv_write_header_section(psiconv_buffer buf,psiconv_u32 uid1, +int psiconv_write_header_section(const psiconv_config config, + psiconv_buffer buf,int lev,psiconv_u32 uid1, psiconv_u32 uid2, psiconv_u32 uid3) { int res; - if ((res = psiconv_write_u32(buf,uid1))) + psiconv_progress(config,lev,0,"Writing header section"); + if ((res = psiconv_write_u32(config,buf,lev+1,uid1))) return res; - if ((res = psiconv_write_u32(buf,uid2))) + if ((res = psiconv_write_u32(config,buf,lev+1,uid2))) return res; - if ((res = psiconv_write_u32(buf,uid3))) + if ((res = psiconv_write_u32(config,buf,lev+1,uid3))) return res; - return psiconv_write_u32(buf,psiconv_checkuid(uid1,uid2,uid3)); + return psiconv_write_u32(config,buf,lev+1,psiconv_checkuid(uid1,uid2,uid3)); } -int psiconv_write_section_table_section(psiconv_buffer buf, +int psiconv_write_section_table_section(const psiconv_config config, + psiconv_buffer buf,int lev, const psiconv_section_table_section value) { int res,i; psiconv_section_table_entry entry; + psiconv_progress(config,lev,0,"Writing section table section"); if (!value) { - psiconv_warn(0,psiconv_list_length(buf),"Null section table section"); + psiconv_error(config,0,psiconv_buffer_length(buf),"Null section table section"); return -PSICONV_E_GENERATE; } - if ((res = psiconv_write_u8(buf,2 * psiconv_list_length(value)))) + if ((res = psiconv_write_u8(config,buf,lev+1,2 * psiconv_list_length(value)))) return res; for (i = 0; i < psiconv_list_length(value); i++) { if (!(entry = psiconv_list_get(value,i))) { - psiconv_warn(0,psiconv_list_length(buf),"Massive memory corruption"); + psiconv_error(config,0,psiconv_buffer_length(buf),"Massive memory corruption"); return -PSICONV_E_NOMEM; } - if ((res = psiconv_write_u32(buf,entry->id))) + if ((res = psiconv_write_u32(config,buf,lev+1,entry->id))) return res; - if ((res = psiconv_write_u32(buf,entry->offset))) + if ((res = psiconv_write_offset(config,buf,lev+1,entry->offset))) return res; } return -PSICONV_E_OK; } -int psiconv_write_application_id_section(psiconv_buffer buf,psiconv_u32 id, +int psiconv_write_application_id_section(const psiconv_config config, + psiconv_buffer buf,int lev,psiconv_u32 id, const psiconv_string_t text) { int res; - if ((res = psiconv_write_u32(buf,id))) + psiconv_progress(config,lev,0,"Writing application id section"); + if ((res = psiconv_write_u32(config,buf,lev+1,id))) return res; - return psiconv_write_string(buf,text); + return psiconv_write_string(config,buf,lev+1,text); } -int psiconv_write_text_section(psiconv_buffer buf, +int psiconv_write_text_section(const psiconv_config config, + psiconv_buffer buf,int lev, const psiconv_text_and_layout value) { int res; @@ -83,29 +99,494 @@ int i,j; psiconv_paragraph paragraph; + psiconv_progress(config,lev,0,"Writing text section"); if (!value) { - psiconv_warn(0,psiconv_list_length(buf),"Null text section"); + psiconv_error(config,0,psiconv_buffer_length(buf),"Null text section"); return -PSICONV_E_GENERATE; } - if (!(extra_buf = psiconv_new_buffer())) - return -PSICONV_E_NOMEM; + if (psiconv_list_length(value)) { + if (!(extra_buf = psiconv_buffer_new())) + return -PSICONV_E_NOMEM; + for (i = 0; i < psiconv_list_length(value); i++) { + if (!(paragraph = psiconv_list_get(value,i))) { + psiconv_error(config,0,psiconv_buffer_length(buf),"Massive memory corruption"); + res = -PSICONV_E_NOMEM; + goto ERROR; + } + for (j = 0; j < psiconv_unicode_strlen(paragraph->text); j++) + if ((res = psiconv_write_u8(config,extra_buf,lev+1, + psiconv_unicode_to_char(config,paragraph->text[j])))) + goto ERROR; + psiconv_write_u8(config,extra_buf,lev+1,0x06); + } + if ((res = psiconv_write_X(config,buf,lev+1,psiconv_buffer_length(extra_buf)))) + goto ERROR; + res = psiconv_buffer_concat(buf,extra_buf); + } else + /* Hack: empty text sections are just not allowed */ + return psiconv_write_u16(config,buf,lev+1,0x0602); + +ERROR: + psiconv_buffer_free(extra_buf); + return res; +} + +int psiconv_write_layout_section(const psiconv_config config, + psiconv_buffer buf,int lev, + const psiconv_text_and_layout value, + const psiconv_word_styles_section styles, + int with_styles) +{ + typedef struct psiconv_paragraph_type_list_s + { + psiconv_character_layout character; + psiconv_paragraph_layout paragraph; + psiconv_u8 style; + psiconv_u8 nr; + } *psiconv_paragraph_type_list; + psiconv_u32 obj_id; + psiconv_list paragraph_type_list; /* Of psiconv_paragraph_type_list_s */ + psiconv_paragraph_type_list paragraph_type; + struct psiconv_paragraph_type_list_s new_type; + psiconv_buffer buf_types,buf_elements,buf_inlines,buf_objects; + psiconv_paragraph paragraph; + psiconv_in_line_layout in_line = NULL; + psiconv_word_style style; + psiconv_character_layout para_charlayout; + int i,j,para_type,nr_of_inlines=0,res,ptl_length,pel_length,thislen,paralen; + + psiconv_progress(config,lev,0,"Writing layout section"); + if (!value) { + psiconv_error(config,0,psiconv_buffer_length(buf),"Null text section"); + return -PSICONV_E_GENERATE; + } + + if (!(paragraph_type_list = psiconv_list_new(sizeof(new_type)))) { + res = -PSICONV_E_NOMEM; + goto ERROR1; + } + + if (!(buf_types = psiconv_buffer_new())) { + res = -PSICONV_E_NOMEM; + goto ERROR2; + } + + if (!(buf_elements = psiconv_buffer_new())) { + res = -PSICONV_E_NOMEM; + goto ERROR3; + } + + if (!(buf_inlines = psiconv_buffer_new())) { + res = -PSICONV_E_NOMEM; + goto ERROR4; + } + + if (!(buf_objects = psiconv_buffer_new())) { + res = -PSICONV_E_NOMEM; + goto ERROR5; + } + for (i = 0; i < psiconv_list_length(value); i++) { if (!(paragraph = psiconv_list_get(value,i))) { - psiconv_warn(0,psiconv_list_length(buf),"Massive memory corruption"); - res = -PSICONV_E_OTHER; - goto ERROR; + psiconv_error(config,0,psiconv_buffer_length(buf),"Massive memory corruption"); + res = -PSICONV_E_NOMEM; + goto ERROR6; + } + if ((res = psiconv_write_u32(config,buf_elements,lev+1, + psiconv_unicode_strlen(paragraph->text)+1))) + goto ERROR6; + + /* We need it for the next if-statement */ + if (psiconv_list_length(paragraph->in_lines) == 1) + if (!(in_line = psiconv_list_get(paragraph->in_lines,1))) + goto ERROR6; + + if ((psiconv_list_length(paragraph->in_lines) > 1) || + ((psiconv_list_length(paragraph->in_lines) == 1) && + (in_line->object != NULL))) { + /* Inline layouts, or an object, so we generate a paragraph element + and inline elements */ + if ((res = psiconv_write_u8(config,buf_elements,lev+1,0x00))) + goto ERROR6; + if (!(style = psiconv_get_style(styles,paragraph->base_style))) { + psiconv_error(config,0,psiconv_buffer_length(buf),"Unknown style"); + res = -PSICONV_E_GENERATE; + goto ERROR6; + } + if ((res = psiconv_write_paragraph_layout_list(config,buf_elements,lev+1, + paragraph->base_paragraph, + style->paragraph))) + goto ERROR6; + if (with_styles) + if ((res = psiconv_write_u8(config,buf_elements,lev+1,paragraph->base_style))) + goto ERROR6; + if ((res = psiconv_write_u32(config,buf_elements,lev+1, + psiconv_list_length(paragraph->in_lines)))) + goto ERROR6; + + /* Generate the inlines. NB: Against what are all settings relative?!? */ + paralen = 0; + for (j = 0; j < psiconv_list_length(paragraph->in_lines); j++) { + nr_of_inlines ++; + if (!(in_line = psiconv_list_get(paragraph->in_lines,j))) { + psiconv_error(config,0,psiconv_buffer_length(buf), + "Massive memory corruption"); + res = -PSICONV_E_NOMEM; + goto ERROR6; + } + if ((res = psiconv_write_u8(config,buf_inlines,lev+1,in_line->object?0x01:0x00))) + goto ERROR6; + thislen = in_line->length; + paralen += thislen; + /* If this is the last in_line, we need to make sure that the + complete length of all inlines equals the text length */ + if (j == psiconv_list_length(paragraph->in_lines)-1) { + if (paralen > psiconv_unicode_strlen(paragraph->text)+1) { + res = -PSICONV_E_GENERATE; + goto ERROR6; + } + thislen += psiconv_unicode_strlen(paragraph->text)+1-paralen; + } + if ((res = psiconv_write_u32(config,buf_inlines,lev+1,thislen))) + goto ERROR6; + if ((res = psiconv_write_character_layout_list(config,buf_inlines,lev+1, + in_line->layout, + style->character))) + goto ERROR6; + if (in_line->object) { + if ((res = psiconv_write_u32(config,buf_inlines,lev+1,PSICONV_ID_OBJECT))) + goto ERROR6; + obj_id = psiconv_buffer_unique_id(); + if ((res = psiconv_buffer_add_reference(buf_inlines,obj_id))) + goto ERROR6; + if ((res = psiconv_buffer_add_target(buf_objects,obj_id))) + goto ERROR6; + if ((res = psiconv_write_embedded_object_section(config,buf_objects,lev+1, + in_line->object))) + goto ERROR6; + if ((res = psiconv_write_length(config,buf_inlines,lev+1,in_line->object_width))) + goto ERROR6; + if ((res = psiconv_write_length(config,buf_inlines,lev+1,in_line->object_height))) + goto ERROR6; + } + } + } else { + /* No inline layouts (or only 1), so we generate a paragraph type list */ + para_type = 0; + /* Set para_charlayout to the correct character-level layout */ + if (psiconv_list_length(paragraph->in_lines) == 0) + para_charlayout = paragraph->base_character; + else { + if (!(in_line = psiconv_list_get(paragraph->in_lines,0))) { + psiconv_error(config,0,psiconv_buffer_length(buf), + "Massive memory corruption"); + res = -PSICONV_E_NOMEM; + goto ERROR6; + } + para_charlayout = in_line->layout; + } + for (j = 0; j < psiconv_list_length(paragraph_type_list); j++) { + if (!(paragraph_type = psiconv_list_get(paragraph_type_list,j))) { + psiconv_error(config,0,psiconv_buffer_length(buf), + "Massive memory corruption"); + res = -PSICONV_E_NOMEM; + goto ERROR6; + } + if ((paragraph->base_style == paragraph_type->style) && + !psiconv_compare_character_layout(para_charlayout, + paragraph_type->character) && + !psiconv_compare_paragraph_layout(paragraph->base_paragraph, + paragraph_type->paragraph)) { + para_type = paragraph_type->nr; + break; + } + } + if (!para_type) { + /* We need to add a new entry */ + para_type = new_type.nr = j+1; + /* No need to copy them, we won't change them anyway */ + new_type.paragraph = paragraph->base_paragraph; + new_type.character = para_charlayout; + new_type.style = paragraph->base_style; + paragraph_type = &new_type; + if ((res = psiconv_list_add(paragraph_type_list,paragraph_type))) + goto ERROR6; + if ((res = psiconv_write_u32(config,buf_types,lev+1,paragraph_type->nr))) + goto ERROR6; + if (!(style = psiconv_get_style(styles,paragraph_type->style))) { + psiconv_error(config,0,psiconv_buffer_length(buf),"Unknown style"); + res = -PSICONV_E_GENERATE; + goto ERROR6; + } + if ((res = psiconv_write_paragraph_layout_list(config,buf_types,lev+1, + paragraph_type->paragraph,style->paragraph))) + goto ERROR6; + if (with_styles) + if ((res = psiconv_write_u8(config,buf_types,lev+1,paragraph_type->style))) + goto ERROR6; + if ((res = psiconv_write_character_layout_list(config,buf_types,lev+1, + paragraph_type->character,style->character))) + goto ERROR6; + } + if ((res = psiconv_write_u8(config,buf_elements,lev+1,para_type))) + goto ERROR6; } - for (j = 0; j < strlen(paragraph->text); j++) - if ((res = psiconv_write_u8(extra_buf,paragraph->text[j]))) - goto ERROR; - psiconv_write_u8(extra_buf,0x06); } - if ((res = psiconv_write_X(buf,psiconv_list_length(extra_buf)))) - goto ERROR; - res = psiconv_list_concat(buf,extra_buf); -ERROR: - psiconv_free_buffer(extra_buf); + /* HACK: special case: no paragraphs at all. We need to improvize. */ + if (!psiconv_list_length(value)) { + if ((res = psiconv_write_u32(config,buf_types,lev+1,1))) + goto ERROR6; + if ((res = psiconv_write_u32(config,buf_types,lev+1,0))) + goto ERROR6; + if (with_styles) + if ((res = psiconv_write_u8(config,buf_types,lev+1,0))) + goto ERROR6; + if ((res = psiconv_write_u32(config,buf_types,lev+1,0))) + goto ERROR6; + + if ((res = psiconv_write_u32(config,buf_elements,lev+1,1))) + goto ERROR6; + if ((res = psiconv_write_u8(config,buf_elements,lev+1,1))) + goto ERROR6; + pel_length = 1; + ptl_length = 1; + } else { + pel_length = psiconv_list_length(value); + ptl_length = psiconv_list_length(paragraph_type_list); + } + + /* Now append everything */ + if ((res = psiconv_write_u16(config,buf,lev+1,with_styles?0x0001:0x0000))) + goto ERROR6; + if ((res = psiconv_write_u8(config,buf,lev+1, ptl_length))) + goto ERROR6; + if ((res = psiconv_buffer_concat(buf,buf_types))) + goto ERROR6; + if ((res = psiconv_write_u32(config,buf,lev+1,pel_length))) + goto ERROR6; + if ((res = psiconv_buffer_concat(buf,buf_elements))) + goto ERROR6; + if ((res = psiconv_write_u32(config,buf,lev+1,nr_of_inlines))) + goto ERROR6; + if ((res = psiconv_buffer_concat(buf,buf_inlines))) + goto ERROR6; + if ((res = psiconv_buffer_concat(buf,buf_objects))) + goto ERROR6; + +ERROR6: + psiconv_buffer_free(buf_objects); +ERROR5: + psiconv_buffer_free(buf_inlines); +ERROR4: + psiconv_buffer_free(buf_elements); +ERROR3: + psiconv_buffer_free(buf_types); +ERROR2: + psiconv_list_free(paragraph_type_list); +ERROR1: + return res; +} + +int psiconv_write_styled_layout_section(const psiconv_config config, + psiconv_buffer buf,int lev, + psiconv_text_and_layout result, + psiconv_word_styles_section styles) +{ + psiconv_progress(config,lev,0,"Writing styled layout section"); + return psiconv_write_layout_section(config,buf,lev+1,result,styles,1); +} + +int psiconv_write_styleless_layout_section(const psiconv_config config, + psiconv_buffer buf,int lev, + const psiconv_text_and_layout value, + const psiconv_character_layout base_char, + const psiconv_paragraph_layout base_para) +{ + int res = 0; + psiconv_word_styles_section styles_section; + + psiconv_progress(config,lev,0,"Writing styleless layout section"); + if (!(styles_section = malloc(sizeof(*styles_section)))) + goto ERROR1; + if (!(styles_section->normal = malloc(sizeof(*styles_section->normal)))) + goto ERROR2; + if (!(styles_section->normal->character = + psiconv_clone_character_layout(base_char))) + goto ERROR3; + if (!(styles_section->normal->paragraph = + psiconv_clone_paragraph_layout(base_para))) + goto ERROR4; + styles_section->normal->hotkey = 0; + if ((res = psiconv_unicode_from_chars(config,"", + &styles_section->normal->name))) + goto ERROR5; + if (!(styles_section->styles = psiconv_list_new(sizeof( + struct psiconv_word_style_s)))) + goto ERROR6; + + res = psiconv_write_layout_section(config,buf,lev+1,value,styles_section,0); + psiconv_free_word_styles_section(styles_section); + return res; + +ERROR6: + free(styles_section->normal->name); +ERROR5: + psiconv_free_paragraph_layout(styles_section->normal->paragraph); +ERROR4: + psiconv_free_character_layout(styles_section->normal->character); +ERROR3: + free(styles_section->normal); +ERROR2: + free(styles_section); +ERROR1: + if (!res) + return -PSICONV_E_NOMEM; + else + return res; +} + + +int psiconv_write_embedded_object_section(const psiconv_config config, + psiconv_buffer buf,int lev, + const psiconv_embedded_object_section value) +{ + int res; + psiconv_u32 display_id,icon_id,table_id; + psiconv_buffer extra_buf; + + psiconv_progress(config,lev,0,"Writing embedded object section"); + if (!value) { + psiconv_error(config,0,psiconv_buffer_length(buf),"Null Object"); + res = -PSICONV_E_GENERATE; + goto ERROR1; + } + + if (!(extra_buf = psiconv_buffer_new())) { + res = -PSICONV_E_NOMEM; + goto ERROR1; + } + + display_id = psiconv_buffer_unique_id(); + icon_id = psiconv_buffer_unique_id(); + table_id = psiconv_buffer_unique_id(); + if ((res = psiconv_write_u8(config,buf,lev+1,0x06))) + goto ERROR2; + if ((res = psiconv_write_u32(config,buf,lev+1,PSICONV_ID_OBJECT_DISPLAY_SECTION))) + goto ERROR2; + if ((res = psiconv_buffer_add_reference(buf,display_id))) + goto ERROR2; + if ((res = psiconv_write_u32(config,buf,lev+1,PSICONV_ID_OBJECT_ICON_SECTION))) + goto ERROR2; + if ((res = psiconv_buffer_add_reference(buf,icon_id))) + goto ERROR2; + if ((res = psiconv_write_u32(config,buf,lev+1,PSICONV_ID_OBJECT_SECTION_TABLE_SECTION))) + goto ERROR2; + if ((res = psiconv_buffer_add_reference(buf,table_id))) + goto ERROR2; + + if ((res = psiconv_buffer_add_target(buf,display_id))) + goto ERROR2; + if ((res = psiconv_write_object_display_section(config,buf,lev+1,value->display))) + goto ERROR2; + if ((res = psiconv_buffer_add_target(buf,icon_id))) + goto ERROR2; + if ((res = psiconv_write_object_icon_section(config,buf,lev+1,value->icon))) + goto ERROR2; + if ((res = psiconv_buffer_add_target(buf,table_id))) + goto ERROR2; + switch(value->object->type) { + case psiconv_word_file: + if ((res = psiconv_write_word_file(config,extra_buf,lev+1, + (psiconv_word_f) value->object->file))) + goto ERROR2; + break; + case psiconv_sketch_file: + if ((res = psiconv_write_sketch_file(config,extra_buf,lev+1, + (psiconv_sketch_f) value->object->file))) + goto ERROR2; + break; +/* + case psiconv_sheet_file: + if ((res = psiconv_write_sheet_file(config,extra_buf,lev+1, + (psiconv_sheet_f) value->object->file))) + goto ERROR2; + break; +*/ + default: + psiconv_error(config,0,psiconv_buffer_length(buf), + "Unknown or unsupported object type"); + res = -PSICONV_E_GENERATE; + goto ERROR2; + } + + if ((res = psiconv_buffer_resolve(extra_buf))) + goto ERROR2; + if ((res = psiconv_buffer_concat(buf,extra_buf))) + goto ERROR2; + + return 0; + +ERROR2: + psiconv_buffer_free(extra_buf); +ERROR1: + return res; +} + + +int psiconv_write_object_display_section(const psiconv_config config, + psiconv_buffer buf,int lev, + const psiconv_object_display_section value) +{ + int res; + + psiconv_progress(config,lev,0,"Writing object display section"); + + if (!value) { + psiconv_error(config,0,psiconv_buffer_length(buf),"Null Object Display Section"); + res = -PSICONV_E_GENERATE; + goto ERROR1; + } + + if ((res = psiconv_write_u8(config,buf,lev+1,value->show_icon?0x00:0x01))) + goto ERROR1; + if ((res = psiconv_write_length(config,buf,lev+1,value->width))) + goto ERROR1; + if ((res = psiconv_write_length(config,buf,lev+1,value->height))) + goto ERROR1; + if ((res = psiconv_write_u32(config,buf,lev+1,0x00000000))) + goto ERROR1; + + return 0; + +ERROR1: + return res; +} + +int psiconv_write_object_icon_section(const psiconv_config config, + psiconv_buffer buf,int lev, + const psiconv_object_icon_section value) +{ + int res; + + psiconv_progress(config,lev,0,"Writing object icon section"); + + if (!value) { + psiconv_error(config,0,psiconv_buffer_length(buf),"Null Object Icon Section"); + res = -PSICONV_E_GENERATE; + goto ERROR1; + } + + if ((res = psiconv_write_string(config,buf,lev+1,value->icon_name))) + goto ERROR1; + if ((res = psiconv_write_length(config,buf,lev+1,value->icon_width))) + goto ERROR1; + if ((res = psiconv_write_length(config,buf,lev+1,value->icon_height))) + goto ERROR1; + + return 0; + +ERROR1: return res; }