r22885 - gnucash/trunk - Register rewrite Update, adds print check, find, schedule and reconcile. This update changes adds the print check, find transactions, schedule transactions and reconcile options to the new register. This was done by copying the existing files and changing them to work with the new register so both new and old could work at the same time. The new find option on the accounts page has been commented out so the old one would work but has been proved to work the same as on the new registers. Also have the refresh option working which involves reloading the register by re-running the query which is also used for the search register updates. Author: Robert Fewell

John Ralls jralls at code.gnucash.org
Sun Apr 7 18:14:31 EDT 2013


Author: jralls
Date: 2013-04-07 18:14:31 -0400 (Sun, 07 Apr 2013)
New Revision: 22885
Trac: http://svn.gnucash.org/trac/changeset/22885

Added:
   gnucash/trunk/src/gnome/dialog-find-transactions2.c
   gnucash/trunk/src/gnome/dialog-find-transactions2.h
   gnucash/trunk/src/gnome/dialog-print-check2.c
   gnucash/trunk/src/gnome/dialog-print-check2.h
   gnucash/trunk/src/gnome/window-reconcile2.c
   gnucash/trunk/src/gnome/window-reconcile2.h
Modified:
   gnucash/trunk/po/POTFILES.in
   gnucash/trunk/src/gnome-utils/gnc-tree-control-split-reg.c
   gnucash/trunk/src/gnome-utils/gnc-tree-control-split-reg.h
   gnucash/trunk/src/gnome-utils/gnc-tree-view-split-reg.c
   gnucash/trunk/src/gnome-utils/gnc-tree-view-split-reg.h
   gnucash/trunk/src/gnome/Makefile.am
   gnucash/trunk/src/gnome/gnc-plugin-basic-commands.c
   gnucash/trunk/src/gnome/gnc-plugin-page-register2.c
   gnucash/trunk/src/gnome/gnc-split-reg2.c
   gnucash/trunk/src/gnome/gnc-split-reg2.h
   gnucash/trunk/src/register/ledger-core/gnc-ledger-display2.c
Log:
Register rewrite Update, adds print check, find, schedule and reconcile. This update changes adds the print check, find transactions, schedule transactions and reconcile options to the new register. This was done by copying the existing files and changing them to work with the new register so both new and old could work at the same time. The new find option on the accounts page has been commented out so the old one would work but has been proved to work the same as on the new registers. Also have the refresh option working which involves reloading the register by re-running the query which is also used for the search register updates. Author: Robert Fewell

Modified: gnucash/trunk/po/POTFILES.in
===================================================================
--- gnucash/trunk/po/POTFILES.in	2013-04-07 22:14:20 UTC (rev 22884)
+++ gnucash/trunk/po/POTFILES.in	2013-04-07 22:14:31 UTC (rev 22885)
@@ -180,11 +180,13 @@
 src/gnome/dialog-commodities.c
 src/gnome/dialog-fincalc.c
 src/gnome/dialog-find-transactions.c
+src/gnome/dialog-find-transactions2.c
 src/gnome/dialog-lot-viewer.c
 src/gnome/dialog-new-user.c
 src/gnome/dialog-price-edit-db.c
 src/gnome/dialog-price-editor.c
 src/gnome/dialog-print-check.c
+src/gnome/dialog-print-check2.c
 src/gnome/dialog-progress.c
 src/gnome/dialog-sx-editor.c
 src/gnome/dialog-sx-from-trans.c
@@ -350,6 +352,7 @@
 src/gnome-utils/window-main-summarybar.c
 src/gnome/window-autoclear.c
 src/gnome/window-reconcile.c
+src/gnome/window-reconcile2.c
 src/html/gnc-html.c
 src/html/gnc-html-factory.c
 src/html/gnc-html-history.c

Modified: gnucash/trunk/src/gnome/Makefile.am
===================================================================
--- gnucash/trunk/src/gnome/Makefile.am	2013-04-07 22:14:20 UTC (rev 22884)
+++ gnucash/trunk/src/gnome/Makefile.am	2013-04-07 22:14:31 UTC (rev 22885)
@@ -32,11 +32,13 @@
   dialog-commodities.c \
   dialog-fincalc.c \
   dialog-find-transactions.c \
+  dialog-find-transactions2.c \
   dialog-lot-viewer.c \
   dialog-new-user.c \
   dialog-price-editor.c \
   dialog-price-edit-db.c \
   dialog-print-check.c \
+  dialog-print-check2.c \
   dialog-progress.c \
   dialog-sx-editor.c \
   dialog-sx-from-trans.c \
@@ -58,6 +60,7 @@
   reconcile-view.c \
   top-level.c \
   window-reconcile.c \
+  window-reconcile2.c \
   window-autoclear.c
 
 gnomeappdir = ${datadir}/applications
@@ -75,9 +78,11 @@
   assistant-stock-split.h \
   dialog-fincalc.h \
   dialog-find-transactions.h \
+  dialog-find-transactions2.h \
   dialog-lot-viewer.h \
   dialog-new-user.h \
   dialog-print-check.h \
+  dialog-print-check2.h \
   dialog-progress.h \
   dialog-sx-editor.h \
   dialog-sx-from-trans.h \
@@ -98,6 +103,7 @@
   reconcile-view.h \
   top-level.h \
   window-reconcile.h \
+  window-reconcile2.h \
   window-autoclear.h
 
 if BUILDING_FROM_SCM

Added: gnucash/trunk/src/gnome/dialog-find-transactions2.c
===================================================================
--- gnucash/trunk/src/gnome/dialog-find-transactions2.c	                        (rev 0)
+++ gnucash/trunk/src/gnome/dialog-find-transactions2.c	2013-04-07 22:14:31 UTC (rev 22885)
@@ -0,0 +1,216 @@
+/********************************************************************\
+ * dialog-find-transactions2.c : locate transactions and show them   *
+ * Copyright (C) 2000 Bill Gribble <grib at billgribble.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       *
+ * 51 Franklin Street, Fifth Floor    Fax:    +1-617-542-2652       *
+ * Boston, MA  02110-1301,  USA       gnu at gnu.org                   *
+\********************************************************************/
+
+#include "config.h"
+
+#include <gtk/gtk.h>
+#include <glib/gi18n.h>
+#include <stdio.h>
+
+#include "gnc-ui-util.h"
+#include "Query.h"
+#include "qof.h"
+#include "SX-book.h"
+#include "Transaction.h"
+#include "dialog-find-transactions2.h"
+#include "gnc-main-window.h"
+#include "gnc-plugin-page-register2.h"
+#include "search-param.h"
+
+#define GCONF_SECTION "dialogs/find"
+
+struct _ftd_data
+{
+    QofQuery *		q;
+    QofQuery *		ledger_q;
+    GNCSearchWindow *	sw;
+};
+
+static void
+do_find_cb (QofQuery *query, gpointer user_data, gpointer *result)
+{
+    struct _ftd_data *ftd = user_data;
+    GNCLedgerDisplay2 *ledger;
+    gboolean new_ledger = FALSE;
+    GncPluginPage *page;
+
+    ledger = gnc_ledger_display2_find_by_query (ftd->ledger_q);
+
+    if (!ledger)
+    {
+        new_ledger = TRUE;
+        ledger = gnc_ledger_display2_query (query, SEARCH_LEDGER2,
+                                           REG2_STYLE_JOURNAL);
+    }
+    else
+        gnc_ledger_display2_set_query (ledger, query);
+
+    gnc_ledger_display2_refresh (ledger);
+
+    if (new_ledger)
+    {
+        page = gnc_plugin_page_register2_new_ledger (ledger);
+        gnc_main_window_open_page (NULL, page);
+    }
+
+    qof_query_destroy (ftd->q);
+
+    gnc_search_dialog_destroy (ftd->sw);
+}
+
+static void
+free_ftd_cb (gpointer user_data)
+{
+    struct _ftd_data *ftd = user_data;
+
+    if (!ftd)
+        return;
+
+    g_free (ftd);
+}
+
+GNCSearchWindow *
+gnc_ui_find_transactions_dialog_create2 (GNCLedgerDisplay2 * orig_ledg)
+{
+    QofIdType type = GNC_ID_SPLIT;
+    struct _ftd_data *ftd;
+    static GList *params = NULL;
+    QofQuery *start_q, *show_q = NULL;
+    gboolean num_action =
+                qof_book_use_split_action_for_num_field(gnc_get_current_book());
+
+    /* Build parameter list in reverse order */
+    if (params == NULL)
+    {
+        params = gnc_search_param_prepend (params, N_("All Accounts"),
+                                           ACCOUNT_MATCH_ALL_TYPE,
+                                           type, SPLIT_TRANS, TRANS_SPLITLIST,
+                                           SPLIT_ACCOUNT_GUID, NULL);
+        params = gnc_search_param_prepend (params, N_("Account"), GNC_ID_ACCOUNT,
+                                           type, SPLIT_ACCOUNT, QOF_PARAM_GUID,
+                                           NULL);
+        params = gnc_search_param_prepend (params, N_("Balanced"), NULL,
+                                           type, SPLIT_TRANS, TRANS_IS_BALANCED,
+                                           NULL);
+        params = gnc_search_param_prepend (params, N_("Reconcile"), RECONCILED_MATCH_TYPE,
+                                           type, SPLIT_RECONCILE, NULL);
+        params = gnc_search_param_prepend (params, N_("Share Price"), NULL,
+                                           type, SPLIT_SHARE_PRICE, NULL);
+        params = gnc_search_param_prepend (params, N_("Shares"), NULL,
+                                           type, SPLIT_AMOUNT, NULL);
+        params = gnc_search_param_prepend (params, N_("Value"), NULL,
+                                           type, SPLIT_VALUE, NULL);
+        params = gnc_search_param_prepend (params, N_("Date Posted"), NULL,
+                                           type, SPLIT_TRANS, TRANS_DATE_POSTED,
+                                           NULL);
+        params = gnc_search_param_prepend (params, N_("Notes"), NULL,
+                                           type, SPLIT_TRANS, TRANS_NOTES, NULL);
+        params = gnc_search_param_prepend (params, (num_action
+                                                    ? N_("Number/Action")
+                                                    : N_("Action")), NULL,
+                                           type, SPLIT_ACTION, NULL);
+        params = gnc_search_param_prepend (params, (num_action
+                                                    ? N_("Transaction Number")
+                                                    : N_("Number")), NULL,
+                                           type, SPLIT_TRANS, TRANS_NUM, NULL);
+        params = gnc_search_param_prepend (params, N_("Memo"), NULL,
+                                           type, SPLIT_MEMO, NULL);
+        params = gnc_search_param_prepend (params, N_("Description"), NULL,
+                                           type, SPLIT_TRANS, TRANS_DESCRIPTION,
+                                           NULL);
+    }
+    else
+    {
+        GList *l;
+        for (l = params; l; l = l->next)
+        {
+            GNCSearchParam *param = l->data;
+
+            if (num_action)
+            {
+                if (strcmp (param->title, N_("Action")) == 0)
+                    gnc_search_param_set_title (param, N_("Number/Action"));
+                if (strcmp (param->title, N_("Number")) == 0)
+                    gnc_search_param_set_title (param, N_("Transaction Number"));
+            }
+            else
+            {
+                if (strcmp (param->title, N_("Number/Action")) == 0)
+                    gnc_search_param_set_title (param, N_("Action"));
+                if (strcmp (param->title, N_("Transaction Number")) == 0)
+                    gnc_search_param_set_title (param, N_("Number"));
+            }
+        }
+    }
+
+    ftd = g_new0 (struct _ftd_data, 1);
+
+    if (orig_ledg)
+    {
+        ftd->ledger_q = gnc_ledger_display2_get_query (orig_ledg);
+        start_q = show_q = qof_query_copy (ftd->ledger_q);
+    }
+    else
+    {
+        start_q = qof_query_create ();
+        qof_query_set_book (start_q, gnc_get_current_book ());
+
+        /* In lieu of not "mis-using" some portion of the infrastructure by writing
+         * a bunch of new code, we just filter out the accounts of the template
+         * transactions.  While these are in a seperate Account trees just for this
+         * reason, the query engine makes no distinction between Account trees.
+         * See Gnome Bug 86302.
+         * 	-- jsled
+         *
+         * copied from gnc-ledger-display2.c:gnc_ledger_display2_gl()  -- warlord
+         *
+         * <jsled> Alternatively, you could look for a GNC_SX_ACCOUNT [SchedAction.h]
+         * key in the KVP frame of the split.
+         */
+        {
+            Account *tRoot;
+            GList *al;
+
+            tRoot = gnc_book_get_template_root( gnc_get_current_book() );
+            al = gnc_account_get_descendants( tRoot );
+            xaccQueryAddAccountMatch( start_q, al, QOF_GUID_MATCH_NONE, QOF_QUERY_AND );
+            g_list_free (al);
+            al = NULL;
+            tRoot = NULL;
+        }
+
+        ftd->q = start_q;		/* save this to destroy it later */
+    }
+
+    ftd->sw = gnc_search_dialog_create (type, _("Find Transaction"),
+                                        params, NULL, start_q, show_q,
+                                        NULL, do_find_cb, NULL,
+                                        ftd, free_ftd_cb, GCONF_SECTION, NULL);
+
+    if (!ftd->sw)
+    {
+        free_ftd_cb (ftd);
+        return NULL;
+    }
+
+    return ftd->sw;
+}

Added: gnucash/trunk/src/gnome/dialog-find-transactions2.h
===================================================================
--- gnucash/trunk/src/gnome/dialog-find-transactions2.h	                        (rev 0)
+++ gnucash/trunk/src/gnome/dialog-find-transactions2.h	2013-04-07 22:14:31 UTC (rev 22885)
@@ -0,0 +1,33 @@
+/********************************************************************\
+ * dialog-find-transactions2.h : locate transactions/splits matching *
+ *                              criteria.                           *
+ * Copyright (C) 2000 Bill Gribble <grib at billgribble.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       *
+ * 51 Franklin Street, Fifth Floor    Fax:    +1-617-542-2652       *
+ * Boston, MA  02110-1301,  USA       gnu at gnu.org                   *
+\********************************************************************/
+
+#ifndef DIALOG_FIND_TRANSACTIONS2_H
+#define DIALOG_FIND_TRANSACTIONS2_H
+
+#include "gnc-ledger-display2.h"
+#include "dialog-search.h"
+
+GNCSearchWindow *
+gnc_ui_find_transactions_dialog_create2 (GNCLedgerDisplay2 * ledger);
+
+#endif

