/*! * Append all styles from the Psion Word Styles Section. */ UT_Error IE_Imp_Psion::applyStyles(const psiconv_word_styles_section style_sec) { UT_UTF8String props; int i; gchar *stylename; psiconv_word_style style; UT_Error res; // Iterate through all defined styles. // Index -1 is misused to represent the default "Normal" style. for (i = -1; i < (int) psiconv_list_length(style_sec->styles); i++) { if (i == -1) style = style_sec->normal; else if (!(style = (psiconv_word_style) psiconv_list_get(style_sec->styles,i))) return UT_IE_IMPORTERROR; // Get the style paragraph and character attributes. props.clear(); if ((res = getParagraphAttributes(style->paragraph,props))) return res; if ((res = getCharacterAttributes(style->character,props))) return res; // Not yet implemented: hotkey // Not yet implemented: built_in // Not yet implemented: outline_level // The three unimplemented features above are not yet available // within AbiWord. // Get the style name. if (i == -1) stylename = (gchar *) strdup("Normal"); else stylename = prepare_style_name(style->name); if (!stylename) return UT_IE_NOMEMORY; UT_DEBUGMSG(("PSION: Importing style %s\n",stylename)); UT_DEBUGMSG(("PSION: Style attributes: %s\n",props.utf8_str())); const PP_PropertyVector propsArray = { "props", props.utf8_str(), "name", stylename, // All Psion styles are based upon the Normal style "basedon", "Normal" }; if (!(getDoc()->appendStyle(propsArray))) { UT_DEBUGMSG(("PSION: AppendStyle failed...\n")); free(stylename); return UT_IE_IMPORTERROR; } free(stylename); } return UT_OK; }
static void set_col_widths (Sheet *sheet, psiconv_sheet_grid_size_list widths) { psiconv_u32 i; psiconv_sheet_grid_size psi_width; for (i = 0; i < psiconv_list_length(widths); i++) { if ((psi_width = psiconv_list_get (widths, i))) sheet_col_set_size_pts (sheet, psi_width->line_number, cm2pts (psi_width->size), TRUE); } }
static void set_row_heights (Sheet *sheet, psiconv_sheet_grid_size_list heights) { psiconv_u32 i; psiconv_sheet_grid_size psi_height; for (i = 0; i < psiconv_list_length(heights); i++) { if ((psi_height = psiconv_list_get (heights, i))) sheet_row_set_size_pts (sheet, psi_height->line_number, cm2pts (psi_height->size), TRUE); } }
static void add_cells(Sheet *sheet, const psiconv_sheet_cell_list psi_cells, const psiconv_formula_list psi_formulas, const GnmStyle *default_style) { psiconv_u32 i; psiconv_sheet_cell psi_cell; /* psiconv_lists are actually arrays, so this isn't inefficient. */ for (i = 0; i < psiconv_list_length(psi_cells); i++) { /* If psiconv_list_get fails, something is very wrong... */ if ((psi_cell = psiconv_list_get(psi_cells,i))) add_cell(sheet,psi_cell,psi_formulas, default_style); } }
static void add_workbook(Workbook *wb, psiconv_sheet_workbook_section psi_workbook) { psiconv_u32 i; psiconv_sheet_worksheet psi_worksheet; /* TODO: Perhaps add formulas and share them? */ for (i = 0; i < psiconv_list_length(psi_workbook->worksheets); i++) { /* If psiconv_list_get fails, something is very wrong... */ if ((psi_worksheet = psiconv_list_get (psi_workbook->worksheets,i))) add_worksheet(wb,psi_worksheet,i, psi_workbook->formulas); } workbook_queue_all_recalc (wb); }
/*! * Get all paragraph-related attributes and append them to props. * * If props is not empty, we start with '; ', else we do not. */ UT_Error IE_Imp_Psion::getParagraphAttributes(const psiconv_paragraph_layout layout, UT_UTF8String &props) { UT_return_val_if_fail(layout != NULL, true /* perhaps should be false, but we want loading to proceed */); UT_UTF8String buffer; psiconv_length_t indent_left,indent_first; int i; psiconv_tab tab; // Compute the indent_left and indent_first settings. Note that // indent_first is always relative to indent_left. There are a few // special cases related to bullets; see the psiconv docs for details. if (layout->bullet && layout->bullet->on && layout->bullet->indent && (layout->indent_first > 0)) indent_left = layout->indent_left + layout->indent_first; else indent_left = layout->indent_left; if (layout->bullet && layout->bullet->on && (layout->indent_first > 0)) if (layout->bullet->indent) indent_first = -layout->indent_first; else indent_first = 0; else indent_first = layout->indent_first; // Append a semicolon if there is already text in the props if (props.length()) props += ";"; // Left indent UT_UTF8String_sprintf(buffer,"margin-left:%6.3fcm",indent_left); props += buffer; // Right indent UT_UTF8String_sprintf(buffer,"; margin-right:%6.3fcm",layout->indent_right); props += buffer; // First line indent UT_UTF8String_sprintf(buffer,"; text-indent:%6.3fcm",indent_first); props += buffer; // Horizontal justify UT_UTF8String_sprintf(buffer,"; text-align:%s", layout->justify_hor==psiconv_justify_left ? "left" : layout->justify_hor==psiconv_justify_right ? "right": layout->justify_hor==psiconv_justify_centre? "center": "justify"); props += buffer; // Vertical justify: ignored (never used in Word documents) // Background color UT_UTF8String_sprintf(buffer, "; bgcolor: %02x%02x%02x", layout->back_color->red, layout->back_color->green, layout->back_color->blue); props += buffer; #if 0 // Linespacing (gives trouble at the moment, so we disable it) UT_UTF8String_sprintf(buffer, "; line-height: %dpt",(int) layout->linespacing); props += buffer; if (! layout->linespacing_exact) props += "+"; #endif // Space above UT_UTF8String_sprintf(buffer,"; margin-top:%dpt",(int) layout->space_above); props += buffer; // Space below UT_UTF8String_sprintf(buffer,"; margin-bottom:%dpt",(int) layout->space_below); props += buffer; // Keep together UT_UTF8String_sprintf(buffer,"; keep-together:%s",layout->keep_together?"yes":"no"); props += buffer; // Keep with next UT_UTF8String_sprintf(buffer,"; keep-with-next:%s",layout->keep_with_next?"yes":"no"); props += buffer; // On next page // This is not yet implemented in AbiWord. We use a hack in // applyParagraphAttributes; styles are out of luck in this. // Last checked 20040229: Dialog is available, but no property yet. // Widow control // I'm not quite sure about the difference between setting widows and // orphans?!? UT_UTF8String_sprintf(buffer,"; widows:%d; orphans:%d", layout->no_widow_protection?0:2, layout->no_widow_protection?0:2); props += buffer; // Default tab interval. UT_UTF8String_sprintf(buffer,"; default-tab-interval:%6.3fcm",layout->tabs->normal); props += buffer; // Other tabs if (psiconv_list_length(layout->tabs->extras)) { props += "; tabstops:"; for (i = 0; i < (int) psiconv_list_length(layout->tabs->extras); i++) { if (!(tab = (psiconv_tab) psiconv_list_get(layout->tabs->extras, i))) { UT_ASSERT(tab != NULL); return(UT_IE_IMPORTERROR); } UT_UTF8String_sprintf(buffer, "%s%6.3fcm/%c", i==0?"":",", tab->location, tab->kind == psiconv_tab_centre?'C': tab->kind == psiconv_tab_right? 'R': 'L'); props += buffer; } } // Bullets. I don't think there is a general way to do this yet. // For now, we will hardcode all bullets to type 'Bullet List', // because we might get into real trouble. Note that we hack // this together in applyParagraphAttributes. // Not yet implemented: borders // These are not yet available in AbiWord. return UT_OK; }
/*! * Read all Psion paragraphs and add them to the document. */ UT_Error IE_Imp_Psion::readParagraphs(const psiconv_text_and_layout psiontext, const psiconv_word_styles_section style_sec) // psiconv_list embobjlst) { unsigned int i,inline_nr; int loc; psiconv_paragraph paragraph; psiconv_in_line_layout in_line; UT_UCS4String text; psiconv_word_style style; const gchar *stylename; UT_Error res; // Iterate through all paragraphs for (i=0; i < psiconv_list_length(psiontext); i++) { UT_DEBUGMSG(("PSION: Importing paragraph %d\n",i)); if (!(paragraph = (psiconv_paragraph) psiconv_list_get(psiontext,i))) { // Something is really wrong... UT_ASSERT(paragraph != NULL); return UT_IE_IMPORTERROR; } // Determine the style name; set it to Normal if it is not available if (!style_sec || !(style = psiconv_get_style(style_sec,paragraph->base_style)) || (!style->name) || !(stylename = prepare_style_name(style->name))) stylename = (const gchar *) strdup("Normal"); if (!stylename) return UT_IE_NOMEMORY; UT_DEBUGMSG(("PSION: paragraph %d: style %s\n",i,stylename)); // Add all paragraph attributes to the document if ((res = applyParagraphAttributes(paragraph->base_paragraph,stylename))) return res; // Iterate through all Psion inlines. These contain the character // layout information, together with the number of characters they // apply to. loc = 0; for(inline_nr=0; inline_nr < psiconv_list_length(paragraph->in_lines); inline_nr++) { UT_DEBUGMSG(("Psion: paragraph %d inline %d\n",i,inline_nr)); if (!(in_line = (psiconv_in_line_layout) psiconv_list_get(paragraph->in_lines,inline_nr))) { // Something is really wrong... UT_ASSERT(in_line != NULL); return UT_IE_IMPORTERROR; } // This may be an object, which needs special handling. // Objects have layout associated with them, but we will ignore // it. I am not sure how it would apply anyway. We will also ignore // all text. It should just be a single character \016, which is the // object marker. if (in_line->object) { if ((res = insertObject(in_line))) return res; } else { // Put all characters belonging to the current inline into text text.clear(); if ((res = prepareCharacters(paragraph->text + loc,in_line->length, text))) return res; // Yes, text may be empty! if (text.length()) { // Add the character layout and the text itself to the document if ((res = applyCharacterAttributes(in_line->layout))) return res; if (!(appendSpan((text.ucs4_str()),text.length()))) return UT_IE_IMPORTERROR; } } loc += in_line->length; } // There may be text left after iterating through all inlines. // This remaining text gets the paragraph base_character layout. if (loc < psiconv_unicode_strlen(paragraph->text)) { // Get the remaining characters into text text.clear(); if ((res = prepareCharacters(paragraph->text+loc, psiconv_unicode_strlen(paragraph->text - loc),text))) return res; // Yes, text may be empty! if (text.length()) { // Add the character layout and the text itself to the document. if ((res = applyCharacterAttributes(paragraph->base_character))) return res; if (!appendSpan(text.ucs4_str(),text.length())) return UT_IE_IMPORTERROR; } } } return UT_OK; }
static GnmExpr const * parse_subexpr(const psiconv_formula psi_formula) { int nrargs=0; /* -1 for variable */ int kind=-1; /* 0 for dat, 1 for operator, 2 for formula, 3 for special, -1 for unknown */ psiconv_formula psi_form1,psi_form2; GnmExpr const *expr1=NULL,*expr2=NULL; switch(psi_formula->type) { /* Translates values */ case psiconv_formula_dat_float: case psiconv_formula_dat_int: case psiconv_formula_dat_string: case psiconv_formula_dat_cellblock: case psiconv_formula_dat_vcellblock: nrargs = 0; kind = 0; break; /* Translates to binary operators */ case psiconv_formula_op_lt: case psiconv_formula_op_le: case psiconv_formula_op_gt: case psiconv_formula_op_ge: case psiconv_formula_op_ne: case psiconv_formula_op_eq: case psiconv_formula_op_add: case psiconv_formula_op_sub: case psiconv_formula_op_mul: case psiconv_formula_op_div: /* case psiconv_formula_op_pow: */ /* case psiconv_formula_op_and: */ /* case psiconv_formula_op_or: */ /* case psiconv_formula_op_con: */ nrargs = 2; kind = 1; break; /* Translates to unary operators */ case psiconv_formula_op_pos: case psiconv_formula_op_neg: case psiconv_formula_op_not: nrargs = 1; kind = 1; break; /* Specially handled */ case psiconv_formula_dat_cellref: case psiconv_formula_op_bra: nrargs = 1; kind = 3; break; /* Should never happen; caught by the default */ /* case psiconv_formula_mark_eof: */ /* case psiconv_formula_mark_opsep: */ /* case psiconv_formula_mark_opend: */ default: kind = -1; break; } if (kind == -1) { /* Unknown value */ return NULL; } else if (kind == 0) { /* Handling data */ GnmValue *v = NULL; switch(psi_formula->type) { case psiconv_formula_dat_float: v = value_new_float(psi_formula->data.dat_float); break; case psiconv_formula_dat_int: v = value_new_int(psi_formula->data.dat_int); break; case psiconv_formula_dat_string: v = psi_new_string(psi_formula->data.dat_string); break; case psiconv_formula_dat_cellblock: { GnmCellRef cr1, cr2; p_cellref_init (&cr1, psi_formula->data.dat_cellblock.first.row.offset, psi_formula->data.dat_cellblock.first.row.absolute, psi_formula->data.dat_cellblock.first.column.offset, psi_formula->data.dat_cellblock.first.column.absolute); p_cellref_init (&cr2, psi_formula->data.dat_cellblock.last.row.offset, psi_formula->data.dat_cellblock.last.row.absolute, psi_formula->data.dat_cellblock.last.column.offset, psi_formula->data.dat_cellblock.last.column.absolute); v = value_new_cellrange (&cr1, &cr2, 1, 1); break; } default: break; } if (!v) return NULL; return gnm_expr_new_constant(v); } else if (kind == 1) { /* Handling the operators */ if (nrargs >= 1) { if (!(psi_form1 = psiconv_list_get (psi_formula->data.fun_operands,0))) return NULL; if (!(expr1 = parse_subexpr(psi_form1))) return NULL; } if (nrargs >= 2) { if (!(psi_form2 = psiconv_list_get (psi_formula->data.fun_operands,1))) { gnm_expr_free(expr1); return NULL; } if (!(expr2 = parse_subexpr(psi_form2))) { gnm_expr_free(expr1); return NULL; } } switch(psi_formula->type) { case psiconv_formula_op_lt: return gnm_expr_new_binary (expr1,GNM_EXPR_OP_LT,expr2); case psiconv_formula_op_le: return gnm_expr_new_binary (expr1,GNM_EXPR_OP_LTE,expr2); case psiconv_formula_op_gt: return gnm_expr_new_binary (expr1,GNM_EXPR_OP_GT,expr2); case psiconv_formula_op_ge: return gnm_expr_new_binary (expr1,GNM_EXPR_OP_GTE,expr2); case psiconv_formula_op_ne: return gnm_expr_new_binary (expr1,GNM_EXPR_OP_NOT_EQUAL,expr2); case psiconv_formula_op_eq: return gnm_expr_new_binary (expr1,GNM_EXPR_OP_EQUAL,expr2); case psiconv_formula_op_add: return gnm_expr_new_binary (expr1,GNM_EXPR_OP_ADD,expr2); case psiconv_formula_op_sub: return gnm_expr_new_binary (expr1,GNM_EXPR_OP_SUB,expr2); case psiconv_formula_op_mul: return gnm_expr_new_binary (expr1,GNM_EXPR_OP_MULT,expr2); case psiconv_formula_op_div: return gnm_expr_new_binary (expr1,GNM_EXPR_OP_DIV,expr2); case psiconv_formula_op_pos: return gnm_expr_new_unary (GNM_EXPR_OP_UNARY_PLUS,expr1); case psiconv_formula_op_neg: return gnm_expr_new_unary (GNM_EXPR_OP_UNARY_NEG,expr1); default: gnm_expr_free(expr1); gnm_expr_free(expr2); return NULL; } } else if (kind == 3) { switch(psi_formula->type) { case psiconv_formula_dat_cellref: { GnmCellRef cr; return gnm_expr_new_cellref (p_cellref_init (&cr, psi_formula->data.dat_cellref.row.offset, psi_formula->data.dat_cellref.row.absolute, psi_formula->data.dat_cellref.column.offset, psi_formula->data.dat_cellref.column.absolute)); } case psiconv_formula_op_bra: if (!(psi_form1 = psiconv_list_get (psi_formula->data.fun_operands,0))) return NULL; return parse_subexpr(psi_form1); default: break; } } return NULL; }