A discussion of the style code, version 0.3
by Jody Goldberg <jody@gnome.org>


	In order to solve several of the problems associated with blank cells
and to simplify the way styles are handled a new approach to styles was
developed by Michael Meeks.   This solved all of the problems it set out to
address, but became bogged down in performance issues as attempts were made to
use it in conjunction with large sheets.  Another approach was then developed
to build upon the experience of and pitfalls of the Michael's work.

1	Programmers guide

1.1	The raw mechanics.

1.1.1	Applying a style to a region

	Simply apply the following steps

	a) Create the style:

	   GnmStyle *empty = gnm_style_new ();
	   GnmStyle *full_of_default_settings = gnm_style_new_default ().


	b) Set elements:

	   gnm_style_set_font_name (style, "Dingbats");

	        The passed const font name in this case is hashed and ref-counted
	internally for efficiency. The only case in which it is necessary to do
	manual ref-counting is if you wish to apply the same StyleColor pointer
	to several mstyles but this is unusual.

	c) Specify the range:

	   GnmRange range

	   range.start.col = 0;
	   range.start.row = 0;
	   range.end.col   = 5;
	   range.end.row   = 5;

		This specifies A1:F6.

	d) Attach it to the sheet:

	   /* Overlay a partially specified style onto the current style */
	   sheet_style_apply_range	(sheet, range, style);

	   /* Use the fully specified style in place of the current style
	   sheet_style_set_range	(sheet, range, style);
	   sheet_style_set_pos		(sheet, col, row, style);

1.1.2	Getting a style

	GnmStyle const *style = sheet_style_get (sheet, col, row);
	    or
	GnmStyle const *style = cell_get_style (cell);

	Neither of these adds a reference to the style.  If you intend to store
	the style for later use you will need to ref/unref it.

	    NB. it is important not to try and set elements on a style you
	have obtained in this way. The way to attach elements is via
	sheet_style_attach ie.

	    BAD BAD BAD
		GnmStyle const *style = cell_get_style (cell);
		gnm_style_set_font_size (style, 12.0);
	    BAD BAD BAD
	
	    Do _not_ even think of doing the above, it will produce wacky
	results;  The next phase of style work will make these things constant.

1.2	Simple points to bear in mind

	If you do the following:

	GnmStyle *style = gnm_style_new ();
	gnm_style_set_font_name (style, "dingbats");
	cell_set_style (cell, style);
	style = gnm_style_new ();
	gnm_style_set_font_bold (style, TRUE);
	cell_set_style (cell, style);

	Then you needlessly create two style regions ( for the same cell )
	where one would have sufficed. This is a degenerate case clearly,
	but happens in real code ( often when subroutines are used ). If
	you need to build up a style for a range pass an GnmStyle * around
	and build it up before applying it once.

1.3	Ref counting for dummies.

	    Since the only efficient way to keep copies of styles around is
	to reference count them the followings ( standard ) conventions are
	used namely:

	GnmStyle *style = gnm_style_new ();

	    Creating an style in this way hands you a single reference.

	sheet_style_set_pos (sheet, col, row, style)

	    Attaching a style passes that reference on to the style code.
	The way to ascertain whether a style reference has been handed on is
	to examine the prototype for the function. Should the GnmStyle *
	parameter be 'const' the reference is _not_ passed, otherwise in
	general it is ( don't get hung up on that rule ). Of course non const
	parameters are needed for eg. gnm_style_set_font_name, but these have
	no conceivable reason to fiddle with the ref-count so they don't.

	    The real gotchas happen when you decide to add a cache to your
	code to speed up style allocation. In general this is what you want
	where 'cache' denotes an GnmStyle * cache item.

	GnmStyle *cache = cache_lookup_fn (gnm_style_cache);

	if (!cache) {	/* We must create the style */
		cache = gnm_style_new ();
		gnm_style_set_font_bold (cache, bold);

		cache_insert_fn (gnm_style_cache, cache);
	}
	gnm_style_ref (cache);	/* NB. */
	return cache;
	
	NB. we 'leave' a reference in the cache. This then must be removed when
	we flush the cache with a simple gnm_style_unref.

2	Implementation details

2.1	How styles are stored

2.2	How styles are searched

2.3	How 'unique' styles are generated

	    Unique styles are needed for user feedback. This is only used in the
	cell format dialog, since the toolbar used the settings of the 'terminal'
	( first selected ) cell in a selection. The process of generating unique
	styles is is effectively a merging of all styles with the target regions.
	Conflicts are marked in the final GnmStyle result and can be tested for
	using:

		gnm_style_element_is_conflict (style, GnmStyleElement);

2.3.1	Unique borders

	    Border support is a HUGE pain.  The current code uses the get_row
	facilities for styles and does some simplistic homogeneity tests.  The
	result is correct but can be slow when applied to an entire sheet.  We
	could easily speed it up by providing a specialized accessor (get_uniform_col)
	that could take advantage of the homogeneity with a tile.

2.4	Further work

	    This document needs some explanation of how elements are stored indexed
	by type internally.

	More work could be done to decrease style fragmentation.
