[Gnucash-changes] Sync the g2 branch with the gnome2-merge-10 tag.

David Hampton hampton at cvs.gnucash.org
Wed Aug 25 18:46:46 EDT 2004


Log Message:
-----------
Sync the g2 branch with the gnome2-merge-10 tag. (2004-08-25)

Tags:
----
gnucash-gnome2-dev

Modified Files:
--------------
    gnucash:
        ChangeLog
        GNOME2_STATUS
    gnucash/src/business/business-core:
        gncAddress.c
        gncBillTerm.c
        gncBillTerm.h
        gncCustomer.c
        gncCustomer.h
        gncEmployee.c
        gncEmployee.h
        gncEntry.c
        gncInvoice.c
        gncJob.c
        gncOrder.c
        gncTaxTable.c
        gncTaxTable.h
        gncVendor.c
    gnucash/src/doc/design:
        engine.texinfo
    gnucash/src/engine:
        Account.c
        Account.h
        Group.c
        Scrub.c
        Scrub2.c
        Transaction.c
        Transaction.h
        cap-gains.c
        cap-gains.h
        gnc-lot.c
        gnc-lot.h
        gnc-numeric.c
        gnc-pricedb.c
        kvp-util.c
        kvp_frame.c
        qof-be-utils.h
        qofbackend-p.h
        qofbook.h
        qofid.c
        qofid.h
        qofmath128.c
        qofquery.c
        qofsession.c
    gnucash/src/engine/test:
        test-lots.c
        test-numeric.c
        test-transaction-reversal.c
    gnucash/src/engine/test-core:
        test-engine-stuff.c
    gnucash/src/gnome:
        gnucash.desktop.in
    gnucash/src/import-export/qif-import:
        qif-dialog-utils.scm
    gnucash/src/report/report-system:
        commodity-utilities.scm
        html-acct-table.scm
        html-table.scm
        report-system.scm
        report-utilities.scm
    gnucash/src/report/standard-reports:
        Makefile.am
        advanced-portfolio.scm
        balance-sheet.scm
        equity-statement.scm
        standard-reports.scm
        transaction.scm

Added Files:
-----------
    gnucash/src:
        count.dat
        count.gplot
    gnucash/src/report/standard-reports:
        general-journal.scm
        general-ledger.scm
        income-statement.scm
        trial-balance.scm

Removed Files:
-------------
    gnucash/src/report/standard-reports:
        pnl.scm

Revision Data
-------------
Index: ChangeLog
===================================================================
RCS file: /home/cvs/cvsroot/gnucash/ChangeLog,v
retrieving revision 1.1487.2.136
retrieving revision 1.1487.2.137
diff -LChangeLog -LChangeLog -u -r1.1487.2.136 -r1.1487.2.137
--- ChangeLog
+++ ChangeLog
@@ -2702,6 +2702,140 @@
 -=-=-=- cvs HEAD ChangeLog is below this line -=-=-=-
 
 
+2004-18-21  Derek Atkins  <derek at ihtfp.com>
+
+	* src/report/standard-reports/advanced-portfolio.scm:
+	  Add option to include zero-amount splits in computations.
+	  Fixes #143722.
+
+2004-18-19  Derek Atkins  <derek at ihtfp.com>
+
+	Neil Williams's "QOF create: functionality added" patch:
+
+	QOF create: adding functions to be used with
+	qof_object_new_instance for new qof_book_merge objects, including
+	business objects.
+
+	Small documentation tweak to make QofEntity and QofParam
+	structures visible to doxygen.
+
+	* src/import-export/qif-import/qif-dialog-utils.scm:
+	  Perry Smith's Null Account Patch.  Make sure the security is
+	  a real string before appending an account separator, so we
+	  don't try to create a "null" account.
+
+2004-08-19  Derek Atkins  <derek at ihtfp.com>
+
+	* configure.in: change the gtkhtml order to search for >= 1.1 before
+	  < 1.1, in order to try to fix #84707 on systems with multiple
+	  versions of gtkhtml.
+
+2004-08-12  David Montenegro  <sunrise2000 at comcast.net>
+
+        * src/report/standard-reports/trial-balance.scm:
+	    src/report/standard-reports/equity-statement.scm:
+	    src/report/report-system/report-utilities.scm:
+	    Added to the work sheet special handling of
+	    inventory and income summary accounts for
+	    merchandising businesses.  Fixes #150008.
+
+2004-08-11  Derek Atkins  <derek at ihtfp.com>
+
+	* src/gnome/gnucash.desktop.in: make the desktop HIG compliant.
+	  Fixes #145545
+
+2004-07-20  Derek Atkins <derek at ihtfp.com>
+
+	* src/engine/Scrub.c
+	* src/engine/Scrub2.c
+	* src/engine/gnc-numeric.c
+	* src/engine/gnc-pricedb.c
+	* src/engine/kvp-util.c
+	* src/engine/qofid.c
+	* src/engine/qofmath128.c
+	* src/engine/qofquery.c
+	* src/engine/qofsession.c
+	* src/engine/test/test-numeric.c
+	  Priit Laes' patch for C90 compliance.
+
+2004-07-13  David Montenegro  <sunrise2000 at comcast.net>
+
+        * src/report/standard-reports/general-ledger.scm:
+	  src/report/standard-reports/standard-reports.scm:
+          src/report/standard-reports/Makefile.am:
+          Added General Ledger report, a Transaction Report
+          with a pre-set set of options.
+
+	* src/report/standard-reports/transaction.scm:
+          FIXME - All accounts now selected by default, avoids
+          confusing error message. Error message also clarified.
+          Fixed "Totals" option so that it works.
+
+        * src/report/standard-reports/balance-sheet.scm:
+        * src/report/standard-reports/equity-statement.scm:
+        * src/report/standard-reports/trial-balance.scm:
+        Updated comments
+	* Fixes #144268
+
+        * src/report/standard-reports/income-statement.scm:
+          src/report/standard-reports/pnl.scm:
+          src/report/standard-reports/standard-reports.scm:
+          src/report/standard-reports/Makefile.am:
+          Rewrote pnl.scm, renamed it to income-statement.scm.
+          Can now create a meaningful statement post-closing.
+
+        * src/report/report-system/html-acct-table.scm:
+          Updated to include ability to "see through" closing
+          and/or adjusting entries.
+	* Fixes #105330.
+
+        * src/report/standard-reports/general-journal.scm:
+          src/report/standard-reports/standard-reports.scm:
+          src/report/standard-reports/Makefile.am:
+          Added General Journal report, a Register Report
+          with a pre-set set of options.
+	* Bug #109738.
+
+2004-07-13  David Montenegro  <sunrise2000 at comcast.net>
+
+        * src/report/standard-reports/trial-balance.scm:
+        * src/report/standard-reports/standard-reports.scm:
+        * src/report/standard-reports/Makefile.am
+          added Trial Balance/Work Sheet report
+
+        * src/report/standard-reports/balance-sheet.scm:
+          added drop-down choices missing in previous version
+          added support for adjusting/closing entries
+
+        * src/report/standard-reports/equity-statement.scm:
+          added support for adjusting/closing entries
+          fixed "For Period Covering" label
+          fixed handling of unrealized gains
+          investment/draw discrimination based on shares sign
+          omit unrealized gains when zero
+
+        * src/report/report-system/html-acct-table.scm:
+        * src/report/report-system/html-table.scm:
+          null reference bug fixes
+
+        * src/report/report-system/report-utilities.scm:
+          added utility functions for accessing splits
+          and creating double-column balance HTML
+          gnc:double-col,
+          gnc:account-get-trans-type-balance-interval,
+          gnc:account-get-pos-trans-total-interval
+
+        * src/report/report-system/commodity-utilities.scm:
+        * src/report/report-system/html-acct-table.scm:
+        * src/report/report-system/report-utilities.scm:
+          moved gnc:commodity-collector-commodity-count and
+          gnc:uniform-commodity? into commodity-utilities.scm
+
+        * src/report/report-system/report-system.scm:
+          added some additional exports
+
+	Bug #144265
+
 2004-07-04  Derek Atkins  <derek at ihtfp.com>
 
 	* acinclude.m4: create a SCANF_QD_CHECK and make sure both
Index: GNOME2_STATUS
===================================================================
RCS file: /home/cvs/cvsroot/gnucash/Attic/GNOME2_STATUS,v
retrieving revision 1.1.2.26
retrieving revision 1.1.2.27
diff -LGNOME2_STATUS -LGNOME2_STATUS -u -r1.1.2.26 -r1.1.2.27
--- GNOME2_STATUS
+++ GNOME2_STATUS
@@ -13,7 +13,7 @@
 names of active developers, that'd be great.
 
 ========================================
-   Last sync with HEAD on 2004-07-05
+   Last sync with HEAD on 2004-08-25
 ========================================
 
 ========================================
