   This file documents the design of the GnuCash program.

   Copyright 2000 Gnumatic Incorporated

   Permission is granted to copy, distribute and/or modify this document
under the terms of the GNU Free Documentation License, Version 1.1 or
any later version published by the Free Software Foundation; with the
Invariant Sections being LIST THEIR TITLES, with the Front-Cover Texts
being LIST, and with the Back-Cover Texts being LIST. A copy of the
license is included in the section entitled "GNU Free Documentation
License".

GnuCash Design Document
***********************

This is Edition 3.4, last updated 29 December 2018, of the 'GnuCash
Design Document', version 3.4.

GNU Free Documentation License
******************************

                        Version 1.1, March 2000

     Copyright (C) 2000  Free Software Foundation, Inc.
     51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
     Everyone is permitted to copy and distribute verbatim copies
     of this license document, but changing it is not allowed.

Preamble
========

The purpose of this License is to make a manual, textbook, or other
written document "free" in the sense of freedom: to assure everyone the
effective freedom to copy and redistribute it, with or without modifying
it, either commercially or noncommercially.  Secondarily, this License
preserves for the author and publisher a way to get credit for their
work, while not being considered responsible for modifications made by
others.

   This License is a kind of "copyleft", which means that derivative
works of the document must themselves be free in the same sense.  It
complements the GNU General Public License, which is a copyleft license
designed for free software.

   We have designed this License in order to use it for manuals for free
software, because free software needs free documentation: a free program
should come with manuals providing the same freedoms that the software
does.  But this License is not limited to software manuals; it can be
used for any textual work, regardless of subject matter or whether it is
published as a printed book.  We recommend this License principally for
works whose purpose is instruction or reference.

APPLICABILITY AND DEFINITIONS
=============================

This License applies to any manual or other work that contains a notice
placed by the copyright holder saying it can be distributed under the
terms of this License.  The "Document", below, refers to any such manual
or work.  Any member of the public is a licensee, and is addressed as
"you".

   A "Modified Version" of the Document means any work containing the
Document or a portion of it, either copied verbatim, or with
modifications and/or translated into another language.

   A "Secondary Section" is a named appendix or a front-matter section
of the Document that deals exclusively with the relationship of the
publishers or authors of the Document to the Document's overall subject
(or to related matters) and contains nothing that could fall directly
within that overall subject.  (For example, if the Document is in part a
textbook of mathematics, a Secondary Section may not explain any
mathematics.)  The relationship could be a matter of historical
connection with the subject or with related matters, or of legal,
commercial, philosophical, ethical or political position regarding them.

   The "Invariant Sections" are certain Secondary Sections whose titles
are designated, as being those of Invariant Sections, in the notice that
says that the Document is released under this License.

   The "Cover Texts" are certain short passages of text that are listed,
as Front-Cover Texts or Back-Cover Texts, in the notice that says that
the Document is released under this License.

   A "Transparent" copy of the Document means a machine-readable copy,
represented in a format whose specification is available to the general
public, whose contents can be viewed and edited directly and
straightforwardly with generic text editors or (for images composed of
pixels) generic paint programs or (for drawings) some widely available
drawing editor, and that is suitable for input to text formatters or for
automatic translation to a variety of formats suitable for input to text
formatters.  A copy made in an otherwise Transparent file format whose
markup has been designed to thwart or discourage subsequent modification
by readers is not Transparent.  A copy that is not "Transparent" is
called "Opaque".

   Examples of suitable formats for Transparent copies include plain
ASCII without markup, Texinfo input format, LaTeX input format, SGML or
XML using a publicly available DTD, and standard-conforming simple HTML
designed for human modification.  Opaque formats include PostScript,
PDF, proprietary formats that can be read and edited only by proprietary
word processors, SGML or XML for which the DTD and/or processing tools
are not generally available, and the machine-generated HTML produced by
some word processors for output purposes only.

   The "Title Page" means, for a printed book, the title page itself,
plus such following pages as are needed to hold, legibly, the material
this License requires to appear in the title page.  For works in formats
which do not have any title page as such, "Title Page" means the text
near the most prominent appearance of the work's title, preceding the
beginning of the body of the text.

VERBATIM COPYING
================

You may copy and distribute the Document in any medium, either
commercially or noncommercially, provided that this License, the
copyright notices, and the license notice saying this License applies to
the Document are reproduced in all copies, and that you add no other
conditions whatsoever to those of this License.  You may not use
technical measures to obstruct or control the reading or further copying
of the copies you make or distribute.  However, you may accept
compensation in exchange for copies.  If you distribute a large enough
number of copies you must also follow the conditions in section 3.

   You may also lend copies, under the same conditions stated above, and
you may publicly display copies.

COPYING IN QUANTITY
===================

If you publish printed copies of the Document numbering more than 100,
and the Document's license notice requires Cover Texts, you must enclose
the copies in covers that carry, clearly and legibly, all these Cover
Texts: Front-Cover Texts on the front cover, and Back-Cover Texts on the
back cover.  Both covers must also clearly and legibly identify you as
the publisher of these copies.  The front cover must present the full
title with all words of the title equally prominent and visible.  You
may add other material on the covers in addition.  Copying with changes
limited to the covers, as long as they preserve the title of the
Document and satisfy these conditions, can be treated as verbatim
copying in other respects.

   If the required texts for either cover are too voluminous to fit
legibly, you should put the first ones listed (as many as fit
reasonably) on the actual cover, and continue the rest onto adjacent
pages.

   If you publish or distribute Opaque copies of the Document numbering
more than 100, you must either include a machine-readable Transparent
copy along with each Opaque copy, or state in or with each Opaque copy a
publicly-accessible computer-network location containing a complete
Transparent copy of the Document, free of added material, which the
general network-using public has access to download anonymously at no
charge using public-standard network protocols.  If you use the latter
option, you must take reasonably prudent steps, when you begin
distribution of Opaque copies in quantity, to ensure that this
Transparent copy will remain thus accessible at the stated location
until at least one year after the last time you distribute an Opaque
copy (directly or through your agents or retailers) of that edition to
the public.

   It is requested, but not required, that you contact the authors of
the Document well before redistributing any large number of copies, to
give them a chance to provide you with an updated version of the
Document.

MODIFICATIONS
=============

You may copy and distribute a Modified Version of the Document under the
conditions of sections 2 and 3 above, provided that you release the
Modified Version under precisely this License, with the Modified Version
filling the role of the Document, thus licensing distribution and
modification of the Modified Version to whoever possesses a copy of it.
In addition, you must do these things in the Modified Version:

  A. Use in the Title Page (and on the covers, if any) a title distinct
     from that of the Document, and from those of previous versions
     (which should, if there were any, be listed in the History section
     of the Document).  You may use the same title as a previous version
     if the original publisher of that version gives permission.

  B. List on the Title Page, as authors, one or more persons or entities
     responsible for authorship of the modifications in the Modified
     Version, together with at least five of the principal authors of
     the Document (all of its principal authors, if it has less than
     five).

  C. State on the Title page the name of the publisher of the Modified
     Version, as the publisher.

  D. Preserve all the copyright notices of the Document.

  E. Add an appropriate copyright notice for your modifications adjacent
     to the other copyright notices.

  F. Include, immediately after the copyright notices, a license notice
     giving the public permission to use the Modified Version under the
     terms of this License, in the form shown in the Addendum below.

  G. Preserve in that license notice the full lists of Invariant
     Sections and required Cover Texts given in the Document's license
     notice.

  H. Include an unaltered copy of this License.

  I. Preserve the section entitled "History", and its title, and add to
     it an item stating at least the title, year, new authors, and
     publisher of the Modified Version as given on the Title Page.  If
     there is no section entitled "History" in the Document, create one
     stating the title, year, authors, and publisher of the Document as
     given on its Title Page, then add an item describing the Modified
     Version as stated in the previous sentence.

  J. Preserve the network location, if any, given in the Document for
     public access to a Transparent copy of the Document, and likewise
     the network locations given in the Document for previous versions
     it was based on.  These may be placed in the "History" section.
     You may omit a network location for a work that was published at
     least four years before the Document itself, or if the original
     publisher of the version it refers to gives permission.

  K. In any section entitled "Acknowledgements" or "Dedications",
     preserve the section's title, and preserve in the section all the
     substance and tone of each of the contributor acknowledgements
     and/or dedications given therein.

  L. Preserve all the Invariant Sections of the Document, unaltered in
     their text and in their titles.  Section numbers or the equivalent
     are not considered part of the section titles.

  M. Delete any section entitled "Endorsements".  Such a section may not
     be included in the Modified Version.

  N. Do not retitle any existing section as "Endorsements" or to
     conflict in title with any Invariant Section.

   If the Modified Version includes new front-matter sections or
appendices that qualify as Secondary Sections and contain no material
copied from the Document, you may at your option designate some or all
of these sections as invariant.  To do this, add their titles to the
list of Invariant Sections in the Modified Version's license notice.
These titles must be distinct from any other section titles.

   You may add a section entitled "Endorsements", provided it contains
nothing but endorsements of your Modified Version by various parties-for
example, statements of peer review or that the text has been approved by
an organization as the authoritative definition of a standard.

   You may add a passage of up to five words as a Front-Cover Text, and
a passage of up to 25 words as a Back-Cover Text, to the end of the list
of Cover Texts in the Modified Version.  Only one passage of Front-Cover
Text and one of Back-Cover Text may be added by (or through arrangements
made by) any one entity.  If the Document already includes a cover text
for the same cover, previously added by you or by arrangement made by
the same entity you are acting on behalf of, you may not add another;
but you may replace the old one, on explicit permission from the
previous publisher that added the old one.

   The author(s) and publisher(s) of the Document do not by this License
give permission to use their names for publicity for or to assert or
imply endorsement of any Modified Version.

COMBINING DOCUMENTS
===================

You may combine the Document with other documents released under this
License, under the terms defined in section 4 above for modified
versions, provided that you include in the combination all of the
Invariant Sections of all of the original documents, unmodified, and
list them all as Invariant Sections of your combined work in its license
notice.

   The combined work need only contain one copy of this License, and
multiple identical Invariant Sections may be replaced with a single
copy.  If there are multiple Invariant Sections with the same name but
different contents, make the title of each such section unique by adding
at the end of it, in parentheses, the name of the original author or
publisher of that section if known, or else a unique number.  Make the
same adjustment to the section titles in the list of Invariant Sections
in the license notice of the combined work.

   In the combination, you must combine any sections entitled "History"
in the various original documents, forming one section entitled
"History"; likewise combine any sections entitled "Acknowledgements",
and any sections entitled "Dedications".  You must delete all sections
entitled "Endorsements."

COLLECTIONS OF DOCUMENTS
========================

You may make a collection consisting of the Document and other documents
released under this License, and replace the individual copies of this
License in the various documents with a single copy that is included in
the collection, provided that you follow the rules of this License for
verbatim copying of each of the documents in all other respects.

   You may extract a single document from such a collection, and
distribute it individually under this License, provided you insert a
copy of this License into the extracted document, and follow this
License in all other respects regarding verbatim copying of that
document.

AGGREGATION WITH INDEPENDENT WORKS
==================================

A compilation of the Document or its derivatives with other separate and
independent documents or works, in or on a volume of a storage or
distribution medium, does not as a whole count as a Modified Version of
the Document, provided no compilation copyright is claimed for the
compilation.  Such a compilation is called an "aggregate", and this
License does not apply to the other self-contained works thus compiled
with the Document, on account of their being thus compiled, if they are
not themselves derivative works of the Document.

   If the Cover Text requirement of section 3 is applicable to these
copies of the Document, then if the Document is less than one quarter of
the entire aggregate, the Document's Cover Texts may be placed on covers
that surround only the Document within the aggregate.  Otherwise they
must appear on covers around the whole aggregate.

TRANSLATION
===========

Translation is considered a kind of modification, so you may distribute
translations of the Document under the terms of section 4.  Replacing
Invariant Sections with translations requires special permission from
their copyright holders, but you may include translations of some or all
Invariant Sections in addition to the original versions of these
Invariant Sections.  You may include a translation of this License
provided that you also include the original English version of this
License.  In case of a disagreement between the translation and the
original English version of this License, the original English version
will prevail.

TERMINATION
===========

You may not copy, modify, sublicense, or distribute the Document except
as expressly provided for under this License.  Any other attempt to
copy, modify, sublicense or distribute the Document is void, and will
automatically terminate your rights under this License.  However,
parties who have received copies, or rights, from you under this License
will not have their licenses terminated so long as such parties remain
in full compliance.

FUTURE REVISIONS OF THIS LICENSE
================================

The Free Software Foundation may publish new, revised versions of the
GNU Free Documentation License from time to time.  Such new versions
will be similar in spirit to the present version, but may differ in
detail to address new problems or concerns.  See
http://www.gnu.org/copyleft/.

   Each version of the License is given a distinguishing version number.
If the Document specifies that a particular numbered version of this
License "or any later version" applies to it, you have the option of
following the terms and conditions either of that specified version or
of any later version that has been published (not as a draft) by the
Free Software Foundation.  If the Document does not specify a version
number of this License, you may choose any version ever published (not
as a draft) by the Free Software Foundation.

ADDENDUM: How to use this License for your documents
====================================================

To use this License in a document you have written, include a copy of
the License in the document and put the following copyright and license
notices just after the title page:

     Copyright (c)  YEAR  YOUR NAME.
     Permission is granted to copy, distribute and/or modify this document
     under the terms of the GNU Free Documentation License, Version 1.1
     or any later version published by the Free Software Foundation;
     with the Invariant Sections being LIST THEIR TITLES, with the
     Front-Cover Texts being LIST, and with the Back-Cover Texts being LIST.
     A copy of the license is included in the section entitled "GNU
     Free Documentation License".

   If you have no Invariant Sections, write "with no Invariant Sections"
instead of saying which ones are invariant.  If you have no Front-Cover
Texts, write "no Front-Cover Texts" instead of "Front-Cover Texts being
LIST"; likewise for Back-Cover Texts.

   If your document contains nontrivial examples of program code, we
recommend releasing these examples in parallel under your choice of free
software license, such as the GNU General Public License, to permit
their use in free software.

Introduction
************

*This whole document is completely outdated.  Don't read this.  All
function names and every described structure has changed completely.
Only read this if you want to know how gnucash looked like in 1999.
This is completely outdated!*

   This document defines the design and architecture of the GnuCash
program, an application for tracking finances.  GnuCash is composed of
several subsystems or modules.  This document describes each module,
specifying its interface and, where appropriate, its implementation, as
well as describing the interactions between each module.

Who Should Read This Document?
==============================

Anyone who plans on making a significant change or addition to GnuCash's
functionality should read this document.  By adhering to the structure
presented here, your contribution will be more likely to work correctly
with existing and future features.

Goals
=====

GnuCash is intended to be a finance and accounting program for
individuals and small businesses.  As such, it should have the following
primary features:

   * A sound underlying model for financial entities such as currencies,
     transactions, and accounts.

   * A user interface which provides an efficient way to accomplish
     common tasks, such as transaction entry, account reconciliation,
     etc.

   * The ability to generate and print standard financial reports such
     as Income Statements, Balance Sheets, etc.

   * The ability to generate and print graphs of financial information.

   A more comprehensive list of current and planned features for GnuCash
is located at <http://cvs.gnucash.org/linux/gnucash/projects.html>.

1 Architectural Overview
************************

*This whole document is completely outdated.  Don't read this.  All
function names and every described structure has changed completely.
Only read this if you want to know how gnucash looked like in 1999.
This is completely outdated!*

   GnuCash is written primarily in two languages: C and Scheme.  The
engine/server is written in C primarily for speed, portability,
stability and historical purposes.  Much of the day-to-day workhorse
code is written in Scheme, primarily for its power, expressiveness and
ease of development.  The user interface is Gtk/Gnome, some of it
written in C, some in scheme, and some with the GUI designer tool Glade
<glade.pn.org>.

   GnuCash is modular, thereby allowing separate individuals to
maintain, develop and enhance certain modules without disturbing the
overall development.  (Never mind that modules help avoid spaghetti code
and nasty, ugly hacks).  The interfaces between modules are documented,
and, for the most part, stable and unchanging.

   GnuCash currently consists of the following modules:

1.1 The Engine
==============

The "Engine" (located under the 'src/engine' directory in the GnuCash
codebase) provides an interface for creating, manipulating, and
destroying three basic financial entities: Accounts, Transactions (known
as Journal Entries in accounting practice), and Splits (known as Ledger
Entries).  These three entities are the central data structures of the
GnuCash financial data model.

   The Engine code contains no GUI code whatsoever.

1.1.1 Query
-----------

The "Query" module ('src/engine/Query.*') provides an interface into the
engine for finding transactions based on a set of criteria, such as
description, date posted, account membership, etc.  Simple queries can
be combined using standard boolean operators.

1.1.2 File I/O
--------------

The "File I/O" module ('src/engine/FileIO.*') provides an interface for
reading and writing a set of Accounts, Transactions, and Splits to a
binary file.  This module is deprecated.

1.1.3 XML I/O
-------------