Added: gnucash/trunk/src/gnome/dialog-print-check2.c
===================================================================
--- gnucash/trunk/src/gnome/dialog-print-check2.c	                        (rev 0)
+++ gnucash/trunk/src/gnome/dialog-print-check2.c	2013-04-07 22:14:31 UTC (rev 22885)
@@ -0,0 +1,2689 @@
+/********************************************************************\
+ * dialog-print-check2.c : dialog to control check printing.         *
+ * Copyright (C) 2000 Bill Gribble <grib at billgribble.com>           *
+ * Copyright (C) 2006,2007 David Hampton <hampton at employees.org>    *
+ *                                                                  *
+ * 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       *
+ * 51 Franklin Street, Fifth Floor    Fax:    +1-617-542-2652       *
+ * Boston, MA  02110-1301,  USA       gnu at gnu.org                   *
+\********************************************************************/
+
+/**
+ * @file dialog-print-check2.c
+ * @brief Print Checks Dialog
+ * @author Copyright (C) 2000 Bill Gribble <grib at billgribble.com>
+ * @author Copyright (C) 2006,2007 David Hampton <hampton at employees.org>
+ */
+
+#include "config.h"
+
+#include <gtk/gtk.h>
+#include <glib/gi18n.h>
+#include <stdio.h>
+#include <locale.h>
+#include <math.h>
+
+#include <gnc-gdate-utils.h>
+#include "qof.h"
+#include "gnc-date.h"
+#include "gnc-gconf-utils.h"
+#include "gnc-numeric.h"
+#include "gnc-plugin-page-register2.h"
+#include "dialog-print-check2.h"
+#include "dialog-utils.h"
+#include "print-session.h"
+#include "gnc-ui.h"
+#include "gnc-date-format.h"
+#include "gnc-ui-util.h"
+#include "gnc-path.h"
+#include "gnc-filepath-utils.h"
+#include "gnc-gkeyfile-utils.h"
+
+#include "gnc-engine.h"
+#include "engine-helpers.h"
+#include "Split.h"
+#include "Transaction.h"
+
+#undef G_LOG_DOMAIN
+#define G_LOG_DOMAIN "gnc.printing.checks"
+
+/* This static indicates the debugging module that this .o belongs to.
+ */
+G_GNUC_UNUSED static QofLogModule log_module = "gnc.printing.checks";
+
+#define GCONF_SECTION 	       "dialogs/print_checks"
+#define KEY_CHECK_FORMAT_GUID  "check_format_guid"
+#define KEY_CHECK_FORMAT       "check_format"
+#define KEY_CHECK_POSITION     "check_position"
+#define KEY_FIRST_PAGE_COUNT   "first_page_count"
+#define KEY_DATE_FORMAT_USER   "date_format_custom"
+#define KEY_CUSTOM_PAYEE       "custom_payee"
+#define KEY_CUSTOM_DATE        "custom_date"
+#define KEY_CUSTOM_WORDS       "custom_amount_words"
+#define KEY_CUSTOM_NUMBER      "custom_amount_number"
+#define KEY_CUSTOM_ADDRESS     "custom_address"
+#define KEY_CUSTOM_NOTES       "custom_memo" /* historically misnamed */
+#define KEY_CUSTOM_MEMO        "custom_memo2"
+#define KEY_CUSTOM_TRANSLATION "custom_translation"
+#define KEY_CUSTOM_ROTATION    "custom_rotation"
+#define KEY_CUSTOM_UNITS       "custom_units"
+#define KEY_PRINT_DATE_FMT     "print_date_format"
+#define KEY_DEFAULT_FONT       "default_font"
+#define KEY_BLOCKING_CHARS     "blocking_chars"
+#define KEY_SPLITS_AMOUNT      "splits_amount"
+#define KEY_SPLITS_MEMO        "splits_memo"
+#define KEY_SPLITS_ACCOUNT     "splits_account"
+
+#define DEFAULT_FONT            "sans 12"
+#define CHECK_FMT_DIR           "checks"
+#define CHECK_NAME_EXTENSION    ".chk"
+#define DEGREES_TO_RADIANS      (G_PI / 180.0)
+
+#define BLOCKING_CHAR_OFF	0
+#define BLOCKING_CHAR_ON	1
+
+#define KF_GROUP_TOP       "Top"
+#define KF_GROUP_POS       "Check Positions"
+#define KF_GROUP_ITEMS     "Check Items"
+#define KF_KEY_GUID        "Guid"
+#define KF_KEY_TITLE       "Title"
+#define KF_KEY_ROTATION    "Rotation"
+#define KF_KEY_TRANSLATION "Translation"
+#define KF_KEY_FONT        "Font"
+#define KF_KEY_ALIGN       "Align"
+#define KF_KEY_BLOCKING    "Blocking_Chars"
+#define KF_KEY_SHOW_GRID   "Show_Grid"
+#define KF_KEY_SHOW_BOXES  "Show_Boxes"
+#define KF_KEY_NAMES       "Names"
+#define KF_KEY_HEIGHT      "Height"
+#define KF_KEY_TYPE        "Type"
+#define KF_KEY_COORDS      "Coords"
+#define KF_KEY_TEXT        "Text"
+#define KF_KEY_FILENAME    "Filename"
+#define KF_KEY_DATE_FORMAT "DateFormat"
+#define KF_KEY_SPLITS_AMOUNT  "SplitsAmount"
+#define KF_KEY_SPLITS_MEMO    "SplitsMemo"
+#define KF_KEY_SPLITS_ACCOUNT "SplitsAccount"
+
+/* This enum specifies the columns used in the check format combobox.
+ */
+typedef enum format_combo_col_t
+{
+    COL_NAME = 0,               /**< This column holds a copy of the check
+                                 *   format name and is what is displayed to
+                                 *   the user in the combobox. It is NULL for
+                                 *   separator lines. */
+    COL_DATA,                   /**< This column holds a pointer to the check
+                                 *   format data read in from a file.  It is
+                                 *   NULL for the custom check format and for
+                                 *   separator lines. */
+    COL_SEP,                    /**< This column contains the value TRUE if
+                                 *   this entry specifies a separator line. */
+} format_combo_col;
+
+void gnc_ui_print_check_response_cb2 (GtkDialog *dialog, gint response, PrintCheckDialog *pcd);
+void gnc_print_check_format_changed2 (GtkComboBox *widget, PrintCheckDialog *pcd);
+void gnc_print_check_position_changed2 (GtkComboBox *widget, PrintCheckDialog *pcd);
+void gnc_print_check_save_button_clicked2 (GtkButton *button, PrintCheckDialog *pcd);
+void gnc_check_format_title_changed2 (GtkEditable *editable, GtkWidget *ok_button);
+
+static void initialize_format_combobox (PrintCheckDialog *pcd);
+gchar* get_check_address2 (PrintCheckDialog *pcd);
+static gboolean check_format_has_address (PrintCheckDialog *pcd);
+gchar* get_check_splits_amount2 (PrintCheckDialog *pcd);
+gchar* get_check_splits_memo2 (PrintCheckDialog *pcd);
+gchar* get_check_splits_account2 (PrintCheckDialog *pcd);
+
+/* This enum defines the types of items that gnucash knows how to
+ * print on checks.  Most refer to specific fields from a gnucash
+ * transaction and split, but some are generic items unrelated to
+ * gnucash.
+ */
+#define ENUM_CHECK_ITEM_TYPE(_) \
+        _(NONE,) \
+        _(PAYEE,) \
+        _(DATE,) \
+        _(NOTES,) \
+        _(CHECK_NUMBER,) \
+                  \
+        _(MEMO,) \
+        _(ACTION,) \
+        _(AMOUNT_NUMBER,) \
+        _(AMOUNT_WORDS,) \
+                         \
+        _(TEXT,) \
+        _(ADDRESS,) \
+        _(DATE_FORMAT,) \
+        _(SPLITS_AMOUNT,) \
+        _(SPLITS_MEMO,) \
+        _(SPLITS_ACCOUNT,) \
+        _(PICTURE,)
+
+DEFINE_ENUM(CheckItemType2, ENUM_CHECK_ITEM_TYPE)
+FROM_STRING_DEC(CheckItemType2, ENUM_CHECK_ITEM_TYPE)
+FROM_STRING_FUNC(CheckItemType2, ENUM_CHECK_ITEM_TYPE)
+AS_STRING_DEC(CheckItemType2, ENUM_CHECK_ITEM_TYPE)
+AS_STRING_FUNC(CheckItemType2, ENUM_CHECK_ITEM_TYPE)
+
+/* This data structure describes a single item printed on a check.
+ * It is built from a description in a text file.
+ */
+typedef struct _check_item
+{
+
+    CheckItemType2 type;         /**< What type of item is this?  */
+
+    gdouble x, y;               /**< The x/y coordinates where this item should
+                                 *   be printed.  The origin for these
+                                 *   coordinates is determined by the print
+                                 *   system used.  */
+
+    gdouble w, h;               /**< Optional. The width and height of this
+                                 *   item.  Text will be clipped to this
+                                 *   size. Pictures will be shrunk to fit if
+                                 *   necessary.  */
+
+    gchar *filename;            /**< The filename for picture items. Otherwise
+                                 *   unused. */
+
+    gchar *text;                /**< The text to be displayed (for text based
+                                 *   items.) Otherwise unused.  */
+
+    gchar *font;                /**< The font to use for text based items. This
+                                 *   overrides any font in the check format.
+                                 *   Unused for non-text items. */
+
+    gboolean blocking;          /**< Optional. Overrides blocking in the check
+                                 *   format. Default is no blocking characters
+                                 *   are written.  Unused for non-text
+                                 *   items. */
+
+    gboolean print_date_format; /**< Optional.  Print date format.  Only
+                                 *   applies to DATE items.  Default is no
+                                 *   format is written. */
+
+    PangoAlignment align;       /**< The alignment of a text based item. Only
+                                 *   used for text based items when a width is
+                                 *   specified.  */
+} check_item_t;
+
+/* This data structure describes an entire page of checks.  Depending
+ * upon the check format, the page may contain multiple checks or
+ * only a single check.  The data structure is built from a
+ * description in a text file.
+ */
+typedef struct _check_format
+{
+
+    gchar *guid;                /**< Unique identifier for this format. */
+
+    const gchar *group;         /**< The group where this format was found. */
+
+    gchar *filename;            /**< The name of the file from which this data
+                                 *   was read.  */
+
+    gchar *title;               /**< Title of this check format. Displayed in
+                                 *   the dialog box. */
+
+    gboolean blocking;          /**< Default for printing blocking characters for
+                                 *   this page of checks.  */
+
+    gboolean print_date_format; /**< Default for printing date format characters for
+                                 *   this page of checks.  */
+
+    gboolean show_grid;         /**< Print a grid pattern on the page */
+
+    gboolean show_boxes;        /**< Print boxes when width and height are
+                                 *   known. */
+
+    gdouble rotation;           /**< Rotate the entire page by this amount. */
+
+    gdouble trans_x;            /**< Move entire page left by this amount. */
+
+    gdouble trans_y;            /**< Move entire page down by this amount. */
+
+    gchar *font;                /**< Default font for this page of checks. */
+
+    gdouble height;             /**< Height of one check on a page. */
+
+    GSList *positions;          /**< Names of the checks on the page. */
+
+    GSList *items;              /**< List of items printed on each check. */
+} check_format_t;
+
+
+/* This data structure is used to manage the print check dialog, and
+ * the overall check printing process.  It contains pointers to many
+ * of the widgets in the dialog, pointers to the check descriptions
+ * that have been read, and also contains the data from the gnucash
+ * transaction/split that is to be printed.
+ */
+struct _print_check_dialog
+{
+    GtkBuilder *builder;
+    GtkWidget *dialog;
+    GtkWindow *caller_window;
+
+    GncPluginPageRegister2 *plugin_page;
+    Split *split;
+    GList *splits;
+
+    GtkWidget *format_combobox;
+    gint format_max;
+    GtkWidget *position_combobox;
+    gint position_max;
+    GtkSpinButton *first_page_count;
+    GtkWidget *custom_table;
+    GtkSpinButton *payee_x, *payee_y;
+    GtkSpinButton *date_x, *date_y;
+    GtkSpinButton *words_x, *words_y;
+    GtkSpinButton *number_x, *number_y;
+    GtkSpinButton *address_x, *address_y;
+    GtkSpinButton *notes_x, *notes_y;
+    GtkSpinButton *memo_x, *memo_y;
+    GtkSpinButton *splits_amount_x, *splits_amount_y;
+    GtkSpinButton *splits_memo_x, *splits_memo_y;
+    GtkSpinButton *splits_account_x, *splits_account_y;
+    GtkSpinButton *translation_x, *translation_y;
+    GtkSpinButton *check_rotation;
+    GtkWidget *translation_label;
+
+    GtkWidget *units_combobox;
+
+    GtkWidget *date_format;
+
+    GtkWidget *check_address_name;
+    GtkWidget *check_address_1;
+    GtkWidget *check_address_2;
+    GtkWidget *check_address_3;
+    GtkWidget *check_address_4;
+
+    gchar *default_font;
+
+    check_format_t *selected_format;
+};
+
+
+/* This function walks ths list of available check formats looking for a
+ * specific format as specified by guid number.  If found, a pointer to it is
+ * returned to the caller.  Additionally, if the caller passed a pointer to a
+ * GtkTreeIter, then the iter for that entry will also be returned.
+ */
+static check_format_t *
+find_existing_format (GtkListStore *store, gchar *guid, GtkTreeIter *iter_out)
+{
+    GtkTreeIter iter;
+    check_format_t *format;
+
+    g_return_val_if_fail(store, NULL);
+    g_return_val_if_fail(guid, NULL);
+
+    if (!gtk_tree_model_get_iter_first(GTK_TREE_MODEL(store), &iter))
+        return NULL;
+
+    do
+    {
+        gtk_tree_model_get(GTK_TREE_MODEL(store), &iter,
+                           COL_DATA, &format, -1);
+        if (format == NULL)
+            continue;
+        if (strcmp(format->guid, guid) != 0)
+            continue;
+
+        if (iter_out)
+            *iter_out = iter;
+        return format;
+    }
+    while (gtk_tree_model_iter_next(GTK_TREE_MODEL(store), &iter));
+
+    return NULL;
+}
+
+
+/* This function is used by the custom format dialog to save position values
+ * to the GConf database.
+ */
+static void
+save_float_pair (const char *section, const char *key, double a, double b)
+{
+    GSList *coord_list = NULL;
+
+    coord_list = g_slist_append(coord_list, &a);
+    coord_list = g_slist_append(coord_list, &b);
+    gnc_gconf_set_list(section, key, GCONF_VALUE_FLOAT, coord_list, NULL);
+    g_slist_free(coord_list);
+}
+
+
+/* This function is used by the custom format dialog to restore position
+ * values from the GConf database.
+ */
+static void
+get_float_pair (const char *section, const char *key, double *a, double *b)
+{
+    GSList *coord_list;
+
+    coord_list = gnc_gconf_get_list (section, key, GCONF_VALUE_FLOAT, NULL);
+    if (NULL == coord_list)
+    {
+        *a = 0;
+        *b = 0;
+        return;
+    }
+
+    *a = *(gdouble*)g_slist_nth_data(coord_list, 0);
+    *b = *(gdouble*)g_slist_nth_data(coord_list, 1);
+    g_slist_free(coord_list);
+}
+
+
+/* This function returns a string containing the check address in a five-line
+ * format.
+ *
+ * Note that the string needs to be freed with g_free.
+ */
+gchar *
+get_check_address2( PrintCheckDialog *pcd)
+{
+    gchar *address;
+    address = g_strconcat(gtk_entry_get_text(GTK_ENTRY(pcd->check_address_name)), "\n",
+                          gtk_entry_get_text(GTK_ENTRY(pcd->check_address_1)), "\n",
+                          gtk_entry_get_text(GTK_ENTRY(pcd->check_address_2)), "\n",
+                          gtk_entry_get_text(GTK_ENTRY(pcd->check_address_3)), "\n",
+                          gtk_entry_get_text(GTK_ENTRY(pcd->check_address_4)),
+                          NULL);
+    return address;
+}
+
+
+//@{
+/** @name Split printing functions */
+
+/* This function formats the splits amounts for printing.
+ */
+gchar *
+get_check_splits_amount2(PrintCheckDialog *pcd)
+{
+    gchar* amount = NULL;
+    gchar* amt_temp;
+    int cnt;
+    const gchar* split_amount;
+    int nSplits;
+    Transaction *trans;
+    Split *split;
+    GList *node;
+    SplitList* s_list;
+
+    trans = xaccSplitGetParent(pcd->split);
+    nSplits = xaccTransCountSplits(trans);
+    s_list = xaccTransGetSplitList(trans);
+    if ( !s_list ) return NULL;
+
+    amount = g_strconcat("", NULL);
+    node = s_list;
+    cnt = 1;
+    while ( cnt < nSplits )
+    {
+        cnt++;
+        split = node->data;
+        split_amount = xaccPrintAmount(xaccSplitGetAmount(split), gnc_split_amount_print_info(split, TRUE));
+        amt_temp = amount;
+        amount = g_strconcat(amt_temp, "\n", split_amount, NULL);
+        g_free(amt_temp);
+        node = node->next;
+    }
+    return amount;
+}
+
+
+/* This function formats the splits memo fields for printing.
+ */
+gchar *
+get_check_splits_memo2(PrintCheckDialog *pcd)
+{
+    gchar* memo = NULL;
+    gchar* memo_temp;
+    int cnt;
+    const gchar* split_memo;
+    int nSplits;
+    Transaction *trans;
+    Split *split;
+    GList *node;
+    SplitList* s_list;
+
+    trans = xaccSplitGetParent(pcd->split);
+    nSplits = xaccTransCountSplits(trans);
+    s_list = xaccTransGetSplitList(trans);
+    if ( !s_list ) return NULL;
+
+    memo = g_strconcat("", NULL);
+    node = s_list;
+    cnt = 1;
+    while ( cnt < nSplits )
+    {
+        cnt++;
+        split = node->data;
+        split_memo = xaccSplitGetMemo(split);
+        memo_temp = memo;
+        memo = g_strconcat(memo_temp, "\n", split_memo, NULL);
+        g_free(memo_temp);
+        node = node->next;
+    }
+    return memo;
+}
+
+
+/* This function formats the splits accounts for printing.
+ */
+gchar *
+get_check_splits_account2(PrintCheckDialog *pcd)
+{
+    gchar* account = NULL;
+    gchar* account_temp;
+    int cnt;
+    const gchar* aName = NULL;
+    int nSplits;
+    Account *pAccount;
+    Transaction *trans;
+    Split *split;
+    GList *node;
+    SplitList* s_list;
+
+    trans = xaccSplitGetParent(pcd->split);
+    nSplits = xaccTransCountSplits(trans);
+    s_list = xaccTransGetSplitList(trans);
+    if ( !s_list ) return NULL;
+
+    account = g_strconcat("", NULL);
+    node = s_list;
+    cnt = 1;
+    while ( cnt < nSplits )
+    {
+        cnt++;
+        split = node->data;
+        pAccount = xaccSplitGetAccount(split);
+        aName = gnc_get_account_name_for_register(pAccount);
+        account_temp = account;
+        account = g_strconcat(account_temp, "\n", aName, NULL);
+        g_free(account_temp);
+        node = node->next;
+    }
+    return account;
+}
+//@}
+
+
+/* This function determines if an address item is present in the check format.
+ */
+static gboolean
+check_format_has_address ( PrintCheckDialog *pcd )
+{
+    /* check format for an ADDRESS item */
+    check_item_t *item = NULL;
+    GSList *elem;
+    check_format_t *format = NULL;
+
+    if ( !pcd ) return FALSE;
+
+    /* If we're printing more than one check no addresses are allowed */
+    if (g_list_length(pcd->splits) != 1)
+        return FALSE;
+
+    /* if format is NULL, then the custom format is being used
+     * which has an ADDRESS item by definition */
+    format = pcd->selected_format;
+    if ( !format ) return TRUE;
+
+    for (elem = pcd->selected_format->items; elem; elem = g_slist_next(elem))
+    {
+        item = elem->data;
+        if ( item->type == ADDRESS ) return TRUE;
+    }
+    return FALSE;
+}
+
+
+static void
+gnc_ui_print_save_dialog(PrintCheckDialog *pcd)
+{
+    GtkTreeModel *model;
+    GtkTreeIter iter;
+    check_format_t *check;
+    const gchar *format;
+    gint active;
+
+    /* Options page */
+    if (gtk_combo_box_get_active_iter(GTK_COMBO_BOX(pcd->format_combobox),
+                                      &iter))
+    {
+        model = gtk_combo_box_get_model(GTK_COMBO_BOX(pcd->format_combobox));
+        gtk_tree_model_get(model, &iter, COL_DATA, &check, -1);
+        gnc_gconf_set_string(GCONF_SECTION, KEY_CHECK_FORMAT_GUID,
+                             check ? check->guid : "custom", NULL);
+    }
+    active = gtk_combo_box_get_active(GTK_COMBO_BOX(pcd->position_combobox));
+    gnc_gconf_set_int(GCONF_SECTION, KEY_CHECK_POSITION, active, NULL);
+    active = gtk_spin_button_get_value_as_int(pcd->first_page_count);
+    gnc_gconf_set_int(GCONF_SECTION, KEY_FIRST_PAGE_COUNT, active, NULL);
+    active = gnc_date_format_get_format (GNC_DATE_FORMAT(pcd->date_format));
+    gnc_gconf_set_int(GCONF_SECTION, KEY_DATE_FORMAT, active, NULL);
+    if (active == QOF_DATE_FORMAT_CUSTOM)
+    {
+        format = gnc_date_format_get_custom (GNC_DATE_FORMAT(pcd->date_format));
+        gnc_gconf_set_string(GCONF_SECTION, KEY_DATE_FORMAT_USER, format, NULL);
+    }
+    else
+    {
+        gnc_gconf_unset (GCONF_SECTION, KEY_DATE_FORMAT_USER, NULL);
+    }
+
+    /* Custom format page */
+    save_float_pair(GCONF_SECTION, KEY_CUSTOM_PAYEE,
+                    gtk_spin_button_get_value(pcd->payee_x),
+                    gtk_spin_button_get_value(pcd->payee_y));
+    save_float_pair(GCONF_SECTION, KEY_CUSTOM_DATE,
+                    gtk_spin_button_get_value(pcd->date_x),
+                    gtk_spin_button_get_value(pcd->date_y));
+    save_float_pair(GCONF_SECTION, KEY_CUSTOM_WORDS,
+                    gtk_spin_button_get_value(pcd->words_x),
+                    gtk_spin_button_get_value(pcd->words_y));
+    save_float_pair(GCONF_SECTION, KEY_CUSTOM_NUMBER,
+                    gtk_spin_button_get_value(pcd->number_x),
+                    gtk_spin_button_get_value(pcd->number_y));
+    save_float_pair(GCONF_SECTION, KEY_CUSTOM_NOTES,
+                    gtk_spin_button_get_value(pcd->notes_x),
+                    gtk_spin_button_get_value(pcd->notes_y));
+    save_float_pair(GCONF_SECTION, KEY_CUSTOM_MEMO,
+                    gtk_spin_button_get_value(pcd->memo_x),
+                    gtk_spin_button_get_value(pcd->memo_y));
+    save_float_pair(GCONF_SECTION, KEY_CUSTOM_ADDRESS,
+                    gtk_spin_button_get_value(pcd->address_x),
+                    gtk_spin_button_get_value(pcd->address_y));
+    save_float_pair(GCONF_SECTION, KEY_SPLITS_AMOUNT,
+                    gtk_spin_button_get_value(pcd->splits_amount_x),
+                    gtk_spin_button_get_value(pcd->splits_amount_y));
+    save_float_pair(GCONF_SECTION, KEY_SPLITS_MEMO,
+                    gtk_spin_button_get_value(pcd->splits_memo_x),
+                    gtk_spin_button_get_value(pcd->splits_memo_y));
+    save_float_pair(GCONF_SECTION, KEY_SPLITS_ACCOUNT,
+                    gtk_spin_button_get_value(pcd->splits_account_x),
+                    gtk_spin_button_get_value(pcd->splits_account_y));
+    save_float_pair(GCONF_SECTION, KEY_CUSTOM_TRANSLATION,
+                    gtk_spin_button_get_value(pcd->translation_x),
+                    gtk_spin_button_get_value(pcd->translation_y));
+    gnc_gconf_set_float(GCONF_SECTION, KEY_CUSTOM_ROTATION,
+                        gtk_spin_button_get_value(pcd->check_rotation),
+                        NULL);
+    active = gtk_combo_box_get_active(GTK_COMBO_BOX(pcd->units_combobox));
+    gnc_gconf_set_int(GCONF_SECTION, KEY_CUSTOM_UNITS, active, NULL);
+}
+
+
+static void
+gnc_ui_print_restore_dialog(PrintCheckDialog *pcd)
+{
+    GtkTreeModel *model;
+    GtkTreeIter iter;
+    gchar *format, *guid;
+    gdouble x, y;
+    gint active;
+
+    /* Options page */
+    guid = gnc_gconf_get_string(GCONF_SECTION, KEY_CHECK_FORMAT_GUID, NULL);
+    if (guid == NULL)
+    {
+        active = gnc_gconf_get_int(GCONF_SECTION, KEY_CHECK_FORMAT, NULL);
+        gtk_combo_box_set_active(GTK_COMBO_BOX(pcd->format_combobox), active);
+    }
+    else if (strcmp(guid, "custom") == 0)
+    {
+        gtk_combo_box_set_active(GTK_COMBO_BOX(pcd->format_combobox),
+                                 pcd->format_max - 1);
+    }
+    else
+    {
+        model = gtk_combo_box_get_model(GTK_COMBO_BOX(pcd->format_combobox));
+        if (find_existing_format(GTK_LIST_STORE(model), guid, &iter))
+        {
+            gtk_combo_box_set_active_iter(GTK_COMBO_BOX(pcd->format_combobox), &iter);
+        }
+        else
+        {
+            gtk_combo_box_set_active(GTK_COMBO_BOX(pcd->format_combobox), 0);
+        }
+    }
+    active = gnc_gconf_get_int(GCONF_SECTION, KEY_CHECK_POSITION, NULL);
+
+    /* If the check format used last time no longer exists, then the saved check
+       position may be invalid.  If so set it to the first position. */
+    if (active < 0 || active > pcd->position_max)
+        active = 0;
+    gtk_combo_box_set_active(GTK_COMBO_BOX(pcd->position_combobox), active);
+    active = gnc_gconf_get_int(GCONF_SECTION, KEY_FIRST_PAGE_COUNT, NULL);
+    gtk_spin_button_set_value(pcd->first_page_count, (gdouble) active);
+    active = gnc_gconf_get_int(GCONF_SECTION, KEY_DATE_FORMAT, NULL);
+    gnc_date_format_set_format(GNC_DATE_FORMAT(pcd->date_format), active);
+    if (active == QOF_DATE_FORMAT_CUSTOM)
+    {
+        format = gnc_gconf_get_string(GCONF_SECTION, KEY_DATE_FORMAT_USER, NULL);
+        if (format)
+        {
+            gnc_date_format_set_custom(GNC_DATE_FORMAT(pcd->date_format), format);
+            g_free(format);
+        }
+    }
+
+    /* Custom format page */
+    get_float_pair(GCONF_SECTION, KEY_CUSTOM_PAYEE, &x, &y);
+    gtk_spin_button_set_value(pcd->payee_x, x);
+    gtk_spin_button_set_value(pcd->payee_y, y);
+
+    get_float_pair(GCONF_SECTION, KEY_CUSTOM_DATE, &x, &y);
+    gtk_spin_button_set_value(pcd->date_x, x);
+    gtk_spin_button_set_value(pcd->date_y, y);
+    get_float_pair(GCONF_SECTION, KEY_CUSTOM_WORDS, &x, &y);
+    gtk_spin_button_set_value(pcd->words_x, x);
+    gtk_spin_button_set_value(pcd->words_y, y);
+    get_float_pair(GCONF_SECTION, KEY_CUSTOM_NUMBER, &x, &y);
+    gtk_spin_button_set_value(pcd->number_x, x);
+    gtk_spin_button_set_value(pcd->number_y, y);
+    get_float_pair(GCONF_SECTION, KEY_CUSTOM_ADDRESS, &x, &y);
+    gtk_spin_button_set_value(pcd->address_x, x);
+    gtk_spin_button_set_value(pcd->address_y, y);
+    get_float_pair(GCONF_SECTION, KEY_CUSTOM_NOTES, &x, &y);
+    gtk_spin_button_set_value(pcd->notes_x, x);
+    gtk_spin_button_set_value(pcd->notes_y, y);
+    get_float_pair(GCONF_SECTION, KEY_CUSTOM_MEMO, &x, &y);
+    gtk_spin_button_set_value(pcd->memo_x, x);
+    gtk_spin_button_set_value(pcd->memo_y, y);
+    get_float_pair(GCONF_SECTION, KEY_SPLITS_AMOUNT, &x, &y);
+    gtk_spin_button_set_value(pcd->splits_amount_x, x);
+    gtk_spin_button_set_value(pcd->splits_amount_y, y);
+    get_float_pair(GCONF_SECTION, KEY_SPLITS_MEMO, &x, &y);
+    gtk_spin_button_set_value(pcd->splits_memo_x, x);
+    gtk_spin_button_set_value(pcd->splits_memo_y, y);
+    get_float_pair(GCONF_SECTION, KEY_SPLITS_ACCOUNT, &x, &y);
+    gtk_spin_button_set_value(pcd->splits_account_x, x);
+    gtk_spin_button_set_value(pcd->splits_account_y, y);
+    get_float_pair(GCONF_SECTION, KEY_CUSTOM_TRANSLATION, &x, &y);
+    gtk_spin_button_set_value(pcd->translation_x, x);
+    gtk_spin_button_set_value(pcd->translation_y, y);
+    x = gnc_gconf_get_float(GCONF_SECTION, KEY_CUSTOM_ROTATION, NULL);
+    gtk_spin_button_set_value(pcd->check_rotation, x);
+    active = gnc_gconf_get_int(GCONF_SECTION, KEY_CUSTOM_UNITS, NULL);
+    gtk_combo_box_set_active(GTK_COMBO_BOX(pcd->units_combobox), active);
+}
+
+
+static gdouble
+pcd_get_custom_multip(PrintCheckDialog *pcd)
+{
+    gint selected;
+
+    selected = gtk_combo_box_get_active(GTK_COMBO_BOX(pcd->units_combobox));
+    switch (selected)
+    {
+    default:
+        return 72.0;        /* inches */
+    case 1:
+        return 28.346;      /* cm */
+    case 2:
+        return 2.8346;      /* mm */
+    case 3:
+        return 1.0;         /* points */
+    }
+}
+
+
+/* This function saves a coordinate pair into a check description file.  It
+ * extracts the values from the spin buttons, adjusts them according to the
+ * unit multiplier (inches, pixels, etc), then adds them to the gKeyFile.
+ */
+static void
+pcd_key_file_save_xy (GKeyFile *key_file, const gchar *group_name,
+                      const gchar *key_name, gdouble multip,
+                      GtkSpinButton *spin0, GtkSpinButton *spin1)
+{
+    gdouble dd[2];
+
+    dd[0] = multip * gtk_spin_button_get_value(spin0);
+    dd[1] = multip * gtk_spin_button_get_value(spin1);
+
+    /* Clip the numbers to three decimal places. */
+    dd[0] = round(dd[0] * 1000) / 1000;
+    dd[1] = round(dd[1] * 1000) / 1000;
+    g_key_file_set_double_list(key_file, group_name, key_name, dd, 2);
+}
+
+
+/* This function saves the information about a single printed item into a
+ * check description file.  It uses a helper function to extracts and save the
+ * item coordinates.
+ */
+static void
+pcd_key_file_save_item_xy (GKeyFile *key_file, int index,
+                           CheckItemType2 type, gdouble multip,
+                           GtkSpinButton *spin0, GtkSpinButton *spin1)
+{
+    gchar *key;
+    key = g_strdup_printf("Type_%d", index);
+    g_key_file_set_string(key_file, KF_GROUP_ITEMS, key,
+                          CheckItemType2asString(type));
+    g_free(key);
+    key = g_strdup_printf("Coords_%d", index);
+    pcd_key_file_save_xy(key_file, KF_GROUP_ITEMS, key, multip, spin0, spin1);
+    g_free(key);
+}
+
+
+/* This function saves all of the information from the custom check dialog
+ *  into a check description file.
+ */
+static void
+pcd_save_custom_data(PrintCheckDialog *pcd, const gchar *title)
+{
+    GKeyFile *key_file;
+    GError *error = NULL;
+    GtkWidget *dialog;
+    gdouble multip;
+    gint i = 1;
+    GncGUID guid;
+    char buf[GUID_ENCODING_LENGTH+1];
+    gchar *filename, *pathname;
+
+    multip = pcd_get_custom_multip(pcd);
+
+    key_file = g_key_file_new();
+    guid_new(&guid);
+    guid_to_string_buff(&guid, buf);
+    g_key_file_set_string(key_file, KF_GROUP_TOP, KF_KEY_GUID, buf);
+    g_key_file_set_string(key_file, KF_GROUP_TOP, KF_KEY_TITLE, title);
+    g_key_file_set_boolean(key_file, KF_GROUP_TOP, KF_KEY_SHOW_GRID, FALSE);
+    g_key_file_set_boolean(key_file, KF_GROUP_TOP, KF_KEY_SHOW_BOXES, FALSE);
+    g_key_file_set_double(key_file, KF_GROUP_TOP, KF_KEY_ROTATION,
+                          gtk_spin_button_get_value(pcd->check_rotation));
+    pcd_key_file_save_xy(key_file, KF_GROUP_TOP, KF_KEY_TRANSLATION, multip,
+                         pcd->translation_x, pcd->translation_y);
+
+    pcd_key_file_save_item_xy(key_file, i++, PAYEE, multip,
+                              pcd->payee_x, pcd->payee_y);
+    pcd_key_file_save_item_xy(key_file, i++, DATE, multip,
+                              pcd->date_x, pcd->date_y);
+    pcd_key_file_save_item_xy(key_file, i++, AMOUNT_WORDS, multip,
+                              pcd->words_x, pcd->words_y);
+    pcd_key_file_save_item_xy(key_file, i++, AMOUNT_NUMBER, multip,
+                              pcd->number_x, pcd->number_y);
+    pcd_key_file_save_item_xy(key_file, i++, ADDRESS, multip,
+                              pcd->address_x, pcd->address_y);
+    pcd_key_file_save_item_xy(key_file, i++, NOTES, multip,
+                              pcd->notes_x, pcd->notes_y);
+    pcd_key_file_save_item_xy(key_file, i++, MEMO, multip,
+                              pcd->memo_x, pcd->memo_y);
+    pcd_key_file_save_item_xy(key_file, i++, SPLITS_AMOUNT, multip,
+                              pcd->splits_amount_x, pcd->splits_amount_y);
+    pcd_key_file_save_item_xy(key_file, i++, SPLITS_MEMO, multip,
+                              pcd->splits_memo_x, pcd->splits_memo_y);
+    pcd_key_file_save_item_xy(key_file, i++, SPLITS_ACCOUNT, multip,
+                              pcd->splits_account_x, pcd->splits_account_y);
+
+    filename = g_strconcat(title, CHECK_NAME_EXTENSION, NULL);
+    pathname = g_build_filename(gnc_dotgnucash_dir(), CHECK_FMT_DIR,
+                                filename, NULL);
+
+    if (gnc_key_file_save_to_file(pathname, key_file, &error))
+    {
+        if (!gnc_gconf_get_bool(GCONF_SECTION, KEY_PRINT_DATE_FMT, NULL))
+            /* Reload the format combo box and reselect the "custom" entry */
+            initialize_format_combobox(pcd);
+
+        gtk_combo_box_set_active(GTK_COMBO_BOX(pcd->format_combobox),
+                                 pcd->format_max - 1);
+    }
+    else
+    {
+        dialog = gtk_message_dialog_new(GTK_WINDOW(pcd->dialog),
+                                        GTK_DIALOG_DESTROY_WITH_PARENT,
+                                        GTK_MESSAGE_ERROR,
+                                        GTK_BUTTONS_CLOSE, "%s",
+                                        _("Cannot save check format file."));
+        gtk_message_dialog_format_secondary_text(GTK_MESSAGE_DIALOG(dialog),
+                "%s", error->message);
+        gtk_dialog_run(GTK_DIALOG(dialog));
+        gtk_widget_destroy(dialog);
+        g_error_free(error);
+    }
+    g_free(pathname);
+    g_free(filename);
+}
+
+
+/* This function makes the OK button active iff a title has been entered.
+ */
+void
+gnc_check_format_title_changed2 (GtkEditable *editable, GtkWidget *ok_button)
+{
+    const gchar *text;
+    gboolean sensitive;
+
+    text = gtk_entry_get_text(GTK_ENTRY(editable));
+    sensitive = text && *text;
+    gtk_widget_set_sensitive(ok_button, sensitive);
+}
+
+
+/* This function is called when the user clicks the "save format" button in
+ * the check printing dialog.  It presents another dialog to the user to get
+ * the filename for saving the data.
+ */
+void
+gnc_print_check_save_button_clicked2(GtkButton *unused, PrintCheckDialog *pcd)
+{
+    GtkWidget *dialog, *entry, *button;
+    GtkBuilder *builder;
+    gchar *title;
+
+    builder = gtk_builder_new();
+    gnc_builder_add_from_file (builder, "dialog-print-check.glade", "Format Title Dialog");
+
+    /* Get a title for the new check format. */
+    dialog = GTK_WIDGET(gtk_builder_get_object (builder, "Format Title Dialog"));
+    entry = GTK_WIDGET(gtk_builder_get_object (builder, "format_title"));
+    button = GTK_WIDGET(gtk_builder_get_object (builder, "ok_button"));
+    gnc_check_format_title_changed2(GTK_EDITABLE(entry), button);
+    gtk_builder_connect_signals_full (builder, gnc_builder_connect_full_func, pcd);
+
+    gtk_window_set_transient_for(GTK_WINDOW(dialog), GTK_WINDOW(pcd->dialog));
+    if (gtk_dialog_run (GTK_DIALOG (dialog)) != GTK_RESPONSE_OK)
+    {
+        gtk_widget_destroy(dialog);
+        g_object_unref(G_OBJECT(builder));
+        return;
+    }
+
+    title = g_strdup(gtk_entry_get_text(GTK_ENTRY(entry)));
+    gtk_widget_destroy (dialog);
+
+    g_object_unref(G_OBJECT(builder));
+
+    pcd_save_custom_data(pcd, title);
+    g_free(title);
+}
+
+
+/* This function is an auxiliary debugging function for converting an array of
+ * doubles into a printable string.
+ */
+static gchar *
+doubles_to_string(gdouble *dd, gint len)
+{
+    GString *str;
+    gint i;
+
+    str = g_string_new_len(NULL, 50);
+    for (i = 0; i < len; i++)
+        g_string_append_printf(str, "%f ", dd[i]);
+    return g_string_free(str, FALSE);
+}
+
+
+/* This function reads in the information describing the placement for each
+ * item to be printed on a check.  This information is all relative to the
+ * upper left hand corner of a "check".  See the format_read_multicheck_info()
+ * function for determining if there are multiple checks on a single page of
+ * paper. This data is build into a linked list and saved as part of the check
+ * format information.  These items will be printed in the same order they are
+ * read, meaning that items listed later in the date file can be printed over
+ * top of items that appear earlier in the file.
+ */
+static GSList *
+format_read_item_placement(const gchar *file,
+                           GKeyFile *key_file, check_format_t *format)
+{
+    check_item_t *data = NULL;
+    GError *error = NULL;
+    GSList *list = NULL;
+    gchar *key, *value, *name;
+    int item_num;
+    gboolean bval;
+    gdouble *dd;
+    gsize dd_len;
+
+    /* Read until failure. */
+    for (item_num = 1;; item_num++)
+    {
+
+        /* Create the per-item data structure */
+        data = g_new0(check_item_t, 1);
+        if (NULL == data)
+            return list;
+
+        /* Get the item type */
+        key = g_strdup_printf("%s_%d", KF_KEY_TYPE, item_num);
+        value = g_key_file_get_string(key_file, KF_GROUP_ITEMS, key, &error);
+        if (error)
+        {
+            if ((error->domain == G_KEY_FILE_ERROR)
+                    && (error->code == G_KEY_FILE_ERROR_KEY_NOT_FOUND))
+            {
+                /* This is the expected exit from this function. */
+                goto cleanup;
+            }
+            goto failed;
+        }
+        g_debug("Check file %s, group %s, key %s, value: %s",
+                file, KF_GROUP_ITEMS, key, value);
+        g_free(key);
+
+        /* Convert the type from a string to an enum, ignoring case. */
+        name = g_utf8_strup(value, -1);
+        data->type = CheckItemType2fromString(name);
+        g_free(name);
+        g_free(value);
+
+
+        /* Get the item location */
+        key = g_strdup_printf("%s_%d", KF_KEY_COORDS, item_num);
+        dd = g_key_file_get_double_list(key_file, KF_GROUP_ITEMS,
+                                        key, &dd_len, &error);
+        if (error)
+            goto failed;
+        value = doubles_to_string(dd, dd_len);
+        g_debug("Check file %s, group %s, key %s, length %"G_GSIZE_FORMAT"; values: %s",
+                file, KF_GROUP_ITEMS, key, dd_len, value);
+        g_free(value);
+
+        /* Must have "x;y" or "x;y;w;h". */
+        switch (dd_len)
+        {
+        case 4:
+            data->w = dd[2];
+            data->h = dd[3];
+            /* fall through */
+        case 2:
+            data->x = dd[0];
+            data->y = dd[1];
+            break;
+        default:
+            g_warning
+            ("Check file %s, group %s, key %s, error: 2 or 4 values only",
+             file, KF_GROUP_ITEMS, key);
+            goto cleanup;
+        }
+        g_free(dd);
+        g_free(key);
+
+        /* Any text item can specify:
+         *   a font  FONT_n
+         *   an alignment if a width was provided for the item  ALIGN_n
+         *   blocking chars flag  BLOCKING_CHARS_n
+         * These values are optional and do not cause a failure if they are missing. */
+
+        if (data->type != PICTURE)
+        {
+            key = g_strdup_printf("%s_%d", KF_KEY_FONT, item_num);
+            data->font =
+                g_key_file_get_string(key_file, KF_GROUP_ITEMS, key, &error);
+            if (!error)
+            {
+                g_debug("Check file %s, group %s, key %s, value: %s",
+                        file, KF_GROUP_ITEMS, key, data->font);
+            }
+            else
+            {
+                if (!((error->domain == G_KEY_FILE_ERROR)
+                        && (error->code == G_KEY_FILE_ERROR_KEY_NOT_FOUND)))
+                    g_warning("Check file %s, group %s, key %s, error: %s",
+                              file, KF_GROUP_ITEMS, key, error->message);
+                g_clear_error(&error);
+            }
+            g_free(key);
+
+            key = g_strdup_printf("%s_%d", KF_KEY_ALIGN, item_num);
+            value =
+                g_key_file_get_string(key_file, KF_GROUP_ITEMS, key, &error);
+            if (!error)
+            {
+                g_debug("Check file %s, group %s, key %s, value: %s",
+                        file, KF_GROUP_ITEMS, key, value);
+                name = g_utf8_strdown(value, -1);
+                if (strcmp(name, "right") == 0)
+                    data->align = PANGO_ALIGN_RIGHT;
+                else if (strcmp(name, "center") == 0)
+                    data->align = PANGO_ALIGN_CENTER;
+                else
+                    data->align = PANGO_ALIGN_LEFT;
+                g_free(name);
+                g_free(value);
+            }
+            else
+            {
+                if (!((error->domain == G_KEY_FILE_ERROR)
+                        && (error->code == G_KEY_FILE_ERROR_KEY_NOT_FOUND)))
+                    g_warning("Check file %s, group %s, key %s, error: %s",
+                              file, KF_GROUP_ITEMS, key, error->message);
+                data->align = PANGO_ALIGN_LEFT;
+                g_clear_error(&error);
+            }
+            g_free(key);
+
+            key = g_strdup_printf("%s_%d", KF_KEY_BLOCKING, item_num);
+            bval =
+                g_key_file_get_boolean(key_file, KF_GROUP_ITEMS, key, &error);
+            if (!error)
+            {
+                g_debug("Check file %s, group %s, key %s, value: %d",
+                        file, KF_GROUP_ITEMS, key, bval);
+                data->blocking = bval;
+            }
+            else
+            {
+                if (!((error->domain == G_KEY_FILE_ERROR)
+                        && (error->code == G_KEY_FILE_ERROR_KEY_NOT_FOUND)))
+                    g_warning("Check file %s, group %s, key %s, error: %s",
+                              file, KF_GROUP_ITEMS, key, error->message);
+                data->blocking = format->blocking;
+                g_clear_error(&error);
+            }
+            g_free(key);
+        }
+        /* Get any extra data for specific items. */
+        switch (data->type)
+        {
+        case PICTURE:
+            key = g_strdup_printf("%s_%d", KF_KEY_FILENAME, item_num);
+            data->filename =
+                g_key_file_get_string(key_file, KF_GROUP_ITEMS, key,
+                                      &error);
+            if (error)
+                goto failed;
+            g_debug("Check file %s, group %s, key %s, value: %s",
+                    file, KF_GROUP_ITEMS, key, data->filename);
+            g_free(key);
+            break;
+        case TEXT:
+            key = g_strdup_printf("%s_%d", KF_KEY_TEXT, item_num);
+            data->text =
+                g_key_file_get_string(key_file, KF_GROUP_ITEMS, key,
+                                      &error);
+            if (error)
+                goto failed;
+            g_debug("Check file %s, group %s, key %s, value: %s",
+                    file, KF_GROUP_ITEMS, key, data->text);
+            g_free(key);
+            break;
+        case DATE:
+            /* no error if the date_format is not present */
+            key = g_strdup_printf("%s_%d", KF_KEY_DATE_FORMAT, item_num);
+            bval = g_key_file_get_boolean(key_file, KF_GROUP_ITEMS, key, &error);
+            if (!error)
+            {
+                g_debug("Check file %s, group %s, key %s, value: %d",
+                        file, KF_GROUP_ITEMS, key, bval);
+                data->print_date_format = bval;
+            }
+            else
+            {
+                if (!((error->domain == G_KEY_FILE_ERROR)
+                        && (error->code == G_KEY_FILE_ERROR_KEY_NOT_FOUND)))
+                    g_warning("Check file %s, group %s, key %s, error: %s",
+                              file, KF_GROUP_ITEMS, key, error->message);
+                //data->print_date_format = gnc_gconf_get_bool(GCONF_SECTION, KEY_PRINT_DATE_FMT, NULL);
+                data->print_date_format = format->print_date_format;
+                g_clear_error(&error);
+            }
+            g_free(key);
+            break;
+        default:
+            break;
+        }
+
+        list = g_slist_append(list, data);
+        data = NULL;
+    }
+
+    /* Should never be reached. */
+    return list;
+
+failed:
+    g_warning("Check file %s, group %s, key %s, error: %s",
+              file, KF_GROUP_ITEMS, key, error->message);
+cleanup:
+    if (error)
+        g_error_free(error);
+    if (data)
+        g_free(data);
+    if (key)
+        g_free(key);
+    return list;
+}
+
+
+/* Free the data describing the placement of a single item on a check.
+ */
+static void
+format_free_item_placement(check_item_t *data)
+{
+    if (data->font)
+        g_free(data->font);
+    if (data->text)
+        g_free(data->text);
+    if (data->filename)
+        g_free(data->filename);
+    g_free(data);
+}
+
+
+/* Read the information describing whether a page contains multiple checks or
+ * a single check.  If there are multiple checks on a page, this functions
+ * builds a linked list of the position names and their offsets (from the
+ * upper left corner of the page).
+ */
+static GSList *
+format_read_multicheck_info(const gchar *file,
+                            GKeyFile *key_file, check_format_t *format)
+{
+    GError *error = NULL;
+    GSList *list = NULL;
+    gchar *key, **names;
+    gsize length;
+    gint i;
+
+    key = g_strdup_printf("%s", KF_KEY_HEIGHT);
+    format->height = g_key_file_get_double(key_file, KF_GROUP_POS, key, &error);
+    if (error)
+    {
+        if ((error->domain == G_KEY_FILE_ERROR)
+                && ((error->code == G_KEY_FILE_ERROR_GROUP_NOT_FOUND)
+                    || (error->code == G_KEY_FILE_ERROR_KEY_NOT_FOUND)))
+        {
+            g_clear_error(&error);
+            format->height = 0.0;
+        }
+        else
+        {
+            g_warning("Check file %s, error reading group %s, key %s: %s",
+                      file, KF_GROUP_POS, key, error->message);
+            g_free(key);
+            return NULL;
+        }
+    }
+
+    names = g_key_file_get_string_list(key_file, KF_GROUP_POS, KF_KEY_NAMES,
+                                       &length, &error);
+    if (error)
+    {
+        if ((error->domain == G_KEY_FILE_ERROR)
+                && ((error->code == G_KEY_FILE_ERROR_GROUP_NOT_FOUND)
+                    || (error->code == G_KEY_FILE_ERROR_KEY_NOT_FOUND)))
+        {
+            /* This is the expected exit from this function. */
+            g_free(key);
+            return NULL;
+        }
+        g_warning("Check file %s, error reading group %s, key %s: %s",
+                  file, KF_GROUP_POS, key, error->message);
+        g_free(key);
+        return list;
+    }
+
+    for (i = 0; i < length; i++)
+        list = g_slist_append(list, g_strdup(names[i]));
+
+    g_strfreev(names);
+    return list;
+}
+
+
+/* Free the data describing the placement of multiple checks on a page.
+ */
+static void
+free_check_position(gchar *name)
+{
+    g_free(name);
+}
+
+
+/* Read the information describing the general layout of a page of checks.
+ * All items in this section are optional except or the name of the check
+ * style.
+ */
+static gboolean
+format_read_general_info(const gchar *file,
+                         GKeyFile *key_file, check_format_t *format)
+{
+    GError *error = NULL;
+    gchar **parts;
+    gchar *value;
+    double *dd;
+    gsize dd_len;
+
+    value = g_key_file_get_string(key_file, KF_GROUP_TOP, KF_KEY_GUID, &error);
+    if (error)
+    {
+        g_warning("Check file %s, group %s, key %s, error: %s",
+                  file, KF_GROUP_TOP, KF_KEY_GUID, error->message);
+        g_error_free(error);
+        return FALSE;
+    }
+    parts = g_strsplit(value, "-", -1);
+    format->guid = g_strjoinv("", parts);
+    g_strfreev(parts);
+    g_debug("Check file %s, group %s, key %s, value: %s",
+            file, KF_GROUP_TOP, KF_KEY_GUID, format->guid);
+
+    format->title =
+        g_key_file_get_string(key_file, KF_GROUP_TOP, KF_KEY_TITLE, &error);
+    if (!error)
+    {
+        g_debug("Check file %s, group %s, key %s, value: %s",
+                file, KF_GROUP_TOP, KF_KEY_TITLE, format->title);
+    }
+    else
+    {
+        g_warning("Check file %s, group %s, key %s, error: %s",
+                  file, KF_GROUP_TOP, KF_KEY_TITLE, error->message);
+        return FALSE;
+    }
+
+    format->blocking =
+        g_key_file_get_boolean(key_file, KF_GROUP_TOP, KF_KEY_BLOCKING,
+                               &error);
+    if (!error)
+    {
+        g_debug("Check file %s, group %s, key %s, value: %d",
+                file, KF_GROUP_TOP, KF_KEY_BLOCKING, format->blocking);
+    }
+    else
+    {
+        if (!((error->domain == G_KEY_FILE_ERROR)
+                && (error->code == G_KEY_FILE_ERROR_KEY_NOT_FOUND)))
+            g_warning("Check file %s, group %s, key %s, error: %s",
+                      file, KF_GROUP_TOP, KF_KEY_BLOCKING, error->message);
+        if ( gnc_gconf_get_bool(GCONF_SECTION, KEY_BLOCKING_CHARS, NULL) )
+        {
+            format->blocking = TRUE;
+        }
+        else
+        {
+            format->blocking = FALSE;
+        }
+        g_clear_error(&error);
+    }
+
+    format->print_date_format =
+        g_key_file_get_boolean(key_file, KF_GROUP_TOP, KF_KEY_DATE_FORMAT,
+                               &error);
+    if (!error)
+    {
+        g_debug("Check file %s, group %s, key %s, value: %d",
+                file, KF_GROUP_TOP, KF_KEY_DATE_FORMAT, format->print_date_format);
+    }
+    else
+    {
+        if (!((error->domain == G_KEY_FILE_ERROR)
+                && (error->code == G_KEY_FILE_ERROR_KEY_NOT_FOUND)))
+            g_warning("Check file %s, group %s, key %s, error: %s",
+                      file, KF_GROUP_TOP, KF_KEY_DATE_FORMAT, error->message);
+        if ( gnc_gconf_get_bool(GCONF_SECTION, KEY_PRINT_DATE_FMT, NULL) )
+        {
+            format->print_date_format = TRUE;
+        }
+        else
+        {
+            format->print_date_format = FALSE;
+        }
+        g_clear_error(&error);
+    }
+
+    format->show_grid =
+        g_key_file_get_boolean(key_file, KF_GROUP_TOP, KF_KEY_SHOW_GRID,
+                               &error);
+    if (!error)
+    {
+        g_debug("Check file %s, group %s, key %s, value: %d",
+                file, KF_GROUP_TOP, KF_KEY_SHOW_GRID, format->show_grid);
+    }
+    else
+    {
+        if (!((error->domain == G_KEY_FILE_ERROR)
+                && (error->code == G_KEY_FILE_ERROR_KEY_NOT_FOUND)))
+            g_warning("Check file %s, group %s, key %s, error: %s",
+                      file, KF_GROUP_TOP, KF_KEY_SHOW_GRID, error->message);
+        format->show_grid = FALSE;
+        g_clear_error(&error);
+    }
+
+    format->show_boxes =
+        g_key_file_get_boolean(key_file, KF_GROUP_TOP, KF_KEY_SHOW_BOXES,
+                               &error);
+    if (!error)
+    {
+        g_debug("Check file %s, group %s, key %s, value: %d",
+                file, KF_GROUP_TOP, KF_KEY_SHOW_BOXES, format->show_boxes);
+    }
+    else
+    {
+        if (!((error->domain == G_KEY_FILE_ERROR)
+                && (error->code == G_KEY_FILE_ERROR_KEY_NOT_FOUND)))
+            g_warning("Check file %s, group %s, key %s, error: %s",
+                      file, KF_GROUP_TOP, KF_KEY_SHOW_BOXES, error->message);
+        format->show_boxes = FALSE;
+        g_clear_error(&error);
+    }
+
+    format->font =
+        g_key_file_get_string(key_file, KF_GROUP_TOP, KF_KEY_FONT, &error);
+    if (!error)
+    {
+        g_debug("Check file %s, group %s, key %s, value: %s",
+                file, KF_GROUP_TOP, KF_KEY_FONT, format->font);
+    }
+    else
+    {
+        if (!((error->domain == G_KEY_FILE_ERROR)
+                && (error->code == G_KEY_FILE_ERROR_KEY_NOT_FOUND)))
+            g_warning("Check file %s, group %s, key %s, error: %s",
+                      file, KF_GROUP_TOP, KF_KEY_FONT, error->message);
+        g_clear_error(&error);
+    }
+
+    format->rotation =
+        g_key_file_get_double(key_file, KF_GROUP_TOP, KF_KEY_ROTATION, &error);
+    if (!error)
+    {
+        g_debug("Check file %s, group %s, key %s, value: %f",
+                file, KF_GROUP_TOP, KF_KEY_ROTATION, format->rotation);
+    }
+    else
+    {
+        if (!((error->domain == G_KEY_FILE_ERROR)
+                && (error->code == G_KEY_FILE_ERROR_KEY_NOT_FOUND)))
+            g_warning("Check file %s, group %s, key %s, error: %s",
+                      file, KF_GROUP_TOP, KF_KEY_ROTATION, error->message);
+        format->rotation = 0.0;
+        g_clear_error(&error);
+    }
+
+    dd = g_key_file_get_double_list(key_file, KF_GROUP_TOP, KF_KEY_TRANSLATION,
+                                    &dd_len, &error);
+    if (!error)
+    {
+        value = doubles_to_string(dd, dd_len);
+        g_debug("Check file %s, group %s, key %s, length %"G_GSIZE_FORMAT"; values: %s",
+                file, KF_GROUP_TOP, KF_KEY_TRANSLATION, dd_len, value);
+        g_free(value);
+
+        if (dd_len == 2)
+        {
+            format->trans_x = dd[0];
+            format->trans_y = dd[1];
+        }
+        else
+        {
+            g_warning("Check file %s, error top %s, key %s: 2 values only",
+                      file, KF_GROUP_TOP, KF_KEY_TRANSLATION);
+        }
+        g_free(dd);
+    }
+    else
+    {
+        if (!((error->domain == G_KEY_FILE_ERROR)
+                && (error->code == G_KEY_FILE_ERROR_KEY_NOT_FOUND)))
+            g_warning("Check file %s, group top %s, key %s: %s",
+                      file, KF_GROUP_ITEMS, KF_KEY_TRANSLATION, error->message);
+        g_clear_error(&error);
+    }
+
+    return TRUE;
+}
+
+
+/* Free all of the information describing a page of checks.
+ */
+static void
+free_check_format(check_format_t *data)
+{
+    g_free(data->guid);
+    g_free(data->filename);
+    g_free(data->title);
+    g_free(data->font);
+    g_slist_foreach(data->positions, (GFunc) free_check_position, NULL);
+    g_slist_free(data->positions);
+    g_slist_foreach(data->items, (GFunc) format_free_item_placement, NULL);
+    g_slist_free(data->items);
+    g_free(data);
+}
+
+
+/* Read a single check format file and append the resulting format to the
+ * list of all known formats.  This function calls other functions to read
+ * each section of the data file.
+ */
+static check_format_t *
+read_one_check_format(PrintCheckDialog *pcd, const gchar *groupname,
+                      const gchar *dirname, const gchar *file)
+{
+    gchar *pathname;
+    GKeyFile *key_file;
+    check_format_t *format;
+
+    pathname = g_build_filename(dirname, file, (char *)NULL);
+    key_file = gnc_key_file_load_from_file(pathname, FALSE, FALSE, NULL);
+    g_free(pathname);
+    if (!key_file)
+    {
+        g_warning("Check file %s, cannot load file", file);
+        return NULL;
+    }
+
+    format = g_new0(check_format_t, 1);
+    format->group = groupname;
+    format->filename = g_strdup(file);
+    if (format_read_general_info(file, key_file, format))
+    {
+        format->positions = format_read_multicheck_info(file, key_file, format);
+        format->items = format_read_item_placement(file, key_file, format);
+    }
+
+    g_key_file_free(key_file);
+    if ((NULL == format->title) || (NULL == format->items))
+    {
+        g_warning("Check file %s, no items read. Dropping file.", file);
+        free_check_format(format);
+        return NULL;
+    }
+
+    return format;
+}
+
+
+/* Iterate over a single check directory, throwing out any backup files and
+ * then calling a helper function to read and parse the check format withing
+ * the file.
+ */
+static void
+read_one_check_directory(PrintCheckDialog *pcd, GtkListStore *store,
+                         const gchar *groupname, const gchar *dirname)
+{
+    check_format_t *format, *existing;
+    GDir *dir;
+    const gchar *filename;
+    GtkTreeIter iter;
+    GtkWidget *dialog;
+    gboolean found = FALSE;
+
+    dir = g_dir_open(dirname, 0, NULL);
+    if (dir == NULL)
+        return;
+
+    while ((filename = g_dir_read_name(dir)) != NULL)
+    {
+        if (g_str_has_prefix(filename, "#"))
+            continue;
+        if (!g_str_has_suffix(filename, ".chk"))
+            continue;
+
+        format = read_one_check_format(pcd, groupname, dirname, filename);
+        if (NULL == format)
+            continue;
+
+        existing = find_existing_format(store, format->guid, NULL);
+        if (existing)
+        {
+            dialog = gtk_message_dialog_new
+                     (GTK_WINDOW(pcd->dialog),
+                      GTK_DIALOG_DESTROY_WITH_PARENT,
+                      GTK_MESSAGE_ERROR, GTK_BUTTONS_CLOSE, "%s",
+                      _("There is a duplicate check format file."));
+            gtk_message_dialog_format_secondary_text
+            (GTK_MESSAGE_DIALOG(dialog),
+             /* Translators: %1$s is the type of the first check
+              * format (user defined or application defined); %2$s
+              * is the filename of that format; %3$s the type of
+              * the other check format; and %4$s the filename of
+              * that other format. */
+             _("The GUIDs in the %s check format file '%s' and "
+               "the %s check format file '%s' match."),
+             existing->group, existing->filename,
+             format->group, format->filename);
+            gtk_dialog_run(GTK_DIALOG(dialog));
+            gtk_widget_destroy(dialog);
+        }
+        else
+        {
+            gtk_list_store_append(store, &iter);
+            gtk_list_store_set(store, &iter, COL_NAME, format->title,
+                               COL_DATA, format, -1);
+            found = TRUE;
+        }
+    }
+    g_dir_close(dir);
+
+    /* If any files were added to the list, add a separator between
+     *  this group and the next. */
+    if (found)
+    {
+        gtk_list_store_append(store, &iter);
+        gtk_list_store_set(store, &iter, COL_SEP, TRUE, -1);
+    }
+}
+
+
+/* Read all check formats.  This function first looks in the system directory
+ * for check files, and then looks in the user's .gnucash directory for any
+ * custom check files.
+ */
+static void
+read_formats(PrintCheckDialog *pcd, GtkListStore *store)
+{
+    gchar *dirname, *pkgdatadir;
+
+    pkgdatadir = gnc_path_get_pkgdatadir();
+    dirname = g_build_filename(pkgdatadir, CHECK_FMT_DIR, (char *)NULL);
+    /* Translators: This is a directory name. It may be presented to
+     * the user to indicate that some data file was defined by the
+     * gnucash application. */
+    read_one_check_directory(pcd, store, _("application"), dirname);
+    g_free(dirname);
+    g_free(pkgdatadir);
+
+    dirname = gnc_build_dotgnucash_path(CHECK_FMT_DIR);
+    /* Translators: This is a directory name. It may be presented to
+     * the user to indicate that some data file was defined by a
+     * user herself. */
+    read_one_check_directory(pcd, store, _("user"), dirname);
+    g_free(dirname);
+}
+
+
+static gboolean
+format_is_a_separator (GtkTreeModel *model, GtkTreeIter *iter, gpointer data)
+{
+    gboolean separator;
+
+    gtk_tree_model_get(model, iter, COL_SEP, &separator, -1);
+    return separator;
+}
+
+
+static void
+initialize_format_combobox (PrintCheckDialog *pcd)
+{
+    GtkListStore *store;
+    GtkTreeIter iter;
+
+    store = gtk_list_store_new(3, G_TYPE_STRING, G_TYPE_POINTER, G_TYPE_BOOLEAN);
+    read_formats(pcd, store);
+    gtk_list_store_append(store, &iter);
+    gtk_list_store_set(store, &iter, COL_NAME, _("Custom"), -1);
+    pcd->format_max = gtk_tree_model_iter_n_children(GTK_TREE_MODEL(store), NULL);
+    gtk_combo_box_set_model(GTK_COMBO_BOX(pcd->format_combobox),
+                            GTK_TREE_MODEL(store));
+    gtk_combo_box_set_row_separator_func(GTK_COMBO_BOX(pcd->format_combobox),
+                                         format_is_a_separator, NULL, NULL);
+}
+
+
+/*****************************************************
+ * gnc_ui_print_check_dialog_create2                  *
+ * make a new print check dialog and wait for it.    *
+ *****************************************************/
+void
+gnc_ui_print_check_dialog_create2(GncPluginPageRegister2 *plugin_page,
+                                 GList *splits)
+{
+    PrintCheckDialog *pcd;
+    GtkBuilder *builder;
+    GtkWidget *table;
+    GtkWindow *window;
+    gchar *font;
+    Transaction *trans = NULL;
+
+    pcd = g_new0(PrintCheckDialog, 1);
+    pcd->plugin_page = plugin_page;
+    pcd->splits = g_list_copy(splits);
+
+    builder = gtk_builder_new();
+    gnc_builder_add_from_file (builder, "dialog-print-check.glade", "adjustment1");
+    gnc_builder_add_from_file (builder, "dialog-print-check.glade", "adjustment2");
+    gnc_builder_add_from_file (builder, "dialog-print-check.glade", "adjustment3");
+    gnc_builder_add_from_file (builder, "dialog-print-check.glade", "adjustment4");
+    gnc_builder_add_from_file (builder, "dialog-print-check.glade", "adjustment5");
+    gnc_builder_add_from_file (builder, "dialog-print-check.glade", "adjustment6");
+    gnc_builder_add_from_file (builder, "dialog-print-check.glade", "adjustment7");
+    gnc_builder_add_from_file (builder, "dialog-print-check.glade", "adjustment8");
+    gnc_builder_add_from_file (builder, "dialog-print-check.glade", "adjustment9");
+    gnc_builder_add_from_file (builder, "dialog-print-check.glade", "adjustment10");
+    gnc_builder_add_from_file (builder, "dialog-print-check.glade", "adjustment11");
+    gnc_builder_add_from_file (builder, "dialog-print-check.glade", "adjustment12");
+    gnc_builder_add_from_file (builder, "dialog-print-check.glade", "adjustment13");
+    gnc_builder_add_from_file (builder, "dialog-print-check.glade", "adjustment14");
+    gnc_builder_add_from_file (builder, "dialog-print-check.glade", "adjustment15");
+    gnc_builder_add_from_file (builder, "dialog-print-check.glade", "adjustment16");
+    gnc_builder_add_from_file (builder, "dialog-print-check.glade", "adjustment17");
+    gnc_builder_add_from_file (builder, "dialog-print-check.glade", "adjustment18");
+    gnc_builder_add_from_file (builder, "dialog-print-check.glade", "adjustment19");
+    gnc_builder_add_from_file (builder, "dialog-print-check.glade", "adjustment20");
+    gnc_builder_add_from_file (builder, "dialog-print-check.glade", "adjustment21");
+    gnc_builder_add_from_file (builder, "dialog-print-check.glade", "adjustment22");
+    gnc_builder_add_from_file (builder, "dialog-print-check.glade", "adjustment23");
+    gnc_builder_add_from_file (builder, "dialog-print-check.glade", "adjustment24");
+    gnc_builder_add_from_file (builder, "dialog-print-check.glade", "liststore1");
+    gnc_builder_add_from_file (builder, "dialog-print-check.glade", "liststore2");
+    gnc_builder_add_from_file (builder, "dialog-print-check.glade", "liststore3");
+    gnc_builder_add_from_file (builder, "dialog-print-check.glade", "Print Check Dialog");
+
+    gtk_builder_connect_signals_full (builder, gnc_builder_connect_full_func, pcd);
+
+    pcd->builder = builder;
+    pcd->dialog = GTK_WIDGET(gtk_builder_get_object (builder, "Print Check Dialog"));
+
+    /* now pick out the relevant child widgets */
+    pcd->format_combobox = GTK_WIDGET(gtk_builder_get_object (builder, "check_format_combobox"));
+    pcd->position_combobox = GTK_WIDGET(gtk_builder_get_object (builder, "check_position_combobox"));
+    pcd->first_page_count = GTK_SPIN_BUTTON(gtk_builder_get_object (builder, "first_page_count_entry"));
+
+    pcd->custom_table = GTK_WIDGET(gtk_builder_get_object (builder, "custom_table"));
+    pcd->payee_x = GTK_SPIN_BUTTON(gtk_builder_get_object (builder, "payee_x_entry"));
+    pcd->payee_y = GTK_SPIN_BUTTON(gtk_builder_get_object (builder, "payee_y_entry"));
+    pcd->date_x = GTK_SPIN_BUTTON(gtk_builder_get_object (builder, "date_x_entry"));
+    pcd->date_y = GTK_SPIN_BUTTON(gtk_builder_get_object (builder, "date_y_entry"));
+    pcd->words_x = GTK_SPIN_BUTTON(gtk_builder_get_object (builder, "amount_words_x_entry"));
+    pcd->words_y = GTK_SPIN_BUTTON(gtk_builder_get_object (builder, "amount_words_y_entry"));
+    pcd->number_x = GTK_SPIN_BUTTON(gtk_builder_get_object (builder, "amount_numbers_x_entry"));
+    pcd->number_y = GTK_SPIN_BUTTON(gtk_builder_get_object (builder, "amount_numbers_y_entry"));
+    pcd->notes_x = GTK_SPIN_BUTTON(gtk_builder_get_object (builder, "notes_x_entry"));
+    pcd->notes_y = GTK_SPIN_BUTTON(gtk_builder_get_object (builder, "notes_y_entry"));
+    pcd->memo_x = GTK_SPIN_BUTTON(gtk_builder_get_object (builder, "memo_x_entry"));
+    pcd->memo_y = GTK_SPIN_BUTTON(gtk_builder_get_object (builder, "memo_y_entry"));
+    pcd->address_x = GTK_SPIN_BUTTON(gtk_builder_get_object (builder, "address_x_entry"));
+    pcd->address_y = GTK_SPIN_BUTTON(gtk_builder_get_object (builder, "address_y_entry"));
+    pcd->splits_amount_x = GTK_SPIN_BUTTON(gtk_builder_get_object (builder, "splits_amount_x_entry"));
+    pcd->splits_amount_y = GTK_SPIN_BUTTON(gtk_builder_get_object (builder, "splits_amount_y_entry"));
+    pcd->splits_memo_x = GTK_SPIN_BUTTON(gtk_builder_get_object (builder, "splits_memo_x_entry"));
+    pcd->splits_memo_y = GTK_SPIN_BUTTON(gtk_builder_get_object (builder, "splits_memo_y_entry"));
+    pcd->splits_account_x = GTK_SPIN_BUTTON(gtk_builder_get_object (builder, "splits_account_x_entry"));
+    pcd->splits_account_y = GTK_SPIN_BUTTON(gtk_builder_get_object (builder, "splits_account_y_entry"));
+    pcd->translation_x = GTK_SPIN_BUTTON(gtk_builder_get_object (builder, "translation_x_entry"));
+    pcd->translation_y = GTK_SPIN_BUTTON(gtk_builder_get_object (builder, "translation_y_entry"));
+    pcd->translation_label = GTK_WIDGET(gtk_builder_get_object (builder, "translation_label"));
+    pcd->check_rotation = GTK_SPIN_BUTTON(gtk_builder_get_object (builder, "check_rotation_entry"));
+    pcd->units_combobox = GTK_WIDGET(gtk_builder_get_object (builder, "units_combobox"));
+
+    window = GTK_WINDOW(GNC_PLUGIN_PAGE(plugin_page)->window);
+    gtk_window_set_transient_for(GTK_WINDOW(pcd->dialog), window);
+    pcd->caller_window = GTK_WINDOW(window);
+
+    /* Create and attach the date-format chooser */
+    table = GTK_WIDGET(gtk_builder_get_object (builder, "options_table"));
+    pcd->date_format = gnc_date_format_new_without_label();
+    gtk_table_attach_defaults(GTK_TABLE(table), pcd->date_format, 1, 3, 4, 7);
+
+    /* Default font (set in preferences) */
+    font = gnc_gconf_get_string(GCONF_SECTION, KEY_DEFAULT_FONT, NULL);
+    pcd->default_font = font ? font : g_strdup(DEFAULT_FONT);
+
+    /* Update the combo boxes bases on the available check formats */
+    initialize_format_combobox(pcd);
+
+    /* address */
+    pcd->check_address_name = GTK_WIDGET(gtk_builder_get_object (builder, "check_address_name"));
+    pcd->check_address_1 = GTK_WIDGET(gtk_builder_get_object (builder, "check_address_1"));
+    pcd->check_address_2 = GTK_WIDGET(gtk_builder_get_object (builder, "check_address_2"));
+    pcd->check_address_3 = GTK_WIDGET(gtk_builder_get_object (builder, "check_address_3"));
+    pcd->check_address_4 = GTK_WIDGET(gtk_builder_get_object (builder, "check_address_4"));
+    /* fill in any available address data */
+    /* Can't access business objects e.g. Customer,Vendor,Employee because
+     * it would create build problems */
+    if (g_list_length(pcd->splits) == 1)
+        trans = xaccSplitGetParent((Split *)(pcd->splits->data));
+    else
+        trans = NULL;
+    if ( trans )
+    {
+        gtk_entry_set_text(GTK_ENTRY(pcd->check_address_name), xaccTransGetDescription(trans));
+    }
+    else
+    {
+        /* nothing to do - defaults to blank */
+    }
+
+    gtk_widget_destroy(GTK_WIDGET(gtk_builder_get_object (builder, "lower_left")));
+
+    gnc_ui_print_restore_dialog(pcd);
+    gnc_restore_window_size(GCONF_SECTION, GTK_WINDOW(pcd->dialog));
+
+    g_object_unref(G_OBJECT(builder));
+    gtk_widget_show_all(pcd->dialog);
+}
+
+
+/**************************************
+ * Print check contents to the page.  *
+ **************************************/
+
+/* Draw a grid pattern on the page to be printed.  This grid is helpful when
+ * figuring out the offsets for where to print various items on the page.
+ */
+static void
+draw_grid(GtkPrintContext *context, gint width, gint height, const gchar *font)
+{
+    const double dash_pattern[2] = { 1.0, 5.0 };
+    PangoFontDescription *desc;
+    PangoLayout *layout;
+    cairo_t *cr;
+    gchar *text;
+    gint i;
+
+    /* Initialize for printing text */
+    layout = gtk_print_context_create_pango_layout(context);
+    desc = pango_font_description_from_string(font);
+    pango_layout_set_font_description(layout, desc);
+    pango_font_description_free(desc);
+    pango_layout_set_alignment(layout, PANGO_ALIGN_LEFT);
+    pango_layout_set_width(layout, -1);
+
+    /* Set up the line to draw with. */
+    cr = gtk_print_context_get_cairo_context(context);
+    cairo_save(cr);
+    cairo_set_line_width(cr, 1.0);
+    cairo_set_line_cap(cr, CAIRO_LINE_JOIN_ROUND);
+    cairo_set_dash(cr, dash_pattern, 2, 0);
+
+    /* Draw horizontal lines */
+    for (i = -200; i < (height + 200); i += 50)
+    {
+        text = g_strdup_printf("%d", (int)i);
+        cairo_move_to(cr, -200, i);
+        cairo_line_to(cr, width + 200, i);
+        cairo_stroke(cr);
+        pango_layout_set_text(layout, text, -1);
+        cairo_move_to(cr, 0, i);
+        pango_cairo_show_layout(cr, layout);
+        g_free(text);
+    }
+
+    /* Draw vertical lines */
+    for (i = -200; i < (width + 200); i += 50)
+    {
+        text = g_strdup_printf("%d", (int)i);
+        cairo_move_to(cr, i, -200);
+        cairo_line_to(cr, i, height + 200);
+        cairo_stroke(cr);
+        pango_layout_set_text(layout, text, -1);
+        cairo_move_to(cr, i, 0);
+        pango_cairo_show_layout(cr, layout);
+        g_free(text);
+    }
+
+    /* Clean up after ourselves */
+    cairo_restore(cr);
+    g_object_unref(layout);
+}
+
+
+/* Print a single line of text to the printed page.  If a width and height
+ * are specified, the line will be wrapped at the specified width, and the
+ * resulting text will be clipped if it does not fit in the space
+ * available.
+ */
+static gdouble
+draw_text(GtkPrintContext *context, const gchar *text, check_item_t *data,
+          PangoFontDescription *default_desc)
+{
+    PangoFontDescription *desc;
+    PangoLayout *layout;
+    cairo_t *cr;
+    gint layout_height, layout_width;
+    gdouble width, height;
+    gchar *new_text;
+
+    if ((NULL == text) || (strlen(text) == 0))
+        return 0.0;
+
+    /* Initialize for printing text */
+    layout = gtk_print_context_create_pango_layout(context);
+    if (data->font)
+    {
+        desc = pango_font_description_from_string(data->font);
+        pango_layout_set_font_description(layout, desc);
+        pango_font_description_free(desc);
+    }
+    else
+    {
+        pango_layout_set_font_description(layout, default_desc);
+    }
+    pango_layout_set_alignment(layout,
+                               data->w ? data->align : PANGO_ALIGN_LEFT);
+    pango_layout_set_width(layout, data->w ? data->w * PANGO_SCALE : -1);
+    pango_layout_set_ellipsize(layout, PANGO_ELLIPSIZE_END);
+    if ( data->blocking )
+    {
+        new_text = g_strdup_printf("***%s***", text);
+        pango_layout_set_text(layout, new_text, -1);
+        g_free(new_text);
+    }
+    else
+    {
+        pango_layout_set_text(layout, text, -1);
+    }
+    pango_layout_get_size(layout, &layout_width, &layout_height);
+    width = (gdouble) layout_width / PANGO_SCALE;
+    height = (gdouble) layout_height / PANGO_SCALE;
+
+    cr = gtk_print_context_get_cairo_context(context);
+    cairo_save(cr);
+
+    /* Clip text to the enclosing rectangle */
+    if (data->w && data->h)
+    {
+        g_debug("Text clip rectangle, coords %f,%f, size %f,%f",
+                data->x, data->y - data->h, data->w, data->h);
+        cairo_rectangle(cr, data->x, data->y - data->h, data->w, data->h);
+        cairo_clip_preserve(cr);
+    }
+
+    /* Draw the text */
+    g_debug("Text move to %f,%f, print '%s'", data->x, data->y,
+            text ? text : "(null)");
+    cairo_move_to(cr, data->x, data->y - height);
+    pango_cairo_show_layout(cr, layout);
+
+    /* Clean up after ourselves */
+    cairo_restore(cr);
+    g_object_unref(layout);
+    return width;
+
+}
+
+
+/* Find and load the specified image.  If the specified filename isn't an
+ * absolute path name, this code will also look in the gnucash system check
+ * format directory, and then in the user's private check format
+ * directory.
+ *
+ * NOTE: The gtk_image_new_from_file() function never fails.  If it can't
+ * find the specified file, it returns the "broken image" icon.  This function
+ * takes advantage of that.
+*/
+static GtkWidget *
+read_image (const gchar *filename)
+{
+    GtkWidget *image;
+    gchar *pkgdatadir, *dirname, *tmp_name;
+
+    if (g_path_is_absolute(filename))
+        return gtk_image_new_from_file(filename);
+
+    pkgdatadir = gnc_path_get_pkgdatadir();
+    tmp_name = g_build_filename(pkgdatadir, CHECK_FMT_DIR, filename, (char *)NULL);
+    if (!g_file_test(tmp_name, G_FILE_TEST_EXISTS))
+    {
+        g_free(tmp_name);
+        dirname = gnc_build_dotgnucash_path(CHECK_FMT_DIR);
+        tmp_name = g_build_filename(dirname, filename, (char *)NULL);
+        g_free(dirname);
+    }
+    image = gtk_image_new_from_file(tmp_name);
+    g_free(tmp_name);
+    return image;
+}
+
+
+/* Print a single image to the printed page.  This picture will be scaled
+ * down to fit in the specified size rectangle.  Scaling is done with the
+ * proportions locked 1:1 so as not to distort the image.
+ */
+static void
+draw_picture(GtkPrintContext *context, check_item_t *data)
+{
+    cairo_t *cr;
+    GdkPixbuf *pixbuf, *scaled_pixbuf;
+    GtkImage *image;
+    gint pix_w, pix_h;
+    gdouble scale_w, scale_h, scale;
+
+    cr = gtk_print_context_get_cairo_context(context);
+    cairo_save(cr);
+
+    /* Get the picture. */
+    image = GTK_IMAGE(read_image(data->filename));
+    pixbuf = gtk_image_get_pixbuf(image);
+    if (pixbuf)
+    {
+        g_object_ref(pixbuf);
+    }
+    else
+    {
+        g_warning("Filename '%s' cannot be read or understood.",
+                  data->filename);
+        pixbuf = gtk_widget_render_icon(GTK_WIDGET(image),
+                                        GTK_STOCK_MISSING_IMAGE,
+                                        -1, NULL);
+    }
+    pix_w = gdk_pixbuf_get_width(pixbuf);
+    pix_h = gdk_pixbuf_get_height(pixbuf);
+
+    /* Draw the enclosing rectangle */
+    if (data->w && data->h)
+    {
+        cairo_rectangle(cr, data->x, data->y - data->h, data->w, data->h);
+        g_debug("Picture clip rectangle, user coords %f,%f, user size %f,%f",
+                data->x, data->y - data->h, data->w, data->h);
+    }
+    else
+    {
+        cairo_rectangle(cr, data->x, data->y - pix_h, pix_w, pix_h);
+        g_debug("Picture clip rectangle, user coords %f,%f, pic size %d,%d",
+                data->x, data->y - data->h, pix_w, pix_h);
+    }
+    cairo_clip_preserve(cr);
+
+    /* Scale down to fit.  Never scale up. */
+    scale_w = scale_h = 1;
+    if (data->w && (pix_w > data->w))
+        scale_w = data->w / pix_w;
+    if (data->h && (pix_h > data->h))
+        scale_h = data->h / pix_h;
+    scale = MIN(scale_w, scale_h);
+
+    if (scale != 1)
+    {
+        scaled_pixbuf = gdk_pixbuf_scale_simple(pixbuf, pix_w * scale,
+                                                pix_h * scale,
+                                                GDK_INTERP_BILINEAR);
+        pix_h = gdk_pixbuf_get_height(scaled_pixbuf);
+        gdk_cairo_set_source_pixbuf(cr, scaled_pixbuf, data->x,
+                                    data->y - pix_h);
+
+        g_object_unref(scaled_pixbuf);
+    }
+    else
+    {
+        gdk_cairo_set_source_pixbuf(cr, pixbuf, data->x, data->y - pix_h);
+    }
+    g_object_unref(pixbuf);
+    cairo_paint(cr);
+
+    /* Clean up after ourselves */
+    cairo_restore(cr);
+    gtk_widget_destroy(GTK_WIDGET(image));
+}
+
+
+#define DATE_FMT_HEIGHT 8
+#define DATE_FMT_SLOP   2
+
+/* There is a new Canadian requirement that all software that prints the date
+ * on a check must also print the format of that date underneath using a 6-8
+ * point font.  This function implements that requirement.  It requires the
+ * font description used in printing the date so that it can print in the same
+ * font using a smaller point size.  It also requires width of the printed
+ * date as an argument, allowing it to center the format string under the
+ * date.
+ *
+ * Note: This code only prints a date if the user has explicitly requested it
+ * via a preference (gconf) setting.  This is because gnucash has no way of
+ * knowing if the user's checks already have a date format printed on them.
+ */
+static void
+draw_date_format(GtkPrintContext *context, const gchar *date_format,
+                 check_item_t *data, PangoFontDescription *default_desc,
+                 gdouble width)
+{
+    PangoFontDescription *date_desc;
+    check_item_t date_item;
+    gchar *text = NULL, *expanded = NULL;
+    const gchar *c;
+    GString *cdn_fmt;
+
+    setlocale(LC_ALL, NULL);
+    if ( !data->print_date_format ) return;
+
+    date_desc = pango_font_description_copy_static(default_desc);
+    pango_font_description_set_size(date_desc, DATE_FMT_HEIGHT * PANGO_SCALE);
+    date_item = *data;
+    date_item.y += (DATE_FMT_HEIGHT + DATE_FMT_SLOP);
+    date_item.w = width;
+    date_item.h = DATE_FMT_HEIGHT + DATE_FMT_SLOP;
+    date_item.align = PANGO_ALIGN_CENTER;
+
+    /* This is a date format string. It should only contain ascii. */
+    cdn_fmt = g_string_new_len(NULL, 50);
+    for (c = date_format; c && *c; )
+    {
+        if ((c[0] != '%') || (c[1] == '\0'))
+        {
+            c += 1;
+            continue;
+        }
+        switch (c[1])
+        {
+        case 'F':
+            cdn_fmt = g_string_append(cdn_fmt, "YYYYMMDD");
+            break;
+        case 'Y':
+            cdn_fmt = g_string_append(cdn_fmt, "YYYY");
+            break;
+        case 'y':
+            cdn_fmt = g_string_append(cdn_fmt, "YY");
+            break;
+        case 'm':
+            cdn_fmt = g_string_append(cdn_fmt, "MM");
+            break;
+        case 'd':
+        case 'e':
+            cdn_fmt = g_string_append(cdn_fmt, "DD");
+            break;
+        case 'x':
+            expanded = g_strdup_printf("%s%s",
+                                       qof_date_format_get_string(QOF_DATE_FORMAT_LOCALE),
+                                       c + 2);
+            c = expanded;
+            continue;
+        default:
+            break;
+        }
+        c += 2;
+    }
+
+    text = g_string_free(cdn_fmt, FALSE);
+    draw_text(context, text, &date_item, date_desc);
+    g_free(text);
+    if (expanded)
+        g_free(expanded);
+    pango_font_description_free(date_desc);
+}
+
+
+/* Print each of the items that in the description of a single check.  This
+ * function uses helper functions to print text based and picture based items.
+ */
+static void
+draw_page_items(GtkPrintContext *context,
+                check_format_t *format, gpointer user_data)
+{
+    PrintCheckDialog *pcd = (PrintCheckDialog *) user_data;
+    PangoFontDescription *default_desc;
+    Transaction *trans;
+    gnc_numeric amount;
+    GNCPrintAmountInfo info;
+    const gchar *date_format;
+    gchar *text = NULL, buf[100];
+    GSList *elem;
+    check_item_t *item;
+    gdouble width;
+    gchar *address = NULL;
+
+    trans = xaccSplitGetParent(pcd->split);
+    /* This was valid when the check printing dialog was instantiated. */
+    g_return_if_fail(trans);
+    amount = gnc_numeric_abs(xaccSplitGetAmount(pcd->split));
+
+    if (format->font)
+        default_desc = pango_font_description_from_string(format->font);
+    else
+        default_desc = pango_font_description_from_string(pcd->default_font);
+
+    /* Now put the actual data onto the page. */
+    for (elem = format->items; elem; elem = g_slist_next(elem))
+    {
+        item = elem->data;
+
+        switch (item->type)
+        {
+        case DATE:
+	{
+	    GDate date;
+	    g_date_clear (&date, 1);
+            gnc_gdate_set_time64 (&date, xaccTransGetDate(trans));
+            date_format =
+                gnc_date_format_get_custom(GNC_DATE_FORMAT
+                                           (pcd->date_format));
+            g_date_strftime(buf, 100, date_format, &date);
+            width = draw_text(context, buf, item, default_desc);
+            draw_date_format(context, date_format, item, default_desc, width);
+            break;
+	}
+
+        case PAYEE:
+            draw_text(context, xaccTransGetDescription(trans), item, default_desc);
+            break;
+
+        case NOTES:
+            draw_text(context, xaccTransGetNotes(trans), item, default_desc);
+            break;
+
+        case MEMO:
+            draw_text(context, xaccSplitGetMemo(pcd->split), item, default_desc);
+            break;
+
+        case ACTION:
+            draw_text(context, gnc_get_action_num(trans, pcd->split), item,
+                                                                default_desc);
+            break;
+
+        case CHECK_NUMBER:
+            draw_text(context, gnc_get_num_action(trans, pcd->split), item,
+                                                                default_desc);
+            break;
+
+        case AMOUNT_NUMBER:
+            info = gnc_default_print_info(FALSE);
+            draw_text(context, xaccPrintAmount(amount, info),
+                      item, default_desc);
+            break;
+
+        case AMOUNT_WORDS:
+            text = numeric_to_words(amount);
+            draw_text(context, text, item, default_desc);
+            g_free(text);
+            break;
+
+        case TEXT:
+            draw_text(context, item->text, item, default_desc);
+            break;
+
+        case ADDRESS:
+            address = get_check_address2(pcd);
+            draw_text(context, address, item, default_desc);
+            g_free(address);
+            break;
+
+        case SPLITS_AMOUNT:
+            text = get_check_splits_amount2(pcd);
+            draw_text(context, text, item, default_desc);
+            g_free(text);
+            break;
+
+        case SPLITS_MEMO:
+            text = get_check_splits_memo2(pcd);
+            draw_text(context, text, item, default_desc);
+            g_free(text);
+            break;
+
+        case SPLITS_ACCOUNT:
+            text = get_check_splits_account2(pcd);
+            draw_text(context, text, item, default_desc);
+            g_free(text);
+            break;
+
+        case PICTURE:
+            draw_picture(context, item);
+            break;
+
+        default:
+            text = g_strdup_printf("(unknown check field, type %d)", item->type);
+            draw_text(context, text, item, default_desc);
+            g_free(text);
+            break;
+        }
+    }
+
+    pango_font_description_free(default_desc);
+}
+
+
+/* Print each of the items that in the description of a single check.  This
+ * function uses helper functions to print text based and picture based items.
+ */
+static void
+draw_page_boxes(GtkPrintContext *context,
+                check_format_t *format, gpointer user_data)
+{
+    cairo_t *cr;
+    GSList *elem;
+    check_item_t *item;
+
+    cr = gtk_print_context_get_cairo_context(context);
+
+    /* Now put the actual data onto the page. */
+    for (elem = format->items; elem; elem = g_slist_next(elem))
+    {
+        item = elem->data;
+        if (!item->w || !item->h)
+            continue;
+        cairo_rectangle(cr, item->x, item->y - item->h, item->w, item->h);
+        cairo_stroke(cr);
+    }
+}
+
+
+/* Print an entire page based upon the layout in a check description file. This
+ * function takes care of translating/rotating the page, calling the function to
+ * print the grid pattern (if requested), and calls a helper function to print
+ * all check items.
+ */
+static void
+draw_check_format(GtkPrintContext *context, gint position,
+                  check_format_t *format, gpointer user_data)
+{
+    PrintCheckDialog *pcd = (PrintCheckDialog *) user_data;
+    cairo_t *cr;
+    gdouble x, y, r, multip;
+
+    cr = gtk_print_context_get_cairo_context(context);
+    cairo_translate(cr, format->trans_x, format->trans_y);
+    g_debug("Page translated by %f,%f", format->trans_x, format->trans_y);
+    cairo_rotate(cr, format->rotation * DEGREES_TO_RADIANS);
+    g_debug("Page rotated by %f degrees", format->rotation);
+
+    /* The grid is useful when determining check layouts */
+    if (format->show_grid)
+    {
+        draw_grid(context,
+                  gtk_print_context_get_width(context),
+                  gtk_print_context_get_height(context),
+                  pcd->default_font);
+    }
+
+    /* Translate all subsequent check items if requested.
+     * For check position 0, no translation is needed. */
+    if ((position > 0) && (position < pcd->position_max))
+    {
+        /* Standard positioning is used.
+         * Note that the first check on the page (position 0) doesn't
+         * need to be moved (hence the test for position > 0 above. */
+        cairo_translate(cr, 0, format->height);
+        g_debug("Position %d translated by %f (pre-defined)", position, format->height);
+    }
+    else if (position == pcd->position_max)
+    {
+        /* Custom positioning is used. */
+        multip = pcd_get_custom_multip(pcd);
+        x = multip * gtk_spin_button_get_value(pcd->translation_x);
+        y = multip * gtk_spin_button_get_value(pcd->translation_y);
+        cairo_translate(cr, x, y);
+        g_debug("Position translated by %f,%f (custom)", x, y);
+        r = gtk_spin_button_get_value(pcd->check_rotation);
+        cairo_rotate(cr, r * DEGREES_TO_RADIANS);
+        g_debug("Position rotated by %f degrees (custom)", r);
+    }
+
+    /* Draw layout boxes if requested. Also useful when determining check
+     * layouts. */
+    if (format->show_boxes)
+        draw_page_boxes(context, format, user_data);
+
+    /* Draw the actual check data. */
+    draw_page_items(context, format, user_data);
+}
+
+
+static void
+draw_check_custom(GtkPrintContext *context, gpointer user_data)
+{
+    PrintCheckDialog *pcd = (PrintCheckDialog *) user_data;
+    GNCPrintAmountInfo info;
+    PangoFontDescription *desc;
+    Transaction *trans;
+    gnc_numeric amount;
+    cairo_t *cr;
+    const gchar *date_format;
+    gchar *text = NULL, buf[100];
+    check_item_t item = { 0 };
+    gdouble x, y, multip, degrees;
+    GDate date;
+    gchar *address;
+
+    trans = xaccSplitGetParent(pcd->split);
+    /* This was valid when the check printing dialog was instantiated. */
+    g_return_if_fail(trans);
+
+    desc = pango_font_description_from_string(pcd->default_font);
+
+    multip = pcd_get_custom_multip(pcd);
+    degrees = gtk_spin_button_get_value(pcd->check_rotation);
+    cr = gtk_print_context_get_cairo_context(context);
+    cairo_rotate(cr, degrees * DEGREES_TO_RADIANS);
+    g_debug("Page rotated by %f degrees", degrees);
+
+    x = multip * gtk_spin_button_get_value(pcd->translation_x);
+    y = multip * gtk_spin_button_get_value(pcd->translation_y);
+    cairo_translate(cr, x, y);
+    g_debug("Page translated by %f,%f", x, y);
+
+    item.x = multip * gtk_spin_button_get_value(pcd->payee_x);
+    item.y = multip * gtk_spin_button_get_value(pcd->payee_y);
+    draw_text(context, xaccTransGetDescription(trans), &item, desc);
+
+    item.x = multip * gtk_spin_button_get_value(pcd->date_x);
+    item.y = multip * gtk_spin_button_get_value(pcd->date_y);
+    g_date_clear (&date, 1);
+    gnc_gdate_set_time64 (&date, xaccTransGetDate(trans));
+    date_format = gnc_date_format_get_custom(GNC_DATE_FORMAT(pcd->date_format));
+    g_date_strftime(buf, 100, date_format, &date);
+    draw_text(context, buf, &item, desc);
+
+    item.x = multip * gtk_spin_button_get_value(pcd->number_x);
+    item.y = multip * gtk_spin_button_get_value(pcd->number_y);
+    info = gnc_default_print_info(FALSE);
+    amount = gnc_numeric_abs(xaccSplitGetAmount(pcd->split));
+    draw_text(context, xaccPrintAmount(amount, info), &item, desc);
+
+    item.x = multip * gtk_spin_button_get_value(pcd->words_x);
+    item.y = multip * gtk_spin_button_get_value(pcd->words_y);
+    text = numeric_to_words(amount);
+    draw_text(context, text, &item, desc);
+    g_free(text);
+
+    item.x = multip * gtk_spin_button_get_value(pcd->address_x);
+    item.y = multip * gtk_spin_button_get_value(pcd->address_y);
+    address = get_check_address2(pcd);
+    draw_text(context, address, &item, desc);
+    g_free(address);
+
+    item.x = multip * gtk_spin_button_get_value(pcd->splits_amount_x);
+    item.y = multip * gtk_spin_button_get_value(pcd->splits_amount_y);
+    text = get_check_splits_amount2(pcd);
+    draw_text(context, text, &item, desc);
+    g_free(text);
+
+    item.x = multip * gtk_spin_button_get_value(pcd->splits_memo_x);
+    item.y = multip * gtk_spin_button_get_value(pcd->splits_memo_y);
+    text = get_check_splits_memo2(pcd);
+    draw_text(context, text, &item, desc);
+    g_free(text);
+
+    item.x = multip * gtk_spin_button_get_value(pcd->splits_account_x);
+    item.y = multip * gtk_spin_button_get_value(pcd->splits_account_y);
+    text = get_check_splits_account2(pcd);
+    draw_text(context, text, &item, desc);
+    g_free(text);
+
+    item.x = multip * gtk_spin_button_get_value(pcd->notes_x);
+    item.y = multip * gtk_spin_button_get_value(pcd->notes_y);
+    draw_text(context, xaccTransGetNotes(trans), &item, desc);
+
+    item.x = multip * gtk_spin_button_get_value(pcd->memo_x);
+    item.y = multip * gtk_spin_button_get_value(pcd->memo_y);
+    draw_text(context, xaccSplitGetMemo(pcd->split), &item, desc);
+
+    pango_font_description_free(desc);
+}
+
+
+/* Print a page of checks. This takes into account the number of checks to print,
+ * the number of checks on a page, and the starting check position on the page.
+ * This function is called once by the GtkPrint code once for each page to be printed.
+ */
+static void
+draw_page(GtkPrintOperation *operation,
+          GtkPrintContext *context, gint page_nr, gpointer user_data)
+{
+    PrintCheckDialog *pcd = (PrintCheckDialog *) user_data;
+    check_format_t *format;
+
+    format = pcd->selected_format;
+    if (format)
+    {
+        gint    first_check, last_check;
+        gint    first_page_count;
+        guint   check_count = g_list_length(pcd->splits);
+        gint    check_number;
+        gint    position = gtk_combo_box_get_active(GTK_COMBO_BOX(pcd->position_combobox));
+        gint    checks_per_page;
+        GList   *next_split;
+
+        if (position == pcd->position_max)
+        {
+            /* Custom position, one check per page */
+            checks_per_page = 1;
+            first_page_count = 1;
+        }
+        else
+        {
+            checks_per_page = pcd->position_max;
+            first_page_count = gtk_spin_button_get_value_as_int(pcd->first_page_count);
+        }
+
+        if (page_nr == 0)
+        {
+            first_check = 0;
+            last_check = first_page_count - 1;
+            next_split = pcd->splits;
+        }
+        else
+        {
+            first_check = first_page_count + (page_nr - 1) * checks_per_page;
+            last_check = MIN(check_count - 1, first_check + checks_per_page - 1);
+            next_split = g_list_nth(pcd->splits, first_check);
+            /* If position is not "custom" reset it to top */
+            if (position < pcd->position_max)
+                position = 0;
+        }
+
+        for (check_number = first_check; check_number <= last_check;
+                check_number++, position++)
+        {
+            pcd->split = (Split *) next_split->data;
+            next_split = g_list_next(next_split);
+            draw_check_format(context, position, format, user_data);
+        }
+    }
+    else
+    {
+        /* Custom check format */
+        pcd->split = (Split *) g_list_nth_data(pcd->splits, page_nr);
+        g_return_if_fail(pcd->split);
+        draw_check_custom(context, user_data);
+    }
+}
+
+
+/* Compute the number of pages required to complete this print operation.
+ * This function is called once by the GtkPrint code to determine the number
+ * of pages required to complete the print operation.
+ */
+static void
+begin_print(GtkPrintOperation *operation,
+            GtkPrintContext *context, gpointer user_data)
+{
+    PrintCheckDialog *pcd = (PrintCheckDialog *) user_data;
+    guint check_count = g_list_length(pcd->splits);
+    gint first_page_count;
+    gint pages;
+    gint position = gtk_combo_box_get_active(GTK_COMBO_BOX(pcd->position_combobox));
+
+    if (pcd->selected_format && pcd->position_max > 1 && position < pcd->position_max)
+    {
+        first_page_count = gtk_spin_button_get_value_as_int(pcd->first_page_count);
+        pages = ((check_count - first_page_count) + pcd->position_max - 1) /
+                pcd->position_max + 1;
+    }
+    else
+        pages = check_count;
+    gtk_print_operation_set_n_pages(operation, pages);
+}
+
+
+/************************************
+ * gnc_ui_print_check_dialog_ok_cb  *
+ ************************************/
+static void
+gnc_ui_print_check_dialog_ok_cb(PrintCheckDialog *pcd)
+{
+    GtkPrintOperation *print;
+    GtkPrintOperationResult res;
+
+    print = gtk_print_operation_new();
+
+    gnc_print_operation_init(print, "GnuCash-Checks");
+    gtk_print_operation_set_unit(print, GTK_UNIT_POINTS);
+    gtk_print_operation_set_use_full_page(print, TRUE);
+    g_signal_connect(print, "begin_print", G_CALLBACK(begin_print), pcd);
+    g_signal_connect(print, "draw_page", G_CALLBACK(draw_page), pcd);
+
+    res = gtk_print_operation_run(print,
+                                  GTK_PRINT_OPERATION_ACTION_PRINT_DIALOG,
+                                  pcd->caller_window, NULL);
+
+    if (res == GTK_PRINT_OPERATION_RESULT_APPLY)
+        gnc_print_operation_save_print_settings(print);
+
+    g_object_unref(print);
+}
+
+
+static void
+gnc_print_check_set_sensitive (GtkWidget *widget, gpointer data)
+{
+    gboolean sensitive;
+    if (GTK_IS_LABEL(widget) || GTK_IS_SEPARATOR(widget))
+        return;
+    sensitive = GPOINTER_TO_INT(data);
+    gtk_widget_set_sensitive(widget, sensitive);
+}
+
+
+void
+gnc_print_check_format_changed2 (GtkComboBox *widget,
+                                PrintCheckDialog *pcd)
+{
+    GtkListStore *p_store;
+    GtkTreeModel *f_model;
+    GtkTreeIter f_iter, iter;
+    gboolean sensitive;
+    gint pnum;
+    check_format_t *format;
+    gboolean separator;
+    GSList *elem;
+
+    if (!gtk_combo_box_get_active_iter(GTK_COMBO_BOX(pcd->format_combobox), &f_iter))
+        return;
+    f_model = gtk_combo_box_get_model(GTK_COMBO_BOX(pcd->format_combobox));
+    gtk_tree_model_get(f_model, &f_iter, COL_DATA, &format, COL_SEP, &separator, -1);
+    if (separator)
+        return;
+
+    pnum = gtk_combo_box_get_active(GTK_COMBO_BOX(pcd->position_combobox));
+
+    /* Update the positions combobox */
+    pcd->selected_format = format;
+    p_store = gtk_list_store_new (1, G_TYPE_STRING);
+    gtk_combo_box_set_model(GTK_COMBO_BOX(pcd->position_combobox),
+                            GTK_TREE_MODEL(p_store));
+    if (format)
+    {
+        if (format->positions)
+        {
+            pcd->position_max = g_slist_length(format->positions); /* -1 for 0 base, +1 for custom entry */
+            for (elem = format->positions; elem; elem = g_slist_next(elem))
+            {
+                gtk_list_store_append(GTK_LIST_STORE(p_store), &iter);
+                gtk_list_store_set (GTK_LIST_STORE(p_store), &iter, 0, elem->data, -1);
+            }
+        }
+        else
+        {
+            /* Invent a "Top" position if format has no positions */
+            pcd->position_max = 1;
+            gtk_list_store_append(GTK_LIST_STORE(p_store), &iter);
+            gtk_list_store_set (GTK_LIST_STORE(p_store), &iter, 0, _("Top"), -1);
+        }
+    }
+    else
+    {
+        pcd->position_max = 0;
+    }
+    gtk_list_store_append(GTK_LIST_STORE(p_store), &iter);
+    gtk_list_store_set (GTK_LIST_STORE(p_store), &iter, 0, _("Custom"), -1);
+
+    /* If there's only one thing in the position combobox, make it insensitive */
+    sensitive = (pcd->position_max > 0);
+    gtk_widget_set_sensitive(GTK_WIDGET(pcd->position_combobox), sensitive);
+
+    /* Update the custom page, this must be done before setting the active
+       entry in the position combo box since gnc_print_check_position_changed2
+       will adjust these settings in some cases. */
+    sensitive = (!separator && !format);
+    gtk_container_foreach(GTK_CONTAINER(pcd->custom_table),
+                          gnc_print_check_set_sensitive,
+                          GINT_TO_POINTER(sensitive));
+
+    /* Set the active entry in the position combo box, this will trigger a
+       call to gnc_print_check_position_changed2 */
+    pnum = MAX(MIN(pnum, pcd->position_max), 0);
+    gtk_combo_box_set_active(GTK_COMBO_BOX(pcd->position_combobox), pnum);
+
+    /* Update address fields */
+    sensitive = check_format_has_address(pcd);
+    gtk_widget_set_sensitive(pcd->check_address_name, sensitive);
+    gtk_widget_set_sensitive(pcd->check_address_1, sensitive);
+    gtk_widget_set_sensitive(pcd->check_address_2, sensitive);
+    gtk_widget_set_sensitive(pcd->check_address_3, sensitive);
+    gtk_widget_set_sensitive(pcd->check_address_4, sensitive);
+}
+
+
+void
+gnc_print_check_position_changed2 (GtkComboBox *widget,
+                                  PrintCheckDialog *pcd)
+{
+    gboolean sensitive;
+    gint pnum;
+    guint check_count;
+    gint first_page_max, first_page_min, first_page_value;
+
+    pnum = gtk_combo_box_get_active(GTK_COMBO_BOX(pcd->position_combobox));
+
+    /* Make the translation and rotation fields active if the position is "custom" */
+    sensitive = pnum == pcd->position_max;
+    gtk_widget_set_sensitive(GTK_WIDGET(pcd->translation_x), sensitive);
+    gtk_widget_set_sensitive(GTK_WIDGET(pcd->translation_y), sensitive);
+    gtk_widget_set_sensitive(GTK_WIDGET(pcd->check_rotation), sensitive);
+    gtk_widget_set_sensitive(GTK_WIDGET(pcd->units_combobox), sensitive);
+
+    /* Set up the first page check count spin box */
+    check_count = g_list_length(pcd->splits);
+    first_page_max = MAX(1, MIN(pcd->position_max - pnum, check_count));
+    first_page_min = 1;
+    pnum = gtk_spin_button_get_value_as_int(pcd->first_page_count);
+    first_page_value = MAX(MIN(pnum, first_page_max), first_page_min);
+    gtk_spin_button_set_range(pcd->first_page_count, (gdouble)first_page_min, (gdouble)first_page_max);
+    gtk_spin_button_set_value(pcd->first_page_count, (gdouble)first_page_value);
+    sensitive = first_page_max > 1;
+    gtk_widget_set_sensitive(GTK_WIDGET(pcd->first_page_count), sensitive);
+}
+
+
+void
+gnc_ui_print_check_response_cb2(GtkDialog *dialog,
+                               gint response,
+                               PrintCheckDialog *pcd)
+{
+    switch (response)
+    {
+    case GTK_RESPONSE_HELP:
+        gnc_gnome_help(HF_HELP, HL_PRINTCHECK);
+        return;
+
+    case GTK_RESPONSE_OK:
+        gnc_ui_print_check_dialog_ok_cb(pcd);
+        gnc_ui_print_save_dialog(pcd);
+        gnc_save_window_size(GCONF_SECTION, GTK_WINDOW(dialog));
+        break;
+
+    case GTK_RESPONSE_CANCEL:
+        gnc_save_window_size(GCONF_SECTION, GTK_WINDOW(dialog));
+        break;
+    }
+
+    gtk_widget_destroy(pcd->dialog);
+    g_free(pcd->default_font);
+    g_list_free(pcd->splits);
+    g_free(pcd);
+}

Added: gnucash/trunk/src/gnome/dialog-print-check2.h
===================================================================
--- gnucash/trunk/src/gnome/dialog-print-check2.h	                        (rev 0)
+++ gnucash/trunk/src/gnome/dialog-print-check2.h	2013-04-07 22:14:31 UTC (rev 22885)
@@ -0,0 +1,34 @@
+/********************************************************************\
+ * dialog-print-check2.h : dialog to control check printing          *
+ * Copyright (C) 2000 Bill Gribble <grib at billgribble.com>           *
+ * Copyright (C) 2006 David Hampton <hampton at employees.org>         *
+ *                                                                  *
+ * 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       *
+ * 51 Franklin Street, Fifth Floor    Fax:    +1-617-542-2652       *
+ * Boston, MA  02110-1301,  USA       gnu at gnu.org                   *
+\********************************************************************/
+
+#ifndef DIALOG_PRINT_CHECK2_H
+#define DIALOG_PRINT_CHECK2_H
+
+#include "print-session.h"
+
+typedef struct _print_check_dialog PrintCheckDialog;
+
+void gnc_ui_print_check_dialog_create2 (GncPluginPageRegister2 *plugin_page,
+                                      GList *splits);
+
+#endif

Modified: gnucash/trunk/src/gnome/gnc-plugin-basic-commands.c
===================================================================
--- gnucash/trunk/src/gnome/gnc-plugin-basic-commands.c	2013-04-07 22:14:20 UTC (rev 22884)
+++ gnucash/trunk/src/gnome/gnc-plugin-basic-commands.c	2013-04-07 22:14:31 UTC (rev 22885)
@@ -43,6 +43,7 @@
 #include "dialog-file-access.h"
 #include "dialog-fincalc.h"
 #include "dialog-find-transactions.h"
+#include "dialog-find-transactions2.h"
 #include "dialog-sx-since-last-run.h"
 #include "dialog-totd.h"
 #include "assistant-acct-period.h"
@@ -624,6 +625,9 @@
 gnc_main_window_cmd_tools_find_transactions (GtkAction *action, GncMainWindowActionData *data)
 {
     gnc_ui_find_transactions_dialog_create (NULL);
+/*################## Added for Reg2 #################*/
+//    gnc_ui_find_transactions_dialog_create2 (NULL);
+/*################## Added for Reg2 #################*/
 }
 
 static void

Modified: gnucash/trunk/src/gnome/gnc-plugin-page-register2.c
===================================================================
--- gnucash/trunk/src/gnome/gnc-plugin-page-register2.c	2013-04-07 22:14:20 UTC (rev 22884)
+++ gnucash/trunk/src/gnome/gnc-plugin-page-register2.c	2013-04-07 22:14:31 UTC (rev 22885)
@@ -52,10 +52,13 @@
 #include "gnc-tree-control-split-reg.h"
 
 #include "dialog-account.h"
-#include "dialog-find-transactions.h"
-//#include "dialog-print-check.h"
+#include "dialog-find-transactions2.h"
+#include "dialog-print-check2.h"
 #include "dialog-transfer.h"
 #include "dialog-utils.h"
+#include "SX-book.h"
+#include "dialog-sx-editor.h"
+#include "dialog-sx-from-trans.h"
 #include "assistant-stock-split.h"
 #include "gnc-gconf-utils.h"
 #include "gnc-component-manager.h"
@@ -77,7 +80,7 @@
 #include "dialog-lot-viewer.h"
 #include "Scrub.h"
 #include "qof.h"
-#include "window-reconcile.h"
+#include "window-reconcile2.h"
 #include "window-autoclear.h"
 #include "window-report.h"
 
@@ -137,6 +140,7 @@
 static void gnc_plugin_page_register2_cmd_unvoid_transaction (GtkAction *action, GncPluginPageRegister2 *plugin_page);
 static void gnc_plugin_page_register2_cmd_reverse_transaction (GtkAction *action, GncPluginPageRegister2 *plugin_page);
 static void gnc_plugin_page_register2_cmd_shift_transaction_forward (GtkAction *action, GncPluginPageRegister2 *plugin_page);
+static void gnc_plugin_page_register2_cmd_reload (GtkAction *action, GncPluginPageRegister2 *plugin_page);
 static void gnc_plugin_page_register2_cmd_view_filter_by (GtkAction *action, GncPluginPageRegister2 *plugin_page);
 static void gnc_plugin_page_register2_cmd_style_changed (GtkAction *action, GtkRadioAction *current, GncPluginPageRegister2 *plugin_page);
 static void gnc_plugin_page_register2_cmd_style_double_line (GtkToggleAction *action, GncPluginPageRegister2 *plugin_page);
@@ -278,6 +282,11 @@
         "ViewFilterByAction", NULL, N_("_Filter By..."), NULL, NULL,
         G_CALLBACK (gnc_plugin_page_register2_cmd_view_filter_by)
     },
+    {
+        "ViewRefreshAction", GTK_STOCK_REFRESH, N_("_Refresh"), "<control>r",
+        N_("Refresh this window"),
+        G_CALLBACK (gnc_plugin_page_register2_cmd_reload)
+    },
 
     /* Actions menu */
 
@@ -555,13 +564,13 @@
     gsr = gnc_ledger_display2_get_user_data (ledger);
     if (gsr)
     {
-        item = gnc_gobject_tracking_get_list(GNC_PLUGIN_PAGE_REGISTER2_NAME);
-        for ( ; item; item = g_list_next(item))
+        item = gnc_gobject_tracking_get_list (GNC_PLUGIN_PAGE_REGISTER2_NAME);
+        for ( ; item; item = g_list_next (item))
         {
             register_page = (GncPluginPageRegister2 *)item->data;
-            priv = GNC_PLUGIN_PAGE_REGISTER2_GET_PRIVATE(register_page);
+            priv = GNC_PLUGIN_PAGE_REGISTER2_GET_PRIVATE (register_page);
             if (priv->gsr == gsr)
-                return GNC_PLUGIN_PAGE(register_page);
+                return GNC_PLUGIN_PAGE (register_page);
         }
     }
 
@@ -570,9 +579,9 @@
     priv->ledger = ledger;
     priv->key = *guid_null();
 
-    plugin_page = GNC_PLUGIN_PAGE(register_page);
-    label = gnc_plugin_page_register2_get_tab_name(plugin_page);
-    gnc_plugin_page_set_page_name(plugin_page, label);
+    plugin_page = GNC_PLUGIN_PAGE (register_page);
+    label = gnc_plugin_page_register2_get_tab_name (plugin_page);
+    gnc_plugin_page_set_page_name (plugin_page, label);
     g_free(label);
 
     label_color = gnc_plugin_page_register2_get_tab_color(plugin_page);
@@ -610,9 +619,9 @@
     else
         ledger = gnc_ledger_display2_simple (account);
 
-    page = gnc_plugin_page_register2_new_common(ledger);
-    priv = GNC_PLUGIN_PAGE_REGISTER2_GET_PRIVATE(page);
-    priv->key = *xaccAccountGetGUID(account);
+    page = gnc_plugin_page_register2_new_common (ledger);
+    priv = GNC_PLUGIN_PAGE_REGISTER2_GET_PRIVATE (page);
+    priv->key = *xaccAccountGetGUID (account);
 
     LEAVE("%p", page);
     return page;
@@ -624,13 +633,13 @@
     GNCLedgerDisplay2 *ledger;
 
     ledger = gnc_ledger_display2_gl ();
-    return gnc_plugin_page_register2_new_common(ledger);
+    return gnc_plugin_page_register2_new_common (ledger);
 }
 
 GncPluginPage *
 gnc_plugin_page_register2_new_ledger (GNCLedgerDisplay2 *ledger)
 {
-    return gnc_plugin_page_register2_new_common(ledger);
+    return gnc_plugin_page_register2_new_common (ledger);
 }
 
 static void
@@ -774,13 +783,12 @@
     view = gnc_ledger_display2_get_split_view_register (priv->ledger);
 
     expanded = gnc_tree_view_split_reg_trans_expanded (view, NULL);
-
-    action = gnc_plugin_page_get_action (GNC_PLUGIN_PAGE(page),
+    action = gnc_plugin_page_get_action (GNC_PLUGIN_PAGE (page),
                                          "SplitTransactionAction");
     gtk_action_set_sensitive (action, model->style == REG2_STYLE_LEDGER);
     g_signal_handlers_block_by_func
     (action, gnc_plugin_page_register2_cmd_expand_transaction, page);
-    gtk_toggle_action_set_active (GTK_TOGGLE_ACTION(action), expanded);
+    gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (action), expanded);
     g_signal_handlers_unblock_by_func
     (action, gnc_plugin_page_register2_cmd_expand_transaction, page);
 
@@ -788,25 +796,24 @@
     trans = gnc_tree_view_split_reg_get_current_trans (view);
     voided = xaccTransHasSplitsInState (trans, VREC); 
 
-    action = gnc_plugin_page_get_action (GNC_PLUGIN_PAGE(page),
+    action = gnc_plugin_page_get_action (GNC_PLUGIN_PAGE (page),
                                          "VoidTransactionAction");
-    gtk_action_set_sensitive (GTK_ACTION(action), !voided);
+    gtk_action_set_sensitive (GTK_ACTION (action), !voided);
 
-    action = gnc_plugin_page_get_action (GNC_PLUGIN_PAGE(page),
+    action = gnc_plugin_page_get_action (GNC_PLUGIN_PAGE (page),
                                          "UnvoidTransactionAction");
-    gtk_action_set_sensitive (GTK_ACTION(action), voided);
+    gtk_action_set_sensitive (GTK_ACTION (action), voided);
 
     /* If we are in a readonly book, make any modifying action inactive */
-    if (qof_book_is_readonly(gnc_get_current_book()))
+    if (qof_book_is_readonly(gnc_get_current_book ()))
     {
         const char **iter;
         for (iter = readonly_inactive_actions; *iter; ++iter)
         {
             /* Set the action's sensitivity */
-            GtkAction *action = gnc_plugin_page_get_action (GNC_PLUGIN_PAGE(page), *iter);
-            gtk_action_set_sensitive(action, FALSE);
+            GtkAction *action = gnc_plugin_page_get_action (GNC_PLUGIN_PAGE (page), *iter);
+            gtk_action_set_sensitive (action, FALSE);
         }
-
     }
 }
 
@@ -883,7 +890,7 @@
 
     ENTER("page %p", plugin_page);
     page = GNC_PLUGIN_PAGE_REGISTER2 (plugin_page);
-    priv = GNC_PLUGIN_PAGE_REGISTER2_GET_PRIVATE(page);
+    priv = GNC_PLUGIN_PAGE_REGISTER2_GET_PRIVATE (page);
     if (priv->widget != NULL)
     {
         LEAVE("existing widget %p", priv->widget);
@@ -894,12 +901,12 @@
     gtk_widget_show (priv->widget);
 
     numRows = priv->lines_default;
-    numRows = MIN(numRows, DEFAULT_LINES_AMOUNT);
+    numRows = MIN (numRows, DEFAULT_LINES_AMOUNT);
 
-    gnc_window = GNC_WINDOW(GNC_PLUGIN_PAGE(page)->window);
+    gnc_window = GNC_WINDOW (GNC_PLUGIN_PAGE (page)->window);
 
-    gsr = gnc_split_reg2_new(priv->ledger,
-                            gnc_window_get_gtk_window(gnc_window),
+    gsr = gnc_split_reg2_new (priv->ledger,
+                            gnc_window_get_gtk_window (gnc_window),
                             numRows, priv->read_only);
     priv->gsr = (GNCSplitReg2 *)gsr;
     gtk_widget_show (gsr);
@@ -907,7 +914,7 @@
     gtk_box_pack_start (GTK_BOX (priv->widget), gsr, TRUE, TRUE, 0);
 
     g_signal_connect (G_OBJECT (gsr), "help-changed",
-                      G_CALLBACK ( gnc_plugin_page_help_changed_cb ),
+                      G_CALLBACK (gnc_plugin_page_help_changed_cb),
                       page );
 
     view = gnc_split_reg2_get_register (priv->gsr);
@@ -1130,7 +1137,7 @@
  *  @param plugin_page The page to save.
  *
  *  @param key_file A pointer to the GKeyFile data structure where the
- *  page information should be written.gnc_plugin_page_register2_save_page
+ *  page information should be written. gnc_plugin_page_register2_save_page
  *
  *  @param group_name The group name to use when saving data. */
 static void
@@ -2267,7 +2274,7 @@
 
 static void
 gnc_plugin_page_register2_cmd_print_check (GtkAction *action,
-        GncPluginPageRegister2 *plugin_page) //FIXME Should work but not tested
+        GncPluginPageRegister2 *plugin_page) // this works
 {
     GncPluginPageRegister2Private *priv;
     GncTreeViewSplitReg *view;
@@ -2286,19 +2293,42 @@
     model = gnc_ledger_display2_get_split_model_register (priv->ledger);
     ledger_type = gnc_ledger_display2_type (priv->ledger);
 
-//FIXME  'gnc_ui_print_check_dialog_create' uses 'GncPluginPageRegister' so this will need to wait
-//        for when we change the type back or I add a new function to dialog-print-check using
-//        'GncPluginPageRegister2'
-#ifdef skip
     if (ledger_type == LD2_SINGLE || ledger_type == LD2_SUBACCOUNT)
     {
         split = gnc_tree_view_split_reg_get_current_split (view);
         trans = xaccSplitGetParent (split);
 
+        if (trans == NULL)
+        {
+            LEAVE("trans is NULL");
+            return;
+        }
+
+        /* See if we were asked to print a blank trans. */
+        if (trans == gnc_tree_control_split_reg_get_blank_trans (view))
+        {
+            LEAVE("Asked to print a blank trans");
+            return;
+        }
+
+        /* See if we are being edited in another register */
+        if (gnc_tree_control_split_reg_trans_test_for_edit (view, trans))
+        {
+            LEAVE("trans being edited in another register");
+            return;
+        }
+
+        /* Make sure we ask to commit any changes before we procede */
+        if (gnc_tree_control_split_reg_trans_open_and_warn (view, trans))
+        {
+            LEAVE("trans being edited");
+            return;
+        }
+
         if (split && trans)
         {
             splits = g_list_append (splits, split);
-            gnc_ui_print_check_dialog_create (plugin_page, splits);
+            gnc_ui_print_check_dialog_create2 (plugin_page, splits);
             g_list_free (splits);
         }
     }
@@ -2346,7 +2376,7 @@
                 }
             }
         }
-        gnc_ui_print_check_dialog_create (plugin_page, splits);
+        gnc_ui_print_check_dialog_create2 (plugin_page, splits);
     }
     else
     {
@@ -2355,7 +2385,6 @@
         LEAVE("Unsupported ledger type");
         return;
     }
-#endif
     LEAVE(" ");
 }
 
@@ -2451,7 +2480,7 @@
 
 static void
 gnc_plugin_page_register2_cmd_find_transactions (GtkAction *action,
-        GncPluginPageRegister2 *page) //FIXME see below
+        GncPluginPageRegister2 *page) // this works
 {
     GncPluginPageRegister2Private *priv;
 
@@ -2459,8 +2488,8 @@
 
     ENTER("(action %p, page %p)", action, page);
     priv = GNC_PLUGIN_PAGE_REGISTER2_GET_PRIVATE(page);
-/*FIXME This function has the original ledger type */
-/*    gnc_ui_find_transactions_dialog_create(priv->ledger); */
+
+    gnc_ui_find_transactions_dialog_create2 (priv->ledger);
     LEAVE(" ");
 }
 
@@ -2811,6 +2840,41 @@
     LEAVE(" ");
 }
 
+
+static void
+gnc_plugin_page_register2_cmd_reload (GtkAction *action, GncPluginPageRegister2 *plugin_page) //this works
+{
+    GncPluginPageRegister2Private *priv;
+    GncTreeViewSplitReg *view;
+
+    Transaction *trans;
+
+    ENTER("(action %p, page %p)", action, plugin_page);
+
+    g_return_if_fail (GNC_IS_PLUGIN_PAGE_REGISTER2 (plugin_page));
+
+    priv = GNC_PLUGIN_PAGE_REGISTER2_GET_PRIVATE (plugin_page);
+
+    view = gnc_ledger_display2_get_split_view_register (priv->ledger);
+
+    trans = gnc_tree_view_split_reg_get_current_trans (view);
+
+    /* Make sure we ask to commit any changes before we procede */
+    if (gnc_tree_control_split_reg_trans_open_and_warn (view, trans))
+    {
+        LEAVE("trans being edited");
+        return;
+    }
+
+    /* give gtk+ a chance to handle pending events */
+    while (gtk_events_pending ())
+        gtk_main_iteration ();
+
+    gnc_ledger_display2_refresh (priv->ledger);
+
+    LEAVE(" ");
+}
+
 /*#################################################################################*/
 /*#################################################################################*/
 
@@ -2825,15 +2889,15 @@
     ENTER("(action %p, radio action %p, plugin_page %p)",
           action, current, plugin_page);
 
-    g_return_if_fail(GTK_IS_ACTION(action));
-    g_return_if_fail(GTK_IS_RADIO_ACTION(current));
-    g_return_if_fail(GNC_IS_PLUGIN_PAGE_REGISTER2(plugin_page));
+    g_return_if_fail (GTK_IS_ACTION (action));
+    g_return_if_fail (GTK_IS_RADIO_ACTION (current));
+    g_return_if_fail (GNC_IS_PLUGIN_PAGE_REGISTER2 (plugin_page));
 
-    priv = GNC_PLUGIN_PAGE_REGISTER2_GET_PRIVATE(plugin_page);
-    value = gtk_radio_action_get_current_value(current);
-    gnc_split_reg2_change_style(priv->gsr, value);
+    priv = GNC_PLUGIN_PAGE_REGISTER2_GET_PRIVATE (plugin_page);
+    value = gtk_radio_action_get_current_value (current);
+    gnc_split_reg2_change_style (priv->gsr, value);
 
-    gtk_tree_view_collapse_all (GTK_TREE_VIEW( gnc_ledger_display2_get_split_view_register (priv->ledger)));
+    gtk_tree_view_collapse_all (GTK_TREE_VIEW (gnc_ledger_display2_get_split_view_register (priv->ledger)));
 
     gnc_plugin_page_register2_ui_update (NULL, plugin_page);
     LEAVE(" ");
@@ -2891,25 +2955,40 @@
 gnc_plugin_page_register2_cmd_reconcile (GtkAction *action,
                                         GncPluginPageRegister2 *page) // this works
 {
+    GncPluginPageRegister2Private *priv;
+    GncTreeViewSplitReg *view;
     Account *account;
+    Transaction *trans;
     GtkWindow *window;
-    RecnWindow * recnData;
+    RecnWindow2 * recnData;
 
     ENTER("(action %p, plugin_page %p)", action, page);
 
-    g_return_if_fail(GNC_IS_PLUGIN_PAGE_REGISTER2(page));
+    g_return_if_fail (GNC_IS_PLUGIN_PAGE_REGISTER2 (page));
 
+    priv = GNC_PLUGIN_PAGE_REGISTER2_GET_PRIVATE (page);
+    view = gnc_ledger_display2_get_split_view_register (priv->ledger);
+
     account = gnc_plugin_page_register2_get_account (page);
 
-    window = gnc_window_get_gtk_window(GNC_WINDOW(GNC_PLUGIN_PAGE (page)->window));
-    recnData = recnWindow (GTK_WIDGET(window), account);
-    gnc_ui_reconcile_window_raise (recnData);
+    trans = gnc_tree_view_split_reg_get_current_trans (view);
+
+    /* Make sure we ask to commit any changes before we procede */
+    if (gnc_tree_control_split_reg_trans_open_and_warn (view, trans))
+    {
+        LEAVE("trans being edited");
+        return;
+    }
+
+    window = gnc_window_get_gtk_window (GNC_WINDOW (GNC_PLUGIN_PAGE (page)->window));
+    recnData = recnWindow2 (GTK_WIDGET (window), account);
+    gnc_ui_reconcile_window2_raise (recnData);
     LEAVE(" ");
 }
 
 static void
 gnc_plugin_page_register2_cmd_autoclear (GtkAction *action,
-                                        GncPluginPageRegister2 *page) //FIXME What is this?
+                                        GncPluginPageRegister2 *page)
 {
     Account *account;
     GtkWindow *window;
@@ -3197,22 +3276,98 @@
 
     ld = gnc_plugin_page_register2_get_ledger (new_page);
     new_view = gnc_ledger_display2_get_split_view_register (ld);
-    gnc_tree_control_split_reg_jump_to_split (new_view, split);
+    gnc_tree_control_split_reg_jump_to_split (new_view, split, FALSE);
     LEAVE(" ");
 }
 
+
+/**
+ * Schedules the current transaction for recurring-entry.
+ * If the selected transaction was created from a scheduled transaction,
+ * opens the editor for that Scheduled Transaction.
+ **/
 static void
 gnc_plugin_page_register2_cmd_schedule (GtkAction *action,
-                                       GncPluginPageRegister2 *plugin_page) //FIXME Not setup
+                                       GncPluginPageRegister2 *plugin_page) // this works
 {
     GncPluginPageRegister2Private *priv;
+    GncTreeViewSplitReg *view;
+    Transaction *trans;
 
     ENTER("(action %p, plugin_page %p)", action, plugin_page);
 
     g_return_if_fail(GNC_IS_PLUGIN_PAGE_REGISTER2(plugin_page));
 
     priv = GNC_PLUGIN_PAGE_REGISTER2_GET_PRIVATE(plugin_page);
-//    gsr2_default_schedule_handler(priv->gsr, NULL);
+    view = gnc_ledger_display2_get_split_view_register (priv->ledger);
+
+    trans = gnc_tree_view_split_reg_get_current_trans (view);
+
+    if (trans == NULL)
+    {
+        LEAVE("trans is NULL");
+        return;
+    }
+
+    /* See if we were asked to schedule a blank trans. */
+    if (trans == gnc_tree_control_split_reg_get_blank_trans (view))
+    {
+        LEAVE("Asked to schedule a blank trans");
+        return;
+    }
+
+    /* See if we are being edited in another register */
+    if (gnc_tree_control_split_reg_trans_test_for_edit (view, trans))
+    {
+        LEAVE("trans being edited in another register");
+        return;
+    }
+
+    /* Make sure we ask to commit any changes before we procede */
+    if (gnc_tree_control_split_reg_trans_open_and_warn (view, trans))
+    {
+        LEAVE("trans being edited");
+        return;
+    }
+
+    /* If the transaction has a sched-xact KVP frame, then go to the editor
+     * for the existing SX; otherwise, do the sx-from-trans dialog. */
+    {
+        kvp_frame *txn_frame;
+        kvp_value *kvp_val;
+        /* set a kvp-frame element in the transaction indicating and
+         * pointing-to the SX this was created from. */
+        txn_frame = xaccTransGetSlots (trans);
+        if ( txn_frame != NULL )
+        {
+            kvp_val = kvp_frame_get_slot (txn_frame, "from-sched-xaction");
+            if (kvp_val)
+            {
+                GncGUID *fromSXId = kvp_value_get_guid (kvp_val);
+                SchedXaction *theSX = NULL;
+                GList *sxElts;
+
+                /* Get the correct SX */
+                for ( sxElts = gnc_book_get_schedxactions (gnc_get_current_book())->sx_list;
+                        (!theSX) && sxElts;
+                        sxElts = sxElts->next )
+                {
+                    SchedXaction *sx = (SchedXaction*)sxElts->data;
+                    theSX =
+                        ((guid_equal (xaccSchedXactionGetGUID (sx), fromSXId))
+                          ? sx : NULL);
+                }
+
+                if (theSX)
+                {
+                    gnc_ui_scheduled_xaction_editor_dialog_create (theSX, FALSE);
+                    LEAVE(" ");
+                    return;
+                }
+            }
+        }
+    }
+    gnc_sx_create_from_trans (trans);
     LEAVE(" ");
 }
 
@@ -3429,12 +3584,14 @@
 }
 
 static void
-gnc_plugin_page_register2_refresh_cb (GHashTable *changes, gpointer user_data) //FIXME does not work ?
+gnc_plugin_page_register2_refresh_cb (GHashTable *changes, gpointer user_data)
 {
     GncPluginPageRegister2 *page = user_data;
     GncPluginPageRegister2Private *priv;
     GncTreeViewSplitReg *view;
 
+// Not sure what this really is but it gets fired from preference changes.
+
 //g_print("gnc_plugin_page_register2_refresh_cb\n");
     g_return_if_fail (GNC_IS_PLUGIN_PAGE_REGISTER2 (page));
     priv = GNC_PLUGIN_PAGE_REGISTER2_GET_PRIVATE (page);

Modified: gnucash/trunk/src/gnome/gnc-split-reg2.c
===================================================================
--- gnucash/trunk/src/gnome/gnc-split-reg2.c	2013-04-07 22:14:20 UTC (rev 22884)
+++ gnucash/trunk/src/gnome/gnc-split-reg2.c	2013-04-07 22:14:31 UTC (rev 22885)
@@ -30,33 +30,14 @@
 
 #include <gtk/gtk.h>
 #include <glib/gi18n.h>
-#include <time.h>
 
 #include "gnc-split-reg2.h"
-
-#include "Account.h"
-#include "qof.h"
-#include "SX-book.h"
-#include "dialog-account.h"
-#include "dialog-sx-editor.h"
-#include "dialog-sx-from-trans.h"
-#include "gnc-component-manager.h"
-#include "gnc-date-edit.h"
-#include "gnc-engine.h"
-#include "gnc-euro.h"
-#include "gnc-gconf-utils.h"
-#include "gnc-gui-query.h"
-#include "gnc-ledger-display2.h"
-#include "gnc-pricedb.h"
-#include "gnc-ui-util.h"
-#include "gnc-ui.h"
-
-#include "gnucash-sheet.h"
-#include "table-allgui.h"
-
 #include "gnc-tree-view-split-reg.h"
 #include "gnc-tree-control-split-reg.h"
+#include "gnc-ledger-display2.h"
 
+#include "gnc-euro.h"
+#include "gnc-gconf-utils.h"
 #include "dialog-utils.h"
 
 #define GCONF_SECTION "window/pages/register2"
@@ -64,24 +45,22 @@
 static QofLogModule log_module = GNC_MOD_GUI;
 
 /***** PROTOTYPES ***************************************************/
-void gnc_split_reg2_raise( GNCSplitReg2 *gsr ); /*FIXME What this for */
+void gnc_split_reg2_raise (GNCSplitReg2 *gsr);
 
-static GtkWidget* add_summary_label( GtkWidget *summarybar,
-                                     const char *label_str );
+static GtkWidget* add_summary_label (GtkWidget *summarybar,
+                                     const char *label_str);
 
-static void gnc_split_reg2_determine_read_only( GNCSplitReg2 *gsr );
+static void gnc_split_reg2_determine_read_only (GNCSplitReg2 *gsr);
 
-static GNCPlaceholderType gnc_split_reg2_get_placeholder( GNCSplitReg2 *gsr );
-static GtkWidget *gnc_split_reg2_get_parent( GNCLedgerDisplay2 *ledger );
+static GNCPlaceholderType gnc_split_reg2_get_placeholder (GNCSplitReg2 *gsr);
+static GtkWidget *gnc_split_reg2_get_parent (GNCLedgerDisplay2 *ledger);
 
+static void gsr2_create_table (GNCSplitReg2 *gsr);
+static void gsr2_setup_table (GNCSplitReg2 *gsr);
 
-static void gsr2_create_table( GNCSplitReg2 *gsr );
-static void gsr2_setup_table( GNCSplitReg2 *gsr );
+static void gsr2_setup_status_widgets (GNCSplitReg2 *gsr);
 
-
-static void gsr2_setup_status_widgets( GNCSplitReg2 *gsr );
-
-static void gsr2_update_summary_label( GtkWidget *label,
+static void gsr2_update_summary_label (GtkWidget *label,
                                       xaccGetBalanceFn getter,
                                       Account *leader,
                                       GNCPrintAmountInfo print_info,
@@ -91,34 +70,21 @@
 
 static void gsr2_redraw_all_cb (GncTreeViewSplitReg *view, gpointer data);
 
-static void gnc_split_reg2_refresh_toolbar( GNCSplitReg2 *gsr );
+static void gnc_split_reg2_refresh_toolbar (GNCSplitReg2 *gsr);
 
-static void gnc_split_reg2_ld_destroy( GNCLedgerDisplay2 *ledger );
+static void gnc_split_reg2_ld_destroy (GNCLedgerDisplay2 *ledger);
 
-static Transaction* create_balancing_transaction(QofBook *book, Account *account,
+static Transaction* create_balancing_transaction (QofBook *book, Account *account,
         time64 statement_date, gnc_numeric balancing_amount);
 
-
-void gsr2_default_schedule_handler ( GNCSplitReg2 *w, gpointer ud );
-
-
-static void gsr2_emit_simple_signal( GNCSplitReg2 *gsr, const char *sigName );
+static void gsr2_emit_simple_signal (GNCSplitReg2 *gsr, const char *sigName);
 static void gsr2_emit_help_changed (GncTreeViewSplitReg *view, gpointer user_data);
-static void gsr2_emit_include_date_signal( GNCSplitReg2 *gsr, time64 date );
 
-
-/*FIXME void gnc_split_reg2_record_cb (GncTreeViewSplitReg *view, gpointer data); */
-
-void gnc_split_reg2_recur_cb(GtkWidget *w, gpointer data);
-void gnc_split_reg2_record_trans_cb(GtkWidget *w, gpointer data);
-
-
 void gnc_split_reg2_style_ledger_cb (GtkWidget *w, gpointer data);
 void gnc_split_reg2_style_auto_ledger_cb (GtkWidget *w, gpointer data);
 void gnc_split_reg2_style_journal_cb (GtkWidget *w, gpointer data);
 void gnc_split_reg2_double_line_cb (GtkWidget *w, gpointer data);
 
-
 void gnc_split_reg2_destroy_cb (GtkWidget *widget, gpointer data);
 
 static void gnc_split_reg2_class_init (GNCSplitReg2Class *class);
@@ -127,7 +93,7 @@
 
 
 GType
-gnc_split_reg2_get_type( void )
+gnc_split_reg2_get_type (void)
 {
     static GType gnc_split_reg2_type = 0;
 
@@ -155,74 +121,37 @@
 }
 
 /* SIGNALS */
-enum gnc_split_reg2_signal_enum
+enum
 {
-    SCHEDULE_ENT_SIGNAL,
-
-
-    HELP_CHANGED_SIGNAL,
-    INCLUDE_DATE_SIGNAL,
+    HELP_CHANGED,
     LAST_SIGNAL
 };
 
 static guint gnc_split_reg2_signals[LAST_SIGNAL] = { 0 };
 
 static void
-gnc_split_reg2_class_init( GNCSplitReg2Class *class )
+gnc_split_reg2_class_init (GNCSplitReg2Class *class)
 {
-    int i;
     GtkObjectClass *object_class;
-    static struct similar_signal_info
-    {
-        enum gnc_split_reg2_signal_enum s;
-        const char *signal_name;
-        guint defaultOffset;
-    } signals[] =
-    {
-        { SCHEDULE_ENT_SIGNAL, "schedule_ent", G_STRUCT_OFFSET( GNCSplitReg2Class, schedule_ent_cb ) },
 
-
-        { HELP_CHANGED_SIGNAL, "help-changed", G_STRUCT_OFFSET( GNCSplitReg2Class, help_changed_cb ) },
-        { INCLUDE_DATE_SIGNAL, "include-date", G_STRUCT_OFFSET( GNCSplitReg2Class, include_date_cb ) },
-        { LAST_SIGNAL, NULL, 0 }
-    };
-
     object_class = (GtkObjectClass*) class;
 
-    for ( i = 0; signals[i].s != INCLUDE_DATE_SIGNAL; i++ )
-    {
-        gnc_split_reg2_signals[ signals[i].s ] =
-            g_signal_new( signals[i].signal_name,
-                          G_TYPE_FROM_CLASS(object_class),
-                          G_SIGNAL_RUN_LAST,
-                          signals[i].defaultOffset,
-                          NULL, NULL,
-                          g_cclosure_marshal_VOID__VOID,
-                          G_TYPE_NONE, 0 );
-    }
-    /* Setup the non-default-marshalled signals; 'i' is still valid, here. */
-    /* "include-date" */
-    gnc_split_reg2_signals[ INCLUDE_DATE_SIGNAL ] =
-        g_signal_new( "include-date",
-                      G_TYPE_FROM_CLASS(object_class),
-                      G_SIGNAL_RUN_LAST,
-                      signals[i++].defaultOffset,
-                      NULL, NULL,
-                      g_cclosure_marshal_VOID__INT, /* time64 == int */
-                      G_TYPE_NONE, 1, G_TYPE_INT );
+    gnc_split_reg2_signals[HELP_CHANGED] =
+        g_signal_new("help-changed",
+                     G_TYPE_FROM_CLASS (object_class),
+                     G_SIGNAL_RUN_LAST,
+                     G_STRUCT_OFFSET (GNCSplitReg2Class, help_changed),
+                     NULL, NULL,
+                     g_cclosure_marshal_VOID__VOID,
+                     G_TYPE_NONE, 0);
 
-    g_assert( i == LAST_SIGNAL );
-
     /* Setup the default handlers. */
-    class->schedule_ent_cb = gsr2_default_schedule_handler;
+    class->help_changed = NULL;
 
-
-    class->help_changed_cb = NULL;
-    class->include_date_cb = NULL;
 }
 
 GtkWidget*
-gnc_split_reg2_new( GNCLedgerDisplay2 *ld,
+gnc_split_reg2_new (GNCLedgerDisplay2 *ld,
                    GtkWindow *parent,
                    gint numberOfLines,
                    gboolean read_only )
@@ -232,38 +161,36 @@
     ENTER("ld=%p, parent=%p, numberOfLines=%d, read_only=%s",
           ld, parent, numberOfLines, read_only ? "TRUE" : "FALSE");
 
-    gsrToRet = g_object_new( gnc_split_reg2_get_type(), NULL );
+    gsrToRet = g_object_new (gnc_split_reg2_get_type(), NULL);
 
-    gsrToRet->numRows        = numberOfLines;
-    gsrToRet->read_only      = read_only;
+    gsrToRet->numRows = numberOfLines;
+    gsrToRet->read_only = read_only;
 
     gsrToRet->ledger = ld;
-    gsrToRet->window = GTK_WIDGET(parent);
+    gsrToRet->window = GTK_WIDGET (parent);
 
-    gnc_split_reg2_init2( gsrToRet );
+    gnc_split_reg2_init2 (gsrToRet);
 
     LEAVE("%p", gsrToRet);
-    return GTK_WIDGET( gsrToRet );
+    return GTK_WIDGET (gsrToRet);
 }
 
 static void
-gnc_split_reg2_init( GNCSplitReg2 *gsr )
+gnc_split_reg2_init (GNCSplitReg2 *gsr)
 {
-    gsr->width = -1;
-    gsr->height = -1;
     gsr->numRows = 10;
     gsr->read_only = FALSE;
 
-    g_signal_connect( gsr, "destroy",
+    g_signal_connect (gsr, "destroy",
                       G_CALLBACK (gnc_split_reg2_destroy_cb), gsr );
 }
 
 static void
-gnc_split_reg2_init2( GNCSplitReg2 *gsr )
+gnc_split_reg2_init2 (GNCSplitReg2 *gsr)
 {
-    if ( !gsr ) return;
+    if (!gsr) return;
 
-    gnc_split_reg2_determine_read_only( gsr );
+    gnc_split_reg2_determine_read_only (gsr);
 
     gsr2_setup_status_widgets( gsr );
     /* ordering is important here... setup_status before create_table */
@@ -275,16 +202,14 @@
 
 static
 void
-gsr2_setup_table( GNCSplitReg2 *gsr )
+gsr2_setup_table (GNCSplitReg2 *gsr)
 {
     GncTreeModelSplitReg *model;
 
     ENTER("gsr=%p", gsr);
 
-    model = gnc_ledger_display2_get_split_model_register( gsr->ledger );
+    model = gnc_ledger_display2_get_split_model_register (gsr->ledger);
 
-    /* events should be sufficient to redraw this */
-    /* gnc_ledger_display2_refresh (gsr->ledger); */
     gnc_split_reg2_refresh_toolbar (gsr);
 
     LEAVE(" ");
@@ -292,7 +217,7 @@
 
 static
 void
-gsr2_create_table( GNCSplitReg2 *gsr )
+gsr2_create_table (GNCSplitReg2 *gsr)
 {
     GtkWidget *register_widget;
     GncTreeViewSplitReg *view;
@@ -324,10 +249,14 @@
     model = gnc_ledger_display2_get_split_model_register (gsr->ledger );
     view = gnc_tree_view_split_reg_new_with_model (model);
 
-    g_object_unref(G_OBJECT(model));
+    g_object_unref (G_OBJECT (model));
 
     gnc_tree_model_split_reg_set_display (model, ((ledger_type == LD2_SUBACCOUNT)?TRUE:FALSE), ((ledger_type == LD2_GL)?TRUE:FALSE));
 
+    // We need to give the General Ledger a Key other than all zeros which the search register gets.
+    if (model->type == GENERAL_LEDGER2)
+        gconf_key = g_strconcat (GCONF_SECTION,"/", "00000000000000000000000000000001", NULL);
+
     scrolled_window = gtk_scrolled_window_new (NULL, NULL);
     gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scrolled_window),
                                    GTK_POLICY_AUTOMATIC,
@@ -360,15 +289,6 @@
     /* This column gets all the free space */
     gnc_tree_view_expand_columns (GNC_TREE_VIEW (view), "descnotes", NULL);
 
-    /*FIXME is this OK ? - Set the Reconcile column width */
-//    col = gnc_tree_view_find_column_by_name (GNC_TREE_VIEW (view), "recn");
-//    if (col != NULL)
-//        g_object_set (G_OBJECT(col),
-//                     "resizable", FALSE,
-//                     "sizing", GTK_TREE_VIEW_COLUMN_FIXED,
-//                     "fixed-width", 15,
-//                      NULL);
-
     /* This sets the status color column, 4 is the minimum */
     col = gnc_tree_view_find_column_by_name (GNC_TREE_VIEW (view), "status");
     if (col != NULL)
@@ -421,10 +341,51 @@
 }
 
 /**
+ * Jump to split.
+ **/
+void
+gnc_split_reg2_jump_to_split (GNCSplitReg2 *gsr, Split *split)
+{
+    GncTreeViewSplitReg *view;
+
+    if (gsr == NULL)
+        return;
+
+    if (split == NULL)
+        return;
+
+    view = gnc_ledger_display2_get_split_view_register (gsr->ledger);
+
+    gnc_tree_control_split_reg_jump_to_split (view, split, FALSE);
+}
+
+
+/**
+ * Move the cursor to the split in the non-blank amount column.
+ **/
+void
+gnc_split_reg2_jump_to_split_amount (GNCSplitReg2 *gsr, Split *split)
+{
+    GncTreeViewSplitReg *view;
+
+    if (gsr == NULL)
+        return;
+
+    if (split == NULL)
+        return;
+
+    view = gnc_ledger_display2_get_split_view_register (gsr->ledger);
+
+    gnc_tree_control_split_reg_jump_to_split (view, split, TRUE);
+
+//FIXME this needs more
+}
+
+/**
  * Raise an existing register window to the front.
  **/
 void
-gnc_split_reg2_raise( GNCSplitReg2 *gsr )
+gnc_split_reg2_raise (GNCSplitReg2 *gsr)
 {
     if (gsr == NULL)
         return;
@@ -432,7 +393,7 @@
     if (gsr->window == NULL)
         return;
 
-    gtk_window_present( GTK_WINDOW(gsr->window) );
+    gtk_window_present (GTK_WINDOW (gsr->window));
 }
 
 
@@ -665,11 +626,10 @@
             gnc_price_unref (price);
         }
     }
-
 }
 
 static void
-gnc_split_reg2_refresh_toolbar( GNCSplitReg2 *gsr )
+gnc_split_reg2_refresh_toolbar (GNCSplitReg2 *gsr)
 {
     GtkToolbarStyle tbstyle;
 
@@ -677,23 +637,22 @@
         return;
 
     tbstyle = gnc_get_toolbar_style ();
-    gtk_toolbar_set_style( GTK_TOOLBAR(gsr->toolbar), tbstyle );
+    gtk_toolbar_set_style (GTK_TOOLBAR (gsr->toolbar), tbstyle );
 }
 
 static void
 gnc_split_reg2_ld_destroy (GNCLedgerDisplay2 *ledger)
 {
-    GNCSplitReg2 *gsr = gnc_ledger_display2_get_user_data( ledger );
+    GNCSplitReg2 *gsr = gnc_ledger_display2_get_user_data (ledger);
     
     gchar *gconf_key;
     const GncGUID * guid;
     Account * account;
     
-    account = gnc_ledger_display2_leader(ledger);
-    guid = xaccAccountGetGUID(account);
+    account = gnc_ledger_display2_leader (ledger);
+    guid = xaccAccountGetGUID (account);
     gconf_key = (gchar*)guid_to_string (guid);
     
-    
     if (gsr)
     {
         GncTreeModelSplitReg *model;
@@ -715,88 +674,16 @@
 
 /* ########################### Handlers ############################### */
 
-
-/**
- * Schedules the current transaction for recurring-entry.
- * If the selected transaction was created from a scheduled transaction,
- * opens the editor for that Scheduled Transaction.
- **/
 void
-gsr2_default_schedule_handler( GNCSplitReg2 *gsr, gpointer data )
+gnc_split_reg2_balancing_entry (GNCSplitReg2 *gsr, Account *account,
+                              time64 statement_date, gnc_numeric balancing_amount) // this works
 {
-/*FIXME*/
-#ifdef skip
-    SplitRegister *reg = gnc_ledger_display2_get_split_register( gsr->ledger );
-    Transaction *pending_trans = gnc_split_register_get_current_trans (reg);
-
-    /* If the transaction has a sched-xact KVP frame, then go to the editor
-     * for the existing SX; otherwise, do the sx-from-trans dialog. */
-    {
-        kvp_frame *txn_frame;
-        kvp_value *kvp_val;
-        /* set a kvp-frame element in the transaction indicating and
-         * pointing-to the SX this was created from. */
-        txn_frame = xaccTransGetSlots( pending_trans );
-        if ( txn_frame != NULL )
-        {
-            kvp_val = kvp_frame_get_slot( txn_frame, "from-sched-xaction" );
-            if ( kvp_val )
-            {
-                GncGUID *fromSXId = kvp_value_get_guid( kvp_val );
-                SchedXaction *theSX = NULL;
-                GList *sxElts;
-
-                /* Get the correct SX */
-                for ( sxElts = gnc_book_get_schedxactions(gnc_get_current_book())->sx_list;
-                        (!theSX) && sxElts;
-                        sxElts = sxElts->next )
-                {
-                    SchedXaction *sx = (SchedXaction*)sxElts->data;
-                    theSX =
-                        ( ( guid_equal( xaccSchedXactionGetGUID( sx ), fromSXId ) )
-                          ? sx : NULL );
-                }
-
-                if ( theSX )
-                {
-                    gnc_ui_scheduled_xaction_editor_dialog_create(theSX, FALSE);
-                    return;
-                }
-            }
-        }
-    }
-
-    gnc_sx_create_from_trans(pending_trans);
-#endif
-}
-
-void
-gnc_split_reg2_recur_cb(GtkWidget *w, gpointer data)
-{
-/*FIXME    GNCSplitReg2 *gsr = data;
-    gsr2_emit_simple_signal( gsr, "schedule_ent" );*/
-}
-
-/**
- * Records into the books the currently-selected transaction.
- **/
-void
-gnc_split_reg2_record_trans_cb (GtkWidget *w, gpointer data)
-{
-/*FIXME    GNCSplitReg2 *gsr = data;
-    gsr2_emit_simple_signal( gsr, "enter_ent" );*/
-}
-
-
-void
-gnc_split_reg2_balancing_entry(GNCSplitReg2 *gsr, Account *account,
-                              time64 statement_date, gnc_numeric balancing_amount)
-{
-/*FIXME*/
-#ifdef skip
+    GncTreeViewSplitReg *view;
     Transaction *transaction;
     Split *split;
 
+    view = gnc_ledger_display2_get_split_view_register (gsr->ledger);
+
     // create transaction
     transaction = create_balancing_transaction (gnc_get_current_book(),
                   account, statement_date, balancing_amount);
@@ -807,14 +694,13 @@
     {
         // default behaviour: jump to blank split
         g_warning("create_balancing_transaction failed");
-        gnc_split_reg2_jump_to_blank (gsr);
+        gnc_tree_control_split_reg_jump_to_blank (view);
     }
     else
     {
         // goto balancing transaction
-        gnc_split_reg2_jump_to_split (gsr, split );
+        gnc_tree_control_split_reg_jump_to_split (view, split, FALSE);
     }
-#endif
 }
 
 static Transaction*
@@ -860,10 +746,8 @@
     return trans;
 }
 
-
 /* ############################## End Handlers ############################ */
 
-
 void
 gnc_split_reg2_change_style (GNCSplitReg2 *gsr, SplitRegisterStyle2 style)
 {
@@ -924,74 +808,6 @@
     gnc_ledger_display2_refresh (gsr->ledger);
 }
 
-static void
-gnc_split_reg2_record (GNCSplitReg2 *gsr)
-{
-/*FIXME*/
-#ifdef skip
-    SplitRegister *reg;
-    Transaction *trans;
-
-    ENTER("gsr=%p", gsr);
-
-    reg = gnc_ledger_display2_get_split_register (gsr->ledger);
-    trans = gnc_split_register_get_current_trans (reg);
-
-    if (!gnc_split_register_save (reg, TRUE))
-    {
-        LEAVE("no save");
-        return;
-    }
-
-    gsr2_emit_include_date_signal( gsr, xaccTransGetDate(trans) );
-
-    /* Explicit redraw shouldn't be needed,
-     * since gui_refresh events should handle this. */
-    /* gnc_split_register_redraw (reg); */
-    LEAVE(" ");
-#endif
-}
-
-static gboolean
-gnc_split_reg2_match_trans_row( VirtualLocation virt_loc,
-                               gpointer user_data )
-{
-/*FIXME*/
-#ifdef skip
-    GNCSplitReg2 *gsr = user_data;
-    CursorClass cursor_class;
-    SplitRegister *sr;
-
-    sr = gnc_ledger_display2_get_split_register (gsr->ledger);
-    cursor_class = gnc_split_register_get_cursor_class (sr, virt_loc.vcell_loc);
-
-    return (cursor_class == CURSOR_CLASS_TRANS);
-#endif
-return FALSE;
-}
-
-static void
-gnc_split_reg2_goto_next_trans_row (GNCSplitReg2 *gsr)
-{
-/*FIXME*/
-#ifdef skip
-    ENTER("gsr=%p", gsr);
-    gnucash_register_goto_next_matching_row( gsr->reg,
-            gnc_split_reg2_match_trans_row,
-            gsr );
-    LEAVE(" ");
-#endif
-}
-
-
-#ifdef skip
-void
-gnc_split_reg2_record_cb (GnucashRegister *reg, gpointer data)
-{
-/*FIXME    gsr2_emit_simple_signal( (GNCSplitReg2*)data, "enter_ent" );*/
-}
-#endif
-
 static
 GtkWidget*
 add_summary_label (GtkWidget *summarybar, const char *label_str)
@@ -1206,13 +1022,6 @@
 
 static
 void
-gsr2_emit_include_date_signal( GNCSplitReg2 *gsr, time64 date )
-{
-    g_signal_emit_by_name( gsr, "include-date", date, NULL );
-}
-
-static
-void
 gsr2_emit_simple_signal (GNCSplitReg2 *gsr, const char *sigName) //this works
 {
     g_signal_emit_by_name( gsr, sigName, NULL );
@@ -1244,5 +1053,5 @@
 void
 gnc_split_reg2_set_moved_cb (GNCSplitReg2 *gsr, GFunc cb, gpointer cb_data ) //this works
 {
-    gnc_tree_view_split_reg_moved_cb (gnc_ledger_display2_get_split_view_register(gsr->ledger), cb, cb_data);
+    gnc_tree_view_split_reg_moved_cb (gnc_ledger_display2_get_split_view_register (gsr->ledger), cb, cb_data);
 }

Modified: gnucash/trunk/src/gnome/gnc-split-reg2.h
===================================================================
--- gnucash/trunk/src/gnome/gnc-split-reg2.h	2013-04-07 22:14:20 UTC (rev 22884)
+++ gnucash/trunk/src/gnome/gnc-split-reg2.h	2013-04-07 22:14:31 UTC (rev 22885)
@@ -1,5 +1,5 @@
 /********************************************************************\
- * gnc-split-reg2.h -- A widget for the common register look-n-feel. *
+ * gnc-split-reg2.h -- A widget for the common register look-n-feel.*
  * Copyright (C) 1997 Robin D. Clark                                *
  * Copyright (C) 1997-1998 Linas Vepstas <linas at linas.org>          *
  * Copyright (C) 1998 Rob Browning <rlb at cs.utexas.edu>              *
@@ -31,7 +31,6 @@
 #define GNC_SPLIT_REG2_H
 
 #include "gnc-ledger-display2.h"
-#include "gnucash-sheet.h"
 #include "gnc-split-reg.h"
 #include "gnc-tree-view-split-reg.h"
 
@@ -49,25 +48,10 @@
 
     /* The containing window. */
     GtkWidget *window;
-    gint width;
-    gint height;
 
     GtkWidget *toolbar;
     GtkWidget *summarybar;
 
-    GtkWidget *popup_menu;
-
-    GtkWidget *edit_menu;
-    GtkWidget *view_menu;
-    GtkWidget *style_submenu;
-    GtkWidget *action_menu;
-
-    GtkWidget *double_line_check;
-
-    GtkWidget *split_button;
-    GtkWidget *split_menu_check;
-    GtkWidget *split_popup_check;
-
     /* Summary Bar Labels */
     GtkWidget *balance_label;
     GtkWidget *cleared_label;
@@ -80,9 +64,6 @@
     /** The current ledger display. **/
     GNCLedgerDisplay2 *ledger;
 
-    /** The actual sheet widget. **/
-    GnucashRegister *reg;
-
     gint numRows;
 
     gboolean read_only;
@@ -93,26 +74,12 @@
     GtkVBoxClass parent_class;
 
     /* Signal defaults */
-
-    void (*schedule_ent_cb) ( GNCSplitReg2 *w, gpointer user_data );
-
-    void (*help_changed_cb) ( GNCSplitReg2 *w, gpointer user_data );
-    void (*include_date_cb) ( GNCSplitReg2 *w, time64 date, gpointer user_data );
+    void (*help_changed) ( GNCSplitReg2 *w, gpointer user_data );
 };
 
-#ifdef skip // Coming from original gnc-split-reg.h
-typedef enum
-{
-    SCHEDULE,
-    SPLIT,
-    STYLE_SUBMENU,
-} GNC_SPLIT_REG2_ITEM;
-#endif
-
 /*FIXME Note sure about this == Coming from original gnc-split-reg.h */
 typedef GNC_SPLIT_REG_ITEM GNC_SPLIT_REG2_ITEM;
 
-
 /**
  * GTK-related; gets an identifier for the class of GNCSplitRegs.
  **/
@@ -150,9 +117,23 @@
  **/
 GtkWidget *gnc_split_reg2_get_summarybar (GNCSplitReg2 *gsr );
 
-void gnc_split_reg2_raise (GNCSplitReg2 *gsr );
+/**
+ * Jump to split.
+ **/
+void gnc_split_reg2_jump_to_split (GNCSplitReg2 *gsr, Split *split);
 
 /**
+ * Move the cursor to the split in the non-blank amount column.
+ **/
+void gnc_split_reg2_jump_to_split_amount (GNCSplitReg2 *gsr, Split *split);
+
+
+/**
+ * Raise an existing register window to the front.
+ **/
+void gnc_split_reg2_raise (GNCSplitReg2 *gsr);
+
+/**
  * Callers can use this to determine if they need to reflect some "read-only"
  * status in the window which contains the GNCSplitReg.
  * @return TRUE if the register is read-only, FALSE if not.
@@ -169,7 +150,6 @@
 void gnc_split_reg2_balancing_entry (GNCSplitReg2 *gsr, Account *account,
                                     time64 statement_date, gnc_numeric balancing_amount);
 
-void gsr2_default_schedule_handler (GNCSplitReg2 *gsr, gpointer data );
 
 void gnc_split_reg2_set_moved_cb (GNCSplitReg2 *gsr, GFunc cb, gpointer cb_data );
 

Added: gnucash/trunk/src/gnome/window-reconcile2.c
===================================================================
--- gnucash/trunk/src/gnome/window-reconcile2.c	                        (rev 0)
+++ gnucash/trunk/src/gnome/window-reconcile2.c	2013-04-07 22:14:31 UTC (rev 22885)
@@ -0,0 +1,2292 @@
+/********************************************************************\
+ * window-reconcile2.c -- the reconcile window                      *
+ * Copyright (C) 1997 Robin D. Clark                                *
+ * Copyright (C) 1998-2000 Linas Vepstas                            *
+ * Copyright (C) 2002 Christian Stimming                            *
+ * Copyright (C) 2006 David Hampton                                 *
+ *                                                                  *
+ * 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       *
+ * 51 Franklin Street, Fifth Floor    Fax:    +1-617-542-2652       *
+ * Boston, MA  02110-1301,  USA       gnu at gnu.org                   *
+ *                                                                  *
+ *   Author: Rob Clark                                              *
+ * Internet: rclark at cs.hmc.edu                                      *
+ *  Address: 609 8th Street                                         *
+ *           Huntington Beach, CA 92648-4632                        *
+\********************************************************************/
+
+#include "config.h"
+
+#include <gtk/gtk.h>
+#include <glib/gi18n.h>
+#ifdef __G_IR_SCANNER__
+#undef __G_IR_SCANNER__
+#endif
+#include <gdk/gdkkeysyms.h>
+
+#include "Scrub.h"
+#include "Scrub3.h"
+#include "dialog-account.h"
+#include "dialog-transfer.h"
+#include "dialog-utils.h"
+#include "gnc-amount-edit.h"
+#include "gnc-component-manager.h"
+#include "gnc-date-edit.h"
+#include "gnc-event.h"
+#include "gnc-filepath-utils.h"
+#include "gnc-gconf-utils.h"
+#include <gnc-gdate-utils.h>
+#include "gnc-gnome-utils.h"
+#include "gnc-main-window.h"
+#include "gnc-plugin-page-register2.h"
+#include "gnc-ui.h"
+#include "gnc-ui-balances.h"
+#include "guile-util.h"
+#include "reconcile-view.h"
+#include "window-reconcile2.h"
+
+#define GCONF_SECTION "dialogs/window-reconcile"
+#define WINDOW_RECONCILE_CM_CLASS "window-reconcile"
+
+
+/** STRUCTS *********************************************************/
+struct _RecnWindow2
+{
+    GncGUID account;             /* The account that we are reconciling  */
+    gnc_numeric new_ending;      /* The new ending balance               */
+    time64 statement_date;       /* The statement date                   */
+
+    gint component_id;           /* id of component                      */
+
+    GtkWidget *window;           /* The reconcile window                 */
+
+    GtkUIManager *ui_merge;
+    GtkActionGroup *action_group;
+    GtkWidget *toolbar;          /* Toolbar widget                       */
+    gint toolbar_change_cb_id;   /* id for toolbar preference change cb  */
+    gint toolbar_change_cb_id2;  /* id for toolbar preference change cb  */
+
+    GtkWidget *starting;         /* The starting balance                 */
+    GtkWidget *ending;           /* The ending balance                   */
+    GtkWidget *recn_date;        /* The statement date                   */
+    GtkWidget *reconciled;       /* The reconciled balance               */
+    GtkWidget *difference;       /* Text field, amount left to reconcile */
+
+    GtkWidget *total_debit;      /* Text field, total debit reconciled   */
+    GtkWidget *total_credit;     /* Text field, total credit reconciled  */
+
+    GtkWidget *debit;            /* Debit matrix show unreconciled debit */
+    GtkWidget *credit;           /* Credit matrix, shows credits...      */
+
+    GtkWidget *debit_frame;      /* Frame around debit matrix            */
+    GtkWidget *credit_frame;     /* Frame around credit matrix           */
+
+    gboolean   delete_refresh;   /* do a refresh upon a window deletion  */
+};
+
+
+/* This structure doesn't contain everything involved in the
+ * startRecnWindow, just pointers that have to be passed in to
+ * callbacks that need more than one piece of data to operate on.
+ * This is also used by the interest transfer dialog code.
+ */
+typedef struct _startRecnWindowData
+{
+    Account       *account;         /* the account being reconciled            */
+    GNCAccountType account_type;    /* the type of the account                 */
+
+    GtkWidget     *startRecnWindow; /* the startRecnWindow dialog              */
+    GtkWidget     *xfer_button;     /* the dialog's interest transfer button   */
+    GtkWidget     *date_value;      /* the dialog's ending date field          */
+    GNCAmountEdit *end_value;       /* the dialog's ending balance amount edit */
+    gnc_numeric    original_value;  /* the dialog's original ending balance    */
+    gboolean       user_set_value;  /* the user changed the ending value       */
+
+    XferDialog    *xferData;        /* the interest xfer dialog (if it exists) */
+    gboolean       include_children;
+
+    time64         date;            /* the interest xfer reconcile date        */
+} startRecnWindowData;
+
+
+/* Note: make sure to update the help text for this in prefs.scm if these
+ * change!  These macros define the account types for which an auto interest
+ * xfer dialog could pop up, if the user's preferences allow it.
+ */
+#define account_type_has_auto_interest_charge(type)  (((type) == ACCT_TYPE_CREDIT) || \
+                                                      ((type) == ACCT_TYPE_LIABILITY) ||\
+						      ((type) == ACCT_TYPE_PAYABLE))
+
+#define account_type_has_auto_interest_payment(type) (((type) == ACCT_TYPE_BANK)  || \
+                                                      ((type) == ACCT_TYPE_ASSET) || \
+                                                      ((type) == ACCT_TYPE_MUTUAL) || \
+						      ((type) == ACCT_TYPE_RECEIVABLE))
+
+#define account_type_has_auto_interest_xfer(type) \
+  (  account_type_has_auto_interest_charge(type) || \
+    account_type_has_auto_interest_payment(type) )
+
+/** PROTOTYPES ******************************************************/
+static gnc_numeric recnRecalculateBalance (RecnWindow2 *recnData);
+
+static void   recn_destroy_cb (GtkWidget *w, gpointer data);
+static void   recn_cancel (RecnWindow2 *recnData);
+static gboolean recn_delete_cb (GtkWidget *widget, GdkEvent *event, gpointer data);
+static gboolean recn_key_press_cb (GtkWidget *widget, GdkEventKey *event, gpointer data);
+static void   recnFinishCB (GtkAction *action, RecnWindow2 *recnData);
+static void   recnPostponeCB (GtkAction *action, gpointer data);
+static void   recnCancelCB (GtkAction *action, gpointer data);
+
+void gnc_start_recn2_children_changed (GtkWidget *widget, startRecnWindowData *data);
+void gnc_start_recn2_interest_clicked_cb (GtkButton *button, startRecnWindowData *data);
+
+static void   gnc_reconcile_window_set_sensitivity (RecnWindow2 *recnData);
+static char * gnc_recn_make_window_name (Account *account);
+static void   gnc_recn_set_window_name (RecnWindow2 *recnData);
+static gboolean find_by_account (gpointer find_data, gpointer user_data);
+
+
+/** GLOBALS ************************************************************/
+/* This static indicates the debugging module that this .o belongs to. */
+G_GNUC_UNUSED static QofLogModule log_module = GNC_MOD_GUI;
+
+static time64 gnc_reconcile_last_statement_date = 0;
+
+
+/** IMPLEMENTATIONS *************************************************/
+
+/** An array of all of the actions provided by the main window code.
+ *  This includes some placeholder actions for the menus that are
+ *  visible in the menu bar but have no action associated with
+ *  them. */
+static GtkActionEntry recnWindow2_actions [];
+/** The number of actions provided by the main window. */
+static guint recnWindow2_n_actions;
+
+/********************************************************************\
+ * recnRefresh                                                      *
+ *   refreshes the transactions in the reconcile window             *
+ *                                                                  *
+ * Args:   account - the account of the reconcile window to refresh *
+ * Return: none                                                     *
+\********************************************************************/
+static void
+recnRefresh (RecnWindow2 *recnData)
+{
+    if (recnData == NULL)
+        return;
+
+    gnc_reconcile_view_refresh (GNC_RECONCILE_VIEW (recnData->debit));
+    gnc_reconcile_view_refresh (GNC_RECONCILE_VIEW (recnData->credit));
+
+    gnc_reconcile_window_set_sensitivity (recnData);
+
+    gnc_recn_set_window_name (recnData);
+
+    recnRecalculateBalance (recnData);
+
+    gtk_widget_queue_resize (recnData->window);
+}
+
+
+static Account *
+recn_get_account (RecnWindow2 *recnData)
+{
+    if (!recnData)
+        return NULL;
+
+    return xaccAccountLookup (&recnData->account, gnc_get_current_book ());
+}
+
+
+/********************************************************************\
+ * recnRecalculateBalance                                           *
+ *   refreshes the balances in the reconcile window                 *
+ *                                                                  *
+ * Args:   recnData -- the reconcile window to refresh              *
+ * Return: the difference between the nominal ending balance        *
+ *         and the 'effective' ending balance.                      *
+\********************************************************************/
+static gnc_numeric
+recnRecalculateBalance (RecnWindow2 *recnData)
+{
+    Account *account;
+    const char *amount;
+    gnc_numeric debit;
+    gnc_numeric credit;
+    gnc_numeric starting;
+    gnc_numeric ending;
+    gnc_numeric reconciled;
+    gnc_numeric diff;
+    GNCPrintAmountInfo print_info;
+    gboolean reverse_balance, include_children;
+    GtkAction *action;
+
+    account = recn_get_account (recnData);
+    if (!account)
+        return gnc_numeric_zero ();
+
+    reverse_balance = gnc_reverse_balance (account);
+
+    /* update the starting balance */
+    include_children = xaccAccountGetReconcileChildrenStatus (account);
+    starting = gnc_ui_account_get_reconciled_balance (account, include_children);
+    print_info = gnc_account_print_info (account, TRUE);
+
+    /*
+     * Do not reverse the balance here. It messes up the math in the
+     * reconciliation window. Also, the balance should show up as a
+     * positive number in the reconciliation window to match the positive
+     * number that shows in the register window.
+     */
+
+    amount = xaccPrintAmount (starting, print_info);
+    gnc_set_label_color (recnData->starting, starting);
+    gtk_label_set_text (GTK_LABEL (recnData->starting), amount);
+    if (reverse_balance)
+        starting = gnc_numeric_neg (starting);
+
+    /* update the statement date */
+    amount = qof_print_date (recnData->statement_date);
+    gtk_label_set_text (GTK_LABEL (recnData->recn_date), amount);
+
+    /* update the ending balance */
+    ending = recnData->new_ending;
+    if (reverse_balance)
+        ending = gnc_numeric_neg (ending);
+    amount = xaccPrintAmount (ending, print_info);
+    gnc_set_label_color (recnData->ending, ending);
+    gtk_label_set_text (GTK_LABEL (recnData->ending), amount);
+    if (reverse_balance)
+        ending = gnc_numeric_neg (ending);
+
+    debit = gnc_reconcile_view_reconciled_balance
+            (GNC_RECONCILE_VIEW (recnData->debit));
+
+    credit = gnc_reconcile_view_reconciled_balance
+             (GNC_RECONCILE_VIEW (recnData->credit));
+
+    /* Update the total debit and credit fields */
+    amount = xaccPrintAmount (debit, print_info);
+    gtk_label_set_text (GTK_LABEL (recnData->total_debit), amount);
+
+    amount = xaccPrintAmount (credit, print_info);
+
+    gtk_label_set_text (GTK_LABEL (recnData->total_credit), amount);
+
+    /* update the reconciled balance */
+    reconciled = gnc_numeric_add_fixed (starting,
+                                        gnc_numeric_sub_fixed (debit, credit));
+    if (reverse_balance)
+        reconciled = gnc_numeric_neg (reconciled);
+    amount = xaccPrintAmount (reconciled, print_info);
+    gnc_set_label_color (recnData->reconciled, reconciled);
+    gtk_label_set_text (GTK_LABEL (recnData->reconciled), amount);
+    if (reverse_balance)
+        reconciled = gnc_numeric_neg (reconciled);
+
+    /* update the difference */
+    diff = gnc_numeric_sub_fixed (ending, reconciled);
+    if (reverse_balance)
+        diff = gnc_numeric_neg (diff);
+    amount = xaccPrintAmount (diff, print_info);
+    gnc_set_label_color (recnData->difference, diff);
+    gtk_label_set_text (GTK_LABEL (recnData->difference), amount);
+    if (reverse_balance)
+        diff = gnc_numeric_neg (diff);
+
+    action = gtk_action_group_get_action (recnData->action_group,
+                                          "RecnFinishAction");
+    gtk_action_set_sensitive (action, gnc_numeric_zero_p (diff));
+
+    action = gtk_action_group_get_action (recnData->action_group,
+                                          "TransBalanceAction");
+    gtk_action_set_sensitive (action, !gnc_numeric_zero_p (diff));
+
+    return diff;
+}
+
+
+static gboolean
+gnc_start_recn2_update_cb (GtkWidget *widget, GdkEventFocus *event,
+                         startRecnWindowData *data)
+{
+    gnc_numeric value;
+
+    gnc_amount_edit_evaluate (GNC_AMOUNT_EDIT (data->end_value));
+
+    value = gnc_amount_edit_get_amount (GNC_AMOUNT_EDIT (data->end_value));
+    data->user_set_value = !gnc_numeric_equal (value, data->original_value);
+    return FALSE;
+}
+
+
+/* If the user changed the date edit widget, update the
+ * ending balance to reflect the ending balance of the account
+ * on the date that the date edit was changed to.
+ */
+static void
+gnc_start_recn2_date_changed (GtkWidget *widget, startRecnWindowData *data)
+{
+    GNCDateEdit *gde = GNC_DATE_EDIT (widget);
+    gnc_numeric new_balance;
+    time64 new_date;
+
+    if (data->user_set_value)
+        return;
+    new_date = gnc_date_edit_get_date_end (gde);
+    /* get the balance for the account as of the new date */
+    new_balance = gnc_ui_account_get_balance_as_of_date (data->account, new_date,
+                  data->include_children);
+    /* update the amount edit with the amount */
+    gnc_amount_edit_set_amount (GNC_AMOUNT_EDIT (data->end_value),
+                                new_balance);
+}
+
+
+void
+gnc_start_recn2_children_changed (GtkWidget *widget, startRecnWindowData *data)
+{
+    data->include_children =
+        gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (widget));
+
+    /* Force an update of the ending balance */
+    gnc_start_recn2_date_changed (data->date_value, data);
+}
+
+
+/* For a given account, determine if an auto interest xfer dialog should be
+ * shown, based on both the per-account flag as well as the global reconcile
+ * option.  The global option is the default that is used if there is no
+ * per-account option.
+ */
+static gboolean
+gnc_recn_interest_xfer_get_auto_interest_xfer_allowed (Account *account)
+{
+    gboolean auto_xfer;
+
+    auto_xfer = gnc_gconf_get_bool (GCONF_RECONCILE_SECTION,
+                                   "auto_interest_transfer", NULL);
+    return xaccAccountGetAutoInterestXfer (account, auto_xfer);
+}
+
+
+/********************************************************************\
+ * recnInterestXferWindow                                           *
+ *   opens up a window to prompt the user to enter an interest      *
+ *   charge or payment for an account prior to reconciling it.      *
+ *   Only to be called for some types of accounts, as defined       *
+ *   in the macros at the top of this file.                         *
+ *                                                                  *
+ * NOTE: This function does not return until the user presses "Ok"  *
+ *       or "Cancel", which means that the transaction must be      *
+ *       resolved before the startRecnWindow will work.             *
+ *                                                                  *
+ * Args:   data           - jumbo structure containing info         *
+ *                          about the start of the reconcile        *
+ *                          process needed by this function.        *
+ * Returns:  none.                                                  *
+\********************************************************************/
+
+/* helper function */
+static char *
+gnc_recn_make_interest_window_name (Account *account, char *text)
+{
+    char *fullname;
+    char *title;
+
+    fullname = gnc_account_get_full_name (account);
+    title = g_strconcat (fullname, " - ", text && *text ? _(text) : "", NULL);
+
+    g_free (fullname);
+
+    return title;
+}
+
+
+/* user clicked button in the interest xfer dialog entitled
+ * "No Auto Interest Payments for this Account".
+ */
+static void
+gnc_recn_interest_xfer_no_auto_clicked_cb (GtkButton *button,
+        startRecnWindowData *data)
+{
+    /* Indicate that the user doesn't want
+     * an auto interest xfer for this account.
+     */
+    xaccAccountSetAutoInterestXfer (data->account, FALSE);
+
+    /* shut down the interest xfer dialog */
+    gnc_xfer_dialog_close (data->xferData);
+
+    /* make the button clickable again */
+    if (data->xfer_button)
+        gtk_widget_set_sensitive (GTK_WIDGET (data->xfer_button), TRUE);
+}
+
+
+static void
+recnInterestXferWindow (startRecnWindowData *data)
+{
+    gchar *title;
+
+    if (!account_type_has_auto_interest_xfer (data->account_type)) return;
+
+    /* get a normal transfer dialog... */
+    data->xferData = gnc_xfer_dialog (GTK_WIDGET(data->startRecnWindow),
+                                      data->account);
+
+    /* ...and start changing things: */
+
+    /* change title */
+    if ( account_type_has_auto_interest_payment (data->account_type))
+        title = gnc_recn_make_interest_window_name (data->account,
+                _("Interest Payment"));
+    else
+        title = gnc_recn_make_interest_window_name (data->account,
+                _("Interest Charge"));
+
+    gnc_xfer_dialog_set_title (data->xferData, title);
+    g_free (title);
+
+
+    /* change frame labels */
+    gnc_xfer_dialog_set_information_label (data->xferData,
+                                           _("Payment Information"));
+
+    /* Interest accrued is a transaction from an income account
+     * to a bank account.  Interest charged is a transaction from
+     * a credit account to an expense account.  The user isn't allowed
+     * to change the account (bank or credit) being reconciled.
+     */
+    if (account_type_has_auto_interest_payment (data->account_type))
+    {
+        gnc_xfer_dialog_set_from_account_label (data->xferData,
+                                                _("Payment From"));
+        gnc_xfer_dialog_set_from_show_button_active( data->xferData, TRUE);
+
+        // XXX: Set "from" account from previous interest payment.
+
+        gnc_xfer_dialog_set_to_account_label (data->xferData,
+                                              _("Reconcile Account"));
+        gnc_xfer_dialog_select_to_account (data->xferData, data->account);
+        gnc_xfer_dialog_lock_to_account_tree (data->xferData );
+
+        /* Quickfill based on the reconcile account, which is the "To" acct. */
+        gnc_xfer_dialog_quickfill_to_account (data->xferData, TRUE);
+    }
+    else  /* interest charged to account rather than paid to it */
+    {
+        gnc_xfer_dialog_set_from_account_label (data->xferData,
+                                                _("Reconcile Account"));
+        gnc_xfer_dialog_select_from_account (data->xferData, data->account);
+        gnc_xfer_dialog_lock_from_account_tree (data->xferData);
+
+        gnc_xfer_dialog_set_to_account_label (data->xferData,
+                                              _("Payment To"));
+        gnc_xfer_dialog_set_to_show_button_active (data->xferData, TRUE);
+
+        // XXX: Set "to" account from previous interest payment.
+
+        /* Quickfill based on the reconcile account, which is the "From" acct. */
+        gnc_xfer_dialog_quickfill_to_account (data->xferData, FALSE);
+    }
+
+
+    /* add a button to disable auto interest payments for this account */
+    gnc_xfer_dialog_add_user_specified_button (data->xferData,
+            ( account_type_has_auto_interest_payment (data->account_type) ?
+              _("No Auto Interest Payments for this Account")
+              : _("No Auto Interest Charges for this Account")),
+            G_CALLBACK (gnc_recn_interest_xfer_no_auto_clicked_cb),
+            (gpointer) data );
+
+    /* no currency frame */
+    gnc_xfer_dialog_toggle_currency_table (data->xferData, FALSE);
+
+    /* set the reconcile date for the transaction date */
+    gnc_xfer_dialog_set_date (data->xferData, data->date);
+
+    /* Now run the transfer dialog.  This blocks until done.
+     * If the user hit Cancel, make the button clickable so that
+     * the user can retry if they want.  We don't make the button
+     * clickable if they successfully entered a transaction, since
+     * the fact that the button was clickable again might make
+     * the user think that the transaction didn't actually go through.
+     */
+    if (!gnc_xfer_dialog_run_until_done (data->xferData))
+        if (data->xfer_button)
+            gtk_widget_set_sensitive (GTK_WIDGET (data->xfer_button), TRUE);
+
+    /* done with the XferDialog */
+    data->xferData = NULL;
+}
+
+
+/* Set up for the interest xfer window, run the window, and update
+ * the startRecnWindow if the interest xfer changed anything that matters.
+ */
+static void
+gnc_reconcile_interest_xfer_run (startRecnWindowData *data)
+{
+    GtkWidget *entry = gnc_amount_edit_gtk_entry (
+                           GNC_AMOUNT_EDIT(data->end_value));
+    gnc_numeric before = gnc_amount_edit_get_amount (
+                             GNC_AMOUNT_EDIT(data->end_value));
+    gnc_numeric after = gnc_numeric_zero();
+
+    recnInterestXferWindow (data);
+
+    /* recompute the ending balance */
+    after = xaccAccountGetBalanceAsOfDate (data->account, data->date);
+
+    /* update the ending balance in the startRecnWindow if it has changed. */
+    if ( gnc_numeric_compare (before, after))
+    {
+        if (gnc_reverse_balance (data->account))
+            after = gnc_numeric_neg (after);
+
+        gnc_amount_edit_set_amount (GNC_AMOUNT_EDIT (data->end_value), after);
+        gtk_widget_grab_focus (GTK_WIDGET (entry));
+        gtk_editable_select_region (GTK_EDITABLE (entry), 0, -1);
+        data->original_value = after;
+        data->user_set_value = FALSE;
+    }
+}
+
+
+void
+gnc_start_recn2_interest_clicked_cb (GtkButton *button, startRecnWindowData *data)
+{
+    /* indicate in account that user wants
+     * an auto interest xfer for this account */
+    xaccAccountSetAutoInterestXfer (data->account, TRUE);
+
+    /* make the button unclickable since we're popping up the window */
+    if (data->xfer_button)
+        gtk_widget_set_sensitive (GTK_WIDGET (data->xfer_button), FALSE);
+
+    /* run the account window */
+    gnc_reconcile_interest_xfer_run (data);
+}
+
+
+static void
+gnc_save_reconcile_interval (Account *account, time64 statement_date)
+{
+    time64 prev_statement_date;
+    int days = 0, months = 0;
+    double seconds;
+
+    if (!xaccAccountGetReconcileLastDate (account, &prev_statement_date))
+        return;
+
+    /*
+     * Compute the number of days difference.
+     */
+    seconds = gnc_difftime (statement_date, prev_statement_date);
+    days = (int)(seconds / 60 / 60 / 24);
+
+    /*
+     * See if we need to remember days(weeks) or months.  The only trick
+     * value is 28 days which could be wither 4 weeks or 1 month.
+     */
+    if (days == 28)
+    {
+        int prev_days = 0, prev_months = 1;
+
+        /* What was it last time? */
+        xaccAccountGetReconcileLastInterval (account, &prev_months, &prev_days);
+        if (prev_months == 1)
+        {
+            months = 1;
+            days = 0;
+        }
+    }
+    else if (days > 28)
+    {
+        struct tm current, prev;
+
+        gnc_localtime_r (&statement_date, &current);
+        gnc_localtime_r (&prev_statement_date, &prev);
+        months = ((12 * current.tm_year + current.tm_mon) -
+                  (12 * prev.tm_year + prev.tm_mon));
+        days = 0;
+    }
+
+    /*
+     * Remember for next time unless it is negative.
+     */
+    if (months >= 0 && days >= 0)
+        xaccAccountSetReconcileLastInterval (account, months, days);
+}
+
+
+/********************************************************************\
+ * startRecnWindow                                                  *
+ *   opens up the window to prompt the user to enter the ending     *
+ *   balance from bank statement                                    *
+ *                                                                  *
+ * NOTE: This function does not return until the user presses "Ok"  *
+ *       or "Cancel"                                                *
+ *                                                                  *
+ * Args:   parent         - the parent of this window               *
+ *         account        - the account to reconcile                *
+ *         new_ending     - returns the amount for ending balance   *
+ *         statement_date - returns date of the statement :)        *
+ * Return: True, if the user presses "Ok", else False               *
+\********************************************************************/
+static gboolean
+startRecnWindow (GtkWidget *parent, Account *account,
+                gnc_numeric *new_ending, time64 *statement_date,
+                gboolean enable_subaccount)
+{
+    GtkWidget *dialog, *end_value, *date_value, *include_children_button;
+    GtkBuilder *builder;
+    startRecnWindowData data = { NULL };
+    gboolean auto_interest_xfer_option;
+    GNCPrintAmountInfo print_info;
+    gnc_numeric ending;
+    char *title;
+    int result;
+
+    /* Initialize the data structure that will be used for several callbacks
+     * throughout this file with the relevant info.  Some initialization is
+     * done below as well.  Note that local storage should be OK for this,
+     * since any callbacks using it will only work while the startRecnWindow
+     * is running.
+     */
+    data.account = account;
+    data.account_type = xaccAccountGetType (account);
+    data.date = *statement_date;
+
+    /* whether to have an automatic interest xfer dialog or not */
+    auto_interest_xfer_option =
+        gnc_recn_interest_xfer_get_auto_interest_xfer_allowed (account);
+
+    data.include_children = xaccAccountGetReconcileChildrenStatus (account);
+
+    ending = gnc_ui_account_get_reconciled_balance (account,
+             data.include_children);
+    print_info = gnc_account_print_info (account, TRUE);
+
+    /*
+     * Do not reverse the balance here.  It messes up the math in the
+     * reconciliation window.  Also, the balance should show up as a
+     * positive number in the reconciliation window to match the positive
+     * number that shows in the register window.
+     */
+
+    /* Create the dialog box */
+    builder = gtk_builder_new();
+    gnc_builder_add_from_file (builder, "window-reconcile.glade", "Reconcile Start Dialog");
+
+    dialog = GTK_WIDGET(gtk_builder_get_object (builder, "Reconcile Start Dialog"));
+
+    title = gnc_recn_make_window_name (account);
+    gtk_window_set_title (GTK_WINDOW (dialog), title);
+    g_free (title);
+
+    data.startRecnWindow = GTK_WIDGET (dialog);
+
+    if (parent != NULL)
+        gtk_window_set_transient_for (GTK_WINDOW (dialog), GTK_WINDOW (parent));
+
+    {
+        GtkWidget *start_value, *box;
+        GtkWidget *entry, *label;
+        GtkWidget *interest = NULL;
+
+        start_value = GTK_WIDGET (gtk_builder_get_object (builder, "start_value"));
+        gtk_label_set_text (GTK_LABEL(start_value), xaccPrintAmount (ending, print_info));
+
+        include_children_button = GTK_WIDGET (gtk_builder_get_object (builder, "subaccount_check"));
+        gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (include_children_button),
+                                     data.include_children);
+        gtk_widget_set_sensitive (include_children_button, enable_subaccount);
+
+        date_value = gnc_date_edit_new (*statement_date, FALSE, FALSE);
+        data.date_value = date_value;
+        box = GTK_WIDGET (gtk_builder_get_object (builder, "date_value_box"));
+        gtk_box_pack_start (GTK_BOX (box), date_value, TRUE, TRUE, 0);
+        label = GTK_WIDGET (gtk_builder_get_object (builder, "date_label"));
+        gnc_date_make_mnemonic_target (GNC_DATE_EDIT (date_value), label);
+
+        end_value = gnc_amount_edit_new ();
+        data.end_value = GNC_AMOUNT_EDIT (end_value);
+        data.original_value = *new_ending;
+        data.user_set_value = FALSE;
+        box = GTK_WIDGET (gtk_builder_get_object (builder, "ending_value_box"));
+        gtk_box_pack_start (GTK_BOX (box), end_value, TRUE, TRUE, 0);
+        label = GTK_WIDGET (gtk_builder_get_object (builder, "end_label"));
+        gtk_label_set_mnemonic_widget (GTK_LABEL (label), end_value);
+
+        gtk_builder_connect_signals_full (builder, gnc_builder_connect_full_func, &data);
+
+        gnc_date_activates_default (GNC_DATE_EDIT (date_value), TRUE);
+
+        /* need to get a callback on date changes to update the recn balance */
+        g_signal_connect ( G_OBJECT (date_value), "date_changed",
+                           G_CALLBACK (gnc_start_recn2_date_changed), (gpointer) &data );
+
+        print_info.use_symbol = 0;
+        gnc_amount_edit_set_print_info (GNC_AMOUNT_EDIT (end_value), print_info);
+        gnc_amount_edit_set_fraction (GNC_AMOUNT_EDIT (end_value),
+                                      xaccAccountGetCommoditySCU (account));
+
+        gnc_amount_edit_set_amount (GNC_AMOUNT_EDIT (end_value), *new_ending);
+
+        entry = gnc_amount_edit_gtk_entry (GNC_AMOUNT_EDIT (end_value));
+        gtk_editable_select_region (GTK_EDITABLE (entry), 0, -1);
+        g_signal_connect (G_OBJECT (entry), "focus-out-event",
+                         G_CALLBACK (gnc_start_recn2_update_cb), (gpointer) &data);
+        gtk_entry_set_activates_default (GTK_ENTRY (entry), TRUE);
+
+        /* if it's possible to enter an interest payment or charge for this
+         * account, add a button so that the user can pop up the appropriate
+         * dialog if it isn't automatically popping up.
+         */
+        interest = GTK_WIDGET(gtk_builder_get_object (builder, "interest_button"));
+        if ( account_type_has_auto_interest_payment( data.account_type ) )
+            gtk_button_set_label (GTK_BUTTON (interest), _("Enter _Interest Payment...") );
+        else if ( account_type_has_auto_interest_charge( data.account_type ) )
+            gtk_button_set_label (GTK_BUTTON (interest), _("Enter _Interest Charge...") );
+        else
+        {
+            gtk_widget_destroy (interest);
+            interest = NULL;
+        }
+
+        if ( interest )
+        {
+            data.xfer_button = interest;
+            if ( auto_interest_xfer_option )
+                gtk_widget_set_sensitive (GTK_WIDGET (interest), FALSE);
+        }
+
+        gtk_widget_show_all (dialog);
+
+        gtk_widget_grab_focus(gnc_amount_edit_gtk_entry
+                              (GNC_AMOUNT_EDIT (end_value)));
+    }
+
+    /* Allow the user to enter an interest payment
+     * or charge prior to reconciling */
+    if (account_type_has_auto_interest_xfer (data.account_type)
+            && auto_interest_xfer_option)
+    {
+        gnc_reconcile_interest_xfer_run (&data);
+    }
+
+    result = gtk_dialog_run (GTK_DIALOG (dialog));
+    if (result == GTK_RESPONSE_OK)
+    {
+        *new_ending = gnc_amount_edit_get_amount (GNC_AMOUNT_EDIT (end_value));
+        *statement_date = gnc_date_edit_get_date_end (GNC_DATE_EDIT (date_value));
+
+        if (gnc_reverse_balance (account))
+            *new_ending = gnc_numeric_neg (*new_ending);
+
+        xaccAccountSetReconcileChildrenStatus (account, data.include_children);
+
+        gnc_save_reconcile_interval (account, *statement_date);
+    }
+    gtk_widget_destroy (dialog);
+    g_object_unref (G_OBJECT (builder));
+
+    return (result == GTK_RESPONSE_OK);
+}
+
+
+static void
+gnc_reconcile_window_set_sensitivity (RecnWindow2 *recnData)
+{
+    gboolean sensitive = FALSE;
+    GNCReconcileView *view;
+    GtkAction *action;
+
+    view = GNC_RECONCILE_VIEW (recnData->debit);
+    if (gnc_reconcile_view_num_selected (view) == 1)
+        sensitive = TRUE;
+
+    view = GNC_RECONCILE_VIEW (recnData->credit);
+    if (gnc_reconcile_view_num_selected (view) == 1)
+        sensitive = TRUE;
+
+    action = gtk_action_group_get_action (recnData->action_group,
+                                          "TransEditAction");
+    gtk_action_set_sensitive (action, sensitive);
+    action = gtk_action_group_get_action (recnData->action_group,
+                                          "TransDeleteAction");
+    gtk_action_set_sensitive (action, sensitive);
+
+    sensitive = FALSE;
+
+    view = GNC_RECONCILE_VIEW (recnData->debit);
+    if (gnc_reconcile_view_num_selected (view) > 0)
+        sensitive = TRUE;
+
+    view = GNC_RECONCILE_VIEW (recnData->credit);
+    if (gnc_reconcile_view_num_selected (view) > 0)
+        sensitive = TRUE;
+
+    action = gtk_action_group_get_action (recnData->action_group,
+                                          "TransRecAction");
+    gtk_action_set_sensitive (action, sensitive);
+    action = gtk_action_group_get_action (recnData->action_group,
+                                          "TransUnRecAction");
+    gtk_action_set_sensitive (action, sensitive);
+}
+
+
+static void
+gnc_reconcile_window_toggled_cb (GNCReconcileView *view, Split *split,
+                             gpointer data)
+{
+    RecnWindow2 *recnData = data;
+    gnc_reconcile_window_set_sensitivity (recnData);
+    recnRecalculateBalance (recnData);
+}
+
+
+static void
+gnc_reconcile_window_row_cb (GNCReconcileView *view, gpointer item,
+                             gpointer data)
+{
+    RecnWindow2 *recnData = data;
+    gnc_reconcile_window_set_sensitivity (recnData);
+}
+
+
+/** Popup a contextual menu.  This function ends up being called when
+ *  the user right-clicks in the context of a window, or uses the
+ *  keyboard context-menu request key combination (Shift-F10 by
+ *  default).
+ *
+ *  @param recnData This is a data structure describing the
+ *  Reconciliation Window.
+ *
+ *  @param event The event parameter passed to the "button-press"
+ *  callback.  May be null if there was no event (aka keyboard
+ *  request).
+ */
+static void
+do_popup_menu (RecnWindow2 *recnData, GdkEventButton *event)
+{
+    GtkWidget *menu;
+    int button, event_time;
+
+    menu = gtk_ui_manager_get_widget (recnData->ui_merge, "/MainPopup");
+    if (!menu)
+    {
+        return;
+    }
+
+    if (event)
+    {
+        button = event->button;
+        event_time = event->time;
+    }
+    else
+    {
+        button = 0;
+        event_time = gtk_get_current_event_time ();
+    }
+
+    gtk_menu_popup (GTK_MENU (menu), NULL, NULL, NULL, NULL, button, event_time);
+}
+
+
+/** Callback function invoked when the user requests that Gnucash
+ *  popup the contextual menu via the keyboard context-menu request
+ *  key combination (Shift-F10 by default).
+ *
+ *  @param recnData This is a data structure describing the
+ *  Reconciliation Window.
+ *
+ *  @param widget Whatever widget had focus when the user issued the
+ *  keyboard context-menu request.
+ *
+ *  @return Always returns TRUE to indicate that the menu request was
+ *  handled.
+ */
+static gboolean
+gnc_reconcile_window_popup_menu_cb (GtkWidget *widget,
+                                    RecnWindow2 *recnData)
+{
+    do_popup_menu (recnData, NULL);
+    return TRUE;
+}
+
+
+/*  Callback function invoked when the user clicks in the content of
+ *  any Gnucash window.  If this was a "right-click" then Gnucash will
+ *  popup the contextual menu.
+ */
+static gboolean
+gnc_reconcile_window_button_press_cb (GtkWidget *widget,
+                                      GdkEventButton *event,
+                                      RecnWindow2 *recnData)
+{
+    GNCQueryView      *qview = GNC_QUERY_VIEW (widget);
+    GtkTreeModel      *model;
+    GtkTreeSelection  *selection;
+    GtkTreePath       *path;
+
+    model = gtk_tree_view_get_model (GTK_TREE_VIEW (qview));
+
+    if (event->button == 3 && event->type == GDK_BUTTON_PRESS)
+    {
+
+        /* Get tree path for row that was clicked */
+        gtk_tree_view_get_path_at_pos (GTK_TREE_VIEW (qview),
+                                             (gint) event->x, 
+                                             (gint) event->y,
+                                             &path, NULL, NULL, NULL);
+
+        selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (qview));
+        gtk_tree_selection_select_path (selection, path);
+        gtk_tree_path_free (path);
+        do_popup_menu (recnData, event);
+        return TRUE;
+    }
+    return FALSE;
+}
+
+
+static GNCSplitReg2 *
+gnc_reconcile_window_open_register (RecnWindow2 *recnData)
+{
+    Account *account = recn_get_account (recnData);
+    GncPluginPage *page;
+    GNCSplitReg2 *gsr;
+    gboolean include_children;
+
+    if (!account)
+        return(NULL);
+
+    include_children = xaccAccountGetReconcileChildrenStatus (account);
+    page = gnc_plugin_page_register2_new (account, include_children);
+    gnc_main_window_open_page (NULL, page);
+    gsr = gnc_plugin_page_register2_get_gsr (page);
+    gnc_split_reg2_raise (gsr);
+    return gsr;
+}
+
+
+static void
+gnc_reconcile_window_double_click_cb (GNCReconcileView *view, Split *split,
+                                     gpointer data)
+{
+    RecnWindow2 *recnData = data;
+    GNCSplitReg2 *gsr;
+
+    /* This should never be true, but be paranoid */
+    if (split == NULL)
+        return;
+
+    gsr = gnc_reconcile_window_open_register (recnData);
+    if (gsr == NULL)
+        return;
+    gnc_split_reg2_jump_to_split (gsr, split);
+}
+
+
+static void
+gnc_reconcile_window_focus_cb (GtkWidget *widget, GdkEventFocus *event,
+                              gpointer data)
+{
+    RecnWindow2 *recnData = data;
+    GNCReconcileView *this_view, *other_view;
+    GNCReconcileView *debit, *credit;
+
+    this_view = GNC_RECONCILE_VIEW (widget);
+
+    debit  = GNC_RECONCILE_VIEW (recnData->debit);
+    credit = GNC_RECONCILE_VIEW (recnData->credit);
+
+    other_view = GNC_RECONCILE_VIEW (this_view == debit ? credit : debit);
+
+    /* clear the *other* list so we always have no more than one selection */
+    gnc_reconcile_view_unselect_all (other_view);
+}
+
+
+static gboolean
+gnc_reconcile_key_press_cb (GtkWidget *widget, GdkEventKey *event,
+                            gpointer data)
+{
+    RecnWindow2 *recnData = data;
+    GtkWidget *this_view, *other_view;
+    GtkWidget *debit, *credit;
+
+    switch (event->keyval)
+    {
+    case GDK_Tab:
+    case GDK_ISO_Left_Tab:
+        break;
+
+    default:
+        return FALSE;
+    }
+
+    g_signal_stop_emission_by_name (widget, "key_press_event");
+
+    this_view = widget;
+
+    debit  = recnData->debit;
+    credit = recnData->credit;
+
+    other_view = (this_view == debit ? credit : debit);
+
+    gtk_widget_grab_focus (other_view);
+
+    return TRUE;
+}
+
+
+static void
+gnc_reconcile_window_set_titles (RecnWindow2 *recnData)
+{
+    gboolean formal;
+    gchar *title;
+
+    formal = gnc_gconf_get_bool (GCONF_GENERAL, KEY_ACCOUNTING_LABELS, NULL);
+
+    if (formal)
+        title = _("Debits");
+    else
+        title = gnc_get_debit_string (ACCT_TYPE_NONE);
+
+    gtk_frame_set_label (GTK_FRAME (recnData->debit_frame), title);
+
+    if (!formal)
+        g_free(title);
+
+    if (formal)
+        title = _("Credits");
+    else
+        title = gnc_get_credit_string (ACCT_TYPE_NONE);
+
+    gtk_frame_set_label (GTK_FRAME (recnData->credit_frame), title);
+
+    if (!formal)
+        g_free(title);
+}
+
+
+static GtkWidget *
+gnc_reconcile_window_create_view_box (Account *account,
+                                     GNCReconcileViewType type,
+                                     RecnWindow2 *recnData,
+                                     GtkWidget **list_save,
+                                     GtkWidget **total_save)
+{
+    GtkWidget *frame, *scrollWin, *view, *vbox, *label, *hbox;
+
+    frame = gtk_frame_new (NULL);
+
+    if (type == RECLIST_DEBIT)
+        recnData->debit_frame = frame;
+    else
+        recnData->credit_frame = frame;
+
+    vbox = gtk_vbox_new (FALSE, 5);
+
+    view = gnc_reconcile_view_new(account, type, recnData->statement_date);
+    *list_save = view;
+
+    g_signal_connect (view, "toggle_reconciled",
+                     G_CALLBACK (gnc_reconcile_window_toggled_cb),
+                     recnData);
+    g_signal_connect (view, "line_selected",
+                     G_CALLBACK (gnc_reconcile_window_row_cb),
+                     recnData);
+    g_signal_connect (view, "button_press_event",
+                     G_CALLBACK (gnc_reconcile_window_button_press_cb),
+                     recnData);
+    g_signal_connect (view, "double_click_split",
+                     G_CALLBACK (gnc_reconcile_window_double_click_cb),
+                     recnData);
+    g_signal_connect (view, "focus_in_event",
+                     G_CALLBACK (gnc_reconcile_window_focus_cb),
+                     recnData);
+    g_signal_connect (view, "key_press_event",
+                     G_CALLBACK (gnc_reconcile_key_press_cb),
+                     recnData);
+
+    scrollWin = gtk_scrolled_window_new (NULL, NULL);
+    gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scrollWin),
+                                   GTK_POLICY_AUTOMATIC,
+                                   GTK_POLICY_AUTOMATIC);
+    gtk_container_set_border_width (GTK_CONTAINER (scrollWin), 5);
+
+    gtk_container_add (GTK_CONTAINER (frame), scrollWin);
+    gtk_container_add (GTK_CONTAINER (scrollWin), view);
+    gtk_box_pack_start (GTK_BOX (vbox), frame, TRUE, TRUE, 0);
+
+    hbox = gtk_hbox_new (FALSE, 5);
+    gtk_box_pack_start (GTK_BOX (vbox), hbox, FALSE, FALSE, 0);
+
+    label = gtk_label_new (_("Total:"));
+    gtk_misc_set_alignment (GTK_MISC (label), 1.0, 0.5);
+    gtk_box_pack_start (GTK_BOX (hbox), label, TRUE, TRUE, 0);
+
+    label = gtk_label_new("");
+    gtk_box_pack_start (GTK_BOX (hbox), label, FALSE, FALSE, 0);
+    *total_save = label;
+
+    return vbox;
+}
+
+
+static Split *
+gnc_reconcile_window_get_current_split (RecnWindow2 *recnData)
+{
+    GNCReconcileView *view;
+    Split *split;
+
+    view = GNC_RECONCILE_VIEW (recnData->debit);
+    split = gnc_reconcile_view_get_current_split (view);
+    if (split != NULL)
+        return split;
+
+    view = GNC_RECONCILE_VIEW (recnData->credit);
+    split = gnc_reconcile_view_get_current_split (view);
+
+    return split;
+}
+
+
+static void
+gnc_ui_reconcile_window_help_cb (GtkWidget *widget, gpointer data)
+{
+    gnc_gnome_help (HF_HELP, HL_RECNWIN);
+}
+
+
+static void
+gnc_ui_reconcile_window_change_cb (GtkAction *action, gpointer data)
+{
+    RecnWindow2 *recnData = data;
+    Account *account = recn_get_account (recnData);
+    gnc_numeric new_ending = recnData->new_ending;
+    time64 statement_date = recnData->statement_date;
+
+    if (gnc_reverse_balance (account))
+        new_ending = gnc_numeric_neg (new_ending);
+    if (startRecnWindow (recnData->window, account, &new_ending, &statement_date,
+                         FALSE))
+    {
+        recnData->new_ending = new_ending;
+        recnData->statement_date = statement_date;
+        recnRecalculateBalance (recnData);
+    }
+}
+
+
+static void
+gnc_ui_reconcile_window_balance_cb (GtkButton *button, gpointer data)
+{
+    RecnWindow2 *recnData = data;
+    GNCSplitReg2 *gsr;
+    Account *account;
+    gnc_numeric balancing_amount;
+    time64 statement_date;
+
+
+    gsr = gnc_reconcile_window_open_register (recnData);
+    if (gsr == NULL)
+        return;
+
+    account = recn_get_account (recnData);
+    if (account == NULL)
+        return;
+
+    balancing_amount = recnRecalculateBalance (recnData);
+    if (gnc_numeric_zero_p (balancing_amount))
+        return;
+
+    statement_date = recnData->statement_date;
+    if (statement_date == 0)
+        statement_date = gnc_time (NULL); // default to 'now'
+
+    gnc_split_reg2_balancing_entry (gsr, account, statement_date, balancing_amount);
+}
+
+
+static void
+gnc_ui_reconcile_window_rec_cb (GtkButton *button, gpointer data)
+{
+    RecnWindow2 *recnData = data;
+    GNCReconcileView *debit, *credit;
+
+    debit  = GNC_RECONCILE_VIEW (recnData->debit);
+    credit = GNC_RECONCILE_VIEW (recnData->credit);
+
+    gnc_reconcile_view_set_list (debit, TRUE);
+    gnc_reconcile_view_set_list (credit, TRUE);
+}
+
+
+static void
+gnc_ui_reconcile_window_unrec_cb(GtkButton *button, gpointer data)
+{
+    RecnWindow2 *recnData = data;
+    GNCReconcileView *debit, *credit;
+
+    debit  = GNC_RECONCILE_VIEW (recnData->debit);
+    credit = GNC_RECONCILE_VIEW (recnData->credit);
+
+    gnc_reconcile_view_set_list (debit, FALSE);
+    gnc_reconcile_view_set_list (credit, FALSE);
+}
+
+
+static void
+gnc_ui_reconcile_window_delete_cb (GtkButton *button, gpointer data)
+{
+    RecnWindow2 *recnData = data;
+    Transaction *trans;
+    Split *split;
+
+    split = gnc_reconcile_window_get_current_split (recnData);
+    /* This should never be true, but be paranoid */
+    if (split == NULL)
+        return;
+
+    {
+        const char *message = _("Are you sure you want to delete the selected "
+                                "transaction?");
+        gboolean result;
+
+        result = gnc_verify_dialog (recnData->window, FALSE, "%s", message);
+
+        if (!result)
+            return;
+    }
+
+    gnc_suspend_gui_refresh ();
+
+    trans = xaccSplitGetParent (split);
+    xaccTransDestroy (trans);
+
+    gnc_resume_gui_refresh ();
+}
+
+
+static void
+gnc_ui_reconcile_window_edit_cb (GtkButton *button, gpointer data)
+{
+    RecnWindow2 *recnData = data;
+    GNCSplitReg2 *gsr;
+    Split *split;
+
+    split = gnc_reconcile_window_get_current_split (recnData);
+    /* This should never be true, but be paranoid */
+    if (split == NULL)
+        return;
+
+    gsr = gnc_reconcile_window_open_register (recnData);
+    if (gsr == NULL)
+        return;
+    gnc_split_reg2_jump_to_split_amount (gsr, split);
+}
+
+
+static char *
+gnc_recn_make_window_name (Account *account)
+{
+    char *fullname;
+    char *title;
+
+    fullname = gnc_account_get_full_name (account);
+    title = g_strconcat (fullname, " - ", _("Reconcile"), NULL);
+
+    g_free (fullname);
+
+    return title;
+}
+
+
+static void
+gnc_recn_set_window_name (RecnWindow2 *recnData)
+{
+    char *title;
+
+    title = gnc_recn_make_window_name (recn_get_account (recnData));
+
+    gtk_window_set_title (GTK_WINDOW (recnData->window), title);
+
+    g_free (title);
+}
+
+
+static void
+gnc_recn_edit_account_cb (GtkAction *action, gpointer data)
+{
+    RecnWindow2 *recnData = data;
+    Account *account = recn_get_account (recnData);
+
+    if (account == NULL)
+        return;
+
+    gnc_ui_edit_account_window (account);
+}
+
+
+static void
+gnc_recn_xfer_cb (GtkAction *action, gpointer data)
+{
+    RecnWindow2 *recnData = data;
+    Account *account = recn_get_account (recnData);
+
+    if (account == NULL)
+        return;
+
+    gnc_xfer_dialog (recnData->window, account);
+}
+
+
+static void
+gnc_recn_scrub_cb (GtkAction *action, gpointer data)
+{
+    RecnWindow2 *recnData = data;
+    Account *account = recn_get_account (recnData);
+
+    if (account == NULL)
+        return;
+
+    gnc_suspend_gui_refresh ();
+
+    xaccAccountTreeScrubOrphans (account);
+    xaccAccountTreeScrubImbalance (account);
+
+    // XXX: Lots are disabled.
+    if (g_getenv("GNC_AUTO_SCRUB_LOTS") != NULL)
+        xaccAccountTreeScrubLots(account);
+
+    gnc_resume_gui_refresh ();
+}
+
+
+static void
+gnc_recn_open_cb (GtkAction *action, gpointer data)
+{
+    RecnWindow2 *recnData = data;
+
+    gnc_reconcile_window_open_register (recnData);
+}
+
+
+static void
+gnc_recn_refresh_toolbar (RecnWindow2 *recnData)
+{
+    GtkToolbarStyle style;
+    GSList *list;
+
+    if ((recnData == NULL) || (recnData->toolbar == NULL))
+        return;
+
+    style = gnc_get_toolbar_style();
+    list = gtk_ui_manager_get_toplevels (recnData->ui_merge, GTK_UI_MANAGER_TOOLBAR);
+    g_slist_foreach (list, (GFunc) gtk_toolbar_set_style, GINT_TO_POINTER(style));
+    g_slist_free (list);
+}
+
+
+static void
+gnc_toolbar_change_cb (GConfClient *client,
+                       guint cnxn_id,
+                       GConfEntry *entry,
+                       gpointer data)
+{
+    RecnWindow2 *recnData = data;
+    GConfValue *value;
+    const gchar *key, *key_tail;
+
+    key = gconf_entry_get_key (entry);
+    value = gconf_entry_get_value (entry);
+    if (!key || !value)
+        return;
+
+    key_tail = strrchr(key, '/');
+    if (key_tail != NULL)
+        key_tail++;
+    if (strcmp(key_tail, KEY_TOOLBAR_STYLE) == 0)
+    {
+        gnc_recn_refresh_toolbar (recnData);
+    }
+}
+
+
+static void
+gnc_get_reconcile_info (Account *account,
+                        gnc_numeric *new_ending,
+                        time64 *statement_date)
+{
+    gboolean always_today;
+    GDate date;
+    time64 today;
+    struct tm tm;
+
+    g_date_clear(&date, 1);
+
+    always_today = gnc_gconf_get_bool (GCONF_RECONCILE_SECTION,
+                                      "always_reconcile_to_today", NULL);
+
+    if (!always_today &&
+            xaccAccountGetReconcileLastDate (account, statement_date))
+    {
+        int months = 1, days = 0;
+
+        gnc_gdate_set_time64 (&date, *statement_date);
+
+        xaccAccountGetReconcileLastInterval (account, &months, &days);
+
+        if (months)
+        {
+            gboolean was_last_day_of_month = g_date_is_last_of_month (&date);
+
+            g_date_add_months (&date, months);
+
+            /* Track last day of the month, i.e. 1/31 -> 2/28 -> 3/31 */
+            if (was_last_day_of_month)
+            {
+                g_date_set_day (&date, g_date_get_days_in_month (g_date_get_month (&date),
+                               g_date_get_year (&date)));
+            }
+        }
+        else
+        {
+            g_date_add_days (&date, days);
+        }
+
+	*statement_date = gnc_time64_get_day_end_gdate (&date);
+
+        today = gnc_time64_get_day_end (gnc_time (NULL));
+        if (*statement_date > today)
+            *statement_date = today;
+    }
+
+    xaccAccountGetReconcilePostponeDate (account, statement_date);
+
+    if (xaccAccountGetReconcilePostponeBalance (account, new_ending))
+    {
+        if (gnc_reverse_balance (account))
+            *new_ending = gnc_numeric_neg (*new_ending);
+    }
+    else
+    {
+        /* if the account wasn't previously postponed, try to predict
+         * the statement balance based on the statement date.
+         */
+        *new_ending =
+            gnc_ui_account_get_balance_as_of_date
+            (account, *statement_date,
+             xaccAccountGetReconcileChildrenStatus (account));
+    }
+}
+
+
+static gboolean
+find_by_account (gpointer find_data, gpointer user_data)
+{
+    Account *account = find_data;
+    RecnWindow2 *recnData = user_data;
+
+    if (!recnData)
+        return FALSE;
+
+    return guid_equal (&recnData->account, xaccAccountGetGUID (account));
+}
+
+
+static void
+recn_set_watches_one_account (gpointer data, gpointer user_data)
+{
+    Account *account = (Account *)data;
+    RecnWindow2 *recnData = (RecnWindow2 *)user_data;
+    GList *node;
+
+    for (node = xaccAccountGetSplitList (account); node; node = node->next)
+    {
+        Split *split = node->data;
+        Transaction *trans;
+        char recn;
+
+        recn = xaccSplitGetReconcile (split);
+        switch (recn)
+        {
+        case NREC:
+        case CREC:
+            trans = xaccSplitGetParent (split);
+
+            gnc_gui_component_watch_entity (recnData->component_id,
+                                            xaccTransGetGUID (trans),
+                                            QOF_EVENT_MODIFY
+                                            | QOF_EVENT_DESTROY
+                                            | GNC_EVENT_ITEM_CHANGED);
+            break;
+
+        default:
+            break;
+        }
+    }
+}
+
+
+static void
+recn_set_watches (RecnWindow2 *recnData)
+{
+    gboolean include_children;
+    Account *account;
+    GList *accounts = NULL;
+
+    gnc_gui_component_clear_watches (recnData->component_id);
+
+    gnc_gui_component_watch_entity (recnData->component_id,
+                                    &recnData->account,
+                                    QOF_EVENT_MODIFY | QOF_EVENT_DESTROY);
+
+    account = recn_get_account (recnData);
+
+    include_children = xaccAccountGetReconcileChildrenStatus (account);
+    if (include_children)
+        accounts = gnc_account_get_descendants (account);
+
+    /* match the account */
+    accounts = g_list_prepend (accounts, account);
+
+    g_list_foreach (accounts, recn_set_watches_one_account, recnData);
+
+    g_list_free (accounts);
+}
+
+
+static void
+refresh_handler (GHashTable *changes, gpointer user_data)
+{
+    RecnWindow2 *recnData = user_data;
+    const EventInfo *info;
+    Account *account;
+
+    account = recn_get_account (recnData);
+    if (!account)
+    {
+        gnc_close_gui_component_by_data (WINDOW_RECONCILE_CM_CLASS, recnData);
+        return;
+    }
+
+    if (changes)
+    {
+        info = gnc_gui_get_entity_events (changes, &recnData->account);
+        if (info && (info->event_mask & QOF_EVENT_DESTROY))
+        {
+            gnc_close_gui_component_by_data (WINDOW_RECONCILE_CM_CLASS, recnData);
+            return;
+        }
+    }
+
+    gnc_reconcile_window_set_titles (recnData);
+    recn_set_watches (recnData);
+
+    recnRefresh (recnData);
+}
+
+
+static void
+close_handler (gpointer user_data)
+{
+    RecnWindow2 *recnData = user_data;
+
+    gnc_save_window_size (GCONF_SECTION, GTK_WINDOW (recnData->window));
+    gtk_widget_destroy (recnData->window);
+}
+
+
+/********************************************************************\
+ * recnWindow2                                                       *
+ *   opens up the window to reconcile an account                    *
+ *                                                                  *
+ * Args:   parent  - the parent of this window                      *
+ *         account - the account to reconcile                       *
+ * Return: recnData - the instance of this RecnWindow2               *
+\********************************************************************/
+RecnWindow2 *
+recnWindow2 (GtkWidget *parent, Account *account)
+{
+    gnc_numeric new_ending;
+    time64 statement_date;
+
+    if (account == NULL)
+        return NULL;
+
+    /* The last time reconciliation was attempted during the current
+     * execution of gnucash, the date was stored. Use that date if
+     * possible. This helps with balancing multiple accounts for which
+     * statements are issued at the same time, like multiple bank
+     * accounts on a single statement. */
+    if (!gnc_reconcile_last_statement_date)
+        statement_date = gnc_time (NULL);
+    else
+        statement_date = gnc_reconcile_last_statement_date;
+
+    gnc_get_reconcile_info (account, &new_ending, &statement_date);
+
+    /* Popup a little window to prompt the user to enter the
+     * ending balance for his/her bank statement */
+    if (!startRecnWindow (parent, account, &new_ending, &statement_date, TRUE))
+        return NULL;
+
+    return recnWindow2WithBalance (parent, account, new_ending, statement_date);
+}
+
+
+static void
+recnWindow2_add_widget (GtkUIManager *merge,
+                       GtkWidget *widget,
+                       GtkVBox *dock)
+{
+    gtk_box_pack_start (GTK_BOX (dock), widget, FALSE, FALSE, 0);
+    gtk_widget_show (widget);
+}
+
+
+/********************************************************************\
+ * recnWindow2WithBalance
+ *
+ *   Opens up the window to reconcile an account, but with ending
+ *   balance and statement date already given.
+ *
+ * Args:   parent         - The parent widget of the new window
+ *         account        - The account to reconcile
+ *         new_ending     - The amount for ending balance
+ *         statement_date - The date of the statement
+ * Return: recnData - the instance of this RecnWindow2
+\********************************************************************/
+RecnWindow2 *
+recnWindow2WithBalance (GtkWidget *parent, Account *account,
+                       gnc_numeric new_ending, time64 statement_date)
+{
+    RecnWindow2 *recnData;
+    GtkWidget *statusbar;
+    GtkWidget *vbox;
+    GtkWidget *dock;
+
+    if (account == NULL)
+        return NULL;
+
+    recnData = gnc_find_first_gui_component (WINDOW_RECONCILE_CM_CLASS,
+               find_by_account, account);
+    if (recnData)
+        return recnData;
+
+    recnData = g_new0 (RecnWindow2, 1);
+
+    recnData->account = *xaccAccountGetGUID (account);
+
+
+    recnData->component_id =
+        gnc_register_gui_component (WINDOW_RECONCILE_CM_CLASS,
+                                    refresh_handler, close_handler,
+                                    recnData);
+
+    recn_set_watches (recnData);
+
+    gnc_reconcile_last_statement_date = statement_date;
+
+    recnData->new_ending = new_ending;
+    recnData->statement_date = statement_date;
+    recnData->window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
+    recnData->delete_refresh = FALSE;
+
+    gnc_recn_set_window_name (recnData);
+
+    vbox = gtk_vbox_new (FALSE, 0);
+    gtk_container_add (GTK_CONTAINER(recnData->window), vbox);
+
+    dock = gtk_vbox_new (FALSE, 0);
+    gtk_widget_show (dock);
+    gtk_box_pack_start (GTK_BOX (vbox), dock, FALSE, TRUE, 0);
+
+    {
+        gchar *filename;
+        gint merge_id;
+        GtkAction *action;
+        GtkActionGroup *action_group;
+        GError *error = NULL;
+
+        recnData->ui_merge = gtk_ui_manager_new ();
+        g_signal_connect (recnData->ui_merge, "add_widget",
+                          G_CALLBACK (recnWindow2_add_widget), dock);
+
+        action_group = gtk_action_group_new ("ReconcileWindowActions");
+        recnData->action_group = action_group;
+        gnc_gtk_action_group_set_translation_domain (action_group, GETTEXT_PACKAGE);
+        gtk_action_group_add_actions (action_group, recnWindow2_actions,
+                                      recnWindow2_n_actions, recnData);
+        action =
+            gtk_action_group_get_action (action_group, "AccountOpenAccountAction");
+        g_object_set (G_OBJECT (action), "short_label", _("Open"), NULL);
+
+        gtk_ui_manager_insert_action_group (recnData->ui_merge, action_group, 0);
+
+        filename = gnc_filepath_locate_ui_file("gnc-reconcile-window-ui.xml");
+        /* Can't do much without a ui. */
+        g_assert (filename);
+
+        merge_id = gtk_ui_manager_add_ui_from_file (recnData->ui_merge,
+                   filename, &error);
+        g_assert(merge_id || error);
+        if (merge_id)
+        {
+            gtk_window_add_accel_group (GTK_WINDOW (recnData->window),
+                                        gtk_ui_manager_get_accel_group (recnData->ui_merge));
+            gtk_ui_manager_ensure_update (recnData->ui_merge);
+        }
+        else
+        {
+            g_critical("Failed to load ui file.\n  Filename %s\n  Error %s",
+                       filename, error->message);
+            g_error_free (error);
+            g_assert (merge_id != 0);
+        }
+        g_free (filename);
+
+        recnData->toolbar_change_cb_id =
+            gnc_gconf_add_anon_notification (GCONF_GENERAL,
+                                            gnc_toolbar_change_cb, recnData);
+        recnData->toolbar_change_cb_id2 =
+            gnc_gconf_add_anon_notification (DESKTOP_GNOME_INTERFACE,
+                                            gnc_toolbar_change_cb, recnData);
+    }
+
+    g_signal_connect (recnData->window, "popup-menu",
+                     G_CALLBACK (gnc_reconcile_window_popup_menu_cb), recnData);
+
+    statusbar = gtk_statusbar_new ();
+    gtk_statusbar_set_has_resize_grip (GTK_STATUSBAR (statusbar), TRUE);
+    gtk_box_pack_end (GTK_BOX (vbox), statusbar, FALSE, FALSE, 0);
+
+    g_signal_connect (recnData->window, "destroy",
+                      G_CALLBACK (recn_destroy_cb), recnData);
+    g_signal_connect (recnData->window, "delete_event",
+                      G_CALLBACK (recn_delete_cb), recnData);
+    g_signal_connect (recnData->window, "key_press_event",
+                      G_CALLBACK (recn_key_press_cb), recnData);
+
+    /* The main area */
+    {
+        GtkWidget *frame = gtk_frame_new (NULL);
+        GtkWidget *main_area = gtk_vbox_new (FALSE, 10);
+        GtkWidget *debcred_area = gtk_table_new (1, 2, TRUE);
+        GtkWidget *debits_box;
+        GtkWidget *credits_box;
+
+        gtk_box_pack_start (GTK_BOX (vbox), frame, TRUE, TRUE, 10);
+
+        /* Force a reasonable starting size */
+        gtk_window_set_default_size (GTK_WINDOW (recnData->window), 800, 600);
+        gnc_restore_window_size (GCONF_SECTION, GTK_WINDOW (recnData->window));
+
+        gtk_container_add(GTK_CONTAINER(frame), main_area);
+        gtk_container_set_border_width(GTK_CONTAINER(main_area), 10);
+
+        debits_box = gnc_reconcile_window_create_view_box
+                     (account, RECLIST_DEBIT, recnData,
+                      &recnData->debit, &recnData->total_debit);
+
+        credits_box = gnc_reconcile_window_create_view_box
+                      (account, RECLIST_CREDIT, recnData,
+                       &recnData->credit, &recnData->total_credit);
+
+        GNC_RECONCILE_VIEW (recnData->debit)->sibling = GNC_RECONCILE_VIEW (recnData->credit);
+        GNC_RECONCILE_VIEW (recnData->credit)->sibling = GNC_RECONCILE_VIEW (recnData->debit);
+
+        gtk_box_pack_start (GTK_BOX (main_area), debcred_area, TRUE, TRUE, 0);
+        gtk_table_set_col_spacings (GTK_TABLE (debcred_area), 15);
+        gtk_table_attach_defaults (GTK_TABLE (debcred_area), debits_box, 0, 1, 0, 1);
+        gtk_table_attach_defaults (GTK_TABLE (debcred_area), credits_box, 1, 2, 0, 1);
+
+        {
+            GtkWidget *hbox, *title_vbox, *value_vbox;
+            GtkWidget *totals_hbox, *frame, *title, *value;
+
+            /* lower horizontal bar below reconcile lists */
+            hbox = gtk_hbox_new (FALSE, 5);
+            gtk_box_pack_start (GTK_BOX (main_area), hbox, FALSE, FALSE, 0);
+
+            /* frame to hold totals */
+            frame = gtk_frame_new (NULL);
+            gtk_box_pack_end (GTK_BOX (hbox), frame, FALSE, FALSE, 0);
+
+            /* hbox to hold title/value vboxes */
+            totals_hbox = gtk_hbox_new (FALSE, 3);
+            gtk_container_add (GTK_CONTAINER (frame), totals_hbox);
+            gtk_container_set_border_width (GTK_CONTAINER (totals_hbox), 5);
+
+            /* vbox to hold titles */
+            title_vbox = gtk_vbox_new (FALSE, 3);
+            gtk_box_pack_start (GTK_BOX (totals_hbox), title_vbox, FALSE, FALSE, 0);
+
+            /* vbox to hold values */
+            value_vbox = gtk_vbox_new (FALSE, 3);
+            gtk_box_pack_start (GTK_BOX (totals_hbox), value_vbox, TRUE, TRUE, 0);
+
+            /* statement date title/value */
+            title = gtk_label_new (_("Statement Date:"));
+            gtk_misc_set_alignment (GTK_MISC (title), 1.0, 0.5);
+            gtk_box_pack_start (GTK_BOX (title_vbox), title, FALSE, FALSE, 0);
+
+            value = gtk_label_new ("");
+            recnData->recn_date = value;
+            gtk_misc_set_alignment (GTK_MISC (value), 1.0, 0.5);
+            gtk_box_pack_start (GTK_BOX (value_vbox), value, FALSE, FALSE, 0);
+
+            /* starting balance title/value */
+            title = gtk_label_new(_("Starting Balance:"));
+            gtk_misc_set_alignment (GTK_MISC (title), 1.0, 0.5);
+            gtk_box_pack_start (GTK_BOX (title_vbox), title, FALSE, FALSE, 3);
+
+            value = gtk_label_new ("");
+            recnData->starting = value;
+            gtk_misc_set_alignment (GTK_MISC (value), 1.0, 0.5);
+            gtk_box_pack_start (GTK_BOX (value_vbox), value, FALSE, FALSE, 3);
+
+            /* ending balance title/value */
+            title = gtk_label_new (_("Ending Balance:"));
+            gtk_misc_set_alignment (GTK_MISC (title), 1.0, 0.5);
+            gtk_box_pack_start (GTK_BOX (title_vbox), title, FALSE, FALSE, 0);
+
+            value = gtk_label_new ("");
+            recnData->ending = value;
+            gtk_misc_set_alignment (GTK_MISC (value), 1.0, 0.5);
+            gtk_box_pack_start (GTK_BOX (value_vbox), value, FALSE, FALSE, 0);
+
+            /* reconciled balance title/value */
+            title = gtk_label_new (_("Reconciled Balance:"));
+            gtk_misc_set_alignment (GTK_MISC (title), 1.0, 0.5);
+            gtk_box_pack_start (GTK_BOX (title_vbox), title, FALSE, FALSE, 0);
+
+            value = gtk_label_new ("");
+            recnData->reconciled = value;
+            gtk_misc_set_alignment (GTK_MISC (value), 1.0, 0.5);
+            gtk_box_pack_start (GTK_BOX (value_vbox), value, FALSE, FALSE, 0);
+
+            /* difference title/value */
+            title = gtk_label_new (_("Difference:"));
+            gtk_misc_set_alignment(GTK_MISC (title), 1.0, 0.5);
+            gtk_box_pack_start (GTK_BOX (title_vbox), title, FALSE, FALSE, 0);
+
+            value = gtk_label_new ("");
+            recnData->difference = value;
+            gtk_misc_set_alignment (GTK_MISC (value), 1.0, 0.5);
+            gtk_box_pack_start (GTK_BOX (value_vbox), value, FALSE, FALSE, 0);
+        }
+
+        /* Set up the data */
+        recnRefresh (recnData);
+    }
+
+    /* Allow resize */
+    gtk_window_set_resizable (GTK_WINDOW (recnData->window), TRUE);
+
+    gtk_widget_show_all (recnData->window);
+
+    gnc_reconcile_window_set_titles (recnData);
+
+    recnRecalculateBalance (recnData);
+
+    gnc_recn_refresh_toolbar (recnData);
+
+    gnc_window_adjust_for_screen (GTK_WINDOW (recnData->window));
+
+    /* Set the sort orders of the debit and credit tree views */
+    gnc_query_sort_order (GNC_QUERY_VIEW (recnData->debit), 1, GTK_SORT_ASCENDING);
+    gnc_query_sort_order (GNC_QUERY_VIEW (recnData->credit), 1, GTK_SORT_ASCENDING);
+
+    gtk_widget_grab_focus (recnData->debit);
+
+    return recnData;
+}
+
+
+/********************************************************************\
+ * gnc_ui_reconile_window2_raise                                     *
+ *   shows and raises an account editing window                     *
+ *                                                                  *
+ * Args:   editAccData - the edit window structure                  *
+\********************************************************************/
+void
+gnc_ui_reconcile_window2_raise (RecnWindow2 * recnData)
+{
+    if (recnData == NULL)
+        return;
+
+    if (recnData->window == NULL)
+        return;
+
+    gtk_window_present (GTK_WINDOW (recnData->window));
+}
+
+
+/********************************************************************\
+ * recn_destroy_cb                                                  *
+ *   frees memory allocated for an recnWindow2, and other cleanup    *
+ *   stuff                                                          *
+ *                                                                  *
+ * Args:   w    - the widget that called us                         *
+ *         data - the data struct for this window                   *
+ * Return: none                                                     *
+\********************************************************************/
+static void
+recn_destroy_cb (GtkWidget *w, gpointer data)
+{
+    RecnWindow2 *recnData = data;
+
+    gnc_unregister_gui_component_by_data (WINDOW_RECONCILE_CM_CLASS, recnData);
+
+    gnc_gconf_remove_anon_notification (GCONF_GENERAL,
+                                       recnData->toolbar_change_cb_id);
+    gnc_gconf_remove_anon_notification (DESKTOP_GNOME_INTERFACE,
+                                       recnData->toolbar_change_cb_id2);
+
+    if (recnData->delete_refresh)
+        gnc_resume_gui_refresh ();
+
+    g_free (recnData);
+}
+
+
+static void
+recn_cancel (RecnWindow2 *recnData)
+{
+    gboolean changed = FALSE;
+
+    if (gnc_reconcile_view_changed (GNC_RECONCILE_VIEW (recnData->credit)))
+        changed = TRUE;
+    if (gnc_reconcile_view_changed (GNC_RECONCILE_VIEW (recnData->debit)))
+        changed = TRUE;
+
+    if (changed)
+    {
+        const char *message = _("You have made changes to this reconcile "
+                                "window. Are you sure you want to cancel?");
+        if (!gnc_verify_dialog(recnData->window, FALSE, "%s", message))
+            return;
+    }
+
+    gnc_close_gui_component_by_data (WINDOW_RECONCILE_CM_CLASS, recnData);
+}
+
+
+static gboolean
+recn_delete_cb (GtkWidget *widget, GdkEvent *event, gpointer data)
+{
+    RecnWindow2 *recnData = data;
+
+    recn_cancel (recnData);
+    return TRUE;
+}
+
+
+static gboolean
+recn_key_press_cb (GtkWidget *widget, GdkEventKey *event, gpointer data)
+{
+    RecnWindow2 *recnData = data;
+
+    if (event->keyval == GDK_Escape)
+    {
+        recn_cancel (recnData);
+        return TRUE;
+    }
+    else
+    {
+        return FALSE;
+    }
+}
+
+
+/********************************************************************\
+ * find_payment_account                                             *
+ *   find an account that 'looks like' a payment account for the    *
+ *   given account. This really only makes sense for credit card    *
+ *   accounts.                                                      *
+ *                                                                  *
+ * Args:   account - the account to look in                         *
+ * Return: a candidate payment account or NULL if none was found    *
+\********************************************************************/
+static Account *
+find_payment_account (Account *account)
+{
+    GList *list;
+    GList *node;
+
+    if (account == NULL)
+        return NULL;
+
+    list = xaccAccountGetSplitList (account);
+
+    /* Search backwards to find the latest payment */
+    for (node = g_list_last (list); node; node = node->prev)
+    {
+        Transaction *trans;
+        Split *split;
+        GList *n;
+
+        split = node->data;
+        if (split == NULL)
+            continue;
+
+        /* ignore 'purchases' */
+        if (!gnc_numeric_positive_p (xaccSplitGetAmount (split)))
+            continue;
+
+        trans = xaccSplitGetParent(split);
+        if (trans == NULL)
+            continue;
+
+        for (n = xaccTransGetSplitList (trans); n; n = n->next)
+        {
+            GNCAccountType type;
+            Account *a;
+            Split *s;
+
+            s = n->data;
+            if ((s == NULL) || (s == split))
+                continue;
+
+            a = xaccSplitGetAccount(s);
+            if ((a == NULL) || (a == account))
+                continue;
+
+            type = xaccAccountGetType(a);
+            if ((type == ACCT_TYPE_BANK) || (type == ACCT_TYPE_CASH) ||
+                    (type == ACCT_TYPE_ASSET))
+                return a;
+        }
+    }
+
+    return NULL;
+}
+
+
+/********************************************************************\
+ * recnFinishCB                                                     *
+ *   saves reconcile information                                    *
+ *                                                                  *
+ * Args:   w    - the widget that called us                         *
+ *         data - the data struct for this window                   *
+ * Return: none                                                     *
+\********************************************************************/
+static void
+recnFinishCB (GtkAction *action, RecnWindow2 *recnData)
+{
+    gboolean auto_payment;
+    Account *account;
+    time64 date;
+
+    if (!gnc_numeric_zero_p (recnRecalculateBalance (recnData)))
+    {
+        const char *message = _("The account is not balanced. "
+                                "Are you sure you want to finish?");
+        if (!gnc_verify_dialog (recnData->window, FALSE, "%s", message))
+            return;
+    }
+
+    date = recnData->statement_date;
+
+    gnc_suspend_gui_refresh ();
+
+    recnData->delete_refresh = TRUE;
+
+    gnc_reconcile_view_commit (GNC_RECONCILE_VIEW (recnData->credit), date);
+    gnc_reconcile_view_commit (GNC_RECONCILE_VIEW (recnData->debit), date);
+
+    auto_payment = gnc_gconf_get_bool (GCONF_RECONCILE_SECTION,
+                                      "auto_cc_payment", NULL);
+
+    account = recn_get_account (recnData);
+
+    xaccAccountClearReconcilePostpone (account);
+    xaccAccountSetReconcileLastDate (account, date);
+
+    if (auto_payment &&
+            (xaccAccountGetType (account) == ACCT_TYPE_CREDIT) &&
+            (gnc_numeric_negative_p (recnData->new_ending)))
+    {
+        Account *payment_account;
+        XferDialog *xfer;
+
+        xfer = gnc_xfer_dialog (NULL, account);
+
+        gnc_xfer_dialog_set_amount (xfer, gnc_numeric_neg (recnData->new_ending));
+
+        payment_account = find_payment_account (account);
+        if (payment_account != NULL)
+            gnc_xfer_dialog_select_from_account (xfer, payment_account);
+    }
+
+    gnc_close_gui_component_by_data (WINDOW_RECONCILE_CM_CLASS, recnData);
+}
+
+
+/********************************************************************\
+ * recnPostponeCB                                                   *
+ *   saves reconcile information for later use                      *
+ *                                                                  *
+ * Args:   w    - the widget that called us                         *
+ *         data - the data struct for this window                   *
+ * Return: none                                                     *
+\********************************************************************/
+static void
+recnPostponeCB (GtkAction *action, gpointer data)
+{
+    RecnWindow2 *recnData = data;
+    Account *account;
+
+    {
+        const char *message = _("Do you want to postpone this reconciliation "
+                                "and finish it later?");
+        if (!gnc_verify_dialog (recnData->window, FALSE, "%s", message))
+            return;
+    }
+
+    gnc_suspend_gui_refresh ();
+
+    recnData->delete_refresh = TRUE;
+
+    gnc_reconcile_view_postpone (GNC_RECONCILE_VIEW (recnData->credit));
+    gnc_reconcile_view_postpone (GNC_RECONCILE_VIEW (recnData->debit));
+
+    account = recn_get_account (recnData);
+
+    xaccAccountSetReconcilePostponeDate (account, recnData->statement_date);
+    xaccAccountSetReconcilePostponeBalance (account, recnData->new_ending);
+
+    gnc_close_gui_component_by_data (WINDOW_RECONCILE_CM_CLASS, recnData);
+}
+
+
+static void
+recnCancelCB (GtkAction *action, gpointer data)
+{
+    RecnWindow2 *recnData = data;
+    recn_cancel (recnData);
+}
+
+
+/** An array of all of the actions provided by the main window code.
+ *  This includes some placeholder actions for the menus that are
+ *  visible in the menu bar but have no action associated with
+ *  them. */
+static GtkActionEntry recnWindow2_actions [] =
+{
+    /* Toplevel */
+
+    { "ReconcileMenuAction",   NULL, N_("_Reconcile"), NULL, NULL, NULL, },
+    { "AccountMenuAction",     NULL, N_("_Account"), NULL, NULL, NULL, },
+    { "TransactionMenuAction", NULL, N_("_Transaction"), NULL, NULL, NULL, },
+    { "HelpMenuAction",        NULL, N_("_Help"), NULL, NULL, NULL, },
+
+    /* Reconcile menu */
+
+    {
+        "RecnChangeInfoAction", NULL, N_("_Reconcile Information..."),  NULL,
+        N_("Change the reconcile information "
+        "including statement date and ending balance."),
+        G_CALLBACK (gnc_ui_reconcile_window_change_cb)
+    },
+    {
+        "RecnFinishAction", GTK_STOCK_YES, N_("_Finish"), "<control>w",
+        N_("Finish the reconciliation of this account"),
+        G_CALLBACK(recnFinishCB)
+    },
+    {
+        "RecnPostponeAction", GTK_STOCK_GO_BACK, N_("_Postpone"), "<control>p",
+        N_("Postpone the reconciliation of this account"),
+        G_CALLBACK(recnPostponeCB)
+    },
+    {
+        "RecnCancelAction", GTK_STOCK_CANCEL, N_("_Cancel"), NULL,
+        N_("Cancel the reconciliation of this account"),
+        G_CALLBACK(recnCancelCB)
+    },
+
+    /* Account menu */
+
+    {
+        "AccountOpenAccountAction", GTK_STOCK_JUMP_TO, N_("_Open Account"), NULL,
+        N_("Open the account"),
+        G_CALLBACK(gnc_recn_open_cb)
+    },
+    {
+        "AccountEditAccountAction", NULL, N_("_Edit Account"), NULL,
+        N_("Edit the main account for this register"),
+        G_CALLBACK(gnc_recn_edit_account_cb)
+    },
+    {
+        "AccountTransferAction", NULL, N_("_Transfer..."), NULL,
+        N_("Transfer funds from one account to another"),
+        G_CALLBACK(gnc_recn_xfer_cb)
+    },
+    {
+        "AccountCheckRepairAction", NULL, N_("_Check & Repair"), NULL,
+        N_("Check for and repair unbalanced transactions and orphan splits "
+        "in this account"),
+        G_CALLBACK(gnc_recn_scrub_cb)
+    },
+
+    /* Transaction menu */
+
+    {
+        "TransBalanceAction", GTK_STOCK_NEW, N_("_Balance"), "<control>b",
+        N_("Add a new balancing entry to the account"),
+        G_CALLBACK(gnc_ui_reconcile_window_balance_cb)
+    },
+    {
+        "TransEditAction", GTK_STOCK_PROPERTIES, N_("_Edit"),  "<control>e",
+        N_("Edit the current transaction"),
+        G_CALLBACK(gnc_ui_reconcile_window_edit_cb)
+    },
+    {
+        "TransDeleteAction", GTK_STOCK_DELETE, N_("_Delete"),  "<control>d",
+        N_("Delete the selected transaction"),
+        G_CALLBACK(gnc_ui_reconcile_window_delete_cb)
+    },
+    {
+        "TransRecAction", GTK_STOCK_APPLY, N_("_Reconcile Selection"), "<control>r",
+        N_("Reconcile the selected transactions"),
+        G_CALLBACK(gnc_ui_reconcile_window_rec_cb)
+    },
+    {
+        "TransUnRecAction", GTK_STOCK_CLEAR, N_("_Unreconcile Selection"), "<control>u",
+        N_("Unreconcile the selected transactions"),
+        G_CALLBACK(gnc_ui_reconcile_window_unrec_cb)
+    },
+
+    /* Help menu */
+
+    {
+        "HelpHelpAction", NULL, N_("_Help"), NULL,
+        N_("Open the GnuCash help window"),
+        G_CALLBACK(gnc_ui_reconcile_window_help_cb)
+    },
+};
+
+/** The number of actions provided by the main window. */
+static guint recnWindow2_n_actions = G_N_ELEMENTS (recnWindow2_actions);

Added: gnucash/trunk/src/gnome/window-reconcile2.h
===================================================================
--- gnucash/trunk/src/gnome/window-reconcile2.h	                        (rev 0)
+++ gnucash/trunk/src/gnome/window-reconcile2.h	2013-04-07 22:14:31 UTC (rev 22885)
@@ -0,0 +1,68 @@
+/********************************************************************\
+ * window-reconcile2.h -- the reconcile window                      *
+ * Copyright (C) 1997 Robin D. Clark                                *
+ * Copyright (C) 1998-2000 Linas Vepstas                            *
+ *                                                                  *
+ * 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       *
+ * 51 Franklin Street, Fifth Floor    Fax:    +1-617-542-2652       *
+ * Boston, MA  02110-1301,  USA       gnu at gnu.org                   *
+\********************************************************************/
+
+#ifndef WINDOW_RECONCILE2_H
+#define WINDOW_RECONCILE2_H
+
+#include "Account.h"
+#include <gtk/gtk.h>
+
+
+/** STRUCTS *********************************************************/
+typedef struct _RecnWindow2 RecnWindow2;
+
+
+/** PROTOTYPES ******************************************************/
+
+/********************************************************************\
+ * recnWindow2                                                       *
+ *   opens up the window to reconcile an account                    *
+ *                                                                  *
+ * Args:   parent  - the parent of this window                      *
+ *         account - the account to reconcile                       *
+ *
+ * Return: recnData - the instance of this RecnWindow2, or NULL if the
+ * user pressed Cancel in the initial date query.
+\********************************************************************/
+RecnWindow2 *recnWindow2 (GtkWidget *parent, Account *account);
+
+/********************************************************************\
+ * recnWindow2WithBalance
+ *
+ *   Opens up the window to reconcile an account, but with ending
+ *   balance and statement date already given.
+ *
+ * Args:   parent         - The parent widget of the new window
+ *         account        - The account to reconcile
+ *         new_ending     - The amount for ending balance
+ *         statement_date - The date of the statement
+ * Return: recnData - the instance of this RecnWindow2
+\********************************************************************/
+RecnWindow2 *recnWindow2WithBalance (GtkWidget *parent,
+                                   Account *account,
+                                   gnc_numeric new_ending,
+                                   time64 statement_date);
+
+void gnc_ui_reconcile_window2_raise (RecnWindow2 * recnData);
+
+#endif /* WINDOW_RECONCILE2_H */

Modified: gnucash/trunk/src/gnome-utils/gnc-tree-control-split-reg.c
===================================================================
--- gnucash/trunk/src/gnome-utils/gnc-tree-control-split-reg.c	2013-04-07 22:14:20 UTC (rev 22884)
+++ gnucash/trunk/src/gnome-utils/gnc-tree-control-split-reg.c	2013-04-07 22:14:31 UTC (rev 22885)
@@ -159,8 +159,9 @@
 
 
 /* Transaction is being edited dialog */
-static gboolean
-gtc_trans_open_and_warn (GncTreeViewSplitReg *view, Transaction *trans)
+#define gtc_trans_open_and_warn gnc_tree_control_split_reg_trans_open_and_warn
+gboolean
+gnc_tree_control_split_reg_trans_open_and_warn (GncTreeViewSplitReg *view, Transaction *trans)
 {
     Transaction *dirty_trans;
     GtkWidget *window;
@@ -201,7 +202,8 @@
 }
 
 
-static gboolean
+#define gtc_trans_test_for_edit gnc_tree_control_split_reg_trans_test_for_edit
+gboolean
 gtc_trans_test_for_edit (GncTreeViewSplitReg *view, Transaction *trans)
 {
     GtkWidget *window;
@@ -503,6 +505,85 @@
 }
 
 
+
+#ifdef skip
+
+/**
+ * Schedules the current transaction for recurring-entry.
+ * If the selected transaction was created from a scheduled transaction,
+ * opens the editor for that Scheduled Transaction.
+ **/
+void
+gnc_tree_control_split_reg_schedule_current_trans (GncTreeViewSplitReg *view)
+{
+    Transaction *trans;
+
+    trans = gnc_tree_view_split_reg_get_current_trans (view);
+
+    if (trans == NULL)
+        return;
+
+    /* See if we were asked to schedule a blank trans. */
+    if (trans == gnc_tree_control_split_reg_get_blank_trans (view))
+        return;
+
+    /* Test for read only */
+    if (gtc_is_trans_readonly_and_warn (view, trans))
+        return;
+
+    /* See if we are being edited in another register */
+    if (gtc_trans_test_for_edit (view, trans))
+        return;
+
+    /* Make sure we ask to commit any changes before we procede */
+    if (gtc_trans_open_and_warn (view, trans))
+        return;
+
+    /* If the transaction has a sched-xact KVP frame, then go to the editor
+     * for the existing SX; otherwise, do the sx-from-trans dialog. */
+    {
+        kvp_frame *txn_frame;
+        kvp_value *kvp_val;
+        /* set a kvp-frame element in the transaction indicating and
+         * pointing-to the SX this was created from. */
+        txn_frame = xaccTransGetSlots (trans);
+        if ( txn_frame != NULL )
+        {
+            kvp_val = kvp_frame_get_slot (txn_frame, "from-sched-xaction");
+            if (kvp_val)
+            {
+                GncGUID *fromSXId = kvp_value_get_guid (kvp_val);
+                SchedXaction *theSX = NULL;
+                GList *sxElts;
+
+                /* Get the correct SX */
+                for ( sxElts = gnc_book_get_schedxactions (gnc_get_current_book())->sx_list;
+                        (!theSX) && sxElts;
+                        sxElts = sxElts->next )
+                {
+                    SchedXaction *sx = (SchedXaction*)sxElts->data;
+                    theSX =
+                        ( ( guid_equal (xaccSchedXactionGetGUID (sx), fromSXId))
+                          ? sx : NULL );
+                }
+
+                if (theSX)
+                {
+                    gnc_ui_scheduled_xaction_editor_dialog_create (theSX, FALSE);
+                    return;
+                }
+            }
+        }
+    }
+    gnc_sx_create_from_trans(pending_trans);
+}
+
+
+#endif
+
+
+
+
 /* Void current transaction */
 void
 gnc_tree_control_split_reg_void_current_trans (GncTreeViewSplitReg *view, const char *reason)
@@ -632,7 +713,7 @@
 
 /* Jump to split */
 void
-gnc_tree_control_split_reg_jump_to_split (GncTreeViewSplitReg *view, Split *split)
+gnc_tree_control_split_reg_jump_to_split (GncTreeViewSplitReg *view, Split *split, gboolean amount)
 {
     GncTreeModelSplitReg *model;
     GtkTreePath *mpath, *spath;
@@ -643,20 +724,50 @@
 
     spath = gnc_tree_view_split_reg_get_sort_path_from_model_path (view, mpath);
 
+//    gnc_tree_view_split_reg_set_current_path (view, spath);
+
     gnc_tree_view_split_reg_expand_trans (view, xaccSplitGetParent (split));
 
-    gnc_tree_view_split_reg_set_current_path (view, spath);
-
     gtk_tree_selection_select_path (gtk_tree_view_get_selection (GTK_TREE_VIEW (view)), spath);
 
-    /* Set cursor to new spath */
-    gtk_tree_view_set_cursor (GTK_TREE_VIEW (view), spath, NULL, FALSE);
+    /* Set cursor to new spath, if amount, cursor is set to correct column ready for editing */
+    if (amount)
+    {
+        GtkCellRenderer *cr0;
+        GList *renderers;
+        GList *columns;
+        GList  *column;
+        gint i;
 
+        columns = gtk_tree_view_get_columns (GTK_TREE_VIEW (view));
+
+        for (column = columns, i = 1; column; column = g_list_next (column), i++)
+        {
+            GtkTreeViewColumn *tvc;
+            ViewCol viewcol;
+
+            tvc = column->data;
+
+            // Get the first renderer, it has the view-column value.
+            renderers = gtk_cell_layout_get_cells (GTK_CELL_LAYOUT (tvc));
+            cr0 = g_list_nth_data (renderers, 0);
+            g_list_free (renderers);
+
+            viewcol = GPOINTER_TO_INT (g_object_get_data (G_OBJECT (cr0), "view_column"));
+
+            if (viewcol == COL_DEBIT && gnc_numeric_positive_p (xaccSplitGetAmount (split)))
+                gtk_tree_view_set_cursor (GTK_TREE_VIEW (view), spath, tvc, TRUE);
+
+            if (viewcol == COL_CREDIT && gnc_numeric_negative_p (xaccSplitGetAmount (split)))
+                gtk_tree_view_set_cursor (GTK_TREE_VIEW (view), spath, tvc, TRUE);
+        }
+        g_list_free (columns);
+    }
+    else
+        gtk_tree_view_set_cursor (GTK_TREE_VIEW (view), spath, NULL, FALSE);
+
     gtk_tree_path_free (spath);
     gtk_tree_path_free (mpath);
-
-    /* scroll when view idle */
-    g_idle_add ((GSourceFunc)gnc_tree_view_split_reg_scroll_to_cell, view );
 }
 
 
@@ -738,7 +849,7 @@
 
     new_spath = gtk_tree_path_new_from_indices (indices[0] + (relative * view->sort_direction), -1);
 
-    gnc_tree_view_split_reg_set_current_path (view, new_spath);
+//    gnc_tree_view_split_reg_set_current_path (view, new_spath);
 
     gnc_tree_view_split_reg_block_selection (view, TRUE);
     gtk_tree_selection_unselect_path (gtk_tree_view_get_selection (GTK_TREE_VIEW (view)), spath);
@@ -1129,7 +1240,7 @@
         gtk_main_iteration ();
 
     /* Now jump to new trans */
-    gnc_tree_control_split_reg_jump_to_split (view, xaccTransGetSplit (new_trans, 0));
+    gnc_tree_control_split_reg_jump_to_split (view, xaccTransGetSplit (new_trans, 0), FALSE);
 
     LEAVE("Reverse transaction created");
 }
@@ -1993,6 +2104,8 @@
     gtk_tree_iter_free (ma);
     gtk_tree_iter_free (mb);
 
+//FIXME this may be needed for this one (!qof_book_use_split_action_for_num_field (gnc_get_current_book()))
+
     switch (depth) {
         case 1: // Number
 
@@ -2004,7 +2117,6 @@
 
         break;
         case 2: // Action
-//FIXME this may be needed for this one (!qof_book_use_split_action_for_num_field (gnc_get_current_book()))
 
         anchor = gnc_tree_model_split_reg_get_anchor (model);
 

Modified: gnucash/trunk/src/gnome-utils/gnc-tree-control-split-reg.h
===================================================================
--- gnucash/trunk/src/gnome-utils/gnc-tree-control-split-reg.h	2013-04-07 22:14:20 UTC (rev 22884)
+++ gnucash/trunk/src/gnome-utils/gnc-tree-control-split-reg.h	2013-04-07 22:14:31 UTC (rev 22885)
@@ -35,15 +35,23 @@
 
 /*****************************************************************************/
 
+gboolean gnc_tree_control_split_reg_trans_open_and_warn (GncTreeViewSplitReg *view, Transaction *trans);
+
+gboolean gnc_tree_control_split_reg_trans_test_for_edit (GncTreeViewSplitReg *view, Transaction *trans);
+
+/*****************************************************************************/
+
 void gnc_tree_control_split_reg_exchange_rate (GncTreeViewSplitReg *view);
 
+void gnc_tree_control_split_reg_schedule_current_trans (GncTreeViewSplitReg *view);
+
 void gnc_tree_control_split_reg_void_current_trans (GncTreeViewSplitReg *view, const char *reason);
 
 void gnc_tree_control_split_reg_unvoid_current_trans (GncTreeViewSplitReg *view);
 
 void gnc_tree_control_split_reg_jump_to_blank (GncTreeViewSplitReg *view);
 
-void gnc_tree_control_split_reg_jump_to_split (GncTreeViewSplitReg *view, Split *split);
+void gnc_tree_control_split_reg_jump_to_split (GncTreeViewSplitReg *view, Split *split, gboolean amount);
 
 void gnc_tree_control_split_reg_cancel_edit (GncTreeViewSplitReg *view, gboolean reg_closing);
 

Modified: gnucash/trunk/src/gnome-utils/gnc-tree-view-split-reg.c
===================================================================
--- gnucash/trunk/src/gnome-utils/gnc-tree-view-split-reg.c	2013-04-07 22:14:20 UTC (rev 22884)
+++ gnucash/trunk/src/gnome-utils/gnc-tree-view-split-reg.c	2013-04-07 22:14:31 UTC (rev 22885)
@@ -113,32 +113,8 @@
                                              GtkTreeViewColumn *column,
                                              gpointer           user_data);
 
-
-
-
-
 static gboolean transaction_changed_confirm (GncTreeViewSplitReg *view, Transaction *new_trans);
 
-typedef enum {
-    COL_DATE,      //0
-    COL_DUEDATE,   //1
-    COL_NUMACT,    //2
-    COL_DESCNOTES, //3
-    COL_TRANSVOID, //4
-    COL_RECN,      //5
-    COL_TYPE,      //6
-    COL_VALUE,     //7
-    COL_AMOUNT,    //8
-    COL_AMTVAL,    //9
-    COL_RATE,      //10
-    COL_PRICE,     //11
-    COL_DEBIT,     //12
-    COL_CREDIT,    //13
-    COL_BALANCE,   //14
-    COL_STATUS,    //15
-    COL_COMM,      //16
-} ViewCol;
-
 typedef struct {
     ViewCol viewcol;
     gint modelcol;
@@ -628,13 +604,20 @@
         return col_list;
         }
 
-    case SEARCH_LEDGER2: //FIXME Not Setup yet
+    case SEARCH_LEDGER2:
+        {
+        static ViewCol col_list[] = {
+        COL_DATE, COL_NUMACT, COL_DESCNOTES, COL_TRANSVOID, COL_RECN,
+        COL_STATUS, COL_RATE, COL_DEBIT, COL_CREDIT, -1};
+        return col_list;
+        }
+        break;
 
     default:
         {
         static ViewCol col_list[] = {
         COL_DATE, COL_NUMACT, COL_DESCNOTES, COL_TRANSVOID, COL_RECN, COL_STATUS,
-        COL_TYPE, COL_VALUE, COL_AMOUNT, COL_RATE, COL_PRICE, COL_DEBIT, COL_CREDIT,
+        COL_VALUE, COL_AMOUNT, COL_RATE, COL_PRICE, COL_DEBIT, COL_CREDIT,
         COL_BALANCE, -1};
         return col_list;
         }
@@ -950,8 +933,6 @@
 {
     GtkTreeModel        *s_model, *f_model;
     GncTreeViewSplitReg *view;
-    GtkCellRenderer     *cr;
-    GtkTreeViewColumn   *col;
     GtkTreeSelection    *selection;
 
     gtk_rc_parse_string (rc_string);
@@ -965,7 +946,7 @@
 
     // Setup the sort model
     s_model = gtk_tree_model_sort_new_with_model (f_model);
-    g_object_unref(G_OBJECT(f_model));
+    g_object_unref(G_OBJECT (f_model));
 
     // Connect model to tree view
     gnc_tree_view_set_model (GNC_TREE_VIEW (view), s_model);
@@ -1077,18 +1058,14 @@
     gtk_tree_path_free (spath);
     gtk_tree_path_free (new_mpath);
 
-    /* give gtk+ a chance to handle pending events */
-//    while (gtk_events_pending ())
-//        gtk_main_iteration ();
-
     /* Refilter the tree view register */
     gnc_tree_view_split_reg_refilter (view);
 
     /* Set the view format */
-    g_idle_add ((GSourceFunc)gnc_tree_view_split_reg_set_format, view);
+    g_idle_add ((GSourceFunc) gnc_tree_view_split_reg_set_format, view);
 
     /* scroll window to show selection when view is idle */
-    g_idle_add ((GSourceFunc)gnc_tree_view_split_reg_scroll_to_cell, view );
+    g_idle_add ((GSourceFunc) gnc_tree_view_split_reg_scroll_to_cell, view );
 
     LEAVE(" ");
 }
@@ -2235,7 +2212,7 @@
         {
             Account *acct = xaccSplitGetAccount (split);
 
-            if ((xaccTransCountSplits (trans) == 0) && (model->type != GENERAL_LEDGER2)) // First split on blank transaction 
+            if ((xaccTransCountSplits (trans) == 0) && model->type != GENERAL_LEDGER2 && model->type != SEARCH_LEDGER2) // First split on blank transaction
                 acct = anchor;
 
             if (acct != NULL)
@@ -2248,7 +2225,7 @@
             else
                 s = "";
 
-            if (anchor == acct && model->type != GENERAL_LEDGER2)
+            if (anchor == acct && model->type != GENERAL_LEDGER2 && model->type != SEARCH_LEDGER2)
                 editable = FALSE;
             else
                 editable = TRUE;
@@ -3271,6 +3248,7 @@
     GList *columns;
     GList  *column;
     gint i;
+    RowDepth temp_depth;
 
     ENTER("title depth is %d and sort_depth %d, sort_col is %d", depth, view->sort_depth, view->sort_col);
 
@@ -3289,42 +3267,53 @@
         cr0 = g_list_nth_data (renderers, 0);
         g_list_free (renderers);
 
-        viewcol = GPOINTER_TO_INT (g_object_get_data (G_OBJECT(cr0), "view_column"));
+        viewcol = GPOINTER_TO_INT (g_object_get_data (G_OBJECT (cr0), "view_column"));
 
         DEBUG("viewcol is %d", viewcol);
 
-        switch(viewcol)
+        switch (viewcol)
         {
         case COL_DATE:
-            switch(model->type)
+            switch (model->type)
             {
             default: //FIXME These if statements may not be required
                 /* Display arrows if we are sorting on this row */
-                if (view->sort_depth == depth && view->sort_col == viewcol)
-                    gtk_tree_view_column_set_sort_indicator (tvc, TRUE);
-                else
-                    gtk_tree_view_column_set_sort_indicator (tvc, FALSE);
+                if ((depth == TRANS1 || depth == SPLIT3) && view->sort_col == viewcol)
+                {
+                    if (view->sort_depth == TRANS1 || view->sort_depth == SPLIT3)
+                        gtk_tree_view_column_set_sort_indicator (tvc, TRUE);
+                    else
+                        gtk_tree_view_column_set_sort_indicator (tvc, FALSE);
+                }
 
-                if(depth == TRANS1 || depth == SPLIT3)
+                if (depth == TRANS2 && view->sort_col == viewcol)
+                {
+                    if (view->sort_depth == TRANS2)
+                        gtk_tree_view_column_set_sort_indicator (tvc, TRUE);
+                    else
+                        gtk_tree_view_column_set_sort_indicator (tvc, FALSE);
+                }
+
+                if (depth == TRANS1 || depth == SPLIT3)
                     gtk_tree_view_column_set_title (tvc, _("Date Posted"));
-                else if(depth == TRANS2)
+                else if (depth == TRANS2)
                     gtk_tree_view_column_set_title (tvc, _("Date Entered"));
                 break;
             }
             break;
 
         case COL_DUEDATE:
-            switch(model->type)
+            switch (model->type)
             {
             default: //FIXME These if statements may not be required
-                if(depth == TRANS1 || depth == TRANS2 || depth == SPLIT3)
+                if (depth == TRANS1 || depth == TRANS2 || depth == SPLIT3)
                     gtk_tree_view_column_set_title (tvc, _("Due Date"));
                 break;
             }
             break;
 
         case COL_NUMACT:
-            switch(model->type)
+            switch (model->type)
             {
             case RECEIVABLE_REGISTER2:
             case PAYABLE_REGISTER2:
@@ -3361,10 +3350,10 @@
             break;
 
         case COL_DESCNOTES:
-            switch(model->type)
+            switch (model->type)
             {
             case RECEIVABLE_REGISTER2:
-                if(depth == TRANS1)
+                if (depth == TRANS1)
                     gtk_tree_view_column_set_title (tvc, _("Customer"));
                 else if (depth == TRANS2)
                     gtk_tree_view_column_set_title (tvc, _("Memo"));
@@ -3375,7 +3364,7 @@
                 break;
 
             case PAYABLE_REGISTER2:
-                if(depth == TRANS1)
+                if (depth == TRANS1)
                     gtk_tree_view_column_set_title (tvc, _("Vendor"));
                 else if (depth == TRANS2)
                     gtk_tree_view_column_set_title (tvc, _("Memo"));
@@ -3393,7 +3382,7 @@
                 else
                     gtk_tree_view_column_set_sort_indicator (tvc, FALSE);
 
-                if(depth == TRANS1)
+                if (depth == TRANS1)
                     gtk_tree_view_column_set_title (tvc, _("Description"));
                 else if (depth == TRANS2)
                     gtk_tree_view_column_set_title (tvc, _("Notes"));
@@ -3406,11 +3395,11 @@
             break;
 
         case COL_TRANSVOID:
-            switch(model->type)
+            switch (model->type)
             {
             case RECEIVABLE_REGISTER2:
             case PAYABLE_REGISTER2:
-                if(depth == TRANS1)
+                if (depth == TRANS1)
                     gtk_tree_view_column_set_title (tvc, _("Accounts"));
                 else if (depth == TRANS2)
                     gtk_tree_view_column_set_title (tvc, _("Accounts"));
@@ -3427,7 +3416,7 @@
                 else
                     gtk_tree_view_column_set_sort_indicator (tvc, FALSE);
 
-                if(depth == TRANS1)
+                if (depth == TRANS1)
                     gtk_tree_view_column_set_title (tvc, _("Accounts"));
                 else if (depth == TRANS2)
                     gtk_tree_view_column_set_title (tvc, _("Void Reason"));
@@ -3440,50 +3429,50 @@
             break;
 
         case COL_RECN:
-            switch(model->type)
+            switch (model->type)
             {
             default: //FIXME These if statements may not be required
-                if(depth == TRANS1 || depth == TRANS2 || depth == SPLIT3)
+                if (depth == TRANS1 || depth == TRANS2 || depth == SPLIT3)
                     gtk_tree_view_column_set_title (tvc, _("R"));
                 break;
             }
             break;
 
         case COL_TYPE:
-            switch(model->type)
+            switch (model->type)
             {
             default: //FIXME These if statements may not be required
-                if(depth == TRANS1 || depth == TRANS2 || depth == SPLIT3)
+                if (depth == TRANS1 || depth == TRANS2 || depth == SPLIT3)
                     gtk_tree_view_column_set_title (tvc, _("Type"));
                 break;
             }
             break;
 
         case COL_VALUE:
-            switch(model->type)
+            switch (model->type)
             {
             default: //FIXME These if statements may not be required
-                if(depth == TRANS1 || depth == TRANS2 || depth == SPLIT3)
+                if (depth == TRANS1 || depth == TRANS2 || depth == SPLIT3)
                     gtk_tree_view_column_set_title (tvc, _("Value"));
                 break;
             }
             break;
 
         case COL_AMOUNT:
-            switch(model->type)
+            switch (model->type)
             {
             default: //FIXME These if statements may not be required
-                if(depth == TRANS1 || depth == TRANS2 || depth == SPLIT3)
+                if (depth == TRANS1 || depth == TRANS2 || depth == SPLIT3)
                     gtk_tree_view_column_set_title (tvc, _("Amount"));
                 break;
             }
             break;
 
         case COL_AMTVAL:
-            switch(model->type)
+            switch (model->type)
             {
             default:
-                if((depth == TRANS1) || (depth == TRANS2))
+                if (depth == TRANS1 || depth == TRANS2)
                     gtk_tree_view_column_set_title (tvc, _("Value"));
                 else if (depth == SPLIT3)
                     gtk_tree_view_column_set_title (tvc, _("Amount"));
@@ -3494,30 +3483,30 @@
             break;
 
         case COL_COMM:
-            switch(model->type)
+            switch (model->type)
             {
             default: //FIXME These if statements may not be required
-                if(depth == TRANS1 || depth == TRANS2 || depth == SPLIT3)
+                if (depth == TRANS1 || depth == TRANS2 || depth == SPLIT3)
                     gtk_tree_view_column_set_title (tvc, _("Commodity"));
                 break;
             }
             break;
 
         case COL_RATE:
-            switch(model->type)
+            switch (model->type)
             {
             default: //FIXME These if statements may not be required
-                if(depth == TRANS1 || depth == TRANS2 || depth == SPLIT3)
+                if (depth == TRANS1 || depth == TRANS2 || depth == SPLIT3)
                     gtk_tree_view_column_set_title (tvc, _("Rate"));
                 break;
             }
             break;
 
         case COL_PRICE:
-            switch(model->type)
+            switch (model->type)
             {
             default: //FIXME These if statements may not be required
-                if(depth == TRANS1 || depth == TRANS2 || depth == SPLIT3)
+                if (depth == TRANS1 || depth == TRANS2 || depth == SPLIT3)
                     gtk_tree_view_column_set_title (tvc, _("Price"));
                 break;
             }
@@ -3526,70 +3515,70 @@
         case COL_CREDIT:
             if(!(model->use_accounting_labels))
             {
-                switch(model->type)
+                switch (model->type)
                 {
                 case BANK_REGISTER2: //FIXME These if statements may not be required
-                if(depth == TRANS1 || depth == TRANS2 || depth == SPLIT3)
+                if (depth == TRANS1 || depth == TRANS2 || depth == SPLIT3)
                         gtk_tree_view_column_set_title (tvc, _("Withdrawl"));
                     break;
 
                 case CASH_REGISTER2:
-                if(depth == TRANS1 || depth == TRANS2 || depth == SPLIT3)
+                if (depth == TRANS1 || depth == TRANS2 || depth == SPLIT3)
                         gtk_tree_view_column_set_title (tvc, _("Spend"));
                     break;
 
                 case ASSET_REGISTER2:
-                if(depth == TRANS1 || depth == TRANS2 || depth == SPLIT3)
+                if (depth == TRANS1 || depth == TRANS2 || depth == SPLIT3)
                         gtk_tree_view_column_set_title (tvc, _("Decrease"));
                     break;
 
                 case LIABILITY_REGISTER2:
                 case EQUITY_REGISTER2:
                 case TRADING_REGISTER2:
-                if(depth == TRANS1 || depth == TRANS2 || depth == SPLIT3)
+                if (depth == TRANS1 || depth == TRANS2 || depth == SPLIT3)
                         gtk_tree_view_column_set_title (tvc, _("Increase"));
                     break;
 
                 case CREDIT_REGISTER2:
-                if(depth == TRANS1 || depth == TRANS2 || depth == SPLIT3)
+                if (depth == TRANS1 || depth == TRANS2 || depth == SPLIT3)
                         gtk_tree_view_column_set_title (tvc, _("Charge"));
                     break;
 
                 case INCOME_REGISTER2:
                 case INCOME_LEDGER2:
-                if(depth == TRANS1 || depth == TRANS2 || depth == SPLIT3)
+                if (depth == TRANS1 || depth == TRANS2 || depth == SPLIT3)
                         gtk_tree_view_column_set_title (tvc, _("Income"));
                     break;
 
                 case EXPENSE_REGISTER2:
-                if(depth == TRANS1 || depth == TRANS2 || depth == SPLIT3)
+                if (depth == TRANS1 || depth == TRANS2 || depth == SPLIT3)
                         gtk_tree_view_column_set_title (tvc, _("Rebate"));
                     break;
 
                 case STOCK_REGISTER2:
                 case CURRENCY_REGISTER2:
                 case PORTFOLIO_LEDGER2:
-                if(depth == TRANS1 || depth == TRANS2 || depth == SPLIT3)
+                if (depth == TRANS1 || depth == TRANS2 || depth == SPLIT3)
                         gtk_tree_view_column_set_title (tvc, _("Sell"));
                     break;
 
                 case RECEIVABLE_REGISTER2:
-                if(depth == TRANS1 || depth == TRANS2 || depth == SPLIT3)
+                if (depth == TRANS1 || depth == TRANS2 || depth == SPLIT3)
                         gtk_tree_view_column_set_title (tvc, _("Payment"));
                     break;
 
                 case PAYABLE_REGISTER2:
-                if(depth == TRANS1 || depth == TRANS2 || depth == SPLIT3)
+                if (depth == TRANS1 || depth == TRANS2 || depth == SPLIT3)
                         gtk_tree_view_column_set_title (tvc, _("Bill"));
                     break;
 
                 case GENERAL_LEDGER2:
-                if(depth == TRANS1 || depth == TRANS2 || depth == SPLIT3)
+                if (depth == TRANS1 || depth == TRANS2 || depth == SPLIT3)
                         gtk_tree_view_column_set_title (tvc, _("Funds Out"));
                     break;
 
                 default:
-                    if(depth == TRANS1 || depth == TRANS2 || depth == SPLIT3)
+                    if (depth == TRANS1 || depth == TRANS2 || depth == SPLIT3)
                         gtk_tree_view_column_set_title (tvc, _("Credit"));
                     break;
                 }
@@ -3601,66 +3590,66 @@
         case COL_DEBIT:
             if(!(model->use_accounting_labels))
             {
-                switch(model->type)
+                switch (model->type)
                 {
                 case BANK_REGISTER2: //FIXME These if statements may not be required
-                if(depth == TRANS1 || depth == TRANS2 || depth == SPLIT3)
+                if (depth == TRANS1 || depth == TRANS2 || depth == SPLIT3)
                         gtk_tree_view_column_set_title (tvc, _("Deposit"));
                     break;
 
                 case CASH_REGISTER2:
-                if(depth == TRANS1 || depth == TRANS2 || depth == SPLIT3)
+                if (depth == TRANS1 || depth == TRANS2 || depth == SPLIT3)
                         gtk_tree_view_column_set_title (tvc, _("Receive"));
                     break;
 
                 case ASSET_REGISTER2:
-                if(depth == TRANS1 || depth == TRANS2 || depth == SPLIT3)
+                if (depth == TRANS1 || depth == TRANS2 || depth == SPLIT3)
                         gtk_tree_view_column_set_title (tvc, _("Increase"));
                     break;
 
                 case LIABILITY_REGISTER2:
                 case EQUITY_REGISTER2:
                 case TRADING_REGISTER2:
-                if(depth == TRANS1 || depth == TRANS2 || depth == SPLIT3)
+                if (depth == TRANS1 || depth == TRANS2 || depth == SPLIT3)
                         gtk_tree_view_column_set_title (tvc, _("Decrease"));
                     break;
 
                 case INCOME_REGISTER2:
                 case INCOME_LEDGER2:
-                if(depth == TRANS1 || depth == TRANS2 || depth == SPLIT3)
+                if (depth == TRANS1 || depth == TRANS2 || depth == SPLIT3)
                         gtk_tree_view_column_set_title (tvc, _("Charge"));
                     break;
 
                 case EXPENSE_REGISTER2:
-                if(depth == TRANS1 || depth == TRANS2 || depth == SPLIT3)
+                if (depth == TRANS1 || depth == TRANS2 || depth == SPLIT3)
                         gtk_tree_view_column_set_title (tvc, _("Expense"));
                     break;
 
                 case STOCK_REGISTER2:
                 case CURRENCY_REGISTER2:
                 case PORTFOLIO_LEDGER2:
-                if(depth == TRANS1 || depth == TRANS2 || depth == SPLIT3)
+                if (depth == TRANS1 || depth == TRANS2 || depth == SPLIT3)
                         gtk_tree_view_column_set_title (tvc, _("Buy"));
                     break;
 
                 case RECEIVABLE_REGISTER2:
-                if(depth == TRANS1 || depth == TRANS2 || depth == SPLIT3)
+                if (depth == TRANS1 || depth == TRANS2 || depth == SPLIT3)
                         gtk_tree_view_column_set_title (tvc, _("Invoice"));
                     break;
 
                 case CREDIT_REGISTER2:
                 case PAYABLE_REGISTER2:
-                if(depth == TRANS1 || depth == TRANS2 || depth == SPLIT3)
+                if (depth == TRANS1 || depth == TRANS2 || depth == SPLIT3)
                         gtk_tree_view_column_set_title (tvc, _("Payment"));
                     break;
 
                 case GENERAL_LEDGER2:
-                if(depth == TRANS1 || depth == TRANS2 || depth == SPLIT3)
+                if (depth == TRANS1 || depth == TRANS2 || depth == SPLIT3)
                         gtk_tree_view_column_set_title (tvc, _("Funds In"));
                     break;
 
                 default:
-                if(depth == TRANS1 || depth == TRANS2 || depth == SPLIT3)
+                if (depth == TRANS1 || depth == TRANS2 || depth == SPLIT3)
                         gtk_tree_view_column_set_title (tvc, _("Debit"));
                     break;
                 }
@@ -3670,10 +3659,10 @@
             break;
 
         case COL_BALANCE:
-            switch(model->type)
+            switch (model->type)
             {
             default: //FIXME These if statements may not be required
-                if(depth == TRANS1 || depth == TRANS2 || depth == SPLIT3)
+                if (depth == TRANS1 || depth == TRANS2 || depth == SPLIT3)
                     gtk_tree_view_column_set_title (tvc, _("Balance"));
                 break;
             }
@@ -3975,7 +3964,6 @@
 }
 
 
-
 /* Call back for when a change to a filter requires the selection to get out of the way */
 static void
 gtv_split_reg_selection_move_filter_cb (GncTreeModelSplitReg *model, gpointer item, gpointer user_data)
@@ -4185,7 +4173,7 @@
                 view->priv->current_ref = gtk_tree_row_reference_copy (view->priv->edit_ref);
 
                 // Jump to the first split of dirty_trans.
-                gnc_tree_control_split_reg_jump_to_split (view, xaccTransGetSplit (view->priv->dirty_trans, 0));
+                gnc_tree_control_split_reg_jump_to_split (view, xaccTransGetSplit (view->priv->dirty_trans, 0), FALSE);
 
                 /* Remove the blank split and re-add - done so we keep it last in list */ 
                 gnc_tree_model_split_reg_set_blank_split_parent (model, view->priv->dirty_trans, TRUE);
@@ -4233,7 +4221,6 @@
     RowDepth depth = 0;
     GtkTreeIter m_iter;
 
-
 //g_print ("\n** gtv_split_reg_motion_cb start\n");
 
     model = gnc_tree_view_split_reg_get_model_from_view (view);
@@ -4302,7 +4289,7 @@
             view->priv->current_ref = gtk_tree_row_reference_copy (view->priv->edit_ref);
 
             // Jump to the first split of dirty_trans.
-            gnc_tree_control_split_reg_jump_to_split (view, xaccTransGetSplit (view->priv->dirty_trans, 0));
+            gnc_tree_control_split_reg_jump_to_split (view, xaccTransGetSplit (view->priv->dirty_trans, 0), FALSE);
 
             /* Remove the blank split and re-add - done so we keep it last in list */ 
             gnc_tree_model_split_reg_set_blank_split_parent (model, view->priv->dirty_trans, TRUE);
@@ -4316,7 +4303,6 @@
 
                 gnc_tree_view_split_reg_expand_trans (view, NULL);
 //            }
-
             return;
         }
         else
@@ -4333,7 +4319,6 @@
         view->priv->current_depth = depth;
 
 //g_print("Motion - ** view->priv-> c_trans is %p c_split is %p depth %d **\n\n", view->priv->current_trans, view->priv->current_split, view->priv->current_depth);
-
         /* Auto expand transaction and collapse previous transaction */
         if (old_trans != trans)
         {
@@ -4359,6 +4344,12 @@
             }
         }
         gtk_tree_path_free (spath);
+
+        // Check to see if current trans is expanded and set appropiately
+        if (gnc_tree_view_split_reg_trans_expanded (view, trans))
+                view->priv->expanded = TRUE;
+        else
+                view->priv->expanded = FALSE;
     }
     else
     {
@@ -4372,7 +4363,6 @@
         /* Set the default selection start position */
         gnc_tree_view_split_reg_default_selection (view);
     }
-
     /* This updates the plugin page gui */
     if (view->moved_cb)
         (view->moved_cb)(view, view->moved_cb_data);
@@ -4666,7 +4656,10 @@
             if (is_blank)
             {
                 /*FIXME May be this should be a signal - Promote the blank split to a real split */
-                g_idle_add ((GSourceFunc)gnc_tree_model_split_reg_commit_blank_split, gnc_tree_view_split_reg_get_model_from_view (view));
+                g_idle_add ((GSourceFunc) gnc_tree_model_split_reg_commit_blank_split, gnc_tree_view_split_reg_get_model_from_view (view));
+
+                /* scroll when view idle */
+                g_idle_add ((GSourceFunc) gnc_tree_view_split_reg_scroll_to_cell, view);
             }
 
             // In transaction mode, two splits only, set up the other split.
@@ -5276,22 +5269,26 @@
     GtkTreePath *mpath, *spath;
 
     model = gnc_tree_view_split_reg_get_model_from_view (view);
-//FIXME needs more work...
+//FIXME This may all reduce to a single scroll_to_cell...
     mpath = gnc_tree_view_split_reg_get_current_path (view);
     spath = gnc_tree_view_split_reg_get_sort_path_from_model_path (view, mpath);
 
     if (view->sort_direction == 1)
-        gtk_tree_view_scroll_to_cell (GTK_TREE_VIEW (view), spath, NULL, TRUE, 0.0, 0.0);
+    {
+        gtk_tree_view_scroll_to_cell (GTK_TREE_VIEW (view), spath, NULL, TRUE, 0.5, 0.0); //0.0
+    }
     else
     {
         if (model->use_double_line)
         {
             gtk_tree_path_down (spath); // move to the second row of transaction
-            gtk_tree_view_scroll_to_cell (GTK_TREE_VIEW (view), spath, NULL, TRUE, 1.0, 0.0);
+            gtk_tree_view_scroll_to_cell (GTK_TREE_VIEW (view), spath, NULL, TRUE, 0.5, 0.0); //1.0
             gtk_tree_path_up (spath); // back to first row of transaction
         }
         else
-            gtk_tree_view_scroll_to_cell (GTK_TREE_VIEW (view), spath, NULL, TRUE, 1.0, 0.0);
+        {
+            gtk_tree_view_scroll_to_cell (GTK_TREE_VIEW (view), spath, NULL, TRUE, 0.5, 0.0); //1.0
+        }
     }
     gtk_tree_path_free (mpath);
     gtk_tree_path_free (spath);
@@ -5383,16 +5380,20 @@
 
     model = gnc_tree_view_split_reg_get_model_from_view (view);
 
-    if(view->priv->current_ref != NULL)
+//FIXME I am not sure this function is needed, it is usualy followed by set selection which
+//      will do this any way ?????
+
+    if (view->priv->current_ref != NULL)
     {
         gtk_tree_row_reference_free (view->priv->current_ref);
         view->priv->current_ref = NULL;
     }
     view->priv->current_ref = gtk_tree_row_reference_new (GTK_TREE_MODEL (model), path);
 
-    view->priv->current_trans = gnc_tree_view_split_reg_get_current_trans (view);
-    view->priv->current_split = gnc_tree_view_split_reg_get_current_split (view);
-    view->priv->current_depth = gnc_tree_view_reg_get_selected_row_depth (view);
+//FIXME this is crap - not needed...
+//    view->priv->current_trans = gnc_tree_view_split_reg_get_current_trans (view);
+//    view->priv->current_split = gnc_tree_view_split_reg_get_current_split (view);
+//    view->priv->current_depth = gnc_tree_view_reg_get_selected_row_depth (view);
 }
 
 
@@ -5505,7 +5506,7 @@
     if (GPOINTER_TO_INT (g_object_get_data (G_OBJECT (view), "data-edited")) && transaction_changed_confirm (view, NULL))
     {
         // Jump to the first split of dirty_trans.
-        gnc_tree_control_split_reg_jump_to_split (view, xaccTransGetSplit (view->priv->dirty_trans, 0)); 
+        gnc_tree_control_split_reg_jump_to_split (view, xaccTransGetSplit (view->priv->dirty_trans, 0), FALSE); 
 
         /* Remove the blank split and re-add - done so we keep it last in list */ 
         gnc_tree_model_split_reg_set_blank_split_parent (model, view->priv->dirty_trans, TRUE);
@@ -5606,6 +5607,7 @@
         spath = gnc_tree_view_split_reg_get_sort_path_from_model_path (view, mpath);
 
         gtk_tree_path_down (spath); /* Move the path down to trow2 */
+
         expanded = gtk_tree_view_row_expanded (GTK_TREE_VIEW (view), spath);
 
         gtk_tree_path_free (mpath);
@@ -5737,6 +5739,9 @@
     if (view->moved_cb)
         (view->moved_cb)(view, view->moved_cb_data);
 
+    /* scroll when view idle */
+    g_idle_add ((GSourceFunc) gnc_tree_view_split_reg_scroll_to_cell, view);
+
     LEAVE(" ");
 }
 

Modified: gnucash/trunk/src/gnome-utils/gnc-tree-view-split-reg.h
===================================================================
--- gnucash/trunk/src/gnome-utils/gnc-tree-view-split-reg.h	2013-04-07 22:14:20 UTC (rev 22884)
+++ gnucash/trunk/src/gnome-utils/gnc-tree-view-split-reg.h	2013-04-07 22:14:31 UTC (rev 22885)
@@ -86,6 +86,25 @@
     SPLIT3, //3
 }RowDepth;
 
+typedef enum {
+    COL_DATE,      //0
+    COL_DUEDATE,   //1
+    COL_NUMACT,    //2
+    COL_DESCNOTES, //3
+    COL_TRANSVOID, //4
+    COL_RECN,      //5
+    COL_TYPE,      //6
+    COL_VALUE,     //7
+    COL_AMOUNT,    //8
+    COL_AMTVAL,    //9
+    COL_RATE,      //10
+    COL_PRICE,     //11
+    COL_DEBIT,     //12
+    COL_CREDIT,    //13
+    COL_BALANCE,   //14
+    COL_STATUS,    //15
+    COL_COMM,      //16
+} ViewCol;
 
 /* Standard g_object type */
 GType gnc_tree_view_split_reg_get_type (void);

Modified: gnucash/trunk/src/register/ledger-core/gnc-ledger-display2.c
===================================================================
--- gnucash/trunk/src/register/ledger-core/gnc-ledger-display2.c	2013-04-07 22:14:20 UTC (rev 22884)
+++ gnucash/trunk/src/register/ledger-core/gnc-ledger-display2.c	2013-04-07 22:14:31 UTC (rev 22885)
@@ -437,7 +437,7 @@
 
     ENTER(" ");
 
-    query = qof_query_create_for(GNC_ID_SPLIT);
+    query = qof_query_create_for (GNC_ID_SPLIT);
 
     qof_query_set_book (query, gnc_get_current_book());
 
@@ -826,8 +826,9 @@
 
     gnc_tree_model_split_reg_set_data (ld->model, ld, gnc_ledger_display2_parent);
 
-//FIXME Not Needed ?    g_signal_connect (G_OBJECT (ld->model), "refresh_signal",
-//                      G_CALLBACK ( gnc_ledger_display2_refresh_cb ), ld );
+    // This sets up a call back for the search_ledger2 to reload after changes
+    g_signal_connect (G_OBJECT (ld->model), "refresh_view",
+                      G_CALLBACK (gnc_ledger_display2_refresh_cb), ld );
 
     splits = qof_query_run (ld->query);
 
@@ -871,12 +872,36 @@
 GNCLedgerDisplay2 *
 gnc_ledger_display2_find_by_query (Query *q)
 {
+    GNCLedgerDisplay2 *ledger_display;
+    GncTreeModelSplitReg *model;
+
     if (!q)
         return NULL;
 
+    ledger_display = gnc_find_first_gui_component (REGISTER_GL_CM_CLASS, find_by_query, q);
+
+    if (ledger_display)
+    {
+        model = ledger_display->model;
+        // To get a new search page from a general ledger, search register is a LD2_GL also.
+        if (model->type == GENERAL_LEDGER2)
+            ledger_display = NULL;
+    }
+    return ledger_display;
+}
+
+#ifdef skip
+GNCLedgerDisplay2 *
+gnc_ledger_display2_find_by_query (Query *q)
+{
+    if (!q)
+        return NULL;
+
     return gnc_find_first_gui_component (REGISTER_GL_CM_CLASS, find_by_query, q);
 }
+#endif
 
+
 /********************************************************************\
  * refresh only the indicated register window                       *
 \********************************************************************/
@@ -884,6 +909,8 @@
 static void
 gnc_ledger_display2_refresh_internal (GNCLedgerDisplay2 *ld, GList *splits)
 {
+    GtkTreeModel *s_model, *f_model, *model;
+
     if (!ld || ld->loading)
         return;
 
@@ -895,11 +922,33 @@
     }
     else
     {
+	/* This is used for the reloading of registers to refresh them and to update the search_ledger */
         ld->loading = TRUE;
+	s_model = gtk_tree_view_get_model (GTK_TREE_VIEW (ld->view)); // this is the sort model
+        f_model = gtk_tree_model_sort_get_model (GTK_TREE_MODEL_SORT (s_model)); // this is the filter model
+        model = gtk_tree_model_filter_get_model (GTK_TREE_MODEL_FILTER (f_model)); // our model
 
+        g_object_ref (s_model);
+        g_object_ref (f_model);
+        g_object_ref (model);
+
+        gnc_tree_view_split_reg_block_selection (ld->view, TRUE); // This blocks the tree selection
+	
+        gtk_tree_view_set_model (GTK_TREE_VIEW (ld->view), NULL); // Detach sort model from view
+	
+        gnc_tree_model_split_reg_load (ld->model, splits, gnc_ledger_display2_leader (ld)); //reload splits
+
+        gtk_tree_view_set_model (GTK_TREE_VIEW (ld->view), GTK_TREE_MODEL (s_model)); // Re-attach sort model to view
+
+        gnc_tree_view_split_reg_block_selection (ld->view, FALSE); // This unblocks the tree selection
+
         /* Set the default selection start position */
         gnc_tree_view_split_reg_default_selection (ld->view);
 
+        g_object_unref (model);
+        g_object_unref (f_model);
+        g_object_unref (s_model);
+
         ld->loading = FALSE;
     }
 }
@@ -985,13 +1034,15 @@
     ld->refresh_ok = ok;
 }
 
+/* This is used for the search_ledger2 reload after any changes made */
 static void
 gnc_ledger_display2_refresh_cb (GncTreeModelSplitReg *model, gpointer user_data)
 {
     GNCLedgerDisplay2 *ld = user_data;
 
-    /* Refresh the view when idle */
-    g_idle_add ((GSourceFunc)gnc_ledger_display2_refresh, ld);
+    if (model->type == SEARCH_LEDGER2)
+        /* Refresh the view when idle */
+        g_idle_add ((GSourceFunc)gnc_ledger_display2_refresh, ld);
 }
 
 void



More information about the gnucash-changes mailing list