GnmValue * expr_name_eval (GnmNamedExpr const *nexpr, GnmEvalPos const *pos, GnmExprEvalFlags flags) { g_return_val_if_fail (pos, NULL); if (!nexpr) return value_new_error_NAME (pos); return gnm_expr_top_eval (nexpr->texpr, pos, flags); }
static void paste_cell_with_operation (Sheet *dst_sheet, int target_col, int target_row, GnmExprRelocateInfo const *rinfo, GnmCellCopy const *src, int paste_flags) { GnmCell *dst; GnmExprOp op; if (src->texpr == NULL && !VALUE_IS_EMPTY (src->val) && !VALUE_IS_NUMBER (src->val)) return; dst = sheet_cell_fetch (dst_sheet, target_col, target_row); if (!cell_has_expr_or_number_or_blank (dst)) return; op = paste_op_to_expr_op (paste_flags); /* FIXME : This does not handle arrays, linked cells, ranges, etc. */ if ((paste_flags & PASTE_CONTENTS) && (NULL != src->texpr || gnm_cell_has_expr (dst))) { GnmExpr const *old_expr = contents_as_expr (dst->base.texpr, dst->value); GnmExpr const *copied_expr = contents_as_expr (src->texpr, src->val); GnmExprTop const *res = gnm_expr_top_new (gnm_expr_new_binary (old_expr, op, copied_expr)); GnmExprTop const *relo = gnm_expr_top_relocate (res, rinfo, FALSE); if (relo) { gnm_cell_set_expr (dst, relo); gnm_expr_top_unref (relo); } else gnm_cell_set_expr (dst, res); gnm_expr_top_unref (res); } else { GnmValue *value; GnmEvalPos pos; GnmExpr const *expr = gnm_expr_new_binary ( gnm_expr_new_constant (value_dup (dst->value)), op, gnm_expr_new_constant (value_dup (src->val))); GnmExprTop const *texpr = gnm_expr_top_new (expr); eval_pos_init_cell (&pos, dst); pos.dep = NULL; /* no dynamic deps */ value = gnm_expr_top_eval (texpr, &pos, GNM_EXPR_EVAL_SCALAR_NON_EMPTY); gnm_expr_top_unref (texpr); gnm_cell_set_value (dst, value); } }
static GtkWidget * vcombo_create_list (SheetObject *so, GtkTreePath **clip, GtkTreePath **select, gboolean *make_buttons) { GnmValidationCombo *vcombo = GNM_VALIDATION_COMBO (so); unsigned i; UniqueCollection uc; GnmEvalPos ep; GtkTreeIter iter; GtkWidget *list; GPtrArray *sorted; GtkListStore *model; GnmValue *v; GnmValue const *cur_val; GnmValidation const *val = vcombo->validation; SheetView const *sv = vcombo->parent.sv; g_return_val_if_fail (val != NULL, NULL); g_return_val_if_fail (val->type == GNM_VALIDATION_TYPE_IN_LIST, NULL); g_return_val_if_fail (val->deps[0].texpr != NULL, NULL); g_return_val_if_fail (sv != NULL, NULL); eval_pos_init_editpos (&ep, sv); v = gnm_expr_top_eval (val->deps[0].texpr, &ep, GNM_EXPR_EVAL_PERMIT_NON_SCALAR | GNM_EXPR_EVAL_PERMIT_EMPTY | GNM_EXPR_EVAL_ARRAY_CONTEXT); if (NULL == v) return NULL; uc.date_conv = workbook_date_conv (sv->sheet->workbook); uc.hash = g_hash_table_new_full ((GHashFunc)value_hash, (GEqualFunc)value_equal, (GDestroyNotify)value_release, (GDestroyNotify)g_free); value_area_foreach (v, &ep, CELL_ITER_IGNORE_BLANK, (GnmValueIterFunc) cb_collect_unique, &uc); value_release (v); sorted = g_ptr_array_new (); g_hash_table_foreach (uc.hash, (GHFunc)cb_hash_domain, sorted); qsort (&g_ptr_array_index (sorted, 0), sorted->len, sizeof (char *), &value_cmp); model = gtk_list_store_new (3, G_TYPE_STRING, G_TYPE_STRING, gnm_value_get_type ()); cur_val = sheet_cell_get_value (ep.sheet, ep.eval.col, ep.eval.row); for (i = 0; i < sorted->len ; i++) { char *label = NULL; unsigned const max = 50; char const *str = g_hash_table_lookup (uc.hash, (v = g_ptr_array_index (sorted, i))); gsize len = g_utf8_strlen (str, -1); if (len > max + 3) { label = g_strdup (str); strcpy (g_utf8_offset_to_pointer (label, max), "..."); } gtk_list_store_append (model, &iter); gtk_list_store_set (model, &iter, 0, label ? label : str, /* Menu text */ 1, str, /* Actual string selected on. */ -1); g_free (label); if (i == 10) *clip = gtk_tree_model_get_path (GTK_TREE_MODEL (model), &iter); if (cur_val != NULL && v != NULL && value_equal (cur_val, v)) { gtk_tree_path_free (*select); *select = gtk_tree_model_get_path (GTK_TREE_MODEL (model), &iter); } } g_hash_table_destroy (uc.hash); g_ptr_array_free (sorted, TRUE); list = gtk_tree_view_new_with_model (GTK_TREE_MODEL (model)); g_object_unref (model); gtk_tree_view_append_column (GTK_TREE_VIEW (list), gtk_tree_view_column_new_with_attributes ("ID", gtk_cell_renderer_text_new (), "text", 0, NULL)); return list; }
/** * gnm_validation_eval: * @wbc: * @mstyle: * @sheet: * * validation set in the GnmStyle if applicable. **/ ValidationStatus gnm_validation_eval (WorkbookControl *wbc, GnmStyle const *mstyle, Sheet *sheet, GnmCellPos const *pos, gboolean *showed_dialog) { GnmValidation const *v; GnmCell *cell; GnmValue *val; gnm_float x; int nok, i; GnmEvalPos ep; if (showed_dialog) *showed_dialog = FALSE; v = gnm_style_get_validation (mstyle); if (v == NULL) return GNM_VALIDATION_STATUS_VALID; if (v->type == GNM_VALIDATION_TYPE_ANY) return GNM_VALIDATION_STATUS_VALID; cell = sheet_cell_get (sheet, pos->col, pos->row); if (cell != NULL) gnm_cell_eval (cell); if (gnm_cell_is_empty (cell)) { if (v->allow_blank) return GNM_VALIDATION_STATUS_VALID; BARF (g_strdup_printf (_("Cell %s is not permitted to be blank"), cell_name (cell))); } val = cell->value; switch (val->type) { case VALUE_ERROR: if (typeinfo[v->type].errors_not_allowed) BARF (g_strdup_printf (_("Cell %s is not permitted to contain error values"), cell_name (cell))); break; case VALUE_BOOLEAN: if (typeinfo[v->type].bool_always_ok) return GNM_VALIDATION_STATUS_VALID; break; case VALUE_STRING: if (typeinfo[v->type].strings_not_allowed) BARF (g_strdup_printf (_("Cell %s is not permitted to contain strings"), cell_name (cell))); break; default: break; } eval_pos_init_cell (&ep, cell); switch (v->type) { case GNM_VALIDATION_TYPE_AS_INT: x = value_get_as_float (val); if (gnm_fake_floor (x) == gnm_fake_ceil (x)) break; else BARF (g_strdup_printf (_("'%s' is not an integer"), value_peek_string (val))); case GNM_VALIDATION_TYPE_AS_NUMBER: x = value_get_as_float (val); break; case GNM_VALIDATION_TYPE_AS_DATE: /* What the hell does this do? */ x = value_get_as_float (val); if (x < 0) BARF (g_strdup_printf (_("'%s' is not a valid date"), value_peek_string (val))); break; case GNM_VALIDATION_TYPE_AS_TIME: /* What the hell does this do? */ x = value_get_as_float (val); break; case GNM_VALIDATION_TYPE_IN_LIST: { GnmExprTop const *texpr = v->deps[0].texpr; if (texpr) { GnmValue *list = gnm_expr_top_eval (texpr, &ep, GNM_EXPR_EVAL_PERMIT_NON_SCALAR | GNM_EXPR_EVAL_PERMIT_EMPTY); GnmValue *res = value_area_foreach (list, &ep, CELL_ITER_IGNORE_BLANK, (GnmValueIterFunc) cb_validate_custom, val); value_release (list); if (res == NULL) { GnmParsePos pp; char *expr_str = gnm_expr_top_as_string (texpr, parse_pos_init_evalpos (&pp, &ep), ep.sheet->convs); char *msg = g_strdup_printf (_("%s does not contain the new value."), expr_str); g_free (expr_str); BARF (msg); } } return GNM_VALIDATION_STATUS_VALID; } case GNM_VALIDATION_TYPE_TEXT_LENGTH: /* XL appears to use a very basic value->string mapping that * ignores formatting. * eg len (12/13/01) == len (37238) = 5 * This seems wrong for */ x = g_utf8_strlen (value_peek_string (val), -1); break; case GNM_VALIDATION_TYPE_CUSTOM: { gboolean valid; GnmExprTop const *texpr = v->deps[0].texpr; if (!texpr) return GNM_VALIDATION_STATUS_VALID; val = gnm_expr_top_eval (texpr, &ep, GNM_EXPR_EVAL_SCALAR_NON_EMPTY); valid = value_get_as_bool (val, NULL); value_release (val); if (valid) return GNM_VALIDATION_STATUS_VALID; else { GnmParsePos pp; char *expr_str = gnm_expr_top_as_string (texpr, parse_pos_init_evalpos (&pp, &ep), ep.sheet->convs); char *msg = g_strdup_printf (_("%s is not true."), expr_str); g_free (expr_str); BARF (msg); } } default: g_assert_not_reached (); return GNM_VALIDATION_STATUS_VALID; } if (v->op == GNM_VALIDATION_OP_NONE) return GNM_VALIDATION_STATUS_VALID; nok = 0; for (i = 0; i < opinfo[v->op].nops; i++) { GnmExprTop const *texpr_i = v->deps[i].texpr; GnmExprTop const *texpr; GnmValue *cres; if (!texpr_i) { nok++; continue; } texpr = gnm_expr_top_new (gnm_expr_new_binary (gnm_expr_new_constant (value_new_float (x)), opinfo[v->op].ops[i], gnm_expr_copy (texpr_i->expr))); cres = gnm_expr_top_eval (texpr, &ep, GNM_EXPR_EVAL_SCALAR_NON_EMPTY); if (value_get_as_bool (cres, NULL)) nok++; value_release (cres); gnm_expr_top_unref (texpr); } if (nok < opinfo[v->op].ntrue) BARF (g_strdup_printf (_("%s is out of permitted range"), value_peek_string (val))); return GNM_VALIDATION_STATUS_VALID; }