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

- Interbook references are workable now. They can only be produced by

  cutting and pasting a reference originally in one book into another.

2000-01-11  Jody Goldberg <jgoldberg@home.com>

	* src/workbook.c (workbook_detach_sheet) : Even books with only 1
	  sheet can have inter-sheet references.  think inter-book...
	(workbook_can_detach_sheet) : Delete we can always detach a sheet.

	* src/expr.c (cellref_relocate) : We only need to range check
	  references that are changing.

	* src/workbook.c (workbook_expr_relocate) : Copying to the same
	  logical cell in another sheet is still a copy.

	* ./src/eval.c (cell_queue_recalc_list) : Handle cross workbook
	  depends correctly.

	* src/eval.c (sheet_get_intersheet_deps) : Delete it is now unnecessary.
	(dependency_data_destroy) : invalidate dangling intersheet
	  dependancies.
parent beacfaa5
2000-01-11 Jody Goldberg <jgoldberg@home.com>
* src/workbook.c (workbook_detach_sheet) : Even books with only 1
sheet can have inter-sheet references. think inter-book...
(workbook_can_detach_sheet) : Delete we can always detach a sheet.
* src/expr.c (cellref_relocate) : We only need to range check
references that are changing.
* src/workbook.c (workbook_expr_relocate) : Copying to the same
logical cell in another sheet is still a copy.
* ./src/eval.c (cell_queue_recalc_list) : Handle cross workbook
depends correctly.
* src/eval.c (sheet_get_intersheet_deps) : Delete it is now unnecessary.
(dependency_data_destroy) : invalidate dangling intersheet
dependancies.
2000-01-10 Morten Welinder <terra@diku.dk>
* src/format.c (split_time): Improve rounding precision and avoid
......
......@@ -6,6 +6,8 @@ Miguel:
Jody:
* Parse errors in formulas.
* Improve xml export of borders to include cleared borders.
* Improve inter{sheet,book} references.
* Cut/paste bug.
* Undo.
Morten:
......
2000-01-11 Jody Goldberg <jgoldberg@home.com>
* src/workbook.c (workbook_detach_sheet) : Even books with only 1
sheet can have inter-sheet references. think inter-book...
(workbook_can_detach_sheet) : Delete we can always detach a sheet.
* src/expr.c (cellref_relocate) : We only need to range check
references that are changing.
* src/workbook.c (workbook_expr_relocate) : Copying to the same
logical cell in another sheet is still a copy.
* ./src/eval.c (cell_queue_recalc_list) : Handle cross workbook
depends correctly.
* src/eval.c (sheet_get_intersheet_deps) : Delete it is now unnecessary.
(dependency_data_destroy) : invalidate dangling intersheet
dependancies.
2000-01-10 Morten Welinder <terra@diku.dk>
* src/format.c (split_time): Improve rounding precision and avoid
......
......@@ -131,27 +131,98 @@ dependency_data_new (void)
return deps;
}
static void
cb_hash_to_list (gpointer key, gpointer value, gpointer closure)
{
GSList **list = closure;
*list = g_slist_prepend (*list, key);
}
static void
invalidate_refs (DependencyRange *deprange, Sheet *invalid_sheet)
{
ExprRelocateInfo info;
/* Copy the list since it will change underneath us. */
GList *cell_list = g_list_copy (deprange->cell_list);
/* Move the cells being depended on to infinity (and beyond) */
info.origin = deprange->range;
info.origin_sheet = info.target_sheet = invalid_sheet;
info.col_offset = SHEET_MAX_COLS;
info.row_offset = SHEET_MAX_ROWS;
while (cell_list != NULL) {
EvalPosition pos;
Cell *cell = cell_list->data;
ExprTree *newtree;
g_return_if_fail (cell != NULL);
g_return_if_fail (cell->parsed_node);
newtree = expr_relocate (cell->parsed_node,
eval_pos_cell (&pos, cell),
&info);
/* We are told this cell depends on this region
* If this is null then we did not depend on it
* and something is hosed.
*/
g_return_if_fail (newtree != NULL);
cell_set_formula_tree (cell, newtree);
cell_list = g_list_remove (cell_list, cell);
}
}
void
dependency_data_destroy (DependencyData *deps)
dependency_data_destroy (DependencyData *deps, Sheet *sheet)
{
if (deps) {
if (deps->range_hash) {
if (g_hash_table_size (deps->range_hash) != 0) {
g_warning ("Dangling range dependencies");
DependencyData *deps;
g_return_if_fail (sheet != NULL);
deps = sheet->deps;
if (deps == NULL)
return;
if (deps->range_hash) {
if (g_hash_table_size (deps->range_hash) != 0) {
/* Copy the dangling depends to avoid problems
* as the table empties under us when the danglers
* are invalidated.
*/
GSList *danglers = NULL;
g_hash_table_foreach (deps->range_hash,
&cb_hash_to_list, &danglers);
while (danglers != NULL) {
DependencyRange *deprange = danglers->data;
invalidate_refs (deprange, sheet);
danglers = g_slist_remove (danglers, deprange);
}
g_hash_table_destroy (deps->range_hash);
}
/* If anything is left. there is a problem */
if (g_hash_table_size (deps->range_hash) != 0)
g_warning ("Dangling dependancies");
g_hash_table_destroy (deps->range_hash);
deps->range_hash = NULL;
}
if (deps->single_hash) {
if (g_hash_table_size (deps->single_hash) != 0)
g_warning ("Dangling single dependencies");
g_hash_table_destroy (deps->single_hash);
}
deps->single_hash = NULL;
if (deps->single_hash) {
/* There are no intersheet depends for singletons
* so any remaining things are errors
*/
if (g_hash_table_size (deps->single_hash) != 0)
g_warning ("Dangling single dependancies");
g_free (deps);
g_hash_table_destroy (deps->single_hash);
deps->single_hash = NULL;
}
g_free (deps);
}
/**
......@@ -726,15 +797,8 @@ cell_unqueue_from_recalc (Cell *cell)
void
cell_queue_recalc_list (GList *list, gboolean freelist)
{
Workbook *wb;
Cell *first_cell;
GList *list0 = list;
if (!list)
return;
first_cell = list->data;
wb = first_cell->sheet->workbook;
Workbook *wb;
while (list) {
Cell *cell = list->data;
......@@ -744,9 +808,13 @@ cell_queue_recalc_list (GList *list, gboolean freelist)
continue;
#ifdef DEBUG_EVALUATION
if (dependency_debugging > 2)
printf ("Queuing: %s\n", cell_name (cell->col->pos, cell->row->pos));
if (dependency_debugging > 2)
printf ("Queuing: %s\n", cell_name (cell->col->pos, cell->row->pos));
#endif
/* Use the wb associated with the current cell in case we have
* cross workbook depends
*/
wb = cell->sheet->workbook;
wb->eval_queue = g_list_prepend (wb->eval_queue, cell);
cell->flags |= CELL_QUEUED_FOR_RECALC;
......@@ -905,42 +973,6 @@ sheet_dump_dependencies (const Sheet *sheet)
}
}
typedef struct {
Sheet *sheet;
GList *list;
} get_intersheet_dep_closure_t;
static void
search_intersheet_deps (gpointer key, gpointer value, gpointer closure)
{
DependencyRange *deprange = key;
get_intersheet_dep_closure_t *c = closure;
GList *l;
for (l = deprange->cell_list; l; l = l->next) {
Cell *cell = l->data;
if (cell->sheet != c->sheet)
c->list = g_list_prepend (c->list, cell);
}
}
GList *
sheet_get_intersheet_deps (Sheet *sheet)
{
get_intersheet_dep_closure_t closure;
g_return_val_if_fail (sheet->deps != NULL, NULL);
closure.sheet = sheet;
closure.list = NULL;
g_hash_table_foreach (sheet->deps->range_hash,
&search_intersheet_deps, &closure);
return closure.list;
}
typedef struct {
Range r;
GList *list;
......
......@@ -5,7 +5,7 @@
#include "cell.h"
DependencyData *dependency_data_new (void);
void dependency_data_destroy (DependencyData *deps);
void dependency_data_destroy (DependencyData *deps, Sheet *sheet);
void sheet_dump_dependencies (const Sheet *sheet);
......@@ -24,8 +24,6 @@ void cell_drop_dependencies (Cell *cell);
*/
GList *cell_get_dependencies (Cell *cell);
GList *sheet_get_intersheet_deps (Sheet *sheet);
GList *sheet_region_get_deps (Sheet *sheet, int start_col, int start_row,
int end_col, int end_row);
......
......@@ -131,27 +131,98 @@ dependency_data_new (void)
return deps;
}
static void
cb_hash_to_list (gpointer key, gpointer value, gpointer closure)
{
GSList **list = closure;
*list = g_slist_prepend (*list, key);
}
static void
invalidate_refs (DependencyRange *deprange, Sheet *invalid_sheet)
{
ExprRelocateInfo info;
/* Copy the list since it will change underneath us. */
GList *cell_list = g_list_copy (deprange->cell_list);
/* Move the cells being depended on to infinity (and beyond) */
info.origin = deprange->range;
info.origin_sheet = info.target_sheet = invalid_sheet;
info.col_offset = SHEET_MAX_COLS;
info.row_offset = SHEET_MAX_ROWS;
while (cell_list != NULL) {
EvalPosition pos;
Cell *cell = cell_list->data;
ExprTree *newtree;
g_return_if_fail (cell != NULL);
g_return_if_fail (cell->parsed_node);
newtree = expr_relocate (cell->parsed_node,
eval_pos_cell (&pos, cell),
&info);
/* We are told this cell depends on this region
* If this is null then we did not depend on it
* and something is hosed.
*/
g_return_if_fail (newtree != NULL);
cell_set_formula_tree (cell, newtree);
cell_list = g_list_remove (cell_list, cell);
}
}
void
dependency_data_destroy (DependencyData *deps)
dependency_data_destroy (DependencyData *deps, Sheet *sheet)
{
if (deps) {
if (deps->range_hash) {
if (g_hash_table_size (deps->range_hash) != 0) {
g_warning ("Dangling range dependencies");
DependencyData *deps;
g_return_if_fail (sheet != NULL);
deps = sheet->deps;
if (deps == NULL)
return;
if (deps->range_hash) {
if (g_hash_table_size (deps->range_hash) != 0) {
/* Copy the dangling depends to avoid problems
* as the table empties under us when the danglers
* are invalidated.
*/
GSList *danglers = NULL;
g_hash_table_foreach (deps->range_hash,
&cb_hash_to_list, &danglers);
while (danglers != NULL) {
DependencyRange *deprange = danglers->data;
invalidate_refs (deprange, sheet);
danglers = g_slist_remove (danglers, deprange);
}
g_hash_table_destroy (deps->range_hash);
}
/* If anything is left. there is a problem */
if (g_hash_table_size (deps->range_hash) != 0)
g_warning ("Dangling dependancies");
g_hash_table_destroy (deps->range_hash);
deps->range_hash = NULL;
}
if (deps->single_hash) {
if (g_hash_table_size (deps->single_hash) != 0)
g_warning ("Dangling single dependencies");
g_hash_table_destroy (deps->single_hash);
}
deps->single_hash = NULL;
if (deps->single_hash) {
/* There are no intersheet depends for singletons
* so any remaining things are errors
*/
if (g_hash_table_size (deps->single_hash) != 0)
g_warning ("Dangling single dependancies");
g_free (deps);
g_hash_table_destroy (deps->single_hash);
deps->single_hash = NULL;
}
g_free (deps);
}
/**
......@@ -726,15 +797,8 @@ cell_unqueue_from_recalc (Cell *cell)
void
cell_queue_recalc_list (GList *list, gboolean freelist)
{
Workbook *wb;
Cell *first_cell;
GList *list0 = list;
if (!list)
return;
first_cell = list->data;
wb = first_cell->sheet->workbook;
Workbook *wb;
while (list) {
Cell *cell = list->data;
......@@ -744,9 +808,13 @@ cell_queue_recalc_list (GList *list, gboolean freelist)
continue;
#ifdef DEBUG_EVALUATION
if (dependency_debugging > 2)
printf ("Queuing: %s\n", cell_name (cell->col->pos, cell->row->pos));
if (dependency_debugging > 2)
printf ("Queuing: %s\n", cell_name (cell->col->pos, cell->row->pos));
#endif
/* Use the wb associated with the current cell in case we have
* cross workbook depends
*/
wb = cell->sheet->workbook;
wb->eval_queue = g_list_prepend (wb->eval_queue, cell);
cell->flags |= CELL_QUEUED_FOR_RECALC;
......@@ -905,42 +973,6 @@ sheet_dump_dependencies (const Sheet *sheet)
}
}
typedef struct {
Sheet *sheet;
GList *list;
} get_intersheet_dep_closure_t;
static void
search_intersheet_deps (gpointer key, gpointer value, gpointer closure)
{
DependencyRange *deprange = key;
get_intersheet_dep_closure_t *c = closure;
GList *l;
for (l = deprange->cell_list; l; l = l->next) {
Cell *cell = l->data;
if (cell->sheet != c->sheet)
c->list = g_list_prepend (c->list, cell);
}
}
GList *
sheet_get_intersheet_deps (Sheet *sheet)
{
get_intersheet_dep_closure_t closure;
g_return_val_if_fail (sheet->deps != NULL, NULL);
closure.sheet = sheet;
closure.list = NULL;
g_hash_table_foreach (sheet->deps->range_hash,
&search_intersheet_deps, &closure);
return closure.list;
}
typedef struct {
Range r;
GList *list;
......
......@@ -5,7 +5,7 @@
#include "cell.h"
DependencyData *dependency_data_new (void);
void dependency_data_destroy (DependencyData *deps);
void dependency_data_destroy (DependencyData *deps, Sheet *sheet);
void sheet_dump_dependencies (const Sheet *sheet);
......@@ -24,8 +24,6 @@ void cell_drop_dependencies (Cell *cell);
*/
GList *cell_get_dependencies (Cell *cell);
GList *sheet_get_intersheet_deps (Sheet *sheet);
GList *sheet_region_get_deps (Sheet *sheet, int start_col, int start_row,
int end_col, int end_row);
......
......@@ -1476,18 +1476,18 @@ cellref_relocate (CellRef * const ref,
row += rinfo->row_offset;
else if (!ref->row_relative && !from_inside)
row -= rinfo->row_offset;
} else {
if (col < 0 || col >= SHEET_MAX_COLS ||
row < 0 || row >= SHEET_MAX_ROWS)
return CELLREF_RELOCATE_ERR;
} else if (from_inside) {
/* Case (c) */
if (ref->col_relative && from_inside)
if (ref->col_relative)
col -= rinfo->col_offset;
if (ref->row_relative && from_inside)
if (ref->row_relative)
row -= rinfo->row_offset;
}
if (col < 0 || col >= SHEET_MAX_COLS ||
row < 0 || row >= SHEET_MAX_ROWS)
return CELLREF_RELOCATE_ERR;
if (ref->col_relative)
col -= pos->eval.col;
if (ref->row_relative)
......
......@@ -2497,7 +2497,7 @@ sheet_destroy (Sheet *sheet)
sheet_destroy_contents (sheet);
dependency_data_destroy (sheet->deps);
dependency_data_destroy (sheet->deps, sheet);
sheet->deps = NULL;
sheet_destroy_styles (sheet);
......
......@@ -158,7 +158,6 @@ gboolean workbook_rename_sheet (Workbook *wb,
const char *old_name,
const char *new_name);
int workbook_sheet_count (Workbook *wb);
gboolean workbook_can_detach_sheet (Workbook *wb, Sheet *sheet);
GList *workbook_sheets (Workbook *wb);
char *workbook_selection_to_string (Workbook *wb, Sheet *base_sheet);
......
......@@ -2514,35 +2514,6 @@ workbook_attach_sheet (Workbook *wb, Sheet *sheet)
gtk_notebook_set_scrollable (GTK_NOTEBOOK (wb->notebook), TRUE);
}
/**
* workbook_can_detach_sheet:
* @wb: workbook.
* @sheet: the sheet that we want to detach from the workbook
*
* Returns true whether the sheet can be safely detached from the
* workbook.
*/
gboolean
workbook_can_detach_sheet (Workbook *wb, Sheet *sheet)
{
GList *dependency_list;
g_return_val_if_fail (wb != NULL, FALSE);
g_return_val_if_fail (sheet != NULL, FALSE);
g_return_val_if_fail (IS_SHEET (sheet), FALSE);
g_return_val_if_fail (sheet->workbook != NULL, FALSE);
g_return_val_if_fail (sheet->workbook == wb, FALSE);
g_return_val_if_fail (workbook_sheet_lookup (wb, sheet->name) == sheet, FALSE);
dependency_list = sheet_get_intersheet_deps (sheet);
if (!dependency_list)
return TRUE;
g_list_free (dependency_list);
return FALSE;
}
/**
* workbook_detach_sheet:
* @wb: workbook.
......@@ -2566,14 +2537,6 @@ workbook_detach_sheet (Workbook *wb, Sheet *sheet, gboolean force)
notebook = GTK_NOTEBOOK (wb->notebook);
sheets = workbook_sheet_count (sheet->workbook);
if (!force) {
if (sheets == 1)
return FALSE;
if (!workbook_can_detach_sheet (wb, sheet))
return FALSE;
}
/*
* Remove our reference to this sheet
*/
......@@ -2823,7 +2786,8 @@ workbook_expr_relocate (Workbook *wb, ExprRelocateInfo const *info)
GList *cells, *l;
GSList *undo_info = NULL;
if (info->col_offset == 0 && info->row_offset == 0)
if (info->col_offset == 0 && info->row_offset == 0 &&
info->origin_sheet == info->target_sheet)
return NULL;
g_return_val_if_fail (wb != NULL, NULL);
......
......@@ -158,7 +158,6 @@ gboolean workbook_rename_sheet (Workbook *wb,
const char *old_name,
const char *new_name);
int workbook_sheet_count (Workbook *wb);
gboolean workbook_can_detach_sheet (Workbook *wb, Sheet *sheet);
GList *workbook_sheets (Workbook *wb);
char *workbook_selection_to_string (Workbook *wb, Sheet *base_sheet);
......
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