Index: Scrub2.c
===================================================================
RCS file: /home/cvs/cvsroot/gnucash/src/engine/Scrub2.c,v
retrieving revision 1.15.2.3
retrieving revision 1.15.2.4
diff -Lsrc/engine/Scrub2.c -Lsrc/engine/Scrub2.c -u -r1.15.2.3 -r1.15.2.4
--- src/engine/Scrub2.c
+++ src/engine/Scrub2.c
@@ -156,6 +156,7 @@
 {
    gnc_commodity *currency = NULL;
    SplitList *snode;
+   GList *node;
    gnc_numeric zero = gnc_numeric_zero();
    gnc_numeric value = zero;
 
@@ -211,7 +212,6 @@
        */
       PERR ("Closed lot fails to double-balance !! lot value=%s",
             gnc_num_dbg_to_string (value));
-      GList *node;
       for (node=lot->splits; node; node=node->next)
       {
         Split *s = node->data;
Index: qofquery.c
===================================================================
RCS file: /home/cvs/cvsroot/gnucash/src/engine/qofquery.c,v
retrieving revision 1.10.2.5
retrieving revision 1.10.2.6
diff -Lsrc/engine/qofquery.c -Lsrc/engine/qofquery.c -u -r1.10.2.5 -r1.10.2.6
--- src/engine/qofquery.c
+++ src/engine/qofquery.c
@@ -1236,13 +1236,13 @@
 
 void qof_query_set_book (QofQuery *q, QofBook *book)
 {
+  GSList *slist = NULL;
   if (!q || !book) return;
 
   /* Make sure this book is only in the list once */
   if (g_list_index (q->books, book) == -1)
     q->books = g_list_prepend (q->books, book);
 
-  GSList *slist = NULL;
   g_slist_prepend (slist, QOF_PARAM_GUID);
   g_slist_prepend (slist, QOF_PARAM_BOOK);
   qof_query_add_guid_match (q, slist,
Index: qofmath128.c
===================================================================
RCS file: /home/cvs/cvsroot/gnucash/src/engine/qofmath128.c,v
retrieving revision 1.6.2.1
retrieving revision 1.6.2.2
diff -Lsrc/engine/qofmath128.c -Lsrc/engine/qofmath128.c -u -r1.6.2.1 -r1.6.2.2
--- src/engine/qofmath128.c
+++ src/engine/qofmath128.c
@@ -43,6 +43,13 @@
 mult128 (gint64 a, gint64 b)
 {
   qofint128 prod;
+  guint64 a0, a1;
+  guint64 b0, b1;
+  guint64 d, d0, d1;
+  guint64 e, e0, e1;
+  guint64 f, f0, f1;
+  guint64 g, g0, g1;
+  guint64 sum, carry, roll, pmax;
 
   prod.isneg = 0;
   if (0>a)
@@ -57,35 +64,35 @@
     b = -b;
   }
 
-  guint64 a1 = a >> 32;
-  guint64 a0 = a - (a1<<32);
+  a1 = a >> 32;
+  a0 = a - (a1<<32);
 
-  guint64 b1 = b >> 32;
-  guint64 b0 = b - (b1<<32);
+  b1 = b >> 32;
+  b0 = b - (b1<<32);
 
-  guint64 d = a0*b0;
-  guint64 d1 = d >> 32;
-  guint64 d0 = d - (d1<<32);
-
-  guint64 e = a0*b1;
-  guint64 e1 = e >> 32;
-  guint64 e0 = e - (e1<<32);
-
-  guint64 f = a1*b0;
-  guint64 f1 = f >> 32;
-  guint64 f0 = f - (f1<<32);
-
-  guint64 g = a1*b1;
-  guint64 g1 = g >> 32;
-  guint64 g0 = g - (g1<<32);
+  d = a0*b0;
+  d1 = d >> 32;
+  d0 = d - (d1<<32);
+
+  e = a0*b1;
+  e1 = e >> 32;
+  e0 = e - (e1<<32);
+
+  f = a1*b0;
+  f1 = f >> 32;
+  f0 = f - (f1<<32);
+
+  g = a1*b1;
+  g1 = g >> 32;
+  g0 = g - (g1<<32);
 
-  guint64 sum = d1+e0+f0;
-  guint64 carry = 0;
+  sum = d1+e0+f0;
+  carry = 0;
   /* Can't say 1<<32 cause cpp will goof it up; 1ULL<<32 might work */
-  guint64 roll = 1<<30;
+  roll = 1<<30;
   roll <<= 2;
 
-  guint64 pmax = roll-1;
+  pmax = roll-1;
   while (pmax < sum)
   {
     sum -= roll;
@@ -125,7 +132,8 @@
 inline qofint128
 shiftleft128 (qofint128 x)
 {
-  guint64 sbit = x.lo & HIBIT;
+  guint64 sbit;
+  sbit = x.lo & HIBIT;
   x.hi <<= 1;
   x.lo <<= 1;
   x.isbig = 0;
@@ -174,6 +182,7 @@
 div128 (qofint128 n, gint64 d)
 {
   qofint128 quotient;
+  int i;
   guint64 remainder = 0;
 
   quotient = n;
@@ -184,7 +193,6 @@
   }
 
   /* Use grade-school long division algorithm */
-  int i;
   for (i=0; i<128; i++)
   {
     guint64 sbit = HIBIT & quotient.hi;
Index: qofid.h
===================================================================
RCS file: /home/cvs/cvsroot/gnucash/src/engine/qofid.h,v
retrieving revision 1.2.6.4
retrieving revision 1.2.6.5
diff -Lsrc/engine/qofid.h -Lsrc/engine/qofid.h -u -r1.2.6.4 -r1.2.6.5
--- src/engine/qofid.h
+++ src/engine/qofid.h
@@ -69,7 +69,9 @@
 #include <string.h>
 #include "guid.h"
 
+/** QofIdType declaration */
 typedef const char * QofIdType;
+/** QofIdTypeConst declaration */
 typedef const char * QofIdTypeConst;
 
 #define QOF_ID_NONE           NULL
@@ -112,10 +114,25 @@
      (obj);                                                   \
   }))
 
-
+/** QofEntity declaration */
 typedef struct QofEntity_s QofEntity;
+/** QofCollection declaration 
+
+ at param e_type QofIdType
+ at param is_dirty gboolean
+ at param hash_of_entities GHashTable
+ at param data gpointer, place where object class can hang arbitrari data
+
+*/
 typedef struct QofCollection_s QofCollection;
 
+/** QofEntity structure
+
+ at param e_type 	Entity type
+ at param guid		GUID for the entity
+ at param collection	Entity collection
+*/
+
 struct QofEntity_s
 {
    QofIdType        e_type;
@@ -171,4 +188,3 @@
 #endif /* QOF_ID_H */
 /** @} */
 /** @} */
-
Index: Scrub.c
===================================================================
RCS file: /home/cvs/cvsroot/gnucash/src/engine/Scrub.c,v
retrieving revision 1.43.4.4
retrieving revision 1.43.4.5
diff -Lsrc/engine/Scrub.c -Lsrc/engine/Scrub.c -u -r1.43.4.4 -r1.43.4.5
--- src/engine/Scrub.c
+++ src/engine/Scrub.c
@@ -137,6 +137,8 @@
 xaccTransScrubOrphans (Transaction *trans)
 {
   SplitList *node;
+  QofBook *book = NULL;
+  AccountGroup *root = NULL;
   for (node = trans->splits; node; node = node->next)
   {
     Split *split = node->data;
@@ -154,8 +156,8 @@
    * XXX we should probably *always* to this, instead of the above loop!
    */
   PINFO ("Free Floating Transaction!");
-  QofBook *book = xaccTransGetBook (trans);
-  AccountGroup *root = xaccGetAccountGroup (book);
+  book = xaccTransGetBook (trans);
+  root = xaccGetAccountGroup (book);
   TransScrubOrphansFast (trans, root);
 }
 
@@ -198,13 +200,22 @@
 void
 xaccTransScrubSplits (Transaction *trans)
 {
+  gnc_commodity *currency;
   GList *node;
 
-  if (!trans)
-    return;
+  if (!trans) return;
+
+  /* The split scrub expects the transaction to have a currency! */
+  currency = xaccTransGetCurrency (trans);
+  if (!currency) 
+  {
+    PERR ("Transaction doesn't have a currency!");
+  }
 
   for (node = trans->splits; node; node = node->next)
+  {
     xaccSplitScrub (node->data);
+  }
 }
 
 void
@@ -212,11 +223,12 @@
 {
   Account *account;
   Transaction *trans;
-  gnc_numeric value;
+  gnc_numeric value, amount;
   gnc_commodity *currency;
   int scu;
 
   if (!split) return;
+  ENTER ("(split=%p)", split);
 
   trans = xaccSplitGetParent (split);
   if (!trans) return;
@@ -242,6 +254,21 @@
     return;  
   }
 
+  /* Split amounts and values should be valid numbers */
+  value = xaccSplitGetValue (split);
+  if (gnc_numeric_check (value))
+  {
+    value = gnc_numeric_zero();
+    xaccSplitSetValue (split, value);
+  }
+
+  amount = xaccSplitGetAmount (split);
+  if (gnc_numeric_check (amount))
+  {
+    amount = gnc_numeric_zero();
+    xaccSplitSetAmount (split, amount);
+  }
+
   currency = xaccTransGetCurrency (trans);
 
   /* If the account doesn't have a commodity, 
@@ -251,16 +278,17 @@
   {
     xaccAccountScrubCommodity (account);
   }
-  if (!account->commodity || !gnc_commodity_equiv (account->commodity, currency))
+  if (!account->commodity || 
+      !gnc_commodity_equiv (account->commodity, currency))
+  {
+    LEAVE ("(split=%p) inequiv currency", split);
     return;
+  }
 
   scu = MIN (xaccAccountGetCommoditySCU (account),
              gnc_commodity_get_fraction (currency));
 
-  value = xaccSplitGetValue (split);
-
-  if (gnc_numeric_same (xaccSplitGetAmount (split),
-                        value, scu, GNC_HOW_RND_ROUND))
+  if (gnc_numeric_same (amount, value, scu, GNC_HOW_RND_ROUND))
   {
     return;
   }
@@ -279,6 +307,7 @@
   xaccTransBeginEdit (trans);
   xaccSplitSetAmount (split, value);
   xaccTransCommitEdit (trans);
+  LEAVE ("(split=%p)", split);
 }
 
 /* ================================================================ */
@@ -334,12 +363,14 @@
                          Account *parent)
 {
   Split *balance_split = NULL;
+  QofBook *book = NULL;
   gnc_numeric imbalance;
   Account *account;
   SplitList *node, *slist;
 
   if (!trans) return;
 
+  ENTER ("()");
   xaccTransScrubSplits (trans);
 
   /* If the transaction is balanced, nothing more to do */
@@ -366,7 +397,7 @@
           /* This should never occur, accounts are always 
            * in an account group */
           PERR ("Can't find root account");
-          QofBook *book = xaccTransGetBook (trans);
+          book = xaccTransGetBook (trans);
           root = xaccGetAccountGroup (book);
        }
        if (NULL == root)
@@ -442,6 +473,7 @@
     xaccSplitScrub (balance_split);
     xaccTransCommitEdit (trans);
   }
+  LEAVE ("()");
 }
 
 /* ================================================================ */
Index: Group.c
===================================================================
RCS file: /home/cvs/cvsroot/gnucash/src/engine/Group.c,v
retrieving revision 1.112.4.6
retrieving revision 1.112.4.7
diff -Lsrc/engine/Group.c -Lsrc/engine/Group.c -u -r1.112.4.6 -r1.112.4.7
--- src/engine/Group.c
+++ src/engine/Group.c
@@ -1267,7 +1267,7 @@
   interface_version: QOF_OBJECT_VERSION,
   e_type:            GNC_ID_GROUP,
   type_label:        "AccountGroup",
-  create:            NULL,
+  create:            (gpointer)xaccMallocAccountGroup,
   book_begin:        group_book_begin,
   book_end:          group_book_end,
   is_dirty:          group_is_dirty,
Index: cap-gains.h
===================================================================
RCS file: /home/cvs/cvsroot/gnucash/src/engine/cap-gains.h,v
retrieving revision 1.4.4.2
retrieving revision 1.4.4.3
diff -Lsrc/engine/cap-gains.h -Lsrc/engine/cap-gains.h -u -r1.4.4.2 -r1.4.4.3
--- src/engine/cap-gains.h
+++ src/engine/cap-gains.h
@@ -26,15 +26,49 @@
  *  This file implements the various routines to automatically
  *  compute and handle Cap Gains/Losses resulting from trading 
  *  activities.  Some of these routines might have broader 
- *  applicability, for handling depreciation *  & etc. 
+ *  applicability, for handling depreciation & etc. 
  *
- *  This code is under development, and is 'alpha': many important
- *  routines are missing, many existing routines are not called 
- *  from inside the engine as needed, and routines may be buggy.
+ *  This code is under development, and is 'beta': we think we're
+ *  mostly done, and we've tested and "things work for us", but there
+ *  may still be something missing, and there might still be some 
+ *  bugs.
  *
  *  This code does not currently handle tax distinctions, e.g
  *  the different tax treatment that short-term and long-term 
  *  cap gains have. 
+ * 
+ * The computation of (Realized) Gains/Losses is performed automatically by
+ * the lot "scrub" routines, using a "double-balance" algorithm. Every
+ * split has two numbers associated with it: an "amount", which is the
+ * number of items that a split describes, and the "value", which is the
+ * cost of those items. In a closed lot, the grand-total amount of items in
+ * the lot is zero: the number of items bought equals the number of items
+ * sold; thus the amount-balance is zero. But since the purchase/sale of
+ * the items in the lot typically happen at different prices, there will
+ * typically be a gain/loss. This gain/loss is the grand-total value of all
+ * the items in the lot (total costs minus total income). 
+ * 
+ * In order to properly account for the gains/losses, an "adjusting split"
+ * is added that brings the total gains/losses back to exactly zero (this
+ * is the second "balance" of "double balance"). This adjusting split will
+ * have an amount of zero (no items are involved) but have a non-zero value
+ * (equal to the total gain/loss). This split can then participate in a
+ * "gains transaction" which records the gains in another account. Thus,
+ * for example, if you record $300 in your bank account due to the purchase
+ * and then the sale of some item, the "gains transaction" will record $300
+ * in income in an income account. Thus, the change in the bank balance is
+ * always reflected by an equal change in income, assuring that the books
+ * are balanced. 
+ *
+ * Notes about auto-recompute:  If the amount in a split is changed, 
+ * then the lot has to be recomputed.
+ * This has a potential trickle-through effect on all later lots. 
+ * Ideally, later lots are dissolved, and recomputed.  However, some 
+ * lots may have been user-hand-built. These should be left alone.
+ *
+ToDo:
+ o XXX Need to create a data-integrity scrubber, tht makes sure that
+   the various flags, and pointers & etc. match. 
  *     @{ */
 
 /** @file cap-gains.h
Index: gnc-numeric.c
===================================================================
RCS file: /home/cvs/cvsroot/gnucash/src/engine/gnc-numeric.c,v
retrieving revision 1.26.4.4
retrieving revision 1.26.4.5
diff -Lsrc/engine/gnc-numeric.c -Lsrc/engine/gnc-numeric.c -u -r1.26.4.4 -r1.26.4.5
--- src/engine/gnc-numeric.c
+++ src/engine/gnc-numeric.c
@@ -82,6 +82,7 @@
 static inline gint64
 gnc_numeric_lcd(gnc_numeric a, gnc_numeric b) 
 {
+  qofint128 lcm;
   if(gnc_numeric_check(a) || gnc_numeric_check(b)) 
   {
     return GNC_ERROR_ARG;
@@ -99,7 +100,7 @@
     return b.denom;
   }
 
-  qofint128 lcm = lcm128 (a.denom, b.denom);
+  lcm = lcm128 (a.denom, b.denom);
   if (lcm.isbig) return GNC_ERROR_ARG;
   return lcm.lo;
 }
@@ -113,6 +114,7 @@
   gint64   num;
   gint64   denom;
   gnc_numeric out;
+  qofint128 red;
 
   t =  rem128 (n, d);
   num = d;
@@ -127,7 +129,7 @@
   }
   /* num now holds the GCD (Greatest Common Divisor) */
 
-  qofint128 red = div128 (n, num);
+  red = div128 (n, num);
   if (red.isbig)
   {
     return gnc_numeric_error (GNC_ERROR_OVERFLOW);
@@ -219,6 +221,7 @@
 gnc_numeric_compare(gnc_numeric a, gnc_numeric b) 
 {
   gint64 aa, bb;
+  qofint128 l, r;
 
   if(gnc_numeric_check(a) || gnc_numeric_check(b)) 
   {
@@ -235,8 +238,8 @@
   if  ((a.denom > 0) && (b.denom > 0))
   {
     /* Avoid overflows using 128-bit intermediate math */
-    qofint128 l = mult128 (a.num, b.denom);
-    qofint128 r = mult128 (b.num, a.denom);
+    l = mult128 (a.num, b.denom);
+    r = mult128 (b.num, a.denom);
     return cmp128 (l,r);
   }
 
@@ -377,18 +380,19 @@
      * Computing the LCD minimizes likelyhood of overflow
      */
     gint64 lcd;
+    qofint128 ca, cb, cab;
     lcd = gnc_numeric_lcd(a,b);
     if (GNC_ERROR_ARG == lcd)
     {
        return gnc_numeric_error(GNC_ERROR_OVERFLOW);
     }
-    qofint128 ca = mult128 (a.num, lcd/a.denom);
+    ca = mult128 (a.num, lcd/a.denom);
     if (ca.isbig) return gnc_numeric_error(GNC_ERROR_OVERFLOW);
 
-    qofint128 cb = mult128 (b.num, lcd/b.denom);
+    cb = mult128 (b.num, lcd/b.denom);
     if (cb.isbig) return gnc_numeric_error(GNC_ERROR_OVERFLOW);
 
-    qofint128 cab = add128 (ca, cb);
+    cab = add128 (ca, cb);
     if (cab.isbig) return gnc_numeric_error(GNC_ERROR_OVERFLOW);
     
     sum.num   = cab.lo;
@@ -414,12 +418,13 @@
 gnc_numeric_sub(gnc_numeric a, gnc_numeric b, 
                 gint64 denom, gint how) 
 {
+  gnc_numeric nb;
   if(gnc_numeric_check(a) || gnc_numeric_check(b)) 
   {
     return gnc_numeric_error(GNC_ERROR_ARG);
   }
 
-  gnc_numeric nb = b;
+  nb = b;
   nb.num = -nb.num;
   return gnc_numeric_add (a, nb, denom, how);
 }
@@ -455,6 +460,13 @@
     }
   }
 
+  if((denom == GNC_DENOM_AUTO) &&
+     ((how & GNC_NUMERIC_DENOM_MASK) == GNC_HOW_DENOM_LCD)) 
+  {
+    denom = gnc_numeric_lcd(a, b);
+    how   = how & GNC_NUMERIC_RND_MASK;
+  }
+
   if(a.denom < 0) {
     a.num *= a.denom;
     a.denom = 1;
@@ -473,6 +485,24 @@
   /* If it looks to be overflowing, try to reduce the fraction ... */
   if (bignume.isbig || bigdeno.isbig)
   {
+    gint64 tmp;
+    a = gnc_numeric_reduce (a);
+    b = gnc_numeric_reduce (b);
+    tmp = a.num;
+    a.num = b.num;
+    b.num = tmp;
+    a = gnc_numeric_reduce (a);
+    b = gnc_numeric_reduce (b);
+
+    bignume = mult128 (a.num, b.num);
+    bigdeno = mult128 (a.denom, b.denom);
+    product.num   = a.num*b.num;
+    product.denom = a.denom*b.denom;
+  }
+
+  /* If it its still overflowing, and rounding is allowed then round */
+  if (bignume.isbig || bigdeno.isbig)
+  {
     /* If rounding allowed, then shift until there's no 
      * more overflow. The conversion at the end will fix 
      * things up for the final value. Else overflow. */
@@ -513,13 +543,6 @@
   }
 #endif
   
-  if((denom == GNC_DENOM_AUTO) &&
-     ((how & GNC_NUMERIC_DENOM_MASK) == GNC_HOW_DENOM_LCD)) 
-  {
-    denom = gnc_numeric_lcd(a, b);
-    how   = how & GNC_NUMERIC_RND_MASK;
-  }
-
   result = gnc_numeric_convert(product, denom, how);                             
   return result;
 }
@@ -534,6 +557,7 @@
                 gint64 denom, gint how) 
 {
   gnc_numeric quotient;
+  qofint128 nume, deno;
 
   if(gnc_numeric_check(a) || gnc_numeric_check(b)) 
   {
@@ -588,60 +612,54 @@
       sgn = -sgn;
       b.num = -b.num;
     }
-    qofint128 nume = mult128(a.num, b.denom);
-    qofint128 deno = mult128(b.num, a.denom);
+    nume = mult128(a.num, b.denom);
+    deno = mult128(b.num, a.denom);
+
+    /* Try to avoid overflow by removing common factors */
+    if (nume.isbig && deno.isbig)
+    {
+      gnc_numeric ra = gnc_numeric_reduce (a);
+      gnc_numeric rb = gnc_numeric_reduce (b);
+
+      gint64 gcf_nume = gcf64(ra.num, rb.num);
+      gint64 gcf_deno = gcf64(rb.denom, ra.denom);
+      nume = mult128(ra.num/gcf_nume, rb.denom/gcf_deno);
+      deno = mult128(rb.num/gcf_nume, ra.denom/gcf_deno);
+    }
+
     if ((0 == nume.isbig) && (0 == deno.isbig))
     {
       quotient.num = sgn * nume.lo;
       quotient.denom = deno.lo;
+      goto dive_done;
     }
     else if (0 == deno.isbig)
     {
       quotient = reduce128 (nume, deno.lo);
-      quotient.num *= sgn;
-    }
-    else
-    {
-      /* Try to avoid overflow by removing common factors */
-      gnc_numeric ra = gnc_numeric_reduce (a);
-      gnc_numeric rb = gnc_numeric_reduce (b);
-
-      gint64 gcf_nume = gcf64(ra.num, rb.num);
-      gint64 gcf_deno = gcf64(rb.denom, ra.denom);
-      qofint128 rnume = mult128(ra.num/gcf_nume, rb.denom/gcf_deno);
-      qofint128 rdeno = mult128(rb.num/gcf_nume, ra.denom/gcf_deno);
-
-      if ((0 == rnume.isbig) && (0 == rdeno.isbig))
-      {
-        quotient.num = sgn * rnume.lo;
-        quotient.denom = rdeno.lo;
-      }
-      else if (0 == rdeno.isbig)
+      if (0 == gnc_numeric_check (quotient))
       {
-        quotient = reduce128 (rnume, rdeno.lo);
         quotient.num *= sgn;
+        goto dive_done;
       }
-      else
-      {
-        /* If rounding allowed, then shift until there's no 
-         * more overflow. The conversion at the end will fix 
-         * things up for the final value. */
-        if ((how & GNC_NUMERIC_RND_MASK) == GNC_HOW_RND_NEVER)
-        {
-          return gnc_numeric_error (GNC_ERROR_OVERFLOW);
-        }
-        while (rnume.isbig || rdeno.isbig)
-        {
-           rnume = shift128 (rnume);
-           rdeno = shift128 (rdeno);
-        }
-        quotient.num = sgn * rnume.lo;
-        quotient.denom = rdeno.lo;
-        if (0 == quotient.denom) 
-        {
-          return gnc_numeric_error (GNC_ERROR_OVERFLOW);
-        }
-      }
+    }
+
+    /* If rounding allowed, then shift until there's no 
+     * more overflow. The conversion at the end will fix 
+     * things up for the final value. */
+    if ((how & GNC_NUMERIC_RND_MASK) == GNC_HOW_RND_NEVER)
+    {
+      return gnc_numeric_error (GNC_ERROR_OVERFLOW);
+    }
+    while (nume.isbig || deno.isbig)
+    {
+       nume = shift128 (nume);
+       deno = shift128 (deno);
+    }
+    quotient.num = sgn * nume.lo;
+    quotient.denom = deno.lo;
+    if (0 == quotient.denom) 
+    {
+      return gnc_numeric_error (GNC_ERROR_OVERFLOW);
     }
   }
   
@@ -651,6 +669,7 @@
     quotient.denom = -quotient.denom;
   }
   
+dive_done:
   if((denom == GNC_DENOM_AUTO) &&
      ((how & GNC_NUMERIC_DENOM_MASK) == GNC_HOW_DENOM_LCD)) 
   {
@@ -704,6 +723,7 @@
   gint        denom_neg=0;
   double      ratio, logratio;
   double      sigfigs;
+  qofint128 nume, newm;
 
   if(gnc_numeric_check(in)) {
     return gnc_numeric_error(GNC_ERROR_ARG);
@@ -800,8 +820,8 @@
      * out.num   = out.num / temp.denom;
      * out.denom = denom;
      */
-    qofint128 nume = mult128 (in.num, temp.num);
-    qofint128 newm = div128 (nume, temp.denom);
+    nume = mult128 (in.num, temp.num);
+    newm = div128 (nume, temp.denom);
     remainder = rem128 (nume, temp.denom);
 
     if (newm.isbig)
Index: Account.c
===================================================================
RCS file: /home/cvs/cvsroot/gnucash/src/engine/Account.c,v
retrieving revision 1.222.4.6
retrieving revision 1.222.4.7
diff -Lsrc/engine/Account.c -Lsrc/engine/Account.c -u -r1.222.4.6 -r1.222.4.7
--- src/engine/Account.c
+++ src/engine/Account.c
@@ -2836,7 +2836,7 @@
   interface_version:     QOF_OBJECT_VERSION,
   e_type:                GNC_ID_ACCOUNT,
   type_label:            "Account",
-  create:                NULL,
+  create:                (gpointer)xaccMallocAccount,
   book_begin:            NULL,
   book_end:              NULL,
   is_dirty:              NULL,
@@ -2849,16 +2849,16 @@
 gboolean xaccAccountRegister (void)
 {
   static QofParam params[] = {
-    { ACCOUNT_NAME_, QOF_TYPE_STRING, (QofAccessFunc)xaccAccountGetName, NULL },
-    { ACCOUNT_CODE_, QOF_TYPE_STRING, (QofAccessFunc)xaccAccountGetCode, NULL },
-    { ACCOUNT_DESCRIPTION_, QOF_TYPE_STRING, (QofAccessFunc)xaccAccountGetDescription, NULL },
-    { ACCOUNT_NOTES_, QOF_TYPE_STRING, (QofAccessFunc)xaccAccountGetNotes, NULL },
+    { ACCOUNT_NAME_, QOF_TYPE_STRING, (QofAccessFunc)xaccAccountGetName, (QofSetterFunc) xaccAccountSetName },
+    { ACCOUNT_CODE_, QOF_TYPE_STRING, (QofAccessFunc)xaccAccountGetCode, (QofSetterFunc) xaccAccountSetCode },
+    { ACCOUNT_DESCRIPTION_, QOF_TYPE_STRING, (QofAccessFunc)xaccAccountGetDescription, (QofSetterFunc) xaccAccountSetDescription },
+    { ACCOUNT_NOTES_, QOF_TYPE_STRING, (QofAccessFunc)xaccAccountGetNotes, (QofSetterFunc) xaccAccountSetNotes },
     { ACCOUNT_PRESENT_, QOF_TYPE_NUMERIC, (QofAccessFunc)xaccAccountGetPresentBalance, NULL },
     { ACCOUNT_BALANCE_, QOF_TYPE_NUMERIC, (QofAccessFunc)xaccAccountGetBalance, NULL },
     { ACCOUNT_CLEARED_, QOF_TYPE_NUMERIC, (QofAccessFunc)xaccAccountGetClearedBalance, NULL },
     { ACCOUNT_RECONCILED_, QOF_TYPE_NUMERIC, (QofAccessFunc)xaccAccountGetReconciledBalance, NULL },
     { ACCOUNT_FUTURE_MINIMUM_, QOF_TYPE_NUMERIC, (QofAccessFunc)xaccAccountGetProjectedMinimumBalance, NULL },
-    { ACCOUNT_TAX_RELATED, QOF_TYPE_BOOLEAN, (QofAccessFunc)xaccAccountGetTaxRelated, NULL },
+    { ACCOUNT_TAX_RELATED, QOF_TYPE_BOOLEAN, (QofAccessFunc)xaccAccountGetTaxRelated, (QofSetterFunc) xaccAccountSetTaxRelated },
     { QOF_PARAM_BOOK, QOF_ID_BOOK, (QofAccessFunc)qof_instance_get_book, NULL },
     { QOF_PARAM_GUID, QOF_TYPE_GUID, (QofAccessFunc)qof_instance_get_guid, NULL },
     { ACCOUNT_KVP, QOF_TYPE_KVP, (QofAccessFunc)qof_instance_get_slots, NULL },
Index: Transaction.h
===================================================================
RCS file: /home/cvs/cvsroot/gnucash/src/engine/Transaction.h,v
retrieving revision 1.141.4.6
retrieving revision 1.141.4.7
diff -Lsrc/engine/Transaction.h -Lsrc/engine/Transaction.h -u -r1.141.4.6 -r1.141.4.7
--- src/engine/Transaction.h
+++ src/engine/Transaction.h
@@ -20,6 +20,62 @@
 /** @addtogroup Engine
     @{ */
 /** @addtogroup Transaction Financial Transactions
+    A good overview of transactions, splits and accounts can be 
+    found in the texinfo documentation, together with an overview of
+    how to use this API.
+
+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.
+                                                                              
+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 sum 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. 
+
+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 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 gives 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". 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.
+
     @{ */
 /** @file Transaction.h 
     @brief API for Transactions and Splits (journal entries)
@@ -60,12 +116,11 @@
 #define TXN_TYPE_PAYMENT 'P'  /**< Transaction is a payment  */
 /**@}*/
 
-/***************************************************************
- * Transaction
- */
+/* --------------------------------------------------------------- */
+/* Transactions */
 
 /** @name Transaction creation and editing */
-/**@{*/
+/** @{ */
 /** 
  The xaccMallocTransaction() will malloc memory and initialize it.
  Once created, it is usually unsafe to merely "free" this memory;
@@ -157,11 +212,11 @@
  */
 guint gnc_book_count_transactions(QofBook *book);
 
-/**@}*/
+/** @} */
 
 
 /** @name Transaction general getters/setters */
-/**@{*/
+/** @{ */
 
 /** Sorts the splits in a transaction, putting the debits first,
  *  followed by the credits.
Index: qofbook.h
===================================================================
RCS file: /home/cvs/cvsroot/gnucash/src/engine/qofbook.h,v
retrieving revision 1.5.2.4
retrieving revision 1.5.2.5
diff -Lsrc/engine/qofbook.h -Lsrc/engine/qofbook.h -u -r1.5.2.4 -r1.5.2.5
--- src/engine/qofbook.h
+++ src/engine/qofbook.h
@@ -62,6 +62,7 @@
   (c_type *) val;                                           \
 })
 
+/** \brief QofBook reference */
 typedef struct _QofBook       QofBook;
                                                                                 
 /** GList of QofBook */
Index: gnc-pricedb.c
===================================================================
RCS file: /home/cvs/cvsroot/gnucash/src/engine/gnc-pricedb.c,v
retrieving revision 1.48.4.5
retrieving revision 1.48.4.6
diff -Lsrc/engine/gnc-pricedb.c -Lsrc/engine/gnc-pricedb.c -u -r1.48.4.5 -r1.48.4.6
--- src/engine/gnc-pricedb.c
+++ src/engine/gnc-pricedb.c
@@ -553,13 +553,14 @@
 gnc_pricedb_create(QofBook * book)
 {
   GNCPriceDB * result;
+  QofCollection *col;
 
   g_return_val_if_fail (book, NULL);
 
   /* There can only be one pricedb per book.  So if one exits already,
    * then use that.  Warn user, they shouldn't be creating two ... 
    */
-  QofCollection *col = qof_book_get_collection (book, GNC_ID_PRICEDB);
+  col = qof_book_get_collection (book, GNC_ID_PRICEDB);
   result = qof_collection_get_data (col);
   if (result) 
   {
@@ -584,10 +585,11 @@
 {
   GList *price_list = (GList *) data;
   GList *node;
+  GNCPrice *p;
 
   for (node = price_list; node; node = node->next)
   {
-    GNCPrice *p = node->data;
+    p = node->data;
 
     p->db = NULL;
   }
@@ -2045,7 +2047,7 @@
   interface_version: QOF_OBJECT_VERSION,
   e_type:            GNC_ID_PRICE,
   type_label:        "Price",
-  create:            NULL,
+  create:            (gpointer)gnc_price_create,
   book_begin:        pricedb_book_begin,
   book_end:          pricedb_book_end,
   is_dirty:          pricedb_is_dirty,
@@ -2059,12 +2061,12 @@
 gnc_pricedb_register (void)
 {
   static QofParam params[] = {
-    { PRICE_COMMODITY, GNC_ID_COMMODITY, (QofAccessFunc)gnc_price_get_commodity, NULL },
-    { PRICE_CURRENCY, GNC_ID_COMMODITY, (QofAccessFunc)gnc_price_get_currency, NULL },
-    { PRICE_DATE, QOF_TYPE_DATE, (QofAccessFunc)gnc_price_get_time, NULL },
-    { PRICE_SOURCE, QOF_TYPE_STRING, (QofAccessFunc)gnc_price_get_source, NULL },
-    { PRICE_TYPE, QOF_TYPE_STRING, (QofAccessFunc)gnc_price_get_type, NULL },
-    { PRICE_VALUE, QOF_TYPE_NUMERIC, (QofAccessFunc)gnc_price_get_value, NULL },
+    { PRICE_COMMODITY, GNC_ID_COMMODITY, (QofAccessFunc)gnc_price_get_commodity, (QofSetterFunc)gnc_price_set_commodity },
+    { PRICE_CURRENCY, GNC_ID_COMMODITY, (QofAccessFunc)gnc_price_get_currency, (QofSetterFunc)gnc_price_set_currency },
+    { PRICE_DATE, QOF_TYPE_DATE, (QofAccessFunc)gnc_price_get_time, (QofSetterFunc)gnc_price_set_time },
+    { PRICE_SOURCE, QOF_TYPE_STRING, (QofAccessFunc)gnc_price_get_source, (QofSetterFunc)gnc_price_set_source },
+    { PRICE_TYPE, QOF_TYPE_STRING, (QofAccessFunc)gnc_price_get_type, (QofSetterFunc)gnc_price_set_type },
+    { PRICE_VALUE, QOF_TYPE_NUMERIC, (QofAccessFunc)gnc_price_get_value, (QofSetterFunc)gnc_price_set_value },
     { NULL },
   };
 
Index: Account.h
===================================================================
RCS file: /home/cvs/cvsroot/gnucash/src/engine/Account.h,v
retrieving revision 1.110.4.6
retrieving revision 1.110.4.7
diff -Lsrc/engine/Account.h -Lsrc/engine/Account.h -u -r1.110.4.6 -r1.110.4.7
--- src/engine/Account.h
+++ src/engine/Account.h
@@ -20,6 +20,22 @@
 /** @addtogroup Engine
     @{ */
 /** @addtogroup Account
+    Splits are grouped into 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" (@pxref{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.
     @{ */
 /** @file Account.h 
     @brief Account handling public routines   
Index: Transaction.c
===================================================================
RCS file: /home/cvs/cvsroot/gnucash/src/engine/Transaction.c,v
retrieving revision 1.261.4.6
retrieving revision 1.261.4.7
diff -Lsrc/engine/Transaction.c -Lsrc/engine/Transaction.c -u -r1.261.4.6 -r1.261.4.7
--- src/engine/Transaction.c
+++ src/engine/Transaction.c
@@ -749,7 +749,7 @@
 xaccSplitSetAmount (Split *s, gnc_numeric amt) 
 {
   if(!s) return;
-  ENTER ("split=%p old amt=%lld/%lld new amt=%lld/%lld", s,
+  ENTER ("(split=%p) old amt=%lld/%lld new amt=%lld/%lld", s,
         s->amount.num, s->amount.denom, amt.num, amt.denom);
 
   check_open (s->parent);
@@ -764,7 +764,7 @@
 xaccSplitSetValue (Split *s, gnc_numeric amt) 
 {
   if(!s) return;
-  ENTER ("split=%p old val=%lld/%lld new val=%lld/%lld", s,
+  ENTER ("(split=%p) old val=%lld/%lld new val=%lld/%lld", s,
         s->value.num, s->value.denom, amt.num, amt.denom);
 
   check_open (s->parent);
@@ -1006,7 +1006,7 @@
 
   if (!trans) return;
 
-  ENTER ("addr=%p", trans);
+  ENTER ("(addr=%p)", trans);
   if (((char *) 1) == trans->num)
   {
     PERR ("double-free %p", trans);
@@ -1044,7 +1044,7 @@
   qof_instance_release (&trans->inst);
   g_free(trans);
 
-  LEAVE ("addr=%p", trans);
+  LEAVE ("(addr=%p)", trans);
 }
 
 /********************************************************************
@@ -1379,11 +1379,20 @@
 gnc_numeric
 xaccTransGetImbalance (const Transaction * trans)
 {
-  if (!trans)
-    return gnc_numeric_zero ();
+  GList *node;
+  gnc_numeric imbal = gnc_numeric_zero();
+  if (!trans) return imbal;
+
+  ENTER("(trans=%p)", trans);
 
-  return xaccSplitsComputeValue (trans->splits, NULL, 
-        trans->common_currency);
+  for (node=trans->splits; node; node=node->next)
+  {
+    Split *s = node->data;
+    imbal = gnc_numeric_add(imbal, xaccSplitGetValue(s),
+                              GNC_DENOM_AUTO, GNC_HOW_DENOM_EXACT);
+  }
+  LEAVE("(trans=%p) imbal=%s", trans, gnc_num_dbg_to_string(imbal));
+  return imbal;
 }
 
 gnc_numeric
@@ -1402,7 +1411,7 @@
     Account *a = xaccSplitGetAccount (s);
     if (a == account)
       total = gnc_numeric_add (total, xaccSplitGetValue (s),
-                               GNC_DENOM_AUTO, GNC_HOW_DENOM_LCD);
+                               GNC_DENOM_AUTO, GNC_HOW_DENOM_EXACT);
   }
   return total;
 }
@@ -1552,6 +1561,9 @@
 xaccTransCommitEdit (Transaction *trans)
 {
    QofBackend *be;
+
+   if (!trans) return;
+
    QOF_COMMIT_EDIT_PART1 (&trans->inst);
 
    /* We increment this for the duration of the call
@@ -1654,7 +1666,7 @@
    trans->inst.editlevel--;
 
    gen_event_trans (trans);
-   LEAVE ("trans addr=%p\n", trans);
+   LEAVE ("(trans=%p)", trans);
 }
 
 /* Ughhh. The Rollback function is terribly complex, and, what's worse,
@@ -2835,8 +2847,9 @@
    * handle some overflow and other error conditions by returning
    * zero.  But still print an error to let us know it happened.
    */
-  if (gnc_numeric_check(price)) {
-    PERR("Computing Shares Price Failed (%d): [ %lld / %lld ] / [ %lld / %lld ]",
+  if (gnc_numeric_check(price)) 
+  {
+    PERR("Computing share price failed (%d): [ %lld / %lld ] / [ %lld / %lld ]",
 	 gnc_numeric_check(price), val.num, val.denom, amt.num, amt.denom);
     return gnc_numeric_create(0,1);
   }
@@ -3201,7 +3214,7 @@
   interface_version:       QOF_OBJECT_VERSION,
   e_type:                  GNC_ID_SPLIT,
   type_label:              "Split",
-  create:                  NULL,
+  create:                  (gpointer)xaccMallocSplit,
   book_begin:              NULL,
   book_end:                NULL,
   is_dirty:                NULL,
@@ -3252,13 +3265,13 @@
       (QofAccessFunc)xaccSplitGetClearedBalance, NULL },
     { SPLIT_RECONCILED_BALANCE, QOF_TYPE_NUMERIC,
       (QofAccessFunc)xaccSplitGetReconciledBalance, NULL },
-    { SPLIT_MEMO, QOF_TYPE_STRING, (QofAccessFunc)xaccSplitGetMemo, NULL },
-    { SPLIT_ACTION, QOF_TYPE_STRING, (QofAccessFunc)xaccSplitGetAction, NULL },
-    { SPLIT_RECONCILE, QOF_TYPE_CHAR, (QofAccessFunc)xaccSplitGetReconcile, NULL },
-    { SPLIT_AMOUNT, QOF_TYPE_NUMERIC, (QofAccessFunc)xaccSplitGetAmount, NULL },
+    { SPLIT_MEMO, QOF_TYPE_STRING, (QofAccessFunc)xaccSplitGetMemo, (QofSetterFunc)xaccSplitSetMemo },
+    { SPLIT_ACTION, QOF_TYPE_STRING, (QofAccessFunc)xaccSplitGetAction, (QofSetterFunc)xaccSplitSetAction },
+    { SPLIT_RECONCILE, QOF_TYPE_CHAR, (QofAccessFunc)xaccSplitGetReconcile, (QofSetterFunc)xaccSplitSetReconcile },
+    { SPLIT_AMOUNT, QOF_TYPE_NUMERIC, (QofAccessFunc)xaccSplitGetAmount, (QofSetterFunc)xaccSplitSetAmount },
     { SPLIT_SHARE_PRICE, QOF_TYPE_NUMERIC,
-      (QofAccessFunc)xaccSplitGetSharePrice, NULL },
-    { SPLIT_VALUE, QOF_TYPE_DEBCRED, (QofAccessFunc)xaccSplitGetValue, NULL },
+      (QofAccessFunc)xaccSplitGetSharePrice, (QofSetterFunc)xaccSplitSetSharePrice },
+    { SPLIT_VALUE, QOF_TYPE_DEBCRED, (QofAccessFunc)xaccSplitGetValue, (QofSetterFunc)xaccSplitSetValue },
     { SPLIT_TYPE, QOF_TYPE_STRING, (QofAccessFunc)xaccSplitGetType, NULL },
     { SPLIT_VOIDED_AMOUNT, QOF_TYPE_NUMERIC,
       (QofAccessFunc)xaccSplitVoidFormerAmount, NULL },
@@ -3273,7 +3286,7 @@
     { SPLIT_ACCT_FULLNAME, SPLIT_ACCT_FULLNAME, no_op, NULL },
     { SPLIT_CORR_ACCT_NAME, SPLIT_CORR_ACCT_NAME, no_op, NULL },
     { SPLIT_CORR_ACCT_CODE, SPLIT_CORR_ACCT_CODE, no_op, NULL },
-    { SPLIT_KVP, QOF_TYPE_KVP, (QofAccessFunc)xaccSplitGetSlots, NULL },
+    { SPLIT_KVP, QOF_TYPE_KVP, (QofAccessFunc)xaccSplitGetSlots, (QofSetterFunc)xaccSplitSetSlots_nc },
     { QOF_PARAM_BOOK, QOF_ID_BOOK, (QofAccessFunc)xaccSplitGetBook, NULL },
     { QOF_PARAM_GUID, QOF_TYPE_GUID, (QofAccessFunc)qof_entity_get_guid, NULL },
     { NULL },
@@ -3297,7 +3310,7 @@
   interface_version:   QOF_OBJECT_VERSION,
   e_type:              GNC_ID_TRANS,
   type_label:          "Transaction",
-  create:              NULL,
+  create:              (gpointer)xaccMallocTransaction,
   book_begin:          NULL,
   book_end:            NULL,
   is_dirty:            NULL,
@@ -3318,15 +3331,15 @@
 gboolean xaccTransRegister (void)
 {
   static QofParam params[] = {
-    { TRANS_NUM, QOF_TYPE_STRING, (QofAccessFunc)xaccTransGetNum,NULL },
-    { TRANS_DESCRIPTION, QOF_TYPE_STRING, (QofAccessFunc)xaccTransGetDescription,NULL },
-    { TRANS_DATE_ENTERED, QOF_TYPE_DATE, (QofAccessFunc)xaccTransRetDateEnteredTS,NULL },
-    { TRANS_DATE_POSTED, QOF_TYPE_DATE, (QofAccessFunc)xaccTransRetDatePostedTS,NULL },
-    { TRANS_DATE_DUE, QOF_TYPE_DATE, (QofAccessFunc)xaccTransRetDateDueTS,NULL },
+    { TRANS_NUM, QOF_TYPE_STRING, (QofAccessFunc)xaccTransGetNum, (QofSetterFunc)xaccTransSetNum },
+    { TRANS_DESCRIPTION, QOF_TYPE_STRING, (QofAccessFunc)xaccTransGetDescription, (QofSetterFunc)xaccTransSetDescription },
+    { TRANS_DATE_ENTERED, QOF_TYPE_DATE, (QofAccessFunc)xaccTransRetDateEnteredTS, (QofSetterFunc)xaccTransSetDateEnteredTS },
+    { TRANS_DATE_POSTED, QOF_TYPE_DATE, (QofAccessFunc)xaccTransRetDatePostedTS, (QofSetterFunc)xaccTransSetDatePostedTS },
+    { TRANS_DATE_DUE, QOF_TYPE_DATE, (QofAccessFunc)xaccTransRetDateDueTS, (QofSetterFunc)xaccTransSetDateDueTS },
     { TRANS_IMBALANCE, QOF_TYPE_NUMERIC, (QofAccessFunc)xaccTransGetImbalance,NULL },
-    { TRANS_NOTES, QOF_TYPE_STRING, (QofAccessFunc)xaccTransGetNotes,NULL },
+    { TRANS_NOTES, QOF_TYPE_STRING, (QofAccessFunc)xaccTransGetNotes, (QofSetterFunc)xaccTransSetNotes },
     { TRANS_IS_BALANCED, QOF_TYPE_BOOLEAN, (QofAccessFunc)trans_is_balanced_p,NULL },
-    { TRANS_TYPE, QOF_TYPE_CHAR, (QofAccessFunc)xaccTransGetTxnType,NULL },
+    { TRANS_TYPE, QOF_TYPE_CHAR, (QofAccessFunc)xaccTransGetTxnType, (QofSetterFunc)xaccTransSetTxnType },
     { TRANS_VOID_STATUS, QOF_TYPE_BOOLEAN, (QofAccessFunc)xaccTransGetVoidStatus,NULL },
     { TRANS_VOID_REASON, QOF_TYPE_STRING, (QofAccessFunc)xaccTransGetVoidReason,NULL },
     { TRANS_VOID_TIME, QOF_TYPE_DATE, (QofAccessFunc)xaccTransGetVoidTime,NULL },
Index: qofsession.c
===================================================================
RCS file: /home/cvs/cvsroot/gnucash/src/engine/qofsession.c,v
retrieving revision 1.2.4.6
retrieving revision 1.2.4.7
diff -Lsrc/engine/qofsession.c -Lsrc/engine/qofsession.c -u -r1.2.4.6 -r1.2.4.7
--- src/engine/qofsession.c
+++ src/engine/qofsession.c
@@ -476,6 +476,7 @@
 qof_session_begin (QofSession *session, const char * book_id, 
                    gboolean ignore_lock, gboolean create_if_nonexistent)
 {
+  char * p;
   if (!session) return;
 
   ENTER (" sess=%p ignore_lock=%d, book-id=%s", 
@@ -511,7 +512,7 @@
    * "postgres://". Everything before the colon is the access 
    * method.  Load the first backend found for that access method.
    */
-  char * p = strchr (book_id, ':');
+  p = strchr (book_id, ':');
   if (p)
   {
     char * access_method = g_strdup (book_id);
@@ -588,6 +589,11 @@
    * id and a lock on the file. */
 
   oldbooks = session->books;
+
+  /* XXX why are we creating a book here? I think the books
+   * need to be handled by the backend ... especially since 
+   * the backend may need to load multiple books ... XXX. FIXME.
+   */
   newbook = qof_book_new();
   session->books = g_list_append (NULL, newbook);
   PINFO ("new book=%p", newbook);
@@ -619,6 +625,11 @@
       }
   }
 
+  /* XXX if the load fails, then we try to restore the old set of books;
+   * however, we don't undo the session id (the URL).  Thus if the 
+   * user attempts to save after a failed load, they weill be trying to 
+   * save to some bogus URL.   This is wrong. XXX  FIXME.
+   */
   err = qof_session_get_error(session);
   if ((err != ERR_BACKEND_NO_ERR) &&
       (err != ERR_FILEIO_FILE_TOO_OLD) &&
Index: cap-gains.c
===================================================================
RCS file: /home/cvs/cvsroot/gnucash/src/engine/cap-gains.c,v
retrieving revision 1.13.4.2
retrieving revision 1.13.4.3
diff -Lsrc/engine/cap-gains.c -Lsrc/engine/cap-gains.c -u -r1.13.4.2 -r1.13.4.3
--- src/engine/cap-gains.c
+++ src/engine/cap-gains.c
@@ -27,15 +27,12 @@
  *  This file implements the various routines to automatically
  *  compute and handle Cap Gains/Losses resulting from trading 
  *  activities.  Some of these routines might have broader 
- *  applicability, for handling depreciation *  & etc. 
+ *  applicability, for handling depreciation & etc. 
  *
- *  This code is under development, and is 'alpha': many important
- *  routines are missing, many existing routines are not called 
- *  from inside the engine as needed, and routines may be buggy.
- *
- *  This code does not currently handle tax distinctions, e.g
- *  the different tax treatment that short-term and long-term 
- *  cap gains have. 
+ *  This code is under development, and is 'beta': we think we're
+ *  mostly done, and we've tested and "things work for us", but there
+ *  may still be something missing, and there might still be some 
+ *  bugs.
  *
  * This code uses a 'gains dirty' flag: A 'dirty' flag on the source 
  * split indicates that the gains transaction needs to be recomputed.
@@ -192,7 +189,8 @@
       
    lot = xaccAccountFindOpenLot (acc, sign, currency,
                    10000000LL * ((long long) LONG_MAX), earliest_pred);
-   LEAVE ("found lot=%p %s", lot, gnc_lot_get_title (lot));
+   LEAVE ("found lot=%p %s baln=%s", lot, gnc_lot_get_title (lot),
+               gnc_num_dbg_to_string(gnc_lot_get_balance(lot)));
    return lot;
 }
 
@@ -488,7 +486,7 @@
       val_a = gnc_numeric_mul (frac, val_tot, 
                         gnc_numeric_denom(val_tot), 
                         GNC_HOW_RND_ROUND| GNC_HOW_DENOM_EXACT);
-
+ 
       val_b = gnc_numeric_sub_fixed (val_tot, val_a);
       if (gnc_numeric_check(val_a))
       {
@@ -608,7 +606,8 @@
     */
    while (split)
    {
-     PINFO ("have split amount=%s", gnc_num_dbg_to_string (split->amount));
+     PINFO ("have split %p amount=%s", split, 
+             gnc_num_dbg_to_string (split->amount));
      split->gains |= GAINS_STATUS_VDIRTY;
      lot = pcy->PolicyGetLot (pcy, split);
      if (!lot)
@@ -674,6 +673,16 @@
 
    /* Make sure the status flags and pointers are initialized */
    if (GAINS_STATUS_UNKNOWN == split->gains) xaccSplitDetermineGainStatus(split);
+
+   /* Not possible to have gains if the transaction currency and 
+    * account commodity are identical. */
+   if (gnc_commodity_equal (currency,
+                            xaccAccountGetCommodity(split->acc)))
+   {
+      LEAVE ("Currency transfer, gains not possible, returning.");
+      return;
+   }
+
    if (pcy->PolicyIsOpeningSplit (pcy, lot, split))
    {
 #if MOVE_THIS_TO_A_DATA_INTEGRITY_SCRUBBER 
@@ -928,6 +937,7 @@
           * just in case someone screwed with it! */
          if (FALSE == gnc_commodity_equiv(currency,trans->common_currency))
          {
+            PWARN ("Resetting the transaction currency!");
             xaccTransSetCurrency (trans, currency);
          }
       }
@@ -955,7 +965,7 @@
 
       xaccTransCommitEdit (trans);
    }
-   LEAVE ("(lot=%s)", kvp_frame_get_string (gnc_lot_get_slots (lot), "/title"));
+   LEAVE ("(lot=%s)", gnc_lot_get_title(lot));
 }
 
 /* ============================================================== */
Index: qofbackend-p.h
===================================================================
RCS file: /home/cvs/cvsroot/gnucash/src/engine/qofbackend-p.h,v
retrieving revision 1.2.4.1
retrieving revision 1.2.4.2
diff -Lsrc/engine/qofbackend-p.h -Lsrc/engine/qofbackend-p.h -u -r1.2.4.1 -r1.2.4.2
--- src/engine/qofbackend-p.h
+++ src/engine/qofbackend-p.h
@@ -72,9 +72,17 @@
  *    exist.  This flag is used to implement the 'SaveAs' GUI, where
  *    the user requests to save data to a new backend.
  *
- * The load() routine should return at least an account tree,
- *    all currencies, pricedb, and any other data that needs to be
- *    loaded at start time.  It does not have to return any
+ * The load() routine should load the minimal set of application data
+ *    needed for the application to be operable at initial startup.
+ *    It is assumed that the application will perform a 'run_query()'
+ *    to obtain any additional data that it needs.  For file-based
+ *    backends, it is acceptable for the backend to return all data
+ *    at load time; for SQL-based backends, it is acceptable for the
+ *    backend to return no data.
+ *
+ *    Thus, for example, for GnuCash, the postrges backend returns
+ *    the account tree, all currencies, and the pricedb, as these
+ *    are needed at startup.  It does not have to return any
  *    transactions whatsoever, as these are obtained at a later stage
  *    when a user opens a register, resulting in a query being sent to
  *    the backend.
Index: gnc-lot.c
===================================================================
RCS file: /home/cvs/cvsroot/gnucash/src/engine/gnc-lot.c,v
retrieving revision 1.14.4.4
retrieving revision 1.14.4.5
diff -Lsrc/engine/gnc-lot.c -Lsrc/engine/gnc-lot.c -u -r1.14.4.4 -r1.14.4.5
--- src/engine/gnc-lot.c
+++ src/engine/gnc-lot.c
@@ -247,7 +247,10 @@
    Account * acc;
    if (!lot || !split) return;
 
-   ENTER ("(lot=%p, split=%p)", lot, split);
+   ENTER ("(lot=%p, split=%p) %s amt=%s val=%s", lot, split,
+        gnc_lot_get_title (lot), 
+        gnc_num_dbg_to_string (split->amount),
+        gnc_num_dbg_to_string (split->value));
    acc = xaccSplitGetAccount (split);
    if (NULL == lot->account)
    {
Index: kvp_frame.c
===================================================================
RCS file: /home/cvs/cvsroot/gnucash/src/engine/kvp_frame.c,v
retrieving revision 1.30.4.5
retrieving revision 1.30.4.6
diff -Lsrc/engine/kvp_frame.c -Lsrc/engine/kvp_frame.c -u -r1.30.4.5 -r1.30.4.6
--- src/engine/kvp_frame.c
+++ src/engine/kvp_frame.c
@@ -667,9 +667,11 @@
 KvpValue * 
 kvp_frame_get_slot(const KvpFrame * frame, const char * slot) 
 {
+  KvpValue *v;
   if (!frame) return NULL;
   if (!frame->hash) return NULL;  /* Error ... */
-  return (KvpValue *)g_hash_table_lookup(frame->hash, slot);
+  v = g_hash_table_lookup(frame->hash, slot);
+  return v;
 }
 
 /* ============================================================ */
Index: qofid.c
===================================================================
RCS file: /home/cvs/cvsroot/gnucash/src/engine/qofid.c,v
retrieving revision 1.3.2.4
retrieving revision 1.3.2.5
diff -Lsrc/engine/qofid.c -Lsrc/engine/qofid.c -u -r1.3.2.4 -r1.3.2.5
--- src/engine/qofid.c
+++ src/engine/qofid.c
@@ -182,8 +182,9 @@
 static void
 qof_collection_remove_entity (QofEntity *ent)
 {
+  QofCollection *col;
   if (!ent) return;
-  QofCollection *col = ent->collection;
+  col = ent->collection;
   if (!col) return;
   g_hash_table_remove (col->hash_of_entities, &ent->guid);
   ent->collection = NULL;
Index: gnc-lot.h
===================================================================
RCS file: /home/cvs/cvsroot/gnucash/src/engine/gnc-lot.h,v
retrieving revision 1.8.4.5
retrieving revision 1.8.4.6
diff -Lsrc/engine/gnc-lot.h -Lsrc/engine/gnc-lot.h -u -r1.8.4.5 -r1.8.4.6
--- src/engine/gnc-lot.h
+++ src/engine/gnc-lot.h
@@ -31,7 +31,22 @@
  *
  * Lots are required to correctly implement invoices, inventory,
  * depreciation and stock market investment gains. See the file
- * src/doc/lots.txt for implmentation overview.
+ * src/doc/lots.txt for a detailed implementation overview.
+ *
+ * A lot is "closed" when the number of items in the lot has gone to zero.
+ * It is very easy to compute the gains/losses for a closed lot: it is the
+ * sum-total of the values of the items put into/taken out of the lot.
+ * (Realized) Gains on still-open lots can be computed by pro-rating the 
+ * purchase prices. 
+ * 
+ * Lots are nothing more than a collection or grouping of splits in an
+ * account. All of the splits in a lot must belong to the same account;
+ * there's no mix-n-match.  Thus, in this sense, a lot belongs to an
+ * accunt as well.
+ *
+ * Lots have an implicit "opening date": the date of the earliest split in
+ * the lot. The "close date" is the date of the split that brought the lot
+ * item balance down to zero. 
  *
  @{ */
 
Index: qof-be-utils.h
===================================================================
RCS file: /home/cvs/cvsroot/gnucash/src/engine/qof-be-utils.h,v
retrieving revision 1.3.2.1
retrieving revision 1.3.2.2
diff -Lsrc/engine/qof-be-utils.h -Lsrc/engine/qof-be-utils.h -u -r1.3.2.1 -r1.3.2.2
--- src/engine/qof-be-utils.h
+++ src/engine/qof-be-utils.h
@@ -57,7 +57,7 @@
     PERR ("unbalanced call - resetting (was %d)", (inst)->editlevel); \
     (inst)->editlevel = 1;                                          \
   }                                                                 \
-  ENTER ("inst=%p", (inst));                                        \
+  ENTER ("(inst=%p)", (inst));                                      \
                                                                     \
   /* See if there's a backend.  If there is, invoke it. */          \
   be = qof_book_get_backend ((inst)->book);                         \
@@ -107,7 +107,7 @@
     PERR ("unbalanced call - resetting (was %d)", (inst)->editlevel); \
     (inst)->editlevel = 0;                                       \
   }                                                              \
-  ENTER ("inst=%p, dirty=%d do-free=%d",                         \
+  ENTER ("(inst=%p) dirty=%d do-free=%d",                        \
             (inst), (inst)->dirty, (inst)->do_free);             \
 }
 
Index: kvp-util.c
===================================================================
RCS file: /home/cvs/cvsroot/gnucash/src/engine/kvp-util.c,v
retrieving revision 1.4.4.4
retrieving revision 1.4.4.5
diff -Lsrc/engine/kvp-util.c -Lsrc/engine/kvp-util.c -u -r1.4.4.4 -r1.4.4.5
--- src/engine/kvp-util.c
+++ src/engine/kvp-util.c
@@ -165,7 +165,7 @@
 static KvpFrame *
 gnc_kvp_bag_get_first (KvpFrame *root, const char * path)
 {
-  KvpValue *arr;
+  KvpValue *arr, *va;
   KvpValueType valtype;
   GList *node;
 
@@ -182,7 +182,7 @@
   node = kvp_value_get_glist(arr);
   if (NULL == node) return NULL;
 
-  KvpValue *va = node->data;
+  va = node->data;
   return kvp_value_get_frame(va);
 }
 
Index: gncEmployee.c
===================================================================
RCS file: /home/cvs/cvsroot/gnucash/src/business/business-core/gncEmployee.c,v
retrieving revision 1.15.4.3
retrieving revision 1.15.4.4
diff -Lsrc/business/business-core/gncEmployee.c -Lsrc/business/business-core/gncEmployee.c -u -r1.15.4.3 -r1.15.4.4
--- src/business/business-core/gncEmployee.c
+++ src/business/business-core/gncEmployee.c
@@ -403,7 +403,7 @@
   interface_version:  QOF_OBJECT_VERSION,
   e_type:             _GNC_MOD_NAME,
   type_label:         "Employee",
-  create:             NULL,
+  create:             (gpointer)gncEmployeeCreate,
   book_begin:         NULL,
   book_end:           NULL,
   is_dirty:           qof_collection_is_dirty,
@@ -416,10 +416,17 @@
 gboolean gncEmployeeRegister (void)
 {
   static QofParam params[] = {
-    { EMPLOYEE_ID, QOF_TYPE_STRING, (QofAccessFunc)gncEmployeeGetID, NULL },
-    { EMPLOYEE_USERNAME, QOF_TYPE_STRING, (QofAccessFunc)gncEmployeeGetUsername, NULL },
+    { EMPLOYEE_ID, QOF_TYPE_STRING, (QofAccessFunc)gncEmployeeGetID, (QofSetterFunc)gncEmployeeSetID },
+    { EMPLOYEE_USERNAME, QOF_TYPE_STRING, (QofAccessFunc)gncEmployeeGetUsername, 
+		(QofSetterFunc)gncEmployeeSetUsername },
+	{ EMPLOYEE_LANGUAGE, QOF_TYPE_STRING, (QofAccessFunc)gncEmployeeGetLanguage, 
+		(QofSetterFunc)gncEmployeeSetLanguage },
+	{ EMPLOYEE_ACL, QOF_TYPE_STRING, (QofAccessFunc)gncEmployeeGetAcl, (QofSetterFunc)gncEmployeeSetAcl },
+	{ EMPLOYEE_WORKDAY, QOF_TYPE_NUMERIC, (QofAccessFunc)gncEmployeeGetWorkday,
+		(QofSetterFunc)gncEmployeeSetWorkday },
+	{ EMPLOYEE_RATE, QOF_TYPE_NUMERIC, (QofAccessFunc)gncEmployeeGetRate, (QofSetterFunc)gncEmployeeSetRate },
     { EMPLOYEE_ADDR, GNC_ADDRESS_MODULE_NAME, (QofAccessFunc)gncEmployeeGetAddr, NULL },
-    { QOF_PARAM_ACTIVE, QOF_TYPE_BOOLEAN, (QofAccessFunc)gncEmployeeGetActive, NULL },
+    { QOF_PARAM_ACTIVE, QOF_TYPE_BOOLEAN, (QofAccessFunc)gncEmployeeGetActive, (QofSetterFunc)gncEmployeeSetActive },
     { QOF_PARAM_BOOK, QOF_ID_BOOK, (QofAccessFunc)qof_instance_get_book, NULL },
     { QOF_PARAM_GUID, QOF_TYPE_GUID, (QofAccessFunc)qof_instance_get_guid, NULL },
     { NULL },
Index: gncBillTerm.h
===================================================================
RCS file: /home/cvs/cvsroot/gnucash/src/business/business-core/gncBillTerm.h,v
retrieving revision 1.3.4.3
retrieving revision 1.3.4.4
diff -Lsrc/business/business-core/gncBillTerm.h -Lsrc/business/business-core/gncBillTerm.h -u -r1.3.4.3 -r1.3.4.4
--- src/business/business-core/gncBillTerm.h
+++ src/business/business-core/gncBillTerm.h
@@ -44,6 +44,18 @@
 #define GNC_IS_BILLTERM(obj)  (QOF_CHECK_TYPE((obj), GNC_ID_BILLTERM))
 #define GNC_BILLTERM(obj)     (QOF_CHECK_CAST((obj), GNC_ID_BILLTERM, GncBillTerm))
 
+/** @name BillTerm parameter names */
+/** @{ */
+#define GNC_BILLTERM_NAME 		"name"
+#define GNC_BILLTERM_DESC 		"description"
+#define GNC_BILLTERM_DUEDAYS 	"number of days due"
+#define GNC_BILLTERM_DISCDAYS 	"number of discounted days"
+#define GNC_BILLTERM_CUTOFF 	"cut off"
+#define GNC_BILLTERM_TYPE 		"bill type"
+#define GNC_BILLTERM_DISCOUNT	"amount of discount"
+#define GNC_BILLTERM_REFCOUNT	"reference count"
+/** @} */
+
 /**
  * How to interpret the amount.
  * You can interpret it as a VALUE or a PERCENT.
Index: gncCustomer.h
===================================================================
RCS file: /home/cvs/cvsroot/gnucash/src/business/business-core/gncCustomer.h,v
retrieving revision 1.13.4.4
retrieving revision 1.13.4.5
diff -Lsrc/business/business-core/gncCustomer.h -Lsrc/business/business-core/gncCustomer.h -u -r1.13.4.4 -r1.13.4.5
--- src/business/business-core/gncCustomer.h
+++ src/business/business-core/gncCustomer.h
@@ -74,6 +74,11 @@
 
 void gncCustomerAddJob (GncCustomer *customer, GncJob *job);
 void gncCustomerRemoveJob (GncCustomer *customer, GncJob *job);
+
+/** added for QOF standardisation */
+void gncCustomerSetTaxIncluded_q (GncCustomer *customer, gint taxincl);
+gint gncCustomerGetTaxIncluded_q (GncCustomer *cust);
+
 /** @} */
 
 /** @name Get Functions */
@@ -111,11 +116,14 @@
 gboolean gncCustomerIsDirty (GncCustomer *customer);
 int gncCustomerCompare (GncCustomer *a, GncCustomer *b);
 
-#define CUSTOMER_ID	"id"
-#define CUSTOMER_NAME	"name"
-#define CUSTOMER_ADDR	"addr"
+#define CUSTOMER_ID			"id"
+#define CUSTOMER_NAME		"name"
+#define CUSTOMER_ADDR		"addr"
 #define CUSTOMER_SHIPADDR	"shipaddr"
-
+#define CUSTOMER_NOTES 		"notes"
+#define CUSTOMER_DISCOUNT 	"amount of discount"
+#define CUSTOMER_CREDIT 	"amount of credit"
+#define CUSTOMER_TT_OVER 	"tax table override"
 /** @deprecated functions, should be removed */
 #define gncCustomerGetGUID(x) qof_instance_get_guid(QOF_INSTANCE(x))
 #define gncCustomerRetGUID(x) (x ? *(qof_instance_get_guid(QOF_INSTANCE(x))) : *(guid_null()))
Index: gncInvoice.c
===================================================================
RCS file: /home/cvs/cvsroot/gnucash/src/business/business-core/gncInvoice.c,v
retrieving revision 1.56.4.5
retrieving revision 1.56.4.6
diff -Lsrc/business/business-core/gncInvoice.c -Lsrc/business/business-core/gncInvoice.c -u -r1.56.4.5 -r1.56.4.6
--- src/business/business-core/gncInvoice.c
+++ src/business/business-core/gncInvoice.c
@@ -1363,7 +1363,7 @@
   interface_version:  QOF_OBJECT_VERSION,
   e_type:             _GNC_MOD_NAME,
   type_label:         "Invoice",
-  create:             NULL,
+  create:             (gpointer)gncInvoiceCreate,
   book_begin:         NULL,
   book_end:           NULL,
   is_dirty:           qof_collection_is_dirty,
@@ -1400,22 +1400,22 @@
 gboolean gncInvoiceRegister (void)
 {
   static QofParam params[] = {
-    { INVOICE_ID, QOF_TYPE_STRING, (QofAccessFunc)gncInvoiceGetID, NULL },
-    { INVOICE_OWNER, GNC_ID_OWNER, (QofAccessFunc)gncInvoiceGetOwner, NULL },
-    { INVOICE_OPENED, QOF_TYPE_DATE, (QofAccessFunc)gncInvoiceGetDateOpened, NULL },
+    { INVOICE_ID, QOF_TYPE_STRING, (QofAccessFunc)gncInvoiceGetID, (QofSetterFunc)gncInvoiceSetID },
+    { INVOICE_OWNER, GNC_ID_OWNER, (QofAccessFunc)gncInvoiceGetOwner, (QofSetterFunc)gncInvoiceSetOwner },
+    { INVOICE_OPENED, QOF_TYPE_DATE, (QofAccessFunc)gncInvoiceGetDateOpened, (QofSetterFunc)gncInvoiceSetDateOpened },
     { INVOICE_DUE, QOF_TYPE_DATE, (QofAccessFunc)gncInvoiceGetDateDue, NULL },
-    { INVOICE_POSTED, QOF_TYPE_DATE, (QofAccessFunc)gncInvoiceGetDatePosted, NULL },
+    { INVOICE_POSTED, QOF_TYPE_DATE, (QofAccessFunc)gncInvoiceGetDatePosted, (QofSetterFunc)gncInvoiceSetDatePosted },
     { INVOICE_IS_POSTED, QOF_TYPE_BOOLEAN, (QofAccessFunc)gncInvoiceIsPosted, NULL },
     { INVOICE_IS_PAID, QOF_TYPE_BOOLEAN, (QofAccessFunc)gncInvoiceIsPaid, NULL },
-    { INVOICE_BILLINGID, QOF_TYPE_STRING, (QofAccessFunc)gncInvoiceGetBillingID, NULL },
-    { INVOICE_NOTES, QOF_TYPE_STRING, (QofAccessFunc)gncInvoiceGetNotes, NULL },
+    { INVOICE_BILLINGID, QOF_TYPE_STRING, (QofAccessFunc)gncInvoiceGetBillingID, (QofSetterFunc)gncInvoiceSetBillingID },
+    { INVOICE_NOTES, QOF_TYPE_STRING, (QofAccessFunc)gncInvoiceGetNotes, (QofSetterFunc)gncInvoiceSetNotes },
     { INVOICE_ACC, GNC_ID_ACCOUNT, (QofAccessFunc)gncInvoiceGetPostedAcc, NULL },
     { INVOICE_POST_TXN, GNC_ID_TRANS, (QofAccessFunc)gncInvoiceGetPostedTxn, NULL },
     { INVOICE_POST_LOT, GNC_ID_LOT, (QofAccessFunc)gncInvoiceGetPostedLot, NULL },
     { INVOICE_TYPE, QOF_TYPE_STRING, (QofAccessFunc)gncInvoiceGetType, NULL },
-    { INVOICE_TERMS, GNC_ID_BILLTERM, (QofAccessFunc)gncInvoiceGetTerms, NULL },
-    { INVOICE_BILLTO, GNC_ID_OWNER, (QofAccessFunc)gncInvoiceGetBillTo, NULL },
-    { QOF_PARAM_ACTIVE, QOF_TYPE_BOOLEAN, (QofAccessFunc)gncInvoiceGetActive, NULL },
+    { INVOICE_TERMS, GNC_ID_BILLTERM, (QofAccessFunc)gncInvoiceGetTerms, (QofSetterFunc)gncInvoiceSetTerms },
+    { INVOICE_BILLTO, GNC_ID_OWNER, (QofAccessFunc)gncInvoiceGetBillTo, (QofSetterFunc)gncInvoiceSetBillTo },
+    { QOF_PARAM_ACTIVE, QOF_TYPE_BOOLEAN, (QofAccessFunc)gncInvoiceGetActive, (QofSetterFunc)gncInvoiceSetActive },
     { QOF_PARAM_BOOK, QOF_ID_BOOK, (QofAccessFunc)qof_instance_get_book, NULL },
     { QOF_PARAM_GUID, QOF_TYPE_GUID, (QofAccessFunc)qof_instance_get_guid, NULL },
     { NULL },
Index: gncCustomer.c
===================================================================
RCS file: /home/cvs/cvsroot/gnucash/src/business/business-core/gncCustomer.c,v
retrieving revision 1.20.4.3
retrieving revision 1.20.4.4
diff -Lsrc/business/business-core/gncCustomer.c -Lsrc/business/business-core/gncCustomer.c -u -r1.20.4.3 -r1.20.4.4
--- src/business/business-core/gncCustomer.c
+++ src/business/business-core/gncCustomer.c
@@ -73,7 +73,7 @@
   gboolean        active;
   GList *         jobs;
 
-  /* The following fields aer unique to 'customer' */
+  /* The following fields are unique to 'customer' */
   gnc_numeric     credit;
   gnc_numeric     discount;
   GncAddress *    shipaddr;
@@ -270,6 +270,13 @@
   gncCustomerCommitEdit (cust);
 }
 
+void gncCustomerSetTaxIncluded_q (GncCustomer *cust, gint taxincl)
+{
+	GncTaxIncluded g = taxincl;
+	if(!g) return;
+	gncCustomerSetTaxIncluded(cust, g);
+}
+
 void gncCustomerSetTaxIncluded (GncCustomer *cust, GncTaxIncluded taxincl)
 {
   if (!cust) return;
@@ -444,6 +451,11 @@
   return cust->terms;
 }
 
+gint gncCustomerGetTaxIncluded_q (GncCustomer *cust)
+{
+	return (GncTaxIncluded)gncCustomerGetTaxIncluded(cust);
+}
+
 GncTaxIncluded gncCustomerGetTaxIncluded (GncCustomer *cust)
 {
   if (!cust) return GNC_TAXINCLUDED_USEGLOBAL;
@@ -536,7 +548,7 @@
   interface_version:  QOF_OBJECT_VERSION,
   e_type:             _GNC_MOD_NAME,
   type_label:         "Customer",
-  create:             NULL,
+  create:             (gpointer)gncCustomerCreate,
   book_begin:         NULL,
   book_end:           NULL,
   is_dirty:           qof_collection_is_dirty,
@@ -549,11 +561,18 @@
 gboolean gncCustomerRegister (void)
 {
   static QofParam params[] = {
-    { CUSTOMER_ID, QOF_TYPE_STRING, (QofAccessFunc)gncCustomerGetID, NULL },
-    { CUSTOMER_NAME, QOF_TYPE_STRING, (QofAccessFunc)gncCustomerGetName, NULL },
+    { CUSTOMER_ID, QOF_TYPE_STRING, (QofAccessFunc)gncCustomerGetID, (QofSetterFunc)gncCustomerSetID },
+    { CUSTOMER_NAME, QOF_TYPE_STRING, (QofAccessFunc)gncCustomerGetName, (QofSetterFunc)gncCustomerSetName },
+	{ CUSTOMER_NOTES, QOF_TYPE_STRING, (QofAccessFunc)gncCustomerGetNotes, (QofSetterFunc)gncCustomerSetNotes },
+	{ CUSTOMER_DISCOUNT, QOF_TYPE_NUMERIC, (QofAccessFunc)gncCustomerGetDiscount,
+		(QofSetterFunc)gncCustomerSetDiscount },
+	{ CUSTOMER_CREDIT, QOF_TYPE_NUMERIC, (QofAccessFunc)gncCustomerGetCredit,
+		(QofSetterFunc)gncCustomerSetCredit },
     { CUSTOMER_ADDR, GNC_ADDRESS_MODULE_NAME, (QofAccessFunc)gncCustomerGetAddr, NULL },
     { CUSTOMER_SHIPADDR, GNC_ADDRESS_MODULE_NAME, (QofAccessFunc)gncCustomerGetShipAddr, NULL },
-    { QOF_PARAM_ACTIVE, QOF_TYPE_BOOLEAN, (QofAccessFunc)gncCustomerGetActive, NULL },
+	{ CUSTOMER_TT_OVER, QOF_TYPE_BOOLEAN, (QofAccessFunc)gncCustomerGetTaxTableOverride, 
+		(QofSetterFunc)gncCustomerSetTaxTableOverride },
+    { QOF_PARAM_ACTIVE, QOF_TYPE_BOOLEAN, (QofAccessFunc)gncCustomerGetActive, (QofSetterFunc)gncCustomerSetActive },
     { QOF_PARAM_BOOK, QOF_ID_BOOK, (QofAccessFunc)qof_instance_get_book, NULL },
     { QOF_PARAM_GUID, QOF_TYPE_GUID, (QofAccessFunc)qof_instance_get_guid, NULL },
     { NULL },
Index: gncEmployee.h
===================================================================
RCS file: /home/cvs/cvsroot/gnucash/src/business/business-core/gncEmployee.h,v
retrieving revision 1.8.4.4
retrieving revision 1.8.4.5
diff -Lsrc/business/business-core/gncEmployee.h -Lsrc/business/business-core/gncEmployee.h -u -r1.8.4.4 -r1.8.4.5
--- src/business/business-core/gncEmployee.h
+++ src/business/business-core/gncEmployee.h
@@ -92,11 +92,13 @@
 
 gboolean gncEmployeeIsDirty (GncEmployee *employee);
 
-
-
-#define EMPLOYEE_ID	"id"
+#define EMPLOYEE_ID			"id"
 #define EMPLOYEE_USERNAME	"username"
-#define EMPLOYEE_ADDR	"addr"
+#define EMPLOYEE_ADDR		"addr"
+#define EMPLOYEE_LANGUAGE 	"native language"
+#define EMPLOYEE_ACL		"acl"
+#define EMPLOYEE_WORKDAY	"workday"
+#define EMPLOYEE_RATE		"rate"
 
 /** deprecated routines */
 #define gncEmployeeGetGUID(E) qof_entity_get_guid(QOF_ENTITY(E))
Index: gncVendor.c
===================================================================
RCS file: /home/cvs/cvsroot/gnucash/src/business/business-core/gncVendor.c,v
retrieving revision 1.21.4.3
retrieving revision 1.21.4.4
diff -Lsrc/business/business-core/gncVendor.c -Lsrc/business/business-core/gncVendor.c -u -r1.21.4.3 -r1.21.4.4
--- src/business/business-core/gncVendor.c
+++ src/business/business-core/gncVendor.c
@@ -486,7 +486,7 @@
   interface_version:  QOF_OBJECT_VERSION,
   e_type:             _GNC_MOD_NAME,
   type_label:         "Vendor",
-  create:             NULL,
+  create:             (gpointer)gncVendorCreate,
   book_begin:         NULL,
   book_end:           NULL,
   is_dirty:           qof_collection_is_dirty,
@@ -499,8 +499,8 @@
 gboolean gncVendorRegister (void)
 {
   static QofParam params[] = {
-    { VENDOR_ID, QOF_TYPE_STRING, (QofAccessFunc)gncVendorGetID, NULL },
-    { VENDOR_NAME, QOF_TYPE_STRING, (QofAccessFunc)gncVendorGetName, NULL },
+    { VENDOR_ID, QOF_TYPE_STRING, (QofAccessFunc)gncVendorGetID, (QofSetterFunc)gncVendorSetID },
+    { VENDOR_NAME, QOF_TYPE_STRING, (QofAccessFunc)gncVendorGetName, (QofSetterFunc)gncVendorSetName },
     { VENDOR_ADDR, GNC_ADDRESS_MODULE_NAME, (QofAccessFunc)gncVendorGetAddr, NULL },
     { QOF_PARAM_BOOK, QOF_ID_BOOK, (QofAccessFunc)qof_instance_get_book, NULL },
     { QOF_PARAM_GUID, QOF_TYPE_GUID, (QofAccessFunc)qof_instance_get_guid, NULL },
Index: gncJob.c
===================================================================
RCS file: /home/cvs/cvsroot/gnucash/src/business/business-core/gncJob.c,v
retrieving revision 1.18.4.4
retrieving revision 1.18.4.5
diff -Lsrc/business/business-core/gncJob.c -Lsrc/business/business-core/gncJob.c -u -r1.18.4.4 -r1.18.4.5
--- src/business/business-core/gncJob.c
+++ src/business/business-core/gncJob.c
@@ -353,7 +353,7 @@
   interface_version:  QOF_OBJECT_VERSION,
   e_type:             _GNC_MOD_NAME,
   type_label:         "Job",
-  create:             NULL,
+  create:             (gpointer)gncJobCreate,
   book_begin:         NULL,
   book_end:           NULL,
   is_dirty:           qof_collection_is_dirty,
@@ -366,11 +366,11 @@
 gboolean gncJobRegister (void)
 {
   static QofParam params[] = {
-    { JOB_ID, QOF_TYPE_STRING, (QofAccessFunc)gncJobGetID, NULL },
-    { JOB_NAME, QOF_TYPE_STRING, (QofAccessFunc)gncJobGetName, NULL },
-    { JOB_ACTIVE, QOF_TYPE_BOOLEAN, (QofAccessFunc)gncJobGetActive, NULL },
-    { JOB_REFERENCE, QOF_TYPE_STRING, (QofAccessFunc)gncJobGetReference, NULL },
-    { JOB_OWNER, GNC_ID_OWNER, (QofAccessFunc)gncJobGetOwner, NULL },
+    { JOB_ID, QOF_TYPE_STRING, (QofAccessFunc)gncJobGetID, (QofSetterFunc)gncJobSetID },
+    { JOB_NAME, QOF_TYPE_STRING, (QofAccessFunc)gncJobGetName, (QofSetterFunc)gncJobSetName },
+    { JOB_ACTIVE, QOF_TYPE_BOOLEAN, (QofAccessFunc)gncJobGetActive, (QofSetterFunc)gncJobSetActive },
+    { JOB_REFERENCE, QOF_TYPE_STRING, (QofAccessFunc)gncJobGetReference, (QofSetterFunc)gncJobSetReference },
+    { JOB_OWNER, GNC_ID_OWNER, (QofAccessFunc)gncJobGetOwner, (QofSetterFunc)gncJobSetOwner },
     { QOF_PARAM_ACTIVE, QOF_TYPE_BOOLEAN, (QofAccessFunc)gncJobGetActive, NULL },
     { QOF_PARAM_BOOK, QOF_ID_BOOK, (QofAccessFunc)qof_instance_get_book, NULL },
     { QOF_PARAM_GUID, QOF_TYPE_GUID, (QofAccessFunc)qof_instance_get_guid, NULL },
Index: gncBillTerm.c
===================================================================
RCS file: /home/cvs/cvsroot/gnucash/src/business/business-core/gncBillTerm.c,v
retrieving revision 1.6.4.3
retrieving revision 1.6.4.4
diff -Lsrc/business/business-core/gncBillTerm.c -Lsrc/business/business-core/gncBillTerm.c -u -r1.6.4.3 -r1.6.4.4
--- src/business/business-core/gncBillTerm.c
+++ src/business/business-core/gncBillTerm.c
@@ -691,6 +691,22 @@
 gboolean gncBillTermRegister (void)
 {
   static QofParam params[] = {
+    { GNC_BILLTERM_NAME, QOF_TYPE_STRING, (QofAccessFunc)gncBillTermGetName,
+      (QofSetterFunc)gncBillTermSetName },
+    { GNC_BILLTERM_DESC, QOF_TYPE_STRING, (QofAccessFunc)gncBillTermGetDescription,
+      (QofSetterFunc)gncBillTermSetDescription },
+    { GNC_BILLTERM_TYPE, QOF_TYPE_INT32, (QofAccessFunc)gncBillTermGetType, 
+      (QofSetterFunc)gncBillTermSetType },
+    { GNC_BILLTERM_DUEDAYS, QOF_TYPE_INT32, (QofAccessFunc)gncBillTermGetDueDays, 
+      (QofSetterFunc)gncBillTermSetDueDays },
+    { GNC_BILLTERM_DISCDAYS, QOF_TYPE_INT32, (QofAccessFunc)gncBillTermGetDiscountDays,
+      (QofSetterFunc)gncBillTermSetDiscountDays },
+    { GNC_BILLTERM_DISCOUNT, QOF_TYPE_NUMERIC, (QofAccessFunc)gncBillTermGetDiscount,
+      (QofSetterFunc)gncBillTermSetDiscount },
+    { GNC_BILLTERM_CUTOFF, QOF_TYPE_INT32, (QofAccessFunc)gncBillTermGetCutoff, 
+      (QofSetterFunc)gncBillTermSetCutoff },
+    { GNC_BILLTERM_REFCOUNT, QOF_TYPE_INT64, (QofAccessFunc)gncBillTermGetRefcount, NULL },
+    { QOF_PARAM_BOOK, QOF_ID_BOOK, (QofAccessFunc)qof_instance_get_book, NULL },
     { QOF_PARAM_BOOK, QOF_ID_BOOK, (QofAccessFunc)qof_instance_get_book, NULL },
     { QOF_PARAM_GUID, QOF_TYPE_GUID, (QofAccessFunc)qof_instance_get_guid, NULL },
     { NULL },
Index: gncEntry.c
===================================================================
RCS file: /home/cvs/cvsroot/gnucash/src/business/business-core/gncEntry.c,v
retrieving revision 1.32.4.3
retrieving revision 1.32.4.4
diff -Lsrc/business/business-core/gncEntry.c -Lsrc/business/business-core/gncEntry.c -u -r1.32.4.3 -r1.32.4.4
--- src/business/business-core/gncEntry.c
+++ src/business/business-core/gncEntry.c
@@ -1169,7 +1169,7 @@
   interface_version:  QOF_OBJECT_VERSION,
   e_type:             _GNC_MOD_NAME,
   type_label:         "Order/Invoice/Bill Entry",
-  create:             NULL,
+  create:             (gpointer)gncEntryCreate,
   book_begin:         NULL,
   book_end:           NULL,
   is_dirty:           qof_collection_is_dirty,
@@ -1182,18 +1182,18 @@
 gboolean gncEntryRegister (void)
 {
   static QofParam params[] = {
-    { ENTRY_DATE, QOF_TYPE_DATE, (QofAccessFunc)gncEntryGetDate, NULL },
-    { ENTRY_DATE_ENTERED, QOF_TYPE_DATE, (QofAccessFunc)gncEntryGetDateEntered, NULL },
-    { ENTRY_DESC, QOF_TYPE_STRING, (QofAccessFunc)gncEntryGetDescription, NULL },
-    { ENTRY_ACTION, QOF_TYPE_STRING, (QofAccessFunc)gncEntryGetAction, NULL },
-    { ENTRY_NOTES, QOF_TYPE_STRING, (QofAccessFunc)gncEntryGetNotes, NULL },
-    { ENTRY_QTY, QOF_TYPE_NUMERIC, (QofAccessFunc)gncEntryGetQuantity, NULL },
-    { ENTRY_IPRICE, QOF_TYPE_NUMERIC, (QofAccessFunc)gncEntryGetInvPrice, NULL },
-    { ENTRY_BPRICE, QOF_TYPE_NUMERIC, (QofAccessFunc)gncEntryGetBillPrice, NULL },
+    { ENTRY_DATE, QOF_TYPE_DATE, (QofAccessFunc)gncEntryGetDate, (QofSetterFunc)gncEntrySetDate },
+    { ENTRY_DATE_ENTERED, QOF_TYPE_DATE, (QofAccessFunc)gncEntryGetDateEntered, (QofSetterFunc)gncEntrySetDateEntered },
+    { ENTRY_DESC, QOF_TYPE_STRING, (QofAccessFunc)gncEntryGetDescription, (QofSetterFunc)gncEntrySetDescription },
+    { ENTRY_ACTION, QOF_TYPE_STRING, (QofAccessFunc)gncEntryGetAction, (QofSetterFunc)gncEntrySetAction },
+    { ENTRY_NOTES, QOF_TYPE_STRING, (QofAccessFunc)gncEntryGetNotes, (QofSetterFunc)gncEntrySetNotes },
+    { ENTRY_QTY, QOF_TYPE_NUMERIC, (QofAccessFunc)gncEntryGetQuantity, (QofSetterFunc)gncEntrySetQuantity },
+    { ENTRY_IPRICE, QOF_TYPE_NUMERIC, (QofAccessFunc)gncEntryGetInvPrice, (QofSetterFunc)gncEntrySetInvPrice },
+    { ENTRY_BPRICE, QOF_TYPE_NUMERIC, (QofAccessFunc)gncEntryGetBillPrice, (QofSetterFunc)gncEntrySetBillPrice },
     { ENTRY_INVOICE, GNC_ID_INVOICE, (QofAccessFunc)gncEntryGetInvoice, NULL },
     { ENTRY_BILL, GNC_ID_INVOICE, (QofAccessFunc)gncEntryGetBill, NULL },
-    { ENTRY_BILLABLE, QOF_TYPE_BOOLEAN, (QofAccessFunc)gncEntryGetBillable, NULL },
-    { ENTRY_BILLTO, GNC_ID_OWNER, (QofAccessFunc)gncEntryGetBillTo, NULL },
+    { ENTRY_BILLABLE, QOF_TYPE_BOOLEAN, (QofAccessFunc)gncEntryGetBillable, (QofSetterFunc)gncEntrySetBillable },
+    { ENTRY_BILLTO, GNC_ID_OWNER, (QofAccessFunc)gncEntryGetBillTo, (QofSetterFunc)gncEntrySetBillTo },
     { ENTRY_ORDER, GNC_ID_ORDER, (QofAccessFunc)gncEntryGetOrder, NULL },
     { QOF_PARAM_BOOK, QOF_ID_BOOK, (QofAccessFunc)qof_instance_get_book, NULL },
     { QOF_PARAM_GUID, QOF_TYPE_GUID, (QofAccessFunc)qof_instance_get_guid, NULL },
Index: gncAddress.c
===================================================================
RCS file: /home/cvs/cvsroot/gnucash/src/business/business-core/gncAddress.c,v
retrieving revision 1.4.4.2
retrieving revision 1.4.4.3
diff -Lsrc/business/business-core/gncAddress.c -Lsrc/business/business-core/gncAddress.c -u -r1.4.4.2 -r1.4.4.3
--- src/business/business-core/gncAddress.c
+++ src/business/business-core/gncAddress.c
@@ -285,10 +285,10 @@
 {
   static QofParam params[] = {
 
-    { ADDRESS_NAME, QOF_TYPE_STRING, (QofAccessFunc)gncAddressGetName, NULL },
-    { ADDRESS_PHONE, QOF_TYPE_STRING, (QofAccessFunc)gncAddressGetPhone, NULL },
-    { ADDRESS_FAX, QOF_TYPE_STRING, (QofAccessFunc)gncAddressGetFax, NULL },
-    { ADDRESS_EMAIL, QOF_TYPE_STRING, (QofAccessFunc)gncAddressGetEmail, NULL },
+    { ADDRESS_NAME, QOF_TYPE_STRING, (QofAccessFunc)gncAddressGetName, (QofSetterFunc)gncAddressSetName },
+    { ADDRESS_PHONE, QOF_TYPE_STRING, (QofAccessFunc)gncAddressGetPhone, (QofSetterFunc)gncAddressSetPhone },
+    { ADDRESS_FAX, QOF_TYPE_STRING, (QofAccessFunc)gncAddressGetFax, (QofSetterFunc)gncAddressSetFax },
+    { ADDRESS_EMAIL, QOF_TYPE_STRING, (QofAccessFunc)gncAddressGetEmail, (QofSetterFunc)gncAddressSetEmail },
     { NULL },
   };
 
Index: gncTaxTable.c
===================================================================
RCS file: /home/cvs/cvsroot/gnucash/src/business/business-core/gncTaxTable.c,v
retrieving revision 1.9.4.3
retrieving revision 1.9.4.4
diff -Lsrc/business/business-core/gncTaxTable.c -Lsrc/business/business-core/gncTaxTable.c -u -r1.9.4.3 -r1.9.4.4
--- src/business/business-core/gncTaxTable.c
+++ src/business/business-core/gncTaxTable.c
@@ -464,6 +464,12 @@
     mod_table (entry->table);
   }
 }
+void gncTaxTableEntrySetType_q (GncTaxTableEntry *entry, gint type)
+{
+	GncAmountType q = type;
+	if(!q) return;
+	gncTaxTableEntrySetType(entry,q);
+}
 
 void gncTaxTableEntrySetType (GncTaxTableEntry *entry, GncAmountType type)
 {
@@ -663,6 +669,11 @@
   return entry->account;
 }
 
+gint gncTaxTableEntryGetType_q (GncTaxTableEntry *entry)
+{
+	return (GncAmountType)gncTaxTableEntryGetType(entry);
+}
+
 GncAmountType gncTaxTableEntryGetType (GncTaxTableEntry *entry)
 {
   if (!entry) return 0;
@@ -799,7 +810,7 @@
   interface_version:  QOF_OBJECT_VERSION,
   e_type:             _GNC_MOD_NAME,
   type_label:         "Tax Table",
-  create:             NULL,
+  create:             (gpointer)gncTaxTableCreate,
   book_begin:         _gncTaxTableCreate,
   book_end:           _gncTaxTableDestroy,
   is_dirty:           qof_collection_is_dirty,
@@ -812,6 +823,8 @@
 gboolean gncTaxTableRegister (void)
 {
   static QofParam params[] = {
+	{ GNC_TT_NAME, QOF_TYPE_STRING, (QofAccessFunc)gncTaxTableGetName, (QofSetterFunc)gncTaxTableSetName },
+	{ GNC_TT_REFCOUNT, QOF_TYPE_INT64, (QofAccessFunc)gncTaxTableGetRefcount, NULL },
     { QOF_PARAM_BOOK, QOF_ID_BOOK, (QofAccessFunc)qof_instance_get_book, NULL },
     { QOF_PARAM_GUID, QOF_TYPE_GUID, (QofAccessFunc)qof_instance_get_guid, NULL },
     { NULL },
@@ -821,3 +834,7 @@
 
   return qof_object_register (&gncTaxTableDesc);
 }
+
+/* need a QOF tax table entry object */
+//gncTaxTableEntrySetType_q int32
+//gint gncTaxTableEntryGetType_q (GncTaxTableEntry *entry);
Index: gncOrder.c
===================================================================
RCS file: /home/cvs/cvsroot/gnucash/src/business/business-core/gncOrder.c,v
retrieving revision 1.23.4.3
retrieving revision 1.23.4.4
diff -Lsrc/business/business-core/gncOrder.c -Lsrc/business/business-core/gncOrder.c -u -r1.23.4.3 -r1.23.4.4
--- src/business/business-core/gncOrder.c
+++ src/business/business-core/gncOrder.c
@@ -438,14 +438,14 @@
 gboolean gncOrderRegister (void)
 {
   static QofParam params[] = {
-    { ORDER_ID, QOF_TYPE_STRING, (QofAccessFunc)gncOrderGetID, NULL },
-    { ORDER_REFERENCE, QOF_TYPE_STRING, (QofAccessFunc)gncOrderGetReference, NULL },
-    { ORDER_OWNER, GNC_ID_OWNER, (QofAccessFunc)gncOrderGetOwner, NULL },
-    { ORDER_OPENED, QOF_TYPE_DATE, (QofAccessFunc)gncOrderGetDateOpened, NULL },
+    { ORDER_ID, QOF_TYPE_STRING, (QofAccessFunc)gncOrderGetID, (QofSetterFunc)gncOrderSetID },
+    { ORDER_REFERENCE, QOF_TYPE_STRING, (QofAccessFunc)gncOrderGetReference, (QofSetterFunc)gncOrderSetReference },
+    { ORDER_OWNER, GNC_ID_OWNER, (QofAccessFunc)gncOrderGetOwner, (QofSetterFunc)gncOrderSetOwner },
+    { ORDER_OPENED, QOF_TYPE_DATE, (QofAccessFunc)gncOrderGetDateOpened, (QofSetterFunc)gncOrderSetDateOpened },
     { ORDER_IS_CLOSED, QOF_TYPE_BOOLEAN, (QofAccessFunc)gncOrderIsClosed, NULL },
-    { ORDER_CLOSED, QOF_TYPE_DATE, (QofAccessFunc)gncOrderGetDateClosed, NULL },
-    { ORDER_NOTES, QOF_TYPE_STRING, (QofAccessFunc)gncOrderGetNotes, NULL },
-    { QOF_PARAM_ACTIVE, QOF_TYPE_BOOLEAN, (QofAccessFunc)gncOrderGetActive, NULL },
+    { ORDER_CLOSED, QOF_TYPE_DATE, (QofAccessFunc)gncOrderGetDateClosed, (QofSetterFunc)gncOrderSetDateClosed },
+    { ORDER_NOTES, QOF_TYPE_STRING, (QofAccessFunc)gncOrderGetNotes, (QofSetterFunc)gncOrderSetNotes },
+    { QOF_PARAM_ACTIVE, QOF_TYPE_BOOLEAN, (QofAccessFunc)gncOrderGetActive, (QofSetterFunc)gncOrderSetActive },
     { QOF_PARAM_BOOK, QOF_ID_BOOK, (QofAccessFunc)qof_instance_get_book, NULL },
     { QOF_PARAM_GUID, QOF_TYPE_GUID, (QofAccessFunc)qof_instance_get_guid, NULL },
     { NULL },
Index: gncTaxTable.h
===================================================================
RCS file: /home/cvs/cvsroot/gnucash/src/business/business-core/gncTaxTable.h,v
retrieving revision 1.7.4.4
retrieving revision 1.7.4.5
diff -Lsrc/business/business-core/gncTaxTable.h -Lsrc/business/business-core/gncTaxTable.h -u -r1.7.4.4 -r1.7.4.5
--- src/business/business-core/gncTaxTable.h
+++ src/business/business-core/gncTaxTable.h
@@ -52,15 +52,15 @@
  * You can interpret it as a VALUE or a PERCENT.
  */
 typedef enum {
-  GNC_AMT_TYPE_VALUE = 1,
-  GNC_AMT_TYPE_PERCENT
+  GNC_AMT_TYPE_VALUE = 1, 	/**< tax is a number */
+  GNC_AMT_TYPE_PERCENT		/**< tax is a percentage */
 } GncAmountType;
 
 /** How to interpret the TaxIncluded */
 typedef enum {
-  GNC_TAXINCLUDED_YES = 1,
-  GNC_TAXINCLUDED_NO,
-  GNC_TAXINCLUDED_USEGLOBAL,
+  GNC_TAXINCLUDED_YES = 1,  /**< tax is included */
+  GNC_TAXINCLUDED_NO,		/**< tax is not included */
+  GNC_TAXINCLUDED_USEGLOBAL, /**< use the global setting */
 } GncTaxIncluded;
 
 const char * gncAmountTypeToString (GncAmountType type);
@@ -91,6 +91,11 @@
 void gncTaxTableChanged (GncTaxTable *table);
 void gncTaxTableBeginEdit (GncTaxTable *table);
 void gncTaxTableCommitEdit (GncTaxTable *table);
+
+/** added for later QOF standardisation */
+gint gncTaxTableEntryGetType_q (GncTaxTableEntry *entry);
+void gncTaxTableEntrySetType_q (GncTaxTableEntry *entry, gint type);
+
 /** @} */
 
 /** @name Get Functions */
@@ -147,6 +152,10 @@
 /** Destroy a list of accountvalues */
 void gncAccountValueDestroy (GList *list);
 
+/** QOF parameter definitions */
+#define GNC_TT_NAME "tax table name"
+#define GNC_TT_REFCOUNT "reference count"
+
 /** @deprecated routine */
 #define gncTaxTableGetGUID(x) qof_instance_get_guid(QOF_INSTANCE(x))
 #define gncTaxTableRetGUID(x) (x ? *(qof_instance_get_guid(QOF_INSTANCE(x))) : *(guid_null()))
Index: test-numeric.c
===================================================================
RCS file: /home/cvs/cvsroot/gnucash/src/engine/test/test-numeric.c,v
retrieving revision 1.18.2.1
retrieving revision 1.18.2.2
diff -Lsrc/engine/test/test-numeric.c -Lsrc/engine/test/test-numeric.c -u -r1.18.2.1 -r1.18.2.2
--- src/engine/test/test-numeric.c
+++ src/engine/test/test-numeric.c
@@ -112,19 +112,22 @@
 static void
 check_reduce (void)
 {
+	gnc_numeric one, rone;
+	gnc_numeric four, rfour;
+	gnc_numeric val, rval;
 	/* Check common factor elimination (needed for equality checks) */
-	gnc_numeric one = gnc_numeric_create (1,1);
-	gnc_numeric rone = gnc_numeric_create (1000000,1000000);
+	one = gnc_numeric_create (1,1);
+	rone = gnc_numeric_create (1000000,1000000);
 	rone = gnc_numeric_reduce (rone);
 	do_test (gnc_numeric_eq(one, rone), "reduce to one");
 
-	gnc_numeric four = gnc_numeric_create (4,1);
-	gnc_numeric rfour = gnc_numeric_create (480,120);
+	four = gnc_numeric_create (4,1);
+	rfour = gnc_numeric_create (480,120);
 	rfour = gnc_numeric_reduce (rfour);
 	do_test (gnc_numeric_eq(four, rfour), "reduce to four");
 
-	gnc_numeric val = gnc_numeric_create(10023234LL, 334216654LL);
-	gnc_numeric rval = gnc_numeric_reduce (val);
+	val = gnc_numeric_create(10023234LL, 334216654LL);
+	rval = gnc_numeric_reduce (val);
 	check_unary_op (gnc_numeric_eq,
 	                gnc_numeric_create (5011617,167108327),
 	                rval,
@@ -150,14 +153,20 @@
 static void
 check_equality_operator (void)
 {
+	int i, m;
+	gint deno, mult, numer;
+	gint64 f;
+	gnc_numeric big, rbig;
+	gnc_numeric val, mval;
+	gnc_numeric bval, rval;
 	/* Check equality operator for some large numer/denom values */
-	gint64 numer = 1<<30;
+	numer = 1<<30;
 	numer <<= 30;   /* we don't trust cpp to compute 1<<60 correctly */
-	gint64 deno = 1<<30;
+	deno = 1<<30;
 	deno <<= 20;
-	gnc_numeric rbig = gnc_numeric_create (numer, deno);
+	rbig = gnc_numeric_create (numer, deno);
 	
-	gnc_numeric big = gnc_numeric_create (1<<10,1);
+	big = gnc_numeric_create (1<<10,1);
 	do_test (gnc_numeric_equal(big, rbig), "equal to billion");
 	
 	big = gnc_numeric_create (1<<20,1<<10);
@@ -183,20 +192,19 @@
 	big = gnc_numeric_create (numer, 1<<20);
 	do_test (gnc_numeric_equal(big, rbig), "equal to 1<<50/1<<20");
 
-	int i;
 	/* We assume RAND_MAX is less that 1<<32 */
 	for (i=0; i<NREPS; i++) 
 	{
-		gint64 deno = rand() / 2;
-		gint64 mult = rand() / 2;
-		gint64 numer = rand() / 2;
+		deno = rand() / 2;
+		mult = rand() / 2;
+		numer = rand() / 2;
 
-		gnc_numeric val = gnc_numeric_create (numer, deno);
-		gnc_numeric mval = gnc_numeric_create (numer*mult, deno*mult);
+		val = gnc_numeric_create (numer, deno);
+		mval = gnc_numeric_create (numer*mult, deno*mult);
 		
 		/* The reduced version should be equivalent */
-		gnc_numeric bval = gnc_numeric_reduce (val);
-		gnc_numeric rval = gnc_numeric_reduce (mval);
+		bval = gnc_numeric_reduce (val);
+		rval = gnc_numeric_reduce (mval);
 		check_unary_op (gnc_numeric_eq, 
                       bval, rval, mval, "expected %s = %s = reduce(%s)");
 		
@@ -209,8 +217,8 @@
 		 * might creep in. */
 		mval.denom >>= 1;
 		mval.num >>= 1;
-		int m=0;
-		gint64 f = mval.denom;
+		m=0;
+		f = mval.denom;
 		while (f%2 == 0)
 		{
 			f >>= 1;
@@ -297,6 +305,7 @@
 static void
 check_double (void)
 {
+	double flo;
 	gnc_numeric val = gnc_numeric_create (0,1);
 
 	check_unary_op (gnc_numeric_eq,
@@ -330,7 +339,7 @@
                                          GNC_HOW_RND_ROUND),
                    val, "expected %s = %s double 6 figs");
 
-	double flo = gnc_numeric_to_double(gnc_numeric_create(7, 16));
+	flo = gnc_numeric_to_double(gnc_numeric_create(7, 16));
 	do_test ((0.4375 == flo), "float pt conversion");
 }
 
@@ -359,8 +368,14 @@
 static void
 check_add_subtract (void)
 {
-  gnc_numeric a = gnc_numeric_create(2, 6);
-  gnc_numeric b = gnc_numeric_create(1, 4);
+  int i;
+  gnc_numeric a, b, c, d, z;
+#if CHECK_ERRORS_TOO
+  gnc_numeric c;
+#endif
+  
+  a = gnc_numeric_create(2, 6);
+  b = gnc_numeric_create(1, 4);
 
   /* Well, actually 14/24 would be acceptable/better in this case */
   check_binary_op (gnc_numeric_create(7,12), 
@@ -402,9 +417,9 @@
   
   /* ------------------------------------------------------------ */
   /* This test has failed before */
-  gnc_numeric c = gnc_numeric_neg (a);
-  gnc_numeric d = gnc_numeric_neg (b);
-  gnc_numeric z = gnc_numeric_zero();
+  c = gnc_numeric_neg (a);
+  d = gnc_numeric_neg (b);
+  z = gnc_numeric_zero();
   check_binary_op (c, gnc_numeric_add_fixed(z,c),
 						 z, c, "expected %s got %s = %s + %s for add fixed");
   
@@ -455,7 +470,6 @@
   
   /* ------------------------------------------------------------ */
 #if CHECK_ERRORS_TOO
-  gnc_numeric c;
   c = gnc_numeric_add_with_error(a, b, 100, GNC_HOW_RND_ROUND, &err);
   printf("add 100ths/error : %s + %s = %s + (error) %s\n\n",
          gnc_numeric_print(a), gnc_numeric_print(b),
@@ -472,7 +486,6 @@
 
   /* ------------------------------------------------------------ */
 	/* Add and subtract some random numbers */
-	int i;
 	for (i=0; i<NREPS; i++)
 	{
 		gnc_numeric e;
@@ -509,7 +522,11 @@
 static void
 check_mult_div (void)
 {
+  int i, j;
+  gint64 v;
   gnc_numeric c, d;
+  gnc_numeric amt_a, amt_tot, frac, val_tot, val_a;
+
   gnc_numeric a = gnc_numeric_create(2, 6);
   gnc_numeric b = gnc_numeric_create(1, 4);
 
@@ -556,7 +573,7 @@
   /* Check for math with 2^63 < num*num < 2^64 which previously failed 
    * see http://bugzilla.gnome.org/show_bug.cgi?id=144980 
    */
-  gint64 v = 1000000;
+  v = 1000000;
   a = gnc_numeric_create(1*v, v);
   b = gnc_numeric_create(10000000*v, v);
 
@@ -567,7 +584,6 @@
 	/* Multiply some random numbers.  This test presumes that
 	 * RAND_MAX is approx 2^32 
 	 */
-	int i;
 	for (i=0; i<NREPS; i++)
 	{
 		gint64 deno = 1;
@@ -588,7 +604,6 @@
 						 a, b, "expected %s got %s = %s * %s for mult exact");
 
 		/* Force 128-bit math to come into play */
-		int j;
 		for (j=1; j<31; j++)
 		{
 			a = gnc_numeric_create(na << j, 1<<j);
@@ -673,9 +688,9 @@
 			 c, d, "expected %s got %s = %s / %s for div round");
 
 	/* A simple irreducible ratio, involving negative numbers */
-	gnc_numeric amt_a = gnc_numeric_create (-6005287905LL, 40595);
-	gnc_numeric amt_tot = gnc_numeric_create (-8744187958LL, 40595);
-	gnc_numeric frac = gnc_numeric_div (amt_a, amt_tot,
+	amt_a = gnc_numeric_create (-6005287905LL, 40595);
+	amt_tot = gnc_numeric_create (-8744187958LL, 40595);
+	frac = gnc_numeric_div (amt_a, amt_tot,
                         GNC_DENOM_AUTO, GNC_HOW_DENOM_REDUCE);
 
 	check_binary_op (gnc_numeric_create(6005287905LL, 8744187958LL),
@@ -683,8 +698,8 @@
 	                 "expected %s got %s = %s / %s for div reduce");
 
 	/* Another overflow-prone condition */
-	gnc_numeric val_tot = gnc_numeric_create (-4280656418LL, 19873);
-	gnc_numeric val_a = gnc_numeric_mul (frac, val_tot,
+	val_tot = gnc_numeric_create (-4280656418LL, 19873);
+	val_a = gnc_numeric_mul (frac, val_tot,
                         gnc_numeric_denom(val_tot),
                         GNC_HOW_RND_ROUND| GNC_HOW_DENOM_EXACT);
 	check_binary_op (gnc_numeric_create(-2939846940LL, 19873),
@@ -699,6 +714,19 @@
 	check_binary_op (gnc_numeric_create(562854125307LL, 100),
 	                 val_a, val_tot, frac,
 	                 "expected %s got %s = %s * %s for mult round");
+
+	/* Yet another bug from bugzilla ... */
+	a = gnc_numeric_create (40066447153986554LL, 4518);
+	b = gnc_numeric_create (26703286457229LL, 3192);
+	frac = gnc_numeric_div(a, b,
+	                      GNC_DENOM_AUTO,
+	                      GNC_HOW_DENOM_SIGFIGS(6) |
+	                      GNC_HOW_RND_ROUND);
+
+	check_binary_op (gnc_numeric_create(106007, 100),
+	                 frac, a, b,
+	                 "expected %s got %s = %s / %s for mult sigfigs");
+
 }
   
 /* ======================================================= */
Index: test-lots.c
===================================================================
RCS file: /home/cvs/cvsroot/gnucash/src/engine/test/test-lots.c,v
retrieving revision 1.3.4.2
retrieving revision 1.3.4.3
diff -Lsrc/engine/test/test-lots.c -Lsrc/engine/test/test-lots.c -u -r1.3.4.2 -r1.3.4.3
--- src/engine/test/test-lots.c
+++ src/engine/test/test-lots.c
@@ -59,16 +59,18 @@
    * automatically fail! */
   g_log_set_always_fatal( G_LOG_LEVEL_CRITICAL | G_LOG_LEVEL_WARNING );
 
-  set_success_print (TRUE);
+  //set_success_print (TRUE);
 
   do_test((NULL!=gnc_module_load("gnucash/engine", 0)), "load engine");
 
-  /* set the rng to a known starting point */
+  /* Set up a reproducible test-case */
   srand(0);
 
   /* Iterate the test a number of times */
-  for (i=0; i< 20; i++)
+  for (i=0; i< 100; i++)
+  {
     run_test ();
+  }
 
   print_test_results();
   exit(get_rv());
Index: test-transaction-reversal.c
===================================================================
RCS file: /home/cvs/cvsroot/gnucash/src/engine/test/test-transaction-reversal.c,v
retrieving revision 1.3.4.1
retrieving revision 1.3.4.2
diff -Lsrc/engine/test/test-transaction-reversal.c -Lsrc/engine/test/test-transaction-reversal.c -u -r1.3.4.1 -r1.3.4.2
--- src/engine/test/test-transaction-reversal.c
+++ src/engine/test/test-transaction-reversal.c
@@ -49,12 +49,15 @@
   if (!acc1 || !acc2)
   {
     failure("accounts not created");
+    return;
   }
 
+  /* Find a transaction that isn't voided */
   do
   {
     transaction = get_random_transaction (book);
-    if (xaccTransGetVoidStatus (transaction))
+    gboolean voyd = xaccTransGetVoidStatus (transaction);
+    if (voyd)
     {
       xaccTransBeginEdit (transaction);
       xaccTransDestroy (transaction);
@@ -62,13 +65,14 @@
       transaction = NULL;
     }
   } while (!transaction);
-
   transaction_set_splits_to_accounts(transaction, acc1, acc2);
   xaccTransSortSplits(transaction);
 
   new_trans = xaccTransClone(transaction);
   if (!xaccTransEqual(transaction, new_trans, FALSE, TRUE, FALSE, TRUE))
+  {
     failure("xaccTransClone failed.");
+  }
 
   xaccTransReverse(new_trans);
   for (i = 0; i < 2; i++) 
@@ -78,7 +82,7 @@
     result = gnc_numeric_add(old, new, GNC_DENOM_AUTO, GNC_DENOM_FIXED);
     if (gnc_numeric_eq(old, gnc_numeric_neg(new))) 
     {
-      msg = g_strdup_printf("Amount of split %d wrong after reversal", i);
+      msg = g_strdup_printf("Amount of split %d wrong after reversal\n", i);
       failure(msg);
     }
 
@@ -87,7 +91,7 @@
     result = gnc_numeric_add(old, new, GNC_DENOM_AUTO, GNC_DENOM_FIXED);
     if (gnc_numeric_eq(old, gnc_numeric_neg(new))) 
     {
-      msg = g_strdup_printf("Value of split %d wrong after reversal", i);
+      msg = g_strdup_printf("Value of split %d wrong after reversal\n", i);
       failure(msg);
     }
 
@@ -101,6 +105,7 @@
   gnc_module_load("gnucash/engine", 0);
 
   xaccLogDisable ();
+  set_success_print (TRUE);
 
   run_test ();
 
Index: test-engine-stuff.c
===================================================================
RCS file: /home/cvs/cvsroot/gnucash/src/engine/test-core/test-engine-stuff.c,v
retrieving revision 1.52.4.7
retrieving revision 1.52.4.8
diff -Lsrc/engine/test-core/test-engine-stuff.c -Lsrc/engine/test-core/test-engine-stuff.c -u -r1.52.4.7 -r1.52.4.8
--- src/engine/test-core/test-engine-stuff.c
+++ src/engine/test-core/test-engine-stuff.c
@@ -4,6 +4,14 @@
  * Create transactions with random values, random accounts, random
  * account heirarchies, etc.
  *
+ * XXX We should modify routines to create really, ugly, dirty
+ * transactions 
+ * -- 3 or more splits (TBD) 
+ * -- splits without parent accounts  (done)
+ * -- splits that have accounts but aren't in a transaction (TBD)
+ * -- splits that share a currency with the transaction, but whose
+ *    value doesn't equal amount (done)
+ *
  * Created by Linux Developers Group, 2001
  * Updates Linas Vepstas July 2004
  */
@@ -19,8 +27,10 @@
 #include <sys/stat.h>
 #include <unistd.h>
 
+#include "Account.h"
 #include "AccountP.h"
 #include "Group.h"
+#include "GroupP.h"
 #include "gnc-date.h"
 #include "gnc-engine.h"
 #include "gnc-engine-util.h"
@@ -42,13 +52,19 @@
 static gint max_total_accounts = 1000;
 static gint total_num_accounts = 0;
 
-static kvp_value* get_random_kvp_value_depth (int type, gint depth);
-static gpointer get_random_list_element (GList *list);
-static void add_random_splits(QofBook *book, Transaction *trn, GList *account_list);
+
+/* The inverse fraction of split/transaction data that should 
+ * contain invalid/inconsistent fields/values.  Thus, 
+ * if borked==1000, then one in 1000 fields will have bad data.
+ * This is used to test the data integrity scrubbers, which are 
+ * supposed to clean up any crud they find.
+ */
+static gint borked = 80;
 
 gboolean gnc_engine_debug_random = FALSE;
 
-/***********************************************************************/
+/* ========================================================== */
+/* Set control parameters governing the run. */
 
 void
 set_max_group_depth (gint max_group_depth_in)
@@ -124,6 +140,71 @@
   usec_resolution = usec_resolution_in;
 }
 
+/* ========================================================== */
+
+static inline gboolean
+do_bork (void)
+{
+  if (1 == get_random_int_in_range (0, borked)) 
+  {
+    return TRUE;
+  }
+  return FALSE;
+}
+
+/* ========================================================== */
+/* GList stuff */
+
+static gpointer
+get_random_list_element (GList *list)
+{
+  g_return_val_if_fail (list, NULL);
+
+  return g_list_nth_data (list,
+                          get_random_int_in_range (0,
+                                                   g_list_length (list) - 1));
+}
+
+static kvp_value* get_random_kvp_value_depth (int type, gint depth);
+
+static GList*
+get_random_glist_depth (gint depth)
+{
+    GList *ret = NULL;
+    int count = get_random_int_in_range(1, 5);
+    int i;
+
+    if (depth >= kvp_max_depth)
+      return NULL;
+
+    for (i = 0; i < count; i++)
+    {
+        KvpValueType kvpt;
+        KvpValue *value;
+
+        kvpt = glist_strings_only ? KVP_TYPE_STRING : -2;
+
+        do
+        {
+          value = get_random_kvp_value_depth (kvpt, depth + 1);
+        }
+        while (!value);
+
+        ret = g_list_prepend(ret, value);
+    }
+
+    return ret;
+}
+
+GList*
+get_random_glist(void)
+{
+  return get_random_glist_depth (0);
+}
+
+/* ========================================================== */
+/* Time/Date, GUID, binary data stuff */
+
 Timespec*
 get_random_timespec(void)
 {
@@ -151,6 +232,204 @@
   return ret;
 }
 
+GUID*
+get_random_guid(void)
+{
+    GUID *ret;
+
+    ret = g_new(GUID, 1);
+    guid_new(ret);
+
+    return ret;
+}
+
+bin_data*
+get_random_binary_data(void)
+{
+    int len;
+    bin_data *ret;
+
+    len = get_random_int_in_range(20,100);
+    ret = g_new(bin_data, 1);
+    ret->data = g_new(char, len);
+    ret->len = len;
+
+    for(len--; len >= 0; len--)
+    {
+        ret->data[len] = (char)get_random_int_in_range(0,255);
+    }
+
+    return ret;
+}
+
+/* ========================================================== */
+/* KVP stuff */
+
+static KvpFrame* get_random_kvp_frame_depth (gint depth);
+
+static KvpValue*
+get_random_kvp_value_depth (int type, gint depth)
+{
+    int datype = type;
+
+    if (datype == -1)
+    {
+        datype = get_random_int_in_range(KVP_TYPE_GINT64, KVP_TYPE_FRAME);
+    }
+
+    if (datype == -2)
+    {
+        datype = get_random_int_in_range(KVP_TYPE_GINT64, KVP_TYPE_FRAME - 1);
+    }
+
+    if (datype == KVP_TYPE_FRAME && depth >= kvp_max_depth)
+      return NULL;
+
+    if (datype == KVP_TYPE_GLIST && depth >= kvp_max_depth)
+      return NULL;
+
+    if (kvp_type_excluded (datype))
+      return NULL;
+
+    switch(datype)
+    {
+    case KVP_TYPE_GINT64:
+        return kvp_value_new_gint64(get_random_gint64());
+        break;
+
+    case KVP_TYPE_DOUBLE:
+        return NULL;
+        break;
+
+    case KVP_TYPE_NUMERIC:
+        return kvp_value_new_gnc_numeric(get_random_gnc_numeric());
+        break;
+
+    case KVP_TYPE_STRING:
+    {
+        gchar *tmp_str;
+        KvpValue *ret;
+        tmp_str = get_random_string();
+        if(!tmp_str)
+        {
+            return NULL;
+        }
+        
+        ret = kvp_value_new_string(tmp_str);
+        g_free(tmp_str);
+        return ret;
+    }
+        break;
+
+    case KVP_TYPE_GUID:
+    {
+        GUID *tmp_guid;
+        KvpValue *ret;
+        tmp_guid = get_random_guid();
+        ret = kvp_value_new_guid(tmp_guid);
+        g_free(tmp_guid);
+        return ret;
+    }
+        break;
+
+    case KVP_TYPE_TIMESPEC:
+    {
+        Timespec *ts = get_random_timespec();
+        return kvp_value_new_timespec (*ts);
+    }
+	break;
+    
+    case KVP_TYPE_BINARY:
+    {
+        bin_data *tmp_data;
+        KvpValue *ret;
+        tmp_data = get_random_binary_data();
+        ret = kvp_value_new_binary(tmp_data->data, tmp_data->len);
+        g_free(tmp_data->data);
+        g_free(tmp_data);
+        return ret;
+    }
+        break;
+ 
+    case KVP_TYPE_GLIST:
+        return kvp_value_new_glist_nc(get_random_glist_depth (depth + 1));
+        break;
+
+    case KVP_TYPE_FRAME:
+    {
+        KvpFrame *tmp_frame;
+        KvpValue *ret;
+        tmp_frame = get_random_kvp_frame_depth(depth + 1);
+        ret = kvp_value_new_frame(tmp_frame);
+        kvp_frame_delete(tmp_frame);
+        return ret;
+    }
+        break;
+
+    default:
+        return NULL;
+        break;
+    }
+}
+
+static KvpFrame*
+get_random_kvp_frame_depth (gint depth)
+{
+    KvpFrame *ret;
+    int vals_to_add;
+    gboolean val_added;
+
+    if (depth >= kvp_max_depth)
+      return NULL;
+
+    ret = kvp_frame_new();
+
+    vals_to_add = get_random_int_in_range(1,kvp_frame_max_elements);
+    val_added = FALSE;
+
+    for (;vals_to_add > 0; vals_to_add--)
+    {
+        gchar *key;
+        KvpValue *val;
+
+        do
+        {
+          key = get_random_string_without("/");
+        } while (!key || *key == '\0');
+
+        val = get_random_kvp_value_depth (-1, depth + 1);
+        if (!val)
+        {
+          if (!val_added)
+            vals_to_add++;
+          continue;
+        }
+
+        val_added = TRUE;
+
+        kvp_frame_set_slot_nc(ret, key, val);
+
+        g_free(key);
+    }
+
+    return ret;
+}
+
+KvpFrame *
+get_random_kvp_frame (void)
+{
+  return get_random_kvp_frame_depth (0);
+}
+
+KvpValue *
+get_random_kvp_value(int type)
+{
+  return get_random_kvp_value_depth (type, 0);
+}
+
+/* ================================================================= */
+/* Numeric stuff */
+
 #define RAND_IN_RANGE(X) (((X)*((gint64) (rand()+1)))/RAND_MAX)
 
 gnc_numeric
@@ -185,6 +464,9 @@
     return gnc_numeric_create(numer, deno);
 }
 
+/* ================================================================= */
+/* Commodity stuff */
+
 const char *types[] =
 {
     "NASDAQ",
@@ -201,18 +483,168 @@
     return get_random_string_in_array(types);
 }
 
-void
-make_random_changes_to_price (QofBook *book, GNCPrice *p)
+static gnc_commodity *
+get_random_commodity_from_table (gnc_commodity_table *table)
 {
-  Timespec *ts;
-  char *string;
-  gnc_commodity *c;
+  GList *namespaces;
+  gnc_commodity *com = NULL;
 
-  g_return_if_fail (book && p);
+  g_return_val_if_fail (table, NULL);
 
-  gnc_price_begin_edit (p);
+  namespaces = gnc_commodity_table_get_namespaces (table);
 
-  c = get_random_commodity (book);
+  do
+  {
+    GList *commodities;
+    char *namespace;
+
+    namespace = get_random_list_element (namespaces);
+
+    commodities = gnc_commodity_table_get_commodities (table, namespace);
+    if (!commodities)
+      continue;
+
+    com = get_random_list_element (commodities);
+
+    g_list_free (commodities);
+
+  } while (!com);
+
+
+  g_list_free (namespaces);
+
+  return com;
+}
+
+gnc_commodity*
+get_random_commodity (QofBook *book)
+{
+    gnc_commodity *ret;
+    gchar *name;
+    const gchar *space;
+    gchar *mn;
+    gchar *xcode;
+    int ran_int;
+    gnc_commodity_table *table;
+
+    table = gnc_commodity_table_get_table (book);
+
+#if 0
+    if (table &&
+        (gnc_commodity_table_get_size (table) > 0) &&
+        get_random_int_in_range (1, 5) < 5)
+      return get_random_commodity_from_table (table);
+#endif
+
+    mn = get_random_string();
+    space = get_random_commodity_namespace();
+
+    if (table)
+    {
+      ret = gnc_commodity_table_lookup (table, space, mn);
+
+      if (ret)
+      {
+        g_free (mn);
+        return ret;
+      }
+    }
+
+    name = get_random_string();
+    xcode = get_random_string();
+
+    /* SCU == smallest currency unit -- the value of the denominator */
+#define MAX_SCU 6000
+    ran_int = get_random_int_in_range(1, MAX_SCU);
+
+    ret = gnc_commodity_new (book, name, space, mn, xcode, ran_int);
+
+    g_free(mn);
+    g_free(name);
+    g_free(xcode);
+
+    if (table)
+      ret = gnc_commodity_table_insert (table, ret);
+
+    return ret;
+}
+
+void
+make_random_changes_to_commodity (gnc_commodity *com)
+{
+  char *str;
+
+  g_return_if_fail (com);
+
+  str = get_random_string ();
+  gnc_commodity_set_namespace (com, str);
+  g_free (str);
+
+  str = get_random_string ();
+  gnc_commodity_set_mnemonic (com, str);
+  g_free (str);
+
+  str = get_random_string ();
+  gnc_commodity_set_fullname (com, str);
+  g_free (str);
+
+  str = get_random_string ();
+  gnc_commodity_set_exchange_code (com, str);
+  g_free (str);
+
+  gnc_commodity_set_fraction (com, get_random_int_in_range (1, 100000));
+}
+
+void
+make_random_changes_to_commodity_table (gnc_commodity_table *table)
+{
+  GList *namespaces;
+  GList *node;
+
+  g_return_if_fail (table);
+
+  namespaces = gnc_commodity_table_get_namespaces (table);
+
+  for (node = namespaces; node; node = node->next)
+  {
+    const char *ns = node->data;
+    GList *commodities;
+    GList *com_node;
+
+    if (gnc_commodity_namespace_is_iso (ns))
+      continue;
+
+    commodities = gnc_commodity_table_get_commodities (table, ns);
+
+    for (com_node = commodities; com_node; com_node = com_node->next)
+    {
+      gnc_commodity *com = com_node->data;
+
+      gnc_commodity_table_remove (table, com);
+      make_random_changes_to_commodity (com);
+      gnc_commodity_table_insert (table, com);
+    }
+
+    g_list_free (commodities);
+  }
+
+  g_list_free (namespaces);
+}
+/* ================================================================= */
+/* Price stuff */
+
+void
+make_random_changes_to_price (QofBook *book, GNCPrice *p)
+{
+  Timespec *ts;
+  char *string;
+  gnc_commodity *c;
+
+  g_return_if_fail (book && p);
+
+  gnc_price_begin_edit (p);
+
+  c = get_random_commodity (book);
   gnc_price_set_commodity (p, c);
 
   c = get_random_commodity (book);
@@ -271,7 +703,8 @@
 {
   GNCPriceDB *db;
 
-  db = gnc_pricedb_create (book);
+  // db = gnc_pricedb_create (book);
+  db = gnc_pricedb_get_db (book);
   make_random_pricedb (book, db);
 
   return db;
@@ -301,264 +734,42 @@
   {
     GNCPrice *p = node->data;
 
-    switch (get_random_int_in_range (0, 5))
-    {
-      case 0: /* Delete */
-        gnc_pricedb_remove_price (pdb, p);
-        break;
-
-      case 1:
-      case 2: /* Change */
-        make_random_changes_to_price (book, p);
-        break;
-
-      default: /* nothing */
-        break;
-    }
-  }
-
-  g_list_free (list);
-
-  /* Add a few new ones */
-  {
-    int i = get_random_int_in_range (1, 5);
-
-    while (i--)
-    {
-      GNCPrice *p = get_random_price (book);
-
-      gnc_pricedb_add_price (pdb, p);
-
-      gnc_price_unref (p);
-    }
-  }
-}
-
-GUID*
-get_random_guid(void)
-{
-    GUID *ret;
-
-    ret = g_new(GUID, 1);
-    guid_new(ret);
-
-    return ret;
-}
-
-static GList*
-get_random_glist_depth (gint depth)
-{
-    GList *ret = NULL;
-    int count = get_random_int_in_range(1, 5);
-    int i;
-
-    if (depth >= kvp_max_depth)
-      return NULL;
-
-    for (i = 0; i < count; i++)
-    {
-        KvpValueType kvpt;
-        kvp_value *value;
-
-        kvpt = glist_strings_only ? KVP_TYPE_STRING : -2;
-
-        do
-        {
-          value = get_random_kvp_value_depth (kvpt, depth + 1);
-        }
-        while (!value);
-
-        ret = g_list_prepend(ret, value);
-    }
-
-    return ret;
-}
-
-GList*
-get_random_glist(void)
-{
-  return get_random_glist_depth (0);
-}
-
-bin_data*
-get_random_binary_data(void)
-{
-    int len;
-    bin_data *ret;
-
-    len = get_random_int_in_range(20,100);
-    ret = g_new(bin_data, 1);
-    ret->data = g_new(char, len);
-    ret->len = len;
-
-    for(len--; len >= 0; len--)
-    {
-        ret->data[len] = (char)get_random_int_in_range(0,255);
-    }
-
-    return ret;
-}
-
-static kvp_frame*
-get_random_kvp_frame_depth (gint depth)
-{
-    kvp_frame *ret;
-    int vals_to_add;
-    gboolean val_added;
-
-    if (depth >= kvp_max_depth)
-      return NULL;
-
-    ret = kvp_frame_new();
-
-    vals_to_add = get_random_int_in_range(1,kvp_frame_max_elements);
-    val_added = FALSE;
-
-    for (;vals_to_add > 0; vals_to_add--)
-    {
-        gchar *key;
-        kvp_value *val;
-
-        do
-        {
-          key = get_random_string_without("/");
-        } while (!key || *key == '\0');
-
-        val = get_random_kvp_value_depth (-1, depth + 1);
-        if (!val)
-        {
-          if (!val_added)
-            vals_to_add++;
-          continue;
-        }
-
-        val_added = TRUE;
-
-        kvp_frame_set_slot_nc(ret, key, val);
-
-        g_free(key);
-    }
-
-    return ret;
-}
-
-kvp_frame*
-get_random_kvp_frame (void)
-{
-  return get_random_kvp_frame_depth (0);
-}
-
-static kvp_value*
-get_random_kvp_value_depth (int type, gint depth)
-{
-    int datype = type;
-
-    if (datype == -1)
-    {
-        datype = get_random_int_in_range(KVP_TYPE_GINT64, KVP_TYPE_FRAME);
-    }
-
-    if (datype == -2)
-    {
-        datype = get_random_int_in_range(KVP_TYPE_GINT64, KVP_TYPE_FRAME - 1);
-    }
-
-    if (datype == KVP_TYPE_FRAME && depth >= kvp_max_depth)
-      return NULL;
-
-    if (datype == KVP_TYPE_GLIST && depth >= kvp_max_depth)
-      return NULL;
-
-    if (kvp_type_excluded (datype))
-      return NULL;
-
-    switch(datype)
-    {
-    case KVP_TYPE_GINT64:
-        return kvp_value_new_gint64(get_random_gint64());
-        break;
-
-    case KVP_TYPE_DOUBLE:
-	return NULL;
-        break;
-
-    case KVP_TYPE_NUMERIC:
-        return kvp_value_new_gnc_numeric(get_random_gnc_numeric());
-        break;
-
-    case KVP_TYPE_STRING:
-    {
-        gchar *tmp_str;
-        kvp_value *ret;
-        tmp_str = get_random_string();
-        if(!tmp_str)
-        {
-            return NULL;
-        }
-        
-        ret = kvp_value_new_string(tmp_str);
-        g_free(tmp_str);
-        return ret;
-    }
-        break;
-
-    case KVP_TYPE_GUID:
-    {
-        GUID *tmp_guid;
-        kvp_value *ret;
-        tmp_guid = get_random_guid();
-        ret = kvp_value_new_guid(tmp_guid);
-        g_free(tmp_guid);
-        return ret;
-    }
-        break;
-
-    case KVP_TYPE_TIMESPEC:
-    {
-        Timespec *ts = get_random_timespec();
-        return kvp_value_new_timespec (*ts);
-    }
-	break;
-    
-    case KVP_TYPE_BINARY:
+    switch (get_random_int_in_range (0, 5))
     {
-        bin_data *tmp_data;
-        kvp_value *ret;
-        tmp_data = get_random_binary_data();
-        ret = kvp_value_new_binary(tmp_data->data, tmp_data->len);
-        g_free(tmp_data->data);
-        g_free(tmp_data);
-        return ret;
-    }
-        break;
- 
-    case KVP_TYPE_GLIST:
-        return kvp_value_new_glist_nc(get_random_glist_depth (depth + 1));
+      case 0: /* Delete */
+        gnc_pricedb_remove_price (pdb, p);
         break;
 
-    case KVP_TYPE_FRAME:
-    {
-        kvp_frame *tmp_frame;
-        kvp_value *ret;
-        tmp_frame = get_random_kvp_frame_depth(depth + 1);
-        ret = kvp_value_new_frame(tmp_frame);
-        kvp_frame_delete(tmp_frame);
-        return ret;
-    }
+      case 1:
+      case 2: /* Change */
+        make_random_changes_to_price (book, p);
         break;
 
-    default:
-        return NULL;
+      default: /* nothing */
         break;
     }
-}
+  }
 
-kvp_value *
-get_random_kvp_value(int type)
-{
-  return get_random_kvp_value_depth (type, 0);
+  g_list_free (list);
+
+  /* Add a few new ones */
+  {
+    int i = get_random_int_in_range (1, 5);
+
+    while (i--)
+    {
+      GNCPrice *p = get_random_price (book);
+
+      gnc_pricedb_add_price (pdb, p);
+
+      gnc_price_unref (p);
+    }
+  }
 }
 
+/* ================================================================= */
+/* Account stuff */
+
 static void
 set_account_random_string(Account* act,
                           void(*func)(Account *act, const gchar*str))
@@ -617,7 +828,7 @@
 }
 
 static void
-make_random_group (QofBook *book, AccountGroup * group)
+make_random_group (QofBook *book, AccountGroup *group)
 {
   int depth;
 
@@ -637,13 +848,91 @@
 
   g_return_val_if_fail (book, NULL);
 
-  group = xaccMallocAccountGroup (book);
+  group = xaccGetAccountGroup (book);
+  if (!group)
+  {
+    group = xaccMallocAccountGroup (book);
+    xaccSetAccountGroup (book, group);
+  }
 
   make_random_group (book, group);
 
   return group;
 }
 
+/* ================================================================= */
+/* transaction stuff */
+
+/** This routine creates a random, but otherwise self-consistent,
+ *  'legal' transaction.  It's been modified to occasionally build
+ *   cruddy, inconsistent transactions, so that the engine 'scrub' 
+ *   routines get tested.
+ */
+static void
+add_random_splits(QofBook *book, Transaction *trn, GList *account_list)
+{
+    Account *acc, *bcc;
+    Split *s;
+
+    /* Gotta have at least two different accounts */
+    if (1 >= g_list_length (account_list)) return;
+
+    /* Set up two splits whose values really are opposites. */
+    gnc_commodity *com = xaccTransGetCurrency (trn);
+    int scu = gnc_commodity_get_fraction(com);
+    gnc_numeric num = get_random_gnc_numeric();
+
+    if (!do_bork()) num = gnc_numeric_convert (num, scu, GNC_HOW_RND_ROUND);
+
+    acc = get_random_list_element (account_list);
+    s = get_random_split(book, acc);
+    xaccTransAppendSplit(trn, s);
+    xaccSplitSetValue(s, num);
+
+    /* If the currencies are the same, the split amount should equal
+     * the split value (unless we bork it on purpose) */
+    if (gnc_commodity_equal (xaccTransGetCurrency(trn), 
+                             xaccAccountGetCommodity(acc)) &&
+        (!do_bork()))
+    {
+      xaccSplitSetAmount(s, num);
+    }
+
+    /* Occasionally leave a dangling split around */
+    if (do_bork()) xaccAccountRemoveSplit (s->acc, s);
+
+    bcc = get_random_list_element (account_list);
+    if ((bcc == acc) && (!do_bork()))
+    { 
+      /* Make sure that each side of the transaction is in 
+       * a different account; otherwise get weirdness in lot
+       * calculcations.  ... Hmm maybe should fix lots in 
+       * this case? */
+      while (bcc == acc) {
+         bcc = get_random_list_element (account_list);
+      }
+    }
+
+    s = get_random_split(book, bcc);
+    xaccTransAppendSplit(trn, s);
+
+    /* Other split should have equal and opposite value */
+    if (do_bork()) 
+    {
+       num = get_random_gnc_numeric();
+    } 
+    xaccSplitSetValue(s, gnc_numeric_neg(num));
+
+    if (gnc_commodity_equal (xaccTransGetCurrency(trn), 
+                             xaccAccountGetCommodity(bcc)) && 
+        (!do_bork()))
+    {
+      xaccSplitSetAmount(s, num);
+    }
+
+    if (do_bork()) xaccAccountRemoveSplit (s->acc, s);
+}
+
 typedef struct
 {
   GUID guid;
@@ -875,6 +1164,7 @@
 Account*
 get_random_account(QofBook *book)
 {
+    AccountGroup *grp;
     Account *ret;
     int tmp_int;
 
@@ -894,6 +1184,13 @@
 
     xaccAccountSetSlots_nc(ret, get_random_kvp_frame());
 
+    grp = xaccGetAccountGroup (book);
+    if (!grp) 
+    {
+        grp = xaccMallocAccountGroup (book);
+        xaccSetAccountGroup (book, grp);
+    }
+    xaccGroupInsertAccount (grp, ret);
     xaccAccountCommitEdit(ret);
 
     return ret;
@@ -1003,29 +1300,6 @@
 }
 
 static void
-add_random_splits(QofBook *book, Transaction *trn, GList *account_list)
-{
-    Account *account;
-    Split *s;
-
-    /* Set up two splits whose values really are opposites. */
-    gnc_commodity *com = xaccTransGetCurrency (trn);
-    int scu = gnc_commodity_get_fraction(com);
-    gnc_numeric num = get_random_gnc_numeric();
-    num = gnc_numeric_convert (num, scu, GNC_HOW_RND_ROUND);
-
-    account = get_random_list_element (account_list);
-    s = get_random_split(book, account);
-    xaccTransAppendSplit(trn, s);
-    xaccSplitSetValue(s, num);
-
-    account = get_random_list_element (account_list);
-    s = get_random_split(book, account);
-    xaccTransAppendSplit(trn, s);
-    xaccSplitSetValue(s, gnc_numeric_neg(num));
-}
-
-static void
 trn_add_ran_timespec(Transaction *trn, void (*func)(Transaction*,
                                                     const Timespec*))
 {
@@ -1046,9 +1320,12 @@
 
     if (!account_list) 
     {
-      account_list = xaccGroupGetSubAccounts (gnc_book_get_group (book));
+      account_list = xaccGroupGetSubAccounts (xaccGetAccountGroup (book));
     }
 
+    /* Gotta have at least two different accounts */
+    if (1 >= g_list_length (account_list)) return NULL;
+
     ret = xaccMallocTransaction(book);
 
     xaccTransBeginEdit(ret);
@@ -1061,7 +1338,8 @@
     trn_add_ran_timespec(ret, xaccTransSetDatePostedTS);
     trn_add_ran_timespec(ret, xaccTransSetDateEnteredTS);
 
-    xaccTransSetSlots_nc(ret, get_random_kvp_frame());
+    KvpFrame *f = get_random_kvp_frame();
+    xaccTransSetSlots_nc(ret, f);
 
     add_random_splits(book, ret, account_list);
 
@@ -1111,163 +1389,6 @@
   xaccTransCommitEdit (trans);
 }
 
-static gpointer
-get_random_list_element (GList *list)
-{
-  g_return_val_if_fail (list, NULL);
-
-  return g_list_nth_data (list,
-                          get_random_int_in_range (0,
-                                                   g_list_length (list) - 1));
-}
-
-static gnc_commodity *
-get_random_commodity_from_table (gnc_commodity_table *table)
-{
-  GList *namespaces;
-  gnc_commodity *com = NULL;
-
-  g_return_val_if_fail (table, NULL);
-
-  namespaces = gnc_commodity_table_get_namespaces (table);
-
-  do
-  {
-    GList *commodities;
-    char *namespace;
-
-    namespace = get_random_list_element (namespaces);
-
-    commodities = gnc_commodity_table_get_commodities (table, namespace);
-    if (!commodities)
-      continue;
-
-    com = get_random_list_element (commodities);
-
-    g_list_free (commodities);
-
-  } while (!com);
-
-
-  g_list_free (namespaces);
-
-  return com;
-}
-
-gnc_commodity*
-get_random_commodity (QofBook *book)
-{
-    gnc_commodity *ret;
-    gchar *name;
-    const gchar *space;
-    gchar *mn;
-    gchar *xcode;
-    int ran_int;
-    gnc_commodity_table *table;
-
-    table = gnc_book_get_commodity_table (book);
-
-#if 0
-    if (table &&
-        (gnc_commodity_table_get_size (table) > 0) &&
-        get_random_int_in_range (1, 5) < 5)
-      return get_random_commodity_from_table (table);
-#endif
-
-    mn = get_random_string();
-    space = get_random_commodity_namespace();
-
-    if (table)
-    {
-      ret = gnc_commodity_table_lookup (table, space, mn);
-
-      if (ret)
-      {
-        g_free (mn);
-        return ret;
-      }
-    }
-
-    name = get_random_string();
-    xcode = get_random_string();
-
-    /* SCU == smallest currency unit -- the value of the denominator */
-#define MAX_SCU 6000
-    ran_int = get_random_int_in_range(1, MAX_SCU);
-
-    ret = gnc_commodity_new (book, name, space, mn, xcode, ran_int);
-
-    g_free(mn);
-    g_free(name);
-    g_free(xcode);
-
-    if (table)
-      ret = gnc_commodity_table_insert (table, ret);
-
-    return ret;
-}
-
-void
-make_random_changes_to_commodity (gnc_commodity *com)
-{
-  char *str;
-
-  g_return_if_fail (com);
-
-  str = get_random_string ();
-  gnc_commodity_set_namespace (com, str);
-  g_free (str);
-
-  str = get_random_string ();
-  gnc_commodity_set_mnemonic (com, str);
-  g_free (str);
-
-  str = get_random_string ();
-  gnc_commodity_set_fullname (com, str);
-  g_free (str);
-
-  str = get_random_string ();
-  gnc_commodity_set_exchange_code (com, str);
-  g_free (str);
-
-  gnc_commodity_set_fraction (com, get_random_int_in_range (1, 100000));
-}
-
-void
-make_random_changes_to_commodity_table (gnc_commodity_table *table)
-{
-  GList *namespaces;
-  GList *node;
-
-  g_return_if_fail (table);
-
-  namespaces = gnc_commodity_table_get_namespaces (table);
-
-  for (node = namespaces; node; node = node->next)
-  {
-    const char *ns = node->data;
-    GList *commodities;
-    GList *com_node;
-
-    if (gnc_commodity_namespace_is_iso (ns))
-      continue;
-
-    commodities = gnc_commodity_table_get_commodities (table, ns);
-
-    for (com_node = commodities; com_node; com_node = com_node->next)
-    {
-      gnc_commodity *com = com_node->data;
-
-      gnc_commodity_table_remove (table, com);
-      make_random_changes_to_commodity (com);
-      gnc_commodity_table_insert (table, com);
-    }
-
-    g_list_free (commodities);
-  }
-
-  g_list_free (namespaces);
-}
 
 static GList *
 get_random_guids(int max)
@@ -1427,7 +1548,7 @@
   while (num_terms-- > 0)
   {
     gint pr_type;
-    kvp_value *value;
+    KvpValue *value;
     Timespec *start;
     Timespec *end;
     GList *guids;
@@ -1599,8 +1720,8 @@
 
   book = qof_book_new ();
 
-  make_random_group (book, gnc_book_get_group (book));
-  make_random_pricedb (book, gnc_book_get_pricedb (book));
+  get_random_group (book);
+  get_random_pricedb (book);
 
   return book;
 }
@@ -1615,8 +1736,8 @@
 
   book = qof_session_get_book (session);
 
-  make_random_group (book, gnc_book_get_group (book));
-  make_random_pricedb (book, gnc_book_get_pricedb (book));
+  get_random_group (book);
+  get_random_pricedb (book);
 
   return session;
 }
@@ -1632,13 +1753,13 @@
 
   g_return_if_fail (book);
 
-  accounts = xaccGroupGetSubAccounts (gnc_book_get_group (book));
+  accounts = xaccGroupGetSubAccounts (xaccGetAccountGroup (book));
 
   g_return_if_fail (accounts);
 
   num_accounts = g_list_length (accounts);
 
-  table = gnc_book_get_commodity_table (book);
+  table = gnc_commodity_table_get_table (book);
 
   while (num_transactions--)
   {
@@ -1656,11 +1777,11 @@
 {
   g_return_if_fail (book);
 
-  make_random_changes_to_group (book, gnc_book_get_group (book));
-  make_random_changes_to_pricedb (book, gnc_book_get_pricedb (book));
+  make_random_changes_to_group (book, xaccGetAccountGroup (book));
+  make_random_changes_to_pricedb (book, gnc_pricedb_get_db (book));
 
 #if 0
-  make_random_changes_to_commodity_table (gnc_book_get_commodity_table (book));
+  make_random_changes_to_commodity_table (gnc_commodity_table_get_table (book));
 #endif
 }
 
@@ -1680,7 +1801,7 @@
 } KVPQueryData;
 
 static void
-add_kvp_value_query (const char *key, kvp_value *value, gpointer data)
+add_kvp_value_query (const char *key, KvpValue *value, gpointer data)
 {
   KVPQueryData *kqd = data;
   GSList *node;
@@ -1701,7 +1822,7 @@
 }
 
 static void
-add_kvp_query (Query *q, kvp_frame *frame, QofIdType where)
+add_kvp_query (Query *q, KvpFrame *frame, QofIdType where)
 {
   KVPQueryData kqd;
 
Index: gnucash.desktop.in
===================================================================
RCS file: /home/cvs/cvsroot/gnucash/src/gnome/gnucash.desktop.in,v
retrieving revision 1.2.4.1
retrieving revision 1.2.4.2
diff -Lsrc/gnome/gnucash.desktop.in -Lsrc/gnome/gnucash.desktop.in -u -r1.2.4.1 -r1.2.4.2
--- src/gnome/gnucash.desktop.in
+++ src/gnome/gnucash.desktop.in
@@ -1,6 +1,7 @@
 [Desktop Entry]
 _Name=GnuCash
-_Comment=GnuCash Personal Finance
+_GenericName=Money Management
+_Comment=Manage your finances, accounts, and investments
 TryExec=gnucash
 Exec=gnucash
 Icon=gnucash/gnucash-icon.png
Index: qif-dialog-utils.scm
===================================================================
RCS file: /home/cvs/cvsroot/gnucash/src/import-export/qif-import/qif-dialog-utils.scm,v
retrieving revision 1.3.4.2
retrieving revision 1.3.4.3
diff -Lsrc/import-export/qif-import/qif-dialog-utils.scm -Lsrc/import-export/qif-import/qif-dialog-utils.scm -u -r1.3.4.2 -r1.3.4.3
--- src/import-export/qif-import/qif-dialog-utils.scm
+++ src/import-export/qif-import/qif-dialog-utils.scm
@@ -18,8 +18,11 @@
 
 (define (default-interest-acct brokerage security) 
   (string-append (_ "Interest") (gnc:account-separator-char) 
-                 brokerage (gnc:account-separator-char)  
-                 security))
+                 brokerage
+		 (if (string=? security "")
+		  ""
+		  (string-append (gnc:account-separator-char)  
+				  security))))
 
 (define (default-capital-return-acct brokerage security) 
   (string-append (_ "Cap Return") (gnc:account-separator-char) 
Index: report-system.scm
===================================================================
RCS file: /home/cvs/cvsroot/gnucash/src/report/report-system/report-system.scm,v
retrieving revision 1.20.4.2
retrieving revision 1.20.4.3
diff -Lsrc/report/report-system/report-system.scm -Lsrc/report/report-system/report-system.scm -u -r1.20.4.2 -r1.20.4.3
--- src/report/report-system/report-system.scm
+++ src/report/report-system/report-system.scm
@@ -68,6 +68,7 @@
 
 ;; html-utilities.scm 
 
+(export gnc:html-make-empty-cell)
 (export gnc:html-make-empty-cells)
 (export gnc:account-anchor-text)
 (export gnc:split-anchor-text)
@@ -593,6 +594,9 @@
 (export gnc:report-finished)
 (export gnc:accounts-count-splits)
 (export gnc:commodity-collector-allzero?)
+(export gnc:account-get-trans-type-balance-interval)
+(export gnc:account-get-pos-trans-total-interval)
+(export gnc:double-col)
 
 (load-from-path "commodity-utilities.scm")
 (load-from-path "html-barchart.scm")
Index: html-table.scm
===================================================================
RCS file: /home/cvs/cvsroot/gnucash/src/report/report-system/html-table.scm,v
retrieving revision 1.1.6.1
retrieving revision 1.1.6.2
diff -Lsrc/report/report-system/html-table.scm -Lsrc/report/report-system/html-table.scm -u -r1.1.6.1 -r1.1.6.2
--- src/report/report-system/html-table.scm
+++ src/report/report-system/html-table.scm
@@ -405,19 +405,25 @@
 ;;   (let ((a '(0 1 2))) (list-set! a 1 "x") a)
 ;;    => (0 "x" 2)
 (define (gnc:html-table-get-cell table row col)
-  (list-ref-safe (gnc:html-table-get-row table row) col))
+  (let* ((row (gnc:html-table-get-row table row)))
+    (and row (list-ref-safe row col)))
+  )
 
 (define (gnc:html-table-get-row table row)
   (let* ((dd (gnc:html-table-data table))
-	 (len (length dd))
+	 (len (and dd (length dd)))
+	 )
+    (and len
+	 (list-ref-safe dd (- (- len 1) row))
 	 )
-    (list-ref-safe dd (- (- len 1) row))
     ))
 
 (define (gnc:html-table-set-cell! table row col . objects)
   (let ((rowdata #f)
 	(row-loc #f)
-        (l (length (gnc:html-table-data table))))
+        (l (length (gnc:html-table-data table)))
+	(objs (length objects))
+	)
     ;; ensure the row-data is there 
     (if (>= row l)
 	(begin
@@ -433,8 +439,12 @@
 	  (set! rowdata (list-ref (gnc:html-table-data table) row-loc))))
     
     ;; make a table-cell and set the data 
-    (let ((tc (gnc:make-html-table-cell)))
-      (apply gnc:html-table-cell-append-objects! tc objects)
+    (let* ((tc (gnc:make-html-table-cell))
+	   (first (car objects)))
+      (if (and (equal? objs 1) (gnc:html-table-cell? first))
+	  (set! tc first)
+	  (apply gnc:html-table-cell-append-objects! tc objects)
+	  )
       (set! rowdata (list-set-safe! rowdata col tc))
       
       ;; add the row-data back to the table 
Index: commodity-utilities.scm
===================================================================
RCS file: /home/cvs/cvsroot/gnucash/src/report/report-system/commodity-utilities.scm,v
retrieving revision 1.11.4.2
retrieving revision 1.11.4.3
diff -Lsrc/report/report-system/commodity-utilities.scm -Lsrc/report/report-system/commodity-utilities.scm -u -r1.11.4.2 -r1.11.4.3
--- src/report/report-system/commodity-utilities.scm
+++ src/report/report-system/commodity-utilities.scm
@@ -906,3 +906,30 @@
 	 #f)
 	balance)
       #f))
+
+;; Returns the number of commodities in a commodity-collector.
+;; (If this were implemented as a record, I would be able to
+;; just (length ...) the alist, but....)
+(define (gnc:commodity-collector-commodity-count collector)
+    (let ((commodities 0))
+	(gnc:commodity-collector-map
+	    collector
+		(lambda (comm amt)
+		  (set! commodities (+ commodities 1))))
+	commodities
+    ))
+
+(define (gnc:uniform-commodity? amt report-commodity)
+  ;; function to see if the commodity-collector amt
+  ;; contains any foreign commodities
+  (let ((elts (gnc:commodity-collector-commodity-count amt))
+	)
+    (or (equal? elts 0)
+	(and (equal? elts 1)
+	     (gnc:commodity-collector-contains-commodity?
+	      amt report-commodity)
+	     )
+	)
+    )
+  )
+
Index: report-utilities.scm
===================================================================
RCS file: /home/cvs/cvsroot/gnucash/src/report/report-system/report-utilities.scm,v
retrieving revision 1.18.4.2
retrieving revision 1.18.4.3
diff -Lsrc/report/report-system/report-utilities.scm -Lsrc/report/report-system/report-utilities.scm -u -r1.18.4.2 -r1.18.4.3
--- src/report/report-system/report-utilities.scm
+++ src/report/report-system/report-utilities.scm
@@ -474,17 +474,6 @@
 (define (gnc:commodity-collector-list collector)
   (collector 'list #f #f))
 
-;; Returns the number of commodities in a commodity-collector.
-;; (If this were implemented as a record, I would be able to
-;; just (length ...) the alist, but....)
-(define (gnc:commodity-collector-commodity-count collector)
-    (let ((commodities 0))
-	(gnc:commodity-collector-map
-	    collector
-		(lambda (comm amt) (set! commodities (+ commodities 1))))
-	commodities
-    ))
-
 ;; Returns zero if all entries in this collector are zero.
 (define (gnc:commodity-collector-allzero? collector)
   (let ((result #t))
@@ -706,3 +695,149 @@
 	 (gnc:accounts-count-splits (cdr accounts)))
       0))
 
+;; Sums up any splits of a certain type affecting a group of accounts.
+;; the type is an alist '((str "match me") (cased #f) (regexp #f))
+(define (gnc:account-get-trans-type-balance-interval
+	 group type start-date-tp end-date-tp)
+  (let* ((query (gnc:malloc-query))
+	 (splits #f)
+	 (get-val (lambda (alist key)
+		    (let ((lst (assoc-ref alist key)))
+		      (if lst (car lst) lst))))
+	 (matchstr (get-val type 'str))
+	 (case-sens (if (get-val type 'cased) 1 0))
+	 (regexp (if (get-val type 'regexp) 1 0))
+	 (total (gnc:make-commodity-collector))
+	 )
+    (gnc:query-set-book query (gnc:get-current-book))
+    (gnc:query-set-match-non-voids-only! query (gnc:get-current-book))
+    (gnc:query-add-account-match query group 'guid-match-any 'query-and)
+    (gnc:query-add-date-match-timepair
+     query
+     (and start-date-tp #t) start-date-tp
+     (and end-date-tp #t) end-date-tp 'query-and)
+    (gnc:query-add-description-match
+     query matchstr case-sens regexp 'query-and)
+    
+    (set! splits (gnc:query-get-splits query))
+    (map (lambda (split)
+		(let* ((shares (gnc:split-get-amount split))
+		       (acct-comm (gnc:account-get-commodity
+				   (gnc:split-get-account split)))
+		       )
+		  (gnc:commodity-collector-add total acct-comm shares)
+		  )
+		)
+	 splits
+	 )
+    (gnc:free-query query)
+    total
+    )
+  )
+
+;; similar, but only counts transactions with non-negative shares and
+;; *ignores* any closing entries
+(define (gnc:account-get-pos-trans-total-interval
+	 group type start-date-tp end-date-tp)
+  (let* ((str-query (gnc:malloc-query))
+	 (sign-query (gnc:malloc-query))
+	 (total-query #f)
+         (splits #f)
+	 (get-val (lambda (alist key)
+		    (let ((lst (assoc-ref alist key)))
+		      (if lst (car lst) lst))))
+	 (matchstr (get-val type 'str))
+	 (case-sens (if (get-val type 'cased) 1 0))
+	 (regexp (if (get-val type 'regexp) 1 0))
+	 (pos? (if (get-val type 'positive) #t #f))
+         (total (gnc:make-commodity-collector))
+         )
+    (gnc:query-set-book str-query (gnc:get-current-book))
+    (gnc:query-set-book sign-query (gnc:get-current-book))
+    (gnc:query-set-match-non-voids-only! str-query (gnc:get-current-book))
+    (gnc:query-set-match-non-voids-only! sign-query (gnc:get-current-book))
+    (gnc:query-add-account-match str-query group 'guid-match-any 'query-and)
+    (gnc:query-add-account-match sign-query group 'guid-match-any 'query-and)
+    (gnc:query-add-date-match-timepair
+     str-query
+     (and start-date-tp #t) start-date-tp
+     (and end-date-tp #t) end-date-tp 'query-and)
+    (gnc:query-add-date-match-timepair
+     sign-query
+     (and start-date-tp #t) start-date-tp
+     (and end-date-tp #t) end-date-tp 'query-and)
+    (gnc:query-add-description-match
+     str-query matchstr case-sens regexp 'query-and)
+    (set! total-query
+	  ;; this is a tad inefficient, but its a simple way to accomplish
+	  ;; description match inversion...
+	  (if pos?
+	      (gnc:query-merge sign-query str-query 'query-and)
+	      (gnc:query-merge
+	       sign-query (gnc:query-invert str-query) 'query-and)
+	      ))
+    
+    (set! splits (gnc:query-get-splits total-query))
+    (map (lambda (split)
+	   (let* ((shares (gnc:split-get-amount split))
+		  (acct-comm (gnc:account-get-commodity
+			      (gnc:split-get-account split)))
+		  )
+	     (or (gnc:numeric-negative-p shares)
+		 (gnc:commodity-collector-add total acct-comm shares)
+		 )
+	     )
+	   )
+         splits
+         )
+    (gnc:free-query total-query)
+    total
+    )
+  )
+
+;; utility to assist with double-column balance tables
+;; a request is made with the <req> argument
+;; <req> may currently be 'entry|'debit-q|'credit-q|'zero-q|'debit|'credit
+;; 'debit-q|'credit-q|'zero-q tests the sign of the balance
+;; 'side returns 'debit or 'credit, the column in which to display
+;; 'debt|'credit return the entry, if appropriate, or #f
+(define (gnc:double-col
+	 req signed-balance report-commodity exchange-fn show-comm?)
+  (let* ((sum (and signed-balance
+		   (gnc:sum-collector-commodity
+		    signed-balance
+		    report-commodity
+		    exchange-fn)))
+	 (amt (and sum (gnc:gnc-monetary-amount sum)))
+	 (neg? (and amt (gnc:numeric-negative-p amt)))
+	 (bal (if neg?
+		  (let ((bal (gnc:make-commodity-collector)))
+		    (bal 'minusmerge signed-balance #f)
+		    bal)
+		  signed-balance))
+	 (bal-sum (gnc:sum-collector-commodity
+		   bal
+		   report-commodity
+		   exchange-fn))
+	 (balance
+	  (if (gnc:uniform-commodity? bal report-commodity)
+	      (if (gnc:numeric-zero-p amt) #f bal-sum)
+	      (if show-comm?
+		  (gnc:commodity-table bal report-commodity exchange-fn)
+		  bal-sum)
+	      ))
+	 )
+    (car (assoc-ref
+	  (list
+	   (list 'entry balance)
+	   (list 'debit (if neg? #f balance))
+	   (list 'credit (if neg? balance #f))
+	   (list 'zero-q (if neg? #f (if balance #f #t)))
+	   (list 'debit-q (if neg? #f (if balance #t #f)))
+	   (list 'credit-q (if neg? #t #f))
+	   )
+	  req
+	  ))
+    )
+  )
+
Index: html-acct-table.scm
===================================================================
RCS file: /home/cvs/cvsroot/gnucash/src/report/report-system/html-acct-table.scm,v
retrieving revision 1.1.2.1
retrieving revision 1.1.2.2
diff -Lsrc/report/report-system/html-acct-table.scm -Lsrc/report/report-system/html-acct-table.scm -u -r1.1.2.1 -r1.1.2.2
--- src/report/report-system/html-acct-table.scm
+++ src/report/report-system/html-acct-table.scm
@@ -62,7 +62,7 @@
 ;; 
 ;; The list of accounts which are to be placed in the
 ;; gnc:html-acct-table object can be controled with the
-;; gnc:make-html-acct-table/accts, gnc:make-html-acct-table/accts/env,
+;; gnc:make-html-acct-table/accts, gnc:make-html-acct-table/env/accts,
 ;; and gnc:html-table-add-accts!  functions.  
 ;; 
 ;; The gnc:html-acct-table parameters, set with
@@ -171,6 +171,27 @@
 ;;          account having a balance of zero. otherwise, a row will be
 ;;          generated for the account.
 ;; 
+;;     balance-mode: 'pre-adjusting 'pre-closing 'post-closing
+;;
+;;          indicates whether or not to ignore adjusting/closing
+;;          entries when computing account balances. 'pre-closing
+;;          ignores only closing entries. 'pre-adjusting also ignores
+;;          adjusting entries. 'post-closing counts all entries.
+;; 
+;;     adjusting-pattern: alist of 'str 'cased 'regexp
+;; 
+;;          a pattern alist, as accepted by
+;;          gnc:account-get-trans-type-balance-interval, matching
+;;          adjusting transactions to be ignored when balance-mode is
+;;          'pre-adjusting.
+;; 
+;;     closing-pattern: alist of 'str 'cased 'regexp
+;; 
+;;          a pattern alist, as accepted by
+;;          gnc:account-get-trans-type-balance-interval, matching
+;;          closing transactions to be ignored when balance-mode is
+;;          'pre-closing.
+;; 
 ;;     account-type: unimplemented
 ;;     account-class: unimplemented
 ;;     row-thunk: unimplemented (for gnc:html-acct-table-render)
@@ -507,6 +528,21 @@
 			  'show-leaf-acct)
 		      ))
 	 (label-mode (or (get-val env 'account-label-mode) 'anchor))
+	 (balance-mode (or (get-val env 'balance-mode) 'post-closing))
+	 (closing-pattern (or (get-val env 'closing-pattern)
+			      (list
+			       (list 'str (N_ "Closing Entries"))
+			       (list 'cased #f)
+			       (list 'regexp #f)
+			       )
+			      ))
+	 (adjusting-pattern (or (get-val env 'adjusting-pattern)
+				(list
+				 (list 'str (N_ "Adjusting Entries"))
+				 (list 'cased #f)
+				 (list 'regexp #f)
+				 )
+				))
 	 ;; local variables
 	 (toplvl-accts (gnc:group-get-account-list (gnc:get-current-group)))
 	 (acct-depth-reached 0)
@@ -522,14 +558,45 @@
 	     )
 	)
       
-      ;; the following two functions were lifted directly
-      ;; from html-utilities.scm
+      ;; the following function was adapted from html-utilities.scm
       (define (my-get-balance-nosub account start-date end-date)
-	(if start-date
-	    (gnc:account-get-comm-balance-interval
-	     account start-date end-date #f)
-	    (gnc:account-get-comm-balance-at-date
-	     account end-date #f)))
+	(let* ((post-closing-bal
+		(if start-date
+		    (gnc:account-get-comm-balance-interval
+		     account start-date end-date #f)
+		    (gnc:account-get-comm-balance-at-date
+		     account end-date #f)))
+	       (closing (lambda(a)
+			  (gnc:account-get-trans-type-balance-interval
+			   (list account) closing-pattern
+			   start-date end-date)
+			  )
+			)
+	       (adjusting (lambda(a)
+			    (gnc:account-get-trans-type-balance-interval
+			     (list account) adjusting-pattern
+			     start-date end-date)
+			    )
+			  )
+	       )
+	  (or (and (equal? balance-mode 'post-closing) post-closing-bal)
+	      (and (equal? balance-mode 'pre-closing)
+		   (let* ((closing-amt (closing account))
+			  )
+		     (post-closing-bal 'minusmerge closing-amt #f)
+		     post-closing-bal)
+		   )
+	      (and (equal? balance-mode 'pre-adjusting)
+		   (let* ((closing-amt (closing account))
+			  (adjusting-amt (adjusting account))
+			  )
+		     (post-closing-bal 'minusmerge closing-amt #f)
+		     (post-closing-bal 'minusmerge adjusting-amt #f)
+		     post-closing-bal)
+		   )
+	      )
+	  )
+	)
       
       ;; Additional function that includes the subaccounts as
       ;; well. Note: It is necessary to define this here (instead of
@@ -741,10 +808,12 @@
 (define (gnc:html-acct-table-get-cell acct-table row col)
   ;; we'll only ever store one object in an html-table-cell
   ;; returns the first object stored in that cell
-  (car (gnc:html-table-cell-data
-	(gnc:html-table-get-cell
-	 (gnc:_html-acct-table-matrix_ acct-table)
-	 row (+ col 1)))))
+  (let* ((cell (gnc:html-table-get-cell
+		(gnc:_html-acct-table-matrix_ acct-table)
+		row (+ col 1))))
+    (and cell (car (gnc:html-table-cell-data cell)))
+    )
+  )
 
 (define (gnc:html-acct-table-set-cell! acct-table row col obj)
   (gnc:html-table-set-cell!
@@ -753,7 +822,8 @@
    obj))
 
 (define (gnc:html-acct-table-get-row-env acct-table row)
-  (gnc:html-acct-table-get-cell acct-table row -1))
+  (gnc:html-acct-table-get-cell acct-table row -1)
+  )
 
 (define (gnc:html-acct-table-set-row-env! acct-table row env)
   (gnc:html-acct-table-set-cell! acct-table row -1 env))
@@ -888,21 +958,6 @@
     table)
   )
 
-(define (gnc:uniform-commodity? amt report-commodity)
-  ;; function to see if the commodity-collector amt
-  ;; contains any foreign commodities
-  (lambda (amt)
-    (let ((elts (gnc:commodity-collector-commodity-count amt))
-	  )
-      (or (equal? elts 0)
-	  (and (equal? elts 1)
-	       (gnc:commodity-collector-contains-commodity?
-		amt report-commodity)
-	       )
-	  )
-      )
-    ))
-
 ;; 
 ;; This function adds all the lines from a gnc:html-acct-table to a
 ;; gnc:html-table in "labeled amount" form.
--- /dev/null
+++ src/count.gplot
@@ -0,0 +1,26 @@
+#
+# file: count.gplot
+# function: plot the number of lines of code in gnucash as function of date
+# To generate the graph, say "gnuplot count.gplot" at the command line
+#
+# history: created by Linas Vepstas July 2004
+#
+# set term x11
+# set term pbm
+# set term gif size 400,300
+set term pbm medium color
+set out 'count.png'
+set data style linespoints 
+set xdata time
+set timefmt "%d/%m/%Y"
+# set format x "%m/%y"
+set format x "%Y"
+set xrange ["01/09/1997":"01/12/2003"]
+set title "Number of Lines of code in GnuCash"
+set key right
+set xlabel "Year"
+set logscale y
+set ylabel "KLOC\nLogarithmic Scale"
+plot "count.dat" using 1:2	title "kloc"
+
+# pause 1000
--- /dev/null
+++ src/count.dat
@@ -0,0 +1,33 @@
+#
+# file: count.dat
+#
+# Raw data for the number of KLOC of code in gnucash,
+# as a function of date.  Taken from the web page
+# http://www.gnucash.org/en/sizing.phtml
+# format: day/month/year <tab> KLOC
+# plot this by saying "gnuplot count.gplot" at the command line
+#
+# xacc-0.9 Sept 97
+1/9/1997	8.8
+# xacc-0.9w Dec 97
+1/12/1997	16.2
+# xacc-1.0.17 Feb 98
+1/2/1998	18.3
+# gnucash-1.1.15 Aug 98
+1/8/1998	34.7
+# gnucash-1.2.2 Aug 99
+1/8/1999	39.0
+# gnucash-1.3.6 April 2000
+1/4/2000	95.1
+# gnucash-1.4.6 Sept 2000
+# 1/9/2000	101.9
+# gnucash-1.4.12 April 2001
+# 1/4/2001	108.2
+# gnucash-1.5.2 Sept 2000
+1/9/2000	114.2
+# gnucash-1.6.0 June 2001
+1/6/2001	193.9
+# gnucash-1.7.2 November 2002
+1/11/2002	297.1
+# gnucash-1.8.4 June 2003
+1/6/2003	385.5
Index: engine.texinfo
===================================================================
RCS file: /home/cvs/cvsroot/gnucash/src/doc/design/engine.texinfo,v
retrieving revision 1.48.4.1
retrieving revision 1.48.4.2
diff -Lsrc/doc/design/engine.texinfo -Lsrc/doc/design/engine.texinfo -u -r1.48.4.1 -r1.48.4.2
--- src/doc/design/engine.texinfo
+++ src/doc/design/engine.texinfo
@@ -42,25 +42,24 @@
 @section Introduction
 
 Splits (@pxref{Splits}), or "Ledger Entries" are the fundamental
-accounting units. Each Split consists of a quantity (number of dollar
-bills, number of shares, etc.), the value of that quantity expressed in
-a (possibly) different currency than the quantity, a Memo, a pointer to
+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 (@pxref{Key-Value Pair Frames}).
 
 Transactions (@pxref{Transactions}) embody the notion of "double entry"
-accounting. A Transaction consists of a date, a description, a number, a
-list of one or more Splits, and a key-value frame. When double-entry
-rules are enforced, the total value of the splits is zero. Note that if
-there is just one split, its value must be zero for double-entry
-accounting; this used to be used for storing prices, but with the advent
-of the Price DB, this is no longer the case. If there are two splits,
+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. Positive Split values are 'debits' and negative Split values are
-'credits'. Ensuring the Splits to 'add up' to zero causes a double-entry
-accounting system to always balance.
+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
@@ -85,13 +84,10 @@
 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 currency that is used for all splits in this account, and a
-pointer to the "security" used for all splits in this account. The
-"security" can be the name of a stock (e.g. "IBM", "McDonald's"), or
-another currency (e.g. "USD", "GBP").  The security is used during
-Transaction balancing to enable trading between accounts denominated in
-different currencies, or to, for example, move stocks from one Account
-to another.
+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" (@pxref{Account Groups}). By accounting
Index: advanced-portfolio.scm
===================================================================
RCS file: /home/cvs/cvsroot/gnucash/src/report/standard-reports/advanced-portfolio.scm,v
retrieving revision 1.5.2.2
retrieving revision 1.5.2.3
diff -Lsrc/report/standard-reports/advanced-portfolio.scm -Lsrc/report/standard-reports/advanced-portfolio.scm -u -r1.5.2.2 -r1.5.2.3
--- src/report/standard-reports/advanced-portfolio.scm
+++ src/report/standard-reports/advanced-portfolio.scm
@@ -41,6 +41,7 @@
 (define optname-price-source (N_ "Price Source"))
 (define optname-shares-digits (N_ "Share decimal places"))
 (define optname-zero-shares (N_ "Include accounts with no shares"))
+(define optname-include-gains (N_ "Include gains and losses"))
 
 (define (options-generator)
   (let* ((options (gnc:new-options)) 
@@ -78,6 +79,13 @@
       "e" (N_ "The number of decimal places to use for share numbers") 2
       0 6 0 1))
 
+    (gnc:register-option 
+     options 
+     (gnc:make-simple-boolean-option
+      gnc:pagename-general optname-include-gains "f" 
+      (N_ "Include splits with no shares for calculating money-in and money-out")
+      #f))
+
     ;; Account tab
     (add-option
      (gnc:make-account-list-option
@@ -127,7 +135,7 @@
     (string=? (gnc:split-get-guid s1) (gnc:split-get-guid s2)))
   
   (define (table-add-stock-rows table accounts to-date
-                                currency price-fn exchange-fn include-empty
+                                currency price-fn exchange-fn include-empty include-gains
                                 total-value total-moneyin total-moneyout
                                 total-gain)
 
@@ -178,7 +186,7 @@
                              ((same-split? s split) 
 			      ;; (gnc:debug "amount" (gnc:numeric-to-double (gnc:split-get-amount s)) )
                               (cond
-                                ((not (gnc:numeric-zero-p (gnc:split-get-amount s)))
+                              ((or include-gains (not (gnc:numeric-zero-p (gnc:split-get-amount s))))
                                  (unitscoll 'add commodity (gnc:split-get-amount s)) ;; Is the stock transaction?
                                  (if (< 0 (gnc:numeric-to-double
                                            (gnc:split-get-amount s)))
@@ -282,6 +290,8 @@
                                   gnc:optname-reportname))
         (include-empty (get-option gnc:pagename-accounts
                                   optname-zero-shares))
+        (include-gains (get-option gnc:pagename-general
+                                  optname-include-gains))
 
         (total-value    (gnc:make-commodity-collector))
         (total-moneyin  (gnc:make-commodity-collector))
@@ -330,7 +340,7 @@
           
           (table-add-stock-rows
            table accounts to-date currency price-fn exchange-fn
-           include-empty total-value total-moneyin total-moneyout total-gain)
+           include-empty include-gains total-value total-moneyin total-moneyout total-gain)
           
           (gnc:html-table-append-row/markup!
            table
Index: transaction.scm
===================================================================
RCS file: /home/cvs/cvsroot/gnucash/src/report/standard-reports/transaction.scm,v
retrieving revision 1.15.4.2
retrieving revision 1.15.4.3
diff -Lsrc/report/standard-reports/transaction.scm -Lsrc/report/standard-reports/transaction.scm -u -r1.15.4.2 -r1.15.4.3
--- src/report/standard-reports/transaction.scm
+++ src/report/standard-reports/transaction.scm
@@ -508,18 +508,13 @@
    (gnc:make-account-list-option
         gnc:pagename-accounts (N_ "Report Accounts")
         "a" (N_ "Report on these accounts")
-    (lambda ()
-      ;; FIXME : gnc:get-current-accounts disappeared.
-      (let ((current-accounts '())
-            (num-accounts (gnc:group-get-num-accounts
-                           (gnc:get-current-group)))
-            (first-account (gnc:group-get-account
-                            (gnc:get-current-group) 0)))
-        (cond ((not (null? current-accounts))
-               (list (car current-accounts)))
-              ((> num-accounts 0) (list first-account))
-              (else ()))))
-    #f #t))
+     ;; select, by default, all accounts...
+     (lambda ()
+       (gnc:filter-accountlist-type 
+	'(bank cash credit asset liability stock mutual-fund currency
+	       payable receivable equity income expense)
+	(gnc:group-get-subaccounts (gnc:get-current-group))))
+     #f #t))
   
       (gnc:register-trep-option
        (gnc:make-account-list-option
@@ -908,9 +903,9 @@
            (list
             (gnc:make-html-table-cell/size
              1 width (gnc:make-html-text (gnc:html-markup-hr)))))
-
-          (render-grand-total table width total-collector export?))
-
+	  (if (gnc:option-value (gnc:lookup-option options "Display" "Totals"))
+	      (render-grand-total table width total-collector export?)))
+	
         (let* ((current (car splits))
                (current-row-style (if multi-rows? def:normal-row-style
                                       (if odd-row? def:normal-row-style 
@@ -1315,7 +1310,8 @@
                   (_ "No matching transactions found"))
                  (gnc:html-markup-p
                   (_ "No transactions were found that \
-match the given time interval and account selection.")))
+match the time interval and account selection specified \
+in the Options panel.")))
                 (gnc:html-document-add-object! document p))))
 
         ;; error condition: no accounts specified
Index: balance-sheet.scm
===================================================================
RCS file: /home/cvs/cvsroot/gnucash/src/report/standard-reports/balance-sheet.scm,v
retrieving revision 1.11.4.3
retrieving revision 1.11.4.4
diff -Lsrc/report/standard-reports/balance-sheet.scm -Lsrc/report/standard-reports/balance-sheet.scm -u -r1.11.4.3 -r1.11.4.4
--- src/report/standard-reports/balance-sheet.scm
+++ src/report/standard-reports/balance-sheet.scm
@@ -18,18 +18,15 @@
 ;;    default) accounts representative of current & fixed assets &
 ;;    liabilities.
 ;;    
-;;    There are some gnc:html-acct-table options which remain unused,
-;;    mostly because I don't know how to make drop-down option
-;;    controls.
-;;    
-;;    This code makes the assumption that you want your equity
-;;    statement to no more than daily resolution.
+;;    This code makes the assumption that you want your balance
+;;    sheet to no more than daily resolution.
 ;;    
 ;;    The Company Name field does not currently default to the name
 ;;    in (gnc:get-current-book).
 ;;    
 ;;    Line & column alignments still do not conform with
 ;;    textbook accounting practice (they're close though!).
+;;    The 'canonically-tabbed option is currently broken.
 ;;    
 ;;    Progress bar functionality is currently mostly broken.
 ;;    
@@ -101,13 +98,12 @@
 (define opthelp-bottom-behavior
   (N_ "Displays accounts which exceed the depth limit at the depth limit"))
 
-(define optname-show-parent-balance (N_ "Show any balance in parent accounts"))
-(define opthelp-show-parent-balance (N_ "Show any balance in parent accounts"))
-;; FIXME optname-show-parent-balance needs immediate/recursive/omit choices
-(define optname-show-parent-total (N_ "Show parent account subtotals"))
-(define opthelp-show-parent-total
-  (N_ "Show account subtotals for all selected accounts having children"))
-;; FIXME optname-show-parent-total needs a 'canonically-tabbed choice
+(define optname-parent-balance-mode (N_ "Parent account balances"))
+(define opthelp-parent-balance-mode
+  (N_ "How to show any balance in parent accounts"))
+(define optname-parent-total-mode (N_ "Parent account subtotals"))
+(define opthelp-parent-total-mode
+  (N_ "How to show account subtotals for selected accounts having children"))
 
 (define optname-show-zb-accts (N_ "Include accounts with zero total balances"))
 (define opthelp-show-zb-accts
@@ -272,14 +268,36 @@
       gnc:pagename-display optname-omit-zb-bals
       "b" opthelp-omit-zb-bals #f))
     ;; what to show for non-leaf accounts
-    (add-option 
-     (gnc:make-simple-boolean-option
-      gnc:pagename-display optname-show-parent-balance 
-      "c" opthelp-show-parent-balance #t))
-    (add-option 
-     (gnc:make-simple-boolean-option
-      gnc:pagename-display optname-show-parent-total
-      "d" opthelp-show-parent-total #f))
+    (add-option
+     (gnc:make-multichoice-option
+      gnc:pagename-display optname-parent-balance-mode
+      "c" opthelp-parent-balance-mode
+      'immediate-bal
+      (list (vector 'immediate-bal
+		    (N_ "Show Immediate Balance")
+		    (N_ "Show only the balance in the parent account, excluding any subaccounts"))
+	    (vector 'recursive-bal
+		    (N_ "Recursive Balance")
+		    (N_ "Include subaccounts in balance"))
+	    (vector 'omit-bal
+		    (N_ "Omit Balance")
+		    (N_ "Do not show parent account balances")))))
+    (add-option
+     (gnc:make-multichoice-option
+      gnc:pagename-display optname-parent-total-mode
+      "d" opthelp-parent-total-mode
+      'f
+      (list (vector 't
+		    (N_ "Show subtotals")
+		    (N_ "Show subtotals for selected accounts which have subaccounts"))
+	    (vector 'f
+		    (N_ "Do not show subtotals")
+		    (N_ "Do not subtotal selected parent accounts"))
+	    (vector 'canonically-tabbed
+		    ;;(N_ "Subtotals indented text book style")
+		    (N_ "Text book style (experimental)")
+		    (N_ "Show parent account subtotals, indented per text book practice (experimental)")))))
+    
     ;; some detailed formatting options
     (add-option 
      (gnc:make-simple-boolean-option
@@ -325,7 +343,7 @@
   ;;;;;;;;;;;;;;;;;;;;;;;;;;;
 ;; balance-sheet-renderer
 ;; set up the document and add the table
-;; then then return the document or, if
+;; then return the document or, if
 ;; requested, export it to a file
   ;;;;;;;;;;;;;;;;;;;;;;;;;;;
 
@@ -362,10 +380,13 @@
                                  optname-show-foreign))
          (show-rates? (get-option pagename-commodities
                                   optname-show-rates))
-         (show-parent-balance? (get-option gnc:pagename-display
-                                           optname-show-parent-balance))
-         (show-parent-total? (get-option gnc:pagename-display
-                                         optname-show-parent-total))
+         (parent-balance-mode (get-option gnc:pagename-display
+                                           optname-parent-balance-mode))
+         (parent-total-mode
+	  (car
+	   (assoc-ref '((t #t) (f #f) (canonically-tabbed canonically-tabbed))
+		      (get-option gnc:pagename-display
+				  optname-parent-total-mode))))
          (show-zb-accts? (get-option gnc:pagename-display
 				     optname-show-zb-accts))
          (omit-zb-bals? (get-option gnc:pagename-display
@@ -409,7 +430,7 @@
 	 ;; (asset, liability, equity) have the same width.
          (tree-depth (if (equal? depth-limit 'all)
                          (gnc:get-current-group-depth) 
-                         depth-limit))
+			 depth-limit))
          ;; exchange rates calculation parameters
 	 (exchange-fn
 	  (gnc:case-exchange-fn price-source report-commodity date-tp))
@@ -420,6 +441,7 @@
     (define (add-subtotal-line table pos-label neg-label signed-balance)
       (define allow-same-column-totals #t)
       (let* ((neg? (and signed-balance
+			neg-label
 			(gnc:numeric-negative-p
 			 (gnc:gnc-monetary-amount
 			  (gnc:sum-collector-commodity
@@ -459,7 +481,7 @@
     
     ;;(gnc:warn "account names" liability-account-names)
     (gnc:html-document-set-title! 
-     doc (string-append report-title " " company-name " "
+     doc (string-append company-name " " report-title " "
 			(gnc:print-date date-tp))
      )
     
@@ -616,7 +638,7 @@
 						 'summarize))
 		 (list 'report-commodity report-commodity)
 		 (list 'exchange-fn exchange-fn)
-		 (list 'parent-account-subtotal-mode show-parent-total?)
+		 (list 'parent-account-subtotal-mode parent-total-mode)
 		 (list 'zero-balance-mode (if show-zb-accts?
 					      'show-leaf-acct
 					      'omit-leaf-acct))
@@ -627,11 +649,7 @@
 		)
 	  (set! params
 		(list
-		 (list 'parent-account-balance-mode
-		       (if show-parent-balance?
-			   'immediate-bal
-			   'omit-bal
-			   ))
+		 (list 'parent-account-balance-mode parent-balance-mode)
 		 (list 'zero-balance-display-mode (if omit-zb-bals?
 						      'omit-balance
 						      'show-balance))
--- /dev/null
+++ src/report/standard-reports/trial-balance.scm
@@ -0,0 +1,1154 @@
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;; trial-balance.scm: trial balance and work sheet
+;; By David Montenegro <sunrise2000 at comcast.net>
+;; 
+;; Prepares a trial balance of your books.
+;; Optionally prepares a complete work sheet.
+;; 
+;; N.B.: Since GnuCash ensures that all your debits and credits
+;; balance, preparing a Trial Balance isn't technically necessary for
+;; GnuCash users.  This report is included primarily for pedagogical
+;; and corroborative purposes.
+;; 
+;; BUGS:
+;; 
+;;    This code makes the assumption that you want your trial
+;;    balance to no more than daily resolution.
+;;    
+;;    The Company Name field does not currently default to the name
+;;    in (gnc:get-current-book).
+;;    
+;;    Progress bar functionality is currently mostly broken.
+;;    
+;;    Unsure if the multi-currency support is correct.
+;;    
+;;    The variables in this code could use more consistent naming.
+;;    
+;;    See also any "FIXME"s in the code.
+;; 
+;; Largely borrowed from balance-sheet.scm By Robert Merkel <rgmerk at mira.net>
+;;
+;; Largely borrowed from pnl.scm by:
+;; Christian Stimming <stimming at tu-harburg.de>
+;;
+;; This program is free software; you can redistribute it and/or    
+;; modify it under the terms of the GNU General Public License as   
+;; published by the Free Software Foundation; either version 2 of   
+;; the License, or (at your option) any later version.              
+;;                                                                  
+;; This program is distributed in the hope that it will be useful,  
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of   
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the    
+;; GNU General Public License for more details.                     
+;;                                                                  
+;; You should have received a copy of the GNU General Public License
+;; along with this program; if not, contact:
+;;
+;; Free Software Foundation           Voice:  +1-617-542-5942
+;; 59 Temple Place - Suite 330        Fax:    +1-617-542-2652
+;; Boston, MA  02111-1307,  USA       gnu at gnu.org
+;;
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+
+(define-module (gnucash report trial-balance))
+(use-modules (gnucash main)) ;; FIXME: delete after we finish modularizing.
+(use-modules (ice-9 slib))
+(use-modules (gnucash gnc-module))
+
+(gnc:module-load "gnucash/report/report-system" 0)
+
+(define reportname (N_ "Trial Balance"))
+
+;; define all option's names and help text so that they are properly
+;; defined in *one* place.
+(define optname-report-title (N_ "Report Title"))
+(define opthelp-report-title (N_ "Title for this report"))
+
+(define optname-party-name (N_ "Company name"))
+(define opthelp-party-name (N_ "Name of company/individual"))
+
+(define optname-start-date (N_ "Start of Adjusting/Closing"))
+(define opthelp-start-date
+  (N_ "The earliest date Adjusting/Closing entries were made for this period"))
+(define optname-end-date (N_ "Date of Report"))
+(define opthelp-end-date (N_ "Trial Balance/Work Sheet as-of date"))
+(define optname-report-variant (N_ "Report variation"))
+(define opthelp-report-variant (N_ "Kind of trial balance to generate"))
+;; FIXME this needs an indent option
+
+(define optname-accounts (N_ "Accounts to include"))
+(define opthelp-accounts
+  (N_ "Report on these accounts"))
+(define optname-depth-limit (N_ "Levels of Subaccounts"))
+(define opthelp-depth-limit
+  (N_ "Maximum number of levels in the account tree displayed"))
+
+(define pagename-merchandising (N_ "Merchandising"))
+(define optname-gross-adjustment-accounts (N_ "Gross adjustment accounts"))
+(define opthelp-gross-adjustment-accounts
+  (N_ "Do not net, but show gross debit/credit adjustments to these accounts. Merchandising businesses will normally select their inventory accounts here."))
+(define optname-income-summary-accounts (N_ "Income summary accounts"))
+(define opthelp-income-summary-accounts
+  (N_ "Adjustments made to these accounts are gross adjusted (see above) in the Adjustments, Adjusted Trial Balance, and Income Statement columns. Mostly useful for merchandising businesses."))
+
+(define pagename-entries (N_ "Entries"))
+(define optname-adjusting-pattern (N_ "Adjusting Entries pattern"))
+(define opthelp-adjusting-pattern
+  (N_ "Any text in the Description column which identifies adjusting entries"))
+(define optname-adjusting-casing
+  (N_ "Adjusting Entries pattern is case-sensitive"))
+(define opthelp-adjusting-casing
+  (N_ "Causes the Adjusting Entries Pattern match to be case-sensitive"))
+(define optname-adjusting-regexp
+  (N_ "Adjusting Entries Pattern is regular expression"))
+(define opthelp-adjusting-regexp
+  (N_ "Causes the Adjusting Entries Pattern to be treated as a regular expression"))
+
+(define optname-closing-pattern (N_ "Closing Entries pattern"))
+(define opthelp-closing-pattern
+  (N_ "Any text in the Description column which identifies closing entries"))
+(define optname-closing-casing
+  (N_ "Closing Entries pattern is case-sensitive"))
+(define opthelp-closing-casing
+  (N_ "Causes the Closing Entries Pattern match to be case-sensitive"))
+(define optname-closing-regexp
+  (N_ "Closing Entries Pattern is regular expression"))
+(define opthelp-closing-regexp
+  (N_ "Causes the Closing Entries Pattern to be treated as a regular expression"))
+
+;; FIXME: this option doesn't produce a correct work sheet when
+;; selected after closing... it omits adjusted temporary accounts
+;; 
+;; the fix for this really should involve passing thunks to
+;; gnc:make-html-acct-table
+(define optname-show-zb-accts (N_ "Include accounts with zero total balances"))
+(define opthelp-show-zb-accts
+  (N_ "Include accounts with zero total (recursive) balances in this report"))
+
+(define optname-account-links (N_ "Display accounts as hyperlinks"))
+(define opthelp-account-links (N_ "Shows each account in the table as a hyperlink to its register window"))
+
+(define pagename-commodities (N_ "Commodities"))
+(define optname-report-commodity (N_ "Report's currency"))
+(define optname-price-source (N_ "Price Source"))
+(define optname-show-foreign (N_ "Show Foreign Currencies"))
+(define opthelp-show-foreign
+  (N_ "Display any foreign currency amount in an account"))
+(define optname-show-rates (N_ "Show Exchange Rates"))
+(define opthelp-show-rates (N_ "Show the exchange rates used"))
+
+;; options generator
+(define (trial-balance-options-generator)
+  (let* ((options (gnc:new-options))
+         (add-option 
+          (lambda (new-option)
+            (gnc:register-option options new-option))))
+    
+    (add-option
+      (gnc:make-string-option
+      (N_ "General") optname-report-title
+      "a" opthelp-report-title reportname))
+    (add-option
+      (gnc:make-string-option
+      (N_ "General") optname-party-name
+      "b" opthelp-party-name (N_ "")))
+    ;; this should default to company name in (gnc:get-current-book)
+    
+    ;; the period over which to collect adjusting/closing entries and
+    ;; date at which to report the balance
+    (gnc:options-add-date-interval!
+     options gnc:pagename-general 
+     optname-start-date optname-end-date "c")
+    
+    (add-option
+     (gnc:make-multichoice-option
+      gnc:pagename-general optname-report-variant
+      "d" opthelp-report-variant
+      'current
+      (list (vector 'current
+		    (N_ "Current Trial Balance")
+		    (N_ "Uses the exact balances in the general ledger"))
+	    (vector 'pre-adj
+		    (N_ "Pre-adjustment Trial Balance")
+		    (N_ "Ignores Adjusting/Closing entries"))
+	    (vector 'work-sheet
+		    (N_ "Work Sheet")
+		    (N_ "Creates a complete end-of-period work sheet")))))
+    
+    ;; accounts to work on
+    (add-option
+     (gnc:make-account-list-option
+      gnc:pagename-accounts optname-accounts
+      "a"
+      opthelp-accounts
+      (lambda ()
+	(gnc:filter-accountlist-type 
+	 '(bank cash credit asset liability stock mutual-fund currency
+		payable receivable equity income expense)
+	 (gnc:group-get-subaccounts (gnc:get-current-group))))
+      #f #t))
+    (gnc:options-add-account-levels!
+     options gnc:pagename-accounts optname-depth-limit
+     "b" opthelp-depth-limit 1)
+
+    ;; options for merchandising business work sheets
+    (add-option
+     (gnc:make-account-list-option
+      pagename-merchandising optname-gross-adjustment-accounts
+      "c"
+      opthelp-gross-adjustment-accounts
+      (lambda ()
+	;; Here, it would be useful to have an inventory account type.
+	;; Lacking that, just select no accounts by default.
+	'()
+	)
+      #f #t))
+    (add-option
+     (gnc:make-account-list-option
+      pagename-merchandising optname-income-summary-accounts
+      "d"
+      opthelp-income-summary-accounts
+      (lambda ()
+	'()
+	)
+      #f #t))
+     
+    ;; all about currencies
+    (gnc:options-add-currency!
+     options pagename-commodities
+     optname-report-commodity "a")
+    
+    (gnc:options-add-price-source! 
+     options pagename-commodities
+     optname-price-source "b" 'weighted-average)
+    
+    (add-option 
+     (gnc:make-simple-boolean-option
+      pagename-commodities optname-show-foreign 
+      "c" opthelp-show-foreign #f))
+    
+    (add-option 
+     (gnc:make-simple-boolean-option
+      pagename-commodities optname-show-rates
+      "d" opthelp-show-rates #f))
+    
+    ;; adjusting/closing entry match criteria
+    ;; 
+    ;; N.B.: transactions really should have a field where we can put
+    ;; transaction types like "Adjusting/Closing/Correcting Entries"
+    (add-option
+      (gnc:make-string-option
+      pagename-entries optname-adjusting-pattern
+      "a" opthelp-adjusting-pattern (N_ "Adjusting Entries")))
+    (add-option
+     (gnc:make-simple-boolean-option
+      pagename-entries optname-adjusting-casing
+      "b" opthelp-adjusting-casing #f))
+    (add-option
+     (gnc:make-simple-boolean-option
+      pagename-entries optname-adjusting-regexp
+      "c" opthelp-adjusting-regexp #f))
+    (add-option
+      (gnc:make-string-option
+      pagename-entries optname-closing-pattern
+      "d" opthelp-closing-pattern (N_ "Closing Entries")))
+    (add-option
+     (gnc:make-simple-boolean-option
+      pagename-entries optname-closing-casing
+      "e" opthelp-closing-casing #f))
+    (add-option
+     (gnc:make-simple-boolean-option
+      pagename-entries optname-closing-regexp
+      "f" opthelp-closing-regexp #f))
+    
+    ;; what to show for zero-balance accounts
+    ;;(add-option 
+    ;; (gnc:make-simple-boolean-option
+    ;;  gnc:pagename-display optname-show-zb-accts
+    ;;  "a" opthelp-show-zb-accts #t))
+    
+    ;; some detailed formatting options
+    (add-option 
+     (gnc:make-simple-boolean-option
+      gnc:pagename-display optname-account-links
+      "e" opthelp-account-links #t))
+    
+    ;; Set the accounts page as default option tab
+    (gnc:options-set-default-section options gnc:pagename-display)
+    
+    options))
+
+  ;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;; trial-balance-renderer
+;; set up the document and add the table
+;; then then return the document or, if
+;; requested, export it to a file
+  ;;;;;;;;;;;;;;;;;;;;;;;;;;;
+
+(define (trial-balance-renderer report-obj choice filename)
+  (define (get-option pagename optname)
+    (gnc:option-value
+     (gnc:lookup-option 
+      (gnc:report-options report-obj) pagename optname)))
+  (define forever-ago (cons 0 0))
+  
+  (gnc:report-starting reportname)
+  
+  ;; get all option's values
+  (let* (
+	 (report-title (get-option gnc:pagename-general optname-report-title))
+	 (company-name (get-option gnc:pagename-general optname-party-name))
+         (start-date-printable (gnc:date-option-absolute-time
+				(get-option gnc:pagename-general
+					    optname-start-date)))
+         (start-date-tp (gnc:timepair-end-day-time
+			 (gnc:timepair-previous-day start-date-printable)))
+         (end-date-tp (gnc:timepair-end-day-time 
+		       (gnc:date-option-absolute-time
+			(get-option gnc:pagename-general
+				    optname-end-date))))
+         (report-variant (get-option gnc:pagename-general
+				     optname-report-variant))
+         (accounts (get-option gnc:pagename-accounts
+                               optname-accounts))
+         (ga-accounts (get-option pagename-merchandising
+				  optname-gross-adjustment-accounts))
+         (is-accounts (get-option pagename-merchandising
+				  optname-income-summary-accounts))
+	 (depth-limit (get-option gnc:pagename-accounts 
+				  optname-depth-limit))
+	 (adjusting-str (get-option pagename-entries
+				    optname-adjusting-pattern))
+	 (adjusting-cased (get-option pagename-entries
+				      optname-adjusting-casing))
+	 (adjusting-regexp (get-option pagename-entries
+				       optname-adjusting-regexp))
+	 (closing-str (get-option pagename-entries
+				  optname-closing-pattern))
+	 (closing-cased (get-option pagename-entries
+				    optname-closing-casing))
+	 (closing-regexp (get-option pagename-entries
+				     optname-closing-regexp))
+         (report-commodity (get-option pagename-commodities
+				       optname-report-commodity))
+         (price-source (get-option pagename-commodities
+                                   optname-price-source))
+         (show-fcur? (get-option pagename-commodities
+                                 optname-show-foreign))
+         (show-rates? (get-option pagename-commodities
+                                  optname-show-rates))
+         ;;(show-zb-accts? (get-option gnc:pagename-display
+	 ;;			     optname-show-zb-accts))
+	 (show-zb-accts? #t) ;; see FIXME above
+         (use-links? (get-option gnc:pagename-display
+				 optname-account-links))
+	 (indent 0)
+	 
+         ;; decompose the account list
+         (split-up-accounts (gnc:decompose-accountlist accounts))
+         (asset-accounts
+	  (assoc-ref split-up-accounts 'asset))
+         (liability-accounts
+	  (assoc-ref split-up-accounts 'liability))
+         (equity-accounts
+          (assoc-ref split-up-accounts 'equity))
+         (income-expense-accounts
+          (append (assoc-ref split-up-accounts 'income)
+                  (assoc-ref split-up-accounts 'expense)))
+	 ;; (all-accounts (map (lambda (X) (cadr X)) split-up-accounts))
+	 ;; ^ will not do what we want
+	 (all-accounts
+	  (append asset-accounts liability-accounts
+		  equity-accounts income-expense-accounts))
+	 
+	 ;; same for gross adjustment accounts...
+	 (split-up-ga-accounts (gnc:decompose-accountlist ga-accounts))
+	 (all-ga-accounts
+          (append (assoc-ref split-up-ga-accounts 'asset)
+                  (assoc-ref split-up-ga-accounts 'liability)
+                  (assoc-ref split-up-ga-accounts 'equity)
+                  (assoc-ref split-up-ga-accounts 'income)
+                  (assoc-ref split-up-ga-accounts 'expense)))
+	 (split-up-is-accounts (gnc:decompose-accountlist is-accounts))
+	 
+	 ;; same for income statement accounts...
+	 (all-is-accounts
+          (append (assoc-ref split-up-is-accounts 'asset)
+                  (assoc-ref split-up-is-accounts 'liability)
+                  (assoc-ref split-up-is-accounts 'equity)
+                  (assoc-ref split-up-is-accounts 'income)
+                  (assoc-ref split-up-is-accounts 'expense)))
+	 
+	 (doc (gnc:make-html-document))
+         ;; exchange rates calculation parameters
+	 (exchange-fn
+	  (gnc:case-exchange-fn price-source report-commodity end-date-tp))
+	 (terse-period? #t)
+	 (period-for (if terse-period?
+			 (string-append " " (N_ "for Period"))
+			 (string-append
+			  ", "
+			  (gnc:print-date start-date-printable) " "
+			  (N_ "to") " "
+			  (gnc:print-date end-date-tp)
+			  )))
+	 )
+    
+    (gnc:html-document-set-title! 
+     doc (if (equal? report-variant 'current)
+	     (sprintf #f (string-append "%s %s %s")
+		      company-name report-title
+		      (gnc:print-date end-date-tp))
+	     (sprintf #f (string-append "%s %s "
+					(N_ "For Period Covering")
+					" %s "
+					(N_ "to")
+					" %s")
+		      company-name report-title
+		      (gnc:print-date start-date-printable)
+		      (gnc:print-date end-date-tp))
+	     )
+     )
+    
+    (if (null? accounts)
+	
+        ;; error condition: no accounts specified
+	;; is this *really* necessary??
+	;; i'd be fine with an all-zero trial balance
+	;; that would, technically, be correct....
+        (gnc:html-document-add-object! 
+         doc 
+         (gnc:html-make-no-account-warning 
+	  reportname (gnc:report-id report-obj)))
+	
+        ;; Get all the balances for each account group.
+        (let* ((build-table (gnc:make-html-table))
+	       (acct-table #f)
+	       (debit-tot (gnc:make-commodity-collector))
+	       (credit-tot (gnc:make-commodity-collector))
+               (unrealized-gain-collector #f)
+               (neg-unrealized-gain-collector #f)
+	       (book-balance #f) ;; assets - liabilities - equity, norm 0
+	       (table-env #f)    ;; parameters for :make-
+	       (account-cols #f)
+	       (indented-depth #f)
+	       (header-rows 0)
+	       (adj-debits (gnc:make-commodity-collector))
+	       (adj-credits (gnc:make-commodity-collector))
+	       (atb-debits (gnc:make-commodity-collector))
+	       (atb-credits (gnc:make-commodity-collector))
+	       (is-debits (gnc:make-commodity-collector))
+	       (is-credits (gnc:make-commodity-collector))
+	       (bs-debits (gnc:make-commodity-collector))
+	       (bs-credits (gnc:make-commodity-collector))
+	       )
+	  
+	  ;; Wrapper to call gnc:html-table-add-labeled-amount-line!
+	  ;; with the proper arguments.
+	  ;; (This is used to fill in the Trial Balance columns.)
+	  (define (add-line table label signed-balance)
+	    (let* ((entry (gnc:double-col
+			   'entry signed-balance
+			   report-commodity exchange-fn show-fcur?))
+		   (credit? (gnc:double-col
+			     'credit-q signed-balance
+			     report-commodity exchange-fn show-fcur?))
+		   )
+	      (gnc:html-table-add-labeled-amount-line!
+	       table
+	       (+ account-cols 2)
+	       "primary-subheading"
+	       #f
+	       label indented-depth 1 "text-cell"
+	       entry
+	       (+ account-cols (if credit? 1 0)) 1 "number-cell"
+	       )
+	      ;; update the running totals
+	      (if credit?
+		  (credit-tot 'minusmerge signed-balance #f)
+		  (debit-tot 'merge signed-balance #f)
+		  )
+	      )
+	    )
+	  
+	  (define (get-val alist key)
+	    (let ((lst (assoc-ref alist key)))
+	      (if lst (car lst) lst)))
+	  
+	  (define pa-col  0) ;; pre-adjustments column
+	  (define adj-col 1) ;; adjustments column
+	  (define atb-col 2) ;; adjusted trial balance column
+	  (define is-col  3) ;; income statement column
+	  (define bs-col  4) ;; balance sheet column
+	  (define bal-col 5) ;; for the current (general ledger) balance
+	  
+	  (define (report-val amt)
+	    (gnc:sum-collector-commodity
+	     amt report-commodity exchange-fn)
+	    )
+
+	  ;; Returns a gnc:html-table-cell containing the absolute value
+	  ;; of the given amount in the report commodity.
+	  (define (tot-abs-amt-cell amt)
+	    (let* ((neg-amt (gnc:make-commodity-collector))
+		   (rv (report-val amt))
+		   (neg? (gnc:numeric-negative-p
+			  (gnc:gnc-monetary-amount rv)))
+		   (cell #f)
+		   )
+	      (neg-amt 'minusmerge amt #f)
+	      (set! cell
+		    (gnc:make-html-table-cell/markup
+		     "total-number-cell" (if neg? (report-val neg-amt) rv)))
+	      (gnc:html-table-cell-set-style!
+	       cell "total-number-cell"
+	       'attribute '("align" "right")
+	       'attribute '("valign" "top")
+	       )
+	      cell)
+	    )
+	  
+	  ;; set default cell alignment
+	  (gnc:html-table-set-style!
+	   build-table "td"
+	   'attribute '("align" "right")
+	   'attribute '("valign" "top")
+	   )
+	  
+	  (gnc:report-percent-done 4)
+	  ;; sum any unrealized gains
+	  ;; 
+	  ;; Hm... unrealized gains....  This is when you purchase
+	  ;; something and its value increases/decreases (prior to
+	  ;; your selling it) and you have to reflect that on your
+	  ;; balance sheet.
+	  ;; 
+	  ;; I *think* a decrease in the value of a liability or
+	  ;; equity constitutes an unrealized loss.  I'm unsure about
+	  ;; that though....
+	  ;; 
+	  (set! book-balance (gnc:make-commodity-collector))
+	  (map (lambda (acct)
+		 (book-balance
+		  'merge
+		  (gnc:account-get-comm-balance-at-date acct end-date-tp #f)
+		  #f)
+		 )
+	       all-accounts)
+          (set! unrealized-gain-collector (gnc:make-commodity-collector))
+          (let* ((weighted-fn
+                  (gnc:case-exchange-fn 'weighted-average
+                                        report-commodity end-date-tp))
+		 
+                 (value
+                  (gnc:gnc-monetary-amount
+                   (gnc:sum-collector-commodity book-balance
+                                                report-commodity
+                                                exchange-fn)))
+		 
+                 (cost
+                  (gnc:gnc-monetary-amount
+                   (gnc:sum-collector-commodity book-balance
+                                                report-commodity
+                                                weighted-fn)))
+		 
+                 (unrealized-gain (gnc:numeric-sub-fixed value cost)))
+	    
+            (unrealized-gain-collector 'add report-commodity unrealized-gain)
+	    )
+	  (set! neg-unrealized-gain-collector (gnc:make-commodity-collector))
+	  (neg-unrealized-gain-collector 'minusmerge
+					 unrealized-gain-collector
+					 #f)
+	  (set! table-env
+		(list
+		 (list 'start-date #f)
+		 (list 'end-date end-date-tp)
+		 (list 'display-tree-depth
+		       (if (integer? depth-limit) depth-limit #f))
+		 (list 'depth-limit-behavior 'flatten)
+		 (list 'report-commodity report-commodity)
+		 (list 'exchange-fn exchange-fn)
+		 (list 'parent-account-subtotal-mode #f)
+		 (list 'zero-balance-mode (if show-zb-accts?
+					      'show-leaf-acct
+					      'omit-leaf-acct))
+		 (list 'account-label-mode (if use-links?
+					       'anchor
+					       'name))
+		 )
+		)
+	  
+	  (set! acct-table
+		(gnc:make-html-acct-table/env/accts table-env all-accounts))
+	  
+	  (gnc:report-percent-done 80)
+	  (let* ((env (gnc:html-acct-table-get-row-env acct-table 0)))
+	    (set! account-cols (get-val env 'account-cols))
+	    )
+	  
+	  ;; Workaround to force gtkhtml into displaying wide
+	  ;; enough columns.
+	  (let ((space
+		 (make-list
+		  (+ account-cols
+		     (if (equal? report-variant 'work-sheet) 10 2))
+		  "&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;")
+		 ))
+	    (gnc:html-table-append-row! build-table space)
+	    (set! header-rows (+ header-rows 1))
+	    )
+	  ;; add the double-column headers if required
+	  (if (equal? report-variant 'work-sheet)
+	      (let* ((headings
+		      (list
+		       (N_ "TRIAL BALANCE")
+		       (N_ "ADJUSTMENTS")
+		       (N_ "ADJUSTED TRIAL BALANCE")
+		       (N_ "INCOME STATEMENT")
+		       (N_ "BALANCE SHEET")
+		       ))
+		     (parent-headings #f)
+		     )
+		(set! parent-headings
+		      (apply append
+			     (map
+			      (if gnc:colspans-are-working-right
+				  (lambda (heading)
+				    (list 
+				     (gnc:make-html-table-cell/size/markup
+				      1 2 "th" heading)
+				     )
+				    )
+				  (lambda (heading)
+				    (list
+				     (gnc:make-html-table-cell/size/markup
+				      1 1 "th" heading)
+				     (gnc:html-make-empty-cell)
+				     )
+				    )
+				  )
+			      headings)
+			     )
+		      )
+		(gnc:html-table-append-row!
+		 build-table
+		 (append
+		  (if gnc:colspans-are-working-right
+		      (list (gnc:make-html-table-cell/size 1 account-cols #f))
+		      (gnc:html-make-empty-cells account-cols)
+		      )
+		  parent-headings)
+		 )
+		(set! header-rows (+ header-rows 1))
+		)
+	      )
+	  ;; add the DEBIT/CREDIT headers
+	  (let* ((debit-cell
+		  (gnc:make-html-table-cell/markup
+		   "th" (N_ "DEBIT")))
+		 (credit-cell
+		  (gnc:make-html-table-cell/markup
+		   "th" (N_ "CREDIT")))
+		 (row (append
+		       (list (gnc:make-html-table-cell/markup
+			      "total-label-cell" (N_ "Account Title")))
+		       (gnc:html-make-empty-cells (- account-cols 1))
+		       (list debit-cell)
+		       (list credit-cell))
+		      )
+		 (ws-col 0)
+		 )
+	    (if (equal? report-variant 'work-sheet)
+		(let ((rownum 0)
+		      (ws-cols 4)
+		      )
+		  (while (< rownum ws-cols)
+			 (set! row (append row (list debit-cell credit-cell)))
+			 (set! rownum (+ rownum 1))
+			 )
+		  )
+		)
+	    (gnc:html-table-append-row!
+	     build-table
+	     row
+	     )
+	    (set! header-rows (+ header-rows 1))
+	    )
+	  
+	  ;; now, for each account, calculate all the column values
+	  ;; and store them in the utility object...
+	  ;; 
+	  ;; this handles merchandising (inventory and income summary)
+	  ;; accounts specially. instead of storing a commodity collector,
+	  ;; it stores a two-element list of commodity collectors:
+	  ;;  (list debit-collector credit-collector)
+	  (let ((row 0)
+		(rows (gnc:html-acct-table-num-rows acct-table))
+		)
+	    (while (< row rows)
+		   (let* ((env
+			   (gnc:html-acct-table-get-row-env acct-table row))
+			  (acct (get-val env 'account))
+			  (group (list acct))
+			  (curr-bal (get-val env 'account-bal))
+			  (closing
+			   (gnc:account-get-trans-type-balance-interval
+			    group
+			    (list (list 'str closing-str)
+				  (list 'cased closing-cased)
+				  (list 'regexp closing-regexp)
+				  )
+			    start-date-tp end-date-tp
+			    ))
+			  (adjusting
+			   (gnc:account-get-trans-type-balance-interval
+			    group
+			    (list (list 'str adjusting-str)
+				  (list 'cased adjusting-cased)
+				  (list 'regexp adjusting-regexp)
+				  )
+			    start-date-tp end-date-tp
+			    ))
+			  (is? (member acct all-is-accounts))
+			  (ga-or-is? (or (member acct all-ga-accounts) is?))
+			  (pos-adjusting
+			   (and ga-or-is?
+				adjusting
+				(gnc:account-get-pos-trans-total-interval
+				 group
+				 (list (list 'str adjusting-str)
+				       (list 'cased adjusting-cased)
+				       (list 'regexp adjusting-regexp)
+				       (list 'positive #t)
+				       )
+				 start-date-tp end-date-tp
+				 )
+				))
+			  (neg-adjusting
+			   (and pos-adjusting (gnc:make-commodity-collector)))
+			  (pre-closing-bal (gnc:make-commodity-collector))
+			  (pre-adjusting-bal (gnc:make-commodity-collector))
+			  (atb #f) ;; adjusted trial balance
+			  )
+		     
+		     ;; +P_ADJ + -N_ADJ = xADJ. xADJ - +P_ADJ = -N_ADJ.
+		     ;; That is, credit values are stored as such (negative).
+		     (if neg-adjusting
+			 (begin
+			   (neg-adjusting 'merge adjusting #f)
+			   (neg-adjusting 'minusmerge pos-adjusting #f)
+			   ))
+		     
+		     (pre-closing-bal 'merge curr-bal #f)
+		     ;; remove closing entries
+		     (pre-closing-bal 'minusmerge closing #f)
+		     (pre-adjusting-bal 'merge pre-closing-bal #f)
+		     ;; remove closing entries
+		     (pre-adjusting-bal 'minusmerge adjusting #f)
+		     ;; we now have a pre-adjusting-bal,
+		     ;; pre-closing-bal, and curr-bal
+		     
+		     (set! atb
+			   ;; calculate the adjusted trial balance to use
+			   ;; this depends on whether or not we are netting
+			   ;; the atb value... so we check is?.
+			   (if is?
+			       (let* ((debit (gnc:make-commodity-collector))
+				      (credit (gnc:make-commodity-collector))
+				      )
+				 (debit 'merge pos-adjusting #f)
+				 (credit 'merge neg-adjusting #f)
+				 (if (gnc:double-col
+				      'credit-q pre-adjusting-bal
+				      report-commodity exchange-fn show-fcur?)
+				     (credit 'merge pre-adjusting-bal #f)
+				     (debit 'merge pre-adjusting-bal #f)
+				     )
+				 (list debit credit)
+				 )
+			       pre-closing-bal)
+			   )
+		     
+		     (gnc:html-acct-table-set-cell!
+		      acct-table row pa-col pre-adjusting-bal)
+		     (gnc:html-acct-table-set-cell!
+		      acct-table row adj-col
+		      (if ga-or-is?
+			  (list pos-adjusting neg-adjusting)
+			  adjusting)
+		      )
+		     (gnc:html-acct-table-set-cell!
+		      acct-table row atb-col atb)
+		     (gnc:html-acct-table-set-cell!
+		      acct-table row
+		      (if (or (gnc:account-is-inc-exp? acct) is?)
+			  is-col bs-col)
+		      atb
+		      )
+		     (gnc:html-acct-table-set-cell!
+		      acct-table row bal-col curr-bal)
+		     
+		     (set! row (+ row 1))
+		     )
+		   )
+	    )
+	  
+	  ;; next, set up the account tree and pre-adjustment balances
+	  ;; (This fills in the Account Title and Trial Balance columns.)
+	  (let ((row 0)
+		(rows (gnc:html-acct-table-num-rows acct-table)))
+	    (while (< row rows)
+		   (let* ((env
+			   (gnc:html-acct-table-get-row-env acct-table row))
+			  (account-bal
+			   (gnc:html-acct-table-get-cell
+			    acct-table
+			    row
+			    (get-val (list (list 'pre-adj pa-col)
+					   (list 'work-sheet pa-col)
+					   (list 'current bal-col)
+					   )
+				     report-variant)
+			    ))
+			  (label (get-val env 'account-label))
+			  )
+		     ;; yeah, i know, global vars are devil... so deal with it
+		     (set! indented-depth (get-val env 'indented-depth))
+		     (add-line build-table label account-bal)
+		     )
+		   (set! row (+ row 1))
+		   )
+	    )
+	  
+	  ;; handle any unrealized gains
+	  ;; 
+	  ;; we omit unrealized gains from the balance report, if
+	  ;; zero, since they are not present on normal trial balances
+	  (and (not (gnc:commodity-collector-allzero?
+		     unrealized-gain-collector))
+	       (let* ((ug-row (+ header-rows
+				 (gnc:html-acct-table-num-rows
+				  acct-table)))
+		      )
+		 (add-line
+		  build-table (N_ "Unrealized Gains")
+		  neg-unrealized-gain-collector)
+		 ;; make table line wide enough
+		 (gnc:html-table-set-cell!
+		  build-table
+		  ug-row
+		  (+ account-cols 1)
+		  #f)
+		 (if (equal? report-variant 'work-sheet)
+		     (let* ((credit? (gnc:double-col
+				      'credit-q neg-unrealized-gain-collector
+				      report-commodity exchange-fn show-fcur?))
+			    (entry (gnc:double-col
+				    'entry neg-unrealized-gain-collector
+				    report-commodity exchange-fn show-fcur?))
+			    )
+		       ;; make table line wide enough
+		       (gnc:html-table-set-cell!
+			build-table
+			ug-row
+			(+ account-cols (* 2 bs-col) 1)
+			#f)
+		       (gnc:html-table-set-cell!
+			build-table
+			ug-row
+			(+ account-cols (* 2 atb-col) (if credit? 1 0))
+			entry)
+		       (gnc:html-table-set-cell!
+			build-table
+			ug-row
+			(+ account-cols (* 2 bs-col) (if credit? 1 0))
+			entry)
+		       (if credit?
+			   (and (atb-credits 'minusmerge
+					     neg-unrealized-gain-collector #f)
+				(bs-credits 'minusmerge
+					    neg-unrealized-gain-collector #f))
+			   (and (atb-debits 'merge
+					    neg-unrealized-gain-collector #f)
+				(bs-debits 'merge
+					   neg-unrealized-gain-collector #f))
+			   )
+		       )
+		     )
+		 )
+	       )
+	  
+	  ;; 
+	  ;; now, if requested, complete the worksheet
+	  ;; 
+	  ;; to complete the worksheet, we mostly just have to dink
+	  ;; around, reading acct-table, putting values in the right
+	  ;; build-table cells... which is comparatively easy.
+	  ;; 
+	  (if (equal? report-variant 'work-sheet)
+	      (let ((row 0)
+		    (rows (gnc:html-acct-table-num-rows acct-table))
+		    (last-col #f)
+		    (html-row #f)
+		    )
+		(while (< row rows)
+		       (map (lambda (colpair debit-coll credit-coll)
+			      (set! html-row (+ row header-rows))
+			      (let* ((bal
+				      (gnc:html-acct-table-get-cell
+				       acct-table
+				       row
+				       colpair))
+				     (gross-bal? (list? bal))
+				     (entry (and bal
+						 (not gross-bal?)
+						 (gnc:double-col
+						  'entry bal
+						  report-commodity
+						  exchange-fn
+						  show-fcur?)))
+				     (credit? (and bal
+						   (or gross-bal?
+						       (gnc:double-col
+							'credit-q bal
+							report-commodity
+							exchange-fn
+							show-fcur?)
+						       )
+						   ))
+				     (non-credit? (and bal
+						       (or gross-bal?
+							   (not credit?))
+						       ))
+				     (debit (or
+					     (and gross-bal? (car bal))
+					     (and non-credit? bal)
+					     ))
+				     (credit (or
+					      (and gross-bal? (cadr bal))
+					      (and credit? bal)
+					      ))
+				     (debit-entry
+				      (and gross-bal?
+					   (gnc:double-col
+					    'entry debit
+					    report-commodity
+					    exchange-fn
+					    show-fcur?))
+				      )
+				     (credit-entry
+				      (and gross-bal?
+					   (gnc:double-col
+					    'entry credit
+					    report-commodity
+					    exchange-fn
+					    show-fcur?))
+				      )
+				     (col (+ account-cols
+					     (* 2 colpair)
+					     (if non-credit? 0 1))
+					  )
+				     )
+				(gnc:html-table-set-cell!
+				 build-table
+				 html-row
+				 col
+				 (or entry debit-entry)
+				 )
+				(if gross-bal?
+				    (gnc:html-table-set-cell!
+				     build-table
+				     html-row
+				     (+ col 1)
+				     credit-entry
+				     )
+				    )
+				;; update the corresponing running total
+				(and bal
+				     (begin
+				       (if credit?
+					   (credit-coll 'minusmerge
+							(if gross-bal?
+							    credit bal)
+							#f)
+					   )
+				       (if non-credit?
+					   (debit-coll 'merge
+						       (if gross-bal?
+							   debit bal)
+						       #f)
+					   )
+				       )
+				     )
+				)
+			      )
+			    (list adj-col atb-col is-col bs-col)
+			    (list adj-debits atb-debits
+				  is-debits bs-debits)
+			    (list adj-credits atb-credits
+				  is-credits bs-credits)
+			    )
+		       ;; make sure the row extends to the final column
+		       (set! last-col (+ account-cols (* 2 bs-col) 1))
+		       (or
+			(gnc:html-table-get-cell
+			 build-table html-row last-col)
+			(gnc:html-table-set-cell!
+			 build-table html-row last-col #f)
+			)
+		       (set! row (+ row 1))
+		       )
+		)
+	      )
+	  
+	  ;; now do the column totals
+	  (let ()
+	    (gnc:html-table-append-row/markup!
+	     build-table "primary-subheading"
+	     (append
+	      (list (gnc:make-html-table-cell/markup
+		     "total-label-cell" #f))
+	      (gnc:html-make-empty-cells (- account-cols 1))
+	      (list (tot-abs-amt-cell debit-tot))
+	      (list (tot-abs-amt-cell credit-tot))
+	      (if (equal? report-variant 'work-sheet)
+		  (list
+		   (tot-abs-amt-cell adj-debits)
+		   (tot-abs-amt-cell adj-credits)
+		   (tot-abs-amt-cell atb-debits)
+		   (tot-abs-amt-cell atb-credits)
+		   (tot-abs-amt-cell is-debits)
+		   (tot-abs-amt-cell is-credits)
+		   (tot-abs-amt-cell bs-debits)
+		   (tot-abs-amt-cell bs-credits)
+		   )
+		  (list)
+		  )
+	      )
+	     )
+	    )
+	  (if (equal? report-variant 'work-sheet)
+	      (let* ((net-is (gnc:make-commodity-collector))
+		     (net-bs (gnc:make-commodity-collector))
+		     (tot-is (gnc:make-commodity-collector))
+		     (tot-bs (gnc:make-commodity-collector))
+		     (is-entry #f)
+		     (is-credit? #f)
+		     (bs-entry #f)
+		     (bs-credit? #f)
+		     (tbl-width (+ account-cols (* 2 bs-col) 2))
+		     (this-row (gnc:html-table-num-rows build-table))
+		     )
+		(net-is 'merge is-debits #f)
+		(net-is 'minusmerge is-credits #f)
+		(net-bs 'merge bs-debits #f)
+		(net-bs 'minusmerge bs-credits #f)
+		(set! is-entry
+		      (gnc:double-col
+		       'entry net-is report-commodity
+		       exchange-fn show-fcur?))
+		(set! is-credit?
+		      (gnc:double-col
+		       'credit-q net-is report-commodity
+		       exchange-fn show-fcur?))
+		(set! bs-entry
+		      (gnc:double-col
+		       'entry net-bs report-commodity
+		       exchange-fn show-fcur?))
+		(set! bs-credit?
+		      (gnc:double-col
+		       'credit-q net-bs report-commodity
+		       exchange-fn show-fcur?))
+		(gnc:html-table-add-labeled-amount-line!
+		 build-table tbl-width "primary-subheading" #f
+		 (if is-credit? (N_ "Net Income") (N_ "Net Loss"))
+		 0 1 "total-label-cell"
+		 is-entry
+		 (+ account-cols (* 2 is-col) (if is-credit? 0 1))
+		 1 "total-number-cell"
+		 )
+		(gnc:html-table-set-cell!
+		 build-table
+		 this-row
+		 (+ account-cols (* 2 bs-col) (if bs-credit? 0 1))
+		 (tot-abs-amt-cell net-bs)
+		 )
+		(set! this-row (+ this-row 1))
+		
+		;; now slap on the grand totals
+		(tot-is 'merge (if is-credit? is-debits is-credits) #f)
+		(if is-credit?
+		    (tot-is 'minusmerge net-is #f)
+		    (tot-is 'merge net-is #f))
+		(tot-bs 'merge (if bs-credit? bs-debits bs-credits) #f)
+		(if bs-credit?
+		    (tot-bs 'minusmerge net-bs #f)
+		    (tot-bs 'merge net-bs #f))
+		
+		(gnc:html-table-append-row/markup!
+		 build-table
+		 "primary-subheading"
+		 (append
+		  (if gnc:colspans-are-working-right
+		      (list (gnc:make-html-table-cell/size
+			     1 (+ account-cols (* 2 is-col)) #f))
+		      (gnc:html-make-empty-cells (+ account-cols (* 2 is-col)))
+		      )
+		  (list
+		   (tot-abs-amt-cell (if is-credit? tot-is is-debits))
+		   (tot-abs-amt-cell (if is-credit? is-credits tot-is))
+		   (tot-abs-amt-cell (if bs-credit? tot-bs bs-debits))
+		   (tot-abs-amt-cell (if bs-credit? bs-credits tot-bs))
+		   )
+		  )
+		 )
+		)
+	      )
+	  
+	  ;; ...and thats a complete trial balance/work sheet
+	  
+	  (gnc:html-document-add-object! doc build-table)
+	  
+          ;; add currency information if requested
+	  (gnc:report-percent-done 90)
+          (if show-rates?
+              (gnc:html-document-add-object! 
+               doc
+               (gnc:html-make-exchangerates 
+                report-commodity exchange-fn accounts)))
+	  (gnc:report-percent-done 100)
+	  
+	  ;; if sending the report to a file, do so now
+	  ;; however, this still doesn't seem to get around the
+	  ;; colspan bug... cf. gnc:colspans-are-working-right
+	  (if filename
+	      (let* ((port (open-output-file filename))
+		     (gnc:display-report-list-item
+		      (list doc) port " trial-balance.scm ")
+		     (close-output-port port)
+		     )
+		)
+	      )
+	  )
+	)
+    
+    (gnc:report-finished)
+    
+    doc
+    )
+  )
+
+(gnc:define-report 
+ 'version 1.1
+ 'name reportname
+ 'menu-path (list gnc:menuname-income-expense)
+ 'options-generator trial-balance-options-generator
+ 'renderer (lambda (report-obj)
+	     (trial-balance-renderer report-obj #f #f))
+ 'export-types #f
+ 'export-thunk (lambda (report-obj choice filename)
+		 (trial-balance-renderer report-obj #f filename)))
+
+;; END
+
--- /dev/null
+++ src/report/standard-reports/income-statement.scm
@@ -0,0 +1,688 @@
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;; income-statement.scm: income statement (a.k.a. Profit & Loss)
+;; 
+;; By David Montenegro <sunrise2000 at comcast.net>
+;;  2004.07.13 - 2004.07.14
+;;
+;;  * BUGS:
+;;    
+;;    This code makes the assumption that you want your income
+;;    statement to no more than daily resolution.
+;;    
+;;    The Company Name field does not currently default to the name
+;;    in (gnc:get-current-book).
+;;    
+;;    Line & column alignments may still not conform with
+;;    textbook accounting practice (they're close though!).
+;;    The 'canonically-tabbed option is currently broken.
+;;    
+;;    Progress bar functionality is currently mostly broken.
+;;    
+;;    The variables in this code could use more consistent naming.
+;;    
+;;    See also all the "FIXME"s in the code.
+;;    
+;; This program is free software; you can redistribute it and/or    
+;; modify it under the terms of the GNU General Public License as   
+;; published by the Free Software Foundation; either version 2 of   
+;; the License, or (at your option) any later version.              
+;;                                                                  
+;; This program is distributed in the hope that it will be useful,  
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of   
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the    
+;; GNU General Public License for more details.                     
+;;                                                                  
+;; You should have received a copy of the GNU General Public License
+;; along with this program; if not, contact:
+;;
+;; Free Software Foundation           Voice:  +1-617-542-5942
+;; 59 Temple Place - Suite 330        Fax:    +1-617-542-2652
+;; Boston, MA  02111-1307,  USA       gnu at gnu.org
+;;
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+
+(define-module (gnucash report income-statement))
+(use-modules (gnucash main)) ;; FIXME: delete after we finish modularizing.
+(use-modules (ice-9 slib))
+(use-modules (gnucash gnc-module))
+
+(gnc:module-load "gnucash/report/report-system" 0)
+
+(define reportname (N_ "Income Statement"))
+
+;; define all option's names and help text so that they are properly
+;; defined in *one* place.
+(define optname-report-title (N_ "Report Title"))
+(define opthelp-report-title (N_ "Title for this report"))
+
+(define optname-party-name (N_ "Company name"))
+(define opthelp-party-name (N_ "Name of company/individual"))
+
+(define optname-start-date (N_ "Income Statement Start Date"))
+(define opthelp-start-date
+  (N_ "Start of the period this income statement will cover"))
+(define optname-end-date (N_ "Income Statement End Date"))
+(define opthelp-end-date
+  (N_ "End of the period this income statement will cover"))
+;; FIXME this could use an indent option
+
+(define optname-accounts (N_ "Accounts to include"))
+(define opthelp-accounts
+  (N_ "Report on these accounts, if display depth allows."))
+(define optname-depth-limit (N_ "Levels of Subaccounts"))
+(define opthelp-depth-limit
+  (N_ "Maximum number of levels in the account tree displayed"))
+(define optname-bottom-behavior (N_ "Flatten list to depth limit"))
+(define opthelp-bottom-behavior
+  (N_ "Displays accounts which exceed the depth limit at the depth limit"))
+
+(define optname-parent-balance-mode (N_ "Parent account balances"))
+(define opthelp-parent-balance-mode
+  (N_ "How to show any balance in parent accounts"))
+(define optname-parent-total-mode (N_ "Parent account subtotals"))
+(define opthelp-parent-total-mode
+  (N_ "How to show account subtotals for selected accounts having children"))
+
+(define optname-show-zb-accts (N_ "Include accounts with zero total balances"))
+(define opthelp-show-zb-accts
+  (N_ "Include accounts with zero total (recursive) balances in this report"))
+(define optname-omit-zb-bals (N_ "Omit zero balance figures"))
+(define opthelp-omit-zb-bals
+  (N_ "Show blank space in place of any zero balances which would be shown"))
+
+(define optname-use-rules (N_ "Show accounting-style rules"))
+(define opthelp-use-rules
+  (N_ "Use rules beneath columns of added numbers like accountants do"))
+
+(define optname-account-links (N_ "Display accounts as hyperlinks"))
+(define opthelp-account-links (N_ "Shows each account in the table as a hyperlink to its register window"))
+
+(define optname-label-revenue (N_ "Label the revenue section"))
+(define opthelp-label-revenue
+  (N_ "Whether or not to include a label for the revenue section"))
+(define optname-total-revenue (N_ "Include revenue total"))
+(define opthelp-total-revenue
+  (N_ "Whether or not to include a line indicating total revenue"))
+(define optname-label-expense (N_ "Label the expense section"))
+(define opthelp-label-expense
+  (N_ "Whether or not to include a label for the expense section"))
+(define optname-total-expense (N_ "Include expense total"))
+(define opthelp-total-expense
+  (N_ "Whether or not to include a line indicating total expense"))
+
+(define pagename-commodities (N_ "Commodities"))
+(define optname-report-commodity (N_ "Report's currency"))
+(define optname-price-source (N_ "Price Source"))
+(define optname-show-foreign (N_ "Show Foreign Currencies"))
+(define opthelp-show-foreign
+  (N_ "Display any foreign currency amount in an account"))
+(define optname-show-rates (N_ "Show Exchange Rates"))
+(define opthelp-show-rates (N_ "Show the exchange rates used"))
+
+(define pagename-entries (N_ "Entries"))
+(define optname-closing-pattern (N_ "Closing Entries pattern"))
+(define opthelp-closing-pattern
+  (N_ "Any text in the Description column which identifies closing entries"))
+(define optname-closing-casing
+  (N_ "Closing Entries pattern is case-sensitive"))
+(define opthelp-closing-casing
+  (N_ "Causes the Closing Entries Pattern match to be case-sensitive"))
+(define optname-closing-regexp
+  (N_ "Closing Entries Pattern is regular expression"))
+(define opthelp-closing-regexp
+  (N_ "Causes the Closing Entries Pattern to be treated as a regular expression"))
+
+;; This calculates the increase in the balance(s) of all accounts in
+;; <accountlist> over the period from <from-date> to <to-date>.
+;; Returns a commodity collector.
+;;
+;; Note: There is both a gnc:account-get-comm-balance-interval and
+;; gnc:group-get-comm-balance-interval which could replace this
+;; function....
+;;
+(define (accountlist-get-comm-balance-at-date accountlist from-date to-date)
+;;  (for-each (lambda (x) (display x))
+;;	    (list "computing from: " (gnc:print-date from-date) " to "
+;;		  (gnc:print-date to-date) "\n"))
+  (let ((collector (gnc:make-commodity-collector)))
+    (for-each (lambda (account)
+                (let* (
+		       (start-balance
+			(gnc:account-get-comm-balance-at-date
+			 account from-date #f))
+		       (sb (cadr (start-balance
+				  'getpair
+				  (gnc:account-get-commodity account)
+				  #f)))
+		       (end-balance
+			(gnc:account-get-comm-balance-at-date 
+			 account to-date #f))
+		       (eb (cadr (end-balance
+				  'getpair
+				  (gnc:account-get-commodity account)
+				  #f)))
+		       )
+;;		  (for-each (lambda (x) (display x))
+;;			    (list "Start balance: " sb " : "
+;;				  (gnc:account-get-name account) " : end balance: "
+;;				  eb "\n"))
+                  (collector 'merge end-balance #f)
+		  (collector 'minusmerge start-balance #f)
+		  ))
+              accountlist)
+    collector))
+
+;; options generator
+(define (income-statement-options-generator)
+  (let* ((options (gnc:new-options))
+         (add-option 
+          (lambda (new-option)
+            (gnc:register-option options new-option))))
+    
+    (add-option
+      (gnc:make-string-option
+      gnc:pagename-general optname-report-title
+      "a" opthelp-report-title reportname))
+    (add-option
+      (gnc:make-string-option
+      gnc:pagename-general optname-party-name
+      "b" opthelp-party-name (N_ "")))
+    ;; this should default to company name in (gnc:get-current-book)
+    ;; does anyone know the function to get the company name??
+    ;; (GnuCash is *so* well documented... sigh)
+    
+    ;; period over which to report income
+    (gnc:options-add-date-interval!
+     options gnc:pagename-general 
+     optname-start-date optname-end-date "c")
+    
+    ;; accounts to work on
+    (add-option
+     (gnc:make-account-list-option
+      gnc:pagename-accounts optname-accounts
+      "a"
+      opthelp-accounts
+      (lambda ()
+	(gnc:filter-accountlist-type
+	 ;; select, by default, only income and expense accounts
+	 '(income expense)
+	 (gnc:group-get-subaccounts (gnc:get-current-group))))
+      #f #t))
+    (gnc:options-add-account-levels!
+     options gnc:pagename-accounts optname-depth-limit
+     "b" opthelp-depth-limit 3)
+    (add-option
+     (gnc:make-simple-boolean-option
+      gnc:pagename-accounts optname-bottom-behavior
+      "c" opthelp-bottom-behavior #f))
+    
+    ;; all about currencies
+    (gnc:options-add-currency!
+     options pagename-commodities
+     optname-report-commodity "a")
+    
+    (gnc:options-add-price-source! 
+     options pagename-commodities
+     optname-price-source "b" 'weighted-average)
+    
+    (add-option 
+     (gnc:make-simple-boolean-option
+      pagename-commodities optname-show-foreign 
+      "c" opthelp-show-foreign #t))
+    
+    (add-option 
+     (gnc:make-simple-boolean-option
+      pagename-commodities optname-show-rates
+      "d" opthelp-show-rates #f))
+    
+    ;; what to show for zero-balance accounts
+    (add-option 
+     (gnc:make-simple-boolean-option
+      gnc:pagename-display optname-show-zb-accts
+      "a" opthelp-show-zb-accts #t))
+    (add-option 
+     (gnc:make-simple-boolean-option
+      gnc:pagename-display optname-omit-zb-bals
+      "b" opthelp-omit-zb-bals #f))
+    ;; what to show for non-leaf accounts
+    (add-option
+     (gnc:make-multichoice-option
+      gnc:pagename-display optname-parent-balance-mode
+      "c" opthelp-parent-balance-mode
+      'immediate-bal
+      (list (vector 'immediate-bal
+		    (N_ "Show Immediate Balance")
+		    (N_ "Show only the balance in the parent account, excluding any subaccounts"))
+	    (vector 'recursive-bal
+		    (N_ "Recursive Balance")
+		    (N_ "Include subaccounts in balance"))
+	    (vector 'omit-bal
+		    (N_ "Omit Balance")
+		    (N_ "Do not show parent account balances")))))
+    (add-option
+     (gnc:make-multichoice-option
+      gnc:pagename-display optname-parent-total-mode
+      "d" opthelp-parent-total-mode
+      'f
+      (list (vector 't
+		    (N_ "Show subtotals")
+		    (N_ "Show subtotals for selected accounts which have subaccounts"))
+	    (vector 'f
+		    (N_ "Do not show subtotals")
+		    (N_ "Do not subtotal selected parent accounts"))
+	    (vector 'canonically-tabbed
+		    ;;(N_ "Subtotals indented text book style")
+		    (N_ "Text book style (experimental)")
+		    (N_ "Show parent account subtotals, indented per text book practice (experimental)")))))
+    
+    ;; some detailed formatting options
+    (add-option 
+     (gnc:make-simple-boolean-option
+      gnc:pagename-display optname-account-links
+      "e" opthelp-account-links #t))
+    (add-option 
+     (gnc:make-simple-boolean-option
+      gnc:pagename-display optname-use-rules
+      "f" opthelp-use-rules #f))
+    
+    (add-option 
+     (gnc:make-simple-boolean-option
+      gnc:pagename-display optname-label-revenue
+      "g" opthelp-label-revenue #t))
+    (add-option 
+     (gnc:make-simple-boolean-option
+      gnc:pagename-display optname-total-revenue
+      "h" opthelp-total-revenue #t))
+    
+    (add-option 
+     (gnc:make-simple-boolean-option
+      gnc:pagename-display optname-label-expense
+      "i" opthelp-label-expense #t))
+    (add-option 
+     (gnc:make-simple-boolean-option
+      gnc:pagename-display optname-total-expense
+      "j" opthelp-total-expense #t))
+    
+    ;; closing entry match criteria
+    ;; 
+    ;; N.B.: transactions really should have a field where we can put
+    ;; transaction types like "Adjusting/Closing/Correcting Entries"
+    (add-option
+      (gnc:make-string-option
+      pagename-entries optname-closing-pattern
+      "a" opthelp-closing-pattern (N_ "Closing Entries")))
+    (add-option
+     (gnc:make-simple-boolean-option
+      pagename-entries optname-closing-casing
+      "b" opthelp-closing-casing #f))
+    (add-option
+     (gnc:make-simple-boolean-option
+      pagename-entries optname-closing-regexp
+      "c" opthelp-closing-regexp #f))
+    
+    ;; Set the accounts page as default option tab
+    (gnc:options-set-default-section options gnc:pagename-accounts)
+    
+    options))
+
+  ;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;; income-statement-renderer
+;; set up the document and add the table
+  ;;;;;;;;;;;;;;;;;;;;;;;;;;;
+
+(define (income-statement-renderer report-obj)
+  (define (get-option pagename optname)
+    (gnc:option-value
+     (gnc:lookup-option 
+      (gnc:report-options report-obj) pagename optname)))
+  
+  (gnc:report-starting reportname)
+  
+  ;; get all option's values
+  (let* (
+	 (report-title (get-option gnc:pagename-general optname-report-title))
+	 (company-name (get-option gnc:pagename-general optname-party-name))
+         (start-date-printable (gnc:date-option-absolute-time
+				(get-option gnc:pagename-general
+					    optname-start-date)))
+         (start-date-tp (gnc:timepair-start-day-time
+			 (gnc:date-option-absolute-time
+			  (get-option gnc:pagename-general
+				      optname-start-date))))
+         (end-date-tp (gnc:timepair-end-day-time
+		       (gnc:date-option-absolute-time
+			(get-option gnc:pagename-general
+				    optname-end-date))))
+         (accounts (get-option gnc:pagename-accounts
+                               optname-accounts))	 
+	 (depth-limit (get-option gnc:pagename-accounts 
+				  optname-depth-limit))
+	 (bottom-behavior (get-option gnc:pagename-accounts 
+				  optname-bottom-behavior))
+         (report-commodity (get-option pagename-commodities
+                                      optname-report-commodity))
+         (price-source (get-option pagename-commodities
+                                   optname-price-source))
+         (show-fcur? (get-option pagename-commodities
+                                 optname-show-foreign))
+         (show-rates? (get-option pagename-commodities
+                                  optname-show-rates))
+         (parent-balance-mode (get-option gnc:pagename-display
+                                           optname-parent-balance-mode))
+         (parent-total-mode
+	  (car
+	   (assoc-ref '((t #t) (f #f) (canonically-tabbed canonically-tabbed))
+		      (get-option gnc:pagename-display
+				  optname-parent-total-mode))))
+         (show-zb-accts? (get-option gnc:pagename-display
+				     optname-show-zb-accts))
+         (omit-zb-bals? (get-option gnc:pagename-display
+				    optname-omit-zb-bals))
+         (label-revenue? (get-option gnc:pagename-display
+				    optname-label-revenue))
+         (total-revenue? (get-option gnc:pagename-display
+				    optname-total-revenue))
+         (label-expense? (get-option gnc:pagename-display
+				    optname-label-expense))
+         (total-expense? (get-option gnc:pagename-display
+				    optname-total-expense))
+         (use-links? (get-option gnc:pagename-display
+				     optname-account-links))
+         (use-rules? (get-option gnc:pagename-display
+				    optname-use-rules))
+	 (closing-str (get-option pagename-entries
+				  optname-closing-pattern))
+	 (closing-cased (get-option pagename-entries
+				    optname-closing-casing))
+	 (closing-regexp (get-option pagename-entries
+				     optname-closing-regexp))
+	 (closing-pattern
+	  (list (list 'str closing-str)
+		(list 'cased closing-cased)
+		(list 'regexp closing-regexp)
+		)
+	  )
+	 (indent 0)
+	 (tabbing #f)
+	 
+         ;; decompose the account list
+         (split-up-accounts (gnc:decompose-accountlist accounts))
+	 (revenue-accounts (assoc-ref split-up-accounts 'income))
+	 (expense-accounts (assoc-ref split-up-accounts 'expense))
+         (income-expense-accounts
+          (append (assoc-ref split-up-accounts 'income)
+                  (assoc-ref split-up-accounts 'expense)))
+	 
+         (doc (gnc:make-html-document))
+	 ;; this can occasionally put extra (blank) columns in our
+	 ;; table (when there is one account at the maximum depth and
+	 ;; it has at least one of its ancestors deselected), but this
+	 ;; is the only simple way to ensure that both tables
+	 ;; (revenue, expense) have the same width.
+         (tree-depth (if (equal? depth-limit 'all)
+                         (gnc:get-current-group-depth) 
+			 depth-limit))
+         ;; exchange rates calculation parameters
+	 (exchange-fn
+	  (gnc:case-exchange-fn price-source report-commodity end-date-tp))
+	 )
+    
+    ;; Wrapper to call gnc:html-table-add-labeled-amount-line!
+    ;; with the proper arguments.
+    (define (add-subtotal-line table pos-label neg-label signed-balance)
+      (define allow-same-column-totals #t)
+      (let* ((neg? (and signed-balance
+			neg-label
+			(gnc:numeric-negative-p
+			 (gnc:gnc-monetary-amount
+			  (gnc:sum-collector-commodity
+			   signed-balance report-commodity exchange-fn)))))
+	     (label (if neg? (or neg-label pos-label) pos-label))
+	     (balance (if neg?
+			  (let ((bal (gnc:make-commodity-collector)))
+			    (bal 'minusmerge signed-balance #f)
+			    bal)
+			  signed-balance))
+	     )
+	(gnc:html-table-add-labeled-amount-line!
+	 table
+	 (+ indent (* tree-depth 2)
+	    (if (equal? tabbing 'canonically-tabbed) 1 0))
+	 "primary-subheading"
+	 (and (not allow-same-column-totals) balance use-rules?)
+	 label indent 1 "total-label-cell"
+	 (gnc:sum-collector-commodity balance report-commodity exchange-fn)
+	 (+ indent (* tree-depth 2) (- 0 1)
+	    (if (equal? tabbing 'canonically-tabbed) 1 0))
+	 1 "total-number-cell")
+	)
+      )
+    
+    ;; wrapper around gnc:html-table-append-ruler!
+    (define (add-rule table)
+      (gnc:html-table-append-ruler!
+       table
+       (+ (* 2 tree-depth)
+	  (if (equal? tabbing 'canonically-tabbed) 1 0))))
+    
+    (gnc:html-document-set-title! 
+     doc (sprintf #f
+		  (string-append "%s %s "
+				 (N_ "For Period Covering")
+				 " %s "
+				 (N_ "to")
+				 " %s")
+		  company-name report-title
+                  (gnc:print-date start-date-printable)
+                  (gnc:print-date end-date-tp)))
+    
+    (if (null? accounts)
+	
+        ;; error condition: no accounts specified
+	;; is this *really* necessary??
+	;; i'd be fine with an all-zero P&L
+	;; that would, technically, be correct....
+        (gnc:html-document-add-object! 
+         doc 
+         (gnc:html-make-no-account-warning 
+	  reportname (gnc:report-id report-obj)))
+	
+        ;; Get all the balances for each account group.
+        (let* ((revenue-closing #f)
+	       (expense-closing #f)
+	       (neg-revenue-total #f)
+	       (revenue-total #f)
+	       (expense-total #f)
+	       (net-income #f)
+	       
+               ;; Create the account tables below where their
+               ;; percentage time can be tracked.
+	       (build-table (gnc:make-html-table)) ;; gnc:html-table
+	       (table-env #f)                      ;; parameters for :make-
+	       (params #f)                         ;; and -add-account-
+               (revenue-table #f)                  ;; gnc:html-acct-table
+               (expense-table #f)                  ;; gnc:html-acct-table
+	       
+	       (terse-period? #t)
+	       (period-for (if terse-period?
+			       (string-append " " (N_ "for Period"))
+			       (string-append
+				", "
+				(gnc:print-date start-date-printable) " "
+				(N_ "to") " "
+				(gnc:print-date end-date-tp)
+				)
+			       )
+			   )
+	       )
+	  
+	  ;; a helper to add a line to our report
+	  (define (report-line
+		   table pos-label neg-label amount col
+		   exchange-fn rule? row-style)
+	    (let* ((neg? (and amount
+			      neg-label
+			      (gnc:numeric-negative-p
+			       (gnc:gnc-monetary-amount
+				(gnc:sum-collector-commodity
+				 amount report-commodity exchange-fn)))))
+		   (label (if neg? (or neg-label pos-label) pos-label))
+		   (pos-bal (if neg?
+				(let ((bal (gnc:make-commodity-collector)))
+				  (bal 'minusmerge amount #f)
+				  bal)
+				amount))
+		   (bal (gnc:sum-collector-commodity
+			 pos-bal report-commodity exchange-fn))
+		   (balance
+		    (or (and (gnc:uniform-commodity? pos-bal report-commodity)
+			     bal)
+			(and show-fucr?
+			     (gnc:commodity-table
+			      pos-bal report-commodity exchange-fn))
+			bal
+			))
+		   (column (or col 0))
+		   )
+	      (gnc:html-table-add-labeled-amount-line!
+	       table (* 2 tree-depth)  row-style rule?
+	       label                0  1 "text-cell"
+	       bal          (+ col 1)  1 "number-cell")
+	      )
+	    )
+	  
+	  ;; sum revenues and expenses
+	  (set! revenue-closing
+		(gnc:account-get-trans-type-balance-interval
+		 revenue-accounts closing-pattern
+		 start-date-tp end-date-tp)
+		) ;; this is norm positive (debit)
+	  (set! expense-closing
+		(gnc:account-get-trans-type-balance-interval
+		 expense-accounts closing-pattern
+		 start-date-tp end-date-tp)
+		) ;; this is norm negative (credit)
+	  (set! expense-total
+		(accountlist-get-comm-balance-at-date
+		 expense-accounts
+		 start-date-tp end-date-tp))
+	  (expense-total 'minusmerge expense-closing #f)
+	  (set! neg-revenue-total
+		(accountlist-get-comm-balance-at-date
+		 revenue-accounts
+		 start-date-tp end-date-tp))
+	  (neg-revenue-total 'minusmerge revenue-closing #f)
+	  (set! revenue-total (gnc:make-commodity-collector))
+	  (revenue-total 'minusmerge neg-revenue-total #f)
+	  ;; calculate net income
+	  (set! net-income (gnc:make-commodity-collector))
+	  (net-income 'merge revenue-total #f)
+	  (net-income 'minusmerge expense-total #f)
+	  
+	  (set! table-env
+		(list
+		 (list 'start-date start-date-tp)
+		 (list 'end-date end-date-tp)
+		 (list 'display-tree-depth tree-depth)
+		 (list 'depth-limit-behavior (if bottom-behavior
+						 'flatten
+						 'summarize))
+		 (list 'report-commodity report-commodity)
+		 (list 'exchange-fn exchange-fn)
+		 (list 'parent-account-subtotal-mode parent-total-mode)
+		 (list 'zero-balance-mode (if show-zb-accts?
+					      'show-leaf-acct
+					      'omit-leaf-acct))
+		 (list 'account-label-mode (if use-links?
+					       'anchor
+					       'name))
+		 ;; we may, at some point, want to add an option to
+		 ;; generate a pre-adjustment income statement...
+		 (list 'balance-mode 'pre-closing)
+		 (list 'closing-pattern closing-pattern)
+		 )
+		)
+	  (set! params
+		(list
+		 (list 'parent-account-balance-mode parent-balance-mode)
+		 (list 'zero-balance-display-mode (if omit-zb-bals?
+						      'omit-balance
+						      'show-balance))
+		 (list 'multicommodity-mode (if show-fcur? 'table #f))
+		 (list 'rule-mode use-rules?)
+		  )
+		)
+	  
+	  ;; Workaround to force gtkhtml into displaying wide
+	  ;; enough columns.
+	  (let ((space
+		 (make-list tree-depth "&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;\
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;\
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;")
+		 ))
+	    (gnc:html-table-append-row! build-table space)
+	    )
+	  
+	  (gnc:report-percent-done 80)
+	  (if label-revenue?
+	      (add-subtotal-line build-table (_ "Revenues") #f #f))
+	  (set! revenue-table
+		(gnc:make-html-acct-table/env/accts
+		 table-env revenue-accounts))
+	  (gnc:html-table-add-account-balances
+	   build-table revenue-table params)
+          (if total-revenue?
+	      (add-subtotal-line 
+	       build-table (_ "Total Revenue") #f revenue-total))
+	  
+	  (gnc:report-percent-done 85)
+	  (if label-expense?
+	      (add-subtotal-line 
+	       build-table (_ "Expenses") #f #f))
+	  (set! expense-table
+		(gnc:make-html-acct-table/env/accts
+		 table-env expense-accounts))
+	  (gnc:html-table-add-account-balances
+	   build-table expense-table params)
+	  (if total-expense?
+	      (add-subtotal-line
+	       build-table (_ "Total Expenses") #f expense-total))
+	  
+	  (report-line
+	   build-table 
+	   (string-append (N_ "Net income") period-for)
+	   (string-append (N_ "Net loss") period-for)
+	   net-income
+	   (* 2 (- tree-depth 1)) exchange-fn #f #f
+	   )
+	  
+	  (gnc:html-document-add-object! doc build-table)
+	  
+          ;; add currency information if requested
+	  (gnc:report-percent-done 90)
+          (if show-rates?
+              (gnc:html-document-add-object! 
+               doc ;;(gnc:html-markup-p)
+               (gnc:html-make-exchangerates 
+                report-commodity exchange-fn accounts)))
+	  (gnc:report-percent-done 100)
+	  
+	  )
+	)
+    
+    (gnc:report-finished)
+    
+    doc
+    )
+  )
+
+(gnc:define-report 
+ 'version 2 ;; but it doesn't matter... :)
+ 'name reportname
+ 'menu-path (list gnc:menuname-income-expense)
+ 'options-generator income-statement-options-generator
+ 'renderer income-statement-renderer
+ )
+
+;; END
+
Index: equity-statement.scm
===================================================================
RCS file: /home/cvs/cvsroot/gnucash/src/report/standard-reports/equity-statement.scm,v
retrieving revision 1.1.2.1
retrieving revision 1.1.2.2
diff -Lsrc/report/standard-reports/equity-statement.scm -Lsrc/report/standard-reports/equity-statement.scm -u -r1.1.2.1 -r1.1.2.2
--- src/report/standard-reports/equity-statement.scm
+++ src/report/standard-reports/equity-statement.scm
@@ -19,7 +19,8 @@
 ;;    statement to no more than daily resolution.
 ;;    
 ;;    The Accounts option panel needs a way to select (and select by
-;;    default) capital and draw accounts.
+;;    default) capital and draw accounts. There really should be a
+;;    contra account type or attribute....
 ;;    
 ;;    The variables in this code could use more consistent naming.
 ;;    
@@ -87,6 +88,19 @@
 (define optname-show-rates (N_ "Show Exchange Rates"))
 (define opthelp-show-rates (N_ "Show the exchange rates used"))
 
+(define pagename-entries (N_ "Entries"))
+(define optname-closing-pattern (N_ "Closing Entries pattern"))
+(define opthelp-closing-pattern
+  (N_ "Any text in the Description column which identifies closing entries"))
+(define optname-closing-casing
+  (N_ "Closing Entries pattern is case-sensitive"))
+(define opthelp-closing-casing
+  (N_ "Causes the Closing Entries Pattern match to be case-sensitive"))
+(define optname-closing-regexp
+  (N_ "Closing Entries Pattern is regular expression"))
+(define opthelp-closing-regexp
+  (N_ "Causes the Closing Entries Pattern to be treated as a regular expression"))
+
 ;; This calculates the increase in the balance(s) of all accounts in
 ;; <accountlist> over the period from <start-date> to <end-date>.
 ;; Returns a commodity collector.
@@ -189,6 +203,23 @@
       gnc:pagename-display optname-use-rules
       "f" opthelp-use-rules #f))
     
+    ;; closing entry match criteria
+    ;; 
+    ;; N.B.: transactions really should have a field where we can put
+    ;; transaction types like "Adjusting/Closing/Correcting Entries"
+    (add-option
+      (gnc:make-string-option
+      pagename-entries optname-closing-pattern
+      "a" opthelp-closing-pattern (N_ "Closing Entries")))
+    (add-option
+     (gnc:make-simple-boolean-option
+      pagename-entries optname-closing-casing
+      "b" opthelp-closing-casing #f))
+    (add-option
+     (gnc:make-simple-boolean-option
+      pagename-entries optname-closing-regexp
+      "c" opthelp-closing-regexp #f))
+    
     ;; Set the accounts page as default option tab
     (gnc:options-set-default-section options gnc:pagename-accounts)
     
@@ -241,6 +272,12 @@
                                   optname-show-rates))
          (use-rules? (get-option gnc:pagename-display
 				    optname-use-rules))
+	 (closing-str (get-option pagename-entries
+				  optname-closing-pattern))
+	 (closing-cased (get-option pagename-entries
+				    optname-closing-casing))
+	 (closing-regexp (get-option pagename-entries
+				     optname-closing-regexp))
 	 
          ;; decompose the account list
          (split-up-accounts (gnc:decompose-accountlist accounts))
@@ -257,6 +294,17 @@
 	 ;; these must still be split-out and itemized separately
 	 (capital-accounts #f)
 	 (drawing-accounts #f)
+	 (investments #f)
+	 (withdrawals #f)
+	 (net-investment #f)
+	 (income-expense-closing #f)
+	 (closing-pattern
+	  (list (list 'str closing-str)
+		(list 'cased closing-cased)
+		(list 'regexp closing-regexp)
+		(list 'positive #f)
+		)
+	  )
 	 
          (doc (gnc:make-html-document))
          ;; exchange rates calculation parameters
@@ -271,11 +319,11 @@
     (gnc:html-document-set-title! 
      doc (sprintf #f
 		  (string-append "%s %s "
-				 (N_ "For Period")
+				 (N_ "For Period Covering")
 				 " %s "
 				 (N_ "to")
 				 " %s")
-		  report-title company-name
+		  company-name report-title
                   (gnc:print-date start-date-printable)
                   (gnc:print-date end-date-tp)))
     
@@ -303,6 +351,8 @@
                (neg-start-equity-balance #f)
                (neg-end-equity-balance #f)
 	       
+	       ;; these variables wont be used until gnucash gets
+	       ;; conta account types
                (start-capital-balance #f)
                (end-capital-balance #f)
                (start-drawing-balance #f)
@@ -315,14 +365,14 @@
 	       (end-unrealized-gains #f)
 	       (net-unrealized-gains #f)
 	       
-	       (start-total-equity #f)
-	       (end-total-equity #f)
-	       
-	       (investments #f)
-	       (draws #f)
+	       (equity-closing #f)
+	       (neg-pre-closing-equity #f)
 	       
 	       (capital-increase #f)
 	       
+	       (start-total-equity #f)
+	       (end-total-equity #f)
+	       
 	       ;; Create the account table below where its
 	       ;; percentage time can be tracked.
 	       (build-table (gnc:make-html-table)) ;; gnc:html-table
@@ -350,6 +400,7 @@
 		   table pos-label neg-label amount col
 		   exchange-fn rule? row-style)
 	    (let* ((neg? (and amount
+			      neg-label
 			      (gnc:numeric-negative-p
 			       (gnc:gnc-monetary-amount
 				(gnc:sum-collector-commodity
@@ -363,10 +414,11 @@
 		   (bal (gnc:sum-collector-commodity
 			 pos-bal report-commodity exchange-fn))
 		   (balance
-		    (or (and (gnc:uniform-commodity? bal report-commodity) bal)
+		    (or (and (gnc:uniform-commodity? pos-bal report-commodity)
+			     bal)
 			(and show-fucr?
 			     (gnc:commodity-table
-			      bal report-commodity exchange-fn))
+			      pos-bal report-commodity exchange-fn))
 			bal
 			))
 		   (column (or col 0))
@@ -444,12 +496,26 @@
 		(accountlist-get-comm-balance-at-date
 		 income-expense-accounts
 		 forever-ago end-date-tp)) ; OK
+	  ;; neg-pre-end-retained-earnings is not used to calculate
+	  ;; profit but is used to calculate unrealized gains
+	  
+	  ;; calculate net income
+	  ;; first, ask out how much profit/loss was closed
+	  (set! income-expense-closing
+		(gnc:account-get-trans-type-balance-interval
+		 income-expense-accounts closing-pattern
+		 start-date-tp end-date-tp)
+		)
+	  ;; find retained earnings for the period
 	  (set! neg-net-income
 		(accountlist-get-comm-balance-at-date
 		 income-expense-accounts
 		 start-date-tp end-date-tp)) ; OK
+	  ;; revert the income/expense to its pre-closing balance
+	  (neg-net-income 'minusmerge income-expense-closing #f)
 	  (set! net-income (gnc:make-commodity-collector))
 	  (net-income 'minusmerge neg-net-income #f)
+	  ;; now we know the net income for the period
 	  
 	  ;; start and end (unadjusted) equity balances
 	  (set! neg-start-equity-balance
@@ -458,6 +524,8 @@
 	  (set! neg-end-equity-balance
                 (gnc:accounts-get-comm-total-assets 
                  equity-accounts get-end-balance-fn)) ; OK
+	  ;; neg-end-equity-balance is used to calculate unrealized
+	  ;; gains and investments/withdrawals
 	  
 	  ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 	  ;; 
@@ -482,6 +550,10 @@
 		(unrealized-gains-at-date start-book-balance
 					  start-exchange-fn
 					  start-date-tp)) ; OK
+	  ;; I suspect that unrealized gains (since never realized)
+	  ;; must be counted from forever-ago....
+	  ;; ...yep, this appears to be correct.
+	  (set! start-unrealized-gains (gnc:make-commodity-collector))
 	  (set! end-unrealized-gains
 		(unrealized-gains-at-date end-book-balance
 					  end-exchange-fn
@@ -492,17 +564,6 @@
 	  (net-unrealized-gains 'merge end-unrealized-gains #f)
 	  (net-unrealized-gains 'minusmerge start-unrealized-gains #f) ; OK
 	  
-	  ;; starting and ending total equity...
-	  (set! start-total-equity (gnc:make-commodity-collector))
-	  (start-total-equity 'minusmerge neg-start-equity-balance #f)
-	  (start-total-equity 'minusmerge neg-pre-start-retained-earnings #f)
-	  (start-total-equity 'merge start-unrealized-gains #f) ; OK
-	  
-	  (set! end-total-equity (gnc:make-commodity-collector))
-	  (end-total-equity 'minusmerge neg-end-equity-balance #f)
-	  (end-total-equity 'minusmerge neg-pre-end-retained-earnings #f)
-	  (end-total-equity 'merge end-unrealized-gains #f) ; OK
-	  
 	  ;; 
 	  ;; calculate investments & draws...
 	  ;; 
@@ -511,21 +572,52 @@
 	  ;; bit...  i'll do a transaction query and classify the
 	  ;; splits by debit/credit.
 	  ;; 
+	  ;;   withdrawals = investments - (investments - withdrawals)
+	  ;;   investments = withdrawals + (investments - withdrawals)
+	  ;; 
+	  ;; assume that positive shares on an equity account are debits...
+	  ;; 
 	  
-	  ;; FIXME: um... no.  that sounds like too much work.
-	  ;; ok, for now, just assume draws are zero and investments signed
-	  (set! draws (gnc:make-commodity-collector))           ;; 0
-	  (set! investments (gnc:make-commodity-collector))     ;; 0
-	  (investments 'minusmerge neg-end-equity-balance #f)   ;; > 0
-	  (investments 'merge neg-start-equity-balance #f)      ;; net increase
+	  (set! equity-closing 
+		(gnc:account-get-trans-type-balance-interval
+		 equity-accounts closing-pattern
+		 start-date-tp end-date-tp)
+		)
+	  (set! neg-pre-closing-equity (gnc:make-commodity-collector))
+	  (neg-pre-closing-equity 'merge neg-end-equity-balance #f)
+	  (neg-pre-closing-equity 'minusmerge equity-closing #f)
+	  
+	  (set! net-investment (gnc:make-commodity-collector))  ;; 0
+	  (net-investment 'minusmerge neg-pre-closing-equity #f);; > 0
+	  (net-investment 'merge neg-start-equity-balance #f)   ;; net increase
+	  
+	  (set! withdrawals (gnc:make-commodity-collector))
+	  (withdrawals 'merge (gnc:account-get-pos-trans-total-interval
+				    equity-accounts closing-pattern
+				    start-date-tp end-date-tp)
+		       #f)
+	  (set! investments (gnc:make-commodity-collector))
+	  (investments 'merge net-investment #f)
+	  (investments 'merge withdrawals #f)
 	  
 	  ;; increase in equity
 	  (set! capital-increase (gnc:make-commodity-collector))
 	  (capital-increase 'merge net-income #f)
 	  (capital-increase 'merge investments #f)
-	  (capital-increase 'minusmerge draws #f)
+	  (capital-increase 'minusmerge withdrawals #f)
 	  (capital-increase 'merge net-unrealized-gains #f)
 	  
+	  ;; starting total equity
+	  (set! start-total-equity (gnc:make-commodity-collector))
+	  (start-total-equity 'minusmerge neg-start-equity-balance #f)
+	  (start-total-equity 'minusmerge neg-pre-start-retained-earnings #f)
+	  (start-total-equity 'merge start-unrealized-gains #f) ; OK
+	  
+	  ;; ending total equity
+	  (set! end-total-equity (gnc:make-commodity-collector))
+	  (end-total-equity 'merge start-total-equity #f)
+	  (end-total-equity 'merge capital-increase #f) ; OK
+	  
 	  (gnc:report-percent-done 30)
 	  
 	  ;; Workaround to force gtkhtml into displaying wide
@@ -555,18 +647,27 @@
 	   )
 	  (report-line
 	   build-table 
-	   (string-append (N_ "Investments less withdrawals") period-for)
+	   (string-append (N_ "Investments") period-for)
 	   #f
 	   investments
 	   0 end-exchange-fn #f #f
 	   )
 	  (report-line
 	   build-table 
-	   (string-append (N_ "Unrealized gains") period-for)
-	   (string-append (N_ "Unrealized losses") period-for)
-	   net-unrealized-gains
+	   (string-append (N_ "Withdrawals") period-for)
+	   #f
+	   withdrawals
 	   0 end-exchange-fn #f #f
 	   )
+	  (or (gnc:commodity-collector-allzero? net-unrealized-gains)
+	      (report-line
+	       build-table 
+	       (N_ "Unrealized gains")
+	       (N_ "Unrealized losses")
+	       net-unrealized-gains
+	       0 end-exchange-fn #f #f
+	       )
+	   )
 	  (report-line
 	   build-table 
 	   (N_ "Increase in capital")
--- src/report/standard-reports/pnl.scm
+++ /dev/null
@@ -1,241 +0,0 @@
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-;; pnl.scm : profit-and-loss report 
-;;  
-;; By Christian Stimming <stimming at tu-harburg.de>
-;;
-;; This program is free software; you can redistribute it and/or    
-;; modify it under the terms of the GNU General Public License as   
-;; published by the Free Software Foundation; either version 2 of   
-;; the License, or (at your option) any later version.              
-;;                                                                  
-;; This program is distributed in the hope that it will be useful,  
-;; but WITHOUT ANY WARRANTY; without even the implied warranty of   
-;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the    
-;; GNU General Public License for more details.                     
-;;                                                                  
-;; You should have received a copy of the GNU General Public License
-;; along with this program; if not, contact:
-;;
-;; Free Software Foundation           Voice:  +1-617-542-5942
-;; 59 Temple Place - Suite 330        Fax:    +1-617-542-2652
-;; Boston, MA  02111-1307,  USA       gnu at gnu.org
-;;
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-
-(define-module (gnucash report pnl))
-
-(use-modules (gnucash main)) ;; FIXME: delete after we finish modularizing.
-(use-modules (srfi srfi-1))
-(use-modules (ice-9 slib))
-(use-modules (gnucash gnc-module))
-
-(require 'printf)
-
-(gnc:module-load "gnucash/report/report-system" 0)
-
-;; Profit and loss report. Actually, people in finances might want
-;; something different under this name, but they are welcomed to
-;; contribute their changes :-)
-
-(define reportname (N_ "Profit And Loss"))
-
-;; define all option's names so that they are properly defined
-;; in *one* place.
-(define optname-from-date (N_ "From"))
-(define optname-to-date (N_ "To"))
-
-(define optname-display-depth (N_ "Account Display Depth"))
-(define optname-show-subaccounts (N_ "Always show sub-accounts"))
-(define optname-accounts (N_ "Account"))
-
-(define optname-group-accounts (N_ "Group the accounts"))
-(define optname-show-parent-balance (N_ "Show balances for parent accounts"))
-(define optname-show-parent-total (N_ "Show subtotals"))
-
-(define optname-show-foreign (N_ "Show Foreign Currencies"))
-(define optname-report-currency (N_ "Report's currency"))
-(define optname-price-source (N_ "Price Source"))
-(define optname-show-rates (N_ "Show Exchange Rates"))
-(define optname-show-zeros (N_ "Show accounts with a 0.0 total"))
-
-;; options generator
-(define (pnl-options-generator)
-  (let ((options (gnc:new-options)))
-    
-    ;; date at which to report balance
-    (gnc:options-add-date-interval!
-     options gnc:pagename-general 
-     optname-from-date optname-to-date "a")
-
-    ;; all about currencies
-    (gnc:options-add-currency!
-     options gnc:pagename-general
-     optname-report-currency "b")
-
-    (gnc:options-add-price-source! 
-     options gnc:pagename-general
-     optname-price-source "c" 'weighted-average)
-
-    ;; accounts to work on
-    (gnc:options-add-account-selection! 
-     options gnc:pagename-accounts
-     optname-display-depth optname-show-subaccounts
-     optname-accounts "a" 2
-     (lambda ()
-       (filter 
-        gnc:account-is-inc-exp?
-        (gnc:group-get-account-list (gnc:get-current-group))))
-     #t)
-
-    ;; with or without grouping
-    (gnc:options-add-group-accounts!      
-     options gnc:pagename-display optname-group-accounts "b" #t)
-
-    ;; what to show about non-leaf accounts
-    (gnc:register-option 
-     options
-     (gnc:make-simple-boolean-option
-      gnc:pagename-display optname-show-parent-balance 
-      "c" (N_ "Show balances for parent accounts") #f))
-
-    ;; have a subtotal for each parent account?
-    (gnc:register-option 
-     options
-     (gnc:make-simple-boolean-option
-      gnc:pagename-display optname-show-parent-total
-      "d" (N_ "Show subtotals for parent accounts") #t))
-
-    (gnc:register-option 
-     options
-     (gnc:make-simple-boolean-option
-      gnc:pagename-display optname-show-foreign 
-      "e" (N_ "Display the account's foreign currency amount?") #f))
-
-    (gnc:register-option 
-     options
-     (gnc:make-simple-boolean-option
-      gnc:pagename-display optname-show-rates
-      "f" (N_ "Show the exchange rates used") #t))
-
-    (gnc:register-option 
-     options
-     (gnc:make-simple-boolean-option
-      gnc:pagename-display optname-show-zeros
-      "g" (N_ "Show account with 0.0 balance") #t))
-
-    ;; Set the general page as default option tab
-    (gnc:options-set-default-section options gnc:pagename-general)      
-
-    options))
-
-  ;;;;;;;;;;;;;;;;;;;;;;;;;;;
-;; pnl-renderer
-;; set up the document and add the table
-  ;;;;;;;;;;;;;;;;;;;;;;;;;;;
-
-(define (pnl-renderer report-obj)
-  (define (get-option pagename optname)
-    (gnc:option-value
-     (gnc:lookup-option 
-      (gnc:report-options report-obj) pagename optname)))
-
-  (gnc:report-starting reportname)
-
-  ;; get all option's values
-  (let* ((display-depth (get-option gnc:pagename-accounts 
-                                    optname-display-depth))
-         (show-subaccts? (get-option gnc:pagename-accounts
-                                     optname-show-subaccounts))
-         (accounts (filter gnc:account-is-inc-exp?
-                           (get-option gnc:pagename-accounts
-                                       optname-accounts)))
-         (do-grouping? (get-option gnc:pagename-display
-                                   optname-group-accounts))
-         (show-parent-balance? (get-option gnc:pagename-display
-                                           optname-show-parent-balance))
-         (show-parent-total? (get-option gnc:pagename-display
-                                         optname-show-parent-total))
-         (show-fcur? (get-option gnc:pagename-display
-                                 optname-show-foreign))
-         (report-currency (get-option gnc:pagename-general
-                                      optname-report-currency))
-         (price-source (get-option gnc:pagename-general
-                                   optname-price-source))
-         (show-rates? (get-option gnc:pagename-display 
-                                  optname-show-rates))
-         (show-zeros? (get-option gnc:pagename-display 
-                                  optname-show-zeros))
-         (to-date-tp (gnc:timepair-end-day-time 
-                      (gnc:date-option-absolute-time
-                       (get-option gnc:pagename-general
-                                   optname-to-date))))
-         (from-date-tp (gnc:timepair-start-day-time 
-                        (gnc:date-option-absolute-time
-                         (get-option gnc:pagename-general
-                                     optname-from-date))))
-         (report-title (sprintf #f
-                                (_ "%s - %s to %s")
-				(get-option gnc:pagename-general gnc:optname-reportname)
-                                (gnc:print-date from-date-tp)
-                                (gnc:print-date to-date-tp)))
-         (doc (gnc:make-html-document)))
-    
-    (gnc:html-document-set-title! 
-     doc report-title)
-    (if (not (null? accounts))
-        ;; if no max. tree depth is given we have to find the
-        ;; maximum existing depth
-        (let* ((tree-depth (+ (if (equal? display-depth 'all)
-                                  (gnc:get-current-group-depth) 
-                                  display-depth)
-                              (if do-grouping? 1 0)))
-
-               (exchange-fn #f)
-               (table #f))
-
-	  ;; calculate the exchange rates
-	  (gnc:report-percent-done 1)
-	  (set! exchange-fn (gnc:case-exchange-fn
-                             price-source report-currency to-date-tp))
-	  (gnc:report-percent-done 10)
-
-	  ;; do the processing here
-	  (set! table (gnc:html-build-acct-table 
-                       from-date-tp to-date-tp 
-                       tree-depth show-subaccts? accounts 10 80 #f
-                       #t gnc:accounts-get-comm-total-profit 
-                       (_ "Profit") do-grouping? 
-                       show-parent-balance? show-parent-total?
-                       show-fcur? report-currency exchange-fn show-zeros?))
-          ;; add the table 
-          (gnc:html-document-add-object! doc table)
-
-          ;; add currency information
-          (if show-rates?
-              (gnc:html-document-add-object! 
-               doc ;;(gnc:html-markup-p
-               (gnc:html-make-exchangerates 
-                report-currency exchange-fn 
-                (append-map 
-                 (lambda (a)
-                   (gnc:group-get-subaccounts
-                    (gnc:account-get-children a)))
-                 accounts))))
-	  (gnc:report-percent-done 100))
-        
-        ;; error condition: no accounts specified
-        
-        (gnc:html-document-add-object!
-         doc
-	 (gnc:html-make-no-account-warning 
-	  report-title (gnc:report-id report-obj))))
-    (gnc:report-finished)
-    doc))
-
-(gnc:define-report 
- 'version 1
- 'name reportname
- 'menu-name (N_ "Profit & Loss")
- 'menu-path (list gnc:menuname-income-expense)
- 'options-generator pnl-options-generator
- 'renderer pnl-renderer)
Index: standard-reports.scm
===================================================================
RCS file: /home/cvs/cvsroot/gnucash/src/report/standard-reports/standard-reports.scm,v
retrieving revision 1.14.4.2
retrieving revision 1.14.4.3
diff -Lsrc/report/standard-reports/standard-reports.scm -Lsrc/report/standard-reports/standard-reports.scm -u -r1.14.4.2 -r1.14.4.3
--- src/report/standard-reports/standard-reports.scm
+++ src/report/standard-reports/standard-reports.scm
@@ -72,14 +72,17 @@
 (use-modules (gnucash report average-balance))
 (use-modules (gnucash report balance-sheet))
 (use-modules (gnucash report equity-statement))
+(use-modules (gnucash report general-journal))
+(use-modules (gnucash report general-ledger))
 (use-modules (gnucash report cash-flow))
 (use-modules (gnucash report category-barchart))
 (use-modules (gnucash report daily-reports))
 (use-modules (gnucash report net-barchart))
-(use-modules (gnucash report pnl))
+(use-modules (gnucash report income-statement))
 (use-modules (gnucash report portfolio))
 (use-modules (gnucash report price-scatter))
 (use-modules (gnucash report register))
+(use-modules (gnucash report trial-balance))
 (use-modules (gnucash report transaction))
 
 (use-modules (gnucash gnc-module))
--- /dev/null
+++ src/report/standard-reports/general-ledger.scm
@@ -0,0 +1,138 @@
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;; general-ledger.scm: general ledger report
+;; 
+;; By David Montenegro <sunrise2000 at comcast.net> 2004.07.13
+;; 
+;;  * BUGS:
+;;    
+;;    See any "FIXME"s in the code.
+;;    
+;; Largely borrowed from welcome-to-gnucash.scm by
+;;  Bill Gribble <grib at gnumatic.com>
+;;
+;; This program is free software; you can redistribute it and/or    
+;; modify it under the terms of the GNU General Public License as   
+;; published by the Free Software Foundation; either version 2 of   
+;; the License, or (at your option) any later version.              
+;;                                                                  
+;; This program is distributed in the hope that it will be useful,  
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of   
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the    
+;; GNU General Public License for more details.                     
+;;                                                                  
+;; You should have received a copy of the GNU General Public License
+;; along with this program; if not, contact:
+;;
+;; Free Software Foundation           Voice:  +1-617-542-5942
+;; 59 Temple Place - Suite 330        Fax:    +1-617-542-2652
+;; Boston, MA  02111-1307,  USA       gnu at gnu.org
+;;
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+
+(define-module (gnucash report general-ledger))
+(export gnc:make-general-ledger-report)
+(use-modules (gnucash main)) ;; FIXME: delete after we finish modularizing.
+(use-modules (ice-9 slib))
+(use-modules (gnucash gnc-module))
+
+(gnc:module-load "gnucash/report/report-system" 0)
+
+(define reportname (N_ "General Ledger"))
+(define xactrptname "Transaction Report")
+
+;; report constructor
+
+(define (gnc:make-general-ledger-report)
+  (let* ((xactrpt (gnc:make-report xactrptname)))
+    xactrpt))
+
+;; options generator
+
+(define (general-ledger-options-generator)
+  
+  (let* ((options (gnc:report-template-new-options/name xactrptname))
+	 )
+    
+    (define pagename-sorting (N_ "Sorting"))
+    (define (set-option! section name value)
+      (gnc:option-set-value 
+       (gnc:lookup-option options section name) value))
+    
+    ;; set options in the accounts tab...
+    (set-option!
+     gnc:pagename-accounts (N_ "Filter Type") 'none)
+    (set-option!
+     gnc:pagename-accounts (N_ "Void Transactions?") 'non-void-only)
+    
+    ;; set options in the display tab...
+    (for-each
+     (lambda (l)
+       (set-option! gnc:pagename-display (car l) (cadr l)))
+     ;; One list per option here with: option-name, default-value
+     (list
+      (list (N_ "Date") #t)
+      (list (N_ "Reconciled Date") #f)
+      (list (N_ "Num") #f)
+      (list (N_ "Description") #t)
+      (list (N_ "Memo") #f)
+      (list (N_ "Account Name") #f)
+      (list (N_ "Use Full Account Name?") #f)
+      (list (N_ "Account Code") #f)
+      (list (N_ "Other Account Name") #f)
+      (list (N_ "Use Full Other Account Name?") #f)
+      (list (N_ "Other Account Code") #f)
+      (list (N_ "Shares") #f)
+      (list (N_ "Price") #f)
+      ;; note the "Amount" multichoice option here
+      (list (N_ "Amount") 'double)
+      (list (N_ "Running Balance") #t)
+      (list (N_ "Totals") #f)
+      (list (N_ "Sign Reverses?") 'credit-accounts)
+      )
+     )
+    
+    ;; set options in the general tab...
+    (set-option!
+     gnc:pagename-general (N_ "Style") 'single)
+    ;; we can't (currently) set the Report name here
+    ;; because it is automatically set to the template
+    ;; name... :(
+    
+    ;; set options in the sorting tab...
+    (for-each
+     (lambda (l)
+       (set-option! pagename-sorting (car l) (cadr l)))
+     ;; One list per option here with: option-name, default-value
+     (list
+      (list (N_ "Primary Key") 'account-code)
+      (list (N_ "Show Full Account Name?") #f)
+      (list (N_ "Show Account Code?") #t)
+      (list (N_ "Primary Subtotal") #t)
+      (list (N_ "Primary Subtotal for Date Key") 'none)
+      (list (N_ "Primary Sort Order") 'ascend)
+      (list (N_ "Secondary Key") 'register-order)
+      (list (N_ "Secondary Subtotal") #t)
+      (list (N_ "Secondary Subtotal for Date Key") 'none)
+      (list (N_ "Secondary Sort Order") 'ascend)
+      )
+     )
+    
+    options)
+  )
+
+;; report renderer
+
+(define (general-ledger-renderer report-obj)
+  ;; just delegate rendering to the Transaction Report renderer...
+  ((gnc:report-template-renderer/name xactrptname) report-obj))
+
+(gnc:define-report 
+ 'version 1
+ 'name reportname
+ 'menu-path (list gnc:menuname-asset-liability)
+ 'options-generator general-ledger-options-generator
+ 'renderer general-ledger-renderer
+ )
+
+;; END
+
Index: Makefile.am
===================================================================
RCS file: /home/cvs/cvsroot/gnucash/src/report/standard-reports/Makefile.am,v
retrieving revision 1.12.4.2
retrieving revision 1.12.4.3
diff -Lsrc/report/standard-reports/Makefile.am -Lsrc/report/standard-reports/Makefile.am -u -r1.12.4.2 -r1.12.4.3
--- src/report/standard-reports/Makefile.am
+++ src/report/standard-reports/Makefile.am
@@ -32,11 +32,14 @@
    daily-reports.scm \
    equity-statement.scm \
    net-barchart.scm \
-   pnl.scm \
+   income-statement.scm \
    portfolio.scm \
    price-scatter.scm \
    register.scm \
    standard-reports.scm \
+   trial-balance.scm \
+   general-journal.scm \
+   general-ledger.scm \
    transaction.scm 
 
 EXTRA_DIST = ${gncscmmod_DATA}
--- /dev/null
+++ src/report/standard-reports/general-journal.scm
@@ -0,0 +1,129 @@
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;; general-journal.scm: general journal report
+;; 
+;; By David Montenegro <sunrise2000 at comcast.net> 2004.07.14
+;; 
+;;  * BUGS:
+;;    
+;;    See any "FIXME"s in the code.
+;;    
+;; This program is free software; you can redistribute it and/or    
+;; modify it under the terms of the GNU General Public License as   
+;; published by the Free Software Foundation; either version 2 of   
+;; the License, or (at your option) any later version.              
+;;                                                                  
+;; This program is distributed in the hope that it will be useful,  
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of   
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the    
+;; GNU General Public License for more details.                     
+;;                                                                  
+;; You should have received a copy of the GNU General Public License
+;; along with this program; if not, contact:
+;;
+;; Free Software Foundation           Voice:  +1-617-542-5942
+;; 59 Temple Place - Suite 330        Fax:    +1-617-542-2652
+;; Boston, MA  02111-1307,  USA       gnu at gnu.org
+;;
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+
+(define-module (gnucash report general-journal))
+(export gnc:make-general-journal-report)
+(use-modules (gnucash main)) ;; FIXME: delete after we finish modularizing.
+(use-modules (ice-9 slib))
+(use-modules (gnucash gnc-module))
+
+(gnc:module-load "gnucash/report/report-system" 0)
+
+(define reportname (N_ "General Journal"))
+(define regrptname "Register")
+
+;; report constructor
+
+(define (gnc:make-general-journal-report)
+  (let* ((regrpt (gnc:make-report regrptname)))
+    regrpt))
+
+;; options generator
+
+(define (general-journal-options-generator)
+  
+  (let* ((options (gnc:report-template-new-options/name regrptname))
+	 (query (gnc:malloc-query))
+	 )
+    
+    (define (set-option! section name value)
+      (gnc:option-set-value 
+       (gnc:lookup-option options section name) value))
+    
+    ;; Match, by default, all non-void transactions ever recorded in
+    ;; all accounts....  Whether or not to match void transactions,
+    ;; however, may be of issue here. Since I don't know if the
+    ;; Register Report properly ignores voided transactions, I'll err
+    ;; on the side of safety by excluding them from the query....
+    (gnc:query-set-book query (gnc:get-current-book))
+    (gnc:query-set-match-non-voids-only! query (gnc:get-current-book))
+    (gnc:query-set-sort-order query
+			      (list gnc:split-trans gnc:trans-date-posted)
+			      (list gnc:query-default-sort)
+			      '())
+    (gnc:query-set-sort-increasing query #t #t #t)
+    ;; set the "__reg" options required by the Register Report...
+    (for-each
+     (lambda (l)
+       (set-option! "__reg" (car l) (cadr l)))
+     ;; One list per option here with: option-name, default-value
+     (list
+      (list (N_ "query") (gnc:query->scm query)) ;; think this wants an scm...
+      (list (N_ "journal") #t)
+      (list (N_ "double") #t)
+      (list (N_ "debit-string") (N_ "Debit"))
+      (list (N_ "credit-string") (N_ "Credit"))
+      )
+     )
+    ;; we'll leave query malloc'd in case this is required by the C side...
+    
+    ;; set options in the general tab...
+    (set-option!
+     gnc:pagename-general (N_ "Title") (N_ "General Journal"))
+    ;; we can't (currently) set the Report name here
+    ;; because it is automatically set to the template
+    ;; name... :(
+    
+    ;; set options in the display tab...
+    (for-each
+     (lambda (l)
+       (set-option! gnc:pagename-display (car l) (cadr l)))
+     ;; One list per option here with: option-name, default-value
+     (list
+      (list (N_ "Date") #t)
+      (list (N_ "Num") #f)
+      (list (N_ "Description") #t)
+      (list (N_ "Account") #t)
+      (list (N_ "Shares") #f)
+      (list (N_ "Price") #f)
+      ;; note the "Amount" multichoice option here
+      (list (N_ "Amount") 'double)
+      (list (N_ "Running Balance") #f)
+      (list (N_ "Totals") #f)
+      )
+     )
+    
+    options)
+  )
+
+;; report renderer
+
+(define (general-journal-renderer report-obj)
+  ;; just delegate rendering to the Register Report renderer...
+  ((gnc:report-template-renderer/name regrptname) report-obj))
+
+(gnc:define-report 
+ 'version 1
+ 'name reportname
+ 'menu-path (list gnc:menuname-asset-liability)
+ 'options-generator general-journal-options-generator
+ 'renderer general-journal-renderer
+ )
+
+;; END
+


More information about the gnucash-changes mailing list