Commit d3cd8897 authored by Jody Goldberg's avatar Jody Goldberg Committed by Jody Goldberg

accept ranges that start or end at the cursor.

2002-09-13  Jody Goldberg <jody@gnome.org>

	* gnumeric-expr-entry.c (gnm_expr_entry_rangesel_start) : accept
	  ranges that start or end at the cursor.

2002-09-13  Jody Goldberg <jody@gnome.org>

	*  functions.c (get_value_class) : delete.
	(gnumeric_check_for_err) : delete.
	(gnumeric_iserror) : make this a 'node' function that takes a scalar
	  This allows implicit iteration to work.
	(gnumeric_isna) : ditto.
	(gnumeric_iserr) : ditto.
	(gnumeric_error_type) : ditto.
	(gnumeric_islogical) : ditto.
	(gnumeric_isnontext) : ditto.
	(gnumeric_isnumber) : ditto.
	(gnumeric_istext) : ditto.
	(gnumeric_type) : ditto.

2002-09-13  Jody Goldberg <jody@gnome.org>

	* src/func.c (function_call_with_list) : support implicit iteration.

	* src/value-sheet.c (value_area_fetch_x_y) : catch value_empty too.

	* src/parse-util.c (col_parse) : don't change accept the column unless
	  at least 1 char was read.
	(row_parse) : ditto.
	(rangeref_parse) : off by 1 error when handling full ranges.

	* src/dependent.h (cell_eval) : make this a macro.

	* src/plugin-service.c (gnum_plugin_file_opener_probe) : silence a
	  warning.

	* src/expr.c (gnm_expr_eval) : rename from expr_eval_real and move the
	  empty handling into.
	(handle_empty) : here.
	(gnm_expr_array_intersection) : delete.
