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

new. (sheet_style_find) : clarify the reference count semantics and fix

2001-11-02  Jody Goldberg <jgoldberg@home.com>

	* src/sheet-style.c (sheet_style_unlink) : new.
	(sheet_style_find) : clarify the reference count semantics and fix
	  leak.
	(cb_style_unlink) : renamed from cb_style_unref, and convert to using
	  link.
	(rstyle_dtor) : handle the style links/refs too.
	(rstyle_apply) : Use the link mechanism.
	(cell_tile_dtor) : use unlink rather than unref.
	(cell_tile_style_new) : ditto.
	(cell_tile_matrix_set) : ditto.
	(sheet_style_init) : link the default style into the sheet.
	(cb_unlink) : renamed from cb_remove_func, and converted to link.
	(sheet_style_shutdown) : default style is in the hash no need to clear
	  in manually.  Disable the hash pointer while clearing so that we
	  don't change the hash while unlinking.
	(sheet_style_set_range) : use rstyle_dtor.
	(sheet_style_set_pos) : use rstyle_dtor.
	(sheet_style_default) : fix docs.
	(sheet_style_apply_range) : move the unref in rstyle_dtor.

	* src/mstyle.c : Add some optional ref/link count debugging.
	(mstyle_new) : init link info.
	(mstyle_copy) : ditto.
	(mstyle_copy_merge) : ditto.
	(mstyle_ref) : add debug.
	(mstyle_destroy) : merge into.
	(mstyle_ref) : here.  add debug. Check link_count == 0 on destruction.
	(mstyle_ref_multiple) : replace with
	(mstyle_link_multiple) : this.
	(mstyle_link_sheet) : new routine that assigns a sheet and sets its
	 link count to 1.  If the sheet is already linked copy it and assign
	 that.
	(mstyle_link) : increment the link count for an already linked style.
	(mstyle_unlink) : unlink and unref if no longer in use.  TODO : this
	  will unlink an dependent aspects of the style.