The "XML I/O" module ('src/engine/*xml*.*' and 'src/engine/*sixtp*.*')
provides an interface for reading and writing the engine information to
an XML format.

1.1.4 Backend
-------------

The "Backend" module ('src/engine/Backend*.*') provides hooks to allow
different modules to be used for storing and retrieving Engine data.
There are two backends currently under development, a Postgresql backend
('src/engine/sql/*') and an RPC backend ('src/engine/rpc/*').

1.2 The Register
================

The "Register" ('src/register') implements a ledger-like GUI that allows
the user to dynamically enter dates, prices, memos descriptions, etc.
in an intuitive fashion that should be obvious to anyone who's used a
checkbook register.  The code is highly configurable, allowing the
ledger columns and rows to be laid out in any way, with no restrictions
on the function, type, and number of columns/rows.  For example, one can
define a ledger with three date fields, one price field, and four memo
fields in a straightforward fashion.  Cell handling objects support and
automatically validate date entry, memo entry (w/auto-completion),
prices, combo-boxes (pull-down menus), and multi-state check-boxes.
Cells can be marked read-write, or output-only.  Cells can be assigned
unique colors.  The currently active ledger row-block can be highlighted
with a unique color.

   The register code is completely independent of the engine code, knows
nothing about accounting or any of the other GnuCash subsystems.  It can
be used in independent projects that have nothing to do with accounting.

1.3 Reports
===========

The "Reports" module ('src/scm/report.scm', 'src/scm/reports') is a
scheme (guile) based system to create balance sheets, profit & loss
statements, etc.  by using the engine API to fetch and display data
formatted in HTML.

   For the most part, this module uses the Query API to fetch the engine
information instead of using the raw engine interface.  This design uses
Queries to extract the data and assemble it into a view-independent
format.  This data is then be converted to HTML reports and/or graphs
such as bar and pie charts.

1.4 Graphs
==========

The "Graphs" module implements GUI graphs such as bar and pie charts.
These graphs can be interactive in that the user can, for example, move
pie wedges, and 'live' in that the user can click on graph subsections
to see a detail graph or report of that particular subsection.

   This module is implemented using the GUPPI library being developed by
