Commit e296f458 authored by Jody Goldberg's avatar Jody Goldberg

Initial implementation of array formulas, along with a sample use of them

in the function MMULT.
parent 1f3071b9
......@@ -22,6 +22,9 @@ Michael
Nick Lamb
Jody Goldberg
* Completed Excel colour handling (Hopefully).
* Improved Excel format support for formulas.
* Initial implementation of array formulas.
* Worked on embryonic Excel chart code
Several translations updated: thanks to our translators
......
1999-06-29 Jody Goldberg <jgoldberg@home.com>
* src/cell.c (cell_set_formula) : Handle special case of array by
setting the entire matrix from the top left corner.
(cell_set_array_formula) : New function.
* src/cell.h : Add cell_set_array_formula.
* src/eval.c (add_cell_range_deps) : Split setup into new function.
(add_cell_range_dep) : Here.
(add_tree_deps) : Support Array operators.
* src/parser.y : Parse new array formula syntax.
(dump_tree) : rename to expr_dump_tree and move to.
* src/expr.c (expr_dump_tree) : From parser.y.
(expr_tree_get_const_int) : New function.
(expr_tree_array_formula) : New function.
(expr_tree_array_formula_corner) : New function.
(do_expr_tree_unref) : Support Array operators.
(value_area_get_at_x_y) : Renamed to value_area_fetch_x_y, fixed
thinko, completed support for relative ranges.
(value_area_get_x_y) : New function, like value_area_fetch_x_y but
does not create missing values.
(eval_expr) : Support Array operators.
(do_expr_decode_tree) : Ditto.
(do_expr_tree_invalidate_references) : Ditto.
(do_expr_tree_fixup_references) : Ditto.
* src/expr.h : Add expr_tree_get_const_int, expr_tree_array_formula,
value_area_get_x_y, and Array operators. Rename value_area_get_at_x_y.
* src/fn-lookup.c : Handle renamed value_area_fetch_x_y.
* src/fn-math.c : Ditto. Add MMULT.
* src/format.c : (format_value) Handle arrays.
(assemble_clear_cell_list) : check that a subset of an array is not
being cleared.
* src/item-cursor.c : Ditto.
* src/item-grid.c : Ditto.
* src/xml-io.c : Deal with Array formula I/O.
1999-06-29 Miguel de Icaza <miguel@nuclecu.unam.mx>
* src/print-info.c (save_range): Save the repeat ranges routine.
......
1999-06-29 Jody Goldberg <jgoldberg@home.com>
* src/cell.c (cell_set_formula) : Handle special case of array by
setting the entire matrix from the top left corner.
(cell_set_array_formula) : New function.
* src/cell.h : Add cell_set_array_formula.
* src/eval.c (add_cell_range_deps) : Split setup into new function.
(add_cell_range_dep) : Here.
(add_tree_deps) : Support Array operators.
* src/parser.y : Parse new array formula syntax.
(dump_tree) : rename to expr_dump_tree and move to.
* src/expr.c (expr_dump_tree) : From parser.y.
(expr_tree_get_const_int) : New function.
(expr_tree_array_formula) : New function.
(expr_tree_array_formula_corner) : New function.
(do_expr_tree_unref) : Support Array operators.
(value_area_get_at_x_y) : Renamed to value_area_fetch_x_y, fixed
thinko, completed support for relative ranges.
(value_area_get_x_y) : New function, like value_area_fetch_x_y but
does not create missing values.
(eval_expr) : Support Array operators.
(do_expr_decode_tree) : Ditto.
(do_expr_tree_invalidate_references) : Ditto.
(do_expr_tree_fixup_references) : Ditto.
* src/expr.h : Add expr_tree_get_const_int, expr_tree_array_formula,
value_area_get_x_y, and Array operators. Rename value_area_get_at_x_y.
* src/fn-lookup.c : Handle renamed value_area_fetch_x_y.
* src/fn-math.c : Ditto. Add MMULT.
* src/format.c : (format_value) Handle arrays.
(assemble_clear_cell_list) : check that a subset of an array is not
being cleared.
* src/item-cursor.c : Ditto.
* src/item-grid.c : Ditto.
* src/xml-io.c : Deal with Array formula I/O.
1999-06-29 Miguel de Icaza <miguel@nuclecu.unam.mx>
* src/print-info.c (save_range): Save the repeat ranges routine.
......
1999-06-29 Jody Goldberg <jgoldberg@home.com>
* src/cell.c (cell_set_formula) : Handle special case of array by
setting the entire matrix from the top left corner.
(cell_set_array_formula) : New function.
* src/cell.h : Add cell_set_array_formula.
* src/eval.c (add_cell_range_deps) : Split setup into new function.
(add_cell_range_dep) : Here.
(add_tree_deps) : Support Array operators.
* src/parser.y : Parse new array formula syntax.
(dump_tree) : rename to expr_dump_tree and move to.
* src/expr.c (expr_dump_tree) : From parser.y.
(expr_tree_get_const_int) : New function.
(expr_tree_array_formula) : New function.
(expr_tree_array_formula_corner) : New function.
(do_expr_tree_unref) : Support Array operators.
(value_area_get_at_x_y) : Renamed to value_area_fetch_x_y, fixed
thinko, completed support for relative ranges.
(value_area_get_x_y) : New function, like value_area_fetch_x_y but
does not create missing values.
(eval_expr) : Support Array operators.
(do_expr_decode_tree) : Ditto.
(do_expr_tree_invalidate_references) : Ditto.
(do_expr_tree_fixup_references) : Ditto.
* src/expr.h : Add expr_tree_get_const_int, expr_tree_array_formula,
value_area_get_x_y, and Array operators. Rename value_area_get_at_x_y.
* src/fn-lookup.c : Handle renamed value_area_fetch_x_y.
* src/fn-math.c : Ditto. Add MMULT.
* src/format.c : (format_value) Handle arrays.
(assemble_clear_cell_list) : check that a subset of an array is not
being cleared.
* src/item-cursor.c : Ditto.
* src/item-grid.c : Ditto.
* src/xml-io.c : Deal with Array formula I/O.
1999-06-29 Miguel de Icaza <miguel@nuclecu.unam.mx>
* src/print-info.c (save_range): Save the repeat ranges routine.
......
1999-06-29 Jody Goldberg <jgoldberg@home.com>
* src/cell.c (cell_set_formula) : Handle special case of array by
setting the entire matrix from the top left corner.
(cell_set_array_formula) : New function.
* src/cell.h : Add cell_set_array_formula.
* src/eval.c (add_cell_range_deps) : Split setup into new function.
(add_cell_range_dep) : Here.
(add_tree_deps) : Support Array operators.
* src/parser.y : Parse new array formula syntax.
(dump_tree) : rename to expr_dump_tree and move to.
* src/expr.c (expr_dump_tree) : From parser.y.
(expr_tree_get_const_int) : New function.
(expr_tree_array_formula) : New function.
(expr_tree_array_formula_corner) : New function.
(do_expr_tree_unref) : Support Array operators.
(value_area_get_at_x_y) : Renamed to value_area_fetch_x_y, fixed
thinko, completed support for relative ranges.
(value_area_get_x_y) : New function, like value_area_fetch_x_y but
does not create missing values.
(eval_expr) : Support Array operators.
(do_expr_decode_tree) : Ditto.
(do_expr_tree_invalidate_references) : Ditto.
(do_expr_tree_fixup_references) : Ditto.
* src/expr.h : Add expr_tree_get_const_int, expr_tree_array_formula,
value_area_get_x_y, and Array operators. Rename value_area_get_at_x_y.
* src/fn-lookup.c : Handle renamed value_area_fetch_x_y.
* src/fn-math.c : Ditto. Add MMULT.
* src/format.c : (format_value) Handle arrays.
(assemble_clear_cell_list) : check that a subset of an array is not
being cleared.
* src/item-cursor.c : Ditto.
* src/item-grid.c : Ditto.
* src/xml-io.c : Deal with Array formula I/O.
1999-06-29 Miguel de Icaza <miguel@nuclecu.unam.mx>
* src/print-info.c (save_range): Save the repeat ranges routine.
......
......@@ -287,7 +287,7 @@ gnumeric_vlookup (FunctionEvalInfo *ei, Value **args)
int compare;
const Value *v;
v = value_area_get_at_x_y (&ei->pos, args[1], 0, lp);
v = value_area_fetch_x_y (&ei->pos, args[1], 0, lp);
g_return_val_if_fail (v != NULL, NULL);
......@@ -296,7 +296,7 @@ gnumeric_vlookup (FunctionEvalInfo *ei, Value **args)
if (compare == 1){
const Value *v;
v = value_area_get_at_x_y (&ei->pos, args [1], col_idx-1, lp);
v = value_area_fetch_x_y (&ei->pos, args [1], col_idx-1, lp);
g_return_val_if_fail (v != NULL, NULL);
return value_duplicate (v);
......@@ -309,7 +309,7 @@ gnumeric_vlookup (FunctionEvalInfo *ei, Value **args)
if (approx && next_largest){
const Value *v;
v = value_area_get_at_x_y (&ei->pos, args [1], col_idx-1,
v = value_area_fetch_x_y (&ei->pos, args [1], col_idx-1,
next_largest_row);
g_return_val_if_fail (v != NULL, NULL);
return value_duplicate (v);
......@@ -367,7 +367,7 @@ gnumeric_hlookup (FunctionEvalInfo *ei, Value **args)
int compare;
const Value *v;
v = value_area_get_at_x_y (&ei->pos, args[1],lp, 0);
v = value_area_fetch_x_y (&ei->pos, args[1],lp, 0);
g_return_val_if_fail (v != NULL, NULL);
......@@ -376,7 +376,7 @@ gnumeric_hlookup (FunctionEvalInfo *ei, Value **args)
if (compare == 1){
const Value *v;
v = value_area_get_at_x_y (&ei->pos, args [1], lp, row_idx-1);
v = value_area_fetch_x_y (&ei->pos, args [1], lp, row_idx-1);
g_return_val_if_fail (v != NULL, NULL);
return value_duplicate (v);
......@@ -390,7 +390,7 @@ gnumeric_hlookup (FunctionEvalInfo *ei, Value **args)
if (approx && next_largest){
const Value *v;
v = value_area_get_at_x_y (&ei->pos, args [1],
v = value_area_fetch_x_y (&ei->pos, args [1],
next_largest_col, row_idx-1);
g_return_val_if_fail (v != NULL, NULL);
......@@ -468,10 +468,10 @@ gnumeric_lookup (FunctionEvalInfo *ei, Value **args)
touched = 0;
for (lpx=0,lpy=0;lpx<maxx && lpy<maxy;) {
const Value *v = value_area_get_at_x_y (&ei->pos, src, lpx, lpy);
const Value *v = value_area_fetch_x_y (&ei->pos, src, lpx, lpy);
compare = lookup_similar (v, args[0], next_largest, 1);
if (compare == 1)
return value_duplicate (value_duplicate (value_area_get_at_x_y (&ei->pos, dest, next_largest_x+x_offset,
return value_duplicate (value_duplicate (value_area_fetch_x_y (&ei->pos, dest, next_largest_x+x_offset,
next_largest_y+y_offset)));
if (compare < 0) {
next_largest = v;
......@@ -489,7 +489,7 @@ gnumeric_lookup (FunctionEvalInfo *ei, Value **args)
if (!next_largest)
return function_error (ei, gnumeric_err_NA);
return value_duplicate (value_area_get_at_x_y (&ei->pos, dest,
return value_duplicate (value_area_fetch_x_y (&ei->pos, dest,
next_largest_x+x_offset,
next_largest_y+y_offset));
}
......
......@@ -2305,6 +2305,123 @@ gnumeric_seriessum (FunctionEvalInfo *ei, GList *nodes)
return value_new_float (p.sum);
}
static char *help_mmult = {
N_("@FUNCTION=MMULT\n"
"@SYNTAX=MMULT(array1,array2)\n"
"@DESCRIPTION="
"SERIESSUM function Returns the matrix product of two arrays. The "
"result is an array with the same number of rows as array1 and the "
"same number of columns as array2."
"\n"
"@SEEALSO=SUMPRODUCT")
};
static int
callback_function_mmult_validate(Sheet *sheet, int col, int row,
Cell *cell, void *user_data)
{
int * item_count = user_data;
if (cell == NULL || cell->value == NULL ||
!VALUE_IS_NUMBER(cell->value))
return FALSE;
++(*item_count);
return TRUE;
}
static int
validate_range_numeric_matrix (const EvalPosition *ep, Value * matrix,
int *rows, int *cols,
char **error_string)
{
int res;
int cell_count = 0;
*cols = value_area_get_width (ep, matrix);
*rows = value_area_get_height (ep, matrix);
/* No checking needed for arrays */
if (matrix->type == VALUE_ARRAY)
return FALSE;
if (matrix->v.cell_range.cell_a.sheet !=
matrix->v.cell_range.cell_b.sheet)
{
*error_string = _("#3D MULT?");
return TRUE;
}
res = sheet_cell_foreach_range (
matrix->v.cell_range.cell_a.sheet, TRUE,
matrix->v.cell_range.cell_a.col,
matrix->v.cell_range.cell_a.row,
matrix->v.cell_range.cell_b.col,
matrix->v.cell_range.cell_b.row,
callback_function_mmult_validate,
&cell_count);
if (!res || cell_count != (*rows * *cols))
{
/* As specified in the Excel Docs */
*error_string = gnumeric_err_VALUE;
return TRUE;
}
return FALSE;
}
static Value *
gnumeric_mmult (FunctionEvalInfo *ei, Value **argv)
{
EvalPosition const * const ep = &ei->pos;
int r, rows_a, rows_b, i;
int c, cols_a, cols_b;
Value *res;
Value *values_a = argv[0];
Value *values_b = argv[1];
char *error_string = NULL;
if (validate_range_numeric_matrix (ep, values_a, &rows_a, &cols_a,
&error_string) ||
validate_range_numeric_matrix (ep, values_b, &rows_b, &cols_b,
&error_string)){
return function_error (ei, error_string);
}
/* Guarantee shape and non-zero size */
if (cols_a != rows_b || !rows_a || !rows_b || !cols_a || !cols_b)
return function_error (ei, gnumeric_err_VALUE);
res = value_array_new (cols_b, rows_a);
res = g_new (Value, 1);
res->type = VALUE_ARRAY;
res->v.array.x = cols_b;
res->v.array.y = rows_a;
res->v.array.vals = g_new (Value **, cols_b);
for (c = 0; c < cols_b; ++c){
res->v.array.vals [c] = g_new (Value *, rows_a);
for (r = 0; r < rows_a; ++r){
/* TODO TODO : Use ints for integer only areas */
float_t tmp = 0.;
for (i = 0; i < cols_a; ++i){
Value const * a =
value_area_get_x_y (ep, values_a, i, r);
Value const * b =
value_area_get_x_y (ep, values_b, c, i);
tmp += value_get_as_float (a) *
value_get_as_float (b);
}
res->v.array.vals[c][r] = value_new_float (tmp);
}
}
return res;
}
static char *help_sumproduct = {
N_("@FUNCTION=SUMPRODUCT\n"
"@SYNTAX=SUMPRODUCT(range1,range2,...)\n"
......@@ -2493,4 +2610,5 @@ void math_functions_init()
function_add_args (cat, "tanh", "f", "number", &help_tanh, gnumeric_tanh);
function_add_args (cat, "trunc", "f|f", "number,digits", &help_trunc, gnumeric_trunc);
function_add_args (cat, "pi", "", "", &help_pi, gnumeric_pi);
function_add_args (cat, "mmult", "AA", "array1,array2", &help_mmult, gnumeric_mmult);
}
......@@ -4,11 +4,13 @@ Makefile
.libs
gnumeric
gnumeric-corba
gnumeric-bonobo
test-format
test-parser
parser.c
number-match
Gnumeric-common.c
Gnumeric-skels.c
Gnumeric-skelimpl.c
Gnumeric-stubs.c
Gnumeric.h
\ No newline at end of file
Gnumeric.h
......@@ -43,6 +43,7 @@ cell_modified (Cell *cell)
void
cell_set_formula (Cell *cell, const char *text)
{
ExprTree *new_expr;
char *error_msg = _("ERROR");
const char *desired_format = NULL;
EvalPosition fp;
......@@ -51,11 +52,12 @@ cell_set_formula (Cell *cell, const char *text)
g_return_if_fail (text != NULL);
cell_modified (cell);
cell->parsed_node = expr_parse_string (&text [1],
new_expr = expr_parse_string (&text [1],
eval_pos_cell (&fp, cell),
&desired_format,
&error_msg);
if (cell->parsed_node == NULL){
if (new_expr == NULL){
cell->parsed_node = NULL;
cell->flags |= CELL_ERROR;
cell_set_rendered_text (cell, error_msg);
......@@ -63,16 +65,32 @@ cell_set_formula (Cell *cell, const char *text)
value_release (cell->value);
cell->value = NULL;
return;
} else {
}
if (new_expr->oper == OPER_ARRAY){
if (new_expr->u.array.x == 0 && new_expr->u.array.y == 0){
cell->parsed_node = new_expr;
cell_set_array_formula (cell->sheet,
cell->row->pos,
cell->col->pos,
cell->row->pos + new_expr->u.array.rows -1,
cell->col->pos + new_expr->u.array.cols -1,
new_expr->u.array.corner.func.expr);
} else
new_expr = NULL;
} else
cell->parsed_node = new_expr;
if (cell->flags & CELL_ERROR)
cell->flags &= ~CELL_ERROR;
}
if (desired_format && strcmp (cell->style->format->format, "General") == 0){
style_format_unref (cell->style->format);
cell->style->format = style_format_new (desired_format);
}
/* Don't touch things if this was part of an array not at the corner */
if (new_expr)
cell_formula_changed (cell);
}
......@@ -719,7 +737,7 @@ cell_set_text (Cell *cell, const char *text)
* - It does not queue redraws (so you have to queue the redraw yourself
* or queue a full redraw).
*
* - It does not queue any recomputations. YOu have to queue the
* - It does not queue any recomputations. You have to queue the
* recompute yourself.
*/
void
......@@ -741,6 +759,63 @@ cell_set_formula_tree_simple (Cell *cell, ExprTree *formula)
cell_formula_changed (cell);
}
/**
* cell_set_array_formula:
* @sheet: The sheet to set the formula to.
* @row_a: The top row in the destination region.
* @col_a: The left column in the destination region.
* @row_b: The bottom row in the destination region.
* @col_b: The right column in the destination region.
* @formula: an expression tree with the formula
*
* Uses cell_set_formula_tree_simple to store the formula as an
* 'array-formula'. The supplied expression is wrapped in an array
* operator for each cell in the range and scheduled for recalc. The
* upper left corner is handled as a special case and care is taken to
* out it at the head of the recalc queue.
*/
void
cell_set_array_formula (Sheet *sheet,
int row_a, int col_a, int row_b, int col_b,
ExprTree *formula)
{
int const num_rows = 1 + row_b - row_a;
int const num_cols = 1 + col_b - col_a;
int x, y;
Cell * const corner = sheet_cell_fetch (sheet, col_a, row_a);
Cell * cell = NULL;
ExprTree *wrapper = NULL;
g_return_if_fail (num_cols > 0);
g_return_if_fail (num_rows > 0);
g_return_if_fail (formula != NULL);
g_return_if_fail (corner != NULL);
wrapper = expr_tree_array_formula (0, 0, num_rows, num_cols);
wrapper->u.array.corner.func.value = NULL;
wrapper->u.array.corner.func.expr = formula;
expr_tree_ref (formula);
cell_set_formula_tree_simple (corner, wrapper);
/* The corner must be 1st on the recalc list, queue it later */
cell_unqueue_from_recalc (corner);
for (x = 0; x < num_cols; ++x)
for (y = 0; y < num_rows; ++y)
{
if (x == 0 && y == 0)
continue;
cell = sheet_cell_fetch (sheet, col_a+x,row_a+y);
wrapper = expr_tree_array_formula (x, y,
num_rows, num_cols);
wrapper->u.array.corner.cell = corner;
cell_set_formula_tree_simple (cell, wrapper);
}
/* Put the corner at the head of the recalc list */
cell_queue_recalc (corner);
}
void
cell_set_formula_tree (Cell *cell, ExprTree *formula)
{
......@@ -1422,7 +1497,7 @@ cell_get_content (Cell *cell)
}
/*
* Return the value wihtout parsing.
* Return the value without parsing.
*/
if (cell->value)
str = value_get_as_string (cell->value);
......
......@@ -122,6 +122,9 @@ void cell_content_changed (Cell *cell);
void cell_set_formula (Cell *cell, const char *text);
void cell_set_formula_tree (Cell *cell, ExprTree *formula);
void cell_set_formula_tree_simple (Cell *cell, ExprTree *formula);
void cell_set_array_formula (Sheet *sheet, int rowa, int cola,
int rowb, int colb,
ExprTree *formula);
void cell_set_format (Cell *cell, const char *format);
void cell_set_format_simple (Cell *cell, const char *format);
void cell_set_format_from_style (Cell *cell, StyleFormat *style_format);
......
......@@ -21,7 +21,7 @@
/*
* Callback information.
*
* Passed trough the workbook structure.
* Passed through the workbook structure.
*/
typedef struct {
Sheet *dest_sheet;
......
......@@ -119,28 +119,11 @@ dependency_hash_init (void)
dependency_hash = g_hash_table_new (dependency_hash_func, dependency_equal);
}
/*
* We add the dependency of Cell a in the ranges
* enclose by CellRef a and CellRef b
*
* We compute the location from cell->row->pos and cell->col->pos
*/
static void
add_cell_range_deps (Cell *cell, const CellRef *a, const CellRef *b)
add_cell_range_dep (Cell *cell, DependencyRange const * const range)
{
DependencyRange range, *result;
int col = cell->col->pos;
int row = cell->row->pos;
/* Convert to absolute cordinates */
cell_get_abs_col_row (a, col, row, &range.range.start_col, &range.range.start_row);
cell_get_abs_col_row (b, col, row, &range.range.end_col, &range.range.end_row);
range.ref_count = 0;
range.sheet = cell->sheet;
/* Look it up */
result = g_hash_table_lookup (dependency_hash, &range);
DependencyRange *result = g_hash_table_lookup (dependency_hash, range);
if (result){
GList *cl;
......@@ -158,13 +141,35 @@ add_cell_range_deps (Cell *cell, const CellRef *a, const CellRef *b)
/* Create a new DependencyRange structure */
result = g_new (DependencyRange, 1);
*result = range;
*result = *range;
result->ref_count = 1;
result->cell_list = g_list_prepend (NULL, cell);
g_hash_table_insert (dependency_hash, result, result);
}
/*
* We add the dependency of Cell a in the ranges
* enclose by CellRef a and CellRef b
*
* We compute the location from cell->row->pos and cell->col->pos
*/
static void
add_cell_range_deps (Cell *cell, const CellRef *a, const CellRef *b)
{
DependencyRange range;
int col = cell->col->pos;
int row = cell->row->pos;
/* Convert to absolute cordinates */
cell_get_abs_col_row (a, col, row, &range.range.start_col, &range.range.start_row);
cell_get_abs_col_row (b, col, row, &range.range.end_col, &range.range.end_row);
range.ref_count = 0;
range.sheet = cell->sheet;
add_cell_range_dep (cell, &range);
}
/*
* Adds the dependencies for a Value
*/
......@@ -233,6 +238,22 @@ add_tree_deps (Cell *cell, ExprTree *tree)
add_tree_deps (cell, l->data);
return;
case OPER_ARRAY:
if (tree->u.array.x != 0 || tree->u.array.y != 0){
/* Non-corner cells depend on the corner */
DependencyRange range;
Cell * corner = tree->u.array.corner.cell;
range.ref_count = 0;
range.sheet = cell->sheet;
range.range.start_col = range.range.end_col =
corner->col->pos;
range.range.start_row = range.range.end_row =
corner->row->pos;
add_cell_range_dep (cell, &range);
} else
/* Corner cell depends on the contents of the expr */
add_tree_deps (cell, tree->u.array.corner.func.expr);
return;
} /* switch */
}
......
......@@ -119,28 +119,11 @@ dependency_hash_init (void)
dependency_hash = g_hash_table_new (dependency_hash_func, dependency_equal);
}
/*
* We add the dependency of Cell a in the ranges
* enclose by CellRef a and CellRef b
*
* We compute the location from cell->row->pos and cell->col->pos
*/
static void
add_cell_range_deps (Cell *cell, const CellRef *a, const CellRef *b)
add_cell_range_dep (Cell *cell, DependencyRange const * const range)
{
DependencyRange range, *result;
int col = cell->col->pos;
int row = cell->row->pos;
/* Convert to absolute cordinates */
cell_get_abs_col_row (a, col, row, &range.range.start_col, &range.range.start_row);
cell_get_abs_col_row (b, col, row, &range.range.end_col, &range.range.end_row);
range.ref_count = 0;
range.sheet = cell->sheet;
/* Look it up */
result = g_hash_table_lookup (dependency_hash, &range);
DependencyRange *result = g_hash_table_lookup (dependency_hash, range);
if (result){
GList *cl;
......@@ -158,13 +141,35 @@ add_cell_range_deps (Cell *cell, const CellRef *a, const CellRef *b)
/* Create a new DependencyRange structure */
result = g_new (DependencyRange, 1);
*result = range;
*result = *range;
result->ref_count = 1;
result->cell_list = g_list_prepend (NULL, cell);
g_hash_table_insert (dependency_hash, result, result);
}
/*
* We add the dependency of Cell a in the ranges
* enclose by CellRef a and CellRef b
*
* We compute the location from cell->row->pos and cell->col->pos
*/
static void
add_cell_range_deps (Cell *cell, const CellRef *a, const CellRef *b)
{
DependencyRange range;
int col = cell->col->pos;
int row = cell->row->pos;
/* Convert to absolute cordinates */
cell_get_abs_col_row (a, col, row, &range.range.start_col, &range.range.start_row);
cell_get_abs_col_row (b, col, row, &range.range.end_col, &range.range.end_row);
range.ref_count = 0;
range.sheet = cell->sheet;
add_cell_range_dep (cell, &range);
}
/*
* Adds the dependencies for a Value
*/
......@@ -233,6 +238,22 @@ add_tree_deps (Cell *cell, ExprTree *tree)
add_tree_deps (cell, l->data);
return;
case OPER_ARRAY:
if (tree->u.array.x != 0 || tree->u.array.y != 0){
/* Non-corner cells depend on the corner */
DependencyRange range;
Cell * corner = tree->u.array.corner.cell;
range.ref_count = 0;