parent cbc41bdd
2002-09-13 Jody Goldberg <jody@gnome.org>
* src/func.c (function_call_with_list) : support implicit iteration.
* src/value-sheet.c (value_area_fetch_x_y) : catch value_empty too.
* src/parse-util.c (col_parse) : don't change accept the column unless
at least 1 char was read.
(row_parse) : ditto.
(rangeref_parse) : off by 1 error when handling full ranges.
* src/dependent.h (cell_eval) : make this a macro.
* src/plugin-service.c (gnum_plugin_file_opener_probe) : silence a
warning.
* src/expr.c (gnm_expr_eval) : rename from expr_eval_real and move the
empty handling into.
(handle_empty) : here.
(gnm_expr_array_intersection) : delete.
2002-09-11 Jody Goldberg <jody@gnome.org>
* src/gnumeric-graph.c (gnm_graph_new_view) : stub so that sheets with
......
......@@ -14,6 +14,8 @@ Jody:
* Make autocorrect unicode safe, and port dialog to treeview
* Fix 'address' so that we pass all of the tests
* Fix handling of optional scalar arguments.
* Covert many of the IS* info functions to nodal:scalar
* Support implicit iteration for array expressions
Morten:
* Leak plugging.
......
2002-09-13 Jody Goldberg <jody@gnome.org>
* src/func.c (function_call_with_list) : support implicit iteration.
* src/value-sheet.c (value_area_fetch_x_y) : catch value_empty too.
* src/parse-util.c (col_parse) : don't change accept the column unless
at least 1 char was read.
(row_parse) : ditto.
(rangeref_parse) : off by 1 error when handling full ranges.
* src/dependent.h (cell_eval) : make this a macro.
* src/plugin-service.c (gnum_plugin_file_opener_probe) : silence a
warning.
* src/expr.c (gnm_expr_eval) : rename from expr_eval_real and move the
empty handling into.
(handle_empty) : here.
(gnm_expr_array_intersection) : delete.
2002-09-11 Jody Goldberg <jody@gnome.org>
* src/gnumeric-graph.c (gnm_graph_new_view) : stub so that sheets with
......
2002-09-13 Jody Goldberg <jody@gnome.org>
* src/func.c (function_call_with_list) : support implicit iteration.
* src/value-sheet.c (value_area_fetch_x_y) : catch value_empty too.
* src/parse-util.c (col_parse) : don't change accept the column unless
at least 1 char was read.
(row_parse) : ditto.
(rangeref_parse) : off by 1 error when handling full ranges.
* src/dependent.h (cell_eval) : make this a macro.
* src/plugin-service.c (gnum_plugin_file_opener_probe) : silence a
warning.
* src/expr.c (gnm_expr_eval) : rename from expr_eval_real and move the
empty handling into.
(handle_empty) : here.
(gnm_expr_array_intersection) : delete.
2002-09-11 Jody Goldberg <jody@gnome.org>
* src/gnumeric-graph.c (gnm_graph_new_view) : stub so that sheets with
......
2002-09-13 Jody Goldberg <jody@gnome.org>
* functions.c (get_value_class) : delete.
(gnumeric_check_for_err) : delete.
(gnumeric_iserror) : make this a 'node' function that takes a scalar
This allows implicit iteration to work.
(gnumeric_isna) : ditto.
(gnumeric_iserr) : ditto.
(gnumeric_error_type) : ditto.
(gnumeric_islogical) : ditto.
(gnumeric_isnontext) : ditto.
(gnumeric_isnumber) : ditto.
(gnumeric_istext) : ditto.
(gnumeric_type) : ditto.
2002-08-30 Morten Welinder <terra@diku.dk>
* functions.c (gnumeric_expression): Avoid copying string.
......
......@@ -59,55 +59,6 @@
GNUMERIC_MODULE_PLUGIN_INFO_DECL;
enum Value_Class {
VALUE_CLASS_NUMBER = 1,
VALUE_CLASS_TEXT = 2,
VALUE_CLASS_BOOL = 4,
VALUE_CLASS_FORMULA = 8,
VALUE_CLASS_ERROR = 16,
VALUE_CLASS_ARRAY = 64,
VALUE_CLASS_BOGUS = -1
};
static enum Value_Class
get_value_class (FunctionEvalInfo *ei, GnmExpr *expr)
{
Value *value;
enum Value_Class res;
value = gnm_expr_eval (expr, ei->pos,
GNM_EXPR_EVAL_PERMIT_NON_SCALAR|GNM_EXPR_EVAL_PERMIT_EMPTY);
if (value) {
switch (value->type) {
case VALUE_INTEGER:
case VALUE_FLOAT:
res = VALUE_CLASS_NUMBER;
break;
case VALUE_STRING:
res = VALUE_CLASS_TEXT;
break;
case VALUE_BOOLEAN:
res = VALUE_CLASS_BOOL;
break;
case VALUE_ERROR:
res = VALUE_CLASS_ERROR;
break;
case VALUE_ARRAY:
res = VALUE_CLASS_ARRAY;
break;
case VALUE_EMPTY:
default:
res = VALUE_CLASS_BOGUS;
break;
}
value_release (value);
} else
res = VALUE_CLASS_ERROR;
return res;
}
/***************************************************************************/
static const char *help_cell = {
......@@ -1380,44 +1331,10 @@ static const char *help_iserror = {
"@SEEALSO=ERROR")
};
/* A utility routine to evaluate a single argument and return any errors
* directly
*/
static Value *
gnumeric_check_for_err (FunctionEvalInfo *ei, GnmExprList *expr_node_list,
Value ** err)
{
Value * tmp;
if (gnm_expr_list_length (expr_node_list) != 1) {
*err = value_new_error(ei->pos,
_("Argument mismatch"));
return NULL;
}
tmp = gnm_expr_eval (expr_node_list->data, ei->pos,
GNM_EXPR_EVAL_STRICT);
if (tmp != NULL) {
if (tmp->type == VALUE_ERROR)
return tmp;
value_release (tmp);
}
return NULL;
}
static Value *
gnumeric_iserror (FunctionEvalInfo *ei, GnmExprList *expr_node_list)
gnumeric_iserror (FunctionEvalInfo *ei, Value **argv)
{
Value * res, *err = NULL;
res = gnumeric_check_for_err (ei, expr_node_list, &err);
if (err != NULL)
return err;
if (res) {
value_release (res);
return value_new_bool (TRUE);
} else
return value_new_bool (FALSE);
return value_new_bool (argv[0]->type == VALUE_ERROR);
}
/***************************************************************************/
......@@ -1441,18 +1358,10 @@ static const char *help_isna = {
* the error handling mechanism
*/
static Value *
gnumeric_isna (FunctionEvalInfo *ei, GnmExprList *expr_node_list)
gnumeric_isna (FunctionEvalInfo *ei, Value **argv)
{
Value * res, *err = NULL;
gboolean b;
res = gnumeric_check_for_err (ei, expr_node_list, &err);
if (err != NULL)
return err;
b = (res && !strcmp (gnumeric_err_NA, res->v_err.mesg->str));
if (res) value_release (res);
return value_new_bool (b);
return value_new_bool (argv[0]->type == VALUE_ERROR &&
!strcmp (gnumeric_err_NA, argv[0]->v_err.mesg->str));
}
/***************************************************************************/
......@@ -1472,18 +1381,10 @@ static const char *help_iserr = {
};
static Value *
gnumeric_iserr (FunctionEvalInfo *ei, GnmExprList *expr_node_list)
gnumeric_iserr (FunctionEvalInfo *ei, Value **argv)
{
Value * res, *err = NULL;
gboolean b;
res = gnumeric_check_for_err (ei, expr_node_list, &err);
if (err != NULL)
return err;
b = (res && strcmp (gnumeric_err_NA, res->v_err.mesg->str));
if (res) value_release (res);
return value_new_bool (b);
return value_new_bool (argv[0]->type == VALUE_ERROR &&
strcmp (gnumeric_err_NA, argv[0]->v_err.mesg->str));
}
/***************************************************************************/
......@@ -1510,18 +1411,14 @@ static const char *help_error_type = {
};
static Value *
gnumeric_error_type (FunctionEvalInfo *ei, GnmExprList *expr_node_list)
gnumeric_error_type (FunctionEvalInfo *ei, Value **argv)
{
int retval = -1;
char const * mesg;
Value * res, *err = NULL;
res = gnumeric_check_for_err (ei, expr_node_list, &err);
if (err != NULL)
return err;
if (res == NULL)
if (argv[0]->type != VALUE_ERROR)
return value_new_error (ei->pos, gnumeric_err_NA);
mesg = res->v_err.mesg->str;
mesg = argv[0]->v_err.mesg->str;
if (!strcmp (gnumeric_err_NULL, mesg))
retval = 1;
else if (!strcmp (gnumeric_err_DIV0, mesg))
......@@ -1536,12 +1433,9 @@ gnumeric_error_type (FunctionEvalInfo *ei, GnmExprList *expr_node_list)
retval = 6;
else if (!strcmp (gnumeric_err_NA, mesg))
retval = 7;
else {
value_release (res);
else
return value_new_error (ei->pos, gnumeric_err_NA);
}
value_release (res);
return value_new_int (retval);
}
......@@ -1677,17 +1571,9 @@ static const char *help_islogical = {
};
static Value *
gnumeric_islogical (FunctionEvalInfo *ei, GnmExprList *expr_node_list)
gnumeric_islogical (FunctionEvalInfo *ei, Value **argv)
{
enum Value_Class cl;
if (gnm_expr_list_length (expr_node_list) != 1)
return value_new_error (ei->pos,
_("Invalid number of arguments"));
cl = get_value_class (ei, expr_node_list->data);
return value_new_bool (cl == VALUE_CLASS_BOOL);
return value_new_bool (argv[0]->type == VALUE_BOOLEAN);
}
/***************************************************************************/
......@@ -1707,14 +1593,9 @@ static const char *help_isnontext = {
};
static Value *
gnumeric_isnontext (FunctionEvalInfo *ei, GnmExprList *expr_node_list)
gnumeric_isnontext (FunctionEvalInfo *ei, Value **argv)
{
if (gnm_expr_list_length (expr_node_list) != 1)
return value_new_error (ei->pos,
_("Invalid number of arguments"));
return value_new_bool (get_value_class (ei, expr_node_list->data)
!= VALUE_CLASS_TEXT);
return value_new_bool (argv[0]->type != VALUE_STRING);
}
/***************************************************************************/
......@@ -1734,14 +1615,10 @@ static const char *help_isnumber = {
};
static Value *
gnumeric_isnumber (FunctionEvalInfo *ei, GnmExprList *expr_node_list)
gnumeric_isnumber (FunctionEvalInfo *ei, Value **argv)
{
if (gnm_expr_list_length (expr_node_list) != 1)
return value_new_error (ei->pos,
_("Invalid number of arguments"));
return value_new_bool (get_value_class (ei, expr_node_list->data)
== VALUE_CLASS_NUMBER);
return value_new_bool (argv[0]->type == VALUE_INTEGER ||
argv[0]->type == VALUE_FLOAT);
}
/***************************************************************************/
......@@ -1815,14 +1692,9 @@ static const char *help_istext = {
};
static Value *
gnumeric_istext (FunctionEvalInfo *ei, GnmExprList *expr_node_list)
gnumeric_istext (FunctionEvalInfo *ei, Value **argv)
{
if (gnm_expr_list_length (expr_node_list) != 1)
return value_new_error (ei->pos,
_("Invalid number of arguments"));
return value_new_bool (get_value_class (ei, expr_node_list->data)
== VALUE_CLASS_TEXT);
return value_new_bool (argv[0]->type == VALUE_STRING);
}
/***************************************************************************/
......@@ -1872,6 +1744,11 @@ static const char *help_type = {
"@DESCRIPTION="
"TYPE returns a number indicating the data type of a value.\n\n"
"1 == number\n"
"2 == text\n"
"4 == boolean\n"
"16 == error\n"
"64 == array\n"
"* This function is Excel compatible.\n"
"\n"
"@EXAMPLES=\n"
......@@ -1882,13 +1759,30 @@ static const char *help_type = {
};
static Value *
gnumeric_type (FunctionEvalInfo *ei, GnmExprList *expr_node_list)
gnumeric_type (FunctionEvalInfo *ei, Value **argv)
{
if (gnm_expr_list_length (expr_node_list) != 1)
return value_new_error (ei->pos,
_("Invalid number of arguments"));
return value_new_int (get_value_class (ei, expr_node_list->data));
switch (argv[0]->type) {
/* case VALUE_EMPTY : not possible, S arguments convert this to int(0)
* This is XL compatible, although I don't really agree with it
*/
case VALUE_BOOLEAN:
return value_new_int (4);
case VALUE_INTEGER:
case VALUE_FLOAT:
return value_new_int (1);
case VALUE_ERROR:
return value_new_int (16);
case VALUE_STRING:
return value_new_int (2);
/* case VALUE_CELLRANGE: S argument handles this */
#warning FIXME : S arguments will filter arrays
case VALUE_ARRAY:
return value_new_int (64);
default:
break;
}
/* not reached */
return value_new_error (ei->pos, gnumeric_err_VALUE);
}
/***************************************************************************/
......@@ -1922,47 +1816,47 @@ gnumeric_getenv (FunctionEvalInfo *ei, Value **argv)
/***************************************************************************/
const ModulePluginFunctionInfo info_functions[] = {
{ "cell", "sr", N_("info_type, cell"), &help_cell,
{ "cell", "sr", N_("info_type, cell"), &help_cell,
gnumeric_cell, NULL, NULL, NULL },
{ "countblank", "r", N_("range"), &help_countblank,
{ "countblank", "r", N_("range"), &help_countblank,
gnumeric_countblank, NULL, NULL, NULL },
{ "error", "s", N_("text"), &help_error,
{ "error", "s", N_("text"), &help_error,
gnumeric_error, NULL, NULL, NULL },
{ "error.type", NULL, N_("value"), &help_error_type,
NULL, gnumeric_error_type, NULL, NULL },
{ "expression", "r", N_("cell"), &help_expression,
{ "error.type", "S", N_("value"), &help_error_type,
gnumeric_error_type, NULL, NULL, NULL },
{ "expression", "r", N_("cell"), &help_expression,
gnumeric_expression, NULL, NULL, NULL },
{ "info", "s", N_("info_type"), &help_info,
{ "info", "s", N_("info_type"), &help_info,
gnumeric_info, NULL, NULL, NULL },
{ "isblank", NULL, N_("value"), &help_isblank,
{ "isblank", NULL, N_("value"), &help_isblank,
NULL, gnumeric_isblank, NULL, NULL },
{ "iserr", NULL, N_("value"), &help_iserr,
NULL, gnumeric_iserr, NULL, NULL },
{ "iserror", NULL, N_("value"), &help_iserror,
NULL, gnumeric_iserror, NULL, NULL },
{ "iseven", "?", N_("value"), &help_iseven,
{ "iserr", "S", N_("value"), &help_iserr,
gnumeric_iserr, NULL, NULL, NULL },
{ "iserror", "S", N_("value"), &help_iserror,
gnumeric_iserror, NULL, NULL, NULL },
{ "iseven", "S", N_("value"), &help_iseven,
gnumeric_iseven, NULL, NULL, NULL },
{ "islogical", NULL, N_("value"), &help_islogical,
NULL, gnumeric_islogical, NULL, NULL },
{ "isna", NULL, N_("value"), &help_isna,
NULL, gnumeric_isna, NULL, NULL },
{ "isnontext", NULL, N_("value"), &help_isnontext,
NULL, gnumeric_isnontext, NULL, NULL },
{ "isnumber", NULL, N_("value"), &help_isnumber,
NULL, gnumeric_isnumber, NULL, NULL },
{ "isodd", "?", N_("value"), &help_isodd,
{ "islogical", "S", N_("value"), &help_islogical,
gnumeric_islogical, NULL, NULL, NULL },
{ "isna", "S", N_("value"), &help_isna,
gnumeric_isna, NULL, NULL, NULL },
{ "isnontext", "S", N_("value"), &help_isnontext,
gnumeric_isnontext, NULL, NULL, NULL },
{ "isnumber", "S", N_("value"), &help_isnumber,
gnumeric_isnumber, NULL, NULL, NULL },
{ "isodd", "S", N_("value"), &help_isodd,
gnumeric_isodd, NULL, NULL, NULL },
{ "isref", NULL, N_("value"), &help_isref,
{ "isref", NULL, N_("value"), &help_isref,
NULL, gnumeric_isref, NULL, NULL },
{ "istext", NULL, N_("value"), &help_istext,
NULL, gnumeric_istext, NULL, NULL },
{ "n", "?", N_("value"), &help_n,
{ "istext", "S", N_("value"), &help_istext,
gnumeric_istext, NULL, NULL, NULL },
{ "n", "S", N_("value"), &help_n,
gnumeric_n, NULL, NULL, NULL },
{ "na", "", "", &help_na,
{ "na", "", "", &help_na,
gnumeric_na, NULL, NULL, NULL },
{ "type", NULL, N_("value"), &help_type,
NULL, gnumeric_type, NULL, NULL },
{ "getenv", "s", N_("string"), &help_getenv,
{ "type", "S", N_("value"), &help_type,
gnumeric_type, NULL, NULL, NULL },
{ "getenv", "s", N_("string"), &help_getenv,
gnumeric_getenv, NULL, NULL, NULL },
{NULL}
};
......@@ -281,8 +281,7 @@ gnumeric_if (FunctionEvalInfo *ei, GnmExprList *expr_node_list)
_("Invalid number of arguments"));
/* Compute the if part */
value = gnm_expr_eval (expr_node_list->data, ei->pos,
GNM_EXPR_EVAL_STRICT);
value = gnm_expr_eval (expr_node_list->data, ei->pos, 0);
if (VALUE_IS_EMPTY_OR_ERROR(value))
return value;
......
......@@ -471,7 +471,7 @@ gnumeric_choose (FunctionEvalInfo *ei, GnmExprList *l)
if (argc < 1 || !l->data)
return value_new_error (ei->pos, gnumeric_err_VALUE);
v = gnm_expr_eval (l->data, ei->pos, GNM_EXPR_EVAL_STRICT);
v = gnm_expr_eval (l->data, ei->pos, 0);
if (!v)
return NULL;
......@@ -777,8 +777,7 @@ gnumeric_indirect (FunctionEvalInfo *ei, Value **args)
expr = tmp;
}
if (expr->any.oper == GNM_EXPR_OP_CELLREF) {
Value *res = gnm_expr_eval (expr, ei->pos,
GNM_EXPR_EVAL_STRICT);
Value *res = gnm_expr_eval (expr, ei->pos, 0);
gnm_expr_unref (expr);
return res;
} else if (expr->any.oper == GNM_EXPR_OP_CONSTANT) {
......
......@@ -2601,7 +2601,7 @@ gnumeric_seriessum (FunctionEvalInfo *ei, GnmExprList *nodes)
if (tree == NULL)
return value_new_error (ei->pos, gnumeric_err_NUM);
val = gnm_expr_eval (tree, ei->pos, GNM_EXPR_EVAL_STRICT);
val = gnm_expr_eval (tree, ei->pos, 0);
if (!val) return NULL;
if (!VALUE_IS_NUMBER (val)) {
value_release (val);
......@@ -2617,7 +2617,7 @@ gnumeric_seriessum (FunctionEvalInfo *ei, GnmExprList *nodes)
if (tree == NULL)
return value_new_error (ei->pos, gnumeric_err_NUM);
val = gnm_expr_eval (tree, ei->pos, GNM_EXPR_EVAL_STRICT);
val = gnm_expr_eval (tree, ei->pos, 0);
if (!val) return NULL;
if (! VALUE_IS_NUMBER (val)) {
value_release (val);
......@@ -2636,7 +2636,7 @@ gnumeric_seriessum (FunctionEvalInfo *ei, GnmExprList *nodes)
if (tree == NULL)
return value_new_error (ei->pos, gnumeric_err_NUM);
val = gnm_expr_eval (tree, ei->pos, GNM_EXPR_EVAL_STRICT);
val = gnm_expr_eval (tree, ei->pos, 0);
if (!val) return NULL;
if (! VALUE_IS_NUMBER (val)) {
value_release (val);
......
......@@ -4761,7 +4761,7 @@ gnumeric_subtotal (FunctionEvalInfo *ei, GnmExprList *expr_node_list)
if (tree == NULL)
return value_new_error (ei->pos, gnumeric_err_NUM);
val = gnm_expr_eval (tree, ei->pos, GNM_EXPR_EVAL_STRICT);
val = gnm_expr_eval (tree, ei->pos, 0);
if (val->type == VALUE_ERROR)
return val;
fun_nbr = value_get_as_int (val);
......
......@@ -107,7 +107,7 @@ generic_marshaller (FunctionEvalInfo *ei, GList *nodes)
* this can be relaxed. We do not need to require
* non emptiness, or scalarness.
*/
Value *v = gnm_expr_eval (l->data, ei->pos, GNM_EXPR_EVAL_STRICT);
Value *v = gnm_expr_eval (l->data, ei->pos, 0);
args = g_slist_prepend (args, value_to_gb (v));
......
......@@ -98,7 +98,7 @@ apply_paste_oper_to_values (Cell const *old_cell, Cell const *copied_cell,
expr.binary.value_a = &arg_a;
expr.binary.value_b = &arg_b;
return gnm_expr_eval (&expr, eval_pos_init_cell (&pos, new_cell), GNM_EXPR_EVAL_STRICT);
return gnm_expr_eval (&expr, eval_pos_init_cell (&pos, new_cell), 0);
}
static void
......
......@@ -960,7 +960,7 @@ dependent_unlink (Dependent *dep, CellPos const *pos)
* it should not be used by anyone. It is an internal
* function.
**/
static gboolean
gboolean
cell_eval_content (Cell *cell)
{
static Cell *iterating = NULL;
......@@ -1023,7 +1023,7 @@ cell_eval_content (Cell *cell)
max_iteration = cell->base.sheet->workbook->iteration.max_number;
iterate :
v = gnm_expr_eval (cell->base.expression, &pos, GNM_EXPR_EVAL_STRICT);
v = gnm_expr_eval (cell->base.expression, &pos, 0);
if (v == NULL)
v = value_new_error (&pos, "Internal error");
......@@ -1087,21 +1087,6 @@ iterate :
return iterating == NULL;
}
void
cell_eval (Cell *cell)
{
g_return_if_fail (cell != NULL);
if (cell_needs_recalc (cell)) {
gboolean finished = cell_eval_content (cell);
/* This should always be the top of the stack */
g_return_if_fail (finished);
cell->base.flags &= ~DEPENDENT_NEEDS_RECALC;
}
}
/**
* dependent_eval :
* @dep :
......
......@@ -88,7 +88,15 @@ void dependents_unrelocate_free (GSList *info);
void cell_queue_recalc (Cell const *cell);
void cell_foreach_dep (Cell const *cell, DepFunc func, gpointer user);
void cell_eval (Cell *cell);
gboolean cell_eval_content (Cell *cell);
#define cell_eval(cell) \
{ \
if (cell_needs_recalc (cell)) { \
cell_eval_content (cell); \
cell->base.flags &= ~DEPENDENT_NEEDS_RECALC; \
} \
}
void sheet_region_queue_recalc (Sheet const *sheet, Range const *range);
void sheet_deps_destroy (Sheet *sheet);
......@@ -108,7 +116,6 @@ void gnm_dep_container_dump (GnmDepContainer const *deps);
} \
} while (0)
#define DEPENDENT_MAKE_TYPE(t, set_expr_handler) \
guint \
t ## _get_dep_type (void) \
......
......@@ -484,28 +484,6 @@ gnm_expr_equal (GnmExpr const *a, GnmExpr const *b)
return FALSE;
}
/**
* gnm_expr_array_intersection :
* @v: a VALUE_ARRAY
*
* Returns the upper left corner of an array.
*
* Always release the value passed in.
*
* FIXME FIXME FIXME : This will need to be reworked
* cellrange for array expressions
*
* Return value:
* duplicate of the value in the upper left of the array
**/
Value *
gnm_expr_array_intersection (Value *a)
{
Value *tmp = value_duplicate (a->v_array.vals[0][0]);
value_release (a);
return tmp;
}
static Value *
cb_range_eval (Sheet *sheet, int col, int row, Cell *cell, void *ignore)
{
......@@ -580,13 +558,37 @@ gnm_expr_extract_ref (CellRef *res, GnmExpr const *expr,
}
static Value *
expr_eval_real (GnmExpr const *expr, EvalPos const *pos,
GnmExprEvalFlags flags)
handle_empty (Value *res, GnmExprEvalFlags flags)
{
if (res == NULL)
return (flags & GNM_EXPR_EVAL_PERMIT_EMPTY)
? NULL : value_new_int (0);
if (res->type == VALUE_EMPTY) {
value_release (res);
return (flags & GNM_EXPR_EVAL_PERMIT_EMPTY)
? NULL : value_new_int (0);
}
return res;
}
/**
* gnm_expr_eval :
* @expr :
* @ep :
* @flags:
*
* if GNM_EXPR_EVAL_PERMIT_EMPTY is not set then return int(0) if the
* expression returns empty, or the value of an unused cell.
*/
Value *
gnm_expr_eval (GnmExpr const *expr, EvalPos const *pos,
GnmExprEvalFlags flags)
{
Value *res = NULL, *a = NULL, *b = NULL;
g_return_val_if_fail (expr != NULL, NULL);
g_return_val_if_fail (pos != NULL, NULL);
g_return_val_if_fail (expr != NULL, handle_empty (NULL, flags));
g_return_val_if_fail (pos != NULL, handle_empty (NULL, flags));
switch (expr->any.oper){
case GNM_EXPR_OP_EQUAL:
......@@ -597,38 +599,32 @@ expr_eval_real (GnmExpr const *expr, EvalPos const *pos,
case GNM_EXPR_OP_LTE: {
ValueCompare comp;
a = expr_eval_real (expr->binary.value_a, pos, flags);
a = gnm_expr_eval (expr->binary.value_a, pos,
flags | GNM_EXPR_EVAL_PERMIT_EMPTY);
if (a != NULL) {
if (a->type == VALUE_CELLRANGE) {
if (a->type == VALUE_CELLRANGE || a->type == VALUE_ARRAY) {
a = value_intersection (a, pos);
if (a == NULL)
return value_new_error (pos, gnumeric_err_VALUE);
} else if (a->type == VALUE_ARRAY) {
a = gnm_expr_array_intersection (a);
if (a == NULL)