<!DOCTYPE book PUBLIC "-//Davenport//DTD DocBook V3.0//EN" [
]>

<book id="gnumeric-design">
  <bookinfo>
    <title>The Gnumeric Spreadsheet Internal Design</title>
    <releaseinfo>July 2, 1998</releaseinfo>
    <author>
      <firstname>Miguel</firstname>
      <surname>de Icaza</surname>
      <affiliation>
        <shortaffil>Instituto de Ciencias Nucleares, Universidad
	  Nacional Autónoma de México
	</shortaffil>
      </affiliation>
    </author>
    <address><email>miguel@gnu.org</email></address>
    <date>September 2, 1998;  July 2, 1999.</date>
  </bookinfo>
  
  <chapter>
    <title>Gnumeric Internal Design</title>
    <sect1>
      <title>Design Goals</title>
      
      <para>
	The Gnumeric Spreadsheet is a spreadsheet that is intended to
	grow in the future to provide all of the features available in
	commercial-grade spreadsheets.
      </para>
      
      <para>
	I am not only intending to provide Gnumeric with a very good
	computation engine, but I am also interested in making the GUI
	experience for the user as pleasant as possible, and that
	includes taking a lot of ideas from existing spreadsheets.
      </para>
    </sect1>
    
    <sect1>
      <title>Target</title>
      
      <para>
	Gnumeric should be compatible as much as possible with
	Microsoft Excel in terms of the user.  This means formulae and
	expressions should be compatible unless we find a serious
	design problem in Excel.
      </para>
      
      <para>
	An example of a design problem in Excel is the fact that
	various internal functions have limits on the number of
	arguments they can take: this is just bad coding and this sort
	of limitation is unacceptable in Gnumeric.  When writing code
	for Gnumeric, no hard coded limits should be set (currently
	Gnumeric breaks this rule by having hardcoded, in a few places,
	the maximum number of columns to be 256).
      </para>
      
    <sect1>
      <title>Basic organization</title>
      
      <para>
	The Gnumeric spreadsheet is basically organized as Workbooks
	(see src/sheet.h for the definition of the workbook object).
	There might be various workbooks loaded at the same time.
	Every one of these workbooks might have a variable number of
	Sheets (see src/sheet.h for the definition of the Sheet
	object), and finally each sheet contains cells (The definition
	of a Gnumeric Cell is in src/cell.h).
      </para>
      
      <itemizedlist>
	  <listitem>
	    <para>
	      Workbooks only take care of keeping various sheets
	      together and giving a name to them.
	    </para>
	  </listitem>
	    
	  <listitem>
	    <para>
	      Item Sheets are the repository of information: cells are
	      kept here, information on the columns and rows is kept
	      here, and the styles attached to the regions are also
	      kept here.
	    </para>
	    
	    <para>
	      Sheets might have multiple views, this is required to
	      support split views and in the future to support the
	      GNOME document model.  The actual front-end to the Sheet
	      object is the SheetView object: SheetView object each
	      one has a number of components:
	    </para>
	    
	    <itemizedlist>
	      <listitem><para>
		  Their scrollbars.</para>
		
		<listitem><para> Their cell display engine (more in a
		    second).</para>
		  
		  <listitem><para> Their bar display (column and row
		      display).</para>
	    </itemizedlist>
	    
	    <para>The cell display engine is basically a modified
	      GnomeCanvas that can deal with keystrokes and can do some
	      extra spreadsheet oriented tasks.  This cell display
	      engine is of type GnumericSheet.</para>
	    
	    <para>GnumericSheet objects usually contain a number of
	      Gnome Canvas items specially designed to be used for a
	      spreadsheet: the Grid Item and the Cursor Item:</para>
	    
	    <itemizedlist>
	      
	      <listitem><para> The Grid item takes care of rendering the
		  actual contents of the Sheet object and displaying the
		  Cells in the way the user requested, this is the
		  actual "core" display engine.</para>
		
		<listitem><para> The Cursor item is the item that actually
		    draws the spreadsheet cursor.  This item, as every
		    other Gnome Canvas item can take events and this one
		    is specially interesting, as it provides the basic
		    facilities for dragging a region of cells. </para>
		  
	    </itemizedlist>
	    
	    <para>
	      During the course of a user session, Gnumeric will
	      create Items of type Editor, a special item designed to
	      display the contents of a cell as it is being typed and
	      it is syncronized with a GtkEntry (to provide an
	      Excel-like way of typing text into the cells).
	    </para>
	</itemizedlist>
	
	<para>
	  Sheets contain information for columns and rows in doubly
	  linked lists to facilitate their traversal (in the future,
	  when bottlenecks are identified, we will provide an
	  alternate quick access method based on hash tables, but the
	  information will still be linked forward and
	  backwards).
	</para>
	
	<para>
	  The column and row information is stored in GList's that
	  contain ColRowInfo structures.  These structures include a
	  number of interesting bits:
	</para>
	
	<itemizedlist>
	  
	  <listitem>
	    <para>
	      Their assigned position (or -1 if they are the "default"
	      style), field name "pos".
	    </para>
	    
	    <listitem>
	      <para>
		The actual width used in pixels (for the current
		magnification setting) as well as their logical size,
		plus the margins required in pixels for displaying
		various cell adornements.
	      </para>
	    </listitem>
	</itemizedlist>
	
	<para>
	  When a cell is allocated, both ColRowInfos (for column and
	  row) are allocated and properly linked, the cell is made to
	  point to these new structures.
	</para>
	
	<para>
	  The column ColRowInfos have a field called "data", this is a
	  linked list of Cells for every row where a cell
	  exists.
	</para>
	
	<para>
	  Cells are stored in a hash table inside the Sheet data
	  structure for quick retrieval and they are also linked
	  properly in their respective columns.
	</para>
	
	<para>
	  A cell might display information in more than one column, so
	  Gnumeric needs to keep track of which cells (column, row
	  pairs) are being managed by which cell.  This information is
	  kept in a per-row fashion in the data pointer in the
	  ColRowInfo structure for the rows.  The registration and
	  unregistration of the view areas code is on the cellspan.c
	  file.</para>
      </sect1>
      
      <sect1>
	<title>Formula storage</title>
	
	<para>
	  When a formula is encountered, Gnumeric parses the formula
	  into a tree structure.  The tree structure is later used to
	  evaluate the expression at a given location (each cordinate
	  in a cell references is stored as either an absolute
	  reference or a relative reference to the cell position).  To
	  read about the actual implementation of this, look in the
	  files <filename>gnumeric/src/expr.h</filename>,
	  <filename>gnumeric/src/expr.c</filename>.
	</para>

	<para>
	  To speed up formula duplication, Gnumeric reference counts
	  the parsed expression, this allow for quick duplication of p
	  expressions.  It should be noted that some file formats (the
	  Excel file format) uses formula references, which can
	  preserve the memory saving features of reference counting.
	</para>
      
	<para>
	  Currently Gnumeric does not provide any way to keep these
	  references, a possible scheme for saving these cells correctly 
	  would be to keep in a special list any formula being
	  saved that has a reference count bigger than one and keep
	  track of these duplicates and generate formula references in
	  the output file rather than outputing the actual formula.
	</para>
      </sect1>

      <sect1>
	<title>Resource management</title>
	
	<para>
	  Data structures in Gnumeric are lightweight, they are
	  designed to consume little memory by reusing as much
	  information as possible.  This is achieved by making common
	  information be hashed and reference-counted.  This is done
	  with strings, parser/interprester symbols and styles.
	</para>
      
	<para>
	  To learn more about this, read:
	  
	  <itemizedlist>
	    <listitem>
	      <para>for strings:
		<filename>gnumeric/src/str.c</filename> and
		<filename>gnumeric/src/str.h</filename>
	      </para>
	    </listitem>
	    
	    <listitem>
	      <para>for styles:
		<filename>gnumeric/src/style.c</filename> and
		<filename>gnumeric/src/style.h</filename>.
	      </para>
	    </listitem>
	    
	    <listitem>
	      <para>
		for symbols:
		<filename>gnumeric/src/symbol.c</filename> and
		<filename>gnumeric/src/symbol.h</filename>
	      </para>
	    </listitem>
	</para>
      </sect1>

      <sect1>
	<title>Plugins</title>

	<para>
	  Gnumeric's plugin API is very simple. Every plugin must have
	  one function: init_plugin see
	  <filename>gnumeric/src/gnm-plugin.h</filename> for the full details.
	</para>
 
      </sect1>
  </chapter>
</book>