Jon Trowbridge (<http://www.gnome.org/guppi>).

1.5 Price Quotes
================

The "Price Quotes" module ('src/quotes') is a Perl system to fetch stock
price data off the Internet and insert it into the GnuCash Engine.  This
module requires the functionality of the Finance::Quote module available
from CPAN. The Finance::Quote module can fetch price quotes from many
different sources including Alphavantage and several international
exchanges and fund companies.

   The Finance::Quote module also supports fetching currency exchange
rates.  GnuCash will be extended to allow the fetching and use of
currency exchange rates.

1.6 User Preferences
====================

The "User Preferences" module ('src/scm/options.scm',
'src/scm/prefs.scm') provides an infrastructure for defining both
user-configurable and internal preferences.  Preferences are defined in
scheme using several predefined preference types such as boolean,
string, date, etc.  Preferences are 'implemented' by providing a GUI
which allows the user to see and change preference values.  An API is
provided to query preference values and to register callbacks which will
be invoked when preferences change.

   Preference values which are different from the default values are
stored as scheme forms in a user-specific preferences file
('~/.gnucash/config.auto').  This file is automatically loaded upon
startup.

1.7 QIF Import
==============

The "QIF Import" module ('src/scm/qif-import') provides functionality
for importing QIF (Quicken Interchange Format) data into GnuCash.

1.8 GnuCash
===========

The GnuCash module ('src/gnome', 'src/register/gnome' and 'src/*.[ch]')
is the main GUI application.  It consists of a collection of
miscellaneous GUI code to glue together all of the pieces above into a
coherent, point-and-click whole.  It is meant to be easy to use and
intuitive to the novice user without sacrificing the power and
flexibility that a professional might expect.  When people say that
GnuCash is trying to be a "Quicken or MS Money look/work/act-alike",
this is the piece that they are referring to.  It really is meant to be
a personal-finance manager with enough power for the power user and the
ease of use for the beginner.

   Currently, the Gnome interface is the only operational interface.
There is an obsolete Motif interface which is not maintained and which
is removed in current CVS. There is also old Qt code (removed in current
CVS) which won't compile, and most/all functions are missing.

2 Engine
********

*This whole document is completely outdated.  Don't read this.  All
function names and every described structure has changed completely.
Only read this if you want to know how gnucash looked like in 1999.
This is completely outdated!*

   The Engine provides an interface to a financial engine with three
basic financial entities: Accounts, Transactions (known as Journal
Entries in accounting practice), and Splits (known as Ledger Entries).
These three entities are the central data structures of the GnuCash
financial data model.

   In addition, the Engine provides the abstraction of Account Groups
(collections of related accounts) and GNCBooks.  A GNCBook abstracts
both a set of related GnuCash data (financial entities plus additional
information such as budgets, per-file preferences, etc.)  plus a
file-editing session allowing transparent support for locking and
implementation with other backends such as SQL.

   The Engine code contains no GUI code whatsoever and is designed to be
created as a shared library for use by other programs.

2.1 Introduction
================

Splits (see Splits), or "Ledger Entries" are the fundamental
accounting units.  Each Split consists of an amount (number of dollar
bills, number of shares, etc.), the value of that amount expressed in a
(possibly) different currency than the amount, a Memo, a pointer to the
parent Transaction, a pointer to the debited Account, a reconciled flag
and timestamp, an "Action" field, and a key-value frame which can store
arbitrary data (see Key-Value Pair Frames).

   Transactions (see Transactions) embody the notion of "double
entry" accounting.  A Transaction consists of a date, a description, an
ID number, a list of one or more Splits, and a key-value frame.  The
transaction also specifies the currency with which all of the splits
will be valued.  When double-entry rules are enforced, the total value
of the splits are zero.  If there are only two splits, then the value of
one must be positive, the other negative: this denotes that one account
is debited, and another is credited by an equal amount.  By forcing the
value of the splits to always 'add up' to zero, we can gaurentee that
the balances of the accounts are always correctly balanced.

   The engine does not enforce double-entry accounting, but provides an
API to enable user-code to find unbalanced transactions and 'repair'
them so that they are in balance.  See Scrub.

   Note the sum of the values of Splits in a Transaction is always
computed with respect to a currency; thus splits can be balanced even
when they are in different currencies, as long as they share a common
currency.  This feature allows currency-trading accounts to be
established.

   Every Split must point to its parent Transaction, and that
Transaction must in turn include that Split in the Transaction's list of
Splits.  A Split can belong to at most one Transaction.  These
relationships are enforced by the engine.  The engine user cannnot
accidentally destroy this relationship as long as they stick to using
the API and never access internal structures directly.

   Splits are grouped into Accounts (see Accounts) which are also
known as "Ledgers" in accounting practice.  Each Account consists of a
list of Splits that debit that Account.  To ensure consistency, if a
Split points to an Account, then the Account must point to the Split,
and vice-versa.  A Split can belong to at most one Account.  Besides
merely containing a list of Splits, the Account structure also give the
Account a name, a code number, description and notes fields, a key-value
frame, a pointer to the commodity that is used for all splits in this
account.  The commodity can be the name of anything traded and tradable:
a stock (e.g.  "IBM", "McDonald's"), a currency (e.g.  "USD", "GBP"), or
anything added to the commodity table.

   Accounts can be arranged in a hierarchical tree.  The nodes of the
tree are called "Account Groups" (see Account Groups).  By
accounting convention, the value of an Account is equal to the value of
all of its Splits plus the value of all of its sub-Accounts.

2.2 Using and Extending the Engine API
======================================

Engine API calls are named using a specific convention.  For example,
the function to access the Memo field of a Split is 'xaccSplitGetMemo'.
The prefix 'xacc' comes first(1), followed by the name of the entity for
which the API call applies ('Split'), followed by the action performed
by the call ('Get'), followed by the name of the field being accessed
('Memo').  Future API calls should conform to this naming convention.

   The formal arguments to Engine API calls always begin with the entity
to which the call applies.  Thus, the arguments to 'xaccSplitSetMemo'
are the 'Split' pointer followed by the pointer to a memo string.
Future API calls should also conform to this convention.

   Engine API calls should be implemented to behave as gracefully as
possible with unexpected input.  Specifically, public API calls should
gracefully handle 'NULL' pointer arguments.  User code should be able to
handle 'NULL' return values from Engine calls as well.

   ---------- Footnotes ----------

   (1) The 'xacc' prefix is a historical artifact.  GnuCash was derived
from X-Accountant by Robin Clark.

2.3 Globally Unique Identifiers
===============================

It is common for Engine structures to reference other Engine structures.
For example, an Account must reference its Splits, its parent Account
Group, and its child Account Group.  Furthermore, other GnuCash modules
may need to reference Engine structures.  For example, a GUI
implementation may wish to save a list of Accounts which the user has
open when the application exits in order to restore that same state upon
the next invocation.

   One way to uniquely identify an Engine structure, at least while the
program is running, is using the C pointer which points to the
structure.  C pointers have the advantage of speed, but also have some
disadvantages:

   * Pointers cannot be used in data files and are not persistent across
     different program invocations.

   * When an entity is destroyed, every other structure which references
     that entity through a direct pointer must be immediately updated to
     prevent illegal accesses.

   The "GUID" (Globally Unique Identifier) provides a way to reference
Engine structures that is more flexible than C pointers.  Each Engine
structure has an associated GUID which can be used to reference that
structure.  Engine GUIDs have the following features:

   * The GUID is permanent, i.e., it persists between invocations of
     GnuCash.

   * The GUID is guaranteed to be unique with the set of all Splits,
     Transactions, and Accounts in the hierarchy of which the structure
     is a member.

   * With very high probability, the GUID is unique among all GUIDs
     created by any invocation of GnuCash, all over the world.

   * GUIDs can be efficiently encoded in a string representation.

2.3.1 When to use GUIDs
-----------------------

Although GUIDs are very flexible, the engine structures like Accounts
will probably continue to use C pointers for the foreseeable future,
since they are much faster (and in certain respects more convenient)
than using GUIDs.  In general, however, it is much safer to use GUIDs.
In particular, you should consider using GUIDs if any of the following
is true:

   * You need to save a reference to an engine structure in a file.

   * You need to save a reference to an engine structure that could be
     deleted in between accesses to the saved reference.

2.3.2 GUID Types
----------------

The GUIDs in GnuCash are typed using the enum 'GNCIdType'.  Possible
values and their meanings for GUID types are:

'GNC_ID_NONE'
     The GUID does not currently refer to a GnuCash entity, though it
     could refer to one in the future.

'GNC_ID_NULL'
     The GUID does not, and never will, refer to a GnuCash entity.

'GNC_ID_ACCOUNT'
     The GUID refers to an Account (see Accounts).

'GNC_ID_TRANS'
     The GUID refers to a Transation (see Transactions).

'GNC_ID_SPLIT'
     The GUID refers to a Split (see Splits).

 -- Function: GNCIdType xaccGUIDType (const GUID * GUID)
     Return the type associated with GUID.

 -- Function: const GUID * xaccGUIDNull (void)
     Return a GUID which is guaranteed to always have type
     'GNC_ID_NULL'.

2.3.3 How to use GUIDs
----------------------

The Engine API functions which access the GUID for a specific entity
return a pointer to the GUID. NOTE: Do not store the pointer itself!
Instead, store a copy of the GUID. Storing the pointer itself would
present some of the same problems as using the account pointer directly.
Example:

     {
       GUID saved_guid;
       Account *account;

       account = < something to get an Account pointer >

       saved_guid = *xaccAccountGetGUID(account);

       ...

       account = xaccAccountLookup(&saved_guid);

       ...
     }

   You can compare two GUIDs with the following functions.

 -- Function: gboolean guid_equal (const GUID * GUID_1, const GUID *
          GUID_2)
     Compare two guids and return TRUE if they are both non-NULL and
     equal.

 -- Function: gint guid_compare (const GUID * G1, const GUID * G2)
     Return the 'memcmp' of the two GUID's.

   You can encode and decode GUIDs and their string representations
using the next two functions.

 -- Function: gchar * guid_to_string (const GUID * GUID)
     Return a null-terminated string encoding of GUID.  String encodings
     of identifiers are hex numbers printed only with the characters '0'
     through '9' and 'a' through 'f'.  The encoding will always be
     'GUID_ENCODING_LENGTH' characters long.  The returned string must
     be freed when no longer needed using g_free.

 -- Function: char * guid_to_string_buff (const GUID * GUID, char *
          BUFF)
     This routine does the same work as 'guid_to_string', except that
     the string is written into the memory pointed at by BUFF.  The
     buffer must be at least GUID_ENCODING_LENGTH+1 characters long.
     This routine is handy for avoiding a malloc/free cycle.  It returns
     a pointer to the _end_ of what was written.  (i.e.  it can be used
     like 'stpcpy' during string concatenation)

 -- Function: gboolean string_to_guid (const char * STRING, GUID * GUID)
     Given a string, decode an id into GUID if GUID is non-NULL. The
     function returns TRUE if the string was a valid 32 character
     hexadecimal number.  This function accepts both upper and lower
     case hex digits.  If the return value is FALSE, the effect on GUID
     is undefined.

   You can allocate and deallocate space for GUIDs using standard memory
routines.  However, if your code is allocating and deallocating lots of
GUID objects, then the next two functions should be used.

 -- Function: GUID * xaccGUIDMalloc (void)
     Return newly allocated memory for a GUID object.  The memory must
     be freed with 'xaccGUIDFree'.  In general, this function is faster
     than using the standard libc allocators.

 -- Function: void xaccGUIDFree (GUID * GUID)
     Free the space for a GUID that was allocated with 'xaccGUIDMalloc'.

   You can use the following two functions to aid in using GUIDS in hash
tables.

 -- Function: guint guid_hash_to_guint (gconstpointer PTR)
     Return a hash value suitable for use with a 'GHashTable'.  PTR must
     point to a GUID.

 -- Function: GHashTable * guid_hash_table_new (void)
     Return a new 'GHashTable' which uses GUIDs as keys.

2.3.4 GUIDs and GnuCash Entities
--------------------------------

This section documents a low-level API for associating entities with
GUIDs.  User code and general engine code should not use this API;
instead use the API documented in the sections for the specific GnuCash
entities such as Accounts and Transactions.

 -- Function: void xaccGUIDNew (GUID * GUID)
     Generate a new guid.  This function is guaranteed to return a guid
     that is unique within the scope of all GnuCash entities being
     managed by the the current invocation of GnuCash.  GnuCash routines
     should always use this function and not 'guid_replace'!

 -- Function: void * xaccLookupEntity (const GUID * GUID, GNCIdType
          ENTITY_TYPE)
     Lookup an entity given an id and a type.  If there is no entity
     associated with the id, or if it has a different type, NULL is
     returned.

 -- Function: void xaccStoreEntity (void * ENTITY, const GUID * GUID,
          GNCIdType entity_type)
     Store the given entity under the given id with the given type.

 -- Function: void xaccRemoveEntity (const GUID * GUID)
     Remove any existing association between an entity and the given id.
     The entity is not changed in any way.

2.3.5 The GUID Generator
------------------------

GUIDs are created by the GUID generator.  The API for this generator is
low-level and should not be used by user-code.

 -- Function: void guid_replace (GUID * GUID)
     Create a new GUID and store it in GUID.  This is a low-level
     function!  GnuCash code should use 'xaccGUIDNew'.

2.4 Numeric Library
===================

=============== The documentation below for gnc_numeric is obsolete and
has been superseded by the gnc_numeric docs in the header file.
=========================================

   Financial quantities in GnuCash (Split quantities and values) are
stored as exact quantities measured in the smallest denominational unit
of the appropriate currency.  For example, 100.50 US Dollars would be
stored as (10050 / 100) US Dollars.  GnuCash uses the 'gnc_numeric'
datatype to store financial quantities.

   The 'gnc_numeric' API provides data types and functions for
manipulating exact numeric quantities.  While the 'gnc_numeric' library
was developed to represent and operate on exact financial quantities in
GnuCash, the library is also (hopefully) suitable for use in any
application where exact numeric representation for rational numbers is
needed.

   A 'gnc_numeric' value represents a number in rational form, with a
64-bit 'long long' integer as numerator and denominator.  If more
precision, a higher-precision representation of irrational numbers, or a
wider dynamic range is needed, a floating point format may be
appropriate.  There are reasonable rational approximations to common
irrational constants (see Numeric Example), but the transcendental
functions have not been implemented for 'gnc_numeric' objects.

2.4.1 Standard Numeric Arguments
--------------------------------

=============== The documentation below for gnc_numeric is obsolete and
has been superseded by the gnc_numeric docs in the header file.
=========================================

   It is useful to specify a denominator in cases where it is known that
the output value is of constrained precision.  For example, monetary
transactions must be executed in an integer number of the "smallest
currency unit" of the transaction.  In US Dollars, the smallest currency
unit is the cent, and all monetary transactions must be done in units of
cents.  Therefore, any fractional cents in a computed price must be
rounded away.

   Most of the 'gnc_numeric' arithmetic functions take two arguments in
addition to their numeric args: DENOM, which is the denominator to use
in the output 'gnc_numeric object', and HOW, which describes how the
arithmetic result is to be converted to that denominator.  This
combination of output denominator and rounding policy allows the results
of financial and other exact computations to be properly rounded to the
appropriate units.

   Valid values for DENOM are:

'n (positive int)'
     Use the number 'n' as the denominator of the output value.

'GNC_DENOM_RECIPROCAL (n)'
     Use the value '1/n' as the denominator of the output value.

'GNC_DENOM_AUTO'
     Compute an appropriate denominator automatically.  Flags in the HOW
     argument will specify how to compute the denominator.

   Valid values for HOW are bitwise combinations of zero or one
"rounding instructions" with zero or one "denominator types".

   Rounding instructions control how fractional parts in the specified
denominator affect the result.  For example, if a computed result is
"3/4" but the specified denominator for the return value is 2, should
the return value be "1/2" or "2/2"?

   Possible rounding instructions are:

'GNC_RND_FLOOR'
     Round toward -infinity

'GNC_RND_CEIL'
     Round toward +infinity

'GNC_RND_TRUNC'
     Truncate fractions (round toward zero)

'GNC_RND_PROMOTE'
     Promote fractions (round away from zero)

'GNC_RND_ROUND'
     Use unbiased ("banker's") rounding.  This rounds to the nearest
     integer, and to the nearest even integer when there are two
     equidistant nearest integers.  This is generally the one you should
     use for financial quantities.

'GNC_RND_ROUND_HALF_UP'
     Round to the nearest integer, rounding away from zero when there
     are two equidistant nearest integers.

'GNC_RND_ROUND_HALF_DOWN'
     Round to the nearest integer, rounding toward zero when there are
     two equidistant nearest integers.

'GNC_RND_NEVER'
     Never round at all, and signal an error if there is a fractional
     result in a computation.

   The denominator type specifies how to compute a denominator if
'GNC_DENOM_AUTO' is specified as the DENOM.  Valid denominator types
are:

'GNC_DENOM_EXACT'
     Use any denominator which gives an exactly correct ratio of
     numerator to denominator.  Use EXACT when you do not wish to lose
     any information in the result but also do not want to spend any
     time finding the "best" denominator.

'GNC_DENOM_REDUCE'
     Reduce the result value by common factor elimination, using the
     smallest possible value for the denominator that keeps the correct
     ratio.  The numerator and denominator of the result are relatively
     prime.  This can be computationally expensive for large fractions.

'GNC_DENOM_LCD'
     Find the least common multiple of the arguments' denominators and
     use that as the denominator of the result.

'GNC_DENOM_FIXED'
     All arguments are required to have the same denominator, that
     denominator is to be used in the output, and an error is to be
     signaled if any argument has a different denominator.

'GNC_DENOM_SIGFIG'
     Round to the number of significant figures given in the rounding
     instructions by the GNC_DENOM_SIGFIGS () macro.

'GNC_DENOM_SIGFIGS (n)'
     Use a value for the denominator that will keep at least 'n'
     significant figures in the result.

   To use traditional rational-number operational semantics (all results
are exact and are reduced to relatively-prime fractions) pass the
argument 'GNC_DENOM_AUTO' as DENOM and 'GNC_DENOM_REDUCE |
GNC_RND_NEVER' as HOW.

   To enforce strict financial semantics (such that all operands must
have the same denominator as each other and as the result), use
GNC_DENOM_AUTO as DENOM and 'GNC_DENOM_FIXED | GNC_RND_NEVER' as HOW.

=============== The documentation below for gnc_numeric is obsolete and
has been superseded by the gnc_numeric docs in the header file.
=========================================

2.4.2 Creating Numeric Objects
------------------------------

 -- Function: gnc_numeric gnc_numeric_create (int NUM, int DENOM)
     Create a 'gnc_numeric' object with a value of "NUM / DENOM".

 -- Function: gnc_numeric gnc_numeric_zero ()
     Create a 'gnc_numeric' object with a value of 0.

2.4.3 Basic Arithmetic Operations
---------------------------------

See Standard Numeric Arguments for a description of the DENOM
and HOW arguments to each arithmetic function.

 -- Function: gnc_numeric gnc_numeric_add (gnc_numeric A, gnc_numeric B,
          gint64 DENOM, gint HOW)
     Return the sum of A and B.

 -- Function: gnc_numeric gnc_numeric_sub (gnc_numeric A, gnc_numeric B,
          gint64 DENOM, gint HOW)
     Return "A - B".

 -- Function: gnc_numeric gnc_numeric_mul (gnc_numeric A, gnc_numeric B,
          gint64 DENOM, gint HOW)
     Return the product of A and B.

 -- Function: gnc_numeric gnc_numeric_div (gnc_numeric A, gnc_numeric B,
          gint64 DENOM, gint HOW)
     Return "A / B".

 -- Function: gnc_numeric gnc_numeric_neg (gnc_numeric A)
     Return "-A".

 -- Function: gnc_numeric gnc_numeric_abs (gnc_numeric A)
     Return the absolute value of A.

 -- Function: gnc_numeric gnc_numeric_add_fixed (gnc_numeric A,
          gnc_numeric B)
     Equivalent to 'gnc_numeric_add' on A and B with 'GNC_DENOM_AUTO'
     for DENOM and 'GNC_DENOM_FIXED | GNC_RND_NEVER' for HOW.

 -- Function: gnc_numeric gnc_numeric_sub_fixed (gnc_numeric A,
          gnc_numeric B)
     Equivalent to 'gnc_numeric_sub' on A and B with 'GNC_DENOM_AUTO'
     for DENOM and 'GNC_DENOM_FIXED | GNC_RND_NEVER' for HOW.

 -- Function: gnc_numeric gnc_numeric_add_with_error (gnc_numeric A,
          gnc_numeric B, gint64 DENOM, gint HOW, gnc_numeric * ERROR)
     The same as 'gnc_numeric_add', but uses ERROR for accumulating
     conversion roundoff error.

 -- Function: gnc_numeric gnc_numeric_sub_with_error (gnc_numeric A,
          gnc_numeric B, gint64 DENOM, gint HOW, gnc_numeric * ERROR)
     The same as 'gnc_numeric_sub', but uses ERROR for accumulating
     conversion roundoff error.

 -- Function: gnc_numeric gnc_numeric_mul_with_error (gnc_numeric A,
          gnc_numeric B, gint64 DENOM, gint HOW, gnc_numeric * ERROR)
     The same as 'gnc_numeric_mul', but uses ERROR for accumulating
     conversion roundoff error.

 -- Function: gnc_numeric gnc_numeric_div_with_error (gnc_numeric A,
          gnc_numeric B, gint64 DENOM, gint HOW, gnc_numeric * ERROR)
     The same as 'gnc_numeric_div', but uses ERROR for accumulating
     conversion roundoff error.

2.4.4 Numeric Comparisons and Predicates
----------------------------------------

 -- Function: int gnc_numeric_zero_p (gnc_numeric A)
     Returns 1 if 'A == 0', otherwise returns 0.

 -- Function: int gnc_numeric_positive_p (gnc_numeric A)
     Returns 1 if 'A > 0', otherwise returns 0.

 -- Function: int gnc_numeric_negative_p (gnc_numeric A)
     Returns 1 if 'A < 0', otherwise returns 0.

 -- Function: int gnc_numeric_compare (gnc_numeric A, gnc_numeric B)
     Returns +1 if 'A > B', -1 if 'B > A', 0 if 'A == B'.

 -- Function: int gnc_numeric_eq (gnc_numeric A, gnc_numeric B)
     Returns 1 if 'numerator(A) == numerator(B)' and 'denominator(A) ==
     denominator(B)', otherwise returns 0.

 -- Function: int gnc_numeric_equal (gnc_numeric A, gnc_numeric B)
     Returns 1 if the fraction represented by A is equal to the fraction
     represented by B, otherwise returns 0.

 -- Function: int gnc_numeric_same (gnc_numeric A, gnc_numeric B, gint64
          DENOM, gint HOW)
     Convert both A and B to DENOM (see Standard Numeric Arguments
     and compare numerators of the result.

            For example, if A == 7/16 and B == 3/4,
            gnc_numeric_same(A, B, 2, GNC_RND_TRUNC) == 1
            because both 7/16 and 3/4 round to 1/2 under truncation. However,
            gnc_numeric_same(A, B, 2, GNC_RND_ROUND) == 0
            because 7/16 rounds to 1/2 under unbiased rounding but 3/4 rounds
            to 2/2.

=============== The documentation below for gnc_numeric is obsolete and
has been superseded by the gnc_numeric docs in the header file.
=========================================

2.4.5 Numeric Denominator Conversion
------------------------------------

 -- Function: gnc_numeric gnc_numeric_convert (gnc_numeric IN, gint64
          DENOM, gint HOW)
     Convert IN to the specified denominator under standard arguments
     DENOM and HOW.  See Standard Numeric Arguments.

 -- Function: gnc_numeric gnc_numeric_convert_with_error (gnc_numeric
          IN, gint64 DENOM, gint HOW, gnc_numeric * ERROR)
     Same as 'gnc_numeric_convert', but return a remainder value for
     accumulating conversion error.

 -- Function: gnc_numeric gnc_numeric_reduce (gnc_numeric IN)
     Return IN reduced by GCF reduction.

2.4.6 Numeric Floating Point Conversion
---------------------------------------

 -- Function: gnc_numeric double_to_gnc_numeric (double ARG, gint64
          DENOM, gint HOW)
     Convert a floating-point number to a 'gnc_numeric'.  Both DENOM and
     HOW are used as in arithmetic, but 'GNC_DENOM_AUTO' is not
     recognized.

 -- Function: double gnc_numeric_to_double (gnc_numeric ARG)
     Convert ARG to a 'double' value.

2.4.7 Numeric String Conversion
-------------------------------

 -- Function: gchar * gnc_numeric_to_string (gnc_numeric N)
     Return a string representation of N.  The string must be freed with
     'g_free'.

 -- Function: const gchar * string_to_gnc_numeric (const gchar * STR,
          gnc_numeric * N)
     Read a 'gnc_numeric' from STR, skipping any leading whitespace, and
     returning a pointer to just past the last byte read.  Return NULL
     on error.

2.4.8 Numeric Error Handling
----------------------------

 -- Function: int gnc_numeric_check (gnc_numeric NUM)
     Check NUM for the possibility that it is an error signal rather
     than a proper value.  Possible return codes are:

     'GNC_ERROR_OK'
          No error condition

     'GNC_ERROR_ARG'
          An improper argument was passed to a function

     'GNC_ERROR_OVERFLOW'
          An overflow occurred while calculating a result

     'GNC_ERROR_DENOM_DIFF'
          'GNC_DENOM_FIXED' was specified, but argument denominators
          differed.

     'GNC_ERROR_REMAINDER'
          'GNC_RND_NEVER' was specified, but the result could not be
          converted to the desired denominator without a remainder.

 -- Function: gnc_numeric gnc_numeric_error (int error_code)
     Create a 'gnc_numeric' object that signals the error condition
     noted by ERROR_CODE rather than a number.

2.4.9 Numeric Example
---------------------

=============== The documentation below for gnc_numeric is obsolete and
has been superseded by the gnc_numeric docs in the header file.
=========================================

   The following program finds the best 'gnc_numeric' approximation to
the 'math.h' constant 'M_PI' given a maximum denominator.  For large
denominators, the 'gnc_numeric' approximation is accurate to more
decimal places than will generally be needed, but in some cases this may
not be good enough.  For example,

         M_PI                   = 3.14159265358979323846
         245850922 / 78256779   = 3.14159265358979311599  (16 sig figs)
         3126535 / 995207       = 3.14159265358865047446  (12 sig figs)
         355 / 113              = 3.14159292035398252096  (7 sig figs)

     #include <glib.h>
     #include "gnc-numeric.h"
     #include <math.h>

     int
     main(int argc, char ** argv)
     {
       gnc_numeric approx, best;
       double err, best_err=1.0;
       double m_pi = M_PI;
       gint64 denom;
       gint64 max;

       sscanf(argv[1], "%Ld", &max);

       for (denom = 1; denom < max; denom++)
       {
         approx = double_to_gnc_numeric (m_pi, denom, GNC_RND_ROUND);
         err    = m_pi - gnc_numeric_to_double (approx);
         if (fabs (err) < fabs (best_err))
         {
           best = approx;
           best_err = err;
           printf ("%Ld / %Ld = %.30f\n", gnc_numeric_num (best),
                   gnc_numeric_denom (best), gnc_numeric_to_double (best));
         }
       }
     }

2.5 Key-Value Pair Frames
=========================

The number and types of data items which are associated with the
financial abstractions (Accounts, Transactions, and Splits) can vary
widely.  For example, an Account which represents a user's checking
account might need to store the bank name, a telephone number, and a
username for online banking purposes.  Another Account representing the
user's ownership of a stock might need to store information about
retrieving price quotes online such as the ticker symbol and the
exchange.

   To meet this need for varying data storage, the GnuCash accounting
entities use Key-Value Pair Frames (hereafter referred to as the
datatype 'kvp_frame').  A 'kvp_frame' is a set of associations between
character strings (keys) and 'KvpValue' structures.  A 'KvpValue' is a
union with possible types enumerated in the 'kvp_value_t' enum which
indicates the type of data stored in a 'KvpValue' object.

2.5.1 Key-Value Policy
----------------------

This section defines the policy that programmers should follow when
using key-value pairs to store information.  Because of the large amount
of information which can potentially be stored using this mechanism, it
is important to follow these guidelines so that order will be
maintained.

   The following rules should be followed for using key-value pairs:

   * The document 'src/engine/kvp_doc.txt' should be used to document
     the use of keys and values.  Please consult this document before
     planning any use of new keys.

   * Key strings should be in all lower case with the '-' character
     separating words.  If possible, use only alphanumeric characters
     and '-'.  Example: 'bank-info'.  Because the '/' character is
     useful for describing keys in sub-frames
     ('bank-info/routing-number'), do not use the '/' character in key
     names.

   * Favor longer, descriptive key strings over short ones.  Example:
     'online-banking-info' is better than 'onln-bnk'.

   * Make use of the fact that frames can be stored in frames.  If a
     group of keys are used for a related purpose, consider storing them
     together in a sub-frame.

   * Values should generally not be accessed directly through keys, but
     should rather be accessed through specific API calls.  The API
     calls do not necessarily need to part a part of the Engine API. For
     example, the GUI would probably define keys that the Engine does
     not need to know about.

   * The same key should not be used for different engine structures
     (Accounts, Transactions, Splits), unless the key's value has the
     same type and the same basic purpose.

2.5.2 kvp_frame
---------------

A 'kvp_frame' is the datatype used to associate key strings with
'KvpValue' objects (see KvpValue).

 -- Function: kvp_frame* kvp_frame_new (void)
     Create and initialize a new 'kvp_frame' object and return a pointer
     to it.

 -- Function: void kvp_frame_delete (kvp_frame * FRAME)
     Free all memory associated with FRAME.

 -- Function: kvp_frame* kvp_frame_copy (const kvp_frame * frame)
     Return a deep copy of FRAME.

 -- Function: void kvp_frame_set_slot (kvp_frame * FRAME, const char *
          KEY, const KvpValue * VALUE)
     Associate KEY with VALUE in FRAME.

 -- Function: void kvp_frame_set_slot_nc (kvp_frame * FRAME, const char
          * KEY, KvpValue * VALUE)
     Same as 'kvp_frame_set_slot', except that VALUE is used directly,
     instead of being copied.  This call transfers 'ownership' of VALUE
     to FRAME.

 -- Function: KvpValue* kvp_frame_get_slot (kvp_frame * FRAME, const
          char * KEY)
     Return the 'KvpValue' object associated with KEY in FRAME or return
     'NULL' if there is no association for KEY.  The value returned is
     not a copy.

 -- Function: void kvp_frame_set_slot_path (kvp_frame * FRAME, const
          KvpValue * VALUE, const char * FIRST_KEY, ...)
     Associate VALUE with the "key path" specified by the variable
     argument list.  Each key in the path except the last denotes a
     sub-frame which is associated with the given key.  The variable
     list must be terminated with NULL.

 -- Function: void kvp_frame_set_slot_path_gslist (kvp_frame * FRAME,
          const KvpValue * VALUE, GSList * KEY_PATH)
     The same as 'kvp_frame_set_slot_path', except that the key path is
     specified using a GSList.  All the keys in the list should be
     non-NULL.

 -- Function: KvpValue * kvp_frame_get_slot_path (kvp_frame * FRAME,
          const char * FIRST_KEY, ...)
     Return the value associated with the key path, or 'NULL' if none.
     The path is specified as in 'kvp_frame_set_slot_path'.

 -- Function: KvpValue * kvp_frame_get_slot_path_gslist (kvp_frame *
          FRAME, GSList * KEY_PATH)
     Return the value associated with the key path, or 'NULL' if none.
     The path is specified as in 'kvp_frame_set_slot_path_gslist'.

 -- Function: kvp_frame * kvp_frame_get_frame (kvp_frame * FRAME, ...)
     Works like 'kvp_frame_get_slot_path', but returns the last frame in
     the path.  All the keys should refer to frames.  If the frame path
     does not exist, it is created.

 -- Function: kvp_frame * kvp_frame_get_frame_gslist (kvp_frame * FRAME,
          GSList * KEY_PATH)
     Works like 'kvp_frame_get_slot_path_gslist', but returns the last
     frame in the path.  All the keys should refer to frames.  If the
     frame path does not exist, it is created.

 -- Function: kvp_frame * kvp_frame_get_frame_slash (kvp_frame * FRAME,
          const char * PATH)
     Works like 'kvp_frame_get_frame', but the frame path is specified
     as a single string where the keys are separated by slashes; thus,
     for example: '/this/is/a/valid/path' and '///so//is////this/'.
     Multiple slashes are compressed and a leading slash is optional.
     The pointers '.' and '..' are _not_ followed/obeyed.  (This is
     arguably a bug that needs fixing).

2.5.3 KvpValue
--------------

The 'KvpValue' object stores the 'value' part of a key-value association
in a 'kvp_frame' object.

 -- Function: void kvp_value_delete (KvpValue * VALUE)
     Free all of the memory associated with VALUE.

 -- Function: KvpValue* kvp_value_copy (const KvpValue * VALUE)
     Return a deep copy of VALUE.

 -- Function: kvp_value_t kvp_value_get_type (const KvpValue * VALUE)
     Return the type of value stored in VALUE.

   A 'kvp_value_t' enum must have one of the following values:

'KVP_TYPE_NONE'
     Indicates the abscence of a value in a 'kvp_frame'.

'KVP_TYPE_INT64'
     A 'gint64' value.

'KVP_TYPE_FLOAT64'
     A 'double' value.

'KVP_TYPE_STRING'
     A 'char *' value of arbitrary length.

'KVP_TYPE_GUID'
     A 'GUID' value.  See Globally Unique Identifiers.

'KVP_TYPE_BINARY'
     Arbitrary binary data.

'KVP_TYPE_LIST'
     A 'kvp_list' item which contains a list of 'KvpValue' items.

'KVP_TYPE_FRAME'
     A 'kvp_frame' object.  Thus, frames may contain other frames in a
     recursive manner.

2.5.3.1 Value Constructors
..........................

The following functions create and return 'KvpValue' objects with
particular values.  In the case of pointer arguments, deep copies are
performed.

 -- Function: KvpValue* kvp_value_new_int64 (gint64 VALUE)
 -- Function: KvpValue* kvp_value_new_float64 (double VALUE)
 -- Function: KvpValue* kvp_value_new_string (const char * VALUE)
 -- Function: KvpValue* kvp_value_new_guid (const GUID * GUID)
 -- Function: KvpValue* kvp_value_new_binary (const void * DATA, int
          DATASIZE)
 -- Function: KvpValue* kvp_value_new_list (const kvp_list * VALUE)
 -- Function: KvpValue* kvp_value_new_frame (const kvp_frame * VALUE);

2.5.3.2 Value Accessors
.......................

The following functions access the value of a given 'KvpValue' object.
If the type of the object does not correspond to that named in the
function, 'NULL', '0', or '0.0' is returned as appropriate.

 -- Function: gint64 kvp_value_get_int64 (const KvpValue * VALUE)
 -- Function: double kvp_value_get_float64 (const KvpValue * VALUE)
 -- Function: char* kvp_value_get_string (const KvpValue * VALUE)
 -- Function: GUID* kvp_value_get_guid (const KvpValue * VALUE)
 -- Function: void* kvp_value_get_binary (const KvpValue * VALUE, int *
          SIZE_RETURN)
 -- Function: kvp_list* kvp_value_get_list (const KvpValue * VALUE)
 -- Function: kvp_frame* kvp_value_get_frame (const KvpValue * VALUE)

2.5.4 kvp_list
--------------

A 'kvp_list' object abstract a list of 'KvpValue' objects.

 -- Function: kvp_list* kvp_list_new ()
     Return a newly allocated 'kvp_list' object.

 -- Function: void kvp_list_delete (kvp_list * LIST)
     Free all memory associated with LIST, including the 'KvpValue'
     objects in LIST.

 -- Function: kvp_list* kvp_list_copy (const kvp_list * LIST)
     Return a deep copy of LIST.

 -- Function: gboolean kvp_list_null_p (const kvp_list * LIST)
     Return 'TRUE' if LIST is the empty list.

 -- Function: KvpValue* kvp_list_car (kvp_list * LIST)
     If LIST is 'NULL' or the empty list, return 'NULL'.  Otherwise,
     return the first 'KvpValue' object in the list.

 -- Function: kvp_list* kvp_list_cdr (kvp_list * LIST)
     If LIST is 'NULL' or the empty list, return 'NULL'.  Otherwise,
     return a 'kvp_list' object consisting of LIST with the first value
     removed.  NOTE: the returned list is not a copy!

 -- Function: kvp_list* kvp_list_cons (KvpValue * CAR, kvp_list * CDR)
     If either CAR or CDR is 'NULL', return 'NULL'.  Otherwise, return a
     'kvp_list' object consisting of the value of CAR followed by the
     values of CDR.  This function uses 'hand-over' semantics, i.e., the
     arguments CAR and CDR are no longer the responsibility of the
     caller and should not be accessed after the function returns.

2.6 Events
==========

The Engine supports the concept of "Events" which notify external code
when engine entities are created, modified, or destroyed.

   User code can register event handers which are invoked for each
event, giving information about the specific engine entity generating
the event and the nature of the event (creation, modification, or
deletion).

2.6.1 Event API
---------------

Engine events are classified using the 'GNCEngineEventType' bitmask
which has the following predefined values:

'GNC_EVENT_NONE'
     A null value.

'GNC_EVENT_CREATE'
     Indicates an entity has been created.

'GNC_EVENT_MODIFY'
     Indicates an entity has been changed in some way.

'GNC_EVENT_DESTROY'
     Indicates an entity is being destroyed.

'GNC_EVENT_ALL'
     The boolean OR of 'GNC_EVENT_CREATE', 'GNC_EVENT_MODIFY', and
     'GNC_EVENT_DESTROY'.

   Event handlers are functions with the following type:

 -- Data type: GNCEngineEventHandler void (*) (GUID * ENTITY,
          GNCEngineEventType EVENT_TYPE, gpointer USER_DATA)
     A callback invoked when an engine event occurs.  ENTITY is the
     'GUID' of the entity generating the event.  EVENT_TYPE is one of
     'GNC_EVENT_CREATE', 'GNC_EVENT_MODIFY', or 'GNC_EVENT_DESTROY'.
     USER_DATA is the user data parameter supplied when the handler was
     registered.

 -- Function: gint gnc_engine_register_event_handler
          (GNCEngineEventHandler HANDLER, gpointer USER_DATA)
     Register a handler for engine events.  The return value is an
     identifier used to specify this handler in other API calls.

 -- Function: void gnc_engine_unregister_event_handler (gint HANDLER_ID)
     Unregister the event handler specified by HANDLER_ID.

 -- Function: void gnc_engine_suspend_events (void)
     Suspend all engine events.  This function may be called multiple
     times.  To resume event generation, an equal number of calls to
     'gnc_engine_resume_events' must be made.

 -- Function: void gnc_engine_resume_events (void)
     Resume engine event generation.

2.7 Commodities
===============

A Commodity is the Engine abstraction of a tradable quantity, like a
national currency or shares of a stock.  A commodity object contains the
following pieces of information:

A mnemonic name
     The 'short' name for the commodity.  For national currencies this
     is the 3-letter ISO4217 code (USD, AUD, etc.).  For stocks this is
     generally the exchange symbol (RHAT, IBM, etc.).

A namespace
     A string identifying the context in which the mnemonic is
     meaninful.

A full name
     The 'long' name for the commodity, such as "US Dollar" or "IBM
     Common Stock".

A printable name
     The name used to print out a string describing the commodity to a
     user.  This name is generally long - in some contexts it may be
     better to use the mnemonic instead.  The printable name is
     determined by the namespace and mnemonic.

A unique name
     A canonical name for the commodity that cannot be identical to
     another commodity's unique name.  The unique name is determined by
     the namespace and mnemonic.

An exchange code
     A code used to identify the commodity in its namespace context.
     For example, stocks have a unique code assigned to them by the
     exchange they are listed on.

A fraction
     An integer N which specifies that 1/N is generally the smallest
     fraction of the commodity which can be traded.  For example, most
     currencies are tradable in 1/100ths, so the fraction would be 100.

2.7.1 General Commodity API
---------------------------

 -- Function: gnc_commodity * gnc_commodity_new (const char * FULLNAME,
          const char * NAMESPACE, const char * MNEMONIC, const char *
          EXCHANGE_CODE, int FRACTION)
     Create and return a new commodity object with the given values, or
     'NULL' if any of the values are invalid.

 -- Function: void gnc_commodity_destroy (gnc_commodity * CM)
     Destroy the given commodity and free all associated memory.

 -- Function: gboolean gnc_commodity_equiv (const gnc_commodity * A,
          const gnc_commodity * B)
     Return true if the two given commodities are equivalent.  Two
     commodities are equivalent when they have the same namespace and
     the same mnemonic.

2.7.2 Commodity Getters
-----------------------

 -- Function: const char * gnc_commodity_get_mnemonic (const
          gnc_commodity * CM)
     Return the mnemonic of CM.

 -- Function: const char * gnc_commodity_get_namespace (const
          gnc_commodity * CM)
     Return the namespace of CM.

 -- Function: const char * gnc_commodity_get_fullname (const
          gnc_commodity * CM)
     Return the full name of CM.

 -- Function: const char * gnc_commodity_get_printname (const
          gnc_commodity * CM)
     Return the print name of CM.

 -- Function: const char * gnc_commodity_get_exchange_code (const
          gnc_commodity * CM)
     Return the exchange code of CM.

 -- Function: const char * gnc_commodity_get_unique_name (const
          gnc_commodity * CM)
     Return the unique name of CM.

 -- Function: int gnc_commodity_get_fraction (const gnc_commodity * CM)
     Return the smallest tradable fraction of CM.

2.7.3 Commodity Setters
-----------------------

 -- Function: void gnc_commodity_set_mnemonic (gnc_commodity * CM, const
          char * MNEMONIC)
     Set the mnemonic of CM to MNEMONIC.

 -- Function: void gnc_commodity_set_namespace (gnc_commodity * CM,
          const char * NAMESPACE)
     Set the namespace of CM to NAMESPACE.

 -- Function: void gnc_commodity_set_fullname (gnc_commodity * CM, const
          char * FULLNAME)
     Set the fullname of CM to FULLNAME.

 -- Function: void gnc_commodity_set_exchange_code (gnc_commodity * CM,
          const char * EXCHANGE_CODE)
     Set the exchange code of CM to EXCHANGE_CODE.

 -- Function: void gnc_commodity_set_fraction (gnc_commodity * CM, int
          SMALLEST_FRACTION)
     Set the fraction of CM to FRACTION.

2.8 Commodity Tables
====================

A Commodity Table holds a set of commodities and allows user code to
add, remove, and access the commodities in the table.

   There is a single, global Commodity Table used by the Engine.

2.8.1 General Commodity Table API
---------------------------------

 -- Function: gnc_commodity_table * gnc_commodity_table_new (void)
     Allocate and initialize a 'gnc_commodity_table'.  The returned
     table must be destroyed with 'gnc_commodity_table_destroy'.

 -- Function: void gnc_commodity_table_destroy (gnc_commodity_table *
          TABLE)
     Destroy TABLE and all associated resources, including all Commodity
     objects in the table.

 -- Function: gnc_commodity_table * gnc_engine_commodities (void)
     Return the global engine commodity table.

2.8.2 Commodity Table Access API
--------------------------------

 -- Function: gnc_commodity * gnc_commodity_table_lookup (const
          gnc_commodity_table * TABLE, const char * NAMESPACE, const
          char * MNEMONIC)
     Look up a commodity in TABLE given the namespace and the mnemonic.
     If no such commodity exists, 'NULL' is returned.

 -- Function: gnc_commodity * gnc_commodity_table_find_full (const
          gnc_commodity_table * TABLE, const char * NAMESPACE, const
          char * FULLNAMe)
     Look up a commodity in TABLE given the namespace and the full name.
     If no such commodity exists, 'NULL' is returned.

 -- Function: int gnc_commodity_table_has_namespace (const
          gnc_commodity_table * TABLE, const char * NAMESPACE)
     Return true if TABLE has the namespace NAMESPACE.

 -- Function: guint gnc_commodity_table_get_size (gnc_commodity_table *
          TABLE)
     Return the total number of commodities stored in TABLE.

 -- Function: guint gnc_commodity_table_get_number_of_namespaces
          (gnc_commodity_table * TABLE)
     Return the number of distinct namespaces in TABLE.

 -- Function: GList * gnc_commodity_table_get_namespaces (const
          gnc_commodity_table * TABLE)
     Return a list of the distinct namespaces in TABLE.  The list should
     be freed with 'g_list_free' but the namespaces should not be freed
     or modified.

 -- Function: GList * gnc_commodity_table_get_commodities (const
          gnc_commodity_table * TABLE, const char * NAMESPACE)
     Return a list of the commodities under NAMESPACE in TABLE.  The
     list should be freed with 'g_list_free' but the commodities should
     not be freed.

2.8.3 Commodity Table Modification API
--------------------------------------

 -- Function: gnc_commodity * gnc_commodity_table_insert
          (gnc_commodity_table * TABLE, gnc_commodity * COMM)
     Add commodity COMM to TABLE.  If COMM's namespace is not in TABLE,
     the namespace will be added.  This function has hand-over
     semantics, i.e., TABLE assumes responsibility for COMM.  COMM may
     even be destroyed by this call!  The function returns the actual
     commodity added as a result of the call.  It may not be the same
     object as COMM, but will be equivalent to COMM.

 -- Function: void gnc_commodity_table_remove (gnc_commodity_table *
          TABLE, gnc_commodity * COMM)
     Remove the given commodity from TABLE.  COMM is not modified or
     destroyed.

 -- Function: void gnc_commodity_table_add_namespace
          (gnc_commodity_table * TABLE, const char * NAMESPACE)
     Add NAMESPACE to TABLE.

 -- Function: void gnc_commodity_table_delete_namespace
          (gnc_commodity_table * TABLE, const char * NAMESPACE)
     Delete NAMESPACE from TABLE including all associated commodities.

 -- Function: void gnc_commodity_table_remove_non_iso
          (gnc_commodity_table * TABLE)
     Remove and destroy all commodities in TABLE which are not in the
     ISO4217 namespace.

2.9 Prices
==========

A Price is the Engine abstraction of an "instantaneous" price quote for
a given commodity with respect to another commodity.  For example, a
given price might represent the value of LNUX in USD on 2001-02-03.  A
Price contains the following pieces of information:

A GUID
     A GUID uniquely identifying the GNCPrice.

A commodity
     The commodity being priced.

A currency
     The denomination of the value of the item being priced.

A value
     The value of the item being priced.

A time
     The time the price was valid.

A source
     A string describing the source of the quote.  These strings will
     have a form like this: "Finance::Quote", "user:misc", "user:foo",
     etc.  If the quote came from a user, as a matter of policy, you
     _must_ prefix the string you give with "user:".  For now, the only
     other reserved values are "Finance::Quote" and "old-file-import".

A type
     A string describing the type of quote - types possible right now
     are "bid", "ask", "last", "nav", and "unknown".

2.9.1 Price Implementation Details
----------------------------------

For the source and type fields, 'NULL' and the empty string are
considered the same, so if one of these is the empty string then it
might be 'NULL' after a file save/restore.

   GNCPrices are reference counted.  When you create a price or or clone
one, the new price's reference count is set to 1.  When you are finished
with a price, call 'gnc_price_unref'.  If you hand the price pointer to
some other code that needs to keep it, make sure it calls
'gnc_price_ref' to indicate its interest in that price, and calls
'gnc_price_unref' when it's finished with the price.  For those
unfamiliar with reference counting, basically each price stores an
integer count which starts at 1 and is incremented every time someone
calls 'gnc_price_ref'.  Conversely, the count is decremented every time
someone calls 'gnc_price_unref'.  If the count ever reaches 0, the price
is destroyed.

   All of the getters return data that's internal to the GNCPrice, not
copies, so don't free or modify these values.

   All of the setters store copies of the data given, with the exception
of the commodity field which just stores the pointer given.  It is
assumed that commodities are a global resource and are pointer unique.

2.9.2 General Price API
-----------------------

 -- Function: GNCPrice * gnc_price_create (void)
     Return a newly allocated and initialized price with a reference
     count of 1.  The price should be dereferenced with
     'gnc_price_unref' when no longer needed, but the price should not
     be freed by user code.

 -- Function: GNCPrice * gnc_price_clone (GNCPrice * P)
     Return a newly allocated price that's a content-wise duplicate of
     P.  The returned clone will have a reference count of 1.

 -- Function: void gnc_price_ref (GNCPrice * P)
     Increase the reference count of P by 1.

 -- Function: void gnc_price_unref (GNCPrice * P)
     Decrease the reference coutn of P by 1.  If the resulting count is
     0, P will be destroyed.

 -- Function: GNCPrice * gnc_price_lookup (const GUID * GUID)
     Lookup and return the price associated with GUID, or 'NULL' if
     there is no such price.

2.9.3 Price Getters
-------------------

 -- Function: const GUID * gnc_price_get_guid (GNCPrice * P)
     Return the GUID of P.

 -- Function: gnc_commodity * gnc_price_get_commodity (GNCPrice * P)
     Return the commodity of P.

 -- Function: gnc_commodity * gnc_price_get_currency (GNCPrice * P)
     Return the currency of P.

 -- Function: time64 gnc_price_get_time64 (GNCPrice * P)
     Return the time of P.

 -- Function: const char * gnc_price_get_source (GNCPrice * P)
     Return the source of P.

 -- Function: const char * gnc_price_get_type (GNCPrice * P)
     Return the type of P.

 -- Function: gnc_numeric gnc_price_get_value (GNCPrice * P)
     Return the value of P.

 -- Function: gint32 gnc_price_get_version (GNCPrice * P)
     Return the version of P.

2.9.4 Price Setters
-------------------

Invocations of the setters should be wrapped with calls to
'gnc_price_begin_edit' and 'gnc_price_commit_edit'.  The begin/commit
calls help ensure that the local price db is synchronized with the
backend.

 -- Function: void gnc_price_begin_edit (GNCPrice * P)
     Begin a sequence of changes to P.

 -- Function: void gnc_price_commit_edit (GNCPrice * P)
     End a sequence of changes to P.

 -- Function: void gnc_price_set_commodity (GNCPrice * P, gnc_commodity
          * C)
     Set the commodity of P to C.

 -- Function: void gnc_price_set_currency (GNCPrice * P, gnc_commodity *
          C)
     Set the currency of P to C.

 -- Function: void gnc_price_set_time64 (GNCPrice * P, time64 T)
     Set the time of P to T.

 -- Function: void gnc_price_set_source (GNCPrice * P, const char *
          SOURCE)
     Set the source of P to SOURCE.

 -- Function: void gnc_price_set_type (GNCPrice * P, const char * TYPE)
     Set the type of Pto TYPE.

 -- Function: void gnc_price_set_value (GNCPrice * P, gnc_numeric VALUE)
     Set the value of P to VALUE.

 -- Function: void gnc_price_set_version (GNCPrice * P, gint32 VERSN)
     Set the version of P to VERSN.

2.10 Price Databases
====================

A Price Database stores GNCPrices and allows prices to be looked up
based on currency, commodity, and time.

2.10.1 Price Lists
------------------

Price Lists are used by Price Databases to organize prices for a given
commodity and currency.  A Price List is a list of prices with the same
commodity and currency, sorted by decreasing time (earlier prices come
later in the list).

 -- Function: gboolean gnc_price_list_insert (GList ** PRICES, GNCPrice
          * P)
     Insert price P into the list PRICES, calling GNC_PRICE_REF on P
     during the process.

 -- Function: gboolean gnc_price_list_remove (GList ** PRICES, GNCPrice
          * P)
     Remove price P from the list PRICES, calling 'gnc_price_unref' on P
     during the process.

 -- Function: void gnc_price_list_destroy (GList * PRICES)
     Destroy the price list PRICES, calling 'gnc_price_unref' on all the
     prices in the list.

2.10.2 General Price Database API
---------------------------------

 -- Function: GNCPriceDB * gnc_pricedb_create (void)
     Create and return a new price database.

 -- Function: void gnc_pricedb_destroy (GNCPriceDB * DB)
     Destroy the price database DB and unreference all of the prices it
     contains.  This may not deallocate all of those prices; other code
     may still be holding references to them.

 -- Function: gboolean gnc_pricedb_add_price (GNCPriceDB * DB, GNCPrice
          * P)
     Add the price P to DB.  This will increase the reference count of
     P, so user code may safely drop its reference to the price (i.e.
     call 'gnc_price_unref') if the call succeeds (returns true).

 -- Function: gboolean gnc_pricedb_remove_price (GNCPriceDB * DB,
          GNCPrice * P)
     Removes the price P from the price database DB.  Returns true if
     successful and false otherwise.

2.11 Splits
===========

A Split is the Engine abstraction of an accounting entry in an Account
Ledger.  In accounting terms, a Split is a Ledger Entry.  As such, it
contains the following pieces of information:

A parent Account
     The Account of which it is an entry.

A parent Transaction.
     In accounting terms, this is the Journal Entry which this Ledger
     Entry is linked to.

A 'share quantity'
     This is the number of 'shares' which have been debited to the
     parent Account.  This quantity may be negative, in which case the
     Split represents a 'credit'.  Shares are given in units of the
     security of the Account, unless the security field is NULL, in
     which case shares are given in units of the Account currency.
     See Accounts.

A 'value'
     This represents the value of the shares in units of the currency of
     the Account.  If the currency and the security are the same, or the
     security field is NULL, the value and share quantity must be equal.

A 'reconciled' flag
     This flag represents the reconciled status of the Split.  Possible
     reconciliation states for a Split are:

     Not Reconciled
          The Split has not been reconciled or cleared.

     Cleared
          The Split has been cleared, but not reconciled.

     Reconciled
          The Split has been reconciled with a statement.

     Frozen
          The Split has been frozen into the accounting period.

   In addition to the above, Splits contain a Memo field, an Action
field, and a key-value pair frame.  The Memo and Action fields are for
arbitrary user input.  See src/engine/kvp_frame.txt for the names of
keys that have already been reserved for use in the frame.

2.11.1 General Split API
------------------------

 -- Function: Split * xaccMallocSplit (void)
     Allocate, initialize, and return a new Split.

 -- Function: void xaccSplitDestroy (Split * SPLIT)
     Update SPLIT's parent Account and Transaction in a consistent
     manner, completely unlinking of SPLIT and freeing its memory.  The
     goal of this routine is to perform the removal and destruction of
     the Split in an atomic fashion, with no chance of accidentally
     leaving the accounting structure out-of-balance or otherwise
     inconsistent.

     If the deletion of the Split leaves the Transaction with no Splits,
     then the Transaction will be marked for deletion, but will not be
     deleted until the 'xaccTransCommitEdit()' routine is called.

 -- Function: const GUID * xaccSplitGetGUID (Split * SPLIT)
     Return the GUID of SPLIT.

 -- Function: Split * xaccSplitLookup (const GUID * GUID)
     Return the split associated with GUID, or 'NULL' if there is no
     such split.

 -- Function: void xaccSplitMakeStockSplit (Split * SPLIT)
     Modify SPLIT to be an "official" stock-split split.  Among other
     things, this involves clearing the value of the split to 0.

2.11.2 Split Getters
--------------------

 -- Function: Account * xaccSplitGetAccount (Split * SPLIT)
     Return the parent Account of SPLIT.

 -- Function: Transaction * xaccSplitGetParent (Split * SPLIT)
     Return the parent Transaction of SPLIT.

 -- Function: gnc_numeric xaccSplitGetShareAmount (Split * SPLIT)
     Return the 'share quantity' of SPLIT.

 -- Function: gnc_numeric xaccSplitGetSharePrice (Split * SPLIT)
     Return the 'share price' of SPLIT, which is the value divided by
     the share quantity.

 -- Function: gnc_numeric xaccSplitGetValue (Split * SPLIT)
     Return the value of SPLIT.

 -- Function: gnc_numeric xaccSplitGetBaseValue (Split * SPLIT, const
          char * BASE_CURRENCY)
     Return either the share quantity or the value of SPLIT, depending
     upon whether BASE_CURRENCY matches the security or currency of the
     parent Account, respectively.  No other value for BASE_CURRENCY is
     legal.

 -- Function: char xaccSplitGetReconcile (Split * SPLIT)
     Return the value of the reconcile flag in SPLIT.  Possible values
     for the flag are:

     'NREC'
          Not Reconciled

     'CREC'
          Cleared

     'YREC'
          Reconciled

     'FREC'
          Frozen

 -- Function: void xaccSplitGetDateReconciledTS (Split * SPLIT, Timespec
          * TS)
     Fill TS with the reconciled date of SPLIT.

 -- Function: const char * xaccSplitGetMemo (Split * SPLIT)
     Return the Memo field of SPLIT.

 -- Function: const char * xaccSplitGetAction (Split * SPLIT)
     Return the Action field of SPLIT.

 -- Function: gnc_numeric xaccSplitGetBalance (Split * SPLIT)
     Return the balance of SPLIT's parent Account up to and including
     SPLIT.  See Accounts for details.

 -- Function: gnc_numeric xaccSplitGetClearedBalance (Split * 'split')
     Return the cleared balance of SPLIT's parent Account up to and
     including SPLIT.  See Accounts for details.

 -- Function: gnc_numeric xaccSplitGetReconciledBalance (Split *
          'split')
     Return the reconciled balance of SPLIT's parent Account up to and
     including SPLIT.  See Accounts for details.

 -- Function: gnc_numeric xaccSplitGetShareBalance (Split * SPLIT)
     Return the share balance of SPLIT's parent Account up to and
     including SPLIT.  See Accounts for details.

 -- Function: gnc_numeric xaccSplitGetShareClearedBalance (Split *
          'split')
     Return the share cleared balance of SPLIT's parent Account up to
     and including SPLIT.  See Accounts for details.

 -- Function: gnc_numeric xaccSplitGetShareReconciledBalance (Split *
          'split')
     Return the share reconciled balance of SPLIT's parent Account up to
     and including SPLIT.  See Accounts for details.

 -- Function: const char* xaccSplitGetType (Split * SPLIT)
     Return SPLIT's type as a string.  Currently, the possibilities are

     'normal'
          a normal split - the default.

     'stock-split'
          a split representing a stock split.  The value should be 0 and
          the share amount should represent the number of shares
          added/subtracted from the account as a result of the
          forward/reverse stock split.

2.11.3 Split Setters
--------------------

 -- Function: void xaccSplitSetMemo (Split * SPLIT, const char * MEMO)
     Set the memo field of SPLIT to MEMO.

 -- Function: void xaccSplitSetAction (Split * SPLIT, const char *
          ACTION)
     Set the action field of SPLIT to MEMO.  The action field is an
     arbitrary string, but is intended to be conveniently limited to a
     menu of selections such as "Buy", "Sell", "Interest", etc.

 -- Function: void xaccSplitSetReconcile (Split * SPLIT, char
          RECONCILED_FLAG)
     Set the reconciled flag of SPLIT to RECONCILED_FLAG.  For the
     possible values and meanings of RECONCILED_FLAG, see Split Getters.

 -- Function: void xaccSplitSetDateReconciledSecs (Split * SPLIT, time_t
          TIME)
     Set the reconciliation date of SPLIT to TIME.

 -- Function: void xaccSplitSetDateReconciledTS (Split * SPLIT, Timespec
          * TS)
     Set the reconciliation date of SPLIT to TS.

 -- Function: void xaccSplitSetShareAmount (Split * SPLIT, gnc_numeric
          amount)
     Set the share quantity of SPLIT to AMOUNT.

 -- Function: void xaccSplitSetSharePrice (Split * SPLIT, gnc_numeric
          PRICE)
     Set the share price of SPLIT to PRICE.

 -- Function: void xaccSplitSetSharePriceAndAmount (Split * SPLIT,
          gnc_numeric PRICE, gnc_numeric AMOUNT)
     Set both the share price and share quantity of SPLIT.  This routine
     is more efficient than calling 'xaccSplitSetShareAmount' and
     'xaccSplitSetSharePrice' in succesion.

 -- Function: void xaccSplitSetValue (Split * SPLIT, gnc_numeric VALUE)
     Adjust the share quantity of SPLIT so that SPLIT's value is equal
     to VALUE.

 -- Function: void xaccSplitSetBaseValue (Split * SPLIT, gnc_numeric
          VALUE, const char * BASE_CURRENCY)
     Set either the share quantity or value of SPLIT depending upon
     whether BASE_CURRENCY is the security or current of SPLIT's parent
     Account.  See Accounts.

2.12 Transactions
=================

A Transaction is the Engine abstraction of an accounting entry in a
Journal.  In accounting terms, a Transaction is a Journal Entry.  As
such, it contains the following pieces of information:

A list of Ledger Entries, or Splits
     The list of debits and credits which make up this Transaction.  As
     in accounting, a Transaction is balanced when the sum of the debits
     equals the sum of the credits.

The entry date
     The date the transaction was entered into GnuCash.

The post date
     The date the transaction was posted.  This is often the date the
     transaction was recorded by the bank, or the date the user
     initiated the transaction (i.e., wrote the check, made the ATM
     withdrawal).

A transaction number field
     This field is intended to hold a transaction number, such as a
     check number or an ID assigned by a bank to an electronic transfer.

A description
     A textual description of the transaction.

   In addition to the above, Transactions contain a key-value pair
frame.

2.12.1 The Transaction Edit Cycle
---------------------------------

The Engine supports (and, in fact, requires) a 2-phase commit/rollback
cycle for modifying Transactions and their constituent Splits.  A
Transaction must be opened for editing using 'xaccTransBeginEdit()'
before any of the following actions may be taken.

   * Modifying any field of a Transaction.

   * Modifying any Split belonging to the Transaction.  That includes
     re-parenting a Split to a different Account or a different
     Transaction.  In the case of re-parenting to a new Transaction,
     both Transactions must be opened for editing.

   * Deleting any Split belonging to the Transaction.

   * Adding a Split to the transaction.

   * Deleting the Transaction.

   After the desired changes have been made, they must either be
committed using 'xaccTransCommitEdit()' or rolled back using
'xaccTransRollbackEdit()'.  Rolling back a transaction will undo any
changes which have been made to it or to its Splits since it was opened
for editing.

2.12.2 General Transaction API
------------------------------

 -- Function: Transaction * xaccMallocTransaction (void)
     Allocate, initialize, and return a new Transaction.

 -- Function: void xaccTransDestroy (Transaction * trans)
     Remove all of the Splits from each of their accounts and free the
     memory associated with them.  This routine must be followed by
     either an 'xaccTransCommitEdit()' in which case the transaction
     memory will be freed, or by 'xaccTransRollbackEdit()', in which
     case all the original Splits are put back into place.

 -- Function: void xaccTransAppendSplit (Transaction * TRANS, Split *
          SPLIT)
     Append SPLIT to the collection of Splits in TRANS.  If the Split is
     already a part of another Transaction, it will be removed from that
     Transaction first.

 -- Function: void xaccTransBeginEdit (Transaction * TRANS)
     This method must be called before any changes are made to TRANS or
     any of its component Splits.  If this is not done, errors will
     result.

 -- Function: void xaccTransCommitEdit (Transaction * TRANS)
     This method indicates that the changes to TRANS and its Splits are
     complete and should be made permanent.  Note this routine may
     result in the deletion of the transaction, if the Transaction is
     "empty" (has no Splits) or if 'xaccTransDestroy()' was called on
     the Transaction.

 -- Function: void xaccTransRollbackEdit (Transaction * TRANS)
     Rejects all changes made to TRANS and its Splits, and sets TRANS
     back to where it was before the 'xaccTransBeginEdit()' call.  This
     includes restoring any deleted Splits, removing any added Splits,
     and undoing the effects of 'xaccTransDestroy()', as well as
     restoring share quantities, memos, descriptions, etc.

 -- Function: gboolean xaccTransIsOpen (Transaction * TRANS)
     Return 'TRUE' if TRANS is open for editing.  Otherwise, it returns
     'FALSE'.

 -- Function: const GUID * xaccTransGetGUID (Transaction * TRANS)
     Return the GUID of TRANS.

 -- Function: Transaction * xaccTransLookup (const GUID * GUID)
     Return the Transaction associated with GUID, or 'NULL' if there is
     no such Transaction.

 -- Function: KvpValue * xaccTransGetSlot (Transaction * TRANS, const
          char * KEY)
     Return the 'KvpValue' associated with KEY in TRANS.  If there is
     none, 'NULL' is returned.

 -- Function: void xaccTransSetSlot (Split * TRANS, const char * KEY,
          const KvpValue * VALUE)
     Associate a copy of VALUE with KEY in TRANS.

2.12.3 Transaction Getters
--------------------------

 -- Function: Split * xaccTransGetSplit (Transaction * TRANS, int I)
     Return the Ith Split of TRANS.

 -- Function: GList * xaccTransGetSplitList (Transaction * TRANS)
     Return a 'GList' of the Splits in TRANS.  This list is owned by
     TRANS and should not be modified in any way!

 -- Function: const char * xaccTransGetNum (Transaction * TRANS)
     Return the number field of TRANS.

 -- Function: const char * xaccTransGetDescription (Transaction * TRANS)
     Return the description field of TRANS.

 -- Function: time_t xaccTransGetDate (Transaction * TRANS)
     Return the post date of TRANS as a 'time_t' value.

 -- Function: long long xaccTransGetDateL (Transaction * TRANS)
     Return the post date of TRANS as a 'long long' value.

 -- Function: void xaccTransGetDateTS (Transaction * TRANS, Timespec *
          TS)
     Return the post date of TRANS in TS.

 -- Function: void xaccTransGetDateEnteredTS (Transaction * TRANS,
          Timespec * TS)
     Return the entry date of TRANS in TS.

 -- Function: char * xaccTransGetDateStr (Transaction * TRANS)
     Return a string representing the post date of TRANS, or NULL if
     TRANS is NULL. The string must be freed with 'free()' after use.

 -- Function: int xaccTransCountSplits (Transaction * TRANS)
     Return the number of Splits in TRANS.

2.12.4 Transaction Setters
--------------------------

Remember, before you modify a Transaction, you must open it for editing
with 'xaccTransBeginEdit'.

 -- Function: void xaccTransSetDate (Transaction * TRANS, int DAY, int
          MON, int YEAR)
     Set the post date of TRANS with DAY, MONTH, and YEAR.

 -- Function: void xaccTransSetDateSecs (Transaction * TRANS, time_t
          TIME)
     Set the post date of TRANS using a 'time_t' value.

 -- Function: void xaccTransSetDateToday (Transaction * TRANS)
     Set the post date of TRANS to the current time.

 -- Function: void xaccTransSetDateTS (Transaction * TRANS, const
          Timespec * TS)
     Set the post date of TRANS from TS.

 -- Function: void xaccTransSetDateEnteredSecs (Transaction *trans,
          time_t time)
     Set the entry date of TRANS from a 'time_t' value.

 -- Function: void xaccTransSetDateEnteredTS (Transaction * TRANS, const
          Timespec * TS)
     Set the entry date of TRANS from TS.

 -- Function: void xaccTransSetNum (Transaction * TRANS, const char *
          NUM)
     Set the number field of TRANS to NUM.

 -- Function: void xaccTransSetDescription (Transaction * TRANS, const
          char * DESC)
     Set the description field of TRANS to DESC.

2.13 Accounts
=============

An Account is the Engine abstraction of an, well, an account.  Accounts
contain the following pieces of information:

A list of Ledger Entries, or Splits
     The list of debits and credits which apply to the Account.  The sum
     of all debits and credits is the account balance.

A type
     An integer code identifying the type of account.  The Account type
     determines whether the Account holds shares valued in a currency or
     not.  It is also used by the GUI and reporting system to determine
     how debits & credits to the Account should be treated and
     displayed.

A name
     The name of the Account.

An account code
     A string that is intended to hold a unique user-selected identifier
     for the account.  However, uniqueness of this field is not
     enforced.

A description
     A textual description of the Account.

A currency
     The commodity that Splits in the account are valued in, i.e., the
     denomination of the 'value' member of Splits in the account.

A curreny SCU
     The SCU is the smallest convertible unit that the currency is
     traded in.  This value overrides the default SCU of the currency.

A security
     For Accounts which may contain shares (such as stock accounts), the
     denomination of the 'share quantity' member of Splits in the
     accounts.  For accounts which do not contain shares, the security
     is blank, and the share quantities are denominated in the Account
     currency.

A security SCU
     Analogous to the currency SCU, but for the security.

A parent and child Account Group.
     The parent and child of an Account are Account Groups (see
     Account Groups).  Account Groups are used to connect Accounts
     together into an Account hierarchy.  If the parent Account Group is
     not present, the Account is at the top level of the hierarchy.  If
     the child Account Group is not present, the Account has no
     children.

   In addition to the above, Accounts contain a key-value pair frame.

2.13.1 Account Types
--------------------

Account Types are defined by the 'GNCAccountType' enumeration.  Possible
values are:

'BAD_TYPE, NO_TYPE'
     Both of these values indicate an illegal Account type.

'BANK'
     Denotes a savings or checking account held at a bank.  Such an
     account is often interest bearing.

'CASH'
     Denotes a shoe-box or pillowcase stuffed with cash.  In other
     words, actual currency held by the user.

'CREDIT'
     Denotes credit card accounts.

'ASSET'
     Denotes a generic asset account.

'LIABILITY'
     Denotes a generic liability account.

'STOCK'
     A stock account containing stock shares.

'MUTUAL'
     A mutual fund account containing fund shares.

'CURRENCY'
     Denotes a currency trading account.  In many ways, a currency
     trading account is like a stock trading account, where both
     quantities and prices are set.  However, generally both currency
     and security are national currencies.

'INCOME'
     Denotes an income account.  The GnuCash financial model does not
     use 'categories'.  Actual accounts are used instead.

'EXPENSE'
     Denotes an expense account.

'EQUITY = 10,'
     Denotes an equity account.

2.13.2 General Account API
--------------------------

 -- Function: Account * xaccMallocAccount (void)
     Allocate and initialize an Account.  The account must be destroyed
     by calling 'xaccAccountBeginEdit' followed by 'xaccAccountDestroy'.

 -- Function: void xaccAccountDestroy (Account * ACCOUNT)
     Destroys ACCOUNT and frees all memory associated with it.  This
     routine will also destroy the Account's children.  You must call
     'xaccAccountBeginEdit' before calling this function.

 -- Function: void xaccAccountBeginEdit (Account * ACCOUNT)
     This routine, together with 'xaccAccountCommitEdit', provide a
     two-phase-commit wrapper for account updates much in the same way
     as XACCTRANSBEGINEDIT and XACCTRANSCOMMITEDIT do for Transactions.

 -- Function: void xaccAccountCommitEdit (Account * ACCOUNT)
     The counterpart to XACCACCOUNTBEGINEDIT.

 -- Function: Account * xaccCloneAccountSimple (const Account * FROM)
     Return a 'copy' of FROM that is identical in the type, name, code,
     description, kvp data, and currency.  All other fields are the same
     as an account returned by 'xaccMallocAccount'.

 -- Function: const GUID * xaccAccountGetGUID (Account * ACCOUNT)
     Return the globally unique id associated with ACCOUNT.

 -- Function: Account * xaccAccountLookup (const GUID * GUID)
     Return the Account associated with GUID, or NULL if there is no
     such Account.

 -- Function: kvp_frame * xaccAccountGetSlots (Account * ACCOUNT)
     Return the 'kvp_frame' associated with ACCOUNT.  User code may
     modify this 'kvp_frame', but must not destroy it.

 -- Function: void xaccAccountSetSlots_nc (Account * ACCOUNT, kvp_frame
          * FRAME)
     Set the 'kvp_frame' associated wih ACCOUNT.  After the call, FRAME
     is owned by ACCOUNT, so don't destroy it.

2.13.3 Account Type API
-----------------------

 -- Function: const char * xaccAccountGetTypeStr (GNCAccountType TYPE)
     Return a string corresponding to the given Account type suitable
     for display by a GUI. The string is translated with gettext
     according to the current locale.

 -- Function: char * xaccAccountTypeEnumAsString (GNCAccountType TYPE)
     Return a string corresponding to the given Account type.  The
     string is not translated and is independent of the current locale.

 -- Function: gboolean xaccAccountStringToType (const char * STR,
          GNCAccountType * TYPE)
     Converts a string of the form returned by
     'xaccAccountTypeEnumAsString' to a type, return in TYPE.  Returns
     true if the string corresponds to an actual type.

 -- Function: GNCAccountType xaccAccountStringToEnum (const char * STR)
     Similar to 'xaccAccountStringToEnum', but returns the type.  If STR
     does not correspond to any valid type, 'BAD_TYPE' is returned.

 -- Function: gboolean xaccAccountTypesCompatible (GNCAccountType
          PARENT_TYPE, GNCAccountType CHILD_TYPE)
     Returns TRUE if accounts of type PARENT_TYPE can have child
     accounts of type CHILD_TYPE.  This compatibility is not enforced by
     the engine, but one day it may be!

2.13.4 Account Getters
----------------------

 -- Function: GNCAccountType xaccAccountGetType (Account * ACCOUNT)
     Return the type of ACCOUNT.

 -- Function: const char * xaccAccountGetName (Account * ACCOUNT)
     Return the name of ACCOUNT.

 -- Function: const char * xaccAccountGetCode (Account * ACCOUNT)
     Return the code of ACCOUNT.

 -- Function: const char * xaccAccountGetDescription (Account * ACCOUNT)
     Return the description of ACCOUNT.

 -- Function: const char * xaccAccountGetNotes (Account * ACCOUNT)
     Return the notes of ACCOUNT.

 -- Function: gnc_commodity * xaccAccountGetCurrency (Account * ACCOUNT)
     Return the currency of ACCOUNT.

 -- Function: int xaccAccountGetCurrencySCU (Account * ACCOUNT)
     Return the SCU (smallest convertible unit) of ACCOUNT's currency.

 -- Function: gnc_commodity * xaccAccountGetSecurity (Account * ACCOUNT)
     Return the security of ACCOUNT.  For accounts without shares, this
     field will be 'NULL'.

 -- Function: int xaccAccountGetSecuritySCU (Account * ACCOUNT)
     Return the SCU (smallest convertible unit) of ACCOUNT's security.

 -- Function: gnc_commodity * xaccAccountGetEffectiveSecurity (Account *
          ACCOUNT)
     Get the 'effective' security of the account.  If the account has a
     non-NULL security field, that field will be returned.  Otherwise,
     the currency will be returned.

 -- Function: AccountGroup * xaccAccountGetChildren (Account * ACCOUNT)
     Return the child group of ACCOUNT.  The child group may be 'NULL',
     indicating ACCOUNT has no children.

 -- Function: AccountGroup * xaccAccountGetParent (Account * ACCOUNT)
     Return the parent Group of ACCOUNT.  The parent may be 'NULL',
     indicating ACCOUNT is a top-level Account.  However, even if the
     parent is not 'NULL', the account may still be top-level if the
     parent Group has no parent Account.

 -- Function: Account * xaccAccountGetParentAccount (Account * ACCOUNT)
     Similar to 'xaccAccountGetParent', but returns the parent Account
     of the parent Group if the parent Group exists.  Otherwise, returns
     'NULL'.

 -- Function: gnc_numeric xaccAccountGetBalance (Account * ACCOUNT)
     Return the balance of ACCOUNT, which is also the balance of the
     last Split in ACCOUNT.  If there are no Splits, the balance is
     zero.  The balance is denominated in the Account currency.

 -- Function: gnc_numeric xaccAccountGetClearedBalance (Account *
          ACCOUNT)
     Return the cleared balance of ACCOUNT.  The cleared balance is the
     balance of all Splits in ACCOUNT which are either cleared or
     reconciled or frozen.  The cleared balance is denominated in the
     Account currency.

 -- Function: gnc_numeric xaccAccountGetReconciledBalance (Account *
          ACCOUNT)
     Return the reconciled balance of ACCOUNT.  The reconciled balance
     is the balance of all Splits in ACCOUNT which are reconciled or
     frozen.  The reconciled balance is denominated in the Account
     currency.

 -- Function: gnc_numeric xaccAccountGetShareBalance (Account *account)
     Return the share balance of ACCOUNT, which is also the share
     balance of the last Split in ACCOUNT.  If there are no Splits, the
     balance is zero.  The balance is denominated in the Account
     security, if the Account security exits; otherwise the share
     balance is denominated in the Account currency.

 -- Function: gnc_numeric xaccAccountGetShareClearedBalance (Account *
          ACCOUNT)
     Return the cleared share balance of ACCOUNT.  The cleared share
     balance is the share balance of all Splits in ACCOUNT which are
     either cleared or reconciled or frozen.  The cleared share balance
     is denominated as the share balance.

 -- Function: gnc_numeric xaccAccountGetShareReconciledBalance (Account
          * ACCOUNT)
     Return the reconciled share balance of ACCOUNT.  The reconciled
     share balance is the share balance of all Splits in ACCOUNT which
     are reconciled or frozen.  The reconciled sharea balance is
     denominated as the share balance.

 -- Function: gnc_numeric xaccAccountGetBalanceAsOfDate (Account *
          ACCOUNT, time_t DATE)
     Return the balance of ACCOUNT including all Splits whose parent
     Transactions have posted dates on or before DATE.

 -- Function: gnc_numeric xaccAccountGetShareBalanceAsOfDate (Account *
          ACCOUNT, time_t DATE)
     Return the share balance of ACCOUNT including all Splits whose
     parent Transactions have posted dates on or before DATE.

 -- Function: GList * xaccAccountGetSplitList (Account * ACCOUNT)
     Return a 'GList' of the Splits in ACCOUNT.  This list must not be
     modified in any way.

 -- Function: char * xaccAccountGetFullName (Account * ACCOUNT, const
          char SEPARATOR)
     Returns the fully qualified name of ACCOUNT using the given
     separator character.  The name must be g_freed after use.  The
     fully qualified name of an account is the concatenation of the
     names of the account and all its ancestor accounts starting with
     the topmost account and ending with the given account.  Each name
     is separated by the given character.

2.13.5 Account Tax API
----------------------

This set of API calls is related to tax information.  All accounts have
a tax-related boolean flag that can be set or unset.  There is an
additional set of API calls related to United States taxes that have
'US' in the function call names.  Future API calls that are specific to
other countries should include the appropriate 2-letter country code in
the function names.

 -- Function: gboolean xaccAccountGetTaxRelated (Account * ACCOUNT)
     Return the tax-related flag of ACCOUNT.

 -- Function: void xaccAccountSetTaxRelated (Account * ACCOUNT, gboolean
          TAX_RELATED)
     Set the tax-related flag of ACCOUNT.

 -- Function: const char * xaccAccountGetTaxUSCode (Account * ACCOUNT)
     Get the US-specific tax code associated with ACCOUNT, or 'NULL' if
     there is none.  These codes are internal to GnuCash and currently
     defined in 'src/scm/report/txf-export.scm'.

 -- Function: void xaccAccountSetTaxUSCode (Account * ACCOUNT, const
          char * CODE)
     Set the US-specific tax code associated with ACCOUNT.

 -- Function: const char * xaccAccountGetTaxUSPayerNameSource (Account *
          ACCOUNT)
     Get the payer name source associated with ACCOUNT.  See
     'src/scm/repot/taxtxf.scm' for details.

 -- Function: void xaccAccountSetTaxUSPayerNameSource (Account *
          ACCOUNT, const char * SOURCE)
     Set the payer name source associated with ACCOUNT.

2.14 Account Groups
===================

Account Groups are used by the Engine to connect Accounts together into
an Account hierarchy.  Account Groups do not correspond to any
accounting concept - they are specific to the GnuCash engine.  Account
Groups contain the following pieces of information:

A list of Accounts
     The list Accounts in the Group.

A not-saved flag
     Indicates whether any information in the hierarchy rooted at the
     Group needs to be saved.  That includes Accounts, Splits, and
     Transactions.

   Account Groups do not have key-value frames or GUIDs.

2.14.1 General Account Group API
--------------------------------

 -- Function: AccountGroup * xaccMallocAccountGroup (void)
     Return a newly-allocated & initialized Account Group.  The Group
     must be freed with 'xaccFreeAccountGroup'.

 -- Function: void xaccFreeAccountGroup (AccountGroup * ACCOUNT_GROUP)
     Free the given Group and all its resources, including the Accounts.

 -- Function: void xaccAccountGroupCommitEdit (AccountGroup * GRP)
     Recursively call 'xaccAccountCommitEdit' on all child accounts and
     their children.

 -- Function: void xaccGroupConcatGroup (AccountGroup * TO, AccountGroup
          * FROM)
     Move all accounts in FROM to TO.  After this function returns, FROM
     will have been destroyed.

 -- Function: void xaccGroupMergeAccounts (AccountGroup * GRP)
     Merge all accounts in GRP that have the same name and description.
     The semantics of this function are rather complex.  Consult the
     implementation before use!

 -- Function: gboolean xaccGroupNotSaved (AccountGroup * GRP)
     Return true if GRP has changes which have not been saved.

 -- Function: void xaccGroupMarkSaved (AccountGroup * GRP)
     Mark GRP and all its children as saved.

 -- Function: void xaccGroupMarkNotSaved (AccountGroup * GRP)
     Mark GRP as not saved.

 -- Function: void xaccGroupMarkDoFree (AccountGroup * GRP)
     Mark all accounts in GRP as slated for destruction.  This will
     improve the efficiency of destroying a large account hierarchy.

2.14.2 Account Group Account API
--------------------------------

 -- Function: void xaccGroupRemoveAccount (AccountGroup * GRP, Account *
          ACCOUNT)
     Remove ACCOUNT from GRP.  If ACCOUNT is not in GRP, the function
     will return without performing any action.  In no case will ACCOUNT
     be destroyed or modified.

 -- Function: void xaccAccountRemoveGroup (Account * ACC)
     Remove ACC's child group.  The child group is not otherwise
     modified or destroyed.

 -- Function: void xaccGroupInsertAccount (AccountGroup * GRP, Account *
          ACC)
     Add ACC to GRP.  If ACC is in another Group, it will be removed
     first.

 -- Function: void xaccAccountInsertSubAccount (Account * PARENT,
          Account * CHILD)
     Like 'xaccGroupInsertAccount', but uses a parent Account instead of
     a parent group.  If PARENT does not have a child Group, one will be
     created.

 -- Function: int xaccGroupGetNumSubAccounts (AccountGroup * GRP)
     Return the total number of Accounts in the hierarchy rooted at GRP.

 -- Function: int xaccGroupGetNumAccounts (AccountGroup * GRP)
     Return the number of accounts in GRP.  This count does not include
     Accounts lower in the hierarchy.

 -- Function: int xaccGroupGetDepth (AccountGroup * GRP)
     Returns the length of the longest tree branch in the hierarchy
     rooted at GRP.  Each link between an Account and its (non-null)
     children counts as one unit of length.

 -- Function: Account * xaccGroupGetAccount (AccountGroup * GROUP, int
          INDEX)
     Return the INDEXth Account in GROUP, starting at zero.  If INDEX is
     out of range, 'NULL' is returned.

 -- Function: GList * xaccGroupGetSubAccounts (AccountGroup * GRP)
     Return a list of the Accounts, including sub-Accounts, in GRP.  The
     returned list should be freed with 'g_list_free' when no longer
     needed.

 -- Function: GList * xaccGroupGetAccountList (AccountGroup * GRP)
     Return a list of the immediate children of GRP.  The returned list
     should not be freed or modified in any way.

2.15 GNCBooks
=============

The "GNCBook" interface encapsulates all the information about a GnuCash
dataset, including the methods used to read and write the dataset to
datastores.  This class provides several important services:

   * Prevents multiple users from editing the same file at the same
     time, thus avoiding lost data due to race conditions.  Thus an
     'open book' implies that the associated file is locked.

   * Provides a search path for the file to be edited.  This should
     simplify install & maintenance problems for users who may not have
     a good grasp of what a file system is, or where they want to keep
     their data files.

   The current implementation assumes the use of files and file locks;
however, the API was designed to be general enough to allow the use of
generic URL's, and/or implementation on top of SQL or other
database/persistent object technology.

2.15.1 GNCBook API
------------------

 -- Function: GNCBook * gnc_book_new (void)
     Allocate, initialize, and return a new GNCBook.  The new book will
     contain a newly allocated AccountGroup.

 -- Function: void gnc_book_destroy (GNCBook * BOOK)
     End any editing session associated with BOOK, and free all memory
     associated with it.

 -- Function: gboolean gnc_book_begin (GNCBook * BOOK, const char *
          BOOK_ID, gboolean ignore_lock, gboolean create_if_nonexistent)
     Begins a new book editing session.  It takes as an argument the
     book id.  The book id must be a string in the form of a URI/URL. In
     the current implementation, only one type of URI is supported, and
     that is the file URI: anything of the form
     <file:/home/somewhere/somedir/file.xac> The path part must be a
     valid path.  The file-part must be a valid GnuCash data file.
     Paths may be relative or absolute.  If the path is relative; that
     is, if the argument is <file:somefile.xac> then a sequence of
     search paths are checked for a file of this name.

     The 'ignore_lock' argument, if set to TRUE, will cause this routine
     to ignore any file locks that it finds.  If set to FALSE, then file
     locks will be tested and obeyed.

     If the file exists, can be opened and read, and a lock can be
     obtained then a lock will be obtained and the function returns
     TRUE.

     If the file/database doesn't exist, and the create_if_nonexistent
     flag is set to TRUE, then the database is created.

     Otherwise the function returns FALSE.

 -- Function: gboolean gnc_book_load (GNCBook * BOOK)
     Load the data associated with the book.  The function returns TRUE
     on success.

 -- Function: GNCBackendError gnc_book_get_error (GNCBook * BOOK)
     Obtain the reason for a failure.  Standard errno values are used.
     Calling this routine resets the error value.  This routine allows
     an implementation of multiple error values, e.g.  in a stack, where
     this routine pops the top value.  The current implementation has a
     stack that is one-deep.

     Some important error values:

     'EINVAL'
          bad argument

     'ETXTBSY'
          book id is in use; it's locked by someone else

     'ENOSYS'
          unsupported URI type

     'ERANGE'
          file path too long

     'ENOLCK'
          book not open when 'gnc_book_save()' was called.

 -- Function: const char * gnc_book_get_error_message (GNCBook * BOOK)
     Return a string describing the reason for the current error.
     Calling this routine resets the error value.

 -- Function: GNCBackendError gnc_book_pop_error (GNCBook * BOOK)
     Same as 'gnc_book_get_error', but the error value is reset in BOOK.

 -- Function: AccountGroup * gnc_book_get_group (GNCBook * BOOK)
     Return the current top-level account group.

 -- Function: void gnc_book_set_group (GNCBook * BOOK, AccountGroup *
          TOPGROUP)
     Set the topgroup to a new value.

 -- Function: const char * gnc_book_get_file_path (GNCBook * BOOK)
     Return the fully-qualified file path for the book.  That is, if a
     relative or partial filename was for the book, then it had to have
     been fully resolved to open the book.  This routine returns the
     result of this resolution.

 -- Function: gboolean gnc_book_save_may_clobber_data (GNCBook * BOOK)
     Return TRUE if saving the book would overwrite other information.

 -- Function: void gnc_book_save (GNCBook * BOOK)
     Commit all changes that have been made to the book.

 -- Function: void gnc_book_end (GNCBook * BOOK)
     Release the session lock.  It will _not_ save the account group to
     a file.  Thus, this method acts as an "abort" or "rollback"
     primitive.

2.16 Scrub
==========

3 Component Manager
*******************

*This whole document is completely outdated.  Don't read this.  All
function names and every described structure has changed completely.
Only read this if you want to know how gnucash looked like in 1999.
This is completely outdated!*

   The Component Manager (hereafter referred to as the CM) is a
framework for managing GUI objects in GnuCash.  The CM provides several
services.

   First, components may request automatic invocation of a 'refresh'
handler that is called when a component may need to be redrawn.  This
mechanism is tied into the Engine's Event mechanism (see Events), so
that GUI components are notified when relevant Engine entities are
created, modified, or destroyed.

   Components may also provide a 'close' handler so that the component
may be closed through the CM API.

   The CM also provides the ability to search for existing components.

3.1 Introduction
================

The GnuCash GUI must manage many different components (registers,
reconcile windows, reports, graphs, main window, etc.).  Functions which
need to be performed on or with GUI components include:

   * Refreshing components.  When Engine objects (Accounts,
     Transactions, Splits, etc.)  are created, modified, or destroyed,
     the GUI components which reference those objects must be refreshed.

   * Searching for existing components.  For example, when the user
     chooses to 'Reconcile' an account with an existing reconcile
     dialog, that dialog should be raised to the top in lieu of creating
     a new reconcile dialog.

   * Closing components.

   In particular, keeping components updated in the face of changes in
the Engine is a difficult problem.  Requirements for handling refreshes
include:

   * The Engine should be able to inform user code when any account or
     transaction is changed (including changing their respective
     splits).  This requirement is satisfied by the Engine Events.

   * The refresh mechanism should not have specific knowledge of
     individual windows and other GUI elements.  It should be easy to
     add new refreshable elements to the mechanism.

   * Changes should be batchable with respect to refreshes, so that a
     sequence of changes only cause a refresh after the last change in a
     batch.  Batching should be nestable, for coding simplicity.

   * For very large batches of changes (loading files) we need to be
     able to turn off the mechanism entirely, perform the changes, and
     then perform a global, forced refresh.  This should also be
     nestable.

   * The Engine should not be managing GUI components.

   * The refresh mechanism should be extendable to a multi-user
     situation in which changes can come from external components.

   * Components should be able to specify which Engine entities can
     cause refreshes.  This requirement allows the implementation to
     avoid unnecessary refreshing.

3.2 Refresh Mechanism
=====================

The major design decisions of the CM relate to the refresh mechanism.
The refresh mechanism consists of two parts, the Engine component and
the GUI component.  The Engine component is the Event mechanism (see
Events), while the GUI component is the Component Manager, which
provide refresh functionality as well as other services.

   The diagram below illustrated the design of the GnuCash refresh
mechanism.

                                 ----------
                                 |        |
                                 | Engine |
                                 |        |
                                 ----------
                                     /|\
                                      |
                                      |--- Events (from Engine)
                                      |
                                     \|/
                         -------------------------
                         |                       |
                         |   Component Manager   |
                         |                       |
                         -------------------------
                        /            /|\          \     GUI Commands
                       /              |            \--- including refresh
                      /              \|/            \   invocations (from CM)
     -----------------         -----------------
     |               |         |               |
     | GUI Component |         | GUI Component |           ...
     |               |         |               |
     -----------------         -----------------

   The top-level component is the Engine, which emits Events to the
Component Manager.  In fact, the Engine will send events to any
registered handler, but in GnuCash, only the CM registers with the
engine.  All other GUI components register with the CM.

   The CM invokes the refresh handlers of GUI components based on the
Engine events received the CM has received as well as information
provided by the GUI components (such as which specific Engine entities
the components are 'watching').

3.3 Initialization and Shutdown
===============================

 -- Function: void gnc_component_manager_init (void)
     Initialize the Component Manager.  This should be called before
     using an other CM functions.

 -- Function: void gnc_component_manager_shutdown (void)
     Shutdown the Component Manager.  This should be called to release
     Component Manager resources.

3.4 Refresh Handlers
====================

When a component registers itself with the CM, it may specify two
different handlers: a refresh handler and a close handler.  A refresh
handler is a function with the following type signature:

 -- Data type: GNCComponentRefreshHandler void (*) (GHashTable *CHANGES,
          gpointer USER_DATA)
     This is the type signature of a refresh handler.  The CHANGES hash
     describes the Engine events which have occurred since the last
     refresh.  It is used to determine whether a refresh is actually
     needed.  It may, however, be 'NULL', meaning the component must
     perform a refresh.  The 'user_data' pointer is the data pointer
     supplied when the component was registered.

   When a refresh handler is invoked, it should perform the following
actions:

  1. Check if the component should be closed.  When a refresh handler is
     invoked, any and all of the Engine objects which the component was
     referencing may have been destroyed, possibly making the component
     obsolete.  For example, a dialog to edit the parameters of a
     specific Account should be automatically closed when the account is
     deleted.  On the other hand, a list of all Accounts in a hierarchy
     should be updated when an Account is deleted, but not necessarily
     closed.

     Components must test for the destruction of critical Engine objects
     in two ways.

       1. Use the 'GUID' lookup functions (such as 'xaccAccountLookup'),
          to determine if the engine object is still bound to its
          'GUID'.  Of course, this means that components should store
          the 'GUID's of critical Engine objects instead of simply
          storing their C pointers.

       2. If the first test succeeds and the CHANGES hash table of the
          refresh handler is non-NULL, the component should use the hash
          to determine of the GNC_EVENT_DESTROY event has ocurred for
          the Engine object in question.  The CHANGES hash is a mapping
          from 'GUID's to 'EventInfo' structures.  An 'EventInfo'
          structure has a single member, 'event_mask', of type
          'GNCEngineEventType'.  The 'event_mask' is a logical or of the
          'GNC_EVENT_CREATE', 'GNC_EVENT_MODIFY', and
          'GNC_EVENT_DESTROY' event types.  Since refreshes may not
          occur with every Engine event, 'event_mask' may have all three
          values.

          There is a utility function for accessing the CHANGES hash:

           -- Function: const EventInfo * gnc_gui_get_entity_events
                    (GHashTable * CHANGES, const GUID * ENTITY)
               Return the event info for the entity specified by ENTITY.
               If there are no events for that entity, 'NULL' is
               returned.

     If the CHANGES hash is NULL, then the first test is sufficient to
     determine whether an object has been destroyed.

     If the refresh handler determines the component should be
     destroyed, it should destroy the component and return.

  2. Check if the component should be refreshed.  If the CHANGES hash is
     'NULL', then the component must refresh itself.  Otherwise, it may
     use the CHANGES hash to determine whether or not a refresh is
     actually necessary.  However, since the component may specify which
     particular Engine objects are relevant (see "Watching Components"
     below), generally a component will simply refresh unconditionally.

  3. Refresh the component if necessary.  This includes updating the GUI
     as well as internal structures to reflect the new state of Engine
     objects.

3.5 Close Handlers
==================

A close handler is a function with the following type signature:

 -- Data type: GNCComponentCloseHandler void (*) (gpointer USER_DATA)
     This is the type signature of a close handler.  The 'user_data'
     pointer is the data pointer supplied when the component was
     registered.

   The invocation of a close handler is a command to the component to
close itself.  The component must close itself - the handler should not
be ignored.  The component is still responsible for unregistering itself
with the Component Manager.

3.6 Registering and Unregistering Components
============================================

 -- Function: gint gnc_register_gui_component (const char *
          COMPONENT_CLASS, GNCComponentRefreshHandler REFRESH_HANDLER,
          GNCComponentCloseHandler CLOSE_HANDLER, gpointer USER_DATA)
     Register a gui component with the Component Manager.

     The variable COMPONENT_CLASS is a string specifying a class of
     components.  Certain CM functions can be performed on all
     components in a class.  For that reason, components in the same
     class should all use the same type for USER_DATA.

     REFRESH_HANDLER and CLOSE_HANDLER specify the refresh and close
     handlers, respectively.  Either or both may be 'NULL'.

     The USER_DATA is supplied as an argument when the handlers are
     invoked.

     The function returns the id of the newly-registered component, or
     'NO_COMPONENT' if there was an error.

   After a refresh handler is registered, the component must use the API
calls under "Watching Engine Objects" below to inform the Component
Manager which engine entities are being watched, i.e., which engine
entities may cause the component to need refreshing.  When a component
is first registered, it is not watching anything, and thus will not
receive refresh events.

 -- Function: void gnc_unregister_gui_component (gint COMPONENT_ID)
     Unregister the component with id COMPONENT from the CM.

 -- Function: void gnc_unregister_gui_component_by_data (const char *
          COMPONENT_CLASS, gpointer USER_DATA)
     Unregister all gui components in the class COMPONENT_CLASS which
     have USER_DATA as a user data pointer.

3.7 Watching Engine Objects
===========================

 -- Function: void gnc_gui_component_watch_entity (gint COMPONENT_ID,
          const GUID * ENTITY, GNCEngineEventType EVENT_MASK)
     If EVENT_MASK is non-zero, add the Engine entity specified by
     ENTITY to the list of entities being watched by the component with
     id COMPONENT_ID.  Only the events specified by EVENTS are watched.
     If EVENT_MASK is 0, the call turns off watching for the entity.

 -- Function: void gnc_gui_component_watch_entity_type (gint
          COMPONENT_ID, GNCIdType ENTITY_TYPE, GNCEngineEventType
          EVENT_MASK)
     if EVENT_MASK, turn on watching for all entities of ENTITY_TYPE.
     Only events specified by EVENT_MASK are watched.  If EVENT_MASK is
     0, turns off watching for the entity type.

 -- Function: void gnc_gui_component_clear_watches (gint COMPONENT_ID)
     Clear all watches for the component with id COMPONENT_ID.

3.8 Controlling Refreshes
=========================

 -- Function: void gnc_suspend_gui_refresh (void)
     Suspend the invocation of refresh handlers by the Component
     Manager.  This routine may be called multiple times.  Each call
     increases the suspend counter which starts at zero.  When refreshes
     are not suspended, any engine event causes a refresh cycle in which
     the refresh handler for every component watching for that event is
     invoked.

 -- Function: void gnc_resume_gui_refresh (void)
     Resume the invocation of refresh handlers by the Component Manager.
     Each call reduces the suspend counter by one.  When the counter
     reaches zero, all events which have occurred since the last refresh
     are collected and passed to refresh handlers via the CHANGES
     argument.  Refresh handlers will still be excluded based on their
     watches.

 -- Function: void gnc_gui_refresh_all (void)
     Force all components to refresh, i.e., invoke all refresh handlers
     with a 'NULL' value for CHANGES.

     This routine may only be invoked when the suspend counter is zero.
     It should never be mixed with the suspend/resume refresh routines.

 -- Function: gboolean gnc_gui_refresh_suspended (void)
     Returns TRUE if GUI refreshing is currently suspended.

3.9 Finding Components
======================

The Component Manager API provides two functions that allow components
to be searched for.  Each function uses a find handler to perform the
actual search work.  A find handler is a function with the following
signature:

 -- Data type: GNCComponentFindHandler gboolean (*) (gpointer FIND_DATA,
          gpointer USER_DATA)
     A find handler is invoked with the FIND_DATA specified in the
     search API call, and the USER_DATA of a particular component.  The
     handler should return TRUE if the component matches the search
     criteria and FALSE otherwise.

 -- Function: GList * gnc_find_gui_components (const char *
          COMPONENT_CLASS, GNCComponentFindHandler FIND_HANDLER,
          gpointer FIND_DATA)
     Search for all components in class COMPONENT_CLASS using
     FIND_HANDLER.  Return a 'GList' of the user data pointers of
     matching components.

 -- Function: gpointer gnc_find_first_gui_component (const char *
          COMPONENT_CLASS, GNCComponentFindHandler FIND_HANDLER,
          gpointer FIND_DATA)
     Like 'gnc_find_gui_components' above, but return the user data
     pointer of the first matching component, or 'NULL' if there are no
     matching components.

3.10 Iterating over Components
==============================

The Component Manager API provides a function for iterating over all
components in a class as well as all registered components regardless of
class.

   In either case, a generic component handler is invoked for each
component.  The handler has the following signature:

 -- Data type: GNCComponentHandler void (*) (const char * CLASS, gint
          COMPONENT_ID, gpointer ITER_DATA)
     The component handler is invoked with the CLASS, COMPONENT_ID of a
     particular component, as well as the ITER_DATA supplied in the
     iteration API call.

 -- Function: void gnc_forall_gui_components (const char *
          COMPONENT_CLASS, GNCComponentHandler HANDLER, gpointer
          ITER_DATA)
     Apply HANDLER to every component in COMPONENT_CLASS.  If
     COMPONENT_CLASS is 'NULL', then iteration is performed over every
     registered component.  ITER_DATA is supplied to HANDLER as the
     third argument.

4 Register
**********

*This whole document is completely outdated.  Don't read this.  All
function names and every described structure has changed completely.
Only read this if you want to know how gnucash looked like in 1999.
This is completely outdated!*

   The register is an infrastructure for building a modular matrix of
cells in which each cell may be specialized to perform a particular
function, e.g., to read dates, numerical amounts, or text.  The register
has been designed to be easy to extend, modular, easy to maintain, and
memory efficient.  It is intended to be used for building financial apps
and spread-sheets.

   The register object should not have any 'knowledge' of the accounting
model of GnuCash or of the workings of the main application.  The
register should not be specific to a particular GUI (such as Gnome/GTK).
It should be possible to use the register in a stand-alone fashion.

   The register is built from several types of components: Cells,
Cellblocks, Cursors, the Table, and the Split Register.

4.1 Cells
=========

A "Cell" is an active object which is designed to read a specific kind
of user input.  A Cell object has callbacks that are called when the
user enters the cell (e.g.  by mouse-clicking on a cell in a table, or
tabbing into it), when the user attempts to modify text in the cell
(e.g.  by typing in it), and when the user leaves the cell (e.g.  by
mouse-clicking elsewhere, or tabbing away).

   Special-purpose cells can be created by "inheriting" from the basic
cell object.  Thus, there are special-purpose cells for handling dates,
pull-down menus, text fields with auto-completion from a list of
alternatives, monetary amounts, etc.

   Cells implementations may or may not contain GUI code.  Cells which
require only that text be displayed are completely "GUI-independent",
that is, they depend on the underlying table to display the text.  Cells
which require additional GUI elements (such as pull-down menus) must
implement the proper GUI handling on their own (using, e.g., GTK).

4.1.1 BasicCell
---------------

The "BasicCell" interface defines the core functionality that all cells
must implement.  A BasicCell contains the following data members.

'char *value'
     The 'value' of the cell stored as a character string.

'GdkWChar *w_value'
     The 'value' of the cell stores as a wide character string.

'gint value_len'
     The length of w_value.

'guint32 changed'
     This member is set to have all 1-bits (2^32 - 1) to indicate the
     cell contents have been changed from the register value.

'guint32 conditionally_changed'
     This member is set to have all 1-bits (2^32 - 1) to indicate the
     cell contents have been changed from the register value, but that
     the register should not be considered to be changed unless other
     cells have been changed (not conditionally).

'char * blank_help'
     This member is a text string which may be used by a GUI
     implementation to display an informative help string when the value
     of a cell is empty (perhaps prompting the user to enter a
     particular kind of value).

4.2 Cellblocks
==============

A "Cellblock" is an array of active cells.  The cells are laid out in
rows and columns.  The cellblock serves as a convenient container for
organizing active cells in an array.  Through the mechanism of Cursors
(defined below), it allows a group of cells to be treated as a single
transactional entity.  That is, the cursor/cellblock allows all edits to
a groups of cells to be simultaneously committed or rejected by
underlying engines.  This makes it appropriate for use as a GUI for
transaction-processing applications with two-phase commit requirements.

4.3 Table
=========

The "Table" is a displayed matrix.  The table is a complex object; it is
_not_ merely a cellblock.  The table provides all of the GUI
infrastructure for displaying a row-column matrix of strings.

   The table provides one very important function for minimizing memory
usage for large matrixes - the notion of a "Cursor".  The cursor is a
cellblock (an array of active cells) that is moved to the location that
the user is currently editing.  The cursor "virtualizes" cell functions;
that is, it makes it seem to the user as if all cells in the table are
active, when in fact the only cell that actually needs to be active is
the one that the user is currently editing.

   The table design allows multiple cursors to be defined.  When a user
enters a cell, the appropriate cursor is positioned within the table.
Cursors cannot overlap: any given cell can be mapped to at most one
cursor.  Multiple-cursor support allows tables to be designed that have
a non-uniform layout.  For example, the multiple-cursor support can be
used to define a tree structure of headings and sub-headings, where the
layout/format of the heading is different from the sub-headings.  A
financial example is a table which lists splits underneath their parent
transaction.  This is very different from a checkbook register, where
all entries are uniform, and can be handled with a single repeated
cursor.

   Users of the table must provide a TableView object which provides an
API the table uses to obtain information about the data it is displaying
such as strings, colors, etc.  Thus, the table represents the non-GUI
portion of the View object in the Model-View-Controller paradigm.

4.4 Split Register
==================

The split register is a special-purpose object aimed at the display of
financial transactions.  It includes cells for the date, prices,
balances, transfer accounts, etc.  The register is where the cells,
cursor and table get put together into a unified whole.  The register
defines specific, actual layouts and widths of the date, price, etc.
cells in a table.  It includes a table header, and defines more than ten
specific layouts: bank, credit-card, stock, general journal, etc.

   The split register implementation is divided into two components.
The first component (src/register/splitreg.[ch]) defines the basic
structure and implementation of a split register, but does not
specifically use or depend on the other GnuCash modules, including the
Engine.  Of course, this implementation was created with the engine
financial structures in mind.

   The second component (src/SplitLedger.[ch]) implements the full
register behavior (the Controller in MVC) and makes full use of the
Engine API. This component is responsible for loading transactions and
splits into the register, modifying transactions and splits according to
user input, and accomplishing tasks such as performing automatic
completion.

5 Reports
*********

*This whole document is completely outdated.  Don't read this.  All
function names and every described structure has changed completely.
Only read this if you want to know how gnucash looked like in 1999.
This is completely outdated!*

   The reporting infrastructure is designed facilitate the creation of
sophisticated reports including tables, graphs, and hyperlinks.  The
infrastructure includes functionality to support the following:

   * Creation of tables, with headings, subheadings, totals, and
     subtotals.

   * Formatting of dates & numbers.

   * Currency conversions.

   * Creation of graphs such as pie and bar charts.

   * Creation of hyperlinks to other reports and to other GnuCash
     objects such as registers.

5.1 Creating a Report
=====================

To define a report, your report must have

   '(gnc:support <your_report_name>)'

   and should have

   '(gnc:depend "report-utilities.scm")'

   as well as

   '(gnc:depend "report-html.scm")'

   if you wish to use the html generation facilities.  You should avoid
creating HTML directly wherever possible.

   To autoload your report, you should add the line '(gnc:depend
<your_report_name>)' to the file 'src/scm/report/report-list.scm'.

   '(gnc:depend "date-utilities.scm")'

   has lots of date-manipulation functions you'll almost certainly need.

   To define a report, you call '(gnc:define-report)'.  This function
can accept a variable number of arguments, but at the moment four
distinct arguments are recognised, as in the following from the
transaction report:

       (gnc:define-report
        'version 1
        'name (N_ "Transaction Report")
        'options-generator trep-options-generator
        'renderer trep-renderer)

'version'
     This is the version number of the report, which is currently
     ignored.

'name'
     This is the name of the report.  It should be marked as
     translatable, but the name should be given in untranslated form,
     hence the use of '(N_ )'.

'options-generator'
     This should be a function that takes no arguments and returns an
     options structure with the options for the report.  The options
     interface is currently not fully documented, but should be.

'renderer'
     This is the function which renders the HTML.

6 User Preferences
******************

*This whole document is completely outdated.  Don't read this.  All
function names and every described structure has changed completely.
Only read this if you want to know how gnucash looked like in 1999.
This is completely outdated!*

   The options system is used to obtain user preferences, both globally,
and when displaying a report.  A wide variety of option types are
supported, so it should be possible to create an option for just about
any property the user might wish to specify.  New option types can be
added if necessary, but as the process requires detailed knowledge of
GnuCash internals and GTK+/GNOME, it is not documented here.

   At present, users are most likely to come across the options system
when designing custom reports, and are consequently mostly going to use
the Scheme interface.  There is also a C interface to much of the
options system which is used to access preferences for the UI, but it is
not yet documented.

6.1 Option Databases
====================

The options for a particular report are placed in an "options database".
For doing a report, the option-generator function must return an options
database.  The function

   '(gnc:new-option)'

   returns a new, empty options database that you can then add options
to.

   Options are organised into sections, which are each given a title
string such as "Register" or "International".  The UI displays each
section on a separate page.  Each section has a number of options.  Each
option has a name that uniquely identifies it in that section, and an
alphabetic "sort tag" that determines the relative ordering of the
options for display.

6.2 Option Types
================

Sometimes, GnuCash requires the user to specify true/false properties.
Others properties most easily specified by selections from a list,
others from a number, others still by selecting dates, or one or more
accounts in the account hierarchy, or even colors.  GnuCash supports all
of these and more:

'boolean'

     These are displayed as a checkbox by the UI. They are used to
     specify yes/no answers.

'string'

     The UI provides a text entry box where arbitrary text may be
     entered.

'font'

     This allows users to select fonts from those available on the
     system.

'currency'

     For specifying a currency such as "USD", "AUD", "UKP" etc.

'date'

     For specifying dates.  Depending on exactly what is required, you
     can choose to let the user specify an "absolute" date, a "relative"
     date such as "one month ago", or "start of the current accounting
     period", or let the user choose how whether to specify the required
     date in relative or absolute terms.

'account-list'

     For selecting a particular account or accounts.  The UI displays a
     tree of the account hierarchy.

'multichoice'

     For selecting one of a group of choices.

'list'

     Similar to the multichoice option, but allows the selection of one
     or more items from the group.

'number-range'

     For specifying a numeric quantity.  The programmer can bound the
     range and precision of the quantity.

'pixmap'

     For selecting a pixmap located on the filesystem.

'color'

     For selecting a color value.

'internal'

     An option that isn't specified through an options dialog box.  For
     instance, this is used to store the window dimensions so that they
     are preserved along with other preferences.

6.3 Option Creation
===================

To add an option to an options database, you first create that option,
then register it with the database.  For example, to create a simple
checkbox-style boolean option, you would use
'gnc:make-simple-boolean-option' to create the option.  Once created,
you can then register the option.  With 'gnc:register-option'.

 -- Function: gnc:register-option database option
     Register OPTION in options database DATABASE

   The example below shows how to create an options database, then
register a boolean option with it:

     (define gnc:*hello-world-options* (gnc:new-options))
     (gnc:register-option gnc:*hello-world-options*
          (gnc:make-simple-boolean-option
           "Hello, World!" "Boolean Option"
           "a" "This is a boolean option." #t))

6.3.1 Option Creation Functions
-------------------------------

 -- Function: gnc:make-simple-boolean-option section name sort-tag
          documentation-string default-value

     Creates a boolean option, with option section SECTION and name NAME
     specified as strings.  Note that the section and name strings
     uniquely specify the option for the option database that they get
     registered to, and are used for looking up the option when the
     value is required.  SORT-TAG is a string tag that specifies the
     relative order when displaying the options.  Options are displayed
     top to bottom in case-sensitive alphabetical order.
     DOCUMENTATION-STRING is a string containing a short string
     describing the purpose of the option, which the UI displays as a
     tooltip.  DEFAULT-VALUE should be a boolean value indicating the
     default value of this option.

     Note that SECTION, NAME, SORT-TAG, and DOCUMENTATION-STRING are
     common to all the following functions.

 -- Function: gnc:make-complex-boolean-option section name sort-tag
          documentation-string default-value setter-function-called-cb
          option-widget-changed-cb

     As above, but the function specified in OPTION-WIDGET-CHANGED-CB is
     called when the GUI widget representing the option is changed (the
     user clicks on the toggle button), and SETTER-FUNCTION-CALLED-CB is
     called when the option's setter is called (when the user selects
     "OK" or "Apply").

     One use for having a non-false OPTION-WIDGET-CHANGED-CB is to make
     another option mutable (in concert with 'gnc:option-set-sensitive',
     discussed later).

 -- Function: gnc:make-string-option section name sort-tag
          documentation-string default-value

     Make an option where the user can specify a string.

 -- Function: gnc:make-date-option section name sort-tag
          documentation-string default-getter show-time subtype
          relative-date-list

     Create a date option.  There are three different variations of date
     options, specified by the variable SUBTYPE, which should be one of
     ''relative', ''absolute', or 'both'.  'absolute' date options allow
     the selection of a specific day/month/year combination.  'relative'
     date options allow the selection from a list of different dates
     specified in relation to the current date, such as "today", "start
     of the current month", or "six months ago".  Finally 'both' allows
     the user to choose either using absolute or relative date options.
   DEFAULT-GETTER should be a "thunk" (Scheme function taking no
arguments) that returns a pair.  The car of the pair should contain
either ''relative' or ''absolute', to indicate whether the default value
is relative or absolute.  If the car is 'relative', then the cdr should
be a one of the relative date symbols listed in RELATIVE-DATE-LIST.  If
the car is 'absolute', it should be a timepair containing the default
date/time.

   SHOW-TIME is a boolean that indicates whether when selecting an
absolute date, the user can specify a time.  It is ignored if the
SUBTYPE is 'relative'.

   RELATIVE-DATE-LIST is a list of symbols that indicate the relative
dates permitted.  The symbols used must have been previously defined as
indicating a particular relative date.  GNC:RELATIVE-DATES contains a
list of symbols that have already been set up for the most common
relative dates.  FIXME: document relative date system.

 -- Function: gnc:make-multichoice-option section name sort-tag
          documentation-string default-value value-list

     Create a multichoice option.  VALUE-LIST is a list of vectors of
     length 3, each representing a different choice.  Each vector should
     contain - in the following order:
        * A symbol identifying this choice.
        * A string naming this choice - this string will be the main one
          displayed.
        * A string describing this choice slightly more fully.  This
          string will appear as a tooltip.

 -- Function: gnc:make-list-option section name sort-key
          documentation-string default-values value-list

     Like a multichoice option, but users can select one or more values
     from a list.  DEFAULT-VALUES is a list of selected values instead
     of just one.

 -- Function: gnc:make-font-option section name sort-tag
          documentation-string default-value

     Allow the user to specify the font.  Font options store font
     descriptions as strings, like the X Logical Font Description.  You
     must provide a default value, as there is unfortunately no easy way
     for the GUI to pick a default value.

 -- Function: gnc:make-color-option section name sort-key
          documentation-string default-value
     scale use-alpha?

     Allow the user to select a color.  The default value should be a
     list of length 4 containing the red, green, blue, and alpha channel
     values for the color.  The scale is the maximum value for a
     channel, and the use-alpha?  is a boolean that, if false,
     disregards the alpha channel (note: if you don't know what an alpha
     channel is, you don't need it).

 -- Function: gnc:make-currency-option section name sort-tag
          documentation-string default-value

     Let the user specify a currency using a currency code.  The GUI
     provides a specialised widget for currency selection.

 -- Function: gnc:make-account-list-option section name sort-tag
          documentation-string default-getter value-validator
          multiple-selection

 -- Function: gnc:make-internal-option section name sort-key
          documentation-string default-value
     Create an option that isn't controlled through the options GUI.
     This is used mainly by the GUI to store state that should be
     preserved from session to session but isn't really configurable
     from a dialog box, such as the size of the GnuCash main window.

 -- Function: gnc:make-number-range-option section name sort-tag
          documentation-string default-value lower-bound upper-bound
          num-decimals step-size

     Create an option for selecting a numerical quantity.  lower-bound
     and upper-bound specify the domain of acceptable figures, and
     num-decimals specifies the range to which the option will be
     displayed (FIXME:and rounded to?).  Step-size specifies the step
     size for the UI's up/down buttons.

6.4 Option Values
=================

To get the value of an option, you must first lookup the option in the
options database.

 -- Function: gnc:lookup-option options section name

     Looks up the option in section SECTION and name NAME in the options
     database OPTIONS.

   Once you have looked up the option, you can get its value using the
function 'gnc:option-value'.

 -- Function: gnc:option-value option

     Get the value of an option.  Option values returned are of the same
     type as how the default values are specified (except the date
     option which needs to be fixed).