static void wb_create_name (WorkbookControl *wbc, char const *text, GnmParsePos *pp) { GnmRange const *r; GnmCellRef a, b; GnmExpr const *target_range; r = selection_first_range (wb_control_cur_sheet_view (wbc), GO_CMD_CONTEXT (wbc), _("Define Name")); if (r != NULL) { a.sheet = b.sheet = wb_control_cur_sheet (wbc); a.col = r->start.col; a.row = r->start.row; b.col = r->end.col; b.row = r->end.row; a.col_relative = a.row_relative = b.col_relative = b.row_relative = FALSE; pp->sheet = NULL; /* make it a global name */ if (gnm_cellref_equal (&a, &b)) target_range = gnm_expr_new_cellref (&a); else target_range = gnm_expr_new_constant ( value_new_cellrange_unsafe (&a, &b)); cmd_define_name (wbc, text, pp, gnm_expr_top_new (target_range), NULL); } }
/* NOTE : Make sure to set up any merged regions in the target range BEFORE * this is called. */ static void paste_link (GnmPasteTarget const *pt, int top, int left, GnmCellRegion const *cr) { GnmCellPos pos; GnmCellRef source_cell_ref; int x, y; /* Not possible to link to arbitrary (non gnumeric) sources yet. */ /* TODO : eventually support interprocess gnumeric links */ if (cr->origin_sheet == NULL) return; /* TODO : support relative links ? */ source_cell_ref.col_relative = 0; source_cell_ref.row_relative = 0; source_cell_ref.sheet = (cr->origin_sheet != pt->sheet) ? cr->origin_sheet : NULL; pos.col = left; for (x = 0 ; x < cr->cols ; x++, pos.col++) { source_cell_ref.col = cr->base.col + x; pos.row = top; for (y = 0 ; y < cr->rows ; y++, pos.row++) { GnmExprTop const *texpr; GnmCell *cell = sheet_cell_fetch (pt->sheet, pos.col, pos.row); /* This could easily be made smarter */ if (!gnm_cell_is_merged (cell) && gnm_sheet_merge_contains_pos (pt->sheet, &pos)) continue; source_cell_ref.row = cr->base.row + y; texpr = gnm_expr_top_new (gnm_expr_new_cellref (&source_cell_ref)); gnm_cell_set_expr (cell, texpr); gnm_expr_top_unref (texpr); } } }
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; }
static void qpro_parse_formula (QProReadState *state, int col, int row, guint8 const *data, guint8 const *end) { guint16 magic, ref_offset; #if 0 int flags = GSF_LE_GET_GUINT16 (data + 8); int length = GSF_LE_GET_GUINT16 (data + 10); #endif GnmValue *val; GSList *stack = NULL; GnmExprTop const *texpr = NULL; guint8 const *refs, *fmla; #ifdef DEBUG_MISSING dump_missing_functions (); #endif Q_CHECK_CONDITION (end - data >= 14); magic = GSF_LE_GET_GUINT16 (data + 6) & 0x7ff8; ref_offset = GSF_LE_GET_GUINT16 (data + 12); fmla = data + 14; refs = fmla + ref_offset; Q_CHECK_CONDITION (refs <= end); #if 0 puts (cell_coord_name (col, row)); gsf_mem_dump (data, 14); gsf_mem_dump (fmla, refs-fmla); gsf_mem_dump (refs, end-refs); #endif while (fmla < refs && *fmla != QPRO_OP_EOF) { QProOperators op = *fmla++; GnmExpr const *expr = NULL; #if 0 g_print ("Operator %d.\n", op); #endif switch (op) { case QPRO_OP_CONST_FLOAT: Q_CHECK_CONDITION (refs - fmla >= 8); expr = gnm_expr_new_constant (value_new_float ( gsf_le_get_double (fmla))); fmla += 8; break; case QPRO_OP_CELLREF: { GnmCellRef ref; guint16 tmp; Q_CHECK_CONDITION (end - refs >= 6); tmp = GSF_LE_GET_GUINT16 (refs + 4); ref.sheet = NULL; ref.col = *((gint8 *)(refs + 2)); ref.col_relative = (tmp & 0x4000) ? TRUE : FALSE; ref.row_relative = (tmp & 0x2000) ? TRUE : FALSE; if (ref.row_relative) ref.row = (int)(((gint16)((tmp & 0x1fff) << 3)) >> 3); else ref.row = tmp & 0x1fff; expr = gnm_expr_new_cellref (&ref); refs += 6; break; } case QPRO_OP_RANGEREF: { GnmCellRef a, b; guint16 tmp; Q_CHECK_CONDITION (end - refs >= 10); tmp = GSF_LE_GET_GUINT16 (refs + 4); a.sheet = NULL; a.col = *((gint8 *)(refs + 2)); a.col_relative = (tmp & 0x4000) ? TRUE : FALSE; a.row_relative = (tmp & 0x2000) ? TRUE : FALSE; if (a.row_relative) a.row = (int)(((gint16)((tmp & 0x1fff) << 3)) >> 3); else a.row = tmp & 0x1fff; tmp = GSF_LE_GET_GUINT16 (refs + 8); b.sheet = NULL; b.col = *((gint8 *)(refs + 6)); b.col_relative = (tmp & 0x4000) ? TRUE : FALSE; b.row_relative = (tmp & 0x2000) ? TRUE : FALSE; if (b.row_relative) b.row = (int)(((gint16)((tmp & 0x1fff) << 3)) >> 3); else b.row = tmp & 0x1fff; expr = gnm_expr_new_constant ( value_new_cellrange_unsafe (&a, &b)); refs += 10; break; }