From f039cc80e989a6ce3a5a024c8bc941e738408199 Mon Sep 17 00:00:00 2001 From: Geert Janssens Date: Wed, 20 Nov 2019 19:35:50 +0100 Subject: [PATCH 1/8] Fix ninja-build check without running ninja-build first The (gnucash reports) guile module should be built before the reports depending on it. --- gnucash/report/reports/CMakeLists.txt | 15 ++++++++------- .../report/reports/standard/budget-barchart.scm | 1 - gnucash/report/test/CMakeLists.txt | 1 + 3 files changed, 9 insertions(+), 8 deletions(-) diff --git a/gnucash/report/reports/CMakeLists.txt b/gnucash/report/reports/CMakeLists.txt index b1daa74bcf..fabe04a904 100644 --- a/gnucash/report/reports/CMakeLists.txt +++ b/gnucash/report/reports/CMakeLists.txt @@ -109,6 +109,7 @@ set(scm_rpt_std_GUILE_DEPENDS ${scm_rpts_GUILE_DEPENDS} scm-app-utils scm-gnc-module + scm-rpt-reports scm-reports-common-links scm-reports-standard-links ) @@ -120,6 +121,13 @@ gnc_add_scheme_targets(scm-reports-common TRUE ) +gnc_add_scheme_targets(scm-rpt-reports + "${reports_SCHEME}" + "gnucash" + "${scm_rpts_GUILE_DEPENDS}" + TRUE +) + gnc_add_scheme_targets(scm-reports-standard "${reports_standard_SCHEME}" "gnucash/reports/standard" @@ -148,13 +156,6 @@ gnc_add_scheme_targets(scm-reports-de_DE TRUE ) -gnc_add_scheme_targets(scm-rpt-reports - "${reports_SCHEME}" - "gnucash" - "scm-reports-standard;scm-reports-example;scm-reports-us;scm-reports-de_DE;${scm_rpts_GUILE_DEPENDS};" - TRUE -) - gnc_add_scheme_targets(scm-reports-standard-2 "${reports_standard_SCHEME_2}" "gnucash/reports/standard" diff --git a/gnucash/report/reports/standard/budget-barchart.scm b/gnucash/report/reports/standard/budget-barchart.scm index f1a9721c6e..f89b0edac6 100644 --- a/gnucash/report/reports/standard/budget-barchart.scm +++ b/gnucash/report/reports/standard/budget-barchart.scm @@ -32,7 +32,6 @@ (use-modules (gnucash gettext)) (gnc:module-load "gnucash/report" 0) -(use-modules (gnucash reports)) (define reportname (N_ "Budget Chart")) diff --git a/gnucash/report/test/CMakeLists.txt b/gnucash/report/test/CMakeLists.txt index a9ce3b81e7..323c60e75f 100644 --- a/gnucash/report/test/CMakeLists.txt +++ b/gnucash/report/test/CMakeLists.txt @@ -34,6 +34,7 @@ set(GUILE_DEPENDS scm-scm scm-report-2 scm-test-report + scm-report-stylesheets ) gnc_add_scheme_tests("${scm_test_report_SOURCES}") From efefac3e1e8c8c1cced71c6d8b02e53d14779dc4 Mon Sep 17 00:00:00 2001 From: Geert Janssens Date: Tue, 8 Oct 2019 17:29:02 +0200 Subject: [PATCH 2/8] Dead code removal --- libgnucash/app-utils/guile-util.c | 33 ------------------------------- libgnucash/app-utils/guile-util.h | 5 ----- 2 files changed, 38 deletions(-) diff --git a/libgnucash/app-utils/guile-util.c b/libgnucash/app-utils/guile-util.c index 2628919854..4543695d11 100644 --- a/libgnucash/app-utils/guile-util.c +++ b/libgnucash/app-utils/guile-util.c @@ -157,39 +157,6 @@ initialize_scm_functions() scm_funcs_inited = TRUE; } - -/********************************************************************\ - gnc_scm_lookup - - returns the SCM binding associated with the given symbol function, - or SCM_UNDEFINED if it couldn't be retrieved. - - Don't use this to get hold of symbols that are considered private - to a given module unless the C code you're writing is considered - part of that module. - - Args: - - module - where to lookup the symbol, something like "ice-9 debug" - symbol - what to look up. - - Returns: value bound to the symbol, if any. -\********************************************************************/ - -#if 0 - -************ NOT TESTED YET ************** - -SCM -gnc_scm_lookup(const char *module, const char *symbol) -{ - SCM scm_module = scm_c_resolve_module(module); - SCM value = scm_c_module_lookup(scm_module, symbol); - return value; -} - -#endif - /********************************************************************\ * gnc_copy_split * * returns a scheme representation of a split. If the split is * diff --git a/libgnucash/app-utils/guile-util.h b/libgnucash/app-utils/guile-util.h index 1624349ca5..c7a523cb8f 100644 --- a/libgnucash/app-utils/guile-util.h +++ b/libgnucash/app-utils/guile-util.h @@ -32,11 +32,6 @@ #include "Account.h" #include "gnc-guile-utils.h" -/* Don't use this to get hold of symbols that are considered private - * to a given module unless the C code you're writing is considered - * part of that module. */ -SCM gnc_scm_lookup(const char *module, const char *symbol); - /* The next set of functions is for manipulating scheme * representations of splits and transactions. */ gboolean gnc_is_split_scm(SCM scm); From 02afa33e5486481b55d7bec03708c4cfe9f6bc00 Mon Sep 17 00:00:00 2001 From: Geert Janssens Date: Tue, 8 Oct 2019 17:46:00 +0200 Subject: [PATCH 3/8] app-utils - reduce guile-util api-surface Make internal-use only function static and drop two unused functions. --- libgnucash/app-utils/guile-util.c | 55 ++----------------------------- libgnucash/app-utils/guile-util.h | 4 --- 2 files changed, 2 insertions(+), 57 deletions(-) diff --git a/libgnucash/app-utils/guile-util.c b/libgnucash/app-utils/guile-util.c index 4543695d11..fdf997d5c7 100644 --- a/libgnucash/app-utils/guile-util.c +++ b/libgnucash/app-utils/guile-util.c @@ -110,7 +110,6 @@ struct _Process gboolean detached; }; - static void initialize_scm_functions() { @@ -242,7 +241,7 @@ gnc_copy_split_scm_onto_split(SCM split_scm, Split *split, * Args: scm - a scheme object * * Returns: true if scm is a scheme split * \********************************************************************/ -gboolean +static gboolean gnc_is_split_scm(SCM scm) { initialize_scm_functions(); @@ -258,7 +257,7 @@ gnc_is_split_scm(SCM scm) * Args: scm - a scheme object * * Returns: true if scm is a scheme transaction * \********************************************************************/ -gboolean +static gboolean gnc_is_trans_scm(SCM scm) { initialize_scm_functions(); @@ -420,56 +419,6 @@ gnc_split_scm_set_value(SCM split_scm, gnc_numeric value) } -/********************************************************************\ - * gnc_split_scm_get_memo * - * return the newly allocated memo of a scheme split, or NULL. * - * * - * Args: split_scm - the scheme split * - * Returns: newly allocated memo string, must be freed with g_free * -\********************************************************************/ -char * -gnc_split_scm_get_memo(SCM split_scm) -{ - SCM result; - - initialize_scm_functions(); - - if (!gnc_is_split_scm(split_scm)) - return NULL; - - result = scm_call_1(getters.split_scm_memo, split_scm); - if (!scm_is_string(result)) - return NULL; - - return gnc_scm_to_utf8_string(result); -} - - -/**********************************************************************\ - * gnc_split_scm_get_action * - * return the newly allocated action of a scheme split, or NULL. * - * * - * Args: split_scm - the scheme split * - * Returns: newly allocated action string, must be freed with g_free * -\**********************************************************************/ -char * -gnc_split_scm_get_action(SCM split_scm) -{ - SCM result; - - initialize_scm_functions(); - - if (!gnc_is_split_scm(split_scm)) - return NULL; - - result = scm_call_1(getters.split_scm_action, split_scm); - if (!scm_is_string(result)) - return NULL; - - return gnc_scm_to_utf8_string(result); -} - - /********************************************************************\ * gnc_split_scm_get_amount * * return the amount of a scheme split * diff --git a/libgnucash/app-utils/guile-util.h b/libgnucash/app-utils/guile-util.h index c7a523cb8f..a66ce2e39a 100644 --- a/libgnucash/app-utils/guile-util.h +++ b/libgnucash/app-utils/guile-util.h @@ -34,8 +34,6 @@ /* The next set of functions is for manipulating scheme * representations of splits and transactions. */ -gboolean gnc_is_split_scm(SCM scm); -gboolean gnc_is_trans_scm(SCM scm); SCM gnc_copy_split(Split *split, gboolean use_cut_semantics); void gnc_copy_split_scm_onto_split(SCM split_scm, Split *split, @@ -48,8 +46,6 @@ void gnc_split_scm_set_reconcile_state(SCM split_scm, char reconcile_state); void gnc_split_scm_set_amount(SCM split_scm, gnc_numeric amount); void gnc_split_scm_set_value(SCM split_scm, gnc_numeric value); -char * gnc_split_scm_get_memo(SCM split_scm); -char * gnc_split_scm_get_action(SCM split_scm); gnc_numeric gnc_split_scm_get_amount(SCM split_scm); gnc_numeric gnc_split_scm_get_value(SCM split_scm); From 9f5cbb3a82b8000d776e95655821723f9511174b Mon Sep 17 00:00:00 2001 From: Geert Janssens Date: Wed, 9 Oct 2019 20:48:11 +0200 Subject: [PATCH 4/8] app-utils - move register's copy operations to ledger-core They are only used by split-register.c in that directory --- gnucash/register/ledger-core/CMakeLists.txt | 2 + .../ledger-core/split-register-copy-ops.c | 711 ++++++++++++++++++ .../ledger-core/split-register-copy-ops.h | 69 ++ gnucash/register/ledger-core/split-register.c | 1 + libgnucash/app-utils/guile-util.c | 622 --------------- libgnucash/app-utils/guile-util.h | 32 - po/POTFILES.in | 1 + 7 files changed, 784 insertions(+), 654 deletions(-) create mode 100644 gnucash/register/ledger-core/split-register-copy-ops.c create mode 100644 gnucash/register/ledger-core/split-register-copy-ops.h diff --git a/gnucash/register/ledger-core/CMakeLists.txt b/gnucash/register/ledger-core/CMakeLists.txt index 9721067344..0b671cee28 100644 --- a/gnucash/register/ledger-core/CMakeLists.txt +++ b/gnucash/register/ledger-core/CMakeLists.txt @@ -7,6 +7,7 @@ set (ledger_core_SOURCES gncmod-ledger-core.c split-register.c split-register-control.c + split-register-copy-ops.c split-register-layout.c split-register-load.c split-register-model.c @@ -26,6 +27,7 @@ set (ledger_core_HEADERS gnc-ledger-display2.h split-register.h split-register-control.h + split-register-copy-ops.h split-register-layout.h split-register-model.h split-register-model-save.h diff --git a/gnucash/register/ledger-core/split-register-copy-ops.c b/gnucash/register/ledger-core/split-register-copy-ops.c new file mode 100644 index 0000000000..8efe5e71c0 --- /dev/null +++ b/gnucash/register/ledger-core/split-register-copy-ops.c @@ -0,0 +1,711 @@ +/********************************************************************\ + * split-register-copy-ops.c -- implement copy/paste semantics for * + * transactions and splits * + * Copyright (C) 1999 Linas Vepstas * + * Copyright (C) 2000 Dave Peticolas * + * Copyright (C) 2017 Aaron Laws * + * * + * This program is free software; you can redistribute it and/or * + * modify it under the terms of the GNU General Public License as * + * published by the Free Software Foundation; either version 2 of * + * the License, or (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License* + * along with this program; if not, write to the Free Software * + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * +\********************************************************************/ + +#include + +#include "swig-runtime.h" +#include +#if PLATFORM(WINDOWS) +#include +#include +#endif + +#include +#include +#include +#ifdef __MINGW32__ +#define _GL_UNISTD_H //Deflect poisonous define of close in Guile's GnuLib +#endif +#include +#include +#ifdef HAVE_UNISTD_H +# ifdef close +# undef close +# endif +# include +#else +# include +# define close _close +#endif +#ifndef HAVE_STRPTIME +# include "strptime.h" +#endif + +#include "qof.h" +#include "gnc-engine-guile.h" +#include "glib-guile.h" +#include "gnc-glib-utils.h" +#include "gnc-guile-utils.h" +#include "gnc-prefs.h" +#include "guile-mappings.h" +#include "split-register-copy-ops.h" + +#define UNUSED_VAR __attribute__ ((unused)) + +/* This static indicates the debugging module this .o belongs to. */ +static QofLogModule UNUSED_VAR log_module = GNC_MOD_GUILE; + +struct _setters +{ + SCM split_scm_account_guid; + SCM split_scm_memo; + SCM split_scm_action; + SCM split_scm_reconcile_state; + SCM split_scm_amount; + SCM split_scm_value; + + SCM trans_scm_date; + SCM trans_scm_num; + SCM trans_scm_description; + SCM trans_scm_notes; + SCM trans_scm_append_split_scm; +} setters; + +struct _getters +{ + SCM split_scm_memo; + SCM split_scm_action; + SCM split_scm_amount; + SCM split_scm_value; + + SCM trans_scm_split_scms; + SCM trans_scm_split_scm; + SCM trans_scm_other_split_scm; +} getters; + +struct _predicates +{ + SCM is_split_scm; + SCM is_trans_scm; +} predicates; + +struct _Process +{ + GPid pid; + gint fd_stdin; + gint fd_stdout; + gint fd_stderr; + gboolean dead; + gboolean detached; +}; + +static void +initialize_scm_functions() +{ + static gboolean scm_funcs_inited = FALSE; + + if (scm_funcs_inited) + return; + + setters.split_scm_account_guid = + scm_c_eval_string("gnc:split-scm-set-account-guid"); + setters.split_scm_memo = scm_c_eval_string("gnc:split-scm-set-memo"); + setters.split_scm_action = scm_c_eval_string("gnc:split-scm-set-action"); + setters.split_scm_reconcile_state = + scm_c_eval_string("gnc:split-scm-set-reconcile-state"); + setters.split_scm_amount = scm_c_eval_string("gnc:split-scm-set-amount"); + setters.split_scm_value = scm_c_eval_string("gnc:split-scm-set-value"); + + setters.trans_scm_date = scm_c_eval_string("gnc:transaction-scm-set-date-posted"); + setters.trans_scm_num = scm_c_eval_string("gnc:transaction-scm-set-num"); + setters.trans_scm_description = + scm_c_eval_string("gnc:transaction-scm-set-description"); + setters.trans_scm_notes = scm_c_eval_string("gnc:transaction-scm-set-notes"); + setters.trans_scm_append_split_scm = + scm_c_eval_string("gnc:transaction-scm-append-split-scm"); + + getters.split_scm_memo = scm_c_eval_string("gnc:split-scm-get-memo"); + getters.split_scm_action = scm_c_eval_string("gnc:split-scm-get-action"); + getters.split_scm_amount = scm_c_eval_string("gnc:split-scm-get-amount"); + getters.split_scm_value = scm_c_eval_string("gnc:split-scm-get-value"); + + getters.trans_scm_split_scms = + scm_c_eval_string("gnc:transaction-scm-get-split-scms"); + getters.trans_scm_split_scm = + scm_c_eval_string("gnc:transaction-scm-get-split-scm"); + getters.trans_scm_other_split_scm = + scm_c_eval_string("gnc:transaction-scm-get-other-split-scm"); + + predicates.is_split_scm = scm_c_eval_string("gnc:split-scm?"); + predicates.is_trans_scm = scm_c_eval_string("gnc:transaction-scm?"); + + scm_funcs_inited = TRUE; +} + +/********************************************************************\ + * gnc_copy_split * + * returns a scheme representation of a split. If the split is * + * NULL, SCM_UNDEFINED is returned. * + * * + * Args: split - the split to copy * + * use_cut_semantics - if TRUE, copy is for a 'cut' operation * + * Returns: SCM representation of split or SCM_UNDEFINED * +\********************************************************************/ +SCM +gnc_copy_split(Split *split, gboolean use_cut_semantics) +{ + static swig_type_info *split_type = NULL; + SCM func; + SCM arg; + + if (split == NULL) + return SCM_UNDEFINED; + + func = scm_c_eval_string("gnc:split->split-scm"); + if (!scm_is_procedure(func)) + return SCM_UNDEFINED; + + if (!split_type) + split_type = SWIG_TypeQuery("_p_Split"); + + arg = SWIG_NewPointerObj(split, split_type, 0); + + return scm_call_2(func, arg, SCM_BOOL(use_cut_semantics)); +} + + +/********************************************************************\ + * gnc_copy_split_scm_onto_split * + * copies a scheme representation of a split onto an actual split.* + * * + * Args: split_scm - the scheme representation of a split * + * split - the split to copy onto * + * Returns: Nothing * +\********************************************************************/ +void +gnc_copy_split_scm_onto_split(SCM split_scm, Split *split, + QofBook * book) +{ + static swig_type_info *split_type = NULL; + SCM result; + SCM func; + SCM arg; + + if (split_scm == SCM_UNDEFINED) + return; + + if (split == NULL) + return; + + g_return_if_fail (book); + + func = scm_c_eval_string("gnc:split-scm?"); + if (!scm_is_procedure(func)) + return; + + result = scm_call_1(func, split_scm); + if (!scm_is_true(result)) + return; + + func = scm_c_eval_string("gnc:split-scm-onto-split"); + if (!scm_is_procedure(func)) + return; + + if (!split_type) + split_type = SWIG_TypeQuery("_p_Split"); + + arg = SWIG_NewPointerObj(split, split_type, 0); + + scm_call_3(func, split_scm, arg, gnc_book_to_scm (book)); +} + + +/********************************************************************\ + * gnc_is_split_scm * + * returns true if the scm object is a scheme split * + * * + * Args: scm - a scheme object * + * Returns: true if scm is a scheme split * +\********************************************************************/ +static gboolean +gnc_is_split_scm(SCM scm) +{ + initialize_scm_functions(); + + return scm_is_true(scm_call_1(predicates.is_split_scm, scm)); +} + + +/********************************************************************\ + * gnc_is_trans_scm * + * returns true if the scm object is a scheme transaction * + * * + * Args: scm - a scheme object * + * Returns: true if scm is a scheme transaction * +\********************************************************************/ +static gboolean +gnc_is_trans_scm(SCM scm) +{ + initialize_scm_functions(); + + return scm_is_true(scm_call_1(predicates.is_trans_scm, scm)); +} + + +/********************************************************************\ + * gnc_split_scm_set_account * + * set the account of a scheme representation of a split. * + * * + * Args: split_scm - the scheme split * + * account - the account to set * + * Returns: Nothing * +\********************************************************************/ +void +gnc_split_scm_set_account(SCM split_scm, Account *account) +{ + gchar guid_string[GUID_ENCODING_LENGTH+1]; + SCM arg; + + initialize_scm_functions(); + + if (!gnc_is_split_scm(split_scm)) + return; + if (account == NULL) + return; + + guid_to_string_buff(xaccAccountGetGUID(account), guid_string); + if (strlen(guid_string) == 0) + return; + + arg = scm_from_utf8_string(guid_string); + + scm_call_2(setters.split_scm_account_guid, split_scm, arg); +} + + +/********************************************************************\ + * gnc_split_scm_set_memo * + * set the memo of a scheme representation of a split. * + * * + * Args: split_scm - the scheme split * + * memo - the memo to set * + * Returns: Nothing * +\********************************************************************/ +void +gnc_split_scm_set_memo(SCM split_scm, const char *memo) +{ + SCM arg; + + initialize_scm_functions(); + + if (!gnc_is_split_scm(split_scm)) + return; + if (memo == NULL) + return; + + arg = scm_from_utf8_string(memo); + + scm_call_2(setters.split_scm_memo, split_scm, arg); +} + + +/********************************************************************\ + * gnc_split_scm_set_action * + * set the action of a scheme representation of a split. * + * * + * Args: split_scm - the scheme split * + * action - the action to set * + * Returns: Nothing * +\********************************************************************/ +void +gnc_split_scm_set_action(SCM split_scm, const char *action) +{ + SCM arg; + + initialize_scm_functions(); + + if (!gnc_is_split_scm(split_scm)) + return; + if (action == NULL) + return; + + arg = scm_from_utf8_string(action); + + scm_call_2(setters.split_scm_action, split_scm, arg); +} + + +/********************************************************************\ + * gnc_split_scm_set_reconcile_state * + * set the reconcile state of a scheme split. * + * * + * Args: split_scm - the scheme split * + * reconcile_state - the reconcile state to set * + * Returns: Nothing * +\********************************************************************/ +void +gnc_split_scm_set_reconcile_state(SCM split_scm, char reconcile_state) +{ + SCM arg; + + initialize_scm_functions(); + + if (!gnc_is_split_scm(split_scm)) + return; + + arg = SCM_MAKE_CHAR(reconcile_state); + + scm_call_2(setters.split_scm_reconcile_state, split_scm, arg); +} + + +/********************************************************************\ + * gnc_split_scm_set_amount * + * set the amount of a scheme split * + * * + * Args: split_scm - the scheme split * + * amount - the amount to set * + * Returns: Nothing * +\********************************************************************/ +void +gnc_split_scm_set_amount(SCM split_scm, gnc_numeric amount) +{ + SCM arg; + + initialize_scm_functions(); + + if (!gnc_is_split_scm(split_scm)) + return; + + arg = gnc_numeric_to_scm(amount); + scm_call_2(setters.split_scm_amount, split_scm, arg); +} + + +/********************************************************************\ + * gnc_split_scm_set_value * + * set the value of a scheme split * + * * + * Args: split_scm - the scheme split * + * value - the value to set * + * Returns: Nothing * +\********************************************************************/ +void +gnc_split_scm_set_value(SCM split_scm, gnc_numeric value) +{ + SCM arg; + + initialize_scm_functions(); + + if (!gnc_is_split_scm(split_scm)) + return; + + arg = gnc_numeric_to_scm(value); + scm_call_2(setters.split_scm_value, split_scm, arg); +} + + +/********************************************************************\ + * gnc_split_scm_get_amount * + * return the amount of a scheme split * + * * + * Args: split_scm - the scheme split * + * Returns: amount of scheme split * +\********************************************************************/ +gnc_numeric +gnc_split_scm_get_amount(SCM split_scm) +{ + SCM result; + + initialize_scm_functions(); + + if (!gnc_is_split_scm(split_scm)) + return gnc_numeric_zero (); + + result = scm_call_1(getters.split_scm_amount, split_scm); + if (!scm_rational_p(result)) + return gnc_numeric_zero (); + + return gnc_scm_to_numeric(result); +} + + +/********************************************************************\ + * gnc_split_scm_get_value * + * return the value of a scheme split * + * * + * Args: split_scm - the scheme split * + * Returns: value of scheme split * +\********************************************************************/ +gnc_numeric +gnc_split_scm_get_value(SCM split_scm) +{ + SCM result; + + initialize_scm_functions(); + + if (!gnc_is_split_scm(split_scm)) + return gnc_numeric_zero (); + + result = scm_call_1(getters.split_scm_value, split_scm); + if (!scm_rational_p(result)) + return gnc_numeric_zero (); + + return gnc_scm_to_numeric(result); +} + + +/********************************************************************\ + * gnc_copy_trans * + * returns a scheme representation of a transaction. If the * + * transaction is NULL, SCM_UNDEFINED is returned. * + * * + * Args: trans - the transaction to copy * + * use_cut_semantics - if TRUE, copy is for a 'cut' operation * + * Returns: SCM representation of transaction or SCM_UNDEFINED * +\********************************************************************/ +SCM +gnc_copy_trans(Transaction *trans, gboolean use_cut_semantics) +{ + static swig_type_info *trans_type = NULL; + SCM func; + SCM arg; + + if (trans == NULL) + return SCM_UNDEFINED; + + func = scm_c_eval_string("gnc:transaction->transaction-scm"); + if (!scm_is_procedure(func)) + return SCM_UNDEFINED; + + if (!trans_type) + trans_type = SWIG_TypeQuery("_p_Transaction"); + + arg = SWIG_NewPointerObj(trans, trans_type, 0); + + return scm_call_2(func, arg, SCM_BOOL(use_cut_semantics)); +} + + +/********************************************************************\ + * gnc_copy_trans_scm_onto_trans * + * copies a scheme representation of a transaction onto * + * an actual transaction. * + * * + * Args: trans_scm - the scheme representation of a transaction * + * trans - the transaction to copy onto * + * Returns: Nothing * +\********************************************************************/ +void +gnc_copy_trans_scm_onto_trans(SCM trans_scm, Transaction *trans, + gboolean do_commit, QofBook *book) +{ + gnc_copy_trans_scm_onto_trans_swap_accounts(trans_scm, trans, NULL, NULL, + do_commit, book); +} + + +/********************************************************************\ + * gnc_copy_trans_scm_onto_trans_swap_accounts * + * copies a scheme representation of a transaction onto * + * an actual transaction. If guid_1 and guid_2 are not NULL, * + * the account guids of the splits are swapped accordingly. * + * * + * Args: trans_scm - the scheme representation of a transaction * + * trans - the transaction to copy onto * + * guid_1 - account guid to swap with guid_2 * + * guid_2 - account guid to swap with guid_1 * + * do_commit - whether to commit the edits * + * Returns: Nothing * +\********************************************************************/ +void +gnc_copy_trans_scm_onto_trans_swap_accounts(SCM trans_scm, + Transaction *trans, + const GncGUID *guid_1, + const GncGUID *guid_2, + gboolean do_commit, + QofBook *book) +{ + static swig_type_info *trans_type = NULL; + SCM result; + SCM func; + SCM arg; + + if (trans_scm == SCM_UNDEFINED) + return; + + if (trans == NULL) + return; + + g_return_if_fail (book); + + func = scm_c_eval_string("gnc:transaction-scm?"); + if (!scm_is_procedure(func)) + return; + + result = scm_call_1(func, trans_scm); + if (!scm_is_true(result)) + return; + + func = scm_c_eval_string("gnc:transaction-scm-onto-transaction"); + if (!scm_is_procedure(func)) + return; + + if (!trans_type) + trans_type = SWIG_TypeQuery("_p_Transaction"); + + arg = SWIG_NewPointerObj(trans, trans_type, 0); + + if ((guid_1 == NULL) || (guid_2 == NULL)) + { + SCM args = SCM_EOL; + SCM commit; + + commit = SCM_BOOL(do_commit); + + args = scm_cons(gnc_book_to_scm (book), args); + args = scm_cons(commit, args); + args = scm_cons(SCM_EOL, args); + args = scm_cons(arg, args); + args = scm_cons(trans_scm, args); + + scm_apply(func, args, SCM_EOL); + } + else + { + gchar guidstr[GUID_ENCODING_LENGTH+1]; + SCM from, to; + SCM map = SCM_EOL; + SCM args = SCM_EOL; + SCM commit; + + args = scm_cons(gnc_book_to_scm (book), args); + + commit = SCM_BOOL(do_commit); + + args = scm_cons(commit, args); + + guid_to_string_buff(guid_1, guidstr); + from = scm_from_utf8_string(guidstr); + guid_to_string_buff(guid_2, guidstr); + to = scm_from_utf8_string(guidstr); + + map = scm_cons(scm_cons(from, to), map); + map = scm_cons(scm_cons(to, from), map); + + args = scm_cons(map, args); + args = scm_cons(arg, args); + args = scm_cons(trans_scm, args); + + scm_apply(func, args, SCM_EOL); + } +} + +/********************************************************************\ + * gnc_trans_scm_append_split_scm * + * append the scheme split onto the scheme transaction * + * * + * Args: trans_scm - the scheme transaction * + * split_scm - the scheme split to append * + * Returns: Nothing * +\********************************************************************/ +void +gnc_trans_scm_append_split_scm(SCM trans_scm, SCM split_scm) +{ + initialize_scm_functions(); + + if (!gnc_is_trans_scm(trans_scm)) + return; + if (!gnc_is_split_scm(split_scm)) + return; + + scm_call_2(setters.trans_scm_append_split_scm, trans_scm, split_scm); +} + + +/********************************************************************\ + * gnc_trans_scm_get_split_scm * + * get the indexth scheme split of a scheme transaction. * + * * + * Args: trans_scm - the scheme transaction * + * index - the index of the split to get * + * Returns: scheme split to get, or SCM_UNDEFINED if none * +\********************************************************************/ +SCM +gnc_trans_scm_get_split_scm(SCM trans_scm, int index) +{ + SCM arg; + + initialize_scm_functions(); + + if (!gnc_is_trans_scm(trans_scm)) + return SCM_UNDEFINED; + + arg = scm_from_int (index); + + return scm_call_2(getters.trans_scm_split_scm, trans_scm, arg); +} + + +/********************************************************************\ + * gnc_trans_scm_get_other_split_scm * + * get the other scheme split of a scheme transaction. * + * * + * Args: trans_scm - the scheme transaction * + * split_scm - the split not to get * + * Returns: other scheme split, or SCM_UNDEFINED if none * +\********************************************************************/ +SCM +gnc_trans_scm_get_other_split_scm(SCM trans_scm, SCM split_scm) +{ + SCM result; + + initialize_scm_functions(); + + if (!gnc_is_trans_scm(trans_scm)) + return SCM_UNDEFINED; + if (!gnc_is_split_scm(split_scm)) + return SCM_UNDEFINED; + + result = scm_call_2(getters.trans_scm_other_split_scm, trans_scm, split_scm); + + if (!gnc_is_split_scm(result)) + return SCM_UNDEFINED; + + return result; +} + + +/********************************************************************\ + * gnc_trans_scm_get_num_splits * + * get the number of scheme splits in a scheme transaction. * + * * + * Args: trans_scm - the scheme transaction * + * Returns: number of scheme splits in the transaction * +\********************************************************************/ +int +gnc_trans_scm_get_num_splits(SCM trans_scm) +{ + SCM result; + + initialize_scm_functions(); + + if (!gnc_is_trans_scm(trans_scm)) + return 0; + + result = scm_call_1(getters.trans_scm_split_scms, trans_scm); + + if (!scm_is_list(result)) + return 0; + + return scm_to_int(scm_length(result)); +} diff --git a/gnucash/register/ledger-core/split-register-copy-ops.h b/gnucash/register/ledger-core/split-register-copy-ops.h new file mode 100644 index 0000000000..b417f434ad --- /dev/null +++ b/gnucash/register/ledger-core/split-register-copy-ops.h @@ -0,0 +1,69 @@ +/********************************************************************\ + * split-register-copy-ops.h -- implement copy/paste semantics for * + * transactions and splits * + * Copyright (C) 1999 Linas Vepstas * + * Copyright (C) 2017 Aaron Laws * + * * + * This program is free software; you can redistribute it and/or * + * modify it under the terms of the GNU General Public License as * + * published by the Free Software Foundation; either version 2 of * + * the License, or (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License* + * along with this program; if not, contact: * + * * + * Free Software Foundation Voice: +1-617-542-5942 * + * 51 Franklin Street, Fifth Floor Fax: +1-617-542-2652 * + * Boston, MA 02110-1301, USA gnu@gnu.org * + * * +\********************************************************************/ + +#ifndef SPLIT_REGISTER_COPY_OPS_H +#define SPLIT_REGISTER_COPY_OPS_H + +#include +#include + +#include "qof.h" +#include "Account.h" +#include "gnc-guile-utils.h" + +/* The next set of functions is for manipulating scheme + * representations of splits and transactions. */ + +SCM gnc_copy_split(Split *split, gboolean use_cut_semantics); +void gnc_copy_split_scm_onto_split(SCM split_scm, Split *split, + QofBook *book); + +void gnc_split_scm_set_account(SCM split_scm, Account *account); +void gnc_split_scm_set_memo(SCM split_scm, const char *memo); +void gnc_split_scm_set_action(SCM split_scm, const char *action); +void gnc_split_scm_set_reconcile_state(SCM split_scm, char reconcile_state); +void gnc_split_scm_set_amount(SCM split_scm, gnc_numeric amount); +void gnc_split_scm_set_value(SCM split_scm, gnc_numeric value); + +gnc_numeric gnc_split_scm_get_amount(SCM split_scm); +gnc_numeric gnc_split_scm_get_value(SCM split_scm); + +SCM gnc_copy_trans(Transaction *trans, gboolean use_cut_semantics); +void gnc_copy_trans_scm_onto_trans(SCM trans_scm, Transaction *trans, + gboolean do_commit, QofBook *book); +void gnc_copy_trans_scm_onto_trans_swap_accounts(SCM trans_scm, + Transaction *trans, + const GncGUID *guid_1, + const GncGUID *guid_2, + gboolean do_commit, + QofBook *book); + +void gnc_trans_scm_append_split_scm(SCM trans_scm, SCM split_scm); + +SCM gnc_trans_scm_get_split_scm(SCM trans_scm, int index); +SCM gnc_trans_scm_get_other_split_scm(SCM trans_scm, SCM split_scm); +int gnc_trans_scm_get_num_splits(SCM trans_scm); + +#endif diff --git a/gnucash/register/ledger-core/split-register.c b/gnucash/register/ledger-core/split-register.c index e78f5d96c0..37c384724c 100644 --- a/gnucash/register/ledger-core/split-register.c +++ b/gnucash/register/ledger-core/split-register.c @@ -40,6 +40,7 @@ #include "gnc-ui.h" #include "gnc-warnings.h" #include "guile-util.h" +#include "split-register-copy-ops.h" #include "numcell.h" #include "pricecell.h" #include "quickfillcell.h" diff --git a/libgnucash/app-utils/guile-util.c b/libgnucash/app-utils/guile-util.c index fdf997d5c7..8b0a955834 100644 --- a/libgnucash/app-utils/guile-util.c +++ b/libgnucash/app-utils/guile-util.c @@ -63,43 +63,12 @@ /* This static indicates the debugging module this .o belongs to. */ static QofLogModule UNUSED_VAR log_module = GNC_MOD_GUILE; -struct _setters -{ - SCM split_scm_account_guid; - SCM split_scm_memo; - SCM split_scm_action; - SCM split_scm_reconcile_state; - SCM split_scm_amount; - SCM split_scm_value; - - SCM trans_scm_date; - SCM trans_scm_num; - SCM trans_scm_description; - SCM trans_scm_notes; - SCM trans_scm_append_split_scm; -} setters; - struct _getters { - SCM split_scm_memo; - SCM split_scm_action; - SCM split_scm_amount; - SCM split_scm_value; - - SCM trans_scm_split_scms; - SCM trans_scm_split_scm; - SCM trans_scm_other_split_scm; - SCM debit_string; SCM credit_string; } getters; -struct _predicates -{ - SCM is_split_scm; - SCM is_trans_scm; -} predicates; - struct _Process { GPid pid; @@ -118,603 +87,12 @@ initialize_scm_functions() if (scm_funcs_inited) return; - setters.split_scm_account_guid = - scm_c_eval_string("gnc:split-scm-set-account-guid"); - setters.split_scm_memo = scm_c_eval_string("gnc:split-scm-set-memo"); - setters.split_scm_action = scm_c_eval_string("gnc:split-scm-set-action"); - setters.split_scm_reconcile_state = - scm_c_eval_string("gnc:split-scm-set-reconcile-state"); - setters.split_scm_amount = scm_c_eval_string("gnc:split-scm-set-amount"); - setters.split_scm_value = scm_c_eval_string("gnc:split-scm-set-value"); - - setters.trans_scm_date = scm_c_eval_string("gnc:transaction-scm-set-date-posted"); - setters.trans_scm_num = scm_c_eval_string("gnc:transaction-scm-set-num"); - setters.trans_scm_description = - scm_c_eval_string("gnc:transaction-scm-set-description"); - setters.trans_scm_notes = scm_c_eval_string("gnc:transaction-scm-set-notes"); - setters.trans_scm_append_split_scm = - scm_c_eval_string("gnc:transaction-scm-append-split-scm"); - - getters.split_scm_memo = scm_c_eval_string("gnc:split-scm-get-memo"); - getters.split_scm_action = scm_c_eval_string("gnc:split-scm-get-action"); - getters.split_scm_amount = scm_c_eval_string("gnc:split-scm-get-amount"); - getters.split_scm_value = scm_c_eval_string("gnc:split-scm-get-value"); - - getters.trans_scm_split_scms = - scm_c_eval_string("gnc:transaction-scm-get-split-scms"); - getters.trans_scm_split_scm = - scm_c_eval_string("gnc:transaction-scm-get-split-scm"); - getters.trans_scm_other_split_scm = - scm_c_eval_string("gnc:transaction-scm-get-other-split-scm"); - getters.debit_string = scm_c_eval_string("gnc:get-debit-string"); getters.credit_string = scm_c_eval_string("gnc:get-credit-string"); - predicates.is_split_scm = scm_c_eval_string("gnc:split-scm?"); - predicates.is_trans_scm = scm_c_eval_string("gnc:transaction-scm?"); - scm_funcs_inited = TRUE; } -/********************************************************************\ - * gnc_copy_split * - * returns a scheme representation of a split. If the split is * - * NULL, SCM_UNDEFINED is returned. * - * * - * Args: split - the split to copy * - * use_cut_semantics - if TRUE, copy is for a 'cut' operation * - * Returns: SCM representation of split or SCM_UNDEFINED * -\********************************************************************/ -SCM -gnc_copy_split(Split *split, gboolean use_cut_semantics) -{ - static swig_type_info *split_type = NULL; - SCM func; - SCM arg; - - if (split == NULL) - return SCM_UNDEFINED; - - func = scm_c_eval_string("gnc:split->split-scm"); - if (!scm_is_procedure(func)) - return SCM_UNDEFINED; - - if (!split_type) - split_type = SWIG_TypeQuery("_p_Split"); - - arg = SWIG_NewPointerObj(split, split_type, 0); - - return scm_call_2(func, arg, SCM_BOOL(use_cut_semantics)); -} - - -/********************************************************************\ - * gnc_copy_split_scm_onto_split * - * copies a scheme representation of a split onto an actual split.* - * * - * Args: split_scm - the scheme representation of a split * - * split - the split to copy onto * - * Returns: Nothing * -\********************************************************************/ -void -gnc_copy_split_scm_onto_split(SCM split_scm, Split *split, - QofBook * book) -{ - static swig_type_info *split_type = NULL; - SCM result; - SCM func; - SCM arg; - - if (split_scm == SCM_UNDEFINED) - return; - - if (split == NULL) - return; - - g_return_if_fail (book); - - func = scm_c_eval_string("gnc:split-scm?"); - if (!scm_is_procedure(func)) - return; - - result = scm_call_1(func, split_scm); - if (!scm_is_true(result)) - return; - - func = scm_c_eval_string("gnc:split-scm-onto-split"); - if (!scm_is_procedure(func)) - return; - - if (!split_type) - split_type = SWIG_TypeQuery("_p_Split"); - - arg = SWIG_NewPointerObj(split, split_type, 0); - - scm_call_3(func, split_scm, arg, gnc_book_to_scm (book)); -} - - -/********************************************************************\ - * gnc_is_split_scm * - * returns true if the scm object is a scheme split * - * * - * Args: scm - a scheme object * - * Returns: true if scm is a scheme split * -\********************************************************************/ -static gboolean -gnc_is_split_scm(SCM scm) -{ - initialize_scm_functions(); - - return scm_is_true(scm_call_1(predicates.is_split_scm, scm)); -} - - -/********************************************************************\ - * gnc_is_trans_scm * - * returns true if the scm object is a scheme transaction * - * * - * Args: scm - a scheme object * - * Returns: true if scm is a scheme transaction * -\********************************************************************/ -static gboolean -gnc_is_trans_scm(SCM scm) -{ - initialize_scm_functions(); - - return scm_is_true(scm_call_1(predicates.is_trans_scm, scm)); -} - - -/********************************************************************\ - * gnc_split_scm_set_account * - * set the account of a scheme representation of a split. * - * * - * Args: split_scm - the scheme split * - * account - the account to set * - * Returns: Nothing * -\********************************************************************/ -void -gnc_split_scm_set_account(SCM split_scm, Account *account) -{ - gchar guid_string[GUID_ENCODING_LENGTH+1]; - SCM arg; - - initialize_scm_functions(); - - if (!gnc_is_split_scm(split_scm)) - return; - if (account == NULL) - return; - - guid_to_string_buff(xaccAccountGetGUID(account), guid_string); - if (strlen(guid_string) == 0) - return; - - arg = scm_from_utf8_string(guid_string); - - scm_call_2(setters.split_scm_account_guid, split_scm, arg); -} - - -/********************************************************************\ - * gnc_split_scm_set_memo * - * set the memo of a scheme representation of a split. * - * * - * Args: split_scm - the scheme split * - * memo - the memo to set * - * Returns: Nothing * -\********************************************************************/ -void -gnc_split_scm_set_memo(SCM split_scm, const char *memo) -{ - SCM arg; - - initialize_scm_functions(); - - if (!gnc_is_split_scm(split_scm)) - return; - if (memo == NULL) - return; - - arg = scm_from_utf8_string(memo); - - scm_call_2(setters.split_scm_memo, split_scm, arg); -} - - -/********************************************************************\ - * gnc_split_scm_set_action * - * set the action of a scheme representation of a split. * - * * - * Args: split_scm - the scheme split * - * action - the action to set * - * Returns: Nothing * -\********************************************************************/ -void -gnc_split_scm_set_action(SCM split_scm, const char *action) -{ - SCM arg; - - initialize_scm_functions(); - - if (!gnc_is_split_scm(split_scm)) - return; - if (action == NULL) - return; - - arg = scm_from_utf8_string(action); - - scm_call_2(setters.split_scm_action, split_scm, arg); -} - - -/********************************************************************\ - * gnc_split_scm_set_reconcile_state * - * set the reconcile state of a scheme split. * - * * - * Args: split_scm - the scheme split * - * reconcile_state - the reconcile state to set * - * Returns: Nothing * -\********************************************************************/ -void -gnc_split_scm_set_reconcile_state(SCM split_scm, char reconcile_state) -{ - SCM arg; - - initialize_scm_functions(); - - if (!gnc_is_split_scm(split_scm)) - return; - - arg = SCM_MAKE_CHAR(reconcile_state); - - scm_call_2(setters.split_scm_reconcile_state, split_scm, arg); -} - - -/********************************************************************\ - * gnc_split_scm_set_amount * - * set the amount of a scheme split * - * * - * Args: split_scm - the scheme split * - * amount - the amount to set * - * Returns: Nothing * -\********************************************************************/ -void -gnc_split_scm_set_amount(SCM split_scm, gnc_numeric amount) -{ - SCM arg; - - initialize_scm_functions(); - - if (!gnc_is_split_scm(split_scm)) - return; - - arg = gnc_numeric_to_scm(amount); - scm_call_2(setters.split_scm_amount, split_scm, arg); -} - - -/********************************************************************\ - * gnc_split_scm_set_value * - * set the value of a scheme split * - * * - * Args: split_scm - the scheme split * - * value - the value to set * - * Returns: Nothing * -\********************************************************************/ -void -gnc_split_scm_set_value(SCM split_scm, gnc_numeric value) -{ - SCM arg; - - initialize_scm_functions(); - - if (!gnc_is_split_scm(split_scm)) - return; - - arg = gnc_numeric_to_scm(value); - scm_call_2(setters.split_scm_value, split_scm, arg); -} - - -/********************************************************************\ - * gnc_split_scm_get_amount * - * return the amount of a scheme split * - * * - * Args: split_scm - the scheme split * - * Returns: amount of scheme split * -\********************************************************************/ -gnc_numeric -gnc_split_scm_get_amount(SCM split_scm) -{ - SCM result; - - initialize_scm_functions(); - - if (!gnc_is_split_scm(split_scm)) - return gnc_numeric_zero (); - - result = scm_call_1(getters.split_scm_amount, split_scm); - if (!scm_rational_p(result)) - return gnc_numeric_zero (); - - return gnc_scm_to_numeric(result); -} - - -/********************************************************************\ - * gnc_split_scm_get_value * - * return the value of a scheme split * - * * - * Args: split_scm - the scheme split * - * Returns: value of scheme split * -\********************************************************************/ -gnc_numeric -gnc_split_scm_get_value(SCM split_scm) -{ - SCM result; - - initialize_scm_functions(); - - if (!gnc_is_split_scm(split_scm)) - return gnc_numeric_zero (); - - result = scm_call_1(getters.split_scm_value, split_scm); - if (!scm_rational_p(result)) - return gnc_numeric_zero (); - - return gnc_scm_to_numeric(result); -} - - -/********************************************************************\ - * gnc_copy_trans * - * returns a scheme representation of a transaction. If the * - * transaction is NULL, SCM_UNDEFINED is returned. * - * * - * Args: trans - the transaction to copy * - * use_cut_semantics - if TRUE, copy is for a 'cut' operation * - * Returns: SCM representation of transaction or SCM_UNDEFINED * -\********************************************************************/ -SCM -gnc_copy_trans(Transaction *trans, gboolean use_cut_semantics) -{ - static swig_type_info *trans_type = NULL; - SCM func; - SCM arg; - - if (trans == NULL) - return SCM_UNDEFINED; - - func = scm_c_eval_string("gnc:transaction->transaction-scm"); - if (!scm_is_procedure(func)) - return SCM_UNDEFINED; - - if (!trans_type) - trans_type = SWIG_TypeQuery("_p_Transaction"); - - arg = SWIG_NewPointerObj(trans, trans_type, 0); - - return scm_call_2(func, arg, SCM_BOOL(use_cut_semantics)); -} - - -/********************************************************************\ - * gnc_copy_trans_scm_onto_trans * - * copies a scheme representation of a transaction onto * - * an actual transaction. * - * * - * Args: trans_scm - the scheme representation of a transaction * - * trans - the transaction to copy onto * - * Returns: Nothing * -\********************************************************************/ -void -gnc_copy_trans_scm_onto_trans(SCM trans_scm, Transaction *trans, - gboolean do_commit, QofBook *book) -{ - gnc_copy_trans_scm_onto_trans_swap_accounts(trans_scm, trans, NULL, NULL, - do_commit, book); -} - - -/********************************************************************\ - * gnc_copy_trans_scm_onto_trans_swap_accounts * - * copies a scheme representation of a transaction onto * - * an actual transaction. If guid_1 and guid_2 are not NULL, * - * the account guids of the splits are swapped accordingly. * - * * - * Args: trans_scm - the scheme representation of a transaction * - * trans - the transaction to copy onto * - * guid_1 - account guid to swap with guid_2 * - * guid_2 - account guid to swap with guid_1 * - * do_commit - whether to commit the edits * - * Returns: Nothing * -\********************************************************************/ -void -gnc_copy_trans_scm_onto_trans_swap_accounts(SCM trans_scm, - Transaction *trans, - const GncGUID *guid_1, - const GncGUID *guid_2, - gboolean do_commit, - QofBook *book) -{ - static swig_type_info *trans_type = NULL; - SCM result; - SCM func; - SCM arg; - - if (trans_scm == SCM_UNDEFINED) - return; - - if (trans == NULL) - return; - - g_return_if_fail (book); - - func = scm_c_eval_string("gnc:transaction-scm?"); - if (!scm_is_procedure(func)) - return; - - result = scm_call_1(func, trans_scm); - if (!scm_is_true(result)) - return; - - func = scm_c_eval_string("gnc:transaction-scm-onto-transaction"); - if (!scm_is_procedure(func)) - return; - - if (!trans_type) - trans_type = SWIG_TypeQuery("_p_Transaction"); - - arg = SWIG_NewPointerObj(trans, trans_type, 0); - - if ((guid_1 == NULL) || (guid_2 == NULL)) - { - SCM args = SCM_EOL; - SCM commit; - - commit = SCM_BOOL(do_commit); - - args = scm_cons(gnc_book_to_scm (book), args); - args = scm_cons(commit, args); - args = scm_cons(SCM_EOL, args); - args = scm_cons(arg, args); - args = scm_cons(trans_scm, args); - - scm_apply(func, args, SCM_EOL); - } - else - { - gchar guidstr[GUID_ENCODING_LENGTH+1]; - SCM from, to; - SCM map = SCM_EOL; - SCM args = SCM_EOL; - SCM commit; - - args = scm_cons(gnc_book_to_scm (book), args); - - commit = SCM_BOOL(do_commit); - - args = scm_cons(commit, args); - - guid_to_string_buff(guid_1, guidstr); - from = scm_from_utf8_string(guidstr); - guid_to_string_buff(guid_2, guidstr); - to = scm_from_utf8_string(guidstr); - - map = scm_cons(scm_cons(from, to), map); - map = scm_cons(scm_cons(to, from), map); - - args = scm_cons(map, args); - args = scm_cons(arg, args); - args = scm_cons(trans_scm, args); - - scm_apply(func, args, SCM_EOL); - } -} - -/********************************************************************\ - * gnc_trans_scm_append_split_scm * - * append the scheme split onto the scheme transaction * - * * - * Args: trans_scm - the scheme transaction * - * split_scm - the scheme split to append * - * Returns: Nothing * -\********************************************************************/ -void -gnc_trans_scm_append_split_scm(SCM trans_scm, SCM split_scm) -{ - initialize_scm_functions(); - - if (!gnc_is_trans_scm(trans_scm)) - return; - if (!gnc_is_split_scm(split_scm)) - return; - - scm_call_2(setters.trans_scm_append_split_scm, trans_scm, split_scm); -} - - -/********************************************************************\ - * gnc_trans_scm_get_split_scm * - * get the indexth scheme split of a scheme transaction. * - * * - * Args: trans_scm - the scheme transaction * - * index - the index of the split to get * - * Returns: scheme split to get, or SCM_UNDEFINED if none * -\********************************************************************/ -SCM -gnc_trans_scm_get_split_scm(SCM trans_scm, int index) -{ - SCM arg; - - initialize_scm_functions(); - - if (!gnc_is_trans_scm(trans_scm)) - return SCM_UNDEFINED; - - arg = scm_from_int (index); - - return scm_call_2(getters.trans_scm_split_scm, trans_scm, arg); -} - - -/********************************************************************\ - * gnc_trans_scm_get_other_split_scm * - * get the other scheme split of a scheme transaction. * - * * - * Args: trans_scm - the scheme transaction * - * split_scm - the split not to get * - * Returns: other scheme split, or SCM_UNDEFINED if none * -\********************************************************************/ -SCM -gnc_trans_scm_get_other_split_scm(SCM trans_scm, SCM split_scm) -{ - SCM result; - - initialize_scm_functions(); - - if (!gnc_is_trans_scm(trans_scm)) - return SCM_UNDEFINED; - if (!gnc_is_split_scm(split_scm)) - return SCM_UNDEFINED; - - result = scm_call_2(getters.trans_scm_other_split_scm, trans_scm, split_scm); - - if (!gnc_is_split_scm(result)) - return SCM_UNDEFINED; - - return result; -} - - -/********************************************************************\ - * gnc_trans_scm_get_num_splits * - * get the number of scheme splits in a scheme transaction. * - * * - * Args: trans_scm - the scheme transaction * - * Returns: number of scheme splits in the transaction * -\********************************************************************/ -int -gnc_trans_scm_get_num_splits(SCM trans_scm) -{ - SCM result; - - initialize_scm_functions(); - - if (!gnc_is_trans_scm(trans_scm)) - return 0; - - result = scm_call_1(getters.trans_scm_split_scms, trans_scm); - - if (!scm_is_list(result)) - return 0; - - return scm_to_int(scm_length(result)); -} - /********************************************************************\ * gnc_get_debit_string * diff --git a/libgnucash/app-utils/guile-util.h b/libgnucash/app-utils/guile-util.h index a66ce2e39a..d8740a25c1 100644 --- a/libgnucash/app-utils/guile-util.h +++ b/libgnucash/app-utils/guile-util.h @@ -32,38 +32,6 @@ #include "Account.h" #include "gnc-guile-utils.h" -/* The next set of functions is for manipulating scheme - * representations of splits and transactions. */ - -SCM gnc_copy_split(Split *split, gboolean use_cut_semantics); -void gnc_copy_split_scm_onto_split(SCM split_scm, Split *split, - QofBook *book); - -void gnc_split_scm_set_account(SCM split_scm, Account *account); -void gnc_split_scm_set_memo(SCM split_scm, const char *memo); -void gnc_split_scm_set_action(SCM split_scm, const char *action); -void gnc_split_scm_set_reconcile_state(SCM split_scm, char reconcile_state); -void gnc_split_scm_set_amount(SCM split_scm, gnc_numeric amount); -void gnc_split_scm_set_value(SCM split_scm, gnc_numeric value); - -gnc_numeric gnc_split_scm_get_amount(SCM split_scm); -gnc_numeric gnc_split_scm_get_value(SCM split_scm); - -SCM gnc_copy_trans(Transaction *trans, gboolean use_cut_semantics); -void gnc_copy_trans_scm_onto_trans(SCM trans_scm, Transaction *trans, - gboolean do_commit, QofBook *book); -void gnc_copy_trans_scm_onto_trans_swap_accounts(SCM trans_scm, - Transaction *trans, - const GncGUID *guid_1, - const GncGUID *guid_2, - gboolean do_commit, - QofBook *book); - -void gnc_trans_scm_append_split_scm(SCM trans_scm, SCM split_scm); - -SCM gnc_trans_scm_get_split_scm(SCM trans_scm, int index); -SCM gnc_trans_scm_get_other_split_scm(SCM trans_scm, SCM split_scm); -int gnc_trans_scm_get_num_splits(SCM trans_scm); /* Two functions that return string synonyms for the terms 'debit' and * 'credit' as appropriate for the given account type and user preferences. diff --git a/po/POTFILES.in b/po/POTFILES.in index d421ddbe7a..1c147ff059 100644 --- a/po/POTFILES.in +++ b/po/POTFILES.in @@ -380,6 +380,7 @@ gnucash/register/ledger-core/gnc-ledger-display.c gnucash/register/ledger-core/gncmod-ledger-core.c gnucash/register/ledger-core/split-register.c gnucash/register/ledger-core/split-register-control.c +gnucash/register/ledger-core/split-register-copy-ops.c gnucash/register/ledger-core/split-register-layout.c gnucash/register/ledger-core/split-register-load.c gnucash/register/ledger-core/split-register-model.c From 543fab25135d7f4b372d2d736436e4137f8442fe Mon Sep 17 00:00:00 2001 From: Geert Janssens Date: Thu, 10 Oct 2019 18:08:42 +0200 Subject: [PATCH 5/8] split-register - port copy operations from scm to c This is done with minimal interpretation, to be able to easily compare with the original scheme code. It will most likely be optimized in future commits --- gnucash/register/ledger-core/CMakeLists.txt | 2 + .../split-register-copy-ops-internals.c | 429 ++++++++++++++++++ .../split-register-copy-ops-internals.h | 119 +++++ po/POTFILES.in | 1 + 4 files changed, 551 insertions(+) create mode 100644 gnucash/register/ledger-core/split-register-copy-ops-internals.c create mode 100644 gnucash/register/ledger-core/split-register-copy-ops-internals.h diff --git a/gnucash/register/ledger-core/CMakeLists.txt b/gnucash/register/ledger-core/CMakeLists.txt index 0b671cee28..158764f3a4 100644 --- a/gnucash/register/ledger-core/CMakeLists.txt +++ b/gnucash/register/ledger-core/CMakeLists.txt @@ -8,6 +8,7 @@ set (ledger_core_SOURCES split-register.c split-register-control.c split-register-copy-ops.c + split-register-copy-ops-internals.c split-register-layout.c split-register-load.c split-register-model.c @@ -28,6 +29,7 @@ set (ledger_core_HEADERS split-register.h split-register-control.h split-register-copy-ops.h + split-register-copy-ops-internals.h split-register-layout.h split-register-model.h split-register-model-save.h diff --git a/gnucash/register/ledger-core/split-register-copy-ops-internals.c b/gnucash/register/ledger-core/split-register-copy-ops-internals.c new file mode 100644 index 0000000000..a7a241e949 --- /dev/null +++ b/gnucash/register/ledger-core/split-register-copy-ops-internals.c @@ -0,0 +1,429 @@ +/********************************************************************\ + * split-register-copy-ops-internals.c -- internal details of * + * copy/paste semantics for transactions and splits * + * Port to C of engine-interface * + * originally written by Dave Peticolas * + * © 2019 Geert Janssens + * * + * This program is free software; you can redistribute it and/or * + * modify it under the terms of the GNU General Public License as * + * published by the Free Software Foundation; either version 2 of * + * the License, or (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License* + * along with this program; if not, write to the Free Software * + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * +\********************************************************************/ + +#include + +#include "config.h" +#include "split-register-copy-ops-internals.h" + +/* accessors */ +Split *gnc_float_split_get_split (const FloatingSplit *fs) +{ + g_return_val_if_fail (fs, NULL); + return fs->m_split; +} + +Account *gnc_float_split_get_account (const FloatingSplit *fs) /* direct account pointer rather than account guid */ +{ + g_return_val_if_fail (fs, NULL); + return fs->m_account; +} + +Transaction *gnc_float_split_get_transaction (const FloatingSplit *fs) /* direct transaction pointer rather than transaction guid */ +{ + g_return_val_if_fail (fs, NULL); + return fs->m_transaction; +} + +const char *gnc_float_split_get_memo (const FloatingSplit *fs) +{ + g_return_val_if_fail (fs, NULL); + return fs->m_memo; +} + +const char *gnc_float_split_get_action (const FloatingSplit *fs) +{ + g_return_val_if_fail (fs, NULL); + return fs->m_action; +} + +char gnc_float_split_get_reconcile_state (const FloatingSplit *fs) +{ + g_return_val_if_fail (fs, '\0'); + return fs->m_reconcile_state; +} + +time64 gnc_float_split_get_reconcile_date (const FloatingSplit *fs) +{ + g_return_val_if_fail (fs, G_MAXINT64); + return fs->m_reconcile_date; +} + +gnc_numeric gnc_float_split_get_amount (const FloatingSplit *fs) +{ + g_return_val_if_fail (fs, gnc_numeric_zero()); + return fs->m_amount; +} + +gnc_numeric gnc_float_split_get_value (const FloatingSplit *fs) +{ + g_return_val_if_fail (fs, gnc_numeric_zero()); + return fs->m_value; +} + + +/* modifiers */ +void gnc_float_split_set_split(FloatingSplit *fs, Split *split) +{ + g_return_if_fail (fs); + fs->m_split = split; +}; + +void gnc_float_split_set_account (FloatingSplit *fs, Account *account) /* direct account pointer rather than account guid */ +{ + g_return_if_fail (fs); + fs->m_account = account; +}; + +void gnc_float_split_set_transaction (FloatingSplit *fs, Transaction *transaction) /* direct transaction pointer rather than transaction guid */ +{ + g_return_if_fail (fs); + fs->m_transaction = transaction; +}; + +void gnc_float_split_set_memo (FloatingSplit *fs, const char *memo) +{ + g_return_if_fail (fs); + fs->m_memo = memo; +}; + +void gnc_float_split_set_action (FloatingSplit *fs, const char *action) +{ + g_return_if_fail (fs); + fs->m_action = action; +}; + +void gnc_float_split_set_reconcile_state (FloatingSplit *fs, char reconcile_state) +{ + g_return_if_fail (fs); + fs->m_reconcile_state = reconcile_state; +}; + +void gnc_float_split_set_reconcile_date (FloatingSplit *fs, time64 reconcile_date) +{ + g_return_if_fail (fs); + fs->m_reconcile_date = reconcile_date; +}; + +void gnc_float_split_set_amount (FloatingSplit *fs, const gnc_numeric amount) +{ + g_return_if_fail (fs); + + fs->m_amount = amount; +}; + +void gnc_float_split_set_value (FloatingSplit *fs, const gnc_numeric value) +{ + g_return_if_fail (fs); + + fs->m_value = value; +}; + +/* This function takes a split and returns a representation + of it as a floating_split structure. Assumes the transaction is open + for editing. +*/ +FloatingSplit *gnc_split_to_float_split (Split *split) +{ + FloatingSplit *fs; + + g_return_val_if_fail (split, NULL); + + fs = g_new0 (FloatingSplit, 1); + fs->m_split = split; + fs->m_account = xaccSplitGetAccount (split); + fs->m_transaction = xaccSplitGetParent (split); + fs->m_memo = xaccSplitGetMemo (split); + fs->m_action = xaccSplitGetAction (split); + fs->m_reconcile_state = xaccSplitGetReconcile (split); + fs->m_reconcile_date = xaccSplitGetDateReconciled (split); + fs->m_amount = xaccSplitGetAmount (split); + fs->m_value = xaccSplitGetValue (split); + + return fs; +} + +/* Copy a temporary split representation onto a real split. + If possible, insert the split into the account of the + split representation. Not all values are copied. The reconcile + status and date are not copied. The split's guid is, + of course, unchanged. +*/ +void gnc_float_split_to_split (const FloatingSplit *fs, Split *split) +{ + g_return_if_fail(split); + + if (fs->m_memo) + xaccSplitSetMemo (split, fs->m_memo); + if (fs->m_action) + xaccSplitSetAction (split, fs->m_action); + xaccSplitSetAmount (split, fs->m_amount); + xaccSplitSetValue (split, fs->m_value); + if (fs->m_account) + { + xaccAccountBeginEdit (fs->m_account); + xaccSplitSetAccount (split, fs->m_account); + xaccAccountCommitEdit (fs->m_account); + } +} + +/* accessors */ +Transaction *gnc_float_txn_get_txn (const FloatingTxn *ft) +{ + g_return_val_if_fail (ft, NULL); + return ft->m_txn; +} + +gnc_commodity *gnc_float_txn_get_currency (const FloatingTxn *ft) +{ + g_return_val_if_fail (ft, NULL); + return ft->m_currency; +} + +time64 gnc_float_txn_get_date_entered (const FloatingTxn *ft) +{ + g_return_val_if_fail (ft, G_MAXINT64); + return ft->m_date_entered; +} + +time64 gnc_float_txn_get_date_posted (const FloatingTxn *ft) +{ + g_return_val_if_fail (ft, G_MAXINT64); + return ft->m_date_posted; +} + +const char *gnc_float_txn_get_num (const FloatingTxn *ft) +{ + g_return_val_if_fail (ft, NULL); + return ft->m_num; +} + +const char *gnc_float_txn_get_description (const FloatingTxn *ft) +{ + g_return_val_if_fail (ft, NULL); + return ft->m_description; +} + +const char *gnc_float_txn_get_notes (const FloatingTxn *ft) +{ + g_return_val_if_fail (ft, NULL); + return ft->m_notes; +} + +const char *gnc_float_txn_get_association (const FloatingTxn *ft) +{ + g_return_val_if_fail (ft, NULL); + return ft->m_association; +} + +SplitList *gnc_float_txn_get_splits (const FloatingTxn *ft) +{ + g_return_val_if_fail (ft, NULL); + return ft->m_splits; +} + +FloatingSplit *gnc_float_txn_get_float_split (const FloatingTxn *ft, guint index) +{ + FloatingSplit *fs = NULL; + guint size = 0; + + g_return_val_if_fail (ft, NULL); + g_return_val_if_fail (ft->m_splits, NULL); + g_return_val_if_fail (index < g_list_length (ft->m_splits) , NULL); + return g_list_nth_data (ft->m_splits, index); +} + +FloatingSplit *gnc_float_txn_get_other_float_split (const FloatingTxn *ft, FloatingSplit *fs) +{ + guint size = 0, other = 0; + + g_return_val_if_fail (ft, NULL); + g_return_val_if_fail (ft->m_splits, NULL); + g_return_val_if_fail (g_list_length (ft->m_splits) == 2 , NULL); + + if (g_list_nth_data (ft->m_splits, 0) == fs) + other = 1; + + return g_list_nth_data (ft->m_splits, other); +} + +/* modifiers */ +void gnc_float_txn_set_txn (FloatingTxn *ft, Transaction *txn) +{ + g_return_if_fail (ft); + ft->m_txn = txn; +}; + +void gnc_float_txn_set_currency (FloatingTxn *ft, gnc_commodity *currency) +{ + g_return_if_fail (ft); + ft->m_currency = currency; +}; + +void gnc_float_txn_set_date_entered (FloatingTxn *ft, time64 date_entered) +{ + g_return_if_fail (ft); + ft->m_date_entered = date_entered; +}; + +void gnc_float_txn_set_date_posted (FloatingTxn *ft, time64 date_posted) +{ + g_return_if_fail (ft); + ft->m_date_posted = date_posted; +}; + +void gnc_float_txn_set_num (FloatingTxn *ft, const char *num) +{ + g_return_if_fail (ft); + ft->m_num = num; +}; + +void gnc_float_txn_set_description (FloatingTxn *ft, const char *description) +{ + g_return_if_fail (ft); + ft->m_description = description; +}; + +void gnc_float_txn_set_notes (FloatingTxn *ft, const char *notes) +{ + g_return_if_fail (ft); + ft->m_notes = notes; +}; + +void gnc_float_txn_set_association (FloatingTxn *ft, const char *association) +{ + g_return_if_fail (ft); + ft->m_association = association; +}; + +void gnc_float_txn_set_splits (FloatingTxn *ft, SplitList *splits) +{ + g_return_if_fail (ft); + ft->m_splits = splits; +}; + +void gnc_float_txn_append_float_split (FloatingTxn *ft, FloatingSplit *fs) +{ + g_return_if_fail (ft); + g_return_if_fail (fs); + ft->m_splits = g_list_append (ft->m_splits, fs); +} + +/* This function takes a C transaction and returns + a representation of it as a floating_txn. */ +FloatingTxn *gnc_txn_to_float_txn (Transaction *txn, gboolean use_cut_semantics) +{ + GList *iter; + + FloatingTxn *ft = g_new0 (FloatingTxn, 1); + + ft->m_txn = txn; + ft->m_currency = xaccTransGetCurrency (txn); + ft->m_date_entered = xaccTransGetDateEntered (txn); + if (use_cut_semantics) + { + ft->m_date_posted = xaccTransGetDate (txn); + ft->m_num = xaccTransGetNum (txn); + } + ft->m_description = xaccTransGetDescription (txn); + ft->m_notes = xaccTransGetNotes (txn); + ft->m_association = xaccTransGetAssociation (txn); + + for (iter = xaccTransGetSplitList (txn); iter ; iter = iter->next) + { + Split *split = iter->data; + if (split) + { + FloatingSplit *fs = gnc_split_to_float_split (split); + ft->m_splits = g_list_prepend (ft->m_splits, fs); + } + } + ft->m_splits = g_list_reverse (ft->m_splits); + + return ft; +} + +void gnc_float_txn_to_txn (const FloatingTxn *ft, Transaction *txn, gboolean do_commit) +{ + gnc_float_txn_to_txn_swap_accounts (ft, txn, NULL, NULL, do_commit); +} + +/* Copy a temporary representation of a transaction onto a real transaction. + I f they exist the two account*s (acct1 and acct2) are used to swap accounts + when when creating splits. */ +void gnc_float_txn_to_txn_swap_accounts (const FloatingTxn *ft, Transaction *txn, Account *acct1, Account *acct2, gboolean do_commit) +{ + GList *iter; + + g_return_if_fail (ft); + g_return_if_fail (txn); + + if (!xaccTransIsOpen (txn)) + xaccTransBeginEdit (txn); + + if (ft->m_currency) + xaccTransSetCurrency (txn, ft->m_currency); + if (ft->m_description) + xaccTransSetDescription (txn, ft->m_description); + if (ft->m_num) + xaccTransSetNum (txn, ft->m_num); + if (ft->m_notes) + xaccTransSetNotes (txn, ft->m_notes); + if (ft->m_association) + xaccTransSetAssociation (txn, ft->m_association); + if (ft->m_date_posted) + xaccTransSetDatePostedSecs (txn, ft->m_date_posted); + + /* strip off the old splits */ + while (xaccTransCountSplits (txn)) + xaccSplitDestroy (xaccTransGetSplit (txn, 0)); + + /* and put on the new ones! Please note they go in the *same* + order as in the original transaction. This is important. */ + for (iter = ft->m_splits; iter; iter = iter->next) + { + Account *old_acc, *new_acc; + Split *split; + FloatingSplit *fs = iter->data; + if (!fs) + continue; + + split = xaccMallocSplit (xaccTransGetBook (txn)); + + old_acc = fs->m_account; + if (fs->m_account == acct1) + new_acc = acct2; + else if (fs->m_account == acct2) + new_acc = acct1; + else + new_acc = fs->m_account; + + fs->m_account = new_acc; + gnc_float_split_to_split (fs, split); + fs->m_account = old_acc; + xaccSplitSetParent (split, txn); + } + + /* close the transaction */ + if (do_commit) + xaccTransCommitEdit (txn); +} diff --git a/gnucash/register/ledger-core/split-register-copy-ops-internals.h b/gnucash/register/ledger-core/split-register-copy-ops-internals.h new file mode 100644 index 0000000000..2f4976566f --- /dev/null +++ b/gnucash/register/ledger-core/split-register-copy-ops-internals.h @@ -0,0 +1,119 @@ +/********************************************************************\ + * split-register-copy-ops-internals.c -- internal details of * + * copy/paste semantics for transactions and splits * + * Port to C of engine-interface * + * originally written by Dave Peticolas * + * © 2019 Geert Janssens + * * + * This program is free software; you can redistribute it and/or * + * modify it under the terms of the GNU General Public License as * + * published by the Free Software Foundation; either version 2 of * + * the License, or (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License* + * along with this program; if not, write to the Free Software * + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * + * \********************************************************************/ + +#ifndef SPLIT_REGISTER_COPY_OPS_INTERNAL_H +#define SPLIT_REGISTER_COPY_OPS_INTERNAL_H + +#include + +#include "gnc-engine.h" /* for typedefs */ +#include "qof.h" + +#include "guid.h" +#include "Split.h" +#include "Account.h" +#include "Transaction.h" + +typedef struct +{ + Split *m_split; + Account *m_account; + Transaction *m_transaction; + const char *m_memo; + const char *m_action; + time64 m_reconcile_date; + char m_reconcile_state; + gnc_numeric m_value; + gnc_numeric m_amount; +} FloatingSplit; + +typedef struct +{ + Transaction *m_txn; + gnc_commodity *m_currency; + time64 m_date_entered; + time64 m_date_posted; + const char *m_num; + const char *m_description; + const char *m_notes; + const char *m_association; + SplitList *m_splits; +} FloatingTxn; + +/* accessors */ +Split *gnc_float_split_get_split(const FloatingSplit* fs); +Account *gnc_float_split_get_account (const FloatingSplit *fs); /* direct account pointer rather than account guid */ +Transaction *gnc_float_split_get_transaction (const FloatingSplit *fs); /* direct transaction pointer rather than transaction guid */ +const char *gnc_float_split_get_memo (const FloatingSplit *fs); +const char *gnc_float_split_get_action (const FloatingSplit *fs); +char gnc_float_split_get_reconcile_state (const FloatingSplit *fs); +time64 gnc_float_split_get_reconcile_date (const FloatingSplit *fs); +gnc_numeric gnc_float_split_get_amount (const FloatingSplit *fs); +gnc_numeric gnc_float_split_get_value (const FloatingSplit *fs); + +/* modifiers */ +void gnc_float_split_set_split (FloatingSplit *fs, Split *split); +void gnc_float_split_set_account (FloatingSplit *fs, Account *account); /* direct account pointer rather than account guid */ +void gnc_float_split_set_transaction (FloatingSplit *fs, Transaction *transaction); /* direct transaction pointer rather than transaction guid */ +void gnc_float_split_set_memo (FloatingSplit *fs, const char *memo); +void gnc_float_split_set_action (FloatingSplit *fs, const char *action); +void gnc_float_split_set_reconcile_state (FloatingSplit *fs, char reconcile_state); +void gnc_float_split_set_reconcile_date (FloatingSplit *fs, time64 reconcile_date); +void gnc_float_split_set_amount (FloatingSplit *fs, gnc_numeric amount); +void gnc_float_split_set_value (FloatingSplit *fs, gnc_numeric value); + +FloatingSplit *gnc_split_to_float_split (Split *split); +void gnc_float_split_to_split (const FloatingSplit *fs, Split *split); + +/* accessors */ +Transaction *gnc_float_txn_get_txn (const FloatingTxn *ft); +gnc_commodity *gnc_float_txn_get_currency (const FloatingTxn *ft); +time64 gnc_float_txn_get_date_entered (const FloatingTxn *ft); +time64 gnc_float_txn_get_date_posted (const FloatingTxn *ft); +const char *gnc_float_txn_get_num (const FloatingTxn *ft); +const char *gnc_float_txn_get_description (const FloatingTxn *ft); +const char *gnc_float_txn_get_notes (const FloatingTxn *ft); +const char *gnc_float_txn_get_association (const FloatingTxn *ft); +SplitList *gnc_float_txn_get_splits (const FloatingTxn *ft); + +FloatingSplit *gnc_float_txn_get_float_split (const FloatingTxn *ft, guint index); +FloatingSplit *gnc_float_txn_get_other_float_split (const FloatingTxn *ft, FloatingSplit *fs); + +/* modifiers */ +void gnc_float_txn_set_txn (FloatingTxn *ft, Transaction *txn); +void gnc_float_txn_set_currency (FloatingTxn *ft, gnc_commodity *currency); +void gnc_float_txn_set_date_entered (FloatingTxn *ft, time64 date_entered); +void gnc_float_txn_set_date_posted (FloatingTxn *ft, time64 date_posted); +void gnc_float_txn_set_num (FloatingTxn *ft, const char *num); +void gnc_float_txn_set_description (FloatingTxn *ft, const char *description); +void gnc_float_txn_set_notes (FloatingTxn *ft, const char *notes); +void gnc_float_txn_set_association (FloatingTxn *ft, const char *association); +void gnc_float_txn_set_splits (FloatingTxn *ft, SplitList *splits); + +void gnc_float_txn_append_float_split (FloatingTxn *ft, FloatingSplit *fs); + +FloatingTxn *gnc_txn_to_float_txn (Transaction *txn, gboolean use_cut_semantics); + +void gnc_float_txn_to_txn (const FloatingTxn *ft, Transaction *txn, gboolean do_commit); +void gnc_float_txn_to_txn_swap_accounts (const FloatingTxn *ft, Transaction *txn, Account *acct1, Account *acct2, gboolean do_commit); + +#endif diff --git a/po/POTFILES.in b/po/POTFILES.in index 1c147ff059..4a1ce99363 100644 --- a/po/POTFILES.in +++ b/po/POTFILES.in @@ -381,6 +381,7 @@ gnucash/register/ledger-core/gncmod-ledger-core.c gnucash/register/ledger-core/split-register.c gnucash/register/ledger-core/split-register-control.c gnucash/register/ledger-core/split-register-copy-ops.c +gnucash/register/ledger-core/split-register-copy-ops-internals.c gnucash/register/ledger-core/split-register-layout.c gnucash/register/ledger-core/split-register-load.c gnucash/register/ledger-core/split-register-model.c From cb273b13a1269cf089c27e21192da444297fe3ae Mon Sep 17 00:00:00 2001 From: Geert Janssens Date: Fri, 6 Dec 2019 18:52:12 +0100 Subject: [PATCH 6/8] split register - use C copy interface instead of scm copy interface --- gnucash/register/ledger-core/split-register.c | 156 +++++++++++------- 1 file changed, 93 insertions(+), 63 deletions(-) diff --git a/gnucash/register/ledger-core/split-register.c b/gnucash/register/ledger-core/split-register.c index 37c384724c..03cefca562 100644 --- a/gnucash/register/ledger-core/split-register.c +++ b/gnucash/register/ledger-core/split-register.c @@ -27,7 +27,6 @@ #include #include -#include #include "combocell.h" #include "datecell.h" @@ -40,7 +39,7 @@ #include "gnc-ui.h" #include "gnc-warnings.h" #include "guile-util.h" -#include "split-register-copy-ops.h" +#include "split-register-copy-ops-internals.h" #include "numcell.h" #include "pricecell.h" #include "quickfillcell.h" @@ -63,13 +62,24 @@ static QofLogModule log_module = GNC_MOD_LEDGER; /* The copied split or transaction, if any */ +typedef struct +{ + GType ftype; + union + { + FloatingSplit *fs; + FloatingTxn *ft; + }; +} ft_fs_store; + +static ft_fs_store copied_item = { 0, { NULL } }; static CursorClass copied_class = CURSOR_CLASS_NONE; -static SCM copied_item = SCM_UNDEFINED; static GncGUID copied_leader_guid; + /** static prototypes *****************************************************/ -static gboolean gnc_split_register_save_to_scm (SplitRegister *reg, - SCM trans_scm, SCM split_scm, +static gboolean gnc_split_register_save_to_copy_buffer (SplitRegister *reg, + FloatingTxn *ft, FloatingSplit *fs, gboolean use_cut_semantics); static gboolean gnc_split_register_auto_calc (SplitRegister *reg, Split *split); @@ -77,39 +87,36 @@ static gboolean gnc_split_register_auto_calc (SplitRegister *reg, /** implementations *******************************************************/ -/* Uses the scheme split copying routines */ static void gnc_copy_split_onto_split(Split *from, Split *to, gboolean use_cut_semantics) { - SCM split_scm; + FloatingSplit *fs; if ((from == NULL) || (to == NULL)) return; - split_scm = gnc_copy_split(from, use_cut_semantics); - if (split_scm == SCM_UNDEFINED) + fs = gnc_split_to_float_split (from); + if (!fs) return; - gnc_copy_split_scm_onto_split(split_scm, to, gnc_get_current_book ()); + gnc_float_split_to_split (fs, to); } -/* Uses the scheme transaction copying routines */ void gnc_copy_trans_onto_trans(Transaction *from, Transaction *to, gboolean use_cut_semantics, gboolean do_commit) { - SCM trans_scm; + FloatingTxn *ft; if ((from == NULL) || (to == NULL)) return; - trans_scm = gnc_copy_trans(from, use_cut_semantics); - if (trans_scm == SCM_UNDEFINED) + ft = gnc_txn_to_float_txn (from, use_cut_semantics); + if (!ft) return; - gnc_copy_trans_scm_onto_trans(trans_scm, to, do_commit, - gnc_get_current_book ()); + gnc_float_txn_to_txn (ft, to, do_commit); } static int @@ -706,7 +713,8 @@ gnc_split_register_copy_current_internal (SplitRegister *reg, Split *blank_split; gboolean changed; Split *split; - SCM new_item; + FloatingSplit *new_fs = NULL; + FloatingTxn *new_ft = NULL; g_return_if_fail(reg); ENTER("reg=%p, use_cut_semantics=%s", reg, @@ -762,12 +770,12 @@ gnc_split_register_copy_current_internal (SplitRegister *reg, if (cursor_class == CURSOR_CLASS_SPLIT) { /* We are on a split in an expanded transaction. Just copy the split. */ - new_item = gnc_copy_split(split, use_cut_semantics); + new_fs = gnc_split_to_float_split (split); - if (new_item != SCM_UNDEFINED) + if (new_fs) { if (changed) - gnc_split_register_save_to_scm (reg, SCM_UNDEFINED, new_item, + gnc_split_register_save_to_copy_buffer (reg, NULL, new_fs, use_cut_semantics); copied_leader_guid = *guid_null(); @@ -776,22 +784,22 @@ gnc_split_register_copy_current_internal (SplitRegister *reg, else { /* We are on a transaction row. Copy the whole transaction. */ - new_item = gnc_copy_trans(trans, use_cut_semantics); + new_ft = gnc_txn_to_float_txn (trans, use_cut_semantics); - if (new_item != SCM_UNDEFINED) + if (new_ft) { if (changed) { int split_index; - SCM split_scm; + FloatingSplit *fs; split_index = xaccTransGetSplitIndex(trans, split); if (split_index >= 0) - split_scm = gnc_trans_scm_get_split_scm(new_item, split_index); + fs = gnc_float_txn_get_float_split(new_ft, split_index); else - split_scm = SCM_UNDEFINED; + fs = NULL; - gnc_split_register_save_to_scm (reg, new_item, split_scm, + gnc_split_register_save_to_copy_buffer (reg, new_ft, fs, use_cut_semantics); } @@ -799,7 +807,7 @@ gnc_split_register_copy_current_internal (SplitRegister *reg, } } - if (new_item == SCM_UNDEFINED) + if (!new_fs && !new_ft) { g_warning("BUG DETECTED: copy failed"); LEAVE("copy failed"); @@ -807,11 +815,22 @@ gnc_split_register_copy_current_internal (SplitRegister *reg, } /* unprotect the old object, if any */ - if (copied_item != SCM_UNDEFINED) - scm_gc_unprotect_object(copied_item); + if (copied_item.ftype == GNC_TYPE_SPLIT) + g_free (copied_item.fs); + if (copied_item.ftype == GNC_TYPE_TRANSACTION) + g_free (copied_item.ft); + copied_item.ftype = 0; - copied_item = new_item; - scm_gc_protect_object(copied_item); + if (new_fs) + { + copied_item.fs = new_fs; + copied_item.ftype = GNC_TYPE_SPLIT; + } + else if (new_ft) + { + copied_item.ft = new_ft; + copied_item.ftype = GNC_TYPE_TRANSACTION; + } copied_class = cursor_class; LEAVE("%s %s", use_cut_semantics ? "cut" : "copied", @@ -970,8 +989,13 @@ gnc_split_register_paste_current (SplitRegister *reg) xaccSplitSetParent(split, trans); } - gnc_copy_split_scm_onto_split(copied_item, split, - gnc_get_current_book ()); + if (copied_item.ftype != GNC_TYPE_SPLIT) + { + LEAVE("copy buffer doesn't represent a split"); + return; + } + + gnc_float_split_to_split (copied_item.fs, split); } else { @@ -979,6 +1003,7 @@ gnc_split_register_paste_current (SplitRegister *reg) "transaction. " "Are you sure you want to do that?"); Account * copied_leader; + Account * default_account; const GncGUID *new_guid; int trans_split_index; int split_index; @@ -990,6 +1015,13 @@ gnc_split_register_paste_current (SplitRegister *reg) return; } + + if (copied_item.ftype != GNC_TYPE_TRANSACTION) + { + LEAVE("copy buffer doesn't represent a transaction"); + return; + } + /* Ask before overwriting an existing transaction. */ if (split != blank_split && !gnc_verify_dialog (GTK_WINDOW (gnc_split_register_get_parent (reg)), @@ -1016,17 +1048,15 @@ gnc_split_register_paste_current (SplitRegister *reg) copied_leader = xaccAccountLookup(&copied_leader_guid, gnc_get_current_book()); - if (copied_leader && (gnc_split_register_get_default_account(reg) != NULL)) + default_account = gnc_split_register_get_default_account(reg); + if (copied_leader && default_account) { - new_guid = &info->default_account; - gnc_copy_trans_scm_onto_trans_swap_accounts(copied_item, trans, - &copied_leader_guid, - new_guid, FALSE, - gnc_get_current_book ()); + gnc_float_txn_to_txn_swap_accounts (copied_item.ft, trans, + copied_leader, + default_account, FALSE); } else - gnc_copy_trans_scm_onto_trans(copied_item, trans, FALSE, - gnc_get_current_book ()); + gnc_float_txn_to_txn (copied_item.ft, trans, FALSE); num_splits = xaccTransCountSplits(trans); if (split_index >= num_splits) @@ -1445,11 +1475,11 @@ gnc_split_register_redraw (SplitRegister *reg) /* Copy from the register object to scheme. This needs to be * in sync with gnc_split_register_save and xaccSRSaveChangedCells. */ static gboolean -gnc_split_register_save_to_scm (SplitRegister *reg, - SCM trans_scm, SCM split_scm, +gnc_split_register_save_to_copy_buffer (SplitRegister *reg, + FloatingTxn *ft, FloatingSplit *fs, gboolean use_cut_semantics) { - SCM other_split_scm = SCM_UNDEFINED; + FloatingSplit *other_fs = NULL; Transaction *trans; /* use the changed flag to avoid heavy-weight updates @@ -1519,7 +1549,7 @@ gnc_split_register_save_to_scm (SplitRegister *reg, cell = gnc_table_layout_get_cell (reg->table->layout, RECN_CELL); flag = gnc_recn_cell_get_flag ((RecnCell *) cell); - gnc_split_scm_set_reconcile_state(split_scm, flag); + gnc_float_split_set_reconcile_state (fs, flag); } if (gnc_table_layout_get_cell_changed (reg->table->layout, ACTN_CELL, TRUE)) @@ -1527,7 +1557,7 @@ gnc_split_register_save_to_scm (SplitRegister *reg, const char *value; value = gnc_table_layout_get_cell_value (reg->table->layout, ACTN_CELL); - gnc_split_scm_set_action (split_scm, value); + gnc_float_split_set_action (fs, value); } if (gnc_table_layout_get_cell_changed (reg->table->layout, MEMO_CELL, TRUE)) @@ -1535,7 +1565,7 @@ gnc_split_register_save_to_scm (SplitRegister *reg, const char *value; value = gnc_table_layout_get_cell_value (reg->table->layout, MEMO_CELL); - gnc_split_scm_set_memo (split_scm, value); + gnc_float_split_set_memo (fs, value); } if (gnc_table_layout_get_cell_changed (reg->table->layout, XFRM_CELL, TRUE)) @@ -1545,38 +1575,38 @@ gnc_split_register_save_to_scm (SplitRegister *reg, new_account = gnc_split_register_get_account (reg, XFRM_CELL); if (new_account != NULL) - gnc_split_scm_set_account (split_scm, new_account); + gnc_float_split_set_account (fs, new_account); } if (reg->style == REG_STYLE_LEDGER) - other_split_scm = gnc_trans_scm_get_other_split_scm (trans_scm, split_scm); + other_fs = gnc_float_txn_get_other_float_split (ft, fs); if (gnc_table_layout_get_cell_changed (reg->table->layout, MXFRM_CELL, TRUE)) { - other_split_scm = gnc_trans_scm_get_other_split_scm (trans_scm, split_scm); + other_fs = gnc_float_txn_get_other_float_split (ft, fs); - if (other_split_scm == SCM_UNDEFINED) + if (!other_fs) { - if (gnc_trans_scm_get_num_splits(trans_scm) == 1) + if (g_list_length (ft->m_splits) == 1) { Split *temp_split; temp_split = xaccMallocSplit (gnc_get_current_book ()); - other_split_scm = gnc_copy_split (temp_split, use_cut_semantics); + other_fs = gnc_split_to_float_split (temp_split); xaccSplitDestroy (temp_split); - gnc_trans_scm_append_split_scm (trans_scm, other_split_scm); + gnc_float_txn_append_float_split (ft, other_fs); } } - if (other_split_scm != SCM_UNDEFINED) + if (other_fs) { Account *new_account; new_account = gnc_split_register_get_account (reg, MXFRM_CELL); if (new_account != NULL) - gnc_split_scm_set_account (other_split_scm, new_account); + gnc_float_split_set_account (other_fs, new_account); } } @@ -1598,7 +1628,7 @@ gnc_split_register_save_to_scm (SplitRegister *reg, new_value = gnc_numeric_sub_fixed (debit, credit); - gnc_split_scm_set_value (split_scm, new_value); + gnc_float_split_set_value (fs, new_value); } if (gnc_table_layout_get_cell_changed (reg->table->layout, PRIC_CELL, TRUE)) @@ -1615,7 +1645,7 @@ gnc_split_register_save_to_scm (SplitRegister *reg, shares = gnc_price_cell_get_value ((PriceCell *) cell); - gnc_split_scm_set_amount (split_scm, shares); + gnc_float_split_set_amount (fs, shares); } if (gnc_table_layout_get_cell_changed (reg->table->layout, @@ -1627,15 +1657,15 @@ gnc_split_register_save_to_scm (SplitRegister *reg, gnc_table_layout_get_cell_changed (reg->table->layout, SHRS_CELL, TRUE)) { - if (other_split_scm != SCM_UNDEFINED) + if (other_fs) { gnc_numeric num; - num = gnc_split_scm_get_amount (split_scm); - gnc_split_scm_set_amount (other_split_scm, gnc_numeric_neg (num)); + num = gnc_float_split_get_amount (fs); + gnc_float_split_set_amount (other_fs, gnc_numeric_neg (num)); - num = gnc_split_scm_get_value (split_scm); - gnc_split_scm_set_value (other_split_scm, gnc_numeric_neg (num)); + num = gnc_float_split_get_value (fs); + gnc_float_split_set_value (other_fs, gnc_numeric_neg (num)); } } From f5e28c3d0fc9e1f57d24e133cc14311f54751a9a Mon Sep 17 00:00:00 2001 From: Geert Janssens Date: Fri, 6 Dec 2019 19:18:27 +0100 Subject: [PATCH 7/8] split register - drop scm copy interface --- gnucash/register/ledger-core/CMakeLists.txt | 2 - .../split-register-copy-ops-internals.c | 429 ------- .../split-register-copy-ops-internals.h | 119 -- .../ledger-core/split-register-copy-ops.c | 1028 ++++++----------- .../ledger-core/split-register-copy-ops.h | 128 +- gnucash/register/ledger-core/split-register.c | 2 +- libgnucash/engine/CMakeLists.txt | 1 - libgnucash/engine/engine-interface.scm | 295 ----- libgnucash/engine/engine.scm | 50 - po/POTFILES.in | 1 - 10 files changed, 463 insertions(+), 1592 deletions(-) delete mode 100644 gnucash/register/ledger-core/split-register-copy-ops-internals.c delete mode 100644 gnucash/register/ledger-core/split-register-copy-ops-internals.h delete mode 100644 libgnucash/engine/engine-interface.scm diff --git a/gnucash/register/ledger-core/CMakeLists.txt b/gnucash/register/ledger-core/CMakeLists.txt index 158764f3a4..0b671cee28 100644 --- a/gnucash/register/ledger-core/CMakeLists.txt +++ b/gnucash/register/ledger-core/CMakeLists.txt @@ -8,7 +8,6 @@ set (ledger_core_SOURCES split-register.c split-register-control.c split-register-copy-ops.c - split-register-copy-ops-internals.c split-register-layout.c split-register-load.c split-register-model.c @@ -29,7 +28,6 @@ set (ledger_core_HEADERS split-register.h split-register-control.h split-register-copy-ops.h - split-register-copy-ops-internals.h split-register-layout.h split-register-model.h split-register-model-save.h diff --git a/gnucash/register/ledger-core/split-register-copy-ops-internals.c b/gnucash/register/ledger-core/split-register-copy-ops-internals.c deleted file mode 100644 index a7a241e949..0000000000 --- a/gnucash/register/ledger-core/split-register-copy-ops-internals.c +++ /dev/null @@ -1,429 +0,0 @@ -/********************************************************************\ - * split-register-copy-ops-internals.c -- internal details of * - * copy/paste semantics for transactions and splits * - * Port to C of engine-interface * - * originally written by Dave Peticolas * - * © 2019 Geert Janssens - * * - * This program is free software; you can redistribute it and/or * - * modify it under the terms of the GNU General Public License as * - * published by the Free Software Foundation; either version 2 of * - * the License, or (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU General Public License for more details. * - * * - * You should have received a copy of the GNU General Public License* - * along with this program; if not, write to the Free Software * - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * -\********************************************************************/ - -#include - -#include "config.h" -#include "split-register-copy-ops-internals.h" - -/* accessors */ -Split *gnc_float_split_get_split (const FloatingSplit *fs) -{ - g_return_val_if_fail (fs, NULL); - return fs->m_split; -} - -Account *gnc_float_split_get_account (const FloatingSplit *fs) /* direct account pointer rather than account guid */ -{ - g_return_val_if_fail (fs, NULL); - return fs->m_account; -} - -Transaction *gnc_float_split_get_transaction (const FloatingSplit *fs) /* direct transaction pointer rather than transaction guid */ -{ - g_return_val_if_fail (fs, NULL); - return fs->m_transaction; -} - -const char *gnc_float_split_get_memo (const FloatingSplit *fs) -{ - g_return_val_if_fail (fs, NULL); - return fs->m_memo; -} - -const char *gnc_float_split_get_action (const FloatingSplit *fs) -{ - g_return_val_if_fail (fs, NULL); - return fs->m_action; -} - -char gnc_float_split_get_reconcile_state (const FloatingSplit *fs) -{ - g_return_val_if_fail (fs, '\0'); - return fs->m_reconcile_state; -} - -time64 gnc_float_split_get_reconcile_date (const FloatingSplit *fs) -{ - g_return_val_if_fail (fs, G_MAXINT64); - return fs->m_reconcile_date; -} - -gnc_numeric gnc_float_split_get_amount (const FloatingSplit *fs) -{ - g_return_val_if_fail (fs, gnc_numeric_zero()); - return fs->m_amount; -} - -gnc_numeric gnc_float_split_get_value (const FloatingSplit *fs) -{ - g_return_val_if_fail (fs, gnc_numeric_zero()); - return fs->m_value; -} - - -/* modifiers */ -void gnc_float_split_set_split(FloatingSplit *fs, Split *split) -{ - g_return_if_fail (fs); - fs->m_split = split; -}; - -void gnc_float_split_set_account (FloatingSplit *fs, Account *account) /* direct account pointer rather than account guid */ -{ - g_return_if_fail (fs); - fs->m_account = account; -}; - -void gnc_float_split_set_transaction (FloatingSplit *fs, Transaction *transaction) /* direct transaction pointer rather than transaction guid */ -{ - g_return_if_fail (fs); - fs->m_transaction = transaction; -}; - -void gnc_float_split_set_memo (FloatingSplit *fs, const char *memo) -{ - g_return_if_fail (fs); - fs->m_memo = memo; -}; - -void gnc_float_split_set_action (FloatingSplit *fs, const char *action) -{ - g_return_if_fail (fs); - fs->m_action = action; -}; - -void gnc_float_split_set_reconcile_state (FloatingSplit *fs, char reconcile_state) -{ - g_return_if_fail (fs); - fs->m_reconcile_state = reconcile_state; -}; - -void gnc_float_split_set_reconcile_date (FloatingSplit *fs, time64 reconcile_date) -{ - g_return_if_fail (fs); - fs->m_reconcile_date = reconcile_date; -}; - -void gnc_float_split_set_amount (FloatingSplit *fs, const gnc_numeric amount) -{ - g_return_if_fail (fs); - - fs->m_amount = amount; -}; - -void gnc_float_split_set_value (FloatingSplit *fs, const gnc_numeric value) -{ - g_return_if_fail (fs); - - fs->m_value = value; -}; - -/* This function takes a split and returns a representation - of it as a floating_split structure. Assumes the transaction is open - for editing. -*/ -FloatingSplit *gnc_split_to_float_split (Split *split) -{ - FloatingSplit *fs; - - g_return_val_if_fail (split, NULL); - - fs = g_new0 (FloatingSplit, 1); - fs->m_split = split; - fs->m_account = xaccSplitGetAccount (split); - fs->m_transaction = xaccSplitGetParent (split); - fs->m_memo = xaccSplitGetMemo (split); - fs->m_action = xaccSplitGetAction (split); - fs->m_reconcile_state = xaccSplitGetReconcile (split); - fs->m_reconcile_date = xaccSplitGetDateReconciled (split); - fs->m_amount = xaccSplitGetAmount (split); - fs->m_value = xaccSplitGetValue (split); - - return fs; -} - -/* Copy a temporary split representation onto a real split. - If possible, insert the split into the account of the - split representation. Not all values are copied. The reconcile - status and date are not copied. The split's guid is, - of course, unchanged. -*/ -void gnc_float_split_to_split (const FloatingSplit *fs, Split *split) -{ - g_return_if_fail(split); - - if (fs->m_memo) - xaccSplitSetMemo (split, fs->m_memo); - if (fs->m_action) - xaccSplitSetAction (split, fs->m_action); - xaccSplitSetAmount (split, fs->m_amount); - xaccSplitSetValue (split, fs->m_value); - if (fs->m_account) - { - xaccAccountBeginEdit (fs->m_account); - xaccSplitSetAccount (split, fs->m_account); - xaccAccountCommitEdit (fs->m_account); - } -} - -/* accessors */ -Transaction *gnc_float_txn_get_txn (const FloatingTxn *ft) -{ - g_return_val_if_fail (ft, NULL); - return ft->m_txn; -} - -gnc_commodity *gnc_float_txn_get_currency (const FloatingTxn *ft) -{ - g_return_val_if_fail (ft, NULL); - return ft->m_currency; -} - -time64 gnc_float_txn_get_date_entered (const FloatingTxn *ft) -{ - g_return_val_if_fail (ft, G_MAXINT64); - return ft->m_date_entered; -} - -time64 gnc_float_txn_get_date_posted (const FloatingTxn *ft) -{ - g_return_val_if_fail (ft, G_MAXINT64); - return ft->m_date_posted; -} - -const char *gnc_float_txn_get_num (const FloatingTxn *ft) -{ - g_return_val_if_fail (ft, NULL); - return ft->m_num; -} - -const char *gnc_float_txn_get_description (const FloatingTxn *ft) -{ - g_return_val_if_fail (ft, NULL); - return ft->m_description; -} - -const char *gnc_float_txn_get_notes (const FloatingTxn *ft) -{ - g_return_val_if_fail (ft, NULL); - return ft->m_notes; -} - -const char *gnc_float_txn_get_association (const FloatingTxn *ft) -{ - g_return_val_if_fail (ft, NULL); - return ft->m_association; -} - -SplitList *gnc_float_txn_get_splits (const FloatingTxn *ft) -{ - g_return_val_if_fail (ft, NULL); - return ft->m_splits; -} - -FloatingSplit *gnc_float_txn_get_float_split (const FloatingTxn *ft, guint index) -{ - FloatingSplit *fs = NULL; - guint size = 0; - - g_return_val_if_fail (ft, NULL); - g_return_val_if_fail (ft->m_splits, NULL); - g_return_val_if_fail (index < g_list_length (ft->m_splits) , NULL); - return g_list_nth_data (ft->m_splits, index); -} - -FloatingSplit *gnc_float_txn_get_other_float_split (const FloatingTxn *ft, FloatingSplit *fs) -{ - guint size = 0, other = 0; - - g_return_val_if_fail (ft, NULL); - g_return_val_if_fail (ft->m_splits, NULL); - g_return_val_if_fail (g_list_length (ft->m_splits) == 2 , NULL); - - if (g_list_nth_data (ft->m_splits, 0) == fs) - other = 1; - - return g_list_nth_data (ft->m_splits, other); -} - -/* modifiers */ -void gnc_float_txn_set_txn (FloatingTxn *ft, Transaction *txn) -{ - g_return_if_fail (ft); - ft->m_txn = txn; -}; - -void gnc_float_txn_set_currency (FloatingTxn *ft, gnc_commodity *currency) -{ - g_return_if_fail (ft); - ft->m_currency = currency; -}; - -void gnc_float_txn_set_date_entered (FloatingTxn *ft, time64 date_entered) -{ - g_return_if_fail (ft); - ft->m_date_entered = date_entered; -}; - -void gnc_float_txn_set_date_posted (FloatingTxn *ft, time64 date_posted) -{ - g_return_if_fail (ft); - ft->m_date_posted = date_posted; -}; - -void gnc_float_txn_set_num (FloatingTxn *ft, const char *num) -{ - g_return_if_fail (ft); - ft->m_num = num; -}; - -void gnc_float_txn_set_description (FloatingTxn *ft, const char *description) -{ - g_return_if_fail (ft); - ft->m_description = description; -}; - -void gnc_float_txn_set_notes (FloatingTxn *ft, const char *notes) -{ - g_return_if_fail (ft); - ft->m_notes = notes; -}; - -void gnc_float_txn_set_association (FloatingTxn *ft, const char *association) -{ - g_return_if_fail (ft); - ft->m_association = association; -}; - -void gnc_float_txn_set_splits (FloatingTxn *ft, SplitList *splits) -{ - g_return_if_fail (ft); - ft->m_splits = splits; -}; - -void gnc_float_txn_append_float_split (FloatingTxn *ft, FloatingSplit *fs) -{ - g_return_if_fail (ft); - g_return_if_fail (fs); - ft->m_splits = g_list_append (ft->m_splits, fs); -} - -/* This function takes a C transaction and returns - a representation of it as a floating_txn. */ -FloatingTxn *gnc_txn_to_float_txn (Transaction *txn, gboolean use_cut_semantics) -{ - GList *iter; - - FloatingTxn *ft = g_new0 (FloatingTxn, 1); - - ft->m_txn = txn; - ft->m_currency = xaccTransGetCurrency (txn); - ft->m_date_entered = xaccTransGetDateEntered (txn); - if (use_cut_semantics) - { - ft->m_date_posted = xaccTransGetDate (txn); - ft->m_num = xaccTransGetNum (txn); - } - ft->m_description = xaccTransGetDescription (txn); - ft->m_notes = xaccTransGetNotes (txn); - ft->m_association = xaccTransGetAssociation (txn); - - for (iter = xaccTransGetSplitList (txn); iter ; iter = iter->next) - { - Split *split = iter->data; - if (split) - { - FloatingSplit *fs = gnc_split_to_float_split (split); - ft->m_splits = g_list_prepend (ft->m_splits, fs); - } - } - ft->m_splits = g_list_reverse (ft->m_splits); - - return ft; -} - -void gnc_float_txn_to_txn (const FloatingTxn *ft, Transaction *txn, gboolean do_commit) -{ - gnc_float_txn_to_txn_swap_accounts (ft, txn, NULL, NULL, do_commit); -} - -/* Copy a temporary representation of a transaction onto a real transaction. - I f they exist the two account*s (acct1 and acct2) are used to swap accounts - when when creating splits. */ -void gnc_float_txn_to_txn_swap_accounts (const FloatingTxn *ft, Transaction *txn, Account *acct1, Account *acct2, gboolean do_commit) -{ - GList *iter; - - g_return_if_fail (ft); - g_return_if_fail (txn); - - if (!xaccTransIsOpen (txn)) - xaccTransBeginEdit (txn); - - if (ft->m_currency) - xaccTransSetCurrency (txn, ft->m_currency); - if (ft->m_description) - xaccTransSetDescription (txn, ft->m_description); - if (ft->m_num) - xaccTransSetNum (txn, ft->m_num); - if (ft->m_notes) - xaccTransSetNotes (txn, ft->m_notes); - if (ft->m_association) - xaccTransSetAssociation (txn, ft->m_association); - if (ft->m_date_posted) - xaccTransSetDatePostedSecs (txn, ft->m_date_posted); - - /* strip off the old splits */ - while (xaccTransCountSplits (txn)) - xaccSplitDestroy (xaccTransGetSplit (txn, 0)); - - /* and put on the new ones! Please note they go in the *same* - order as in the original transaction. This is important. */ - for (iter = ft->m_splits; iter; iter = iter->next) - { - Account *old_acc, *new_acc; - Split *split; - FloatingSplit *fs = iter->data; - if (!fs) - continue; - - split = xaccMallocSplit (xaccTransGetBook (txn)); - - old_acc = fs->m_account; - if (fs->m_account == acct1) - new_acc = acct2; - else if (fs->m_account == acct2) - new_acc = acct1; - else - new_acc = fs->m_account; - - fs->m_account = new_acc; - gnc_float_split_to_split (fs, split); - fs->m_account = old_acc; - xaccSplitSetParent (split, txn); - } - - /* close the transaction */ - if (do_commit) - xaccTransCommitEdit (txn); -} diff --git a/gnucash/register/ledger-core/split-register-copy-ops-internals.h b/gnucash/register/ledger-core/split-register-copy-ops-internals.h deleted file mode 100644 index 2f4976566f..0000000000 --- a/gnucash/register/ledger-core/split-register-copy-ops-internals.h +++ /dev/null @@ -1,119 +0,0 @@ -/********************************************************************\ - * split-register-copy-ops-internals.c -- internal details of * - * copy/paste semantics for transactions and splits * - * Port to C of engine-interface * - * originally written by Dave Peticolas * - * © 2019 Geert Janssens - * * - * This program is free software; you can redistribute it and/or * - * modify it under the terms of the GNU General Public License as * - * published by the Free Software Foundation; either version 2 of * - * the License, or (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU General Public License for more details. * - * * - * You should have received a copy of the GNU General Public License* - * along with this program; if not, write to the Free Software * - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * - * \********************************************************************/ - -#ifndef SPLIT_REGISTER_COPY_OPS_INTERNAL_H -#define SPLIT_REGISTER_COPY_OPS_INTERNAL_H - -#include - -#include "gnc-engine.h" /* for typedefs */ -#include "qof.h" - -#include "guid.h" -#include "Split.h" -#include "Account.h" -#include "Transaction.h" - -typedef struct -{ - Split *m_split; - Account *m_account; - Transaction *m_transaction; - const char *m_memo; - const char *m_action; - time64 m_reconcile_date; - char m_reconcile_state; - gnc_numeric m_value; - gnc_numeric m_amount; -} FloatingSplit; - -typedef struct -{ - Transaction *m_txn; - gnc_commodity *m_currency; - time64 m_date_entered; - time64 m_date_posted; - const char *m_num; - const char *m_description; - const char *m_notes; - const char *m_association; - SplitList *m_splits; -} FloatingTxn; - -/* accessors */ -Split *gnc_float_split_get_split(const FloatingSplit* fs); -Account *gnc_float_split_get_account (const FloatingSplit *fs); /* direct account pointer rather than account guid */ -Transaction *gnc_float_split_get_transaction (const FloatingSplit *fs); /* direct transaction pointer rather than transaction guid */ -const char *gnc_float_split_get_memo (const FloatingSplit *fs); -const char *gnc_float_split_get_action (const FloatingSplit *fs); -char gnc_float_split_get_reconcile_state (const FloatingSplit *fs); -time64 gnc_float_split_get_reconcile_date (const FloatingSplit *fs); -gnc_numeric gnc_float_split_get_amount (const FloatingSplit *fs); -gnc_numeric gnc_float_split_get_value (const FloatingSplit *fs); - -/* modifiers */ -void gnc_float_split_set_split (FloatingSplit *fs, Split *split); -void gnc_float_split_set_account (FloatingSplit *fs, Account *account); /* direct account pointer rather than account guid */ -void gnc_float_split_set_transaction (FloatingSplit *fs, Transaction *transaction); /* direct transaction pointer rather than transaction guid */ -void gnc_float_split_set_memo (FloatingSplit *fs, const char *memo); -void gnc_float_split_set_action (FloatingSplit *fs, const char *action); -void gnc_float_split_set_reconcile_state (FloatingSplit *fs, char reconcile_state); -void gnc_float_split_set_reconcile_date (FloatingSplit *fs, time64 reconcile_date); -void gnc_float_split_set_amount (FloatingSplit *fs, gnc_numeric amount); -void gnc_float_split_set_value (FloatingSplit *fs, gnc_numeric value); - -FloatingSplit *gnc_split_to_float_split (Split *split); -void gnc_float_split_to_split (const FloatingSplit *fs, Split *split); - -/* accessors */ -Transaction *gnc_float_txn_get_txn (const FloatingTxn *ft); -gnc_commodity *gnc_float_txn_get_currency (const FloatingTxn *ft); -time64 gnc_float_txn_get_date_entered (const FloatingTxn *ft); -time64 gnc_float_txn_get_date_posted (const FloatingTxn *ft); -const char *gnc_float_txn_get_num (const FloatingTxn *ft); -const char *gnc_float_txn_get_description (const FloatingTxn *ft); -const char *gnc_float_txn_get_notes (const FloatingTxn *ft); -const char *gnc_float_txn_get_association (const FloatingTxn *ft); -SplitList *gnc_float_txn_get_splits (const FloatingTxn *ft); - -FloatingSplit *gnc_float_txn_get_float_split (const FloatingTxn *ft, guint index); -FloatingSplit *gnc_float_txn_get_other_float_split (const FloatingTxn *ft, FloatingSplit *fs); - -/* modifiers */ -void gnc_float_txn_set_txn (FloatingTxn *ft, Transaction *txn); -void gnc_float_txn_set_currency (FloatingTxn *ft, gnc_commodity *currency); -void gnc_float_txn_set_date_entered (FloatingTxn *ft, time64 date_entered); -void gnc_float_txn_set_date_posted (FloatingTxn *ft, time64 date_posted); -void gnc_float_txn_set_num (FloatingTxn *ft, const char *num); -void gnc_float_txn_set_description (FloatingTxn *ft, const char *description); -void gnc_float_txn_set_notes (FloatingTxn *ft, const char *notes); -void gnc_float_txn_set_association (FloatingTxn *ft, const char *association); -void gnc_float_txn_set_splits (FloatingTxn *ft, SplitList *splits); - -void gnc_float_txn_append_float_split (FloatingTxn *ft, FloatingSplit *fs); - -FloatingTxn *gnc_txn_to_float_txn (Transaction *txn, gboolean use_cut_semantics); - -void gnc_float_txn_to_txn (const FloatingTxn *ft, Transaction *txn, gboolean do_commit); -void gnc_float_txn_to_txn_swap_accounts (const FloatingTxn *ft, Transaction *txn, Account *acct1, Account *acct2, gboolean do_commit); - -#endif diff --git a/gnucash/register/ledger-core/split-register-copy-ops.c b/gnucash/register/ledger-core/split-register-copy-ops.c index 8efe5e71c0..22c36f6bb7 100644 --- a/gnucash/register/ledger-core/split-register-copy-ops.c +++ b/gnucash/register/ledger-core/split-register-copy-ops.c @@ -1,9 +1,9 @@ /********************************************************************\ - * split-register-copy-ops.c -- implement copy/paste semantics for * - * transactions and splits * - * Copyright (C) 1999 Linas Vepstas * - * Copyright (C) 2000 Dave Peticolas * - * Copyright (C) 2017 Aaron Laws * + * split-register-copy-ops.c -- copy/paste semantics for * + * transactions and splits * + * Port to C of engine-interface * + * originally written by Dave Peticolas * + * © 2019 Geert Janssens * * * This program is free software; you can redistribute it and/or * * modify it under the terms of the GNU General Public License as * @@ -20,692 +20,410 @@ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * \********************************************************************/ -#include - -#include "swig-runtime.h" -#include -#if PLATFORM(WINDOWS) -#include -#include -#endif - #include -#include -#include -#ifdef __MINGW32__ -#define _GL_UNISTD_H //Deflect poisonous define of close in Guile's GnuLib -#endif -#include -#include -#ifdef HAVE_UNISTD_H -# ifdef close -# undef close -# endif -# include -#else -# include -# define close _close -#endif -#ifndef HAVE_STRPTIME -# include "strptime.h" -#endif -#include "qof.h" -#include "gnc-engine-guile.h" -#include "glib-guile.h" -#include "gnc-glib-utils.h" -#include "gnc-guile-utils.h" -#include "gnc-prefs.h" -#include "guile-mappings.h" +#include "config.h" #include "split-register-copy-ops.h" -#define UNUSED_VAR __attribute__ ((unused)) - -/* This static indicates the debugging module this .o belongs to. */ -static QofLogModule UNUSED_VAR log_module = GNC_MOD_GUILE; - -struct _setters +/* accessors */ +Split *gnc_float_split_get_split (const FloatingSplit *fs) { - SCM split_scm_account_guid; - SCM split_scm_memo; - SCM split_scm_action; - SCM split_scm_reconcile_state; - SCM split_scm_amount; - SCM split_scm_value; + g_return_val_if_fail (fs, NULL); + return fs->m_split; +} - SCM trans_scm_date; - SCM trans_scm_num; - SCM trans_scm_description; - SCM trans_scm_notes; - SCM trans_scm_append_split_scm; -} setters; - -struct _getters +Account *gnc_float_split_get_account (const FloatingSplit *fs) /* direct account pointer rather than account guid */ { - SCM split_scm_memo; - SCM split_scm_action; - SCM split_scm_amount; - SCM split_scm_value; + g_return_val_if_fail (fs, NULL); + return fs->m_account; +} - SCM trans_scm_split_scms; - SCM trans_scm_split_scm; - SCM trans_scm_other_split_scm; -} getters; - -struct _predicates +Transaction *gnc_float_split_get_transaction (const FloatingSplit *fs) /* direct transaction pointer rather than transaction guid */ { - SCM is_split_scm; - SCM is_trans_scm; -} predicates; + g_return_val_if_fail (fs, NULL); + return fs->m_transaction; +} -struct _Process +const char *gnc_float_split_get_memo (const FloatingSplit *fs) { - GPid pid; - gint fd_stdin; - gint fd_stdout; - gint fd_stderr; - gboolean dead; - gboolean detached; + g_return_val_if_fail (fs, NULL); + return fs->m_memo; +} + +const char *gnc_float_split_get_action (const FloatingSplit *fs) +{ + g_return_val_if_fail (fs, NULL); + return fs->m_action; +} + +char gnc_float_split_get_reconcile_state (const FloatingSplit *fs) +{ + g_return_val_if_fail (fs, '\0'); + return fs->m_reconcile_state; +} + +time64 gnc_float_split_get_reconcile_date (const FloatingSplit *fs) +{ + g_return_val_if_fail (fs, G_MAXINT64); + return fs->m_reconcile_date; +} + +gnc_numeric gnc_float_split_get_amount (const FloatingSplit *fs) +{ + g_return_val_if_fail (fs, gnc_numeric_zero()); + return fs->m_amount; +} + +gnc_numeric gnc_float_split_get_value (const FloatingSplit *fs) +{ + g_return_val_if_fail (fs, gnc_numeric_zero()); + return fs->m_value; +} + + +/* modifiers */ +void gnc_float_split_set_split(FloatingSplit *fs, Split *split) +{ + g_return_if_fail (fs); + fs->m_split = split; }; -static void -initialize_scm_functions() +void gnc_float_split_set_account (FloatingSplit *fs, Account *account) /* direct account pointer rather than account guid */ { - static gboolean scm_funcs_inited = FALSE; + g_return_if_fail (fs); + fs->m_account = account; +}; - if (scm_funcs_inited) - return; +void gnc_float_split_set_transaction (FloatingSplit *fs, Transaction *transaction) /* direct transaction pointer rather than transaction guid */ +{ + g_return_if_fail (fs); + fs->m_transaction = transaction; +}; - setters.split_scm_account_guid = - scm_c_eval_string("gnc:split-scm-set-account-guid"); - setters.split_scm_memo = scm_c_eval_string("gnc:split-scm-set-memo"); - setters.split_scm_action = scm_c_eval_string("gnc:split-scm-set-action"); - setters.split_scm_reconcile_state = - scm_c_eval_string("gnc:split-scm-set-reconcile-state"); - setters.split_scm_amount = scm_c_eval_string("gnc:split-scm-set-amount"); - setters.split_scm_value = scm_c_eval_string("gnc:split-scm-set-value"); +void gnc_float_split_set_memo (FloatingSplit *fs, const char *memo) +{ + g_return_if_fail (fs); + fs->m_memo = memo; +}; - setters.trans_scm_date = scm_c_eval_string("gnc:transaction-scm-set-date-posted"); - setters.trans_scm_num = scm_c_eval_string("gnc:transaction-scm-set-num"); - setters.trans_scm_description = - scm_c_eval_string("gnc:transaction-scm-set-description"); - setters.trans_scm_notes = scm_c_eval_string("gnc:transaction-scm-set-notes"); - setters.trans_scm_append_split_scm = - scm_c_eval_string("gnc:transaction-scm-append-split-scm"); +void gnc_float_split_set_action (FloatingSplit *fs, const char *action) +{ + g_return_if_fail (fs); + fs->m_action = action; +}; - getters.split_scm_memo = scm_c_eval_string("gnc:split-scm-get-memo"); - getters.split_scm_action = scm_c_eval_string("gnc:split-scm-get-action"); - getters.split_scm_amount = scm_c_eval_string("gnc:split-scm-get-amount"); - getters.split_scm_value = scm_c_eval_string("gnc:split-scm-get-value"); +void gnc_float_split_set_reconcile_state (FloatingSplit *fs, char reconcile_state) +{ + g_return_if_fail (fs); + fs->m_reconcile_state = reconcile_state; +}; - getters.trans_scm_split_scms = - scm_c_eval_string("gnc:transaction-scm-get-split-scms"); - getters.trans_scm_split_scm = - scm_c_eval_string("gnc:transaction-scm-get-split-scm"); - getters.trans_scm_other_split_scm = - scm_c_eval_string("gnc:transaction-scm-get-other-split-scm"); +void gnc_float_split_set_reconcile_date (FloatingSplit *fs, time64 reconcile_date) +{ + g_return_if_fail (fs); + fs->m_reconcile_date = reconcile_date; +}; - predicates.is_split_scm = scm_c_eval_string("gnc:split-scm?"); - predicates.is_trans_scm = scm_c_eval_string("gnc:transaction-scm?"); +void gnc_float_split_set_amount (FloatingSplit *fs, const gnc_numeric amount) +{ + g_return_if_fail (fs); - scm_funcs_inited = TRUE; + fs->m_amount = amount; +}; + +void gnc_float_split_set_value (FloatingSplit *fs, const gnc_numeric value) +{ + g_return_if_fail (fs); + + fs->m_value = value; +}; + +/* This function takes a split and returns a representation + of it as a floating_split structure. Assumes the transaction is open + for editing. +*/ +FloatingSplit *gnc_split_to_float_split (Split *split) +{ + FloatingSplit *fs; + + g_return_val_if_fail (split, NULL); + + fs = g_new0 (FloatingSplit, 1); + fs->m_split = split; + fs->m_account = xaccSplitGetAccount (split); + fs->m_transaction = xaccSplitGetParent (split); + fs->m_memo = xaccSplitGetMemo (split); + fs->m_action = xaccSplitGetAction (split); + fs->m_reconcile_state = xaccSplitGetReconcile (split); + fs->m_reconcile_date = xaccSplitGetDateReconciled (split); + fs->m_amount = xaccSplitGetAmount (split); + fs->m_value = xaccSplitGetValue (split); + + return fs; } -/********************************************************************\ - * gnc_copy_split * - * returns a scheme representation of a split. If the split is * - * NULL, SCM_UNDEFINED is returned. * - * * - * Args: split - the split to copy * - * use_cut_semantics - if TRUE, copy is for a 'cut' operation * - * Returns: SCM representation of split or SCM_UNDEFINED * -\********************************************************************/ -SCM -gnc_copy_split(Split *split, gboolean use_cut_semantics) +/* Copy a temporary split representation onto a real split. + If possible, insert the split into the account of the + split representation. Not all values are copied. The reconcile + status and date are not copied. The split's guid is, + of course, unchanged. +*/ +void gnc_float_split_to_split (const FloatingSplit *fs, Split *split) { - static swig_type_info *split_type = NULL; - SCM func; - SCM arg; - - if (split == NULL) - return SCM_UNDEFINED; - - func = scm_c_eval_string("gnc:split->split-scm"); - if (!scm_is_procedure(func)) - return SCM_UNDEFINED; - - if (!split_type) - split_type = SWIG_TypeQuery("_p_Split"); - - arg = SWIG_NewPointerObj(split, split_type, 0); - - return scm_call_2(func, arg, SCM_BOOL(use_cut_semantics)); -} - - -/********************************************************************\ - * gnc_copy_split_scm_onto_split * - * copies a scheme representation of a split onto an actual split.* - * * - * Args: split_scm - the scheme representation of a split * - * split - the split to copy onto * - * Returns: Nothing * -\********************************************************************/ -void -gnc_copy_split_scm_onto_split(SCM split_scm, Split *split, - QofBook * book) -{ - static swig_type_info *split_type = NULL; - SCM result; - SCM func; - SCM arg; - - if (split_scm == SCM_UNDEFINED) - return; - - if (split == NULL) - return; - - g_return_if_fail (book); - - func = scm_c_eval_string("gnc:split-scm?"); - if (!scm_is_procedure(func)) - return; - - result = scm_call_1(func, split_scm); - if (!scm_is_true(result)) - return; - - func = scm_c_eval_string("gnc:split-scm-onto-split"); - if (!scm_is_procedure(func)) - return; - - if (!split_type) - split_type = SWIG_TypeQuery("_p_Split"); - - arg = SWIG_NewPointerObj(split, split_type, 0); - - scm_call_3(func, split_scm, arg, gnc_book_to_scm (book)); -} - - -/********************************************************************\ - * gnc_is_split_scm * - * returns true if the scm object is a scheme split * - * * - * Args: scm - a scheme object * - * Returns: true if scm is a scheme split * -\********************************************************************/ -static gboolean -gnc_is_split_scm(SCM scm) -{ - initialize_scm_functions(); - - return scm_is_true(scm_call_1(predicates.is_split_scm, scm)); -} - - -/********************************************************************\ - * gnc_is_trans_scm * - * returns true if the scm object is a scheme transaction * - * * - * Args: scm - a scheme object * - * Returns: true if scm is a scheme transaction * -\********************************************************************/ -static gboolean -gnc_is_trans_scm(SCM scm) -{ - initialize_scm_functions(); - - return scm_is_true(scm_call_1(predicates.is_trans_scm, scm)); -} - - -/********************************************************************\ - * gnc_split_scm_set_account * - * set the account of a scheme representation of a split. * - * * - * Args: split_scm - the scheme split * - * account - the account to set * - * Returns: Nothing * -\********************************************************************/ -void -gnc_split_scm_set_account(SCM split_scm, Account *account) -{ - gchar guid_string[GUID_ENCODING_LENGTH+1]; - SCM arg; - - initialize_scm_functions(); - - if (!gnc_is_split_scm(split_scm)) - return; - if (account == NULL) - return; - - guid_to_string_buff(xaccAccountGetGUID(account), guid_string); - if (strlen(guid_string) == 0) - return; - - arg = scm_from_utf8_string(guid_string); - - scm_call_2(setters.split_scm_account_guid, split_scm, arg); -} - - -/********************************************************************\ - * gnc_split_scm_set_memo * - * set the memo of a scheme representation of a split. * - * * - * Args: split_scm - the scheme split * - * memo - the memo to set * - * Returns: Nothing * -\********************************************************************/ -void -gnc_split_scm_set_memo(SCM split_scm, const char *memo) -{ - SCM arg; - - initialize_scm_functions(); - - if (!gnc_is_split_scm(split_scm)) - return; - if (memo == NULL) - return; - - arg = scm_from_utf8_string(memo); - - scm_call_2(setters.split_scm_memo, split_scm, arg); -} - - -/********************************************************************\ - * gnc_split_scm_set_action * - * set the action of a scheme representation of a split. * - * * - * Args: split_scm - the scheme split * - * action - the action to set * - * Returns: Nothing * -\********************************************************************/ -void -gnc_split_scm_set_action(SCM split_scm, const char *action) -{ - SCM arg; - - initialize_scm_functions(); - - if (!gnc_is_split_scm(split_scm)) - return; - if (action == NULL) - return; - - arg = scm_from_utf8_string(action); - - scm_call_2(setters.split_scm_action, split_scm, arg); -} - - -/********************************************************************\ - * gnc_split_scm_set_reconcile_state * - * set the reconcile state of a scheme split. * - * * - * Args: split_scm - the scheme split * - * reconcile_state - the reconcile state to set * - * Returns: Nothing * -\********************************************************************/ -void -gnc_split_scm_set_reconcile_state(SCM split_scm, char reconcile_state) -{ - SCM arg; - - initialize_scm_functions(); - - if (!gnc_is_split_scm(split_scm)) - return; - - arg = SCM_MAKE_CHAR(reconcile_state); - - scm_call_2(setters.split_scm_reconcile_state, split_scm, arg); -} - - -/********************************************************************\ - * gnc_split_scm_set_amount * - * set the amount of a scheme split * - * * - * Args: split_scm - the scheme split * - * amount - the amount to set * - * Returns: Nothing * -\********************************************************************/ -void -gnc_split_scm_set_amount(SCM split_scm, gnc_numeric amount) -{ - SCM arg; - - initialize_scm_functions(); - - if (!gnc_is_split_scm(split_scm)) - return; - - arg = gnc_numeric_to_scm(amount); - scm_call_2(setters.split_scm_amount, split_scm, arg); -} - - -/********************************************************************\ - * gnc_split_scm_set_value * - * set the value of a scheme split * - * * - * Args: split_scm - the scheme split * - * value - the value to set * - * Returns: Nothing * -\********************************************************************/ -void -gnc_split_scm_set_value(SCM split_scm, gnc_numeric value) -{ - SCM arg; - - initialize_scm_functions(); - - if (!gnc_is_split_scm(split_scm)) - return; - - arg = gnc_numeric_to_scm(value); - scm_call_2(setters.split_scm_value, split_scm, arg); -} - - -/********************************************************************\ - * gnc_split_scm_get_amount * - * return the amount of a scheme split * - * * - * Args: split_scm - the scheme split * - * Returns: amount of scheme split * -\********************************************************************/ -gnc_numeric -gnc_split_scm_get_amount(SCM split_scm) -{ - SCM result; - - initialize_scm_functions(); - - if (!gnc_is_split_scm(split_scm)) - return gnc_numeric_zero (); - - result = scm_call_1(getters.split_scm_amount, split_scm); - if (!scm_rational_p(result)) - return gnc_numeric_zero (); - - return gnc_scm_to_numeric(result); -} - - -/********************************************************************\ - * gnc_split_scm_get_value * - * return the value of a scheme split * - * * - * Args: split_scm - the scheme split * - * Returns: value of scheme split * -\********************************************************************/ -gnc_numeric -gnc_split_scm_get_value(SCM split_scm) -{ - SCM result; - - initialize_scm_functions(); - - if (!gnc_is_split_scm(split_scm)) - return gnc_numeric_zero (); - - result = scm_call_1(getters.split_scm_value, split_scm); - if (!scm_rational_p(result)) - return gnc_numeric_zero (); - - return gnc_scm_to_numeric(result); -} - - -/********************************************************************\ - * gnc_copy_trans * - * returns a scheme representation of a transaction. If the * - * transaction is NULL, SCM_UNDEFINED is returned. * - * * - * Args: trans - the transaction to copy * - * use_cut_semantics - if TRUE, copy is for a 'cut' operation * - * Returns: SCM representation of transaction or SCM_UNDEFINED * -\********************************************************************/ -SCM -gnc_copy_trans(Transaction *trans, gboolean use_cut_semantics) -{ - static swig_type_info *trans_type = NULL; - SCM func; - SCM arg; - - if (trans == NULL) - return SCM_UNDEFINED; - - func = scm_c_eval_string("gnc:transaction->transaction-scm"); - if (!scm_is_procedure(func)) - return SCM_UNDEFINED; - - if (!trans_type) - trans_type = SWIG_TypeQuery("_p_Transaction"); - - arg = SWIG_NewPointerObj(trans, trans_type, 0); - - return scm_call_2(func, arg, SCM_BOOL(use_cut_semantics)); -} - - -/********************************************************************\ - * gnc_copy_trans_scm_onto_trans * - * copies a scheme representation of a transaction onto * - * an actual transaction. * - * * - * Args: trans_scm - the scheme representation of a transaction * - * trans - the transaction to copy onto * - * Returns: Nothing * -\********************************************************************/ -void -gnc_copy_trans_scm_onto_trans(SCM trans_scm, Transaction *trans, - gboolean do_commit, QofBook *book) -{ - gnc_copy_trans_scm_onto_trans_swap_accounts(trans_scm, trans, NULL, NULL, - do_commit, book); -} - - -/********************************************************************\ - * gnc_copy_trans_scm_onto_trans_swap_accounts * - * copies a scheme representation of a transaction onto * - * an actual transaction. If guid_1 and guid_2 are not NULL, * - * the account guids of the splits are swapped accordingly. * - * * - * Args: trans_scm - the scheme representation of a transaction * - * trans - the transaction to copy onto * - * guid_1 - account guid to swap with guid_2 * - * guid_2 - account guid to swap with guid_1 * - * do_commit - whether to commit the edits * - * Returns: Nothing * -\********************************************************************/ -void -gnc_copy_trans_scm_onto_trans_swap_accounts(SCM trans_scm, - Transaction *trans, - const GncGUID *guid_1, - const GncGUID *guid_2, - gboolean do_commit, - QofBook *book) -{ - static swig_type_info *trans_type = NULL; - SCM result; - SCM func; - SCM arg; - - if (trans_scm == SCM_UNDEFINED) - return; - - if (trans == NULL) - return; - - g_return_if_fail (book); - - func = scm_c_eval_string("gnc:transaction-scm?"); - if (!scm_is_procedure(func)) - return; - - result = scm_call_1(func, trans_scm); - if (!scm_is_true(result)) - return; - - func = scm_c_eval_string("gnc:transaction-scm-onto-transaction"); - if (!scm_is_procedure(func)) - return; - - if (!trans_type) - trans_type = SWIG_TypeQuery("_p_Transaction"); - - arg = SWIG_NewPointerObj(trans, trans_type, 0); - - if ((guid_1 == NULL) || (guid_2 == NULL)) + g_return_if_fail(split); + + if (fs->m_memo) + xaccSplitSetMemo (split, fs->m_memo); + if (fs->m_action) + xaccSplitSetAction (split, fs->m_action); + xaccSplitSetAmount (split, fs->m_amount); + xaccSplitSetValue (split, fs->m_value); + if (fs->m_account) { - SCM args = SCM_EOL; - SCM commit; - - commit = SCM_BOOL(do_commit); - - args = scm_cons(gnc_book_to_scm (book), args); - args = scm_cons(commit, args); - args = scm_cons(SCM_EOL, args); - args = scm_cons(arg, args); - args = scm_cons(trans_scm, args); - - scm_apply(func, args, SCM_EOL); - } - else - { - gchar guidstr[GUID_ENCODING_LENGTH+1]; - SCM from, to; - SCM map = SCM_EOL; - SCM args = SCM_EOL; - SCM commit; - - args = scm_cons(gnc_book_to_scm (book), args); - - commit = SCM_BOOL(do_commit); - - args = scm_cons(commit, args); - - guid_to_string_buff(guid_1, guidstr); - from = scm_from_utf8_string(guidstr); - guid_to_string_buff(guid_2, guidstr); - to = scm_from_utf8_string(guidstr); - - map = scm_cons(scm_cons(from, to), map); - map = scm_cons(scm_cons(to, from), map); - - args = scm_cons(map, args); - args = scm_cons(arg, args); - args = scm_cons(trans_scm, args); - - scm_apply(func, args, SCM_EOL); + xaccAccountBeginEdit (fs->m_account); + xaccSplitSetAccount (split, fs->m_account); + xaccAccountCommitEdit (fs->m_account); } } -/********************************************************************\ - * gnc_trans_scm_append_split_scm * - * append the scheme split onto the scheme transaction * - * * - * Args: trans_scm - the scheme transaction * - * split_scm - the scheme split to append * - * Returns: Nothing * -\********************************************************************/ -void -gnc_trans_scm_append_split_scm(SCM trans_scm, SCM split_scm) +/* accessors */ +Transaction *gnc_float_txn_get_txn (const FloatingTxn *ft) { - initialize_scm_functions(); - - if (!gnc_is_trans_scm(trans_scm)) - return; - if (!gnc_is_split_scm(split_scm)) - return; - - scm_call_2(setters.trans_scm_append_split_scm, trans_scm, split_scm); + g_return_val_if_fail (ft, NULL); + return ft->m_txn; } - -/********************************************************************\ - * gnc_trans_scm_get_split_scm * - * get the indexth scheme split of a scheme transaction. * - * * - * Args: trans_scm - the scheme transaction * - * index - the index of the split to get * - * Returns: scheme split to get, or SCM_UNDEFINED if none * -\********************************************************************/ -SCM -gnc_trans_scm_get_split_scm(SCM trans_scm, int index) +gnc_commodity *gnc_float_txn_get_currency (const FloatingTxn *ft) { - SCM arg; - - initialize_scm_functions(); - - if (!gnc_is_trans_scm(trans_scm)) - return SCM_UNDEFINED; - - arg = scm_from_int (index); - - return scm_call_2(getters.trans_scm_split_scm, trans_scm, arg); + g_return_val_if_fail (ft, NULL); + return ft->m_currency; } - -/********************************************************************\ - * gnc_trans_scm_get_other_split_scm * - * get the other scheme split of a scheme transaction. * - * * - * Args: trans_scm - the scheme transaction * - * split_scm - the split not to get * - * Returns: other scheme split, or SCM_UNDEFINED if none * -\********************************************************************/ -SCM -gnc_trans_scm_get_other_split_scm(SCM trans_scm, SCM split_scm) +time64 gnc_float_txn_get_date_entered (const FloatingTxn *ft) { - SCM result; - - initialize_scm_functions(); - - if (!gnc_is_trans_scm(trans_scm)) - return SCM_UNDEFINED; - if (!gnc_is_split_scm(split_scm)) - return SCM_UNDEFINED; - - result = scm_call_2(getters.trans_scm_other_split_scm, trans_scm, split_scm); - - if (!gnc_is_split_scm(result)) - return SCM_UNDEFINED; - - return result; + g_return_val_if_fail (ft, G_MAXINT64); + return ft->m_date_entered; } - -/********************************************************************\ - * gnc_trans_scm_get_num_splits * - * get the number of scheme splits in a scheme transaction. * - * * - * Args: trans_scm - the scheme transaction * - * Returns: number of scheme splits in the transaction * -\********************************************************************/ -int -gnc_trans_scm_get_num_splits(SCM trans_scm) +time64 gnc_float_txn_get_date_posted (const FloatingTxn *ft) { - SCM result; - - initialize_scm_functions(); - - if (!gnc_is_trans_scm(trans_scm)) - return 0; - - result = scm_call_1(getters.trans_scm_split_scms, trans_scm); - - if (!scm_is_list(result)) - return 0; - - return scm_to_int(scm_length(result)); + g_return_val_if_fail (ft, G_MAXINT64); + return ft->m_date_posted; +} + +const char *gnc_float_txn_get_num (const FloatingTxn *ft) +{ + g_return_val_if_fail (ft, NULL); + return ft->m_num; +} + +const char *gnc_float_txn_get_description (const FloatingTxn *ft) +{ + g_return_val_if_fail (ft, NULL); + return ft->m_description; +} + +const char *gnc_float_txn_get_notes (const FloatingTxn *ft) +{ + g_return_val_if_fail (ft, NULL); + return ft->m_notes; +} + +const char *gnc_float_txn_get_association (const FloatingTxn *ft) +{ + g_return_val_if_fail (ft, NULL); + return ft->m_association; +} + +SplitList *gnc_float_txn_get_splits (const FloatingTxn *ft) +{ + g_return_val_if_fail (ft, NULL); + return ft->m_splits; +} + +FloatingSplit *gnc_float_txn_get_float_split (const FloatingTxn *ft, guint index) +{ + FloatingSplit *fs = NULL; + guint size = 0; + + g_return_val_if_fail (ft, NULL); + g_return_val_if_fail (ft->m_splits, NULL); + g_return_val_if_fail (index < g_list_length (ft->m_splits) , NULL); + return g_list_nth_data (ft->m_splits, index); +} + +FloatingSplit *gnc_float_txn_get_other_float_split (const FloatingTxn *ft, FloatingSplit *fs) +{ + guint size = 0, other = 0; + + g_return_val_if_fail (ft, NULL); + g_return_val_if_fail (ft->m_splits, NULL); + g_return_val_if_fail (g_list_length (ft->m_splits) == 2 , NULL); + + if (g_list_nth_data (ft->m_splits, 0) == fs) + other = 1; + + return g_list_nth_data (ft->m_splits, other); +} + +/* modifiers */ +void gnc_float_txn_set_txn (FloatingTxn *ft, Transaction *txn) +{ + g_return_if_fail (ft); + ft->m_txn = txn; +}; + +void gnc_float_txn_set_currency (FloatingTxn *ft, gnc_commodity *currency) +{ + g_return_if_fail (ft); + ft->m_currency = currency; +}; + +void gnc_float_txn_set_date_entered (FloatingTxn *ft, time64 date_entered) +{ + g_return_if_fail (ft); + ft->m_date_entered = date_entered; +}; + +void gnc_float_txn_set_date_posted (FloatingTxn *ft, time64 date_posted) +{ + g_return_if_fail (ft); + ft->m_date_posted = date_posted; +}; + +void gnc_float_txn_set_num (FloatingTxn *ft, const char *num) +{ + g_return_if_fail (ft); + ft->m_num = num; +}; + +void gnc_float_txn_set_description (FloatingTxn *ft, const char *description) +{ + g_return_if_fail (ft); + ft->m_description = description; +}; + +void gnc_float_txn_set_notes (FloatingTxn *ft, const char *notes) +{ + g_return_if_fail (ft); + ft->m_notes = notes; +}; + +void gnc_float_txn_set_association (FloatingTxn *ft, const char *association) +{ + g_return_if_fail (ft); + ft->m_association = association; +}; + +void gnc_float_txn_set_splits (FloatingTxn *ft, SplitList *splits) +{ + g_return_if_fail (ft); + ft->m_splits = splits; +}; + +void gnc_float_txn_append_float_split (FloatingTxn *ft, FloatingSplit *fs) +{ + g_return_if_fail (ft); + g_return_if_fail (fs); + ft->m_splits = g_list_append (ft->m_splits, fs); +} + +/* This function takes a C transaction and returns + a representation of it as a floating_txn. */ +FloatingTxn *gnc_txn_to_float_txn (Transaction *txn, gboolean use_cut_semantics) +{ + GList *iter; + + FloatingTxn *ft = g_new0 (FloatingTxn, 1); + + ft->m_txn = txn; + ft->m_currency = xaccTransGetCurrency (txn); + ft->m_date_entered = xaccTransGetDateEntered (txn); + if (use_cut_semantics) + { + ft->m_date_posted = xaccTransGetDate (txn); + ft->m_num = xaccTransGetNum (txn); + } + ft->m_description = xaccTransGetDescription (txn); + ft->m_notes = xaccTransGetNotes (txn); + ft->m_association = xaccTransGetAssociation (txn); + + for (iter = xaccTransGetSplitList (txn); iter ; iter = iter->next) + { + Split *split = iter->data; + if (split) + { + FloatingSplit *fs = gnc_split_to_float_split (split); + ft->m_splits = g_list_prepend (ft->m_splits, fs); + } + } + ft->m_splits = g_list_reverse (ft->m_splits); + + return ft; +} + +void gnc_float_txn_to_txn (const FloatingTxn *ft, Transaction *txn, gboolean do_commit) +{ + gnc_float_txn_to_txn_swap_accounts (ft, txn, NULL, NULL, do_commit); +} + +/* Copy a temporary representation of a transaction onto a real transaction. + I f they exist the two account*s (acct1 and acct2) are used to swap accounts + when when creating splits. */ +void gnc_float_txn_to_txn_swap_accounts (const FloatingTxn *ft, Transaction *txn, Account *acct1, Account *acct2, gboolean do_commit) +{ + GList *iter; + + g_return_if_fail (ft); + g_return_if_fail (txn); + + if (!xaccTransIsOpen (txn)) + xaccTransBeginEdit (txn); + + if (ft->m_currency) + xaccTransSetCurrency (txn, ft->m_currency); + if (ft->m_description) + xaccTransSetDescription (txn, ft->m_description); + if (ft->m_num) + xaccTransSetNum (txn, ft->m_num); + if (ft->m_notes) + xaccTransSetNotes (txn, ft->m_notes); + if (ft->m_association) + xaccTransSetAssociation (txn, ft->m_association); + if (ft->m_date_posted) + xaccTransSetDatePostedSecs (txn, ft->m_date_posted); + + /* strip off the old splits */ + while (xaccTransCountSplits (txn)) + xaccSplitDestroy (xaccTransGetSplit (txn, 0)); + + /* and put on the new ones! Please note they go in the *same* + order as in the original transaction. This is important. */ + for (iter = ft->m_splits; iter; iter = iter->next) + { + Account *old_acc, *new_acc; + Split *split; + FloatingSplit *fs = iter->data; + if (!fs) + continue; + + split = xaccMallocSplit (xaccTransGetBook (txn)); + + old_acc = fs->m_account; + if (fs->m_account == acct1) + new_acc = acct2; + else if (fs->m_account == acct2) + new_acc = acct1; + else + new_acc = fs->m_account; + + fs->m_account = new_acc; + gnc_float_split_to_split (fs, split); + fs->m_account = old_acc; + xaccSplitSetParent (split, txn); + } + + /* close the transaction */ + if (do_commit) + xaccTransCommitEdit (txn); } diff --git a/gnucash/register/ledger-core/split-register-copy-ops.h b/gnucash/register/ledger-core/split-register-copy-ops.h index b417f434ad..ea1e340b2d 100644 --- a/gnucash/register/ledger-core/split-register-copy-ops.h +++ b/gnucash/register/ledger-core/split-register-copy-ops.h @@ -1,8 +1,9 @@ /********************************************************************\ - * split-register-copy-ops.h -- implement copy/paste semantics for * - * transactions and splits * - * Copyright (C) 1999 Linas Vepstas * - * Copyright (C) 2017 Aaron Laws * + * split-register-copy-ops.c -- copy/paste semantics for * + * transactions and splits * + * Port to C of engine-interface * + * originally written by Dave Peticolas * + * © 2019 Geert Janssens * * * This program is free software; you can redistribute it and/or * * modify it under the terms of the GNU General Public License as * @@ -15,55 +16,104 @@ * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License* - * along with this program; if not, contact: * - * * - * Free Software Foundation Voice: +1-617-542-5942 * - * 51 Franklin Street, Fifth Floor Fax: +1-617-542-2652 * - * Boston, MA 02110-1301, USA gnu@gnu.org * - * * -\********************************************************************/ + * along with this program; if not, write to the Free Software * + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * + * \********************************************************************/ #ifndef SPLIT_REGISTER_COPY_OPS_H #define SPLIT_REGISTER_COPY_OPS_H #include -#include +#include "gnc-engine.h" /* for typedefs */ #include "qof.h" + +#include "guid.h" +#include "Split.h" #include "Account.h" -#include "gnc-guile-utils.h" +#include "Transaction.h" -/* The next set of functions is for manipulating scheme - * representations of splits and transactions. */ +typedef struct +{ + Split *m_split; + Account *m_account; + Transaction *m_transaction; + const char *m_memo; + const char *m_action; + time64 m_reconcile_date; + char m_reconcile_state; + gnc_numeric m_value; + gnc_numeric m_amount; +} FloatingSplit; -SCM gnc_copy_split(Split *split, gboolean use_cut_semantics); -void gnc_copy_split_scm_onto_split(SCM split_scm, Split *split, - QofBook *book); +typedef struct +{ + Transaction *m_txn; + gnc_commodity *m_currency; + time64 m_date_entered; + time64 m_date_posted; + const char *m_num; + const char *m_description; + const char *m_notes; + const char *m_association; + SplitList *m_splits; +} FloatingTxn; -void gnc_split_scm_set_account(SCM split_scm, Account *account); -void gnc_split_scm_set_memo(SCM split_scm, const char *memo); -void gnc_split_scm_set_action(SCM split_scm, const char *action); -void gnc_split_scm_set_reconcile_state(SCM split_scm, char reconcile_state); -void gnc_split_scm_set_amount(SCM split_scm, gnc_numeric amount); -void gnc_split_scm_set_value(SCM split_scm, gnc_numeric value); +/* accessors */ +Split *gnc_float_split_get_split(const FloatingSplit* fs); +Account *gnc_float_split_get_account (const FloatingSplit *fs); /* direct account pointer rather than account guid */ +Transaction *gnc_float_split_get_transaction (const FloatingSplit *fs); /* direct transaction pointer rather than transaction guid */ +const char *gnc_float_split_get_memo (const FloatingSplit *fs); +const char *gnc_float_split_get_action (const FloatingSplit *fs); +char gnc_float_split_get_reconcile_state (const FloatingSplit *fs); +time64 gnc_float_split_get_reconcile_date (const FloatingSplit *fs); +gnc_numeric gnc_float_split_get_amount (const FloatingSplit *fs); +gnc_numeric gnc_float_split_get_value (const FloatingSplit *fs); -gnc_numeric gnc_split_scm_get_amount(SCM split_scm); -gnc_numeric gnc_split_scm_get_value(SCM split_scm); +/* modifiers */ +void gnc_float_split_set_split (FloatingSplit *fs, Split *split); +void gnc_float_split_set_account (FloatingSplit *fs, Account *account); /* direct account pointer rather than account guid */ +void gnc_float_split_set_transaction (FloatingSplit *fs, Transaction *transaction); /* direct transaction pointer rather than transaction guid */ +void gnc_float_split_set_memo (FloatingSplit *fs, const char *memo); +void gnc_float_split_set_action (FloatingSplit *fs, const char *action); +void gnc_float_split_set_reconcile_state (FloatingSplit *fs, char reconcile_state); +void gnc_float_split_set_reconcile_date (FloatingSplit *fs, time64 reconcile_date); +void gnc_float_split_set_amount (FloatingSplit *fs, gnc_numeric amount); +void gnc_float_split_set_value (FloatingSplit *fs, gnc_numeric value); -SCM gnc_copy_trans(Transaction *trans, gboolean use_cut_semantics); -void gnc_copy_trans_scm_onto_trans(SCM trans_scm, Transaction *trans, - gboolean do_commit, QofBook *book); -void gnc_copy_trans_scm_onto_trans_swap_accounts(SCM trans_scm, - Transaction *trans, - const GncGUID *guid_1, - const GncGUID *guid_2, - gboolean do_commit, - QofBook *book); +FloatingSplit *gnc_split_to_float_split (Split *split); +void gnc_float_split_to_split (const FloatingSplit *fs, Split *split); -void gnc_trans_scm_append_split_scm(SCM trans_scm, SCM split_scm); +/* accessors */ +Transaction *gnc_float_txn_get_txn (const FloatingTxn *ft); +gnc_commodity *gnc_float_txn_get_currency (const FloatingTxn *ft); +time64 gnc_float_txn_get_date_entered (const FloatingTxn *ft); +time64 gnc_float_txn_get_date_posted (const FloatingTxn *ft); +const char *gnc_float_txn_get_num (const FloatingTxn *ft); +const char *gnc_float_txn_get_description (const FloatingTxn *ft); +const char *gnc_float_txn_get_notes (const FloatingTxn *ft); +const char *gnc_float_txn_get_association (const FloatingTxn *ft); +SplitList *gnc_float_txn_get_splits (const FloatingTxn *ft); -SCM gnc_trans_scm_get_split_scm(SCM trans_scm, int index); -SCM gnc_trans_scm_get_other_split_scm(SCM trans_scm, SCM split_scm); -int gnc_trans_scm_get_num_splits(SCM trans_scm); +FloatingSplit *gnc_float_txn_get_float_split (const FloatingTxn *ft, guint index); +FloatingSplit *gnc_float_txn_get_other_float_split (const FloatingTxn *ft, FloatingSplit *fs); + +/* modifiers */ +void gnc_float_txn_set_txn (FloatingTxn *ft, Transaction *txn); +void gnc_float_txn_set_currency (FloatingTxn *ft, gnc_commodity *currency); +void gnc_float_txn_set_date_entered (FloatingTxn *ft, time64 date_entered); +void gnc_float_txn_set_date_posted (FloatingTxn *ft, time64 date_posted); +void gnc_float_txn_set_num (FloatingTxn *ft, const char *num); +void gnc_float_txn_set_description (FloatingTxn *ft, const char *description); +void gnc_float_txn_set_notes (FloatingTxn *ft, const char *notes); +void gnc_float_txn_set_association (FloatingTxn *ft, const char *association); +void gnc_float_txn_set_splits (FloatingTxn *ft, SplitList *splits); + +void gnc_float_txn_append_float_split (FloatingTxn *ft, FloatingSplit *fs); + +FloatingTxn *gnc_txn_to_float_txn (Transaction *txn, gboolean use_cut_semantics); + +void gnc_float_txn_to_txn (const FloatingTxn *ft, Transaction *txn, gboolean do_commit); +void gnc_float_txn_to_txn_swap_accounts (const FloatingTxn *ft, Transaction *txn, Account *acct1, Account *acct2, gboolean do_commit); #endif diff --git a/gnucash/register/ledger-core/split-register.c b/gnucash/register/ledger-core/split-register.c index 03cefca562..3bb9dc9905 100644 --- a/gnucash/register/ledger-core/split-register.c +++ b/gnucash/register/ledger-core/split-register.c @@ -39,7 +39,7 @@ #include "gnc-ui.h" #include "gnc-warnings.h" #include "guile-util.h" -#include "split-register-copy-ops-internals.h" +#include "split-register-copy-ops.h" #include "numcell.h" #include "pricecell.h" #include "quickfillcell.h" diff --git a/libgnucash/engine/CMakeLists.txt b/libgnucash/engine/CMakeLists.txt index 29a19f082f..19e429b9ce 100644 --- a/libgnucash/engine/CMakeLists.txt +++ b/libgnucash/engine/CMakeLists.txt @@ -273,7 +273,6 @@ set (engine_SCHEME_0 set (engine_SCHEME_1 commodity-table.scm - engine-interface.scm engine-utilities.scm gnc-numeric.scm ) diff --git a/libgnucash/engine/engine-interface.scm b/libgnucash/engine/engine-interface.scm deleted file mode 100644 index 34a1768841..0000000000 --- a/libgnucash/engine/engine-interface.scm +++ /dev/null @@ -1,295 +0,0 @@ -;; engine-interface.scm -- support for working with the GnuCash -;; engine data structures -;; Copyright (C) 2000 Dave Peticolas -;; -;; This program is free software; you can redistribute it and/or -;; modify it under the terms of the GNU General Public License as -;; published by the Free Software Foundation; either version 2 of -;; the License, or (at your option) any later version. -;; -;; This program is distributed in the hope that it will be useful, -;; but WITHOUT ANY WARRANTY; without even the implied warranty of -;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -;; GNU General Public License for more details. -;; -;; You should have received a copy of the GNU General Public License -;; along with this program; if not, contact: -;; -;; Free Software Foundation Voice: +1-617-542-5942 -;; 51 Franklin Street, Fifth Floor Fax: +1-617-542-2652 -;; Boston, MA 02110-1301, USA gnu@gnu.org - -;; This defines a scheme representation of splits. -(define gnc:split-structure - (make-record-type - "gnc:split-structure" - '(split-guid account-guid transaction-guid memo action - reconcile-state reconciled-date amount value))) - -;; constructor -(define gnc:make-split-scm - (record-constructor gnc:split-structure)) - -;; type predicate -(define gnc:split-scm? - (record-predicate gnc:split-structure)) - -;; accessors -(define gnc:split-scm-get-split-guid - (record-accessor gnc:split-structure 'split-guid)) - -(define gnc:split-scm-get-account-guid - (record-accessor gnc:split-structure 'account-guid)) - -(define gnc:split-scm-get-transaction-guid - (record-accessor gnc:split-structure 'transaction-guid)) - -(define gnc:split-scm-get-memo - (record-accessor gnc:split-structure 'memo)) - -(define gnc:split-scm-get-action - (record-accessor gnc:split-structure 'action)) - -(define gnc:split-scm-get-reconcile-state - (record-accessor gnc:split-structure 'reconcile-state)) - -(define gnc:split-scm-get-reconciled-date - (record-accessor gnc:split-structure 'reconciled-date)) - -(define gnc:split-scm-get-amount - (record-accessor gnc:split-structure 'amount)) - -(define gnc:split-scm-get-value - (record-accessor gnc:split-structure 'value)) - -;; modifiers -(define gnc:split-scm-set-split-guid - (record-modifier gnc:split-structure 'split-guid)) - -(define gnc:split-scm-set-account-guid - (record-modifier gnc:split-structure 'account-guid)) - -(define gnc:split-scm-set-transaction-guid - (record-modifier gnc:split-structure 'transaction-guid)) - -(define gnc:split-scm-set-memo - (record-modifier gnc:split-structure 'memo)) - -(define gnc:split-scm-set-action - (record-modifier gnc:split-structure 'action)) - -(define gnc:split-scm-set-reconcile-state - (record-modifier gnc:split-structure 'reconcile-state)) - -(define gnc:split-scm-set-reconciled-date - (record-modifier gnc:split-structure 'reconciled-date)) - -(define gnc:split-scm-set-amount - (record-modifier gnc:split-structure 'amount)) - -(define gnc:split-scm-set-value - (record-modifier gnc:split-structure 'value)) - -;; This function take a C split and returns a representation -;; of it as a split-structure. Assumes the transaction is open -;; for editing. -(define (gnc:split->split-scm split use-cut-semantics?) - (gnc:make-split-scm - (gncSplitGetGUID split) - (gncAccountGetGUID (xaccSplitGetAccount split)) - (gncTransGetGUID (xaccSplitGetParent split)) - (xaccSplitGetMemo split) - (xaccSplitGetAction split) - (xaccSplitGetReconcile split) - (xaccSplitGetDateReconciled split) - (xaccSplitGetAmount split) - (xaccSplitGetValue split))) - -;; Copy a scheme representation of a split onto a C split. -;; If possible, insert the C split into the account of the -;; scheme split. Not all values are copied. The reconcile -;; status and date are not copied. The C split's guid is, -;; of course, unchanged. -(define (gnc:split-scm-onto-split split-scm split book) - (if (null? split) - #f - (begin - (let ((memo (gnc:split-scm-get-memo split-scm)) - (action (gnc:split-scm-get-action split-scm)) - (amount (gnc:split-scm-get-amount split-scm)) - (value (gnc:split-scm-get-value split-scm))) - (if memo (xaccSplitSetMemo split memo)) - (if action (xaccSplitSetAction split action)) - (if amount (xaccSplitSetAmount split amount)) - (if value (xaccSplitSetValue split value))) - (let ((account (xaccAccountLookup - (gnc:split-scm-get-account-guid split-scm) - book))) - (if (not (null? account)) - (begin - (xaccAccountBeginEdit account) - (xaccSplitSetAccount split account) - (xaccAccountCommitEdit account))))))) - -;; Defines a scheme representation of a transaction. -(define gnc:transaction-structure - (make-record-type - "gnc:transaction-structure" - '(transaction-guid currency date-entered date-posted - num description notes association split-scms))) - -;; constructor -(define gnc:make-transaction-scm - (record-constructor gnc:transaction-structure)) - -;; type predicate -(define gnc:transaction-scm? - (record-predicate gnc:transaction-structure)) - -;; accessors -(define gnc:transaction-scm-get-transaction-guid - (record-accessor gnc:transaction-structure 'transaction-guid)) - -(define gnc:transaction-scm-get-currency - (record-accessor gnc:transaction-structure 'currency)) - -(define gnc:transaction-scm-get-date-entered - (record-accessor gnc:transaction-structure 'date-entered)) - -(define gnc:transaction-scm-get-date-posted - (record-accessor gnc:transaction-structure 'date-posted)) - -(define gnc:transaction-scm-get-num - (record-accessor gnc:transaction-structure 'num)) - -(define gnc:transaction-scm-get-description - (record-accessor gnc:transaction-structure 'description)) - -(define gnc:transaction-scm-get-notes - (record-accessor gnc:transaction-structure 'notes)) - -(define gnc:transaction-scm-get-association - (record-accessor gnc:transaction-structure 'association)) - -(define gnc:transaction-scm-get-split-scms - (record-accessor gnc:transaction-structure 'split-scms)) - -(define (gnc:transaction-scm-get-split-scm trans-scm index) - (let ((split-scms (gnc:transaction-scm-get-split-scms trans-scm))) - (cond ((< index 0) #f) - ((not (pair? split-scms)) #f) - ((>= index (length split-scms)) #f) - (else (list-ref split-scms index))))) - -(define (gnc:transaction-scm-get-other-split-scm trans-scm split-scm) - (let ((split-scms (gnc:transaction-scm-get-split-scms trans-scm))) - (cond ((not (= (length split-scms) 2)) #f) - ((eq? split-scm (car split-scms)) (cadr split-scms)) - (else (car split-scms))))) - -;; modifiers -(define gnc:transaction-scm-set-transaction-guid - (record-modifier gnc:transaction-structure 'transaction-guid)) - -(define gnc:transaction-scm-set-currency - (record-modifier gnc:transaction-structure 'currency)) - -(define gnc:transaction-scm-set-date-entered - (record-modifier gnc:transaction-structure 'date-entered)) - -(define gnc:transaction-scm-set-date-posted - (record-modifier gnc:transaction-structure 'date-posted)) - -(define gnc:transaction-scm-set-num - (record-modifier gnc:transaction-structure 'num)) - -(define gnc:transaction-scm-set-description - (record-modifier gnc:transaction-structure 'description)) - -(define gnc:transaction-scm-set-notes - (record-modifier gnc:transaction-structure 'notes)) - -(define gnc:transaction-scm-set-association - (record-modifier gnc:transaction-structure 'association)) - -(define gnc:transaction-scm-set-split-scms - (record-modifier gnc:transaction-structure 'split-scms)) - -(define (gnc:transaction-scm-append-split-scm trans-scm split-scm) - (let ((split-scms (gnc:transaction-scm-get-split-scms trans-scm))) - (gnc:transaction-scm-set-split-scms - trans-scm (append split-scms (list split-scm))))) - -;; This function takes a C transaction and returns -;; a representation of it as a transaction-structure. -(define (gnc:transaction->transaction-scm trans use-cut-semantics?) - (define (trans-splits i) - (let ((split (xaccTransGetSplit trans i))) - (if (null? split) - '() - (cons (gnc:split->split-scm split use-cut-semantics?) - (trans-splits (+ i 1)))))) - (gnc:make-transaction-scm - (gncTransGetGUID trans) - (xaccTransGetCurrency trans) - (xaccTransGetDateEntered trans) - (if use-cut-semantics? - (xaccTransGetDate trans) - #f) - (if use-cut-semantics? - (xaccTransGetNum trans) - #f) - (xaccTransGetDescription trans) - (xaccTransGetNotes trans) - (xaccTransGetAssociation trans) - (trans-splits 0))) - -;; Copy a scheme representation of a transaction onto a C transaction. -;; guid-mapping must be an alist, mapping guids to guids. This list is -;; used to use alternate account guids when creating splits. -(define (gnc:transaction-scm-onto-transaction trans-scm trans guid-mapping - commit? book) - (if (null? trans) - #f - (begin - ;; open the transaction for editing - (if (not (xaccTransIsOpen trans)) - (xaccTransBeginEdit trans)) - - ;; copy in the transaction values - (let ((currency (gnc:transaction-scm-get-currency trans-scm)) - (description (gnc:transaction-scm-get-description trans-scm)) - (num (gnc:transaction-scm-get-num trans-scm)) - (notes (gnc:transaction-scm-get-notes trans-scm)) - (association (gnc:transaction-scm-get-association trans-scm)) - (date-posted (gnc:transaction-scm-get-date-posted trans-scm))) - (if currency (xaccTransSetCurrency trans currency)) - (if description (xaccTransSetDescription trans description)) - (if num (xaccTransSetNum trans num)) - (if notes (xaccTransSetNotes trans notes)) - (if association (xaccTransSetAssociation trans association)) - (if date-posted (xaccTransSetDatePostedSecs trans date-posted))) - - ;; strip off the old splits - (for-each (lambda (split) - (xaccSplitDestroy split)) - (xaccTransGetSplitList trans)) - - ;; and put on the new ones! Please note they go in the *same* - ;; order as in the original transaction. This is important. - (for-each - (lambda (split-scm) - (let* ((new-split (xaccMallocSplit book)) - (old-guid (gnc:split-scm-get-account-guid split-scm)) - (new-guid (assoc-ref guid-mapping old-guid))) - (if (not new-guid) - (set! new-guid old-guid)) - (gnc:split-scm-set-account-guid split-scm new-guid) - (gnc:split-scm-onto-split split-scm new-split book) - (gnc:split-scm-set-account-guid split-scm old-guid) - (xaccSplitSetParent new-split trans))) - (gnc:transaction-scm-get-split-scms trans-scm)) - - ;; close the transaction - (if commit? - (xaccTransCommitEdit trans))))) diff --git a/libgnucash/engine/engine.scm b/libgnucash/engine/engine.scm index 71e39fa964..f9f1a10f92 100644 --- a/libgnucash/engine/engine.scm +++ b/libgnucash/engine/engine.scm @@ -66,56 +66,6 @@ (export account-full-namesplit-scm) -(export gnc:split-scm-onto-split) -(export gnc:transaction-structure) -(export gnc:make-transaction-scm) -(export gnc:transaction-scm?) -(export gnc:transaction-scm-get-transaction-guid) -(export gnc:transaction-scm-get-currency) -(export gnc:transaction-scm-get-date-entered) -(export gnc:transaction-scm-get-date-posted) -(export gnc:transaction-scm-get-num) -(export gnc:transaction-scm-get-description) -(export gnc:transaction-scm-get-notes) -(export gnc:transaction-scm-get-split-scms) -(export gnc:transaction-scm-get-split-scm) -(export gnc:transaction-scm-get-other-split-scm) -(export gnc:transaction-scm-set-transaction-guid) -(export gnc:transaction-scm-set-currency) -(export gnc:transaction-scm-set-date-entered) -(export gnc:transaction-scm-set-date-posted) -(export gnc:transaction-scm-set-num) -(export gnc:transaction-scm-set-description) -(export gnc:transaction-scm-set-notes) -(export gnc:transaction-scm-set-split-scms) -(export gnc:transaction-scm-append-split-scm) -(export gnc:transaction->transaction-scm) -(export trans-splits) -(export gnc:transaction-scm-onto-transaction) - (load-from-path "gnucash/engine/gnc-numeric") (load-from-path "gnucash/engine/commodity-table") -(load-from-path "gnucash/engine/engine-interface") (load-from-path "gnucash/engine/engine-utilities") diff --git a/po/POTFILES.in b/po/POTFILES.in index 4a1ce99363..1c147ff059 100644 --- a/po/POTFILES.in +++ b/po/POTFILES.in @@ -381,7 +381,6 @@ gnucash/register/ledger-core/gncmod-ledger-core.c gnucash/register/ledger-core/split-register.c gnucash/register/ledger-core/split-register-control.c gnucash/register/ledger-core/split-register-copy-ops.c -gnucash/register/ledger-core/split-register-copy-ops-internals.c gnucash/register/ledger-core/split-register-layout.c gnucash/register/ledger-core/split-register-load.c gnucash/register/ledger-core/split-register-model.c From 9b803428ef673099e4522c7e50b0ee8753ff95aa Mon Sep 17 00:00:00 2001 From: Geert Janssens Date: Fri, 6 Dec 2019 17:36:16 +0100 Subject: [PATCH 8/8] split register - add tests for copy operations --- .../register/ledger-core/test/CMakeLists.txt | 26 +- .../ledger-core/test/test-split-register.c | 46 ++ .../test/utest-split-register-copy-ops.c | 621 ++++++++++++++++++ 3 files changed, 692 insertions(+), 1 deletion(-) create mode 100644 gnucash/register/ledger-core/test/test-split-register.c create mode 100644 gnucash/register/ledger-core/test/utest-split-register-copy-ops.c diff --git a/gnucash/register/ledger-core/test/CMakeLists.txt b/gnucash/register/ledger-core/test/CMakeLists.txt index 31dd6b3766..576974cb8d 100644 --- a/gnucash/register/ledger-core/test/CMakeLists.txt +++ b/gnucash/register/ledger-core/test/CMakeLists.txt @@ -6,4 +6,28 @@ gnc_add_test(test-link-module-ledger-core test-link-module.c LEDGER_CORE_TEST_INCLUDE_DIRS LEDGER_CORE_TEST_LIBS ) -set_dist_list(test_ledger_core_DIST CMakeLists.txt test-link-module.c) \ No newline at end of file +set(SPLIT_REG_TEST_SOURCES + test-split-register.c + utest-split-register-copy-ops.c +) + +set(SPLIT_REG_TEST_INCLUDE_DIRS + ${CMAKE_SOURCE_DIR}/libgnucash/engine + ${CMAKE_SOURCE_DIR}/gnucash/register/ledger-core + ${CMAKE_BINARY_DIR}/common # for config.h + ${CMAKE_SOURCE_DIR}/common/test-core # for unittest-support.h + ${GLIB2_INCLUDE_DIRS} +) + +set(SPLIT_REG_TEST_LIBS + gnc-engine + gncmod-ledger-core +) + +gnc_add_test(test-split-register-copy-ops + "${SPLIT_REG_TEST_SOURCES};${CMAKE_SOURCE_DIR}/common/test-core/unittest-support.c" + SPLIT_REG_TEST_INCLUDE_DIRS + SPLIT_REG_TEST_LIBS +) + +set_dist_list(test_ledger_core_DIST CMakeLists.txt test-link-module.c ${SPLIT_REG_TEST_SOURCES}) diff --git a/gnucash/register/ledger-core/test/test-split-register.c b/gnucash/register/ledger-core/test/test-split-register.c new file mode 100644 index 0000000000..1178348185 --- /dev/null +++ b/gnucash/register/ledger-core/test/test-split-register.c @@ -0,0 +1,46 @@ +/******************************************************************** + * test-split-register.c: Main test for split register. * + * Copyright 2019 Geert Janssens * + * * + * This program is free software; you can redistribute it and/or * + * modify it under the terms of the GNU General Public License as * + * published by the Free Software Foundation; either version 2 of * + * the License, or (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License* + * along with this program; if not, contact: * + * * + * Free Software Foundation Voice: +1-617-542-5942 * + * 51 Franklin Street, Fifth Floor Fax: +1-617-542-2652 * + * Boston, MA 02110-1301, USA gnu@gnu.org * + * \********************************************************************/ + + +#include +#include +#include +#include + +extern void test_suite_split_register_copy_ops(); + +int +main (int argc, + char *argv[]) +{ + qof_init(); /* Initialize the GObject system */ + qof_log_init_filename_special("stderr"); /* Init the log system */ + g_test_init ( &argc, &argv, NULL ); /* initialize test program */ + //qof_log_set_level("gnc", G_LOG_LEVEL_DEBUG); + g_test_bug_base("https://bugs.gnucash.org/show_bug.cgi?id="); /* init the bugzilla URL */ + /* Disable the transaction log */ + xaccLogDisable(); + + test_suite_split_register_copy_ops(); + + return g_test_run( ); +} diff --git a/gnucash/register/ledger-core/test/utest-split-register-copy-ops.c b/gnucash/register/ledger-core/test/utest-split-register-copy-ops.c new file mode 100644 index 0000000000..95db38d13d --- /dev/null +++ b/gnucash/register/ledger-core/test/utest-split-register-copy-ops.c @@ -0,0 +1,621 @@ +/******************************************************************** + * utest-split-register-copy-ops.c: GLib g_test test suite for split-register-copy-ops.c. * + * Copyright 2019 Geert Janssens * + * * + * This program is free software; you can redistribute it and/or * + * modify it under the terms of the GNU General Public License as * + * published by the Free Software Foundation; either version 2 of * + * the License, or (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License* + * along with this program; if not, you can retrieve it from * + * https://www.gnu.org/licenses/old-licenses/gpl-2.0.html * + * or contact: * + * * + * Free Software Foundation Voice: +1-617-542-5942 * + * 51 Franklin Street, Fifth Floor Fax: +1-617-542-2652 * + * Boston, MA 02110-1301, USA gnu@gnu.org * + ********************************************************************/ +#include +#include +#include +#include +/* Add specific headers for this class */ +#include "split-register-copy-ops.h" +#include + +static const gchar *suitename = "/register/ledger-core/split-register-copy-ops"; +void test_suite_split_register_copy_ops ( void ); + +typedef struct +{ + gboolean swap_accts; + gboolean docommit; +} SwapCommitPrefs; + +typedef struct +{ + QofBook *book; + Account *acc1; + Account *acc2; + gnc_commodity *curr; + + Transaction *txn; +} Fixture; + +typedef struct +{ + QofBook *book; + Account *acc1; + Account *acc2; + gnc_commodity *curr; + + FloatingTxn ft; + FloatingSplit fs1, fs2; +} FlFixture; + +static void +setup( Fixture *fixture, gconstpointer pData ) +{ + time64 entered = gnc_dmy2time64 (20, 4, 2012); + time64 posted = gnc_dmy2time64 (21, 4, 2012); + + Split *split1 = NULL; + Split *split2 = NULL; + + fixture->book = qof_book_new(); + + split1 = xaccMallocSplit (fixture->book); + split2 = xaccMallocSplit (fixture->book); + fixture->acc1 = xaccMallocAccount(fixture->book); + fixture->acc2 = xaccMallocAccount(fixture->book); + fixture->curr = gnc_commodity_new(fixture->book, "Gnu Rand", "CURRENCY", "GNR", "", 100); + xaccAccountSetCommodity(fixture->acc1, fixture->curr); + xaccAccountSetCommodity(fixture->acc2, fixture->curr); + + fixture->txn = xaccMallocTransaction (fixture->book); + + xaccSplitSetMemo (split1, CACHE_INSERT ("foo")); + xaccSplitSetAction (split1, CACHE_INSERT ("bar")); + xaccSplitSetAmount (split1, gnc_numeric_create (3200, 100)); + xaccSplitSetValue (split1, gnc_numeric_create (3200, 100)); + xaccSplitSetAccount (split1, fixture->acc1); + + xaccSplitSetAmount (split2, gnc_numeric_create (-3200, 100)); + xaccSplitSetValue (split2, gnc_numeric_create (-3200, 100)); + xaccSplitSetAccount (split2, fixture->acc2); + + xaccTransBeginEdit (fixture->txn); + { + xaccTransSetNum (fixture->txn, CACHE_INSERT ("123")); + xaccTransSetDescription (fixture->txn, CACHE_INSERT ("Waldo Pepper")); + xaccTransSetDatePostedSecs (fixture->txn, posted); + xaccTransSetDateEnteredSecs (fixture->txn, entered); + xaccTransSetCurrency (fixture->txn, fixture->curr); + xaccSplitSetParent (split1, fixture->txn); + xaccSplitSetParent (split2, fixture->txn); + xaccTransSetNotes (fixture->txn, "Salt pork sausage"); + } + xaccTransCommitEdit (fixture->txn); + xaccAccountSortSplits(fixture->acc1, FALSE); + xaccAccountSortSplits(fixture->acc2, FALSE); + xaccAccountRecomputeBalance(fixture->acc1); + xaccAccountRecomputeBalance(fixture->acc2); +} + +static void +teardown( Fixture *fixture, gconstpointer pData ) +{ + xaccTransDestroy (fixture->txn); + xaccAccountBeginEdit(fixture->acc1); + xaccAccountDestroy(fixture->acc1); + xaccAccountBeginEdit(fixture->acc2); + xaccAccountDestroy(fixture->acc2); + gnc_commodity_destroy(fixture->curr); + qof_book_destroy( fixture->book ); +}; + +static void +flsetup( FlFixture *fixture, gconstpointer pData ) +{ + time64 entered = gnc_dmy2time64 (20, 4, 2012); + time64 posted = gnc_dmy2time64 (21, 4, 2012); + time64 reconciled = gnc_dmy2time64 (22, 4, 2012); + + fixture->book = qof_book_new(); + fixture->acc1 = xaccMallocAccount(fixture->book); + fixture->acc2 = xaccMallocAccount(fixture->book); + fixture->curr = gnc_commodity_new(fixture->book, "Gnu Rand", "CURRENCY", "GNR", "", 100); + xaccAccountSetCommodity(fixture->acc1, fixture->curr); + xaccAccountSetCommodity(fixture->acc2, fixture->curr); + + fixture->ft.m_txn = NULL; + fixture->ft.m_currency = fixture->curr; + fixture->ft.m_date_entered = entered; + fixture->ft.m_date_posted = posted; + fixture->ft.m_num = CACHE_INSERT ("FtNum"); + fixture->ft.m_description = CACHE_INSERT ("FtDescription"); + fixture->ft.m_notes = CACHE_INSERT ("FtNotes"); + fixture->ft.m_association = CACHE_INSERT ("FtAssociation"); + + fixture->fs1.m_split = NULL; + fixture->fs1.m_account = fixture->acc1; + fixture->fs1.m_transaction = NULL; + fixture->fs1.m_memo = CACHE_INSERT ("Fs1Memo"); + fixture->fs1.m_action = CACHE_INSERT ("Fs1Action"); + fixture->fs1.m_reconcile_date = INT64_MAX; + fixture->fs1.m_reconcile_state = NREC; + fixture->fs1.m_value = gnc_numeric_create (4500, 100); + fixture->fs1.m_amount = gnc_numeric_create (4500, 100); + + fixture->fs2.m_split = NULL; + fixture->fs2.m_account = fixture->acc2; + fixture->fs2.m_transaction = NULL; + fixture->fs2.m_memo = CACHE_INSERT ("Fs2Memo"); + fixture->fs2.m_action = CACHE_INSERT ("Fs2Action"); + fixture->fs2.m_reconcile_date = reconciled; + fixture->fs2.m_reconcile_state = YREC; + fixture->fs2.m_value = gnc_numeric_create (-4500, 100); + fixture->fs2.m_amount = gnc_numeric_create (-4500, 100); + + fixture->ft.m_splits = NULL; + fixture->ft.m_splits = g_list_append (NULL, &fixture->fs1); + fixture->ft.m_splits = g_list_append (fixture->ft.m_splits, &fixture->fs2); +} + +static void +flteardown( FlFixture *fixture, gconstpointer pData ) +{ + g_list_free (fixture->ft.m_splits); + xaccAccountBeginEdit(fixture->acc1); + xaccAccountDestroy(fixture->acc1); + xaccAccountBeginEdit(fixture->acc2); + xaccAccountDestroy(fixture->acc2); + gnc_commodity_destroy(fixture->curr); + qof_book_destroy( fixture->book ); +}; + +// Not Used +/* gnc_float_split_get_reconcile_state - trivial getter, skipping +char gnc_float_split_get_reconcile_state (const FloatingSplit *fs)// Local: 0:0:0 +*/ +// Not Used +/* gnc_float_split_get_reconcile_date - trivial getter, skipping +time64 gnc_float_split_get_reconcile_date (const FloatingSplit *fs)// Local: 0:0:0 +*/ +/* gnc_float_split_get_amount - trivial getter, skipping +gnc_numeric gnc_float_split_get_amount (const FloatingSplit *fs)// C: 1 Local: 0:0:0 +*/ +/* static void +test_gnc_float_split_get_amount (Fixture *fixture, gconstpointer pData) +{ +}*/ +/* gnc_float_split_get_value - trivial getter, skipping +gnc_numeric gnc_float_split_get_value (const FloatingSplit *fs)// C: 1 Local: 0:0:0 +*/ +/* static void +test_gnc_float_split_get_value (Fixture *fixture, gconstpointer pData) +{ +}*/ +// Not Used +/* gnc_float_split_set_split - trivial getter, skipping +void gnc_float_split_set_split(FloatingSplit *fs, Split *split)// Local: 0:0:0 +*/ +/* gnc_float_split_set_account - trivial setter, skipping +void gnc_float_split_set_account (FloatingSplit *fs, Account *account) // C: 2 in 1 Local: 0:0:0 +*/ +/* static void +test_gnc_float_split_set_account (Fixture *fixture, gconstpointer pData) +{ +}*/ +// Not Used +/* gnc_float_split_set_transaction - trivial setter, skipping +void gnc_float_split_set_transaction (FloatingSplit *fs, Transaction *transaction) // Local: 0:0:0 +*/ +/* gnc_float_split_set_memo +void gnc_float_split_set_memo (FloatingSplit *fs, const char *memo)// C: 1 Local: 0:0:0 +*/ +/* static void +test_gnc_float_split_set_memo (Fixture *fixture, gconstpointer pData) +{ +}*/ +/* gnc_float_split_set_action - trivial setter, skipping +void gnc_float_split_set_action (FloatingSplit *fs, const char *action)// C: 1 Local: 0:0:0 +*/ +/* static void +test_gnc_float_split_set_action (Fixture *fixture, gconstpointer pData) +{ +}*/ +/* gnc_float_split_set_reconcile_state - trivial setter, skipping +void gnc_float_split_set_reconcile_state (FloatingSplit *fs, char reconcile_state)// C: 1 Local: 0:0:0 +*/ +/* static void +test_gnc_float_split_set_reconcile_state (Fixture *fixture, gconstpointer pData) +{ +}*/ +// Not Used +/* gnc_float_split_set_reconcile_date - trivial setter, skipping +void gnc_float_split_set_reconcile_date (FloatingSplit *fs, time64 reconcile_date)// Local: 0:0:0 +*/ +/* gnc_float_split_set_amount - trivial setter, skipping +void gnc_float_split_set_amount (FloatingSplit *fs, const gnc_numeric amount)// C: 2 in 1 Local: 0:0:0 +*/ +/* static void +test_gnc_float_split_set_amount (Fixture *fixture, gconstpointer pData) +{ +}*/ +/* gnc_float_split_set_value - trivial setter, skipping +void gnc_float_split_set_value (FloatingSplit *fs, const gnc_numeric value)// C: 2 in 1 Local: 0:0:0 +*/ +/* static void +test_gnc_float_split_set_value (Fixture *fixture, gconstpointer pData) +{ +}*/ +/* gnc_split_to_float_split +FloatingSplit *gnc_split_to_float_split (Split *split)// C: 3 in 1 Local: 1:0:0 +*/ +static void +test_gnc_split_to_float_split (Fixture *fixture, gconstpointer pData) +{ + FloatingSplit *fs = NULL; + Split *s = xaccTransFindSplitByAccount (fixture->txn, fixture->acc1); + + g_assert_nonnull (s); + + fs = gnc_split_to_float_split (s); + g_assert_true (fs->m_split == s); + g_assert_true (fs->m_account == xaccSplitGetAccount (s)); + g_assert_true (fs->m_transaction == xaccSplitGetParent (s)); + g_assert_cmpstr (fs->m_memo, ==, xaccSplitGetMemo (s)); + g_assert_cmpstr (fs->m_action, ==, xaccSplitGetAction (s)); + g_assert_true (gnc_numeric_equal(fs->m_value, xaccSplitGetValue (s))); + g_assert_true (gnc_numeric_equal(fs->m_amount, xaccSplitGetAmount (s))); + + g_free (fs); +} +/* gnc_float_split_to_split +void gnc_float_split_to_split (const FloatingSplit *fs, Split *split)// C: 2 in 1 Local: 1:0:0 +*/ +static void +test_gnc_float_split_to_split (Fixture *fixture, gconstpointer pData) +{ + gnc_numeric amt = gnc_numeric_create (500, 100); + FloatingSplit fs = { NULL, fixture->acc1, NULL, "Memo1", "Action1", INT64_MAX, 'u', amt, amt }; + Split *s = xaccMallocSplit(fixture->book); + Transaction *txn = xaccMallocTransaction (fixture->book); + + gnc_float_split_to_split (&fs, s); + g_assert_true (fixture->acc1 == xaccSplitGetAccount (s)); + g_assert_cmpstr ("Memo1", ==, xaccSplitGetMemo (s)); + g_assert_cmpstr ("Action1", ==, xaccSplitGetAction (s)); + g_assert_true (gnc_numeric_equal(amt, xaccSplitGetValue (s))); + g_assert_true (gnc_numeric_equal(amt, xaccSplitGetAmount (s))); + + + xaccTransBeginEdit (txn); + xaccTransSetCurrency (txn, fixture->curr); + xaccSplitSetParent (s, txn); + xaccTransCommitEdit (txn); + xaccTransDestroy (txn); +} +// Not Used +/* gnc_float_txn_get_date_entered - trivial getter, skipping +time64 gnc_float_txn_get_date_entered (const FloatingTxn *ft)// Local: 0:0:0 +*/ +// Not Used +/* gnc_float_txn_get_date_posted - trivial getter, skipping +time64 gnc_float_txn_get_date_posted (const FloatingTxn *ft)// Local: 0:0:0 +*/ +// Not Used +/* gnc_float_txn_set_txn - trivial setter, skipping +void gnc_float_txn_set_txn (FloatingTxn *ft, Transaction *txn)// Local: 0:0:0 +*/ +// Not Used +/* gnc_float_txn_set_currency - trivial setter, skipping +void gnc_float_txn_set_currency (FloatingTxn *ft, gnc_commodity *currency)// Local: 0:0:0 +*/ +// Not Used +/* gnc_float_txn_set_date_entered - trivial setter, skipping +void gnc_float_txn_set_date_entered (FloatingTxn *ft, time64 date_entered)// Local: 0:0:0 +*/ +// Not Used +/* gnc_float_txn_set_date_posted - trivial setter, skipping +void gnc_float_txn_set_date_posted (FloatingTxn *ft, time64 date_posted)// Local: 0:0:0 +*/ +// Not Used +/* gnc_float_txn_set_num - trivial setter, skipping +void gnc_float_txn_set_num (FloatingTxn *ft, const char *num)// Local: 0:0:0 +*/ +// Not Used +/* gnc_float_txn_set_description - trivial setter, skipping +void gnc_float_txn_set_description (FloatingTxn *ft, const char *description)// Local: 0:0:0 +*/ +// Not Used +/* gnc_float_txn_set_notes - trivial setter, skipping +void gnc_float_txn_set_notes (FloatingTxn *ft, const char *notes)// Local: 0:0:0 +*/ +// Not Used +/* gnc_float_txn_set_association - trivial setter, skipping +void gnc_float_txn_set_association (FloatingTxn *ft, const char *association)// Local: 0:0:0 +*/ +// Not Used +/* gnc_float_txn_set_splits - trivial setter, skipping +void gnc_float_txn_set_splits (FloatingTxn *ft, SplitList *splits)// Local: 0:0:0 +*/ +/* gnc_float_txn_append_float_split +void gnc_float_txn_append_float_split (FloatingTxn *ft, FloatingSplit *fs)// C: 1 Local: 0:0:0 +*/ +/* static void +test_gnc_float_txn_append_float_split (Fixture *fixture, gconstpointer pData) +{ +}*/ +/* gnc_txn_to_float_txn +FloatingTxn *gnc_txn_to_float_txn (Transaction *txn, gboolean use_cut_semantics)// C: 3 in 1 Local: 0:0:0 +*/ +static void +test_gnc_txn_to_float_txn (Fixture *fixture, gconstpointer pData) +{ + FloatingTxn *ft = NULL; + SplitList *sl = xaccTransGetSplitList(fixture->txn), *siter; + SplitList *fsl, *fsiter; + FloatingSplit *fs; + Split *s; + + ft = gnc_txn_to_float_txn (fixture->txn, FALSE); + + /* Check transaction fields */ + g_assert_true (ft->m_txn == fixture->txn); + g_assert_true (ft->m_currency == xaccTransGetCurrency (fixture->txn)); + g_assert_cmpint (ft->m_date_entered, ==, xaccTransGetDateEntered (fixture->txn)); + g_assert_cmpint (ft->m_date_posted, ==, 0); + g_assert_null (ft->m_num); + g_assert_cmpstr (ft->m_description, ==, xaccTransGetDescription (fixture->txn)); + g_assert_cmpstr (ft->m_notes, ==, xaccTransGetNotes (fixture->txn)); + g_assert_cmpstr (ft->m_association, ==, xaccTransGetAssociation (fixture->txn)); + + /* Check split fields of first split */ + siter = sl; + s = siter->data; + + fsiter = ft->m_splits; + fs = fsiter->data; + + g_assert_nonnull (fs); + g_assert_true (fs->m_split == s); + g_assert_true (fs->m_account == xaccSplitGetAccount (s)); + g_assert_true (fs->m_transaction == xaccSplitGetParent (s)); + g_assert_cmpstr (fs->m_memo, ==, xaccSplitGetMemo (s)); + g_assert_cmpstr (fs->m_action, ==, xaccSplitGetAction (s)); + g_assert_true (gnc_numeric_equal(fs->m_value, xaccSplitGetValue (s))); + g_assert_true (gnc_numeric_equal(fs->m_amount, xaccSplitGetAmount (s))); + + /* Check split fields of second split */ + siter = siter->next; + s = siter->data; + + fsiter = fsiter->next; + fs = fsiter->data; + + g_assert_nonnull (fs); + g_assert_true (fs->m_split == s); + g_assert_true (fs->m_account == xaccSplitGetAccount (s)); + g_assert_true (fs->m_transaction == xaccSplitGetParent (s)); + g_assert_cmpstr (fs->m_memo, ==, xaccSplitGetMemo (s)); + g_assert_cmpstr (fs->m_action, ==, xaccSplitGetAction (s)); + g_assert_true (gnc_numeric_equal(fs->m_value, xaccSplitGetValue (s))); + g_assert_true (gnc_numeric_equal(fs->m_amount, xaccSplitGetAmount (s))); + + g_assert_null (fsiter->next); + + g_list_free_full(ft->m_splits, g_free); + ft->m_splits = NULL; + g_free (ft); +} +static void +test_gnc_txn_to_float_txn_cut_semantics (Fixture *fixture, gconstpointer pData) +{ + FloatingTxn *ft = NULL; + SplitList *sl = xaccTransGetSplitList(fixture->txn), *siter; + SplitList *fsl, *fsiter; + FloatingSplit *fs; + Split *s; + + ft = gnc_txn_to_float_txn (fixture->txn, TRUE); + + /* Check transaction fields */ + g_assert_true (ft->m_txn == fixture->txn); + g_assert_true (ft->m_currency == xaccTransGetCurrency (fixture->txn)); + g_assert_cmpint (ft->m_date_entered, ==, xaccTransGetDateEntered (fixture->txn)); + g_assert_cmpint (ft->m_date_posted, ==, xaccTransGetDate (fixture->txn)); + g_assert_cmpstr (ft->m_num, ==, xaccTransGetNum (fixture->txn)); + g_assert_cmpstr (ft->m_description, ==, xaccTransGetDescription (fixture->txn)); + g_assert_cmpstr (ft->m_notes, ==, xaccTransGetNotes (fixture->txn)); + g_assert_cmpstr (ft->m_association, ==, xaccTransGetAssociation (fixture->txn)); + + /* Check split fields of first split */ + siter = sl; + s = siter->data; + + fsiter = ft->m_splits; + fs = fsiter->data; + + g_assert_nonnull (fs); + g_assert_true (fs->m_split == s); + g_assert_true (fs->m_account == xaccSplitGetAccount (s)); + g_assert_true (fs->m_transaction == xaccSplitGetParent (s)); + g_assert_cmpstr (fs->m_memo, ==, xaccSplitGetMemo (s)); + g_assert_cmpstr (fs->m_action, ==, xaccSplitGetAction (s)); + g_assert_true (gnc_numeric_equal(fs->m_value, xaccSplitGetValue (s))); + g_assert_true (gnc_numeric_equal(fs->m_amount, xaccSplitGetAmount (s))); + + /* Check split fields of second split */ + siter = siter->next; + s = siter->data; + + fsiter = fsiter->next; + fs = fsiter->data; + + g_assert_nonnull (fs); + g_assert_true (fs->m_split == s); + g_assert_true (fs->m_account == xaccSplitGetAccount (s)); + g_assert_true (fs->m_transaction == xaccSplitGetParent (s)); + g_assert_cmpstr (fs->m_memo, ==, xaccSplitGetMemo (s)); + g_assert_cmpstr (fs->m_action, ==, xaccSplitGetAction (s)); + g_assert_true (gnc_numeric_equal(fs->m_value, xaccSplitGetValue (s))); + g_assert_true (gnc_numeric_equal(fs->m_amount, xaccSplitGetAmount (s))); + + g_assert_null (fsiter->next); + + g_list_free_full(ft->m_splits, g_free); + ft->m_splits = NULL; + g_free (ft); +} + + +/* gnc_float_txn_get_float_split +FloatingSplit *gnc_float_txn_get_float_split (const FloatingTxn *ft, guint index)// C: 1 in 1 Local: 0:0:0 +*/ +static void +test_gnc_float_txn_get_float_split (FlFixture *fixture, gconstpointer pData) +{ + FloatingSplit *fs = gnc_float_txn_get_float_split(&fixture->ft, 0); + + g_assert_nonnull (fs); + g_assert_true (fs->m_account == fixture->acc1); + g_assert_cmpstr (fs->m_memo, ==, "Fs1Memo"); + g_assert_cmpstr (fs->m_action, ==, "Fs1Action"); + g_assert_true (gnc_numeric_equal(fs->m_value, gnc_numeric_create (4500, 100))); + g_assert_true (gnc_numeric_equal(fs->m_amount, gnc_numeric_create (4500, 100))); + + fs = gnc_float_txn_get_float_split(&fixture->ft, 1); + + g_assert_nonnull (fs); + g_assert_true (fs->m_account == fixture->acc2); + g_assert_cmpstr (fs->m_memo, ==, "Fs2Memo"); + g_assert_cmpstr (fs->m_action, ==, "Fs2Action"); + g_assert_true (gnc_numeric_equal(fs->m_value, gnc_numeric_create (-4500, 100))); + g_assert_true (gnc_numeric_equal(fs->m_amount, gnc_numeric_create (-4500, 100))); +} + +/* gnc_float_txn_get_other_float_split +FloatingSplit *gnc_float_txn_get_other_float_split (const FloatingTxn *ft, FloatingSplit *fs)// C: 2 in 1 Local: 0:0:0 +*/ +static void +test_gnc_float_txn_get_other_float_split (FlFixture *fixture, gconstpointer pData) +{ + FloatingSplit *first = gnc_float_txn_get_float_split(&fixture->ft, 0); + FloatingSplit *other = gnc_float_txn_get_other_float_split(&fixture->ft, first); + + g_assert_nonnull (other); + g_assert_true (other->m_account == fixture->acc2); + g_assert_cmpstr (other->m_memo, ==, "Fs2Memo"); + g_assert_cmpstr (other->m_action, ==, "Fs2Action"); + g_assert_true (gnc_numeric_equal(other->m_value, gnc_numeric_create (-4500, 100))); + g_assert_true (gnc_numeric_equal(other->m_amount, gnc_numeric_create (-4500, 100))); + + first = gnc_float_txn_get_float_split(&fixture->ft, 1); + other = gnc_float_txn_get_other_float_split(&fixture->ft, first); + + g_assert_nonnull (other); + g_assert_true (other->m_account == fixture->acc1); + g_assert_cmpstr (other->m_memo, ==, "Fs1Memo"); + g_assert_cmpstr (other->m_action, ==, "Fs1Action"); + g_assert_true (gnc_numeric_equal(other->m_value, gnc_numeric_create (4500, 100))); + g_assert_true (gnc_numeric_equal(other->m_amount, gnc_numeric_create (4500, 100))); +} +/* gnc_float_txn_to_txn_swap_accounts +void gnc_float_txn_to_txn_swap_accounts (const FloatingTxn *ft, Transaction *txn, Account *acct1, Account *acct2, gboolean do_commit)// C: 1 Local: 1:0:0 +*/ +static void +test_gnc_float_txn_to_txn_swap_accounts (FlFixture *fixture, gconstpointer pData) +{ + SwapCommitPrefs *prefs = (SwapCommitPrefs*)pData; + Transaction *txn = xaccMallocTransaction (fixture->book); + Account *sw_acct1 = NULL, *sw_acct2 = NULL; + Account *exp_acct1 = fixture->acc1, *exp_acct2 = fixture->acc2; + SplitList *siter; + Split *s; + gnc_numeric amt; + + if (prefs->swap_accts) + { + sw_acct1 = fixture->acc1; + sw_acct2 = fixture->acc2; + exp_acct1 = fixture->acc2; + exp_acct2 = fixture->acc1; + } + + gnc_float_txn_to_txn_swap_accounts (&fixture->ft, txn, sw_acct1, sw_acct2, prefs->docommit); + + /* First compare transaction values */ + g_assert_true (fixture->ft.m_currency == xaccTransGetCurrency (txn)); + g_assert_cmpstr (fixture->ft.m_description, ==, "FtDescription"); + g_assert_cmpstr (fixture->ft.m_num, ==, "FtNum"); + g_assert_cmpstr (fixture->ft.m_notes, ==, "FtNotes"); + g_assert_cmpstr (fixture->ft.m_association, ==, "FtAssociation"); + g_assert_cmpint (fixture->ft.m_date_posted, ==, xaccTransGetDate (txn)); + + /* Next compare values for first split */ + siter = xaccTransGetSplitList (txn); + g_assert_nonnull (siter); + + s = siter->data; + g_assert_nonnull (s); + + g_assert_true (exp_acct1 == xaccSplitGetAccount (s)); + g_assert_cmpstr (fixture->fs1.m_memo, ==, xaccSplitGetMemo (s)); + g_assert_cmpstr (fixture->fs1.m_action, ==, xaccSplitGetAction (s)); + g_assert_true (gnc_numeric_equal(fixture->fs1.m_value, xaccSplitGetValue (s))); + g_assert_true (gnc_numeric_equal(fixture->fs1.m_value, xaccSplitGetAmount (s))); + + /* Next compare values for second split */ + siter = siter->next; + g_assert_nonnull (siter); + + s = siter->data; + g_assert_nonnull (s); + + g_assert_true (exp_acct2 == xaccSplitGetAccount (s)); + g_assert_cmpstr (fixture->fs2.m_memo, ==, xaccSplitGetMemo (s)); + g_assert_cmpstr (fixture->fs2.m_action, ==, xaccSplitGetAction (s)); + g_assert_true (gnc_numeric_equal(fixture->fs2.m_value, xaccSplitGetValue (s))); + g_assert_true (gnc_numeric_equal(fixture->fs2.m_value, xaccSplitGetAmount (s))); + + /* Test there are only two splits */ + siter = siter->next; + g_assert_null (siter); + + /* Verify whether transaction is still open or not based on input value */ + g_assert_true (xaccTransIsOpen (txn) != prefs->docommit); + + xaccTransDestroy (txn); +} + + +void +test_suite_split_register_copy_ops (void) +{ + SwapCommitPrefs prefs; + GNC_TEST_ADD (suitename, "gnc split to float split", Fixture, NULL, setup, test_gnc_split_to_float_split, teardown); + GNC_TEST_ADD (suitename, "gnc float split to split", Fixture, NULL, setup, test_gnc_float_split_to_split, teardown); + GNC_TEST_ADD (suitename, "gnc float txn to float txn", Fixture, NULL, setup, test_gnc_txn_to_float_txn, teardown); + GNC_TEST_ADD (suitename, "gnc float txn to float txn cut semantics", Fixture, NULL, setup, test_gnc_txn_to_float_txn, teardown); + GNC_TEST_ADD (suitename, "gnc float txn get float split", FlFixture, NULL, flsetup, test_gnc_float_txn_get_float_split, flteardown); + GNC_TEST_ADD (suitename, "gnc float txn get other float split", FlFixture, NULL, flsetup, test_gnc_float_txn_get_other_float_split, flteardown); + + prefs.swap_accts = FALSE; + prefs.docommit = FALSE; + GNC_TEST_ADD (suitename, "gnc float txn to txn noswap nocommit", FlFixture, &prefs, flsetup, test_gnc_float_txn_to_txn_swap_accounts, flteardown); + prefs.docommit = TRUE; + GNC_TEST_ADD (suitename, "gnc float txn to txn noswap commit", FlFixture, &prefs, flsetup, test_gnc_float_txn_to_txn_swap_accounts, flteardown); + prefs.swap_accts = TRUE; + GNC_TEST_ADD (suitename, "gnc float txn to txn swap commit", FlFixture, &prefs, flsetup, test_gnc_float_txn_to_txn_swap_accounts, flteardown); + prefs.docommit = FALSE; + GNC_TEST_ADD (suitename, "gnc float txn to txn swap nocommit", FlFixture, &prefs, flsetup, test_gnc_float_txn_to_txn_swap_accounts, flteardown); + +}