Commit 2092b8cf authored by Morten Welinder's avatar Morten Welinder Committed by Morten Welinder

New function. (dependents_revive_sheet): Check sanity here.

2005-06-10  Morten Welinder  <terra@gnome.org>

	* src/dependent.c (gnm_dep_container_sanity_check): New function.
	(dependents_revive_sheet): Check sanity here.
	(gnm_dep_container_dump): And here.
	(handle_outgoing_references): New function.  Properly unlink
	dependencies that reference stuff outside current sheet.
	(do_deps_destroy, do_deps_invalidate): Use
	handle_outgoing_references.

	* src/dependent.c (dependents_invalidate_sheets): Handle 3d deps
	here.  Avoid crashes by not modifying the hash while we go over
	it.
	* src/workbook.c (workbook_sheet_delete): Not here.
parent f9bbed7d
......@@ -639,7 +639,8 @@ Short Term Goals
34.5) Base sheet removal undo on just keeping a ref (DONE)
34.6) Track changes to names during sheet detach for undo. (DONE)
34.7) Track changes to cells during sheet detach for undo. (DONE)
34.8) Rework sheet reorganize dialog to new scheme.
34.8) Track changes to 3d deps during sheet detach for undo. (DONE)
34.9) Rework sheet reorganize dialog to new scheme.
Misc stuff that should be fixed
-------------------------------
......
2005-06-10 Morten Welinder <terra@gnome.org>
* src/dependent.c (gnm_dep_container_sanity_check): New function.
(dependents_revive_sheet): Check sanity here.
(gnm_dep_container_dump): And here.
(handle_outgoing_references): New function. Properly unlink
dependencies that reference stuff outside current sheet.
(do_deps_destroy, do_deps_invalidate): Use
handle_outgoing_references.
* src/dependent.c (dependents_invalidate_sheets): Handle 3d deps
here. Avoid crashes by not modifying the hash while we go over
it.
* src/workbook.c (workbook_sheet_delete): Not here.
* src/xml-sax-write.c (xml_write_sheet): Write visibility.
* src/xml-sax-read.c (xml_sax_attr_enum): New function.
......
......@@ -75,6 +75,7 @@ Morten:
* Fix sheet removal undo to also undo changes to names and
cells in other sheets.
* Save and load visibility sheet attribute.
* Fix 3D deps crash.
--------------------------------------------------------------------------
Gnumeric 1.5.1
......
2005-06-10 Morten Welinder <terra@gnome.org>
* src/dependent.c (gnm_dep_container_sanity_check): New function.
(dependents_revive_sheet): Check sanity here.
(gnm_dep_container_dump): And here.
(handle_outgoing_references): New function. Properly unlink
dependencies that reference stuff outside current sheet.
(do_deps_destroy, do_deps_invalidate): Use
handle_outgoing_references.
* src/dependent.c (dependents_invalidate_sheets): Handle 3d deps
here. Avoid crashes by not modifying the hash while we go over
it.
* src/workbook.c (workbook_sheet_delete): Not here.
* src/xml-sax-write.c (xml_write_sheet): Write visibility.
* src/xml-sax-read.c (xml_sax_attr_enum): New function.
......
......@@ -911,7 +911,8 @@ workbook_unlink_3d_dep (GnmDependent *dep)
if (wb->being_reordered)
return;
g_hash_table_remove (dep->sheet->workbook->sheet_order_dependents, dep);
g_hash_table_remove (wb->sheet_order_dependents, dep);
}
/*****************************************************************************/
......@@ -1725,7 +1726,7 @@ cb_dep_hash_destroy (G_GNUC_UNUSED gpointer key,
closure->sheet->revive.dep_exprs =
g_slist_prepend
(g_slist_prepend (closure->sheet->revive.dep_exprs, e),
dep);
dep);
}
dependent_set_expr (dep, newtree);
gnm_expr_unref (newtree);
......@@ -1846,11 +1847,12 @@ handle_referencing_names (GnmDepContainer *deps, Sheet *sheet, gboolean destroy)
if (!names)
return;
if (destroy)
if (destroy) {
accum.deps = NULL;
deps->referencing_names = NULL;
} else
accum.deps = sheet->revive.relink;
/* collect the deps of the names */
accum.deps = NULL;
accum.names = NULL;
g_hash_table_foreach (names,
(GHFunc)cb_collect_deps_of_names,
......@@ -1878,7 +1880,24 @@ handle_referencing_names (GnmDepContainer *deps, Sheet *sheet, gboolean destroy)
g_slist_free (accum.deps);
g_hash_table_destroy (names);
} else
sheet->revive.name_deps = accum.deps;
sheet->revive.relink = accum.deps;
}
static void
handle_outgoing_references (GnmDepContainer *deps, Sheet *sheet, gboolean destroy)
{
DependentFlags what = DEPENDENT_USES_NAME;
what |= sheet->workbook->during_destruction
? DEPENDENT_GOES_INTERBOOK
: DEPENDENT_GOES_INTERSHEET;
DEPENDENT_CONTAINER_FOREACH_DEPENDENT (deps, dep, {
if (dependent_is_linked (dep) && (dep->flags & what)) {
dependent_unlink (dep);
if (!destroy)
sheet->revive.relink = g_slist_prepend (sheet->revive.relink, dep);
}
});
}
static void
......@@ -1905,8 +1924,8 @@ clear_revive_info (Sheet *sheet)
g_slist_free (sheet->revive.dep_exprs);
sheet->revive.dep_exprs = NULL;
g_slist_free (sheet->revive.name_deps);
sheet->revive.name_deps = NULL;
g_slist_free (sheet->revive.relink);
sheet->revive.relink = NULL;
}
/*
......@@ -1979,14 +1998,7 @@ do_deps_destroy (Sheet *sheet)
* to other containers. If the entire workbook is going away
* just look for inter-book links.
*/
DEPENDENT_CONTAINER_FOREACH_DEPENDENT (deps, dep, {
if (dependent_is_linked (dep) &&
((dep->flags & DEPENDENT_USES_NAME) ||
!dep->sheet->being_invalidated))
unlink_expr_dep (dep,
dep->expression);
dep->flags &= ~DEPENDENT_LINK_FLAGS;
});
handle_outgoing_references (deps, sheet, TRUE);
g_free (deps);
}
......@@ -2026,16 +2038,53 @@ do_deps_invalidate (Sheet *sheet)
* to other containers. If the entire workbook is going away
* just look for inter-book links.
*/
DEPENDENT_CONTAINER_FOREACH_DEPENDENT (deps, dep, {
if (dependent_is_linked (dep) &&
((dep->flags & DEPENDENT_USES_NAME) ||
!dep->sheet->being_invalidated))
unlink_expr_dep (dep,
dep->expression);
dep->flags &= ~DEPENDENT_LINK_FLAGS;
});
handle_outgoing_references (deps, sheet, FALSE);
}
static void
cb_tweak_3d (GnmDependent *dep, G_GNUC_UNUSED gpointer value, GSList **deps)
{
*deps = g_slist_prepend (*deps, dep);
}
static void
tweak_3d (Sheet *sheet, gboolean destroy)
{
Workbook *wb = sheet->workbook;
GSList *deps = NULL, *l;
GnmExprRewriteInfo rwinfo;
if (!wb->sheet_order_dependents)
return;
g_hash_table_foreach (wb->sheet_order_dependents,
(GHFunc)cb_tweak_3d,
&deps);
rwinfo.type = GNM_EXPR_REWRITE_INVALIDATE_SHEETS;
for (l = deps; l; l = l->next) {
GnmDependent *dep = l->data;
GnmExpr *e = (GnmExpr *)dep->expression;
const GnmExpr *newtree = gnm_expr_rewrite (e, &rwinfo);
if (newtree != NULL) {
if (!destroy) {
gnm_expr_ref (e);
sheet->revive.dep_exprs =
g_slist_prepend
(g_slist_prepend (sheet->revive.dep_exprs, e),
dep);
}
dependent_set_expr (dep, newtree);
gnm_expr_unref (newtree);
dependent_link (dep);
dependent_changed (dep);
}
}
g_slist_free (deps);
}
void
dependents_invalidate_sheet (Sheet *sheet, gboolean destroy)
{
......@@ -2052,14 +2101,7 @@ void
dependents_invalidate_sheets (GSList *sheets, gboolean destroy)
{
GSList *tmp;
/*
* FIXME: this should probably take care of fixing-up 3d deps.
* A slight amount of care is needed for this since we really
* only want to do that once per workbook.
*
* Further, if !destroy, add changes to the revive data.
*/
Workbook *last_wb;
/* Mark all first. */
for (tmp = sheets; tmp; tmp = tmp->next) {
......@@ -2067,6 +2109,21 @@ dependents_invalidate_sheets (GSList *sheets, gboolean destroy)
sheet->being_invalidated = TRUE;
}
/*
* Fixup 3d refs that start or end on one of these sheets.
* Ideally we do this one per workbook, but that is not critical
* so we are not going to outright sort the sheet list.
*/
last_wb = NULL;
for (tmp = sheets; tmp; tmp = tmp->next) {
Sheet *sheet = tmp->data;
Workbook *wb = sheet->workbook;
if (wb != last_wb)
tweak_3d (sheet, destroy);
last_wb = wb;
}
/* Now invalidate. */
for (tmp = sheets; tmp; tmp = tmp->next) {
Sheet *sheet = tmp->data;
......@@ -2133,24 +2190,14 @@ dependents_revive_sheet (Sheet *sheet)
dependent_changed (dep);
}
dependents_link (sheet->revive.name_deps);
/*
* Re-link dependencies. Warning: do not link inside the
* loop as that causes interesting effects.
*/
l = NULL;
DEPENDENT_CONTAINER_FOREACH_DEPENDENT (sheet->deps, dep, {
if (!dependent_is_linked (dep))
l = g_slist_prepend (l, dep);
});
dependents_link (l);
g_slist_free (l);
dependents_link (sheet->revive.relink);
/* Re-link local names. */
gnm_named_expr_collection_relink (sheet->names);
clear_revive_info (sheet);
gnm_dep_container_sanity_check (sheet->deps);
}
void
......@@ -2392,6 +2439,8 @@ gnm_dep_container_dump (GnmDepContainer const *deps)
g_return_if_fail (deps != NULL);
gnm_dep_container_sanity_check (deps);
for (i = (SHEET_MAX_ROWS - 1) / BUCKET_SIZE; i >= 0 ; i--) {
GHashTable *hash = deps->range_hash[i];
if (hash != NULL && g_hash_table_size (hash) > 0) {
......@@ -2424,6 +2473,40 @@ gnm_dep_container_dump (GnmDepContainer const *deps)
}
}
void
gnm_dep_container_sanity_check (GnmDepContainer const *deps)
{
const GnmDependent *dep;
GHashTable *seenb4;
if (deps->head && !deps->tail)
g_warning ("Dependency container %p has head, but no tail.", deps);
if (deps->tail && !deps->head)
g_warning ("Dependency container %p has tail, but no head.", deps);
if (deps->head && deps->head->prev_dep)
g_warning ("Dependency container %p has head, but not at the beginning.", deps);
if (deps->tail && deps->tail->next_dep)
g_warning ("Dependency container %p has tail, but not at the end.", deps);
seenb4 = g_hash_table_new (g_direct_hash, g_direct_equal);
for (dep = deps->head; dep; dep = dep->next_dep) {
if (dep->prev_dep && (dep->prev_dep->next_dep != dep))
g_warning ("Dependency container %p has left double-link failure at %p.", deps, dep);
if (dep->next_dep && (dep->next_dep->prev_dep != dep))
g_warning ("Dependency container %p has right double-link failure at %p.", deps, dep);
if (!dep->next_dep && dep != deps->tail)
g_warning ("Dependency container %p ends before its tail.", deps);
if (!dependent_is_linked (dep))
g_warning ("Dependency container %p contains unlinked dependency %p.", deps, dep);
if (g_hash_table_lookup (seenb4, dep)) {
g_warning ("Dependency container %p is circular.", deps);
break;
}
g_hash_table_insert (seenb4, (gpointer)dep, (gpointer)dep);
}
g_hash_table_destroy (seenb4);
}
/**
* dependent_debug_name :
* @dep : The dependent we are interested in.
......
......@@ -109,6 +109,7 @@ void workbook_queue_all_recalc (Workbook *wb);
GnmDepContainer *gnm_dep_container_new (void);
void gnm_dep_container_dump (GnmDepContainer const *deps);
void gnm_dep_container_sanity_check (GnmDepContainer const *deps);
#define DEPENDENT_CONTAINER_FOREACH_DEPENDENT(dc, dep, code) \
do { \
......
2005-06-10 Morten Welinder <terra@gnome.org>
* dialog-sheet-order.c (cb_add_clicked): Plug leak.
2005-06-09 Andreas J. Guelzow <aguelzow@taliesin.ca>
* formula-guru.glade: add checkbox
......
......@@ -467,7 +467,7 @@ cb_add_clicked (G_GNUC_UNUSED GtkWidget *ignore, SheetManager *state)
GtkTreeIter this_iter;
GtkTreeSelection *selection = gtk_tree_view_get_selection (state->sheet_list);
int i = 0;
char *name, *old_name, *new_name;
char *name;
if (!gtk_tree_selection_get_selected (selection, NULL, &sel_iter))
gtk_list_store_append (state->model, &iter);
......@@ -484,6 +484,8 @@ cb_add_clicked (G_GNUC_UNUSED GtkWidget *ignore, SheetManager *state)
sprintf (name, _("Sheet%d"), i);
while (gtk_tree_model_iter_nth_child (GTK_TREE_MODEL (state->model),
&this_iter, NULL, n)) {
char *old_name, *new_name;
gtk_tree_model_get (GTK_TREE_MODEL (state->model), &this_iter,
SHEET_NAME, &old_name,
SHEET_NEW_NAME, &new_name,
......@@ -491,6 +493,8 @@ cb_add_clicked (G_GNUC_UNUSED GtkWidget *ignore, SheetManager *state)
n++;
match = (new_name != NULL && !strcmp (name, new_name)) ||
(old_name != NULL && !strcmp (name, old_name));
g_free (old_name);
g_free (new_name);
if (match)
break;
}
......
......@@ -33,7 +33,7 @@ struct _Sheet {
/* An alternating list of deps and ref'd expressions. */
GSList *dep_exprs;
/* A list of deps to relink. */
GSList *name_deps;
GSList *relink;
} revive;
GPtrArray *sheet_views;
......@@ -231,6 +231,7 @@ gboolean sheet_range_contains_region (Sheet const *sheet, GnmRange const *r,
void sheet_range_bounding_box (Sheet const *sheet, GnmRange *r);
/* Redraw */
#define sheet_is_visible(_sheet) ((_sheet)->visibility == GNM_SHEET_VISIBILITY_VISIBLE)
void sheet_redraw_all (Sheet const *sheet, gboolean header);
void sheet_redraw_cell (GnmCell const *cell);
void sheet_redraw_range (Sheet const *sheet, GnmRange const *r);
......
......@@ -1043,16 +1043,6 @@ workbook_sheet_add (Workbook *wb, int pos, gboolean make_dirty)
return new_sheet;
}
static void
cb_tweak_3d (GnmDependent *dep, gpointer value, GnmExprRewriteInfo *rwinfo)
{
GnmExpr const *newtree = gnm_expr_rewrite (dep->expression, rwinfo);
if (newtree != NULL) {
dependent_set_expr (dep, newtree);
gnm_expr_unref (newtree);
}
}
/**
* workbook_sheet_delete:
* @sheet: the sheet that we want to delete from its workbook
......@@ -1085,23 +1075,6 @@ workbook_sheet_delete (Sheet *sheet)
/* All is fine, remove the sheet */
pre_sheet_index_change (wb);
/* If we are not destroying things, Check for 3d refs that start or end
* on this sheet */
if (wb->sheet_order_dependents != NULL) {
GnmExprRewriteInfo rwinfo;
/*
* Why here and not in dependents_invalidate_sheet?
*/
rwinfo.type = GNM_EXPR_REWRITE_INVALIDATE_SHEETS;
sheet->being_invalidated = TRUE;
g_hash_table_foreach (wb->sheet_order_dependents,
(GHFunc)cb_tweak_3d,
&rwinfo);
sheet->being_invalidated = FALSE;
}
/* Remove our reference to this sheet */
g_ptr_array_remove_index (wb->sheets, sheet_index);
workbook_sheet_index_update (wb, sheet_index);
sheet->index_in_wb = -1;
......
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