parent 708608dd
2001-11-02 Jody Goldberg <jgoldberg@home.com>
* src/sheet-style.c (sheet_style_unlink) : new.
(sheet_style_find) : clarify the reference count semantics and fix
leak.
(cb_style_unlink) : renamed from cb_style_unref, and convert to using
link.
(rstyle_dtor) : handle the style links/refs too.
(rstyle_apply) : Use the link mechanism.
(cell_tile_dtor) : use unlink rather than unref.
(cell_tile_style_new) : ditto.
(cell_tile_matrix_set) : ditto.
(sheet_style_init) : link the default style into the sheet.
(cb_unlink) : renamed from cb_remove_func, and converted to link.
(sheet_style_shutdown) : default style is in the hash no need to clear
in manually. Disable the hash pointer while clearing so that we
don't change the hash while unlinking.
(sheet_style_set_range) : use rstyle_dtor.
(sheet_style_set_pos) : use rstyle_dtor.
(sheet_style_default) : fix docs.
(sheet_style_apply_range) : move the unref in rstyle_dtor.
* src/mstyle.c : Add some optional ref/link count debugging.
(mstyle_new) : init link info.
(mstyle_copy) : ditto.
(mstyle_copy_merge) : ditto.
(mstyle_ref) : add debug.
(mstyle_destroy) : merge into.
(mstyle_ref) : here. add debug. Check link_count == 0 on destruction.
(mstyle_ref_multiple) : replace with
(mstyle_link_multiple) : this.
(mstyle_link_sheet) : new routine that assigns a sheet and sets its
link count to 1. If the sheet is already linked copy it and assign
that.
(mstyle_link) : increment the link count for an already linked style.
(mstyle_unlink) : unlink and unref if no longer in use. TODO : this
will unlink an dependent aspects of the style.
2001-11-01 Jody Goldberg <jgoldberg@home.com>
* src/workbook-edit.c (entry_changed) : autocomplete is in the wbv now.
......
......@@ -17,6 +17,8 @@ Jody:
* Improve dbf importer.
* Make autocorrect non-modal and cleaner.
* Make autocompletion a view attribute, with a gui.
* Enable per sheet style management to support
validation, conditionals, and simply XL export.
Jukka:
* Lots of documentation added.
......
2001-11-02 Jody Goldberg <jgoldberg@home.com>
* src/sheet-style.c (sheet_style_unlink) : new.
(sheet_style_find) : clarify the reference count semantics and fix
leak.
(cb_style_unlink) : renamed from cb_style_unref, and convert to using
link.
(rstyle_dtor) : handle the style links/refs too.
(rstyle_apply) : Use the link mechanism.
(cell_tile_dtor) : use unlink rather than unref.
(cell_tile_style_new) : ditto.
(cell_tile_matrix_set) : ditto.
(sheet_style_init) : link the default style into the sheet.
(cb_unlink) : renamed from cb_remove_func, and converted to link.
(sheet_style_shutdown) : default style is in the hash no need to clear
in manually. Disable the hash pointer while clearing so that we
don't change the hash while unlinking.
(sheet_style_set_range) : use rstyle_dtor.
(sheet_style_set_pos) : use rstyle_dtor.
(sheet_style_default) : fix docs.
(sheet_style_apply_range) : move the unref in rstyle_dtor.
* src/mstyle.c : Add some optional ref/link count debugging.
(mstyle_new) : init link info.
(mstyle_copy) : ditto.
(mstyle_copy_merge) : ditto.
(mstyle_ref) : add debug.
(mstyle_destroy) : merge into.
(mstyle_ref) : here. add debug. Check link_count == 0 on destruction.
(mstyle_ref_multiple) : replace with
(mstyle_link_multiple) : this.
(mstyle_link_sheet) : new routine that assigns a sheet and sets its
link count to 1. If the sheet is already linked copy it and assign
that.
(mstyle_link) : increment the link count for an already linked style.
(mstyle_unlink) : unlink and unref if no longer in use. TODO : this
will unlink an dependent aspects of the style.
2001-11-01 Jody Goldberg <jgoldberg@home.com>
* src/workbook-edit.c (entry_changed) : autocomplete is in the wbv now.
......
2001-11-02 Jody Goldberg <jgoldberg@home.com>
* src/sheet-style.c (sheet_style_unlink) : new.
(sheet_style_find) : clarify the reference count semantics and fix
leak.
(cb_style_unlink) : renamed from cb_style_unref, and convert to using
link.
(rstyle_dtor) : handle the style links/refs too.
(rstyle_apply) : Use the link mechanism.
(cell_tile_dtor) : use unlink rather than unref.
(cell_tile_style_new) : ditto.
(cell_tile_matrix_set) : ditto.
(sheet_style_init) : link the default style into the sheet.
(cb_unlink) : renamed from cb_remove_func, and converted to link.
(sheet_style_shutdown) : default style is in the hash no need to clear
in manually. Disable the hash pointer while clearing so that we
don't change the hash while unlinking.
(sheet_style_set_range) : use rstyle_dtor.
(sheet_style_set_pos) : use rstyle_dtor.
(sheet_style_default) : fix docs.
(sheet_style_apply_range) : move the unref in rstyle_dtor.
* src/mstyle.c : Add some optional ref/link count debugging.
(mstyle_new) : init link info.
(mstyle_copy) : ditto.
(mstyle_copy_merge) : ditto.
(mstyle_ref) : add debug.
(mstyle_destroy) : merge into.
(mstyle_ref) : here. add debug. Check link_count == 0 on destruction.
(mstyle_ref_multiple) : replace with
(mstyle_link_multiple) : this.
(mstyle_link_sheet) : new routine that assigns a sheet and sets its
link count to 1. If the sheet is already linked copy it and assign
that.
(mstyle_link) : increment the link count for an already linked style.
(mstyle_unlink) : unlink and unref if no longer in use. TODO : this
will unlink an dependent aspects of the style.
2001-11-01 Jody Goldberg <jgoldberg@home.com>
* src/workbook-edit.c (entry_changed) : autocomplete is in the wbv now.
......
2001-11-02 Jody Goldberg <jgoldberg@home.com>
* src/sheet-style.c (sheet_style_unlink) : new.
(sheet_style_find) : clarify the reference count semantics and fix
leak.
(cb_style_unlink) : renamed from cb_style_unref, and convert to using
link.
(rstyle_dtor) : handle the style links/refs too.
(rstyle_apply) : Use the link mechanism.
(cell_tile_dtor) : use unlink rather than unref.
(cell_tile_style_new) : ditto.
(cell_tile_matrix_set) : ditto.
(sheet_style_init) : link the default style into the sheet.
(cb_unlink) : renamed from cb_remove_func, and converted to link.
(sheet_style_shutdown) : default style is in the hash no need to clear
in manually. Disable the hash pointer while clearing so that we
don't change the hash while unlinking.
(sheet_style_set_range) : use rstyle_dtor.
(sheet_style_set_pos) : use rstyle_dtor.
(sheet_style_default) : fix docs.
(sheet_style_apply_range) : move the unref in rstyle_dtor.
* src/mstyle.c : Add some optional ref/link count debugging.
(mstyle_new) : init link info.
(mstyle_copy) : ditto.
(mstyle_copy_merge) : ditto.
(mstyle_ref) : add debug.
(mstyle_destroy) : merge into.
(mstyle_ref) : here. add debug. Check link_count == 0 on destruction.
(mstyle_ref_multiple) : replace with
(mstyle_link_multiple) : this.
(mstyle_link_sheet) : new routine that assigns a sheet and sets its
link count to 1. If the sheet is already linked copy it and assign
that.
(mstyle_link) : increment the link count for an already linked style.
(mstyle_unlink) : unlink and unref if no longer in use. TODO : this
will unlink an dependent aspects of the style.
2001-11-01 Jody Goldberg <jgoldberg@home.com>
* src/workbook-edit.c (entry_changed) : autocomplete is in the wbv now.
......
/* vim: set sw=8: */
/*
* MStyle.c: The guts of the style engine.
*
......@@ -8,14 +9,14 @@
* Almer S. Tigelaar <almer@gnome.org>
*/
#include <config.h>
#include "str.h"
#include "mstyle.h"
#include "str.h"
#include "style-border.h"
#include "style-color.h"
#include "validation.h"
#include "pattern.h"
#include "format.h"
#include "main.h"
#include "sheet-style.h"
typedef struct {
MStyleElementType type;
......@@ -71,6 +72,7 @@ typedef struct {
struct _MStyle {
guint32 ref_count;
guint32 link_count;
Sheet *linked_sheet;
MStyleElement elements[MSTYLE_ELEMENT_MAX];
};
......@@ -136,6 +138,13 @@ const char *mstyle_names[MSTYLE_ELEMENT_MAX] = {
"Validation"
};
/* Some ref/link count debugging */
#if 0
#define d(arg) printf arg
#else
#define d(arg) do { } while (0)
#endif
guint
mstyle_hash (gconstpointer st)
{
......@@ -537,7 +546,9 @@ mstyle_new (void)
MStyle *style = g_new0 (MStyle, 1);
style->ref_count = 1;
style->link_count = 0;
style->linked_sheet = NULL;
d(("new %p\n", style));
return style;
}
......@@ -548,9 +559,11 @@ mstyle_copy (const MStyle *style)
MStyle *new_style = g_new (MStyle, 1);
new_style->ref_count = 1;
new_style->link_count = 0;
new_style->linked_sheet = NULL;
mstyle_elements_copy (new_style, style);
d(("copy %p\n", new_style));
return new_style;
}
......@@ -565,6 +578,7 @@ mstyle_copy_merge (const MStyle *orig, const MStyle *overlay)
const MStyleElement *overlay_e;
res->ref_count = 1;
res->link_count = 0;
res->linked_sheet = NULL;
res_e = res->elements;
orig_e = orig->elements;
......@@ -574,6 +588,7 @@ mstyle_copy_merge (const MStyle *orig, const MStyle *overlay)
res_e [i] = mstyle_element_ref (
(overlay_e [i].type ? overlay_e : orig_e) + i);
d(("copy merge %p\n", res));
return res;
}
......@@ -639,29 +654,84 @@ mstyle_ref (MStyle *style)
g_return_if_fail (style->ref_count > 0);
style->ref_count++;
d(("ref %p = %d\n", style, style->ref_count));
}
void
mstyle_ref_multiple (MStyle *style, int count)
mstyle_unref (MStyle *style)
{
g_return_if_fail (style->ref_count > 0);
style->ref_count += count;
d(("unref %p = %d\n", style, style->ref_count-1));
if (style->ref_count-- <= 1) {
g_return_if_fail (style->link_count == 0);
g_return_if_fail (style->linked_sheet == NULL);
if (style->elements)
mstyle_elements_unref (style->elements);
g_free (style);
}
}
int
mstyle_unref (MStyle *style)
/**
* mstyle_link_sheet :
* @style :
* @sheet :
*
* ABSORBS a reference to the style and sets the link count to 1.
*/
MStyle *
mstyle_link_sheet (MStyle *style, Sheet *sheet)
{
int res;
if (style->linked_sheet != NULL) {
MStyle *orig = style;
style = mstyle_copy (style);
mstyle_unref (orig);
g_return_if_fail (style->ref_count > 0);
/* safety test */
g_return_val_if_fail (style->linked_sheet != sheet, style);
}
res = --style->ref_count;
g_return_val_if_fail (style->link_count == 0, style);
g_return_val_if_fail (style->linked_sheet == NULL, style);
if (style->ref_count <= 0)
mstyle_destroy (style);
style->linked_sheet = sheet;
style->link_count = 1;
return res;
d(("link sheet %p = 1\n", style));
return style;
}
void
mstyle_link (MStyle *style)
{
g_return_if_fail (style->link_count > 0);
style->link_count++;
d(("link %p = %d\n", style, style->link_count));
}
void
mstyle_link_multiple (MStyle *style, int count)
{
g_return_if_fail (style->link_count > 0);
style->link_count += count;
d(("multiple link %p + %d = %d\n", style, count, style->link_count));
}
void
mstyle_unlink (MStyle *style)
{
g_return_if_fail (style->link_count > 0);
d(("unlink %p = %d\n", style, style->link_count-1));
if (style->link_count-- <= 1) {
sheet_style_unlink (style->linked_sheet, style);
style->linked_sheet = NULL;
mstyle_unref (style);
}
}
char *
......@@ -702,18 +772,6 @@ mstyle_dump (const MStyle *style)
g_free (txt);
}
void
mstyle_destroy (MStyle *style)
{
g_return_if_fail (style != NULL);
g_return_if_fail (style->ref_count == 0);
if (style->elements)
mstyle_elements_unref (style->elements);
g_free (style);
}
gboolean
mstyle_equal (const MStyle *a, const MStyle *b)
{
......
......@@ -59,11 +59,13 @@ MStyle *mstyle_new_default (void);
MStyle *mstyle_copy (const MStyle *st);
MStyle *mstyle_copy_merge (const MStyle *orig, const MStyle *overlay);
void mstyle_ref (MStyle *st);
void mstyle_ref_multiple (MStyle *st, int count);
int mstyle_unref (MStyle *st);
void mstyle_link (MStyle *st, Sheet *sheet);
void mstyle_unref (MStyle *st);
MStyle *mstyle_link_sheet (MStyle *st, Sheet *sheet);
void mstyle_link (MStyle *st);
void mstyle_link_multiple (MStyle *st, int count);
void mstyle_unlink (MStyle *st);
void mstyle_destroy (MStyle *st);
gboolean mstyle_equal (const MStyle *a, const MStyle *b);
gboolean mstyle_verify (const MStyle *st);
guint mstyle_hash (gconstpointer st);
......
......@@ -39,23 +39,37 @@ struct _SheetStyleData {
};
/**
* sheet_style_lookup :
* sheet_style_unlink
* For internal use only
*/
void
sheet_style_unlink (Sheet *sheet, MStyle *st)
{
if (sheet->style_data->style_hash != NULL)
g_hash_table_remove (sheet->style_data->style_hash, st);
}
/**
* sheet_style_find :
*
* @sheet : the sheet
* @s : a style
*
* Looks up (but does not reference) a style from the sheets collection.
* Inserting if necessary.
* Looks up a style from the sheets collection. Linking if necessary.
* ABSORBS the reference and adds a link.
*/
static MStyle *
sheet_style_find (Sheet *sheet, MStyle *s)
{
MStyle *res;
res = g_hash_table_lookup (sheet->style_data->style_hash, s);
if (res != NULL)
if (res != NULL) {
mstyle_link (res);
mstyle_unref (s);
return res;
}
mstyle_ref (s);
s = mstyle_link_sheet (s, sheet);
g_hash_table_insert (sheet->style_data->style_hash, s, s);
return s;
}
......@@ -96,20 +110,28 @@ rstyle_ctor (ReplacementStyle *res, MStyle *new_style, MStyle *pstyle, Sheet *sh
}
static void
cb_style_unref (gpointer key, gpointer value, gpointer user_data)
cb_style_unlink (gpointer key, gpointer value, gpointer user_data)
{
mstyle_unref ((MStyle *)key);
mstyle_unref ((MStyle *)value);
mstyle_unlink ((MStyle *)key);
mstyle_unlink ((MStyle *)value);
}
static void
rstyle_dtor (ReplacementStyle *rs)
{
if (rs->cache != NULL) {
g_hash_table_foreach (rs->cache, cb_style_unref, NULL);
g_hash_table_foreach (rs->cache, cb_style_unlink, NULL);
g_hash_table_destroy (rs->cache);
rs->cache = NULL;
}
if (rs->new_style != NULL) {
mstyle_unlink (rs->new_style);
rs->new_style = NULL;
}
if (rs->pstyle != NULL) {
mstyle_unref (rs->pstyle);
rs->pstyle = NULL;
}
}
/**
......@@ -132,20 +154,16 @@ rstyle_apply (MStyle **old, ReplacementStyle *rs)
if (s == NULL) {
MStyle *tmp = mstyle_copy_merge (*old, rs->pstyle);
s = sheet_style_find (rs->sheet, tmp);
mstyle_ref (*old);
mstyle_link (*old);
g_hash_table_insert (rs->cache, *old, s);
}
} else
s = rs->new_style;
if (*old != s) {
mstyle_ref (s);
if (*old) {
if (mstyle_unref (*old) == 1) {
g_hash_table_remove (rs->sheet->style_data->style_hash, *old);
mstyle_unref (*old);
}
}
mstyle_link (s);
if (*old)
mstyle_unlink (*old);
*old = s;
}
}
......@@ -237,7 +255,7 @@ cell_tile_dtor (CellTile *tile)
} else if (TILE_SIMPLE <= t && t <= TILE_MATRIX) {
int i = tile_size [t];
while (--i >= 0) {
mstyle_unref (tile->style_any.style [i]);
mstyle_unlink (tile->style_any.style [i]);
tile->style_any.style [i] = NULL;
}
} else {
......@@ -269,7 +287,7 @@ cell_tile_style_new (MStyle *style, CellTileType t)
if (style != NULL) {
int i = tile_size [t];
mstyle_ref_multiple (style, i);
mstyle_link_multiple (style, i);
while (--i >= 0)
res->style_any.style [i] = style;
}
......@@ -347,7 +365,7 @@ cell_tile_matrix_set (CellTile *t, Range const *indic, ReplacementStyle *rs)
switch (t->type) {
case TILE_SIMPLE :
mstyle_ref_multiple (tmp = t->style_simple.style [0],
mstyle_link_multiple (tmp = t->style_simple.style [0],
i = TILE_SIZE_COL * TILE_SIZE_ROW);
while (--i >= 0)
res->style [i] = tmp;
......@@ -356,13 +374,13 @@ cell_tile_matrix_set (CellTile *t, Range const *indic, ReplacementStyle *rs)
case TILE_COL :
for (i = r = 0 ; r < TILE_SIZE_ROW ; ++r)
for (c = 0 ; c < TILE_SIZE_COL ; ++c)
mstyle_ref (res->style [i++] =
t->style_col.style [c]);
mstyle_link (res->style [i++] =
t->style_col.style [c]);
break;
case TILE_ROW :
for (i = r = 0 ; r < TILE_SIZE_ROW ; ++r) {
mstyle_ref_multiple (tmp = t->style_row.style [r],
TILE_SIZE_COL);
mstyle_link_multiple (tmp = t->style_row.style [r],
TILE_SIZE_COL);
for (c = 0 ; c < TILE_SIZE_COL ; ++c)
res->style [i++] = tmp;
}
......@@ -400,34 +418,43 @@ sheet_style_init (Sheet *sheet)
sheet->style_data = g_new (SheetStyleData, 1);
sheet->style_data->style_hash =
g_hash_table_new (mstyle_hash, (GCompareFunc) mstyle_equal);
sheet->style_data->default_style = mstyle_new_default ();
sheet->style_data->default_style =
sheet_style_find (sheet, mstyle_new_default ());
sheet->style_data->styles =
cell_tile_style_new (sheet->style_data->default_style,
TILE_SIMPLE);
}
static gboolean
cb_remove_func (void *key, void *value, void *user)
cb_unlink (void *key, void *value, void *user)
{
mstyle_unref (key);
mstyle_unlink (key);
return TRUE;
}
void
sheet_style_shutdown (Sheet *sheet)
{
GHashTable *table;
g_return_if_fail (IS_SHEET (sheet));
g_return_if_fail (sheet->style_data != NULL);
cell_tile_dtor (sheet->style_data->styles);
sheet->style_data->styles = NULL;
g_hash_table_foreach_remove (sheet->style_data->style_hash,
cb_remove_func, NULL);
g_hash_table_destroy (sheet->style_data->style_hash);
sheet->style_data->default_style = NULL;
/* Clear the pointer to the hash BEFORE clearing and add a test in
* sheet_style_unlink. If we don't then it is possible/probable that
* unlinking the styles will attempt to remove them from the hash while
* we are walking it.
*/
table = sheet->style_data->style_hash;
sheet->style_data->style_hash = NULL;
g_hash_table_foreach_remove (table, cb_unlink, NULL);
g_hash_table_destroy (table);
mstyle_unref (sheet->style_data->default_style);
g_free (sheet->style_data);
sheet->style_data = NULL;
......@@ -813,7 +840,7 @@ sheet_style_set_range (Sheet *sheet, Range const *range,
cell_tile_apply (&sheet->style_data->styles,
TILE_TOP_LEVEL, 0, 0,
range, rstyle_ctor (&rs, style, NULL, sheet));
mstyle_unref (style);
rstyle_dtor (&rs);
}
/**
......@@ -838,16 +865,14 @@ sheet_style_set_pos (Sheet *sheet, int col, int row,
cell_tile_apply_pos (&sheet->style_data->styles,
TILE_TOP_LEVEL, col, row,
rstyle_ctor (&rs, style, NULL, sheet));
mstyle_unref (style);
rstyle_dtor (&rs);
}
/**
* sheet_style_default :
*
* @sheet :
*
* Return the default style for a sheet.
* NOTE : This does NOT add a reference.
* Returns a reference to default style for a sheet.
*/
MStyle *
sheet_style_default (Sheet const *sheet)
......@@ -1094,7 +1119,6 @@ sheet_style_apply_range (Sheet *sheet, Range const *range, MStyle *pstyle)
TILE_TOP_LEVEL, 0, 0,
range, rstyle_ctor (&rs, NULL, pstyle, sheet));
rstyle_dtor (&rs);
mstyle_unref (pstyle);
}
static void
......
......@@ -51,4 +51,7 @@ StyleList *sheet_style_get_list (Sheet const *sheet, Range const *r);
SpanCalcFlags sheet_style_set_list (Sheet *sheet, CellPos const *corner,
gboolean transpose, StyleList const *l);
/* For internal use only */
void sheet_style_unlink (Sheet *sheet, MStyle *st);
#endif /* GNUMERIC_SHEET_STYLE_H */
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