Commit f43025f5 authored by Morten Welinder's avatar Morten Welinder

Reworked the insert/delete column/row code again. Beat on it, please!

parent aa53e19d
......@@ -11,6 +11,7 @@ And fixed these:
Morten:
* Found everyone else's bugs.
* Reworked the insert/delete column/row again.
Miguel
*
......
1999-05-21 Morten Welinder <terra@diku.dk>
* src/sheet-autofill.c (autofill_cell): Add FIXME.
* src/sheet.h (IS_SHEET): Remove cast.
* src/expr.h: Delete expr_tree_relocate.
* src/expr.c (fixup_calc_new_cellref): New function.
(do_expr_tree_fixup_references): Simplify using
fixup_calc_new_cellref.
(do_expr_tree_relocate): Delete.
(expr_tree_relocate): Delete.
* src/sheet.c (sheet_cell_formula_link): Add debug code.
(sheet_insert_col, sheet_delete_col, sheet_insert_row,
sheet_delete_row): Do fixups early.
* src/cell.c (cell_relocate): Don't relocate cell -- fixup handles
all that is needed.
* src/color.c (gs_white, gs_black, gs_light_gray, gs_dark_gray,
gs_red): Moved from src/gnumeric-sheet.c.
(gnumeric_color_context): make static.
1999-05-21 Jukka-Pekka Iivonen <iivonen@iki.fi>
* src/fn-stat.c: PERCENTRANK() added.
......
1999-05-21 Morten Welinder <terra@diku.dk>
* src/sheet-autofill.c (autofill_cell): Add FIXME.
* src/sheet.h (IS_SHEET): Remove cast.
* src/expr.h: Delete expr_tree_relocate.
* src/expr.c (fixup_calc_new_cellref): New function.
(do_expr_tree_fixup_references): Simplify using
fixup_calc_new_cellref.
(do_expr_tree_relocate): Delete.
(expr_tree_relocate): Delete.
* src/sheet.c (sheet_cell_formula_link): Add debug code.
(sheet_insert_col, sheet_delete_col, sheet_insert_row,
sheet_delete_row): Do fixups early.
* src/cell.c (cell_relocate): Don't relocate cell -- fixup handles
all that is needed.
* src/color.c (gs_white, gs_black, gs_light_gray, gs_dark_gray,
gs_red): Moved from src/gnumeric-sheet.c.
(gnumeric_color_context): make static.
1999-05-21 Jukka-Pekka Iivonen <iivonen@iki.fi>
* src/fn-stat.c: PERCENTRANK() added.
......
1999-05-21 Morten Welinder <terra@diku.dk>
* src/sheet-autofill.c (autofill_cell): Add FIXME.
* src/sheet.h (IS_SHEET): Remove cast.
* src/expr.h: Delete expr_tree_relocate.
* src/expr.c (fixup_calc_new_cellref): New function.
(do_expr_tree_fixup_references): Simplify using
fixup_calc_new_cellref.
(do_expr_tree_relocate): Delete.
(expr_tree_relocate): Delete.
* src/sheet.c (sheet_cell_formula_link): Add debug code.
(sheet_insert_col, sheet_delete_col, sheet_insert_row,
sheet_delete_row): Do fixups early.
* src/cell.c (cell_relocate): Don't relocate cell -- fixup handles
all that is needed.
* src/color.c (gs_white, gs_black, gs_light_gray, gs_dark_gray,
gs_red): Moved from src/gnumeric-sheet.c.
(gnumeric_color_context): make static.
1999-05-21 Jukka-Pekka Iivonen <iivonen@iki.fi>
* src/fn-stat.c: PERCENTRANK() added.
......
1999-05-21 Morten Welinder <terra@diku.dk>
* src/sheet-autofill.c (autofill_cell): Add FIXME.
* src/sheet.h (IS_SHEET): Remove cast.
* src/expr.h: Delete expr_tree_relocate.
* src/expr.c (fixup_calc_new_cellref): New function.
(do_expr_tree_fixup_references): Simplify using
fixup_calc_new_cellref.
(do_expr_tree_relocate): Delete.
(expr_tree_relocate): Delete.
* src/sheet.c (sheet_cell_formula_link): Add debug code.
(sheet_insert_col, sheet_delete_col, sheet_insert_row,
sheet_delete_row): Do fixups early.
* src/cell.c (cell_relocate): Don't relocate cell -- fixup handles
all that is needed.
* src/color.c (gs_white, gs_black, gs_light_gray, gs_dark_gray,
gs_red): Moved from src/gnumeric-sheet.c.
(gnumeric_color_context): make static.
1999-05-21 Jukka-Pekka Iivonen <iivonen@iki.fi>
* src/fn-stat.c: PERCENTRANK() added.
......
......@@ -1023,20 +1023,10 @@ cell_relocate (Cell *cell, int col_diff, int row_diff)
/* 2. If the cell contains a formula, relocate the formula */
if (cell->parsed_node){
sheet_cell_formula_unlink (cell);
if (col_diff != 0 || row_diff != 0){
ExprTree *new_tree;
new_tree = expr_tree_relocate (cell->parsed_node, col_diff, row_diff);
if (new_tree) {
expr_tree_unref (cell->parsed_node);
cell->parsed_node = new_tree;
}
}
/* The following call also relinks the cell. */
cell_formula_changed (cell);
}
/* 3. Move any auxiliary canvas items */
if (cell->comment)
cell_comment_reposition (cell);
......
......@@ -12,7 +12,10 @@
#include "color.h"
static int color_inited;
GdkColorContext *gnumeric_color_context;
static GdkColorContext *gnumeric_color_context;
/* Public colors: shared by all of our items in Gnumeric */
GdkColor gs_white, gs_black, gs_light_gray, gs_dark_gray, gs_red;
int
color_alloc (gushort red, gushort green, gushort blue)
......
......@@ -1451,132 +1451,6 @@ expr_decode_tree (ExprTree *tree, Sheet *sheet, int col, int row)
return do_expr_decode_tree (tree, sheet, col, row, 0);
}
static ExprTree *
do_expr_tree_relocate (ExprTree *tree, int coldiff, int rowdiff)
{
switch (tree->oper){
case OPER_ANY_BINARY: {
ExprTree *a, *b, *new_tree;
a = do_expr_tree_relocate (tree->u.binary.value_a, coldiff, rowdiff);
b = do_expr_tree_relocate (tree->u.binary.value_b, coldiff, rowdiff);
if (!a && !b) return NULL;
if (!a)
expr_tree_ref ((a = tree->u.binary.value_a));
if (!b)
expr_tree_ref ((b = tree->u.binary.value_b));
new_tree = g_new (ExprTree, 1);
new_tree->oper = tree->oper;
new_tree->ref_count = 1;
new_tree->u.binary.value_a = a;
new_tree->u.binary.value_b = b;
return new_tree;
}
case OPER_ANY_UNARY: {
ExprTree *a, *new_tree;
a = do_expr_tree_relocate (tree->u.value, coldiff, rowdiff);
if (!a) return NULL;
new_tree = g_new (ExprTree, 1);
new_tree->oper = tree->oper;
new_tree->ref_count = 1;
new_tree->u.value = a;
return new_tree;
}
case OPER_FUNCALL: {
gboolean any = FALSE;
GList *new_args = NULL;
GList *l;
for (l = tree->u.function.arg_list; l; l = l->next) {
ExprTree *arg = do_expr_tree_relocate (l->data, coldiff, rowdiff);
new_args = g_list_append (new_args, arg);
if (arg) any = TRUE;
}
if (any) {
ExprTree *new_tree;
GList *m;
for (l = tree->u.function.arg_list, m = new_args; l; l = l->next, m = m->next) {
if (m->data == NULL)
expr_tree_ref ((m->data = l->data));
}
new_tree = g_new (ExprTree, 1);
new_tree->oper = OPER_FUNCALL;
new_tree->ref_count = 1;
symbol_ref ((new_tree->u.function.symbol = tree->u.function.symbol));
new_tree->u.function.arg_list = new_args;
return new_tree;
} else {
g_list_free (new_args);
return NULL;
}
}
case OPER_VAR: {
ExprTree *new_tree;
new_tree = g_new (ExprTree, 1);
new_tree->oper = tree->oper;
new_tree->ref_count = 1;
new_tree->u.ref = tree->u.ref;
new_tree->u.ref.col -= coldiff;
new_tree->u.ref.row -= rowdiff;
return new_tree;
}
case OPER_CONSTANT: {
if (tree->u.constant->type == VALUE_CELLRANGE) {
ExprTree *new_tree;
CellRef *ref;
new_tree = g_new (ExprTree, 1);
new_tree->oper = tree->oper;
new_tree->ref_count = 1;
new_tree->u.constant = value_duplicate (tree->u.constant);
ref = &new_tree->u.constant->v.cell_range.cell_a;
ref->col -= coldiff;
ref->row -= rowdiff;
ref = &new_tree->u.constant->v.cell_range.cell_b;
ref->col -= coldiff;
ref->row -= rowdiff;
return new_tree;
} else
return NULL;
}
}
g_assert_not_reached ();
return NULL;
}
/*
* Create a copy of an expression they way it should look after being
* moved (coldiff,rowdiff) with a sheet.
*
* A return value of NULL means "no change necessary". If a copy really
* is desired in that case, a simple expr_tree_ref should do.
*/
ExprTree *
expr_tree_relocate (ExprTree *tree, int coldiff, int rowdiff)
{
g_return_val_if_fail (tree != NULL, NULL);
return do_expr_tree_relocate (tree, coldiff, rowdiff);
}
static ExprTree *
build_error_string (const char *txt)
......@@ -1620,7 +1494,7 @@ struct expr_tree_frob_references {
/* Relative move (fixup only). */
int coldelta, rowdelta;
/* In this sheet */
/* In this sheet */
Sheet *sheet;
/* Are we deleting? (fixup only). */
......@@ -1819,6 +1693,46 @@ expr_tree_invalidate_references (ExprTree *src, Sheet *src_sheet,
return dst;
}
static gboolean
fixup_calc_new_cellref (CellRef *crp, const struct expr_tree_frob_references *info)
{
CellRef oldcr = *crp;
int src_col = info->src_col;
int src_row = info->src_row;
cell_ref_make_absolute (crp, src_col, src_row);
if (info->deleting) {
if (info->colcount) {
if (crp->col >= info->col)
crp->col = MAX (crp->col - info->colcount, info->col);
if (src_col >= info->col)
src_col = MAX (src_col - info->colcount, info->col);
} else {
if (crp->row >= info->row)
crp->row = MAX (crp->row - info->rowcount, info->row);
if (src_row >= info->row)
src_row = MAX (src_row - info->rowcount, info->row);
}
} else {
if (info->colcount) {
if (crp->col >= info->col)
crp->col += info->colcount;
if (src_col >= info->col)
src_col += info->colcount;
} else {
if (crp->row >= info->row)
crp->row += info->rowcount;
if (src_row >= info->row)
src_row += info->rowcount;
}
}
cell_ref_restore_absolute (crp, &oldcr, src_col, src_row);
return (crp->col != oldcr.col || crp->row != oldcr.row);
}
static ExprTree *
do_expr_tree_fixup_references (ExprTree *src, const struct expr_tree_frob_references *info)
{
......@@ -1897,30 +1811,22 @@ do_expr_tree_fixup_references (ExprTree *src, const struct expr_tree_frob_refere
}
case OPER_VAR: {
ExprTree *dst;
CellRef cr = src->u.ref; /* Copy a structure, not a pointer. */
/* If the sheet is wrong, do nothing. */
/* If the sheet is wrong, do nothing. */
if (cr.sheet != info->sheet)
return NULL;
cell_ref_make_absolute (&cr, info->src_col, info->src_row);
if (cr.col >= info->col && cr.row >= info->row) {
ExprTree *dst;
cr.col += info->coldelta;
cr.row += info->rowdelta;
if (!fixup_calc_new_cellref (&cr, info))
return NULL;
cell_ref_restore_absolute (&cr, &src->u.ref, info->src_col, info->src_row);
dst = g_new (ExprTree, 1);
dst->oper = src->oper;
dst->ref_count = 1;
dst->u.ref = cr;
dst = g_new (ExprTree, 1);
dst->oper = src->oper;
dst->ref_count = 1;
dst->u.ref = cr;
return dst;
} else
return NULL;
return dst;
}
case OPER_CONSTANT: {
......@@ -1933,7 +1839,9 @@ do_expr_tree_fixup_references (ExprTree *src, const struct expr_tree_frob_refere
return NULL;
case VALUE_CELLRANGE: {
gboolean any = FALSE;
gboolean a_changed, b_changed;
ExprTree *dst;
Value *nv;
CellRef ca = v->v.cell_range.cell_a; /* Copy a structure, not a pointer. */
CellRef cb = v->v.cell_range.cell_b; /* Copy a structure, not a pointer. */
......@@ -1942,55 +1850,23 @@ do_expr_tree_fixup_references (ExprTree *src, const struct expr_tree_frob_refere
if (ca.sheet != info->sheet)
return NULL;
cell_ref_make_absolute (&ca, info->src_col, info->src_row);
cell_ref_make_absolute (&cb, info->src_col, info->src_row);
if (ca.col >= info->col && ca.row >= info->row) {
any = TRUE;
if (info->deleting && cell_in_range (&ca, info)) {
if (info->colcount)
ca.col = info->col;
else
ca.row = info->row;
} else {
ca.col += info->coldelta;
ca.row += info->rowdelta;
}
}
a_changed = fixup_calc_new_cellref (&ca, info);
b_changed = fixup_calc_new_cellref (&cb, info);
if (cb.col >= info->col && cb.row >= info->row) {
any = TRUE;
if (info->deleting && cell_in_range (&cb, info)) {
if (info->colcount)
cb.col = info->col - 1;
else
cb.row = info->row - 1;
} else {
cb.col += info->coldelta;
cb.row += info->rowdelta;
}
}
if (any) {
ExprTree *dst;
Value *nv;
cell_ref_restore_absolute (&ca, &v->v.cell_range.cell_a, info->src_col, info->src_row);
cell_ref_restore_absolute (&cb, &v->v.cell_range.cell_b, info->src_col, info->src_row);
if (!a_changed && !b_changed)
return NULL;
nv = g_new (Value, 1);
nv->type = v->type;
nv->v.cell_range.cell_a = ca;
nv->v.cell_range.cell_b = cb;
nv = g_new (Value, 1);
nv->type = v->type;
nv->v.cell_range.cell_a = ca;
nv->v.cell_range.cell_b = cb;
dst = g_new (ExprTree, 1);
dst->oper = src->oper;
dst->ref_count = 1;
dst->u.constant = nv;
dst = g_new (ExprTree, 1);
dst->oper = src->oper;
dst->ref_count = 1;
dst->u.constant = nv;
return dst;
} else
return NULL;
return dst;
}
case VALUE_ARRAY:
fprintf (stderr, "Reminder: FIXME in do_expr_tree_fixup_references\n");
......
......@@ -159,7 +159,6 @@ ParseErr gnumeric_expr_parser (const char *expr, Sheet *sheet,
ExprTree **tree);
ExprTree *expr_tree_duplicate (ExprTree *expr);
ExprTree *expr_tree_relocate (ExprTree *expr, int col_diff, int row_diff);
char *expr_decode_tree (ExprTree *tree, Sheet *sheet,
int col, int row);
......
......@@ -17,13 +17,8 @@
#include "cursors.h"
#include "utils.h"
#define CURSOR_COL(gsheet) gsheet->sheet_view->sheet->cursor_col
#define CURSOR_ROW(gsheet) gsheet->sheet_view->sheet->cursor_row
/* Public colors: shared by all of our items in Gnumeric */
GdkColor gs_white, gs_black, gs_light_gray, gs_dark_gray, gs_red;
#define CURSOR_COL(gsheet) (gsheet)->sheet_view->sheet->cursor_col
#define CURSOR_ROW(gsheet) (gsheet)->sheet_view->sheet->cursor_row
static GnomeCanvasClass *sheet_parent_class;
......@@ -1227,4 +1222,3 @@ gnumeric_sheet_get_type (void)
return gnumeric_sheet_type;
}
......@@ -17,13 +17,8 @@
#include "cursors.h"
#include "utils.h"
#define CURSOR_COL(gsheet) gsheet->sheet_view->sheet->cursor_col
#define CURSOR_ROW(gsheet) gsheet->sheet_view->sheet->cursor_row
/* Public colors: shared by all of our items in Gnumeric */
GdkColor gs_white, gs_black, gs_light_gray, gs_dark_gray, gs_red;
#define CURSOR_COL(gsheet) (gsheet)->sheet_view->sheet->cursor_col
#define CURSOR_ROW(gsheet) (gsheet)->sheet_view->sheet->cursor_row
static GnomeCanvasClass *sheet_parent_class;
......@@ -1227,4 +1222,3 @@ gnumeric_sheet_get_type (void)
return gnumeric_sheet_type;
}
......@@ -516,6 +516,8 @@ autofill_cell (Cell *cell, int idx, FillItem *fi)
}
case FILL_FORMULA: {
/* FIXME: we should invalidate cell refs that are now outside
the valid range. */
cell_set_formula_tree (cell, fi->v.formula);
return;
}
......
......@@ -20,6 +20,8 @@
# include <libgnorba/gnorba.h>
#endif
#undef DEBUG_CELL_FORMULA_LIST
#define GNUMERIC_SHEET_VIEW(p) GNUMERIC_SHEET (SHEET_VIEW(p)->sheet_view);
/* Used to locate cells in a sheet */
......@@ -2194,6 +2196,16 @@ sheet_cell_formula_link (Cell *cell)
sheet = cell->sheet;
#ifdef DEBUG_CELL_FORMULA_LIST
if (g_list_find (sheet->workbook->formula_cell_list, cell)) {
/* Anything that shows here is a bug. */
g_warning ("Cell %s %p re-linked\n",
cell_name (cell->col->pos, cell->row->pos),
cell);
return;
}
#endif
sheet->workbook->formula_cell_list = g_list_prepend (sheet->workbook->formula_cell_list, cell);
cell_add_dependencies (cell);
}
......@@ -2693,6 +2705,9 @@ sheet_insert_col (Sheet *sheet, int col, int count)
/* FIXME: we should probably invalidate the rightmost `count' columns here. */
/* Fixup all references to point at cells' new location. */
workbook_fixup_references (sheet->workbook, sheet, col, 0, count, 0);
/* 1. Start scaning from the last column toward the goal column
* moving all of the cells to their new location
*/
......@@ -2723,8 +2738,6 @@ sheet_insert_col (Sheet *sheet, int col, int count)
cur_col = cur_col->prev;
} while (cur_col);
workbook_fixup_references (sheet->workbook, sheet, col, 0, count, 0);
/* 2. Recompute dependencies */
deps = region_get_dependencies (sheet, col, 0, SHEET_MAX_COLS-1, SHEET_MAX_ROWS-1);
cell_queue_recalc_list (deps);
......@@ -2757,6 +2770,9 @@ sheet_delete_col (Sheet *sheet, int col, int count)
/* Invalidate all references to cells being deleted. */
workbook_invalidate_references (sheet->workbook, sheet, col, 0, count, 0);
/* Fixup all references to point at cells' new location. */
workbook_fixup_references (sheet->workbook, sheet, col, 0, -count, 0);
/* Assemble the list of columns to destroy */
destroy_list = NULL;
for (cols = sheet->cols_info; cols; cols = cols->next){
......@@ -2788,8 +2804,6 @@ sheet_delete_col (Sheet *sheet, int col, int count)
sheet_move_column (sheet, ci, ci->pos-count);
}
workbook_fixup_references (sheet->workbook, sheet, col, 0, -count, 0);
/* Recompute dependencies */
deps = region_get_dependencies (sheet, col, 0, SHEET_MAX_COLS-1, SHEET_MAX_ROWS-1);
cell_queue_recalc_list (deps);
......@@ -2820,7 +2834,7 @@ colrow_closest_above (GList *l, int pos)
* @sheet the sheet
* @row row where the shifting takes place
* @col first column
* @count numbers of columns to shift. anegative numbers will
* @count numbers of columns to shift. negative numbers will
* delete count columns, positive number will insert
* count columns.
*/
......@@ -2947,6 +2961,9 @@ sheet_insert_row (Sheet *sheet, int row, int count)
/* FIXME: we should probably invalidate the bottom `count' rows here. */
/* Fixup all references to point at cells' new location. */
workbook_fixup_references (sheet->workbook, sheet, 0, row, 0, count);
/* 1. Walk every column, see which cells are out of range */
for (cols = sheet->cols_info; cols; cols = cols->next){
ColRowInfo *ci = cols->data;
......@@ -3013,8 +3030,6 @@ sheet_insert_row (Sheet *sheet, int row, int count)
g_list_free (cell_store);
workbook_fixup_references (sheet->workbook, sheet, 0, row, 0, count);
/* 4. Recompute any changes required */
deps = region_get_dependencies (sheet, 0, row, SHEET_MAX_COLS-1, SHEET_MAX_ROWS-1);
cell_queue_recalc_list (deps);
......@@ -3042,6 +3057,9 @@ sheet_delete_row (Sheet *sheet, int row, int count)
/* Invalidate all references to cells being deleted. */
workbook_invalidate_references (sheet->workbook, sheet, 0, row, 0, count);
/* Fixup all references to point at cells' new location. */
workbook_fixup_references (sheet->workbook, sheet, 0, row, 0, -count);
/* 1. Remove cells from hash tables and grab all dangling rows */
cell_store = NULL;
for (cols = sheet->cols_info; cols; cols = cols->next){
......@@ -3056,7 +3074,7 @@ sheet_delete_row (Sheet *sheet, int row, int count)
continue;
if (cell->parsed_node)
sheet_cell_formula_unlink (cell);
sheet_cell_formula_unlink (cell);
sheet_cell_remove_from_hash (sheet, cell);
......@@ -3110,8 +3128,6 @@ sheet_delete_row (Sheet *sheet, int row, int count)
}
g_list_free (cell_store);
workbook_fixup_references (sheet->workbook, sheet, 0, row, 0, -count);
/* 4. Recompute dependencies */
deps = region_get_dependencies (sheet, 0, row, SHEET_MAX_COLS-1, SHEET_MAX_ROWS-1);
cell_queue_recalc_list (deps);
......
......@@ -173,7 +173,7 @@ struct _Sheet {
};
#define SHEET_SIGNATURE 0x12349876
#define IS_SHEET(x) (((Sheet *) x)->signature == SHEET_SIGNATURE)
#define IS_SHEET(x) ((x)->signature == SHEET_SIGNATURE)
typedef void (*sheet_col_row_callback)(Sheet *sheet, ColRowInfo *ci,
void *user_data);
......
......@@ -12,7 +12,10 @@
#include "color.h"
static int color_inited;
GdkColorContext *gnumeric_color_context;
static GdkColorContext *gnumeric_color_context;
/* Public colors: shared by all of our items in Gnumeric */
GdkColor gs_white, gs_black, gs_light_gray, gs_dark_gray, gs_red;
int
color_alloc (gushort red, gushort green, gushort blue)
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment