"Fossies" - the Fresh Open Source Software Archive

Member "gnucash-3.7/gnucash/register/ledger-core/split-register.c" (7 Sep 2019, 101553 Bytes) of package /linux/misc/gnucash-3.7.tar.bz2:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file. For more information about "split-register.c" see the Fossies "Dox" file reference documentation and the latest Fossies "Diffs" side-by-side code changes report: 3.6_vs_3.7.

    1 /********************************************************************\
    2  * This program is free software; you can redistribute it and/or    *
    3  * modify it under the terms of the GNU General Public License as   *
    4  * published by the Free Software Foundation; either version 2 of   *
    5  * the License, or (at your option) any later version.              *
    6  *                                                                  *
    7  * This program is distributed in the hope that it will be useful,  *
    8  * but WITHOUT ANY WARRANTY; without even the implied warranty of   *
    9  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the    *
   10  * GNU General Public License for more details.                     *
   11  *                                                                  *
   12  * You should have received a copy of the GNU General Public License*
   13  * along with this program; if not, contact:                        *
   14  *                                                                  *
   15  * Free Software Foundation           Voice:  +1-617-542-5942       *
   16  * 51 Franklin Street, Fifth Floor    Fax:    +1-617-542-2652       *
   17  * Boston, MA  02110-1301,  USA       gnu@gnu.org                   *
   18  *                                                                  *
   19 \********************************************************************/
   20 /*
   21  * split-register.c
   22  * author Copyright (c) 1998-2000 Linas Vepstas <linas@linas.org>
   23  * author Copyright (c) 2000-2001 Dave Peticolas <dave@krondo.com>
   24  * author Copyright (c) 2017 Aaron Laws
   25  */
   26 #include <config.h>
   27 
   28 #include <glib.h>
   29 #include <glib/gi18n.h>
   30 #include <libguile.h>
   31 
   32 #include "combocell.h"
   33 #include "datecell.h"
   34 #include "dialog-utils.h"
   35 #include "gnc-component-manager.h"
   36 #include "split-register-p.h"
   37 #include "gnc-date.h"
   38 #include "gnc-ledger-display.h"
   39 #include "gnc-prefs.h"
   40 #include "gnc-ui.h"
   41 #include "gnc-warnings.h"
   42 #include "guile-util.h"
   43 #include "numcell.h"
   44 #include "pricecell.h"
   45 #include "quickfillcell.h"
   46 #include "recncell.h"
   47 #include "split-register.h"
   48 #include "split-register-control.h"
   49 #include "split-register-layout.h"
   50 #include "split-register-model.h"
   51 #include "split-register-model-save.h"
   52 #include "table-allgui.h"
   53 #include "dialog-account.h"
   54 #include "dialog-dup-trans.h"
   55 #include "engine-helpers.h"
   56 #include "qofbookslots.h"
   57 
   58 
   59 /** static variables ******************************************************/
   60 
   61 /* This static indicates the debugging module that this .o belongs to. */
   62 static QofLogModule log_module = GNC_MOD_LEDGER;
   63 
   64 /* The copied split or transaction, if any */
   65 static CursorClass copied_class = CURSOR_CLASS_NONE;
   66 static SCM copied_item = SCM_UNDEFINED;
   67 static GncGUID copied_leader_guid;
   68 /** static prototypes *****************************************************/
   69 
   70 static gboolean gnc_split_register_save_to_scm (SplitRegister *reg,
   71         SCM trans_scm, SCM split_scm,
   72         gboolean use_cut_semantics);
   73 static gboolean gnc_split_register_auto_calc (SplitRegister *reg,
   74         Split *split);
   75 
   76 
   77 /** implementations *******************************************************/
   78 
   79 /* Uses the scheme split copying routines */
   80 static void
   81 gnc_copy_split_onto_split(Split *from, Split *to, gboolean use_cut_semantics)
   82 {
   83     SCM split_scm;
   84 
   85     if ((from == NULL) || (to == NULL))
   86         return;
   87 
   88     split_scm = gnc_copy_split(from, use_cut_semantics);
   89     if (split_scm == SCM_UNDEFINED)
   90         return;
   91 
   92     gnc_copy_split_scm_onto_split(split_scm, to, gnc_get_current_book ());
   93 }
   94 
   95 /* Uses the scheme transaction copying routines */
   96 void
   97 gnc_copy_trans_onto_trans(Transaction *from, Transaction *to,
   98                           gboolean use_cut_semantics,
   99                           gboolean do_commit)
  100 {
  101     SCM trans_scm;
  102 
  103     if ((from == NULL) || (to == NULL))
  104         return;
  105 
  106     trans_scm = gnc_copy_trans(from, use_cut_semantics);
  107     if (trans_scm == SCM_UNDEFINED)
  108         return;
  109 
  110     gnc_copy_trans_scm_onto_trans(trans_scm, to, do_commit,
  111                                   gnc_get_current_book ());
  112 }
  113 
  114 static int
  115 gnc_split_get_value_denom (Split *split)
  116 {
  117     gnc_commodity *currency;
  118     int denom;
  119 
  120     currency = xaccTransGetCurrency (xaccSplitGetParent (split));
  121     denom = gnc_commodity_get_fraction (currency);
  122     if (denom == 0)
  123     {
  124         gnc_commodity *commodity = gnc_default_currency ();
  125         denom = gnc_commodity_get_fraction (commodity);
  126         if (denom == 0)
  127             denom = 100;
  128     }
  129 
  130     return denom;
  131 }
  132 
  133 static int
  134 gnc_split_get_amount_denom (Split *split)
  135 {
  136     int denom;
  137 
  138     denom = xaccAccountGetCommoditySCU (xaccSplitGetAccount (split));
  139     if (denom == 0)
  140     {
  141         gnc_commodity *commodity = gnc_default_currency ();
  142         denom = gnc_commodity_get_fraction (commodity);
  143         if (denom == 0)
  144             denom = 100;
  145     }
  146 
  147     return denom;
  148 }
  149 
  150 /* returns TRUE if begin_edit was aborted */
  151 gboolean
  152 gnc_split_register_begin_edit_or_warn(SRInfo *info, Transaction *trans)
  153 {
  154     ENTER("info=%p, trans=%p", info, trans);
  155 
  156     if (!xaccTransIsOpen(trans))
  157     {
  158         xaccTransBeginEdit(trans);
  159         /* This is now the pending transaction */
  160         info->pending_trans_guid = *xaccTransGetGUID(trans);
  161         LEAVE("opened and marked pending");
  162         return FALSE;
  163     }
  164     else
  165     {
  166         Split       *blank_split = xaccSplitLookup (&info->blank_split_guid,
  167                                    gnc_get_current_book ());
  168         Transaction *blank_trans = xaccSplitGetParent (blank_split);
  169 
  170         if (trans == blank_trans)
  171         {
  172             /* This is a brand-new transaction. It is already
  173              * open, so just mark it as pending. */
  174             info->pending_trans_guid = *xaccTransGetGUID(trans);
  175             LEAVE("already open, now pending.");
  176             return FALSE;
  177         }
  178         else
  179         {
  180             GtkWindow *parent = NULL;
  181             if (info->get_parent)
  182                 parent = GTK_WINDOW (info->get_parent (info->user_data));
  183             gnc_error_dialog(parent, "%s", _("This transaction is already being edited in another register. Please finish editing it there first."));
  184             LEAVE("already editing");
  185             return TRUE;
  186         }
  187     }
  188     LEAVE(" ");
  189     return FALSE;  /* to satisfy static code analysis */
  190 }
  191 
  192 void
  193 gnc_split_register_expand_current_trans (SplitRegister *reg, gboolean expand)
  194 {
  195     SRInfo *info = gnc_split_register_get_info (reg);
  196     VirtualLocation virt_loc;
  197 
  198     if (!reg)
  199         return;
  200 
  201     if (reg->style == REG_STYLE_AUTO_LEDGER ||
  202             reg->style == REG_STYLE_JOURNAL)
  203         return;
  204 
  205     /* ok, so I just wanted an excuse to use exclusive-or */
  206     if (!(expand ^ info->trans_expanded))
  207         return;
  208 
  209     if (!expand)
  210     {
  211         virt_loc = reg->table->current_cursor_loc;
  212         gnc_split_register_get_trans_split (reg, virt_loc.vcell_loc,
  213                                             &virt_loc.vcell_loc);
  214 
  215         if (gnc_table_find_close_valid_cell (reg->table, &virt_loc, FALSE))
  216             gnc_table_move_cursor_gui (reg->table, virt_loc);
  217         else
  218         {
  219             PERR ("Can't find place to go!");
  220             return;
  221         }
  222     }
  223 
  224     info->trans_expanded = expand;
  225 
  226     gnc_table_set_virt_cell_cursor (reg->table,
  227                                     reg->table->current_cursor_loc.vcell_loc,
  228                                     gnc_split_register_get_active_cursor (reg));
  229 
  230     gnc_split_register_set_trans_visible(
  231         reg, reg->table->current_cursor_loc.vcell_loc, expand, FALSE);
  232 
  233     virt_loc = reg->table->current_cursor_loc;
  234     if (!expand || !gnc_table_virtual_loc_valid (reg->table, virt_loc, FALSE))
  235     {
  236         if (gnc_table_find_close_valid_cell (reg->table, &virt_loc, FALSE))
  237             gnc_table_move_cursor_gui (reg->table, virt_loc);
  238         else
  239         {
  240             PERR ("Can't find place to go!");
  241             return;
  242         }
  243     }
  244 
  245     gnc_table_refresh_gui (reg->table, TRUE);
  246 
  247     if (expand)
  248         gnc_split_register_show_trans (reg,
  249                                        reg->table->current_cursor_loc.vcell_loc);
  250 }
  251 
  252 gboolean
  253 gnc_split_register_current_trans_expanded (SplitRegister *reg)
  254 {
  255     SRInfo *info = gnc_split_register_get_info (reg);
  256 
  257     if (!reg)
  258         return FALSE;
  259 
  260     if (reg->style == REG_STYLE_AUTO_LEDGER ||
  261             reg->style == REG_STYLE_JOURNAL)
  262         return TRUE;
  263 
  264     return info->trans_expanded;
  265 }
  266 
  267 Transaction *
  268 gnc_split_register_get_current_trans (SplitRegister *reg)
  269 {
  270     Split *split;
  271     VirtualCellLocation vcell_loc;
  272 
  273     if (reg == NULL)
  274         return NULL;
  275 
  276     split = gnc_split_register_get_current_split (reg);
  277     if (split != NULL)
  278         return xaccSplitGetParent(split);
  279 
  280     /* Split is blank. Assume it is the blank split of a multi-line
  281      * transaction. Go back one row to find a split in the transaction. */
  282     vcell_loc = reg->table->current_cursor_loc.vcell_loc;
  283 
  284     vcell_loc.virt_row--;
  285 
  286     split = gnc_split_register_get_split (reg, vcell_loc);
  287 
  288     return xaccSplitGetParent (split);
  289 }
  290 
  291 Split *
  292 gnc_split_register_get_current_split (SplitRegister *reg)
  293 {
  294     if (reg == NULL)
  295         return NULL;
  296 
  297     return gnc_split_register_get_split(
  298                reg, reg->table->current_cursor_loc.vcell_loc);
  299 }
  300 
  301 Split *
  302 gnc_split_register_get_blank_split (SplitRegister *reg)
  303 {
  304     SRInfo *info = gnc_split_register_get_info (reg);
  305 
  306     if (!reg) return NULL;
  307 
  308     return xaccSplitLookup (&info->blank_split_guid, gnc_get_current_book ());
  309 }
  310 
  311 gboolean
  312 gnc_split_register_get_split_virt_loc (SplitRegister *reg, Split *split,
  313                                        VirtualCellLocation *vcell_loc)
  314 {
  315     Table *table;
  316     int v_row;
  317     int v_col;
  318 
  319     if (!reg || !split) return FALSE;
  320 
  321     table = reg->table;
  322 
  323     /* go backwards because typically you search for splits at the end
  324      * and because we find split rows before transaction rows. */
  325 
  326     for (v_row = table->num_virt_rows - 1; v_row > 0; v_row--)
  327         for (v_col = 0; v_col < table->num_virt_cols; v_col++)
  328         {
  329             VirtualCellLocation vc_loc = { v_row, v_col };
  330             VirtualCell *vcell;
  331             Split *s;
  332 
  333             vcell = gnc_table_get_virtual_cell (table, vc_loc);
  334             if (!vcell || !vcell->visible)
  335                 continue;
  336 
  337             s = xaccSplitLookup (vcell->vcell_data, gnc_get_current_book ());
  338 
  339             if (s == split)
  340             {
  341                 if (vcell_loc)
  342                     *vcell_loc = vc_loc;
  343 
  344                 return TRUE;
  345             }
  346         }
  347 
  348     return FALSE;
  349 }
  350 
  351 gboolean
  352 gnc_split_register_get_split_amount_virt_loc (SplitRegister *reg, Split *split,
  353         VirtualLocation *virt_loc)
  354 {
  355     VirtualLocation v_loc;
  356     CursorClass cursor_class;
  357     const char *cell_name;
  358     gnc_numeric value;
  359 
  360     if (!gnc_split_register_get_split_virt_loc (reg, split, &v_loc.vcell_loc))
  361         return FALSE;
  362 
  363     cursor_class = gnc_split_register_get_cursor_class (reg, v_loc.vcell_loc);
  364 
  365     value = xaccSplitGetValue (split);
  366 
  367     switch (cursor_class)
  368     {
  369     case CURSOR_CLASS_SPLIT:
  370     case CURSOR_CLASS_TRANS:
  371         cell_name = (gnc_numeric_negative_p (value)) ? CRED_CELL : DEBT_CELL;
  372         break;
  373     default:
  374         return FALSE;
  375     }
  376 
  377     if (!gnc_table_get_cell_location (reg->table, cell_name,
  378                                       v_loc.vcell_loc, &v_loc))
  379         return FALSE;
  380 
  381     if (virt_loc == NULL)
  382         return TRUE;
  383 
  384     *virt_loc = v_loc;
  385 
  386     return TRUE;
  387 }
  388 
  389 Split *
  390 gnc_split_register_duplicate_current (SplitRegister *reg)
  391 {
  392     SRInfo *info = gnc_split_register_get_info(reg);
  393     CursorClass cursor_class;
  394     Transaction *trans;
  395     Split *return_split;
  396     Split *trans_split;
  397     Split *blank_split;
  398     gboolean changed;
  399     Split *split;
  400 
  401     ENTER("reg=%p", reg);
  402 
  403     blank_split = xaccSplitLookup(&info->blank_split_guid,
  404                                   gnc_get_current_book ());
  405     split = gnc_split_register_get_current_split (reg);
  406     trans = gnc_split_register_get_current_trans (reg);
  407     trans_split = gnc_split_register_get_current_trans_split (reg, NULL);
  408 
  409     /* This shouldn't happen, but be paranoid. */
  410     if (trans == NULL)
  411     {
  412         LEAVE("no transaction");
  413         return NULL;
  414     }
  415 
  416     cursor_class = gnc_split_register_get_current_cursor_class (reg);
  417 
  418     /* Can't do anything with this. */
  419     if (cursor_class == CURSOR_CLASS_NONE)
  420     {
  421         LEAVE("no cursor class");
  422         return NULL;
  423     }
  424 
  425     /* This shouldn't happen, but be paranoid. */
  426     if ((split == NULL) && (cursor_class == CURSOR_CLASS_TRANS))
  427     {
  428         LEAVE("no split with transaction class");
  429         return NULL;
  430     }
  431 
  432     changed = gnc_table_current_cursor_changed (reg->table, FALSE);
  433 
  434     /* See if we were asked to duplicate an unchanged blank split.
  435      * There's no point in doing that! */
  436     if (!changed && ((split == NULL) || (split == blank_split)))
  437     {
  438         LEAVE("skip unchanged blank split");
  439         return NULL;
  440     }
  441 
  442     gnc_suspend_gui_refresh ();
  443 
  444     /* If the cursor has been edited, we are going to have to commit
  445      * it before we can duplicate. Make sure the user wants to do that. */
  446     if (changed)
  447     {
  448         GtkWidget *dialog, *window;
  449         gint response;
  450         const char *title = _("Save transaction before duplicating?");
  451         const char *message =
  452             _("The current transaction has been changed. Would you like to "
  453               "record the changes before duplicating the transaction, or "
  454               "cancel the duplication?");
  455 
  456         window = gnc_split_register_get_parent (reg);
  457         dialog = gtk_message_dialog_new(GTK_WINDOW(window),
  458                                         GTK_DIALOG_DESTROY_WITH_PARENT,
  459                                         GTK_MESSAGE_QUESTION,
  460                                         GTK_BUTTONS_CANCEL,
  461                                         "%s", title);
  462         gtk_message_dialog_format_secondary_text(GTK_MESSAGE_DIALOG(dialog),
  463                 "%s", message);
  464         gtk_dialog_add_button(GTK_DIALOG(dialog),
  465                               _("_Record"), GTK_RESPONSE_ACCEPT);
  466         response = gnc_dialog_run(GTK_DIALOG(dialog), GNC_PREF_WARN_REG_TRANS_DUP);
  467         gtk_widget_destroy(dialog);
  468 
  469         if (response != GTK_RESPONSE_ACCEPT)
  470         {
  471             gnc_resume_gui_refresh ();
  472             LEAVE("save cancelled");
  473             return NULL;
  474         }
  475 
  476         gnc_split_register_save (reg, TRUE);
  477 
  478         /* If the split is NULL, then we were on a blank split row
  479          * in an expanded transaction. The new split (created by
  480          * gnc_split_register_save above) will be the last split in the
  481          * current transaction, as it was just added. */
  482         if (split == NULL)
  483             split = xaccTransGetSplit (trans, xaccTransCountSplits (trans) - 1);
  484     }
  485 
  486     /* Ok, we are now ready to make the copy. */
  487 
  488     if (cursor_class == CURSOR_CLASS_SPLIT)
  489     {
  490         Split *new_split;
  491         char *out_num;
  492         gboolean new_act_num = FALSE;
  493 
  494         /* We are on a split in an expanded transaction.
  495          * Just copy the split and add it to the transaction.
  496          * However, if the split-action field is being used as the register
  497          * number, and the action field is a number, request a new value or
  498          * cancel. Need to get next number and update account last num from
  499          * split account not register account, which may be the same or not */
  500 
  501         if (!reg->use_tran_num_for_num_field
  502             && gnc_strisnum (gnc_get_num_action (NULL, split)))
  503         {
  504             Account *account = xaccSplitGetAccount (split);
  505             const char *in_num = NULL;
  506             const char* title = _("New Split Information");
  507             time64 date = info->last_date_entered;
  508 
  509             if (account)
  510                 in_num = xaccAccountGetLastNum (account);
  511             else
  512                 in_num = gnc_get_num_action (NULL, split);
  513 
  514             if (!gnc_dup_trans_dialog (gnc_split_register_get_parent (reg),
  515                                    title, FALSE, &date, in_num, &out_num,
  516                                    NULL, NULL, NULL, NULL))
  517             {
  518                 gnc_resume_gui_refresh ();
  519                 LEAVE("dup cancelled");
  520                 return NULL;
  521             }
  522             new_act_num = TRUE;
  523         }
  524 
  525         new_split = xaccMallocSplit (gnc_get_current_book ());
  526 
  527         xaccTransBeginEdit (trans);
  528         xaccSplitSetParent (new_split, trans);
  529         gnc_copy_split_onto_split (split, new_split, FALSE);
  530         if (new_act_num) /* if new number supplied by user dialog */
  531             gnc_set_num_action (NULL, new_split, out_num, NULL);
  532 
  533         xaccTransCommitEdit (trans);
  534 
  535         if (new_act_num && gnc_strisnum (out_num))
  536         {
  537             Account *account = xaccSplitGetAccount (new_split);
  538 
  539             /* If current register is for account, set last num */
  540             if (xaccAccountEqual(account,
  541                                     gnc_split_register_get_default_account(reg),
  542                                     TRUE))
  543             {
  544                 NumCell *num_cell;
  545                 num_cell = (NumCell *) gnc_table_layout_get_cell (reg->table->layout,
  546                        NUM_CELL);
  547                 if (gnc_num_cell_set_last_num (num_cell, out_num))
  548                     gnc_split_register_set_last_num (reg, out_num);
  549             }
  550             else
  551             {
  552                 xaccAccountSetLastNum (account, out_num);
  553             }
  554         }
  555 
  556         return_split = new_split;
  557 
  558         info->cursor_hint_split = new_split;
  559         info->cursor_hint_cursor_class = CURSOR_CLASS_SPLIT;
  560         if (new_act_num)
  561             g_free (out_num);
  562     }
  563     else
  564     {
  565         NumCell *num_cell;
  566         Transaction *new_trans;
  567         int trans_split_index;
  568         int split_index;
  569         const char *in_num = NULL;
  570         const char *in_tnum = NULL;
  571         char *out_num = NULL;
  572         char *out_tnum = NULL;
  573         char *out_tassoc = NULL;
  574         time64 date;
  575         gboolean use_autoreadonly = qof_book_uses_autoreadonly(gnc_get_current_book());
  576 
  577         /* We are on a transaction row. Copy the whole transaction. */
  578 
  579         date = info->last_date_entered;
  580         if (gnc_strisnum (gnc_get_num_action (trans, trans_split)))
  581         {
  582             Account *account = gnc_split_register_get_default_account (reg);
  583 
  584             if (account)
  585                 in_num = xaccAccountGetLastNum (account);
  586             else
  587                 in_num = gnc_get_num_action (trans, trans_split);
  588             in_tnum = (reg->use_tran_num_for_num_field
  589                                         ? NULL
  590                                         : gnc_get_num_action (trans, NULL));
  591         }
  592 
  593         if (!gnc_dup_trans_dialog (gnc_split_register_get_parent (reg), NULL,
  594                                    TRUE, &date, in_num, &out_num, in_tnum, &out_tnum,
  595                                    xaccTransGetAssociation (trans), &out_tassoc))
  596         {
  597             gnc_resume_gui_refresh ();
  598             LEAVE("dup cancelled");
  599             return NULL;
  600         }
  601 
  602         if (use_autoreadonly)
  603         {
  604             GDate d;
  605             GDate *readonly_threshold = qof_book_get_autoreadonly_gdate(gnc_get_current_book());
  606             gnc_gdate_set_time64 (&d, date);
  607             if (g_date_compare(&d, readonly_threshold) < 0)
  608             {
  609                 GtkWidget *dialog = gtk_message_dialog_new(NULL,
  610                                     0,
  611                                     GTK_MESSAGE_ERROR,
  612                                     GTK_BUTTONS_OK,
  613                                     "%s", _("Cannot store a transaction at this date"));
  614                 gtk_message_dialog_format_secondary_text(GTK_MESSAGE_DIALOG(dialog),
  615                         "%s", _("The entered date of the duplicated transaction is older than the \"Read-Only Threshold\" set for this book. "
  616                                 "This setting can be changed in File -> Properties -> Accounts."));
  617                 gtk_dialog_run(GTK_DIALOG(dialog));
  618                 gtk_widget_destroy(dialog);
  619 
  620                 g_date_free(readonly_threshold);
  621                 return NULL;
  622             }
  623             g_date_free(readonly_threshold);
  624         }
  625 
  626         split_index = xaccTransGetSplitIndex(trans, split);
  627         trans_split_index = xaccTransGetSplitIndex(trans, trans_split);
  628 
  629         /* we should *always* find the split, but be paranoid */
  630         if (split_index < 0)
  631         {
  632             gnc_resume_gui_refresh ();
  633             LEAVE("no split");
  634             return NULL;
  635         }
  636 
  637         new_trans = xaccMallocTransaction (gnc_get_current_book ());
  638 
  639         xaccTransBeginEdit (new_trans);
  640         gnc_copy_trans_onto_trans (trans, new_trans, FALSE, FALSE);
  641         xaccTransSetDatePostedSecsNormalized (new_trans, date);
  642         /* We also must set a new DateEntered on the new entry
  643          * because otherwise the ordering is not deterministic */
  644         xaccTransSetDateEnteredSecs(new_trans, gnc_time(NULL));
  645 
  646         /* clear the associated entry if returned value NULL */
  647         if (out_tassoc == NULL)
  648             xaccTransSetAssociation (new_trans, "");
  649         else
  650             g_free (out_tassoc);
  651 
  652         /* set per book option */
  653         gnc_set_num_action (new_trans, NULL, out_num, out_tnum);
  654         if (!reg->use_tran_num_for_num_field)
  655         {
  656             /* find split in new_trans that equals trans_split and set
  657              * split_action to out_num */
  658             gnc_set_num_action (NULL,
  659                                 xaccTransGetSplit (new_trans, trans_split_index),
  660                                 out_num, NULL);
  661             /* note that if the transaction has multiple splits to the register
  662              * account, only the anchor split will be set with user input. The
  663              * user will have to adjust other splits manually. */
  664         }
  665         xaccTransCommitEdit (new_trans);
  666 
  667         num_cell = (NumCell *) gnc_table_layout_get_cell (reg->table->layout,
  668                    NUM_CELL);
  669         if (gnc_num_cell_set_last_num (num_cell, out_num))
  670             gnc_split_register_set_last_num (reg, out_num);
  671 
  672         g_free (out_num);
  673         if (!reg->use_tran_num_for_num_field)
  674             g_free (out_tnum);
  675 
  676         /* This shouldn't happen, but be paranoid. */
  677         if (split_index >= xaccTransCountSplits (new_trans))
  678             split_index = 0;
  679 
  680         return_split = xaccTransGetSplit (new_trans, split_index);
  681         trans_split = xaccTransGetSplit (new_trans, trans_split_index);
  682 
  683         info->cursor_hint_trans = new_trans;
  684         info->cursor_hint_split = return_split;
  685         info->cursor_hint_trans_split = trans_split;
  686         info->cursor_hint_cursor_class = CURSOR_CLASS_TRANS;
  687 
  688         info->trans_expanded = FALSE;
  689     }
  690 
  691     /* Refresh the GUI. */
  692     gnc_resume_gui_refresh ();
  693 
  694     LEAVE(" ");
  695     return return_split;
  696 }
  697 
  698 static void
  699 gnc_split_register_copy_current_internal (SplitRegister *reg,
  700         gboolean use_cut_semantics)
  701 {
  702     SRInfo *info = gnc_split_register_get_info(reg);
  703     CursorClass cursor_class;
  704     Transaction *trans;
  705     Split *blank_split;
  706     gboolean changed;
  707     Split *split;
  708     SCM new_item;
  709 
  710     g_return_if_fail(reg);
  711     ENTER("reg=%p, use_cut_semantics=%s", reg,
  712           use_cut_semantics ? "TRUE" : "FALSE");
  713 
  714     blank_split = xaccSplitLookup(&info->blank_split_guid,
  715                                   gnc_get_current_book ());
  716     split = gnc_split_register_get_current_split (reg);
  717     trans = gnc_split_register_get_current_trans (reg);
  718 
  719     /* This shouldn't happen, but be paranoid. */
  720     if (trans == NULL)
  721     {
  722         LEAVE("no trans");
  723         return;
  724     }
  725 
  726     cursor_class = gnc_split_register_get_current_cursor_class (reg);
  727 
  728     /* Can't do anything with this. */
  729     if (cursor_class == CURSOR_CLASS_NONE)
  730     {
  731         LEAVE("no cursor class");
  732         return;
  733     }
  734 
  735     /* This shouldn't happen, but be paranoid. */
  736     if ((split == NULL) && (cursor_class == CURSOR_CLASS_TRANS))
  737     {
  738         g_warning("BUG DETECTED: transaction cursor with no anchoring split!");
  739         LEAVE("transaction cursor with no anchoring split");
  740         return;
  741     }
  742 
  743     changed = gnc_table_current_cursor_changed (reg->table, FALSE);
  744 
  745     /* See if we were asked to copy an unchanged blank split. Don't. */
  746     if (!changed && ((split == NULL) || (split == blank_split)))
  747     {
  748         /* We're either on an unedited, brand-new split or an unedited, brand-new
  749          * transaction (the transaction anchored by the blank split.) */
  750         /* FIXME: This doesn't work exactly right. When entering a new transaction,
  751          *        you can edit the description, move to a split row, then move
  752          *        back to the description, then ask for a copy, and this code will
  753          *        be reached. It forgets that you changed the row the first time
  754          *        you were there.  -Charles */
  755         LEAVE("nothing to copy/cut");
  756         return;
  757     }
  758 
  759     /* Ok, we are now ready to make the copy. */
  760 
  761     if (cursor_class == CURSOR_CLASS_SPLIT)
  762     {
  763         /* We are on a split in an expanded transaction. Just copy the split. */
  764         new_item = gnc_copy_split(split, use_cut_semantics);
  765 
  766         if (new_item != SCM_UNDEFINED)
  767         {
  768             if (changed)
  769                 gnc_split_register_save_to_scm (reg, SCM_UNDEFINED, new_item,
  770                                                 use_cut_semantics);
  771 
  772             copied_leader_guid = *guid_null();
  773         }
  774     }
  775     else
  776     {
  777         /* We are on a transaction row. Copy the whole transaction. */
  778         new_item = gnc_copy_trans(trans, use_cut_semantics);
  779 
  780         if (new_item != SCM_UNDEFINED)
  781         {
  782             if (changed)
  783             {
  784                 int split_index;
  785                 SCM split_scm;
  786 
  787                 split_index = xaccTransGetSplitIndex(trans, split);
  788                 if (split_index >= 0)
  789                     split_scm = gnc_trans_scm_get_split_scm(new_item, split_index);
  790                 else
  791                     split_scm = SCM_UNDEFINED;
  792 
  793                 gnc_split_register_save_to_scm (reg, new_item, split_scm,
  794                                                 use_cut_semantics);
  795             }
  796 
  797             copied_leader_guid = info->default_account;
  798         }
  799     }
  800 
  801     if (new_item == SCM_UNDEFINED)
  802     {
  803         g_warning("BUG DETECTED: copy failed");
  804         LEAVE("copy failed");
  805         return;
  806     }
  807 
  808     /* unprotect the old object, if any */
  809     if (copied_item != SCM_UNDEFINED)
  810         scm_gc_unprotect_object(copied_item);
  811 
  812     copied_item = new_item;
  813     scm_gc_protect_object(copied_item);
  814 
  815     copied_class = cursor_class;
  816     LEAVE("%s %s", use_cut_semantics ? "cut" : "copied",
  817           cursor_class == CURSOR_CLASS_SPLIT ? "split" : "transaction");
  818 }
  819 
  820 void
  821 gnc_split_register_copy_current (SplitRegister *reg)
  822 {
  823     gnc_split_register_copy_current_internal (reg, FALSE);
  824 }
  825 
  826 void
  827 gnc_split_register_cut_current (SplitRegister *reg)
  828 {
  829     SRInfo *info = gnc_split_register_get_info (reg);
  830     CursorClass cursor_class;
  831     Transaction *trans;
  832     Split *blank_split;
  833     gboolean changed;
  834     Split *split;
  835 
  836     blank_split = xaccSplitLookup (&info->blank_split_guid,
  837                                    gnc_get_current_book ());
  838     split = gnc_split_register_get_current_split (reg);
  839     trans = gnc_split_register_get_current_trans (reg);
  840 
  841     /* This shouldn't happen, but be paranoid. */
  842     if (trans == NULL)
  843         return;
  844 
  845     cursor_class = gnc_split_register_get_current_cursor_class (reg);
  846 
  847     /* Can't do anything with this. */
  848     if (cursor_class == CURSOR_CLASS_NONE)
  849         return;
  850 
  851     /* This shouldn't happen, but be paranoid. */
  852     if ((split == NULL) && (cursor_class == CURSOR_CLASS_TRANS))
  853         return;
  854 
  855     changed = gnc_table_current_cursor_changed (reg->table, FALSE);
  856 
  857     /* See if we were asked to cut an unchanged blank split. Don't. */
  858     if (!changed && ((split == NULL) || (split == blank_split)))
  859         return;
  860 
  861     gnc_split_register_copy_current_internal (reg, TRUE);
  862 
  863     if (cursor_class == CURSOR_CLASS_SPLIT)
  864         gnc_split_register_delete_current_split (reg);
  865     else
  866         gnc_split_register_delete_current_trans (reg);
  867 }
  868 
  869 void
  870 gnc_split_register_paste_current (SplitRegister *reg)
  871 {
  872     SRInfo *info = gnc_split_register_get_info(reg);
  873     CursorClass cursor_class;
  874     Transaction *trans;
  875     Transaction *blank_trans;
  876     Split *blank_split;
  877     Split *trans_split;
  878     Split *split;
  879 
  880     ENTER("reg=%p", reg);
  881 
  882     if (copied_class == CURSOR_CLASS_NONE)
  883     {
  884         LEAVE("no copied cursor class");
  885         return;
  886     }
  887 
  888     blank_split = xaccSplitLookup (&info->blank_split_guid,
  889                                    gnc_get_current_book ());
  890     blank_trans = xaccSplitGetParent (blank_split);
  891     split = gnc_split_register_get_current_split (reg);
  892     trans = gnc_split_register_get_current_trans (reg);
  893 
  894     trans_split = gnc_split_register_get_current_trans_split (reg, NULL);
  895 
  896     /* This shouldn't happen, but be paranoid. */
  897     if (trans == NULL)
  898     {
  899         LEAVE("no transaction");
  900         return;
  901     }
  902 
  903     cursor_class = gnc_split_register_get_current_cursor_class (reg);
  904 
  905     /* Can't do anything with this. */
  906     if (cursor_class == CURSOR_CLASS_NONE)
  907     {
  908         LEAVE("no current cursor class");
  909         return;
  910     }
  911 
  912     /* This shouldn't happen, but be paranoid. */
  913     if ((split == NULL) && (cursor_class == CURSOR_CLASS_TRANS))
  914     {
  915         g_warning("BUG DETECTED: transaction cursor with no anchoring split!");
  916         LEAVE("transaction cursor with no anchoring split");
  917         return;
  918     }
  919 
  920     if (cursor_class == CURSOR_CLASS_SPLIT)
  921     {
  922         const char *message = _("You are about to overwrite an existing split. "
  923                                 "Are you sure you want to do that?");
  924         const char *anchor_message = _("This is the split anchoring this transaction "
  925                                        "to the register. You may not overwrite it from "
  926                                        "this register window. You may overwrite it if "
  927                                        "you navigate to a register that shows another "
  928                                        "side of this same transaction.");
  929 
  930         if (copied_class == CURSOR_CLASS_TRANS)
  931         {
  932             /* An entire transaction was copied, but we're just on a split. */
  933             LEAVE("can't copy trans to split");
  934             return;
  935         }
  936 
  937         if (split != NULL)
  938         {
  939             /* the General Journal does not have any anchoring splits */
  940             if ((reg->type != GENERAL_JOURNAL) &&
  941                 split == gnc_split_register_get_current_trans_split (reg, NULL))
  942             {
  943                 gnc_warning_dialog (GTK_WINDOW (gnc_split_register_get_parent (reg)),
  944                                     "%s", anchor_message);
  945                 LEAVE("anchore split");
  946                 return;
  947             }
  948             else if (!gnc_verify_dialog (GTK_WINDOW (gnc_split_register_get_parent (reg)),
  949                                          FALSE, "%s", message))
  950             {
  951                 LEAVE("user cancelled");
  952                 return;
  953             }
  954         }
  955 
  956         /* Open the transaction for editing. */
  957         if (gnc_split_register_begin_edit_or_warn (info, trans))
  958         {
  959             LEAVE("can't begin editing");
  960             return;
  961         }
  962 
  963         gnc_suspend_gui_refresh ();
  964 
  965         if (split == NULL)
  966         {
  967             /* We are on a null split in an expanded transaction. */
  968             split = xaccMallocSplit(gnc_get_current_book ());
  969             xaccSplitSetParent(split, trans);
  970         }
  971 
  972         gnc_copy_split_scm_onto_split(copied_item, split,
  973                                       gnc_get_current_book ());
  974     }
  975     else
  976     {
  977         const char *message = _("You are about to overwrite an existing "
  978                                 "transaction. "
  979                                 "Are you sure you want to do that?");
  980         Account * copied_leader;
  981         const GncGUID *new_guid;
  982         int trans_split_index;
  983         int split_index;
  984         int num_splits;
  985 
  986         if (copied_class == CURSOR_CLASS_SPLIT)
  987         {
  988             LEAVE("can't copy split to transaction");
  989             return;
  990         }
  991 
  992         /* Ask before overwriting an existing transaction. */
  993         if (split != blank_split &&
  994                 !gnc_verify_dialog (GTK_WINDOW (gnc_split_register_get_parent (reg)),
  995                                    FALSE, "%s", message))
  996         {
  997             LEAVE("user cancelled");
  998             return;
  999         }
 1000 
 1001         /* Open the transaction for editing. */
 1002         if (gnc_split_register_begin_edit_or_warn(info, trans))
 1003         {
 1004             LEAVE("can't begin editing");
 1005             return;
 1006         }
 1007 
 1008         gnc_suspend_gui_refresh ();
 1009 
 1010         DEBUG("Pasting txn, trans=%p, split=%p, blank_trans=%p, blank_split=%p",
 1011               trans, split, blank_trans, blank_split);
 1012 
 1013         split_index = xaccTransGetSplitIndex(trans, split);
 1014         trans_split_index = xaccTransGetSplitIndex(trans, trans_split);
 1015 
 1016         copied_leader = xaccAccountLookup(&copied_leader_guid,
 1017                                           gnc_get_current_book());
 1018         if (copied_leader && (gnc_split_register_get_default_account(reg) != NULL))
 1019         {
 1020             new_guid = &info->default_account;
 1021             gnc_copy_trans_scm_onto_trans_swap_accounts(copied_item, trans,
 1022                     &copied_leader_guid,
 1023                     new_guid, FALSE,
 1024                     gnc_get_current_book ());
 1025         }
 1026         else
 1027             gnc_copy_trans_scm_onto_trans(copied_item, trans, FALSE,
 1028                                           gnc_get_current_book ());
 1029 
 1030         num_splits = xaccTransCountSplits(trans);
 1031         if (split_index >= num_splits)
 1032             split_index = 0;
 1033 
 1034         if (trans == blank_trans)
 1035         {
 1036             /* In pasting, the blank split is deleted. Pick a new one. */
 1037             blank_split = xaccTransGetSplit(trans, 0);
 1038             info->blank_split_guid = *xaccSplitGetGUID (blank_split);
 1039             info->blank_split_edited = TRUE;
 1040             info->auto_complete = FALSE;
 1041             DEBUG("replacement blank_split=%p", blank_split);
 1042 
 1043             /* NOTE: At this point, the blank transaction virtual cell is still
 1044              *       anchored by the old, deleted blank split. The register will
 1045              *       have to be reloaded (redrawn) to correct this. */
 1046         }
 1047 
 1048         info->cursor_hint_trans = trans;
 1049         info->cursor_hint_split = xaccTransGetSplit(trans, split_index);
 1050         info->cursor_hint_trans_split = xaccTransGetSplit(trans,
 1051                                         trans_split_index);
 1052         info->cursor_hint_cursor_class = CURSOR_CLASS_TRANS;
 1053     }
 1054 
 1055     /* Refresh the GUI. */
 1056     gnc_resume_gui_refresh ();
 1057     LEAVE(" ");
 1058 }
 1059 
 1060 gboolean
 1061 gnc_split_register_is_blank_split (SplitRegister *reg, Split *split)
 1062 {
 1063     SRInfo *info = gnc_split_register_get_info (reg);
 1064     Split *current_blank_split = xaccSplitLookup (&info->blank_split_guid, gnc_get_current_book ());
 1065 
 1066     if (split == current_blank_split)
 1067         return TRUE;
 1068 
 1069     return FALSE;
 1070 }
 1071 
 1072 void
 1073 gnc_split_register_change_blank_split_ref (SplitRegister *reg, Split *split)
 1074 {
 1075     SRInfo *info = gnc_split_register_get_info (reg);
 1076     Split *current_blank_split = xaccSplitLookup (&info->blank_split_guid, gnc_get_current_book ());
 1077     Split *pref_split = NULL; // has the same account as incoming split
 1078     Split *other_split = NULL; // other split
 1079     Split *s;
 1080     Account *blank_split_account = xaccSplitGetAccount (current_blank_split);
 1081     Transaction *trans = xaccSplitGetParent (split);
 1082     int i = 0;
 1083 
 1084     // loop through splitlist looking for splits other than the blank_split
 1085     while ((s = xaccTransGetSplit (trans, i)) != NULL)
 1086     {
 1087         if (s != current_blank_split)
 1088         {
 1089             if (blank_split_account == xaccSplitGetAccount (s))
 1090                 pref_split = s;  // prefer same account
 1091             else
 1092                 other_split = s; // any other split
 1093         }
 1094         i++;
 1095     }
 1096     // now change the saved blank split reference
 1097     if (pref_split != NULL)
 1098         info->blank_split_guid = *xaccSplitGetGUID (pref_split);
 1099     else if (other_split != NULL)
 1100         info->blank_split_guid = *xaccSplitGetGUID (other_split);
 1101 }
 1102 
 1103 void
 1104 gnc_split_register_delete_current_split (SplitRegister *reg)
 1105 {
 1106     SRInfo *info = gnc_split_register_get_info (reg);
 1107     Transaction *pending_trans;
 1108     Transaction *trans;
 1109     Split *blank_split;
 1110     Split *split;
 1111 
 1112     if (!reg) return;
 1113 
 1114     blank_split = xaccSplitLookup (&info->blank_split_guid,
 1115                                    gnc_get_current_book ());
 1116 
 1117     pending_trans = xaccTransLookup (&info->pending_trans_guid,
 1118                                      gnc_get_current_book ());
 1119 
 1120     /* get the current split based on cursor position */
 1121     split = gnc_split_register_get_current_split (reg);
 1122     if (split == NULL)
 1123         return;
 1124 
 1125     /* If we are deleting the blank split, just cancel. The user is
 1126      * allowed to delete the blank split as a method for discarding
 1127      * any edits they may have made to it. */
 1128     if (split == blank_split)
 1129     {
 1130         gnc_split_register_cancel_cursor_split_changes (reg);
 1131         return;
 1132     }
 1133 
 1134     gnc_suspend_gui_refresh ();
 1135 
 1136     trans = xaccSplitGetParent(split);
 1137 
 1138     /* Check pending transaction */
 1139     if (trans == pending_trans)
 1140     {
 1141         g_assert(xaccTransIsOpen(trans));
 1142     }
 1143     else
 1144     {
 1145         g_assert(!pending_trans);
 1146         if (gnc_split_register_begin_edit_or_warn(info, trans))
 1147         {
 1148             gnc_resume_gui_refresh ();
 1149             return;
 1150         }
 1151     }
 1152     xaccSplitDestroy (split);
 1153 
 1154     gnc_resume_gui_refresh ();
 1155     gnc_split_register_redraw(reg);
 1156 }
 1157 
 1158 void
 1159 gnc_split_register_delete_current_trans (SplitRegister *reg)
 1160 {
 1161     SRInfo *info = gnc_split_register_get_info (reg);
 1162     Transaction *pending_trans;
 1163     Transaction *trans;
 1164     Split *blank_split;
 1165     Split *split;
 1166     gboolean was_open;
 1167 
 1168     ENTER("reg=%p", reg);
 1169     if (!reg)
 1170     {
 1171         LEAVE("no register");
 1172         return;
 1173     }
 1174 
 1175     blank_split = xaccSplitLookup (&info->blank_split_guid,
 1176                                    gnc_get_current_book ());
 1177     pending_trans = xaccTransLookup (&info->pending_trans_guid,
 1178                                      gnc_get_current_book ());
 1179 
 1180     /* get the current split based on cursor position */
 1181     split = gnc_split_register_get_current_split (reg);
 1182     if (split == NULL)
 1183     {
 1184         LEAVE("no split");
 1185         return;
 1186     }
 1187 
 1188     gnc_suspend_gui_refresh ();
 1189     trans = xaccSplitGetParent(split);
 1190 
 1191     /* If we just deleted the blank split, clean up. The user is
 1192      * allowed to delete the blank split as a method for discarding
 1193      * any edits they may have made to it. */
 1194     if (split == blank_split)
 1195     {
 1196         DEBUG("deleting blank split");
 1197         info->blank_split_guid = *guid_null();
 1198         info->auto_complete = FALSE;
 1199     }
 1200     else
 1201     {
 1202         info->trans_expanded = FALSE;
 1203     }
 1204 
 1205     /* Check pending transaction */
 1206     if (trans == pending_trans)
 1207     {
 1208         DEBUG("clearing pending trans");
 1209         info->pending_trans_guid = *guid_null();
 1210         pending_trans = NULL;
 1211     }
 1212 
 1213     was_open = xaccTransIsOpen(trans);
 1214     xaccTransDestroy(trans);
 1215     if (was_open)
 1216     {
 1217         DEBUG("committing");
 1218         xaccTransCommitEdit(trans);
 1219     }
 1220     gnc_resume_gui_refresh ();
 1221     LEAVE(" ");
 1222 }
 1223 
 1224 void
 1225 gnc_split_register_void_current_trans (SplitRegister *reg, const char *reason)
 1226 {
 1227     SRInfo *info = gnc_split_register_get_info (reg);
 1228     Transaction *pending_trans;
 1229     Transaction *trans;
 1230     Split *blank_split;
 1231     Split *split;
 1232 
 1233     if (!reg) return;
 1234 
 1235     blank_split = xaccSplitLookup (&info->blank_split_guid,
 1236                                    gnc_get_current_book ());
 1237     pending_trans = xaccTransLookup (&info->pending_trans_guid,
 1238                                      gnc_get_current_book ());
 1239 
 1240     /* get the current split based on cursor position */
 1241     split = gnc_split_register_get_current_split (reg);
 1242     if (split == NULL)
 1243         return;
 1244 
 1245     /* Bail if trying to void the blank split. */
 1246     if (split == blank_split)
 1247         return;
 1248 
 1249     /* already voided. */
 1250     if (xaccSplitGetReconcile (split) == VREC)
 1251         return;
 1252 
 1253     info->trans_expanded = FALSE;
 1254 
 1255     gnc_suspend_gui_refresh ();
 1256 
 1257     trans = xaccSplitGetParent(split);
 1258     xaccTransVoid(trans, reason);
 1259 
 1260     /* Check pending transaction */
 1261     if (trans == pending_trans)
 1262     {
 1263         info->pending_trans_guid = *guid_null();
 1264         pending_trans = NULL;
 1265     }
 1266     if (xaccTransIsOpen(trans))
 1267     {
 1268         PERR("We should not be voiding an open transaction.");
 1269         xaccTransCommitEdit(trans);
 1270     }
 1271     gnc_resume_gui_refresh ();
 1272 }
 1273 
 1274 void
 1275 gnc_split_register_unvoid_current_trans (SplitRegister *reg)
 1276 {
 1277     SRInfo *info = gnc_split_register_get_info (reg);
 1278     Transaction *pending_trans;
 1279     Transaction *trans;
 1280     Split *blank_split;
 1281     Split *split;
 1282 
 1283     if (!reg) return;
 1284 
 1285     blank_split = xaccSplitLookup (&info->blank_split_guid,
 1286                                    gnc_get_current_book ());
 1287     pending_trans = xaccTransLookup (&info->pending_trans_guid,
 1288                                      gnc_get_current_book ());
 1289 
 1290     /* get the current split based on cursor position */
 1291     split = gnc_split_register_get_current_split (reg);
 1292     if (split == NULL)
 1293         return;
 1294 
 1295     /* Bail if trying to unvoid the blank split. */
 1296     if (split == blank_split)
 1297         return;
 1298 
 1299     /* not voided. */
 1300     if (xaccSplitGetReconcile (split) != VREC)
 1301         return;
 1302 
 1303     info->trans_expanded = FALSE;
 1304 
 1305     gnc_suspend_gui_refresh ();
 1306 
 1307     trans = xaccSplitGetParent(split);
 1308 
 1309     xaccTransUnvoid(trans);
 1310 
 1311     /* Check pending transaction */
 1312     if (trans == pending_trans)
 1313     {
 1314         info->pending_trans_guid = *guid_null();
 1315         pending_trans = NULL;
 1316     }
 1317 
 1318     gnc_resume_gui_refresh ();
 1319 }
 1320 
 1321 void
 1322 gnc_split_register_empty_current_trans_except_split (SplitRegister *reg,
 1323         Split *split)
 1324 {
 1325     SRInfo *info;
 1326     Transaction *trans;
 1327     Transaction *pending;
 1328     int i = 0;
 1329     Split *s;
 1330 
 1331     if ((reg == NULL)  || (split == NULL))
 1332         return;
 1333 
 1334     gnc_suspend_gui_refresh ();
 1335     info = gnc_split_register_get_info(reg);
 1336     pending = xaccTransLookup(&info->pending_trans_guid, gnc_get_current_book());
 1337 
 1338     trans = xaccSplitGetParent(split);
 1339     if (!pending)
 1340     {
 1341         if (gnc_split_register_begin_edit_or_warn(info, trans))
 1342         {
 1343             gnc_resume_gui_refresh ();
 1344             return;
 1345         }
 1346     }
 1347     else if (pending == trans)
 1348     {
 1349         g_assert(xaccTransIsOpen(trans));
 1350     }
 1351     else g_assert_not_reached();
 1352 
 1353     while ((s = xaccTransGetSplit(trans, i)) != NULL)
 1354     {
 1355         if (s != split)
 1356             xaccSplitDestroy(s);
 1357         else i++;
 1358     }
 1359 
 1360     gnc_resume_gui_refresh ();
 1361     gnc_split_register_redraw(reg);
 1362 }
 1363 
 1364 void
 1365 gnc_split_register_empty_current_trans (SplitRegister *reg)
 1366 {
 1367     Split *split;
 1368 
 1369     /* get the current split based on cursor position */
 1370     split = gnc_split_register_get_current_split (reg);
 1371     gnc_split_register_empty_current_trans_except_split (reg, split);
 1372 }
 1373 
 1374 void
 1375 gnc_split_register_cancel_cursor_split_changes (SplitRegister *reg)
 1376 {
 1377     VirtualLocation virt_loc;
 1378 
 1379     if (reg == NULL)
 1380         return;
 1381 
 1382     virt_loc = reg->table->current_cursor_loc;
 1383 
 1384     if (!gnc_table_current_cursor_changed (reg->table, FALSE))
 1385         return;
 1386 
 1387     /* We're just cancelling the current split here, not the transaction.
 1388      * When cancelling edits, reload the cursor from the transaction. */
 1389     gnc_table_clear_current_cursor_changes (reg->table);
 1390 
 1391     if (gnc_table_find_close_valid_cell (reg->table, &virt_loc, FALSE))
 1392         gnc_table_move_cursor_gui (reg->table, virt_loc);
 1393 
 1394     gnc_table_refresh_gui (reg->table, TRUE);
 1395 }
 1396 
 1397 void
 1398 gnc_split_register_cancel_cursor_trans_changes (SplitRegister *reg)
 1399 {
 1400     SRInfo *info = gnc_split_register_get_info (reg);
 1401     Transaction *pending_trans, *blank_trans;
 1402     gboolean refresh_all = FALSE;
 1403 
 1404     pending_trans = xaccTransLookup (&info->pending_trans_guid,
 1405                                      gnc_get_current_book ());
 1406 
 1407     blank_trans = xaccSplitGetParent (gnc_split_register_get_blank_split (reg));
 1408 
 1409     if (pending_trans == blank_trans)
 1410         refresh_all = TRUE;
 1411 
 1412     /* Get the currently open transaction, rollback the edits on it, and
 1413      * then repaint everything. To repaint everything, make a note of
 1414      * all of the accounts that will be affected by this rollback. */
 1415     if (!xaccTransIsOpen (pending_trans))
 1416     {
 1417         gnc_split_register_cancel_cursor_split_changes (reg);
 1418         return;
 1419     }
 1420 
 1421     if (!pending_trans)
 1422         return;
 1423 
 1424     gnc_suspend_gui_refresh ();
 1425 
 1426     xaccTransRollbackEdit (pending_trans);
 1427 
 1428     info->pending_trans_guid = *guid_null ();
 1429 
 1430     gnc_resume_gui_refresh ();
 1431 
 1432     if (refresh_all)
 1433         gnc_gui_refresh_all (); // force a refresh of all registers
 1434     else
 1435         gnc_split_register_redraw (reg);
 1436 }
 1437 
 1438 void
 1439 gnc_split_register_redraw (SplitRegister *reg)
 1440 {
 1441     gnc_ledger_display_refresh_by_split_register (reg);
 1442 }
 1443 
 1444 /* Copy from the register object to scheme. This needs to be
 1445  * in sync with gnc_split_register_save and xaccSRSaveChangedCells. */
 1446 static gboolean
 1447 gnc_split_register_save_to_scm (SplitRegister *reg,
 1448                                 SCM trans_scm, SCM split_scm,
 1449                                 gboolean use_cut_semantics)
 1450 {
 1451     SCM other_split_scm = SCM_UNDEFINED;
 1452     Transaction *trans;
 1453 
 1454     /* use the changed flag to avoid heavy-weight updates
 1455      * of the split & transaction fields. This will help
 1456      * cut down on uneccessary register redraws. */
 1457     if (!gnc_table_current_cursor_changed (reg->table, FALSE))
 1458         return FALSE;
 1459 
 1460     /* get the handle to the current split and transaction */
 1461     trans = gnc_split_register_get_current_trans (reg);
 1462     if (trans == NULL)
 1463         return FALSE;
 1464 
 1465     /* copy the contents from the cursor to the split */
 1466     if (gnc_table_layout_get_cell_changed (reg->table->layout, DATE_CELL, TRUE))
 1467     {
 1468         BasicCell *cell;
 1469         time64 time;
 1470         cell = gnc_table_layout_get_cell (reg->table->layout, DATE_CELL);
 1471         gnc_date_cell_get_date ((DateCell *) cell, &time, TRUE);
 1472         xaccTransSetDatePostedSecsNormalized(trans, time);
 1473     }
 1474 
 1475     if (gnc_table_layout_get_cell_changed (reg->table->layout, NUM_CELL, TRUE))
 1476     {
 1477         const char *value;
 1478 
 1479         value = gnc_table_layout_get_cell_value (reg->table->layout, NUM_CELL);
 1480         if (reg->use_tran_num_for_num_field)
 1481             xaccTransSetNum (trans, value);
 1482      /* else this contains the same as ACTN_CELL which is already handled below *
 1483       * and the TNUM_CELL contains transaction number which is handled in next  *
 1484       * if statement. */
 1485     }
 1486 
 1487     if (gnc_table_layout_get_cell_changed (reg->table->layout, TNUM_CELL, TRUE))
 1488     {
 1489         const char *value;
 1490 
 1491         value = gnc_table_layout_get_cell_value (reg->table->layout, TNUM_CELL);
 1492         if (!reg->use_tran_num_for_num_field)
 1493             xaccTransSetNum (trans, value);
 1494      /* else this cell is not used */
 1495     }
 1496 
 1497     if (gnc_table_layout_get_cell_changed (reg->table->layout, DESC_CELL, TRUE))
 1498     {
 1499         const char *value;
 1500 
 1501         value = gnc_table_layout_get_cell_value (reg->table->layout, DESC_CELL);
 1502         xaccTransSetDescription (trans, value);
 1503     }
 1504 
 1505     if (gnc_table_layout_get_cell_changed (reg->table->layout, NOTES_CELL, TRUE))
 1506     {
 1507         const char *value;
 1508 
 1509         value = gnc_table_layout_get_cell_value (reg->table->layout, NOTES_CELL);
 1510         xaccTransSetNotes (trans, value);
 1511     }
 1512 
 1513     if (gnc_table_layout_get_cell_changed (reg->table->layout, RECN_CELL, TRUE))
 1514     {
 1515         BasicCell *cell;
 1516         char flag;
 1517 
 1518         cell = gnc_table_layout_get_cell (reg->table->layout, RECN_CELL);
 1519         flag = gnc_recn_cell_get_flag ((RecnCell *) cell);
 1520 
 1521         gnc_split_scm_set_reconcile_state(split_scm, flag);
 1522     }
 1523 
 1524     if (gnc_table_layout_get_cell_changed (reg->table->layout, ACTN_CELL, TRUE))
 1525     {
 1526         const char *value;
 1527 
 1528         value = gnc_table_layout_get_cell_value (reg->table->layout, ACTN_CELL);
 1529         gnc_split_scm_set_action (split_scm, value);
 1530     }
 1531 
 1532     if (gnc_table_layout_get_cell_changed (reg->table->layout, MEMO_CELL, TRUE))
 1533     {
 1534         const char *value;
 1535 
 1536         value = gnc_table_layout_get_cell_value (reg->table->layout, MEMO_CELL);
 1537         gnc_split_scm_set_memo (split_scm, value);
 1538     }
 1539 
 1540     if (gnc_table_layout_get_cell_changed (reg->table->layout, XFRM_CELL, TRUE))
 1541     {
 1542         Account *new_account;
 1543 
 1544         new_account = gnc_split_register_get_account (reg, XFRM_CELL);
 1545 
 1546         if (new_account != NULL)
 1547             gnc_split_scm_set_account (split_scm, new_account);
 1548     }
 1549 
 1550     if (reg->style == REG_STYLE_LEDGER)
 1551         other_split_scm = gnc_trans_scm_get_other_split_scm (trans_scm, split_scm);
 1552 
 1553     if (gnc_table_layout_get_cell_changed (reg->table->layout, MXFRM_CELL, TRUE))
 1554     {
 1555         other_split_scm = gnc_trans_scm_get_other_split_scm (trans_scm, split_scm);
 1556 
 1557         if (other_split_scm == SCM_UNDEFINED)
 1558         {
 1559             if (gnc_trans_scm_get_num_splits(trans_scm) == 1)
 1560             {
 1561                 Split *temp_split;
 1562 
 1563                 temp_split = xaccMallocSplit (gnc_get_current_book ());
 1564                 other_split_scm = gnc_copy_split (temp_split, use_cut_semantics);
 1565                 xaccSplitDestroy (temp_split);
 1566 
 1567                 gnc_trans_scm_append_split_scm (trans_scm, other_split_scm);
 1568             }
 1569         }
 1570 
 1571         if (other_split_scm != SCM_UNDEFINED)
 1572         {
 1573             Account *new_account;
 1574 
 1575             new_account = gnc_split_register_get_account (reg, MXFRM_CELL);
 1576 
 1577             if (new_account != NULL)
 1578                 gnc_split_scm_set_account (other_split_scm, new_account);
 1579         }
 1580     }
 1581 
 1582     if (gnc_table_layout_get_cell_changed (reg->table->layout,
 1583                                            DEBT_CELL, TRUE) ||
 1584             gnc_table_layout_get_cell_changed (reg->table->layout,
 1585                     CRED_CELL, TRUE))
 1586     {
 1587         BasicCell *cell;
 1588         gnc_numeric new_value;
 1589         gnc_numeric credit;
 1590         gnc_numeric debit;
 1591 
 1592         cell = gnc_table_layout_get_cell (reg->table->layout, CRED_CELL);
 1593         credit = gnc_price_cell_get_value ((PriceCell *) cell);
 1594 
 1595         cell = gnc_table_layout_get_cell (reg->table->layout, DEBT_CELL);
 1596         debit = gnc_price_cell_get_value ((PriceCell *) cell);
 1597 
 1598         new_value = gnc_numeric_sub_fixed (debit, credit);
 1599 
 1600         gnc_split_scm_set_value (split_scm, new_value);
 1601     }
 1602 
 1603     if (gnc_table_layout_get_cell_changed (reg->table->layout, PRIC_CELL, TRUE))
 1604     {
 1605         /* do nothing for now */
 1606     }
 1607 
 1608     if (gnc_table_layout_get_cell_changed (reg->table->layout, SHRS_CELL, TRUE))
 1609     {
 1610         BasicCell *cell;
 1611         gnc_numeric shares;
 1612 
 1613         cell = gnc_table_layout_get_cell (reg->table->layout, SHRS_CELL);
 1614 
 1615         shares = gnc_price_cell_get_value ((PriceCell *) cell);
 1616 
 1617         gnc_split_scm_set_amount (split_scm, shares);
 1618     }
 1619 
 1620     if (gnc_table_layout_get_cell_changed (reg->table->layout,
 1621                                            DEBT_CELL, TRUE) ||
 1622             gnc_table_layout_get_cell_changed (reg->table->layout,
 1623                     CRED_CELL, TRUE) ||
 1624             gnc_table_layout_get_cell_changed (reg->table->layout,
 1625                     PRIC_CELL, TRUE) ||
 1626             gnc_table_layout_get_cell_changed (reg->table->layout,
 1627                     SHRS_CELL, TRUE))
 1628     {
 1629         if (other_split_scm != SCM_UNDEFINED)
 1630         {
 1631             gnc_numeric num;
 1632 
 1633             num = gnc_split_scm_get_amount (split_scm);
 1634             gnc_split_scm_set_amount (other_split_scm, gnc_numeric_neg (num));
 1635 
 1636             num = gnc_split_scm_get_value (split_scm);
 1637             gnc_split_scm_set_value (other_split_scm, gnc_numeric_neg (num));
 1638         }
 1639     }
 1640 
 1641     return TRUE;
 1642 }
 1643 
 1644 gboolean
 1645 gnc_split_register_save (SplitRegister *reg, gboolean do_commit)
 1646 {
 1647     SRInfo *info = gnc_split_register_get_info (reg);
 1648     Transaction *pending_trans;
 1649     Transaction *blank_trans;
 1650     Transaction *trans;
 1651     Account *account;
 1652     Split *blank_split;
 1653     const char *memo;
 1654     const char *desc;
 1655     Split *split;
 1656 
 1657     ENTER("reg=%p, do_commit=%s", reg, do_commit ? "TRUE" : "FALSE");
 1658 
 1659     if (!reg)
 1660     {
 1661         LEAVE("no register");
 1662         return FALSE;
 1663     }
 1664 
 1665     blank_split = xaccSplitLookup (&info->blank_split_guid,
 1666                                    gnc_get_current_book ());
 1667 
 1668     pending_trans = xaccTransLookup (&info->pending_trans_guid,
 1669                                      gnc_get_current_book ());
 1670 
 1671     blank_trans = xaccSplitGetParent (blank_split);
 1672 
 1673     /* get the handle to the current split and transaction */
 1674     split = gnc_split_register_get_current_split (reg);
 1675     trans = gnc_split_register_get_current_trans (reg);
 1676     if (trans == NULL)
 1677     {
 1678         LEAVE("no transaction");
 1679         return FALSE;
 1680     }
 1681 
 1682     /* use the changed flag to avoid heavy-weight updates
 1683      * of the split & transaction fields. This will help
 1684      * cut down on unnecessary register redraws. */
 1685     if (!gnc_table_current_cursor_changed (reg->table, FALSE))
 1686     {
 1687         if (!do_commit)
 1688         {
 1689             LEAVE("commit unnecessary");
 1690             return FALSE;
 1691         }
 1692 
 1693         if (!xaccTransIsOpen(trans))
 1694         {
 1695             LEAVE("transaction not open");
 1696             return FALSE;
 1697         }
 1698 
 1699         if (trans == pending_trans ||
 1700                 (trans == blank_trans && info->blank_split_edited))
 1701         {
 1702             /* We are going to commit. */
 1703 
 1704             gnc_suspend_gui_refresh ();
 1705 
 1706             if (trans == blank_trans)
 1707             {
 1708                 /* We have to clear the blank split before the
 1709                  * refresh or a new one won't be created. */
 1710                 info->last_date_entered = xaccTransGetDate (trans);
 1711                 info->blank_split_guid = *guid_null ();
 1712                 info->blank_split_edited = FALSE;
 1713                 info->auto_complete = FALSE;
 1714             }
 1715 
 1716             /* We have to clear the pending guid *before* committing the
 1717              * trans, because the event handler will find it otherwise. */
 1718             if (trans == pending_trans)
 1719                 info->pending_trans_guid = *guid_null ();
 1720 
 1721             PINFO("committing trans (%p)", trans);
 1722             xaccTransCommitEdit(trans);
 1723 
 1724             gnc_resume_gui_refresh ();
 1725         }
 1726         else
 1727             DEBUG("leaving trans (%p) open", trans);
 1728 
 1729         LEAVE("unchanged cursor");
 1730         return TRUE;
 1731     }
 1732 
 1733     DEBUG("save split=%p", split);
 1734     DEBUG("blank_split=%p, blank_trans=%p, pending_trans=%p, trans=%p",
 1735           blank_split, blank_trans, pending_trans, trans);
 1736 
 1737     /* Act on any changes to the current cell before the save. */
 1738     if (!gnc_split_register_check_cell (reg,
 1739             gnc_table_get_current_cell_name (reg->table)))
 1740     {
 1741         LEAVE("need another go at changing cell");
 1742         return FALSE;
 1743     }
 1744 
 1745     if (!gnc_split_register_auto_calc (reg, split))
 1746     {
 1747         LEAVE("auto calc failed");
 1748         return FALSE;
 1749     }
 1750 
 1751     /* Validate the transfer account names */
 1752     (void)gnc_split_register_get_account (reg, MXFRM_CELL);
 1753     (void)gnc_split_register_get_account (reg, XFRM_CELL);
 1754 
 1755     /* Maybe deal with exchange-rate transfers */
 1756     if (gnc_split_register_handle_exchange (reg, FALSE))
 1757     {
 1758         LEAVE("no exchange rate");
 1759         return TRUE;
 1760     }
 1761 
 1762     gnc_suspend_gui_refresh ();
 1763 
 1764     /* determine whether we should commit the pending transaction */
 1765     if (pending_trans != trans)
 1766     {
 1767         // FIXME: How could the pending transaction not be open?
 1768         // FIXME: For that matter, how could an open pending
 1769         // transaction ever not be the current trans?
 1770         if (xaccTransIsOpen (pending_trans))
 1771         {
 1772             g_warning("Impossible? commiting pending %p", pending_trans);
 1773             xaccTransCommitEdit (pending_trans);
 1774         }
 1775         else if (pending_trans)
 1776         {
 1777             g_critical("BUG DETECTED! pending transaction (%p) not open",
 1778                        pending_trans);
 1779             g_assert_not_reached();
 1780         }
 1781 
 1782         if (trans == blank_trans)
 1783         {
 1784             /* Don't begin editing the blank trans, because it's
 1785                already open, but mark it pending now. */
 1786             g_assert(xaccTransIsOpen(blank_trans));
 1787             /* This is now the pending transaction */
 1788             info->pending_trans_guid = *xaccTransGetGUID(blank_trans);
 1789         }
 1790         else
 1791         {
 1792             PINFO("beginning edit of trans %p", trans);
 1793             if (gnc_split_register_begin_edit_or_warn(info, trans))
 1794             {
 1795                 gnc_resume_gui_refresh ();
 1796                 LEAVE("transaction opened elsewhere");
 1797                 return FALSE;
 1798             }
 1799         }
 1800         pending_trans = trans;
 1801     }
 1802     g_assert(xaccTransIsOpen(trans));
 1803 
 1804     /* If we are saving a brand new transaction and the blank split hasn't
 1805      * been edited, then we need to give it a default account. */
 1806     /* Q: Why check 'split == blank_split'? Isn't 'trans == blank_trans'
 1807      *    even better? What if there were some way that we could be on
 1808      *    a row other than the transaction row or blank split row, but
 1809      *    the blank split still hasn't been edited? It seems to be assumed
 1810      *    that it isn't possible, but... -Charles, Jan 2009 */
 1811     if (split == blank_split && !info->blank_split_edited)
 1812     {
 1813         /* If we've reached this point, it means that the blank split is
 1814          * anchoring the transaction - see gnc_split_register_add_transaction()
 1815          * for an explanation - and the transaction has been edited (as evidenced
 1816          * by the earlier check for a changed cursor.) Since the blank split
 1817          * itself has not been edited, we'll have to assign a default account. */
 1818         account = gnc_split_register_get_default_account(reg);
 1819         if (account)
 1820             xaccSplitSetAccount(blank_split, account);
 1821         xaccTransSetDateEnteredSecs(trans, gnc_time (NULL));
 1822     }
 1823 
 1824     if (split == NULL)
 1825     {
 1826         /* If we were asked to save data for a row for which there is no
 1827          * associated split, then assume that this was an "empty" row - see
 1828          * gnc_split_register_add_transaction() for an explanation. This row
 1829          * is used to add splits to an existing transaction, or to add the
 1830          * 2nd through nth split rows to a brand new transaction.
 1831          * xaccSRGetCurrent will handle this case, too. We will create
 1832          * a new split, copy the row contents to that split, and append
 1833          * the split to the pre-existing transaction. */
 1834         Split *trans_split;
 1835 
 1836         split = xaccMallocSplit (gnc_get_current_book ());
 1837         xaccTransAppendSplit (trans, split);
 1838 
 1839         gnc_table_set_virt_cell_data (reg->table,
 1840                                       reg->table->current_cursor_loc.vcell_loc,
 1841                                       xaccSplitGetGUID (split));
 1842         DEBUG("assigned cell to new split=%p", split);
 1843 
 1844         trans_split = gnc_split_register_get_current_trans_split (reg, NULL);
 1845         if ((info->cursor_hint_trans == trans) &&
 1846                 (info->cursor_hint_trans_split == trans_split) &&
 1847                 (info->cursor_hint_split == NULL))
 1848         {
 1849             info->cursor_hint_split = split;
 1850             info->cursor_hint_cursor_class = CURSOR_CLASS_SPLIT;
 1851         }
 1852     }
 1853 
 1854     DEBUG("updating trans=%p", trans);
 1855 
 1856     {
 1857         SRSaveData *sd;
 1858 
 1859         sd = gnc_split_register_save_data_new (
 1860                  trans, split, (info->trans_expanded ||
 1861                                 reg->style == REG_STYLE_AUTO_LEDGER ||
 1862                                 reg->style == REG_STYLE_JOURNAL));
 1863         gnc_table_save_cells (reg->table, sd);
 1864         gnc_split_register_save_data_destroy (sd);
 1865     }
 1866 
 1867     memo = xaccSplitGetMemo (split);
 1868     memo = memo ? memo : "(null)";
 1869     desc = xaccTransGetDescription (trans);
 1870     desc = desc ? desc : "(null)";
 1871     PINFO ("finished saving split \"%s\" of trans \"%s\"", memo, desc);
 1872 
 1873     /* If the modified split is the "blank split", then it is now an
 1874      * official part of the account. Set the blank split to NULL, so we
 1875      * can be sure of getting a new blank split. Also, save the date
 1876      * for the new blank split. */
 1877     if (trans == blank_trans)
 1878     {
 1879         if (do_commit)
 1880         {
 1881             info->blank_split_guid = *guid_null ();
 1882             info->auto_complete = FALSE;
 1883             blank_split = NULL;
 1884             info->last_date_entered = xaccTransGetDate (trans);
 1885         }
 1886         else
 1887             info->blank_split_edited = TRUE;
 1888     }
 1889 
 1890     /* If requested, commit the current transaction and set the pending
 1891      * transaction to NULL. */
 1892     if (do_commit)
 1893     {
 1894         g_assert(trans == blank_trans || trans == pending_trans);
 1895         if (pending_trans == trans)
 1896         {
 1897             pending_trans = NULL;
 1898             info->pending_trans_guid = *guid_null ();
 1899         }
 1900         xaccTransCommitEdit (trans);
 1901     }
 1902 
 1903     /* If there are splits in the unreconcile list and we are committing
 1904      * we need to unreconcile them */
 1905     if (do_commit && (reg->unrecn_splits != NULL))
 1906     {
 1907         GList *node;
 1908 
 1909         PINFO ("Unreconcile %d splits of reconciled transaction", g_list_length (reg->unrecn_splits));
 1910 
 1911         for (node = reg->unrecn_splits; node; node = node->next)
 1912         {
 1913             Split *split = node->data;
 1914 
 1915             if (xaccSplitGetReconcile (split) == YREC)
 1916                 xaccSplitSetReconcile (split, NREC);
 1917         }
 1918         g_list_free (reg->unrecn_splits);
 1919         reg->unrecn_splits = NULL;
 1920     }
 1921 
 1922     gnc_table_clear_current_cursor_changes (reg->table);
 1923 
 1924     gnc_resume_gui_refresh ();
 1925 
 1926     LEAVE(" ");
 1927     return TRUE;
 1928 }
 1929 
 1930 
 1931 Account *
 1932 gnc_split_register_get_account_by_name (SplitRegister *reg, BasicCell * bcell,
 1933                                         const char *name)
 1934 {
 1935     const char *placeholder = _("The account %s does not allow transactions.");
 1936     const char *missing = _("The account %s does not exist. "
 1937                             "Would you like to create it?");
 1938     char *account_name;
 1939     ComboCell *cell = (ComboCell *) bcell;
 1940     Account *account;
 1941     static gboolean creating_account = FALSE;
 1942     GtkWindow *parent = GTK_WINDOW (gnc_split_register_get_parent (reg));
 1943 
 1944     if (!name || (strlen(name) == 0))
 1945         return NULL;
 1946 
 1947     /* Find the account */
 1948     account = gnc_account_lookup_for_register (gnc_get_current_root_account (), name);
 1949     if (!account)
 1950         account = gnc_account_lookup_by_code(gnc_get_current_root_account(), name);
 1951 
 1952     /* if gnc_ui_new_accounts_from_name_window is used, there is a call to
 1953      * refresh which subsequently calls this function again, thats the
 1954      * reason for static creating_account. */
 1955 
 1956     if (!account && !creating_account)
 1957     {
 1958         /* Ask if they want to create a new one. */
 1959         if (!gnc_verify_dialog (parent, TRUE, missing, name))
 1960             return NULL;
 1961         creating_account = TRUE;
 1962         /* User said yes, they want to create a new account. */
 1963         account = gnc_ui_new_accounts_from_name_window (parent, name);
 1964         creating_account = FALSE;
 1965         if (!account)
 1966             return NULL;
 1967     }
 1968 
 1969     if (!creating_account)
 1970     {
 1971         /* Now have the account. */
 1972         account_name = gnc_get_account_name_for_split_register (account, reg->show_leaf_accounts);
 1973         if (g_strcmp0(account_name, gnc_basic_cell_get_value(bcell)))
 1974         {
 1975             /* The name has changed. Update the cell. */
 1976             gnc_combo_cell_set_value (cell, account_name);
 1977             gnc_basic_cell_set_changed (&cell->cell, TRUE);
 1978         }
 1979         g_free (account_name);
 1980 
 1981         /* See if the account (either old or new) is a placeholder. */
 1982         if (account && xaccAccountGetPlaceholder (account))
 1983         {
 1984             gchar *fullname = gnc_account_get_full_name (account);
 1985             gnc_error_dialog (GTK_WINDOW (gnc_split_register_get_parent (reg)),
 1986                               placeholder, fullname);
 1987             g_free (fullname);
 1988             return NULL;
 1989         }
 1990     }
 1991 
 1992     /* Be seeing you. */
 1993     return account;
 1994 }
 1995 
 1996 Account *
 1997 gnc_split_register_get_account (SplitRegister *reg, const char * cell_name)
 1998 {
 1999     BasicCell *cell;
 2000     const char *name;
 2001 
 2002     if (!gnc_table_layout_get_cell_changed (reg->table->layout, cell_name, TRUE))
 2003         return NULL;
 2004 
 2005     cell = gnc_table_layout_get_cell (reg->table->layout, cell_name);
 2006     if (!cell)
 2007         return NULL;
 2008     name = gnc_basic_cell_get_value (cell);
 2009     return gnc_split_register_get_account_by_name (reg, cell, name);
 2010 }
 2011 
 2012 static gnc_numeric
 2013 calculate_value (SplitRegister *reg)
 2014 {
 2015     gnc_numeric credit;
 2016     gnc_numeric debit;
 2017 
 2018     PriceCell *cell = (PriceCell*)gnc_table_layout_get_cell (reg->table->layout,
 2019                                                              CRED_CELL);
 2020     credit = gnc_price_cell_get_value (cell);
 2021 
 2022     cell = (PriceCell*)gnc_table_layout_get_cell (reg->table->layout,
 2023                                                   DEBT_CELL);
 2024     debit = gnc_price_cell_get_value (cell);
 2025 
 2026     return gnc_numeric_sub_fixed (debit, credit);
 2027 }
 2028 
 2029 
 2030 static int
 2031 recalc_message_box (SplitRegister *reg, gboolean shares_changed,
 2032                     gboolean price_changed, gboolean value_changed)
 2033 {
 2034     int choice;
 2035     int default_value;
 2036     GList *node;
 2037     GList *radio_list = NULL;
 2038     const char *title = _("Recalculate Transaction");
 2039     const char *message = _("The values entered for this transaction "
 2040                             "are inconsistent. Which value would you "
 2041                             "like to have recalculated?");
 2042 
 2043     if (shares_changed)
 2044         radio_list = g_list_append (radio_list, g_strdup_printf ("%s (%s)",
 2045                                                                  _("_Shares"),
 2046                                                                  _("Changed")));
 2047     else
 2048         radio_list = g_list_append (radio_list, g_strdup (_("_Shares")));
 2049 
 2050     if (price_changed)
 2051         radio_list = g_list_append (radio_list, g_strdup_printf ("%s (%s)",
 2052                                                                  _("_Price"),
 2053                                                                  _("Changed")));
 2054     else
 2055         radio_list = g_list_append (radio_list, g_strdup (_("_Price")));
 2056 
 2057     if (value_changed)
 2058         radio_list = g_list_append (radio_list, g_strdup_printf ("%s (%s)",
 2059                                                                  _("_Value"),
 2060                                                                  _("Changed")));
 2061     else
 2062         radio_list = g_list_append (radio_list, g_strdup (_("_Value")));
 2063 
 2064     if (price_changed) default_value = 2;  /* change the value */
 2065     else  default_value = 1;  /* change the value */
 2066 
 2067     choice = gnc_choose_radio_option_dialog
 2068         (gnc_split_register_get_parent (reg),
 2069          title,
 2070          message,
 2071          _("_Recalculate"),
 2072          default_value,
 2073          radio_list);
 2074 
 2075     for (node = radio_list; node; node = node->next)
 2076         g_free (node->data);
 2077 
 2078     g_list_free (radio_list);
 2079 
 2080     return choice;
 2081 }
 2082 
 2083 static void
 2084 recalculate_shares (Split* split, SplitRegister *reg,
 2085                gnc_numeric value, gnc_numeric price, gboolean value_changed)
 2086 {
 2087     gint64 denom = gnc_split_get_amount_denom (split);
 2088     gnc_numeric amount = gnc_numeric_div (value, price, denom,
 2089                                           GNC_HOW_RND_ROUND_HALF_UP);
 2090 
 2091     BasicCell *cell = gnc_table_layout_get_cell (reg->table->layout, SHRS_CELL);
 2092     gnc_price_cell_set_value ((PriceCell *) cell, amount);
 2093     gnc_basic_cell_set_changed (cell, TRUE);
 2094 
 2095     if (value_changed)
 2096     {
 2097         cell = gnc_table_layout_get_cell (reg->table->layout, PRIC_CELL);
 2098         gnc_basic_cell_set_changed (cell, FALSE);
 2099     }
 2100 }
 2101 
 2102 static void
 2103 recalculate_price (Split *split, SplitRegister *reg,
 2104               gnc_numeric value, gnc_numeric amount)
 2105 {
 2106     BasicCell *price_cell;
 2107     gnc_numeric price = gnc_numeric_div (value, amount,
 2108                                          GNC_DENOM_AUTO,
 2109                                          GNC_HOW_DENOM_EXACT);
 2110 
 2111     if (gnc_numeric_negative_p (price))
 2112     {
 2113         BasicCell *debit_cell;
 2114         BasicCell *credit_cell;
 2115 
 2116         debit_cell = gnc_table_layout_get_cell (reg->table->layout,
 2117                                                 DEBT_CELL);
 2118 
 2119         credit_cell = gnc_table_layout_get_cell (reg->table->layout,
 2120                                                  CRED_CELL);
 2121 
 2122         price = gnc_numeric_neg (price);
 2123 
 2124         gnc_price_cell_set_debt_credit_value ((PriceCell *) debit_cell,
 2125                                               (PriceCell *) credit_cell,
 2126                                               gnc_numeric_neg (value));
 2127 
 2128         gnc_basic_cell_set_changed (debit_cell, TRUE);
 2129         gnc_basic_cell_set_changed (credit_cell, TRUE);
 2130     }
 2131 
 2132     price_cell = gnc_table_layout_get_cell (reg->table->layout, PRIC_CELL);
 2133     gnc_price_cell_set_value ((PriceCell *) price_cell, price);
 2134     gnc_basic_cell_set_changed (price_cell, TRUE);
 2135 }
 2136 
 2137 static void
 2138 recalculate_value (Split *split, SplitRegister *reg,
 2139               gnc_numeric price, gnc_numeric amount, gboolean shares_changed)
 2140 {
 2141     BasicCell *debit_cell = gnc_table_layout_get_cell (reg->table->layout,
 2142                                                        DEBT_CELL);
 2143     BasicCell *credit_cell = gnc_table_layout_get_cell (reg->table->layout,
 2144                                                         CRED_CELL);
 2145     gint64 denom = gnc_split_get_value_denom (split);
 2146     gnc_numeric value = gnc_numeric_mul (price, amount, denom,
 2147                                          GNC_HOW_RND_ROUND_HALF_UP);
 2148 
 2149     gnc_price_cell_set_debt_credit_value ((PriceCell *) debit_cell,
 2150                                           (PriceCell *) credit_cell, value);
 2151 
 2152     gnc_basic_cell_set_changed (debit_cell, TRUE);
 2153     gnc_basic_cell_set_changed (credit_cell, TRUE);
 2154 
 2155     if (shares_changed)
 2156     {
 2157         BasicCell *cell = gnc_table_layout_get_cell (reg->table->layout,
 2158                                                      PRIC_CELL);
 2159         gnc_basic_cell_set_changed (cell, FALSE);
 2160     }
 2161 }
 2162 
 2163 static void
 2164 record_price (SplitRegister *reg, Account *account, gnc_numeric value,
 2165               PriceSource source)
 2166 {
 2167     Transaction *trans = gnc_split_register_get_current_trans (reg);
 2168     QofBook *book = qof_instance_get_book (QOF_INSTANCE (account));
 2169     GNCPriceDB *pricedb = gnc_pricedb_get_db (book);
 2170     gnc_commodity *comm = xaccAccountGetCommodity (account);
 2171     gnc_commodity *curr = xaccTransGetCurrency (trans);
 2172     GNCPrice *price;
 2173     gnc_numeric price_value;
 2174     int scu = gnc_commodity_get_fraction(curr);
 2175     time64 time;
 2176     BasicCell *cell = gnc_table_layout_get_cell (reg->table->layout, DATE_CELL);
 2177     gboolean swap = FALSE;
 2178 
 2179     /* Only record the price for account types that don't have a
 2180      * "rate" cell. They'll get handled later by
 2181      * gnc_split_register_handle_exchange.
 2182      */
 2183     if (gnc_split_reg_has_rate_cell (reg->type))
 2184         return;
 2185     gnc_date_cell_get_date ((DateCell*)cell, &time, TRUE);
 2186     price = gnc_pricedb_lookup_day_t64 (pricedb, comm, curr, time);
 2187     if (gnc_commodity_equiv (comm, gnc_price_get_currency (price)))
 2188             swap = TRUE;
 2189 
 2190     if (price)
 2191     {
 2192         price_value = gnc_price_get_value(price);
 2193         if (gnc_numeric_equal(swap ? gnc_numeric_invert(value) : value,
 2194                               price_value))
 2195         {
 2196             gnc_price_unref (price);
 2197             return;
 2198         }
 2199         if (gnc_price_get_source(price) < PRICE_SOURCE_XFER_DLG_VAL)
 2200         {
 2201             /* Existing price is preferred over this one. */
 2202             gnc_price_unref(price);
 2203             return;
 2204         }
 2205         if (swap)
 2206         {
 2207             value = gnc_numeric_invert(value);
 2208             scu = gnc_commodity_get_fraction(comm);
 2209         }
 2210         value = gnc_numeric_convert(value, scu * COMMODITY_DENOM_MULT,
 2211                                     GNC_HOW_RND_ROUND_HALF_UP);
 2212         gnc_price_begin_edit (price);
 2213         gnc_price_set_time64 (price, time);
 2214         gnc_price_set_source (price, source);
 2215         gnc_price_set_typestr (price, PRICE_TYPE_TRN);
 2216         gnc_price_set_value (price, value);
 2217         gnc_price_commit_edit (price);
 2218         gnc_price_unref (price);
 2219         return;
 2220     }
 2221 
 2222     value = gnc_numeric_convert(value, scu * COMMODITY_DENOM_MULT,
 2223                                 GNC_HOW_RND_ROUND_HALF_UP);
 2224     price = gnc_price_create (book);
 2225     gnc_price_begin_edit (price);
 2226     gnc_price_set_commodity (price, comm);
 2227     gnc_price_set_currency (price, curr);
 2228     gnc_price_set_time64 (price, time);
 2229     gnc_price_set_source (price, source);
 2230     gnc_price_set_typestr (price, PRICE_TYPE_TRN);
 2231     gnc_price_set_value (price, value);
 2232     gnc_pricedb_add_price (pricedb, price);
 2233     gnc_price_commit_edit (price);
 2234 }
 2235 
 2236 static gboolean
 2237 gnc_split_register_auto_calc (SplitRegister *reg, Split *split)
 2238 {
 2239     PriceCell *cell = NULL;
 2240     gboolean recalc_shares = FALSE;
 2241     gboolean recalc_price = FALSE;
 2242     gboolean recalc_value = FALSE;
 2243     gboolean price_changed;
 2244     gboolean value_changed;
 2245     gboolean shares_changed;
 2246     gnc_numeric calc_value;
 2247     gnc_numeric value;
 2248     gnc_numeric price;
 2249     gnc_numeric amount;
 2250     Account *account;
 2251     int denom;
 2252     int choice;
 2253     PriceSource source = PRICE_SOURCE_USER_PRICE;
 2254 
 2255     if (STOCK_REGISTER    != reg->type &&
 2256         CURRENCY_REGISTER != reg->type &&
 2257         PORTFOLIO_LEDGER  != reg->type)
 2258         return TRUE;
 2259 
 2260     account = gnc_split_register_get_account (reg, XFRM_CELL);
 2261 
 2262     if (!account)
 2263         account = xaccSplitGetAccount (split);
 2264 
 2265     if (!account)
 2266         account = gnc_split_register_get_default_account (reg);
 2267 
 2268     if (!xaccAccountIsPriced(account))
 2269         return TRUE;
 2270 
 2271     price_changed = gnc_table_layout_get_cell_changed (reg->table->layout,
 2272                     PRIC_CELL, TRUE);
 2273     value_changed = (gnc_table_layout_get_cell_changed (reg->table->layout,
 2274                       DEBT_CELL, TRUE) ||
 2275                       gnc_table_layout_get_cell_changed (reg->table->layout,
 2276                               CRED_CELL, TRUE));
 2277     shares_changed = gnc_table_layout_get_cell_changed (reg->table->layout,
 2278                      SHRS_CELL, TRUE);
 2279 
 2280     if (!price_changed && !value_changed && !shares_changed)
 2281         return TRUE;
 2282 
 2283     /* If we are using commodity trading accounts then the value may
 2284        not really be the value.  Punt if so. */
 2285     if (xaccTransUseTradingAccounts (xaccSplitGetParent (split)))
 2286     {
 2287         gnc_commodity *acc_commodity;
 2288         acc_commodity = xaccAccountGetCommodity (account);
 2289         if (! (xaccAccountIsPriced (account) ||
 2290                 !gnc_commodity_is_iso (acc_commodity)))
 2291             return TRUE;
 2292     }
 2293 
 2294     if (shares_changed)
 2295     {
 2296         cell = (PriceCell *) gnc_table_layout_get_cell (reg->table->layout,
 2297                 SHRS_CELL);
 2298         amount = gnc_price_cell_get_value (cell);
 2299     }
 2300     else
 2301         amount = xaccSplitGetAmount (split);
 2302 
 2303     if (price_changed)
 2304     {
 2305         cell = (PriceCell *) gnc_table_layout_get_cell (reg->table->layout,
 2306                 PRIC_CELL);
 2307         price = gnc_price_cell_get_value (cell);
 2308     }
 2309     else
 2310         price = xaccSplitGetSharePrice (split);
 2311 
 2312     if (value_changed)
 2313         value = calculate_value (reg);
 2314     else
 2315         value = xaccSplitGetValue (split);
 2316 
 2317 
 2318     /* Check if shares and price are BOTH zero (and value is non-zero).
 2319      * If so, we can assume that this is an income-correcting split
 2320      */
 2321     if (gnc_numeric_zero_p(amount) && gnc_numeric_zero_p(price) &&
 2322             !gnc_numeric_zero_p(value))
 2323     {
 2324         return TRUE;
 2325     }
 2326 
 2327     /* Check if precisely one value is zero. If so, we can assume that the
 2328      * zero value needs to be recalculated.   */
 2329 
 2330     if (!gnc_numeric_zero_p (amount))
 2331     {
 2332         if (gnc_numeric_zero_p (price))
 2333         {
 2334             if (!gnc_numeric_zero_p (value))
 2335                 recalc_price = TRUE;
 2336         }
 2337         else if (gnc_numeric_zero_p (value))
 2338             recalc_value = TRUE;
 2339     }
 2340     else if (!gnc_numeric_zero_p (price))
 2341         if (!gnc_numeric_zero_p (value))
 2342             recalc_shares = TRUE;
 2343 
 2344     /* If we have not already flagged a recalc, check if this is a split
 2345      * which has 2 of the 3 values changed. */
 2346 
 2347     if ((!recalc_shares) &&
 2348             (!recalc_price)  &&
 2349             (!recalc_value))
 2350     {
 2351         if (price_changed && value_changed)
 2352         {
 2353             if (!shares_changed)
 2354                 recalc_shares = TRUE;
 2355         }
 2356         else if (value_changed && shares_changed)
 2357             recalc_price = TRUE;
 2358         else if (price_changed && shares_changed)
 2359             recalc_value = TRUE;
 2360     }
 2361 
 2362     calc_value = gnc_numeric_mul (price, amount,
 2363                                   GNC_DENOM_AUTO, GNC_HOW_DENOM_LCD);
 2364 
 2365     denom = gnc_split_get_value_denom (split);
 2366 
 2367     /*  Now, if we have not flagged one of the recalcs, and value and
 2368      *  calc_value are not the same number, then we need to ask for
 2369      *  help from the user. */
 2370 
 2371     if (!recalc_shares &&
 2372         !recalc_price &&
 2373         !recalc_value &&
 2374         !gnc_numeric_same (value, calc_value, denom, GNC_HOW_RND_ROUND_HALF_UP))
 2375     {
 2376         choice = recalc_message_box(reg, shares_changed,
 2377                                     price_changed,
 2378                                     value_changed);
 2379         switch (choice)
 2380         {
 2381         case 0: /* Modify number of shares */
 2382             recalc_shares = TRUE;
 2383             break;
 2384         case 1: /* Modify the share price */
 2385             recalc_price = TRUE;
 2386             break;
 2387         case 2: /* Modify total value */
 2388             recalc_value = TRUE;
 2389             break;
 2390         default: /* Cancel */
 2391             return FALSE;
 2392         }
 2393     }
 2394 
 2395     if (recalc_shares && !gnc_numeric_zero_p (price))
 2396         recalculate_shares (split, reg, value, price, value_changed);
 2397 
 2398     if (recalc_price && !gnc_numeric_zero_p (amount))
 2399     {
 2400         recalculate_price (split, reg, value, amount);
 2401         price_changed = TRUE;
 2402         source = PRICE_SOURCE_SPLIT_REG;
 2403     }
 2404     if (recalc_value)
 2405         recalculate_value (split, reg, price, amount, shares_changed);
 2406 
 2407     if (price_changed)
 2408     {
 2409         cell = (PriceCell *) gnc_table_layout_get_cell (reg->table->layout,
 2410                 PRIC_CELL);
 2411         price = gnc_price_cell_get_value (cell);
 2412     if (gnc_numeric_positive_p(price))
 2413         record_price (reg, account, price, source);
 2414     }
 2415     return TRUE;
 2416 }
 2417 
 2418 static GNCAccountType
 2419 gnc_split_register_type_to_account_type (SplitRegisterType sr_type)
 2420 {
 2421     switch (sr_type)
 2422     {
 2423     case BANK_REGISTER:
 2424         return ACCT_TYPE_BANK;
 2425     case CASH_REGISTER:
 2426         return ACCT_TYPE_CASH;
 2427     case ASSET_REGISTER:
 2428         return ACCT_TYPE_ASSET;
 2429     case CREDIT_REGISTER:
 2430         return ACCT_TYPE_CREDIT;
 2431     case LIABILITY_REGISTER:
 2432         return ACCT_TYPE_LIABILITY;
 2433     case PAYABLE_REGISTER:
 2434         return ACCT_TYPE_PAYABLE;
 2435     case RECEIVABLE_REGISTER:
 2436         return ACCT_TYPE_RECEIVABLE;
 2437     case INCOME_LEDGER:
 2438     case INCOME_REGISTER:
 2439         return ACCT_TYPE_INCOME;
 2440     case EXPENSE_REGISTER:
 2441         return ACCT_TYPE_EXPENSE;
 2442     case STOCK_REGISTER:
 2443     case PORTFOLIO_LEDGER:
 2444         return ACCT_TYPE_STOCK;
 2445     case CURRENCY_REGISTER:
 2446         return ACCT_TYPE_CURRENCY;
 2447     case TRADING_REGISTER:
 2448         return ACCT_TYPE_TRADING;
 2449     case GENERAL_JOURNAL:
 2450         return ACCT_TYPE_NONE;
 2451     case EQUITY_REGISTER:
 2452         return ACCT_TYPE_EQUITY;
 2453     case SEARCH_LEDGER:
 2454         return ACCT_TYPE_NONE;
 2455     default:
 2456         return ACCT_TYPE_NONE;
 2457     }
 2458 }
 2459 
 2460 const char *
 2461 gnc_split_register_get_debit_string (SplitRegister *reg)
 2462 {
 2463     SRInfo *info = gnc_split_register_get_info (reg);
 2464 
 2465     if (!reg)
 2466         return NULL;
 2467 
 2468     if (info->debit_str)
 2469         return info->debit_str;
 2470 
 2471     info->debit_str =
 2472         gnc_get_debit_string
 2473         (gnc_split_register_type_to_account_type (reg->type));
 2474 
 2475     if (info->debit_str)
 2476         return info->debit_str;
 2477 
 2478     info->debit_str = g_strdup (_("Debit"));
 2479 
 2480     return info->debit_str;
 2481 }
 2482 
 2483 const char *
 2484 gnc_split_register_get_credit_string (SplitRegister *reg)
 2485 {
 2486     SRInfo *info = gnc_split_register_get_info (reg);
 2487 
 2488     if (!reg)
 2489         return NULL;
 2490 
 2491     if (info->credit_str)
 2492         return info->credit_str;
 2493 
 2494     info->credit_str =
 2495         gnc_get_credit_string
 2496         (gnc_split_register_type_to_account_type (reg->type));
 2497 
 2498     if (info->credit_str)
 2499         return info->credit_str;
 2500 
 2501     info->credit_str = g_strdup (_("Credit"));
 2502 
 2503     return info->credit_str;
 2504 }
 2505 
 2506 gboolean
 2507 gnc_split_register_changed (SplitRegister *reg)
 2508 {
 2509     SRInfo *info = gnc_split_register_get_info (reg);
 2510     Transaction *pending_trans;
 2511 
 2512     ENTER("reg=%p", reg);
 2513 
 2514     if (reg == NULL)
 2515     {
 2516         LEAVE("no register");
 2517         return FALSE;
 2518     }
 2519 
 2520     if (gnc_table_current_cursor_changed (reg->table, FALSE))
 2521     {
 2522         LEAVE("cursor changed");
 2523         return TRUE;
 2524     }
 2525 
 2526     pending_trans = xaccTransLookup (&info->pending_trans_guid,
 2527                                      gnc_get_current_book ());
 2528     if (xaccTransIsOpen (pending_trans))
 2529     {
 2530         LEAVE("open and pending txn");
 2531         return TRUE;
 2532     }
 2533 
 2534     LEAVE("register unchanged");
 2535     return FALSE;
 2536 }
 2537 
 2538 void
 2539 gnc_split_register_show_present_divider (SplitRegister *reg,
 2540         gboolean show_present)
 2541 {
 2542     SRInfo *info = gnc_split_register_get_info (reg);
 2543 
 2544     if (reg == NULL)
 2545         return;
 2546 
 2547     info->show_present_divider = show_present;
 2548 }
 2549 
 2550 gboolean
 2551 gnc_split_register_full_refresh_ok (SplitRegister *reg)
 2552 {
 2553     SRInfo *info = gnc_split_register_get_info (reg);
 2554 
 2555     if (!info)
 2556         return FALSE;
 2557 
 2558     return info->full_refresh;
 2559 }
 2560 
 2561 /* configAction strings into the action cell */
 2562 /* hack alert -- this stuff really, really should be in a config file ... */
 2563 static void
 2564 gnc_split_register_config_action (SplitRegister *reg)
 2565 {
 2566     ComboCell *cell;
 2567 
 2568     cell = (ComboCell *) gnc_table_layout_get_cell (reg->table->layout,
 2569             ACTN_CELL);
 2570 
 2571     /* setup strings in the action pull-down */
 2572     switch (reg->type)
 2573     {
 2574     case BANK_REGISTER:
 2575         /* broken ! FIXME bg */
 2576     case SEARCH_LEDGER:
 2577         /* Translators: This string has a context prefix; the translation
 2578             must only contain the part after the | character. */
 2579         gnc_combo_cell_add_menu_item (cell, Q_("Action Column|Deposit"));
 2580         gnc_combo_cell_add_menu_item (cell, _("Withdraw"));
 2581         gnc_combo_cell_add_menu_item (cell, _("Check"));
 2582         gnc_combo_cell_add_menu_item (cell, _("Interest"));
 2583         gnc_combo_cell_add_menu_item (cell, _("ATM Deposit"));
 2584         gnc_combo_cell_add_menu_item (cell, _("ATM Draw"));
 2585         gnc_combo_cell_add_menu_item (cell, _("Teller"));
 2586         gnc_combo_cell_add_menu_item (cell, _("Charge"));
 2587         gnc_combo_cell_add_menu_item (cell, _("Payment"));
 2588         gnc_combo_cell_add_menu_item (cell, _("Receipt"));
 2589         gnc_combo_cell_add_menu_item (cell, _("Increase"));
 2590         gnc_combo_cell_add_menu_item (cell, _("Decrease"));
 2591         /* Action: Point Of Sale */
 2592         gnc_combo_cell_add_menu_item (cell, _("POS"));
 2593         gnc_combo_cell_add_menu_item (cell, _("Phone"));
 2594         gnc_combo_cell_add_menu_item (cell, _("Online"));
 2595         /* Action: Automatic Deposit ?!? */
 2596         gnc_combo_cell_add_menu_item (cell, _("AutoDep"));
 2597         gnc_combo_cell_add_menu_item (cell, _("Wire"));
 2598         gnc_combo_cell_add_menu_item (cell, _("Credit"));
 2599         gnc_combo_cell_add_menu_item (cell, _("Direct Debit"));
 2600         gnc_combo_cell_add_menu_item (cell, _("Transfer"));
 2601         break;
 2602     case CASH_REGISTER:
 2603         gnc_combo_cell_add_menu_item (cell, _("Increase"));
 2604         gnc_combo_cell_add_menu_item (cell, _("Decrease"));
 2605         gnc_combo_cell_add_menu_item (cell, _("Buy"));
 2606         gnc_combo_cell_add_menu_item (cell, _("Sell"));
 2607         break;
 2608     case ASSET_REGISTER:
 2609         gnc_combo_cell_add_menu_item (cell, _("Buy"));
 2610         gnc_combo_cell_add_menu_item (cell, _("Sell"));
 2611         gnc_combo_cell_add_menu_item (cell, _("Fee"));
 2612         break;
 2613     case CREDIT_REGISTER:
 2614         gnc_combo_cell_add_menu_item (cell, _("ATM Deposit"));
 2615         gnc_combo_cell_add_menu_item (cell, _("ATM Draw"));
 2616         gnc_combo_cell_add_menu_item (cell, _("Buy"));
 2617         gnc_combo_cell_add_menu_item (cell, _("Credit"));
 2618         gnc_combo_cell_add_menu_item (cell, _("Fee"));
 2619         gnc_combo_cell_add_menu_item (cell, _("Interest"));
 2620         gnc_combo_cell_add_menu_item (cell, _("Online"));
 2621         gnc_combo_cell_add_menu_item (cell, _("Sell"));
 2622         break;
 2623     case LIABILITY_REGISTER:
 2624         gnc_combo_cell_add_menu_item (cell, _("Buy"));
 2625         gnc_combo_cell_add_menu_item (cell, _("Sell"));
 2626         gnc_combo_cell_add_menu_item (cell, _("Loan"));
 2627         gnc_combo_cell_add_menu_item (cell, _("Interest"));
 2628         gnc_combo_cell_add_menu_item (cell, _("Payment"));
 2629         break;
 2630     case RECEIVABLE_REGISTER:
 2631     case PAYABLE_REGISTER:
 2632         gnc_combo_cell_add_menu_item (cell, _("Invoice"));
 2633         gnc_combo_cell_add_menu_item (cell, _("Payment"));
 2634         gnc_combo_cell_add_menu_item (cell, _("Interest"));
 2635         gnc_combo_cell_add_menu_item (cell, _("Credit"));
 2636         break;
 2637     case INCOME_LEDGER:
 2638     case INCOME_REGISTER:
 2639         gnc_combo_cell_add_menu_item (cell, _("Increase"));
 2640         gnc_combo_cell_add_menu_item (cell, _("Decrease"));
 2641         gnc_combo_cell_add_menu_item (cell, _("Buy"));
 2642         gnc_combo_cell_add_menu_item (cell, _("Sell"));
 2643         gnc_combo_cell_add_menu_item (cell, _("Interest"));
 2644         gnc_combo_cell_add_menu_item (cell, _("Payment"));
 2645         gnc_combo_cell_add_menu_item (cell, _("Rebate"));
 2646         gnc_combo_cell_add_menu_item (cell, _("Paycheck"));
 2647         break;
 2648     case EXPENSE_REGISTER:
 2649     case TRADING_REGISTER:
 2650         gnc_combo_cell_add_menu_item (cell, _("Increase"));
 2651         gnc_combo_cell_add_menu_item (cell, _("Decrease"));
 2652         gnc_combo_cell_add_menu_item (cell, _("Buy"));
 2653         gnc_combo_cell_add_menu_item (cell, _("Sell"));
 2654         break;
 2655     case GENERAL_JOURNAL:
 2656     case EQUITY_REGISTER:
 2657         gnc_combo_cell_add_menu_item (cell, _("Buy"));
 2658         gnc_combo_cell_add_menu_item (cell, _("Sell"));
 2659         gnc_combo_cell_add_menu_item (cell, _("Equity"));
 2660         break;
 2661     case STOCK_REGISTER:
 2662     case PORTFOLIO_LEDGER:
 2663     case CURRENCY_REGISTER:
 2664         gnc_combo_cell_add_menu_item (cell, ACTION_BUY_STR);
 2665         gnc_combo_cell_add_menu_item (cell, ACTION_SELL_STR);
 2666         gnc_combo_cell_add_menu_item (cell, _("Price"));
 2667         gnc_combo_cell_add_menu_item (cell, _("Fee"));
 2668         /* Action: Dividend */
 2669         gnc_combo_cell_add_menu_item (cell, _("Dividend"));
 2670         gnc_combo_cell_add_menu_item (cell, _("Interest"));
 2671         /* Action: Long Term Capital Gains */
 2672         gnc_combo_cell_add_menu_item (cell, _("LTCG"));
 2673         /* Action: Short Term Capital Gains */
 2674         gnc_combo_cell_add_menu_item (cell, _("STCG"));
 2675         gnc_combo_cell_add_menu_item (cell, _("Income"));
 2676         /* Action: Distribution */
 2677         gnc_combo_cell_add_menu_item (cell, _("Dist"));
 2678         /* Translators: This string has a disambiguation prefix */
 2679         gnc_combo_cell_add_menu_item (cell, Q_("Action Column|Split"));
 2680         break;
 2681 
 2682     default:
 2683         gnc_combo_cell_add_menu_item (cell, _("Increase"));
 2684         gnc_combo_cell_add_menu_item (cell, _("Decrease"));
 2685         gnc_combo_cell_add_menu_item (cell, _("Buy"));
 2686         gnc_combo_cell_add_menu_item (cell, _("Sell"));
 2687         break;
 2688     }
 2689 }
 2690 
 2691 static void
 2692 gnc_split_register_config_cells (SplitRegister *reg)
 2693 {
 2694     gnc_combo_cell_add_ignore_string
 2695     ((ComboCell *)
 2696      gnc_table_layout_get_cell (reg->table->layout, MXFRM_CELL),
 2697      SPLIT_TRANS_STR);
 2698 
 2699     gnc_combo_cell_add_ignore_string
 2700     ((ComboCell *)
 2701      gnc_table_layout_get_cell (reg->table->layout, MXFRM_CELL),
 2702      STOCK_SPLIT_STR);
 2703 
 2704     /* the action cell */
 2705     gnc_combo_cell_set_autosize
 2706     ((ComboCell *)
 2707      gnc_table_layout_get_cell (reg->table->layout, ACTN_CELL), TRUE);
 2708 
 2709     /* Use GNC_COMMODITY_MAX_FRACTION for prices and "exchange rates"  */
 2710     gnc_price_cell_set_fraction
 2711     ((PriceCell *)
 2712      gnc_table_layout_get_cell (reg->table->layout, PRIC_CELL),
 2713      GNC_COMMODITY_MAX_FRACTION);
 2714 
 2715     /* Initialize shares and share balance cells */
 2716     gnc_price_cell_set_print_info
 2717     ((PriceCell *) gnc_table_layout_get_cell (reg->table->layout, SHRS_CELL),
 2718      gnc_default_share_print_info ());
 2719 
 2720     gnc_price_cell_set_print_info
 2721     ((PriceCell *) gnc_table_layout_get_cell (reg->table->layout, TSHRS_CELL),
 2722      gnc_default_share_print_info ());
 2723 
 2724     /* Initialize the rate cell
 2725      * use a share_print_info to make sure we don't have rounding errors
 2726      */
 2727     gnc_price_cell_set_print_info
 2728     ((PriceCell *) gnc_table_layout_get_cell (reg->table->layout, RATE_CELL),
 2729      gnc_default_share_print_info());
 2730 
 2731     /* The action cell should accept strings not in the list */
 2732     gnc_combo_cell_set_strict
 2733     ((ComboCell *)
 2734      gnc_table_layout_get_cell (reg->table->layout, ACTN_CELL), FALSE);
 2735 
 2736     /* number format for share quantities in stock ledgers */
 2737     switch (reg->type)
 2738     {
 2739     case CURRENCY_REGISTER:
 2740     case STOCK_REGISTER:
 2741     case PORTFOLIO_LEDGER:
 2742         gnc_price_cell_set_print_info
 2743         ((PriceCell *)
 2744          gnc_table_layout_get_cell (reg->table->layout, PRIC_CELL),
 2745          gnc_default_price_print_info (gnc_default_currency ()));
 2746         break;
 2747 
 2748     default:
 2749         break;
 2750     }
 2751 
 2752     /* add menu items for the action cell */
 2753     gnc_split_register_config_action (reg);
 2754 }
 2755 
 2756 static void
 2757 split_register_pref_changed (gpointer prefs, gchar *pref, gpointer user_data)
 2758 {
 2759     SplitRegister * reg = user_data;
 2760     SRInfo *info;
 2761 
 2762     g_return_if_fail(pref);
 2763     if (reg == NULL)
 2764         return;
 2765 
 2766     info = reg->sr_info;
 2767     if (!info)
 2768         return;
 2769 
 2770     if (g_str_has_suffix(pref, GNC_PREF_ACCOUNTING_LABELS))
 2771     {
 2772         /* Release current strings. Will be reloaded at next reference. */
 2773         g_free (info->debit_str);
 2774         g_free (info->tdebit_str);
 2775         g_free (info->credit_str);
 2776         g_free (info->tcredit_str);
 2777 
 2778         info->debit_str = NULL;
 2779         info->tdebit_str = NULL;
 2780         info->credit_str = NULL;
 2781         info->tcredit_str = NULL;
 2782 
 2783     }
 2784     else if (g_str_has_suffix(pref, GNC_PREF_ACCOUNT_SEPARATOR))
 2785     {
 2786         info->separator_changed = TRUE;
 2787     }
 2788     else if (g_str_has_suffix(pref, GNC_PREF_SHOW_LEAF_ACCT_NAMES))
 2789     {
 2790         reg->show_leaf_accounts = gnc_prefs_get_bool(GNC_PREFS_GROUP_GENERAL_REGISTER,
 2791                                             GNC_PREF_SHOW_LEAF_ACCT_NAMES);
 2792     }
 2793     else if (g_str_has_suffix(pref, GNC_PREF_ALT_COLOR_BY_TRANS))
 2794     {
 2795         reg->double_alt_color = gnc_prefs_get_bool(GNC_PREFS_GROUP_GENERAL_REGISTER,
 2796                                             GNC_PREF_ALT_COLOR_BY_TRANS);
 2797     }
 2798     else
 2799     {
 2800         g_warning("split_register_pref_changed: Unknown preference %s", pref);
 2801     }
 2802 }
 2803 
 2804 static void
 2805 split_register_book_option_changed (gpointer new_val, gpointer user_data)
 2806 {
 2807     SplitRegister * reg = user_data;
 2808     gboolean *new_data = (gboolean*)new_val;
 2809 
 2810     if (reg == NULL)
 2811         return;
 2812 
 2813     reg->use_tran_num_for_num_field = (*new_data ? FALSE : TRUE);
 2814 }
 2815 
 2816 static void
 2817 gnc_split_register_init (SplitRegister *reg,
 2818                          SplitRegisterType type,
 2819                          SplitRegisterStyle style,
 2820                          gboolean use_double_line,
 2821                          gboolean do_auto_complete,
 2822                          gboolean is_template)
 2823 {
 2824     TableLayout *layout;
 2825     TableModel *model;
 2826     TableControl *control;
 2827 
 2828     /* Register 'destroy' callback */
 2829     gnc_prefs_register_cb (GNC_PREFS_GROUP_GENERAL,
 2830                            GNC_PREF_ACCOUNTING_LABELS,
 2831                            split_register_pref_changed,
 2832                            reg);
 2833     gnc_prefs_register_cb (GNC_PREFS_GROUP_GENERAL,
 2834                            GNC_PREF_ACCOUNT_SEPARATOR,
 2835                            split_register_pref_changed,
 2836                            reg);
 2837     gnc_prefs_register_cb (GNC_PREFS_GROUP_GENERAL_REGISTER,
 2838                            GNC_PREF_SHOW_LEAF_ACCT_NAMES,
 2839                            split_register_pref_changed,
 2840                            reg);
 2841     gnc_prefs_register_cb (GNC_PREFS_GROUP_GENERAL_REGISTER,
 2842                            GNC_PREF_ALT_COLOR_BY_TRANS,
 2843                            split_register_pref_changed,
 2844                            reg);
 2845     gnc_book_option_register_cb(OPTION_NAME_NUM_FIELD_SOURCE,
 2846                                 split_register_book_option_changed,
 2847                                 reg);
 2848 
 2849     reg->sr_info = NULL;
 2850 
 2851     reg->unrecn_splits = NULL;
 2852 
 2853     reg->show_leaf_accounts = gnc_prefs_get_bool(GNC_PREFS_GROUP_GENERAL_REGISTER,
 2854                                             GNC_PREF_SHOW_LEAF_ACCT_NAMES);
 2855     reg->double_alt_color = gnc_prefs_get_bool(GNC_PREFS_GROUP_GENERAL_REGISTER,
 2856                                             GNC_PREF_ALT_COLOR_BY_TRANS);
 2857 
 2858     reg->type = type;
 2859     reg->style = style;
 2860     reg->use_double_line = use_double_line;
 2861     reg->do_auto_complete = do_auto_complete;
 2862     reg->is_template = is_template;
 2863     reg->use_tran_num_for_num_field =
 2864                 (qof_book_use_split_action_for_num_field(gnc_get_current_book())
 2865                     ? FALSE : TRUE);
 2866 
 2867     layout = gnc_split_register_layout_new (reg);
 2868 
 2869     if (is_template)
 2870         model = gnc_template_register_model_new ();
 2871     else
 2872         model = gnc_split_register_model_new ();
 2873     model->handler_user_data = reg;
 2874 
 2875     control = gnc_split_register_control_new ();
 2876     control->user_data = reg;
 2877 
 2878     reg->table = gnc_table_new (layout, model, control);
 2879 
 2880     gnc_split_register_config_cells (reg);
 2881 
 2882     /* Set up header */
 2883     {
 2884         VirtualCellLocation vcell_loc = { 0, 0 };
 2885         CellBlock *header;
 2886 
 2887         header = gnc_table_layout_get_cursor (reg->table->layout, CURSOR_HEADER);
 2888 
 2889         gnc_table_set_vcell (reg->table, header, NULL, TRUE, TRUE, vcell_loc);
 2890     }
 2891 
 2892     /* Set up first and only initial row */
 2893     {
 2894         VirtualLocation vloc;
 2895         CellBlock *cursor;
 2896 
 2897         vloc.vcell_loc.virt_row = 1;
 2898         vloc.vcell_loc.virt_col = 0;
 2899         vloc.phys_row_offset = 0;
 2900         vloc.phys_col_offset = 0;
 2901 
 2902         cursor = gnc_table_layout_get_cursor (reg->table->layout,
 2903                                               CURSOR_SINGLE_LEDGER);
 2904 
 2905         gnc_table_set_vcell (reg->table, cursor, NULL, TRUE, TRUE, vloc.vcell_loc);
 2906 
 2907         if (gnc_table_find_close_valid_cell (reg->table, &vloc, FALSE))
 2908             gnc_table_move_cursor (reg->table, vloc);
 2909         else
 2910         {
 2911             PERR ("Can't find valid initial location");
 2912         }
 2913     }
 2914 }
 2915 
 2916 SplitRegister *
 2917 gnc_split_register_new (SplitRegisterType type,
 2918                         SplitRegisterStyle style,
 2919                         gboolean use_double_line,
 2920                         gboolean is_template)
 2921 {
 2922     SplitRegister * reg;
 2923     gboolean default_do_auto_complete = TRUE;
 2924 
 2925     reg = g_new0 (SplitRegister, 1);
 2926 
 2927     if (type >= NUM_SINGLE_REGISTER_TYPES)
 2928         style = REG_STYLE_JOURNAL;
 2929 
 2930     gnc_split_register_init (reg,
 2931                              type,
 2932                              style,
 2933                              use_double_line,
 2934                              default_do_auto_complete,
 2935                              is_template);
 2936 
 2937     return reg;
 2938 }
 2939 
 2940 void
 2941 gnc_split_register_config (SplitRegister *reg,
 2942                            SplitRegisterType newtype,
 2943                            SplitRegisterStyle newstyle,
 2944                            gboolean use_double_line)
 2945 {
 2946     if (!reg) return;
 2947 
 2948     /* If shrinking the transaction split, put the cursor on the first row of the trans */
 2949     if (reg->use_double_line && !use_double_line)
 2950     {
 2951         VirtualLocation virt_loc = reg->table->current_cursor_loc;
 2952         if (gnc_table_find_close_valid_cell (reg->table, &virt_loc, FALSE))
 2953         {
 2954             if (virt_loc.phys_row_offset)
 2955             {
 2956                 gnc_table_move_vertical_position (reg->table, &virt_loc, -virt_loc.phys_row_offset);
 2957                 gnc_table_move_cursor_gui (reg->table, virt_loc);
 2958             }
 2959         }
 2960         else
 2961         {
 2962             /* WTF?  Go to a known safe location. */
 2963             virt_loc.vcell_loc.virt_row = 1;
 2964             virt_loc.vcell_loc.virt_col = 0;
 2965             virt_loc.phys_row_offset = 0;
 2966             virt_loc.phys_col_offset = 0;
 2967             gnc_table_move_cursor_gui (reg->table, virt_loc);
 2968         }
 2969     }
 2970 
 2971     reg->type = newtype;
 2972 
 2973     if (reg->type >= NUM_SINGLE_REGISTER_TYPES)
 2974         newstyle = REG_STYLE_JOURNAL;
 2975 
 2976     reg->style = newstyle;
 2977     reg->use_double_line = use_double_line;
 2978 
 2979     gnc_table_realize_gui (reg->table);
 2980 }
 2981 
 2982 void
 2983 gnc_split_register_set_auto_complete(SplitRegister *reg,
 2984                                      gboolean do_auto_complete)
 2985 {
 2986     g_return_if_fail(reg);
 2987     reg->do_auto_complete = do_auto_complete;
 2988 }
 2989 
 2990 static void
 2991 gnc_split_register_destroy_info (SplitRegister *reg)
 2992 {
 2993     SRInfo *info;
 2994 
 2995     if (reg == NULL)
 2996         return;
 2997 
 2998     if (reg->unrecn_splits != NULL)
 2999     {
 3000         g_list_free (reg->unrecn_splits);
 3001         reg->unrecn_splits =  NULL;
 3002     }
 3003 
 3004     info = reg->sr_info;
 3005     if (!info)
 3006         return;
 3007 
 3008     g_free (info->debit_str);
 3009     g_free (info->tdebit_str);
 3010     g_free (info->credit_str);
 3011     g_free (info->tcredit_str);
 3012 
 3013     info->debit_str = NULL;
 3014     info->tdebit_str = NULL;
 3015     info->credit_str = NULL;
 3016     info->tcredit_str = NULL;
 3017 
 3018     g_free (reg->sr_info);
 3019 
 3020     reg->sr_info = NULL;
 3021 }
 3022 
 3023 void
 3024 gnc_split_register_set_data (SplitRegister *reg, void *user_data,
 3025                              SRGetParentCallback get_parent)
 3026 {
 3027     SRInfo *info = gnc_split_register_get_info (reg);
 3028 
 3029     g_return_if_fail (reg != NULL);
 3030 
 3031     info->user_data = user_data;
 3032     info->get_parent = get_parent;
 3033 }
 3034 
 3035 static void
 3036 gnc_split_register_cleanup (SplitRegister *reg)
 3037 {
 3038     SRInfo *info = gnc_split_register_get_info (reg);
 3039     Transaction *pending_trans;
 3040     Transaction *blank_trans = NULL;
 3041     Split *blank_split;
 3042 
 3043     ENTER("reg=%p", reg);
 3044 
 3045     blank_split = xaccSplitLookup (&info->blank_split_guid,
 3046                                    gnc_get_current_book ());
 3047 
 3048     pending_trans = xaccTransLookup (&info->pending_trans_guid,
 3049                                      gnc_get_current_book ());
 3050 
 3051     gnc_suspend_gui_refresh ();
 3052 
 3053     /* Destroy the transaction containing the "blank split", which was only
 3054      * created to support the area for entering a new transaction. Since the
 3055      * register is closing, this transaction is no longer needed. */
 3056     if (blank_split != NULL)
 3057     {
 3058         gboolean was_open;
 3059 
 3060         blank_trans = xaccSplitGetParent (blank_split);
 3061 
 3062         DEBUG("blank_split=%p, blank_trans=%p, pending_trans=%p",
 3063               blank_split, blank_trans, pending_trans);
 3064 
 3065         /* Destroying the transaction will automatically remove its splits. */
 3066         was_open = xaccTransIsOpen (blank_trans);
 3067         xaccTransDestroy (blank_trans);
 3068         if (was_open)
 3069             xaccTransCommitEdit (blank_trans);
 3070 
 3071         /* Update the register info. */
 3072         if (blank_trans == pending_trans)
 3073         {
 3074             info->pending_trans_guid = *guid_null ();
 3075             pending_trans = NULL;
 3076         }
 3077         info->blank_split_guid = *guid_null ();
 3078         info->auto_complete = FALSE;
 3079         blank_split = NULL;
 3080     }
 3081 
 3082     /* be sure to take care of any open transactions */
 3083     if (pending_trans != NULL)
 3084     {
 3085         g_critical("BUG DETECTED: pending_trans=%p, blank_split=%p, blank_trans=%p",
 3086                    pending_trans, blank_split, blank_trans);
 3087         g_assert_not_reached();
 3088         info->pending_trans_guid = *guid_null ();
 3089         /* CAS: It's not clear to me that we'd really want to commit
 3090            here, rather than rollback. But, maybe this is just dead
 3091            code. */
 3092         if (xaccTransIsOpen (pending_trans))
 3093             xaccTransCommitEdit (pending_trans);
 3094         else g_assert_not_reached();
 3095 
 3096         pending_trans = NULL;
 3097     }
 3098 
 3099     gnc_split_register_destroy_info (reg);
 3100 
 3101     gnc_resume_gui_refresh ();
 3102 
 3103     LEAVE(" ");
 3104 }
 3105 
 3106 void
 3107 gnc_split_register_destroy (SplitRegister *reg)
 3108 {
 3109     g_return_if_fail(reg);
 3110 
 3111     ENTER("reg=%p", reg);
 3112 
 3113     gnc_prefs_remove_cb_by_func (GNC_PREFS_GROUP_GENERAL,
 3114                                  GNC_PREF_ACCOUNTING_LABELS,
 3115                                  split_register_pref_changed,
 3116                                  reg);
 3117     gnc_prefs_remove_cb_by_func (GNC_PREFS_GROUP_GENERAL,
 3118                                  GNC_PREF_ACCOUNT_SEPARATOR,
 3119                                  split_register_pref_changed,
 3120                                  reg);
 3121     gnc_prefs_remove_cb_by_func (GNC_PREFS_GROUP_GENERAL_REGISTER,
 3122                                  GNC_PREF_SHOW_LEAF_ACCT_NAMES,
 3123                                  split_register_pref_changed,
 3124                                  reg);
 3125     gnc_prefs_remove_cb_by_func (GNC_PREFS_GROUP_GENERAL_REGISTER,
 3126                                  GNC_PREF_ALT_COLOR_BY_TRANS,
 3127                                  split_register_pref_changed,
 3128                                  reg);
 3129     gnc_book_option_remove_cb (OPTION_NAME_NUM_FIELD_SOURCE,
 3130                                  split_register_book_option_changed,
 3131                                  reg);
 3132 
 3133     gnc_split_register_cleanup (reg);
 3134 
 3135     gnc_table_destroy (reg->table);
 3136     reg->table = NULL;
 3137 
 3138     /* free the memory itself */
 3139     g_free (reg);
 3140     LEAVE(" ");
 3141 }
 3142 
 3143 void
 3144 gnc_split_register_set_read_only (SplitRegister *reg, gboolean read_only)
 3145 {
 3146     gnc_table_model_set_read_only (reg->table->model, read_only);
 3147 }