26#define __USE_MINGW_ANSI_STDIO 1
30#include <glib/gi18n.h>
37#if defined(G_OS_WIN32) && !defined(_MSC_VER)
45#include <unicode/uchar.h>
46#include <unicode/utf8.h>
47#include <unicode/listformatter.h>
56#include "gnc-session.h"
57#include "engine-helpers.h"
58#include "gnc-locale-utils.h"
60#define GNC_PREF_CURRENCY_CHOICE_LOCALE "currency-choice-locale"
61#define GNC_PREF_CURRENCY_CHOICE_OTHER "currency-choice-other"
62#define GNC_PREF_CURRENCY_OTHER "currency-other"
63#define GNC_PREF_REVERSED_ACCTS_NONE "reversed-accounts-none"
64#define GNC_PREF_REVERSED_ACCTS_CREDIT "reversed-accounts-credit"
65#define GNC_PREF_REVERSED_ACCTS_INC_EXP "reversed-accounts-incomeexpense"
66#define GNC_PREF_PRICES_FORCE_DECIMAL "force-price-decimal"
68using UniStr = icu::UnicodeString;
70static QofLogModule log_module = GNC_MOD_GUI;
72static bool auto_decimal_enabled =
false;
73static int auto_decimal_places = 2;
75static bool reverse_balance_inited =
false;
81static char* user_default_currency =
nullptr;
82static char* user_report_currency =
nullptr;
83constexpr int maximum_decimals = 15;
84constexpr int64_t pow_10[] = {1, 10, 100, 1000, 10000, 100000, 1000000,
85 10000000, 100000000, 1000000000, 10000000000,
86 100000000000, 1000000000000, 10000000000000,
87 100000000000000, 1000000000000000};
90gnc_normalize_account_separator (
const gchar* separator)
92 char* new_sep=
nullptr;
94 if (!separator || !*separator || g_strcmp0(separator,
"colon") == 0)
95 new_sep = g_strdup (
":");
96 else if (g_strcmp0(separator,
"slash") == 0)
97 new_sep = g_strdup (
"/");
98 else if (g_strcmp0(separator,
"backslash") == 0)
99 new_sep = g_strdup (
"\\");
100 else if (g_strcmp0(separator,
"dash") == 0)
101 new_sep = g_strdup (
"-");
102 else if (g_strcmp0(separator,
"period") == 0)
103 new_sep = g_strdup (
".");
105 new_sep = g_strdup (separator);
116gnc_configure_account_separator (
void)
119 auto separator = gnc_normalize_account_separator (
string);
121 gnc_set_account_separator(separator);
129gnc_configure_reverse_balance (
void)
132 reverse_type[i] =
false;
139 else if (
gnc_prefs_get_bool (GNC_PREFS_GROUP_GENERAL, GNC_PREF_REVERSED_ACCTS_CREDIT))
148 PWARN(
"no reversed account preference set, using none");
153gnc_reverse_balance_init (
void)
155 gnc_configure_reverse_balance ();
156 reverse_balance_inited = TRUE;
160gnc_reverse_balance (
const Account *account)
162 if (account ==
nullptr)
169 if (!reverse_balance_inited)
170 gnc_reverse_balance_init ();
172 return reverse_type[type];
175gboolean gnc_using_equity_type_opening_balance_account (
QofBook* book)
177 return gnc_features_check_used (book, GNC_FEATURE_EQUITY_TYPE_OPENING_BALANCE);
180void gnc_set_use_equity_type_opening_balance_account (
QofBook* book)
186gnc_get_default_directory (
const char* section)
193 dir = g_strdup (g_get_user_data_dir ());
195 dir = g_strdup (g_get_home_dir ());
202gnc_set_default_directory (
const char* section,
const char* directory)
208gnc_get_current_book (
void)
222gnc_is_new_book (
void)
224 return (!gnc_current_session_exist() ||
228#define OPTION_TAXUS_NAME "tax_US/name"
229#define OPTION_TAXUS_TYPE "tax_US/type"
230#define OLD_OPTION_TAXUS_NAME "book/tax_US/name"
231#define OLD_OPTION_TAXUS_TYPE "book/tax_US/type"
234gnc_set_current_book_tax_name_type (gboolean name_changed,
const char* tax_name,
235 gboolean type_changed,
const char* tax_type)
241 auto book = gnc_get_current_book();
242 if ((g_strcmp0 (tax_name,
"") == 0) ||
243 (tax_name ==
nullptr))
245 if ((g_strcmp0 (tax_type,
"Other") == 0) ||
246 (g_strcmp0 (tax_type,
"") == 0) ||
247 (tax_type ==
nullptr))
249 qof_book_set_string_option(book, OPTION_TAXUS_NAME,
nullptr);
250 qof_book_set_string_option(book, OPTION_TAXUS_TYPE,
nullptr);
251 qof_book_option_frame_delete(book,
"tax_US");
255 qof_book_set_string_option(book, OPTION_TAXUS_NAME,
nullptr);
256 qof_book_set_string_option(book, OPTION_TAXUS_TYPE, tax_type);
261 if ((g_strcmp0 (tax_type,
"Other") == 0) ||
262 (g_strcmp0 (tax_type,
"") == 0) ||
263 (tax_type ==
nullptr))
265 qof_book_set_string_option(book, OPTION_TAXUS_TYPE,
nullptr);
266 qof_book_set_string_option(book, OPTION_TAXUS_NAME, tax_name);
270 qof_book_set_string_option(book, OPTION_TAXUS_NAME, tax_name);
271 qof_book_set_string_option(book, OPTION_TAXUS_TYPE, tax_type);
277 auto book = gnc_get_current_book();
278 if ((g_strcmp0 (tax_name,
"") == 0) ||
279 (tax_name ==
nullptr))
281 if ((g_strcmp0 (tax_type,
"Other") == 0) ||
282 (g_strcmp0 (tax_type,
"") == 0) ||
283 (tax_type ==
nullptr))
285 qof_book_set_string_option(book, OPTION_TAXUS_NAME,
nullptr);
286 qof_book_option_frame_delete(book,
"tax_US");
290 qof_book_set_string_option(book, OPTION_TAXUS_NAME,
nullptr);
295 qof_book_set_string_option(book, OPTION_TAXUS_NAME, tax_name);
303 auto book = gnc_get_current_book();
304 if ((g_strcmp0 (tax_type,
"Other") == 0) ||
305 (g_strcmp0 (tax_type,
"") == 0) ||
306 (tax_type ==
nullptr))
308 if ((g_strcmp0 (tax_name,
"") == 0) ||
309 (tax_name ==
nullptr))
311 qof_book_set_string_option(book, OPTION_TAXUS_TYPE,
nullptr);
312 qof_book_option_frame_delete(book,
"tax_US");
316 qof_book_set_string_option(book, OPTION_TAXUS_TYPE,
nullptr);
321 qof_book_set_string_option(book, OPTION_TAXUS_TYPE, tax_type);
328gnc_get_current_book_tax_name (
void)
330 auto book = gnc_get_current_book();
331 auto tax_name = qof_book_get_string_option(book, OPTION_TAXUS_NAME);
338 const char* old_option_taxus_name =
339 qof_book_get_string_option(book, OLD_OPTION_TAXUS_NAME);
340 if (old_option_taxus_name)
342 char* taxus_name = g_strdup(old_option_taxus_name);
343 const char* old_option_taxus_type =
344 qof_book_get_string_option(book, OLD_OPTION_TAXUS_TYPE);
345 if (old_option_taxus_type)
347 char* taxus_type = g_strdup(old_option_taxus_type);
348 qof_book_set_string_option(book, OPTION_TAXUS_NAME, taxus_name);
349 qof_book_set_string_option(book, OLD_OPTION_TAXUS_NAME,
nullptr);
350 qof_book_set_string_option(book, OPTION_TAXUS_TYPE, taxus_type);
351 qof_book_set_string_option(book, OLD_OPTION_TAXUS_TYPE,
nullptr);
352 qof_book_option_frame_delete(book,
"book/tax_US");
353 qof_book_option_frame_delete(book,
"book");
358 qof_book_set_string_option(book, OPTION_TAXUS_NAME, taxus_name);
359 qof_book_set_string_option(book, OLD_OPTION_TAXUS_NAME,
nullptr);
360 qof_book_option_frame_delete(book,
"book/tax_US");
361 qof_book_option_frame_delete(book,
"book");
364 return qof_book_get_string_option(book, OPTION_TAXUS_NAME);
371gnc_get_current_book_tax_type (
void)
373 auto book = gnc_get_current_book();
375 qof_book_get_string_option(book, OPTION_TAXUS_TYPE);
382 auto old_option_taxus_type =
383 qof_book_get_string_option(book, OLD_OPTION_TAXUS_TYPE);
384 if (old_option_taxus_type)
386 auto taxus_type = g_strdup(old_option_taxus_type);
387 auto old_option_taxus_name =
388 qof_book_get_string_option(book, OLD_OPTION_TAXUS_NAME);
389 if (old_option_taxus_name)
391 auto taxus_name = g_strdup(old_option_taxus_name);
392 qof_book_set_string_option(book, OPTION_TAXUS_NAME, taxus_name);
393 qof_book_set_string_option(book, OLD_OPTION_TAXUS_NAME,
nullptr);
394 qof_book_set_string_option(book, OPTION_TAXUS_TYPE, taxus_type);
395 qof_book_set_string_option(book, OLD_OPTION_TAXUS_TYPE,
nullptr);
396 qof_book_option_frame_delete(book,
"book/tax_US");
397 qof_book_option_frame_delete(book,
"book");
402 qof_book_set_string_option(book, OPTION_TAXUS_TYPE, taxus_type);
403 qof_book_set_string_option(book, OLD_OPTION_TAXUS_TYPE,
nullptr);
404 qof_book_option_frame_delete(book,
"book/tax_US");
405 qof_book_option_frame_delete(book,
"book");
408 return qof_book_get_string_option(book, OPTION_TAXUS_TYPE);
415gnc_get_current_root_account (
void)
417 return gnc_book_get_root_account (gnc_get_current_book ());
421gnc_get_current_commodities (
void)
423 if (gnc_current_session_exist())
430 gboolean show_leaf_accounts)
432 if (show_leaf_accounts)
441 auto show_leaf_accounts =
443 GNC_PREF_SHOW_LEAF_ACCT_NAMES);
451 auto show_leaf_accounts =
453 GNC_PREF_SHOW_LEAF_ACCT_NAMES);
455 if (show_leaf_accounts)
469gnc_get_reconcile_str (
char reconciled_flag)
471 switch (reconciled_flag)
474 return C_(
"Reconciled flag 'not cleared'",
"n");
476 return C_(
"Reconciled flag 'cleared'",
"c");
478 return C_(
"Reconciled flag 'reconciled'",
"y");
480 return C_(
"Reconciled flag 'frozen'",
"f");
482 return C_(
"Reconciled flag 'void'",
"v");
484 PERR(
"Bad reconciled flag\n");
496gnc_get_reconcile_valid_flags (
void)
510gnc_get_reconcile_flag_order (
void)
512 static const char flags[] = {
NREC,
CREC, 0 };
522 return C_(
"Document Link flag for 'web'",
"w");
524 return C_(
"Document Link flag for 'file'",
"f");
528 PERR(
"Bad link flag");
536 static const char flags[] = { FLINK, WLINK,
' ', 0 };
543 static const char flags[] = { FLINK, WLINK,
' ', 0 };
548equity_base_name (GNCEquityType equity_type)
552 case EQUITY_OPENING_BALANCE:
553 return N_(
"Opening Balances");
555 case EQUITY_RETAINED_EARNINGS:
556 return N_(
"Retained Earnings");
564gnc_find_or_create_equity_account (
Account *root,
565 GNCEquityType equity_type,
566 gnc_commodity *currency)
568 g_return_val_if_fail (equity_type >= 0,
nullptr);
569 g_return_val_if_fail (equity_type < NUM_EQUITY_TYPES,
nullptr);
570 g_return_val_if_fail (currency !=
nullptr,
nullptr);
571 g_return_val_if_fail (root !=
nullptr,
nullptr);
574 auto use_eq_op_feature = equity_type == EQUITY_OPENING_BALANCE && gnc_using_equity_type_opening_balance_account (gnc_get_current_book ());
576 if (use_eq_op_feature)
583 auto base_name = equity_base_name (equity_type);
591 base_name = base_name && *base_name ?
_(base_name) :
"";
598 auto base_name_exists = (account !=
nullptr);
603 if (use_eq_op_feature)
608 auto name = g_strconcat (base_name,
" - ",
614 auto name_exists = (account !=
nullptr);
619 if (use_eq_op_feature)
625 if (name_exists && base_name_exists)
627 PWARN (
"equity account with unexpected currency");
632 if (!base_name_exists &&
636 name = g_strdup (base_name);
652 if (use_eq_op_feature)
667gnc_account_create_opening_balance (
Account *account,
675 g_return_val_if_fail (account !=
nullptr, FALSE);
679 auto equity_account =
681 EQUITY_OPENING_BALANCE,
726 auto table = gnc_get_current_commodities ();
727 auto code = gnc_locale_default_iso_currency_code ();
729 auto currency = gnc_commodity_table_lookup (
table,
730 GNC_COMMODITY_NS_CURRENCY,
733 return (currency ? currency :
nullptr);
741 return (currency ? currency :
742 gnc_commodity_table_lookup (gnc_get_current_commodities (),
743 GNC_COMMODITY_NS_CURRENCY,
"USD"));
748gnc_default_currency_common (
char* requested_currency,
751 gnc_commodity *currency =
nullptr;
753 if (requested_currency)
754 return gnc_commodity_table_lookup(gnc_get_current_commodities(),
755 GNC_COMMODITY_NS_CURRENCY,
758 if (gnc_current_session_exist() &&
762 currency = gnc_commodity_table_lookup(gnc_get_current_commodities(),
763 GNC_COMMODITY_NS_CURRENCY,
765 DEBUG(
"mnemonic %s, result %p",
766 mnemonic && *mnemonic ? mnemonic :
"(null)", currency);
775 g_free (requested_currency);
784 return gnc_default_currency_common (user_default_currency,
785 GNC_PREFS_GROUP_GENERAL);
790 gboolean * currency_from_account_found)
792 gnc_commodity *currency;
795 if (currency_from_account_found)
796 *currency_from_account_found = FALSE;
803 if (currency_from_account_found)
804 *currency_from_account_found = TRUE;
808 if (currency_from_account_found)
809 *currency_from_account_found = FALSE;
820 return gnc_default_currency_common (user_report_currency,
821 GNC_PREFS_GROUP_GENERAL_REPORT);
825gnc_currency_changed_cb (GSettings *settings,
char* key, gpointer user_data)
827 user_default_currency =
nullptr;
828 user_report_currency =
nullptr;
829 gnc_hook_run(HOOK_CURRENCY_CHANGED,
nullptr);
834gnc_default_print_info (gboolean use_symbol)
837 static bool got_it =
false;
840 info.use_symbol = use_symbol ? 1 : 0;
846 auto lc = gnc_localeconv ();
848 info.max_decimal_places = lc->frac_digits;
849 info.min_decimal_places = lc->frac_digits;
851 info.use_separators = 1;
863is_decimal_fraction (
int fraction, uint8_t *max_decimal_places_p)
865 uint8_t max_decimal_places = 0;
870 while (fraction != 1)
872 if (fraction % 10 != 0)
875 fraction = fraction / 10;
876 max_decimal_places += 1;
879 if (max_decimal_places_p)
880 *max_decimal_places_p = max_decimal_places;
886gnc_commodity_print_info (
const gnc_commodity *commodity,
891 if (commodity ==
nullptr)
892 return gnc_default_print_info (use_symbol);
894 info.commodity = commodity;
899 &info.max_decimal_places))
902 info.min_decimal_places = info.max_decimal_places;
904 info.min_decimal_places = 0;
907 info.max_decimal_places = info.min_decimal_places = 0;
909 info.use_separators = 1;
910 info.use_symbol = use_symbol ? 1 : 0;
911 info.use_locale = is_iso ? 1 : 0;
920gnc_account_print_info_helper(
const Account *account, gboolean use_symbol,
921 gnc_commodity * (*efffunc)(
const Account *),
922 int (*scufunc)(
const Account*))
926 if (account ==
nullptr)
927 return gnc_default_print_info (use_symbol);
929 info.commodity = efffunc (account);
933 auto scu = scufunc (account);
935 if (is_decimal_fraction (scu, &info.max_decimal_places))
938 info.min_decimal_places = info.max_decimal_places;
940 info.min_decimal_places = 0;
943 info.max_decimal_places = info.min_decimal_places = 0;
945 info.use_separators = 1;
946 info.use_symbol = use_symbol ? 1 : 0;
947 info.use_locale = is_iso ? 1 : 0;
956gnc_account_print_info (
const Account *account, gboolean use_symbol)
958 return gnc_account_print_info_helper(account, use_symbol,
964gnc_split_amount_print_info (Split *split, gboolean use_symbol)
969 info.use_symbol = use_symbol;
977gnc_default_print_info_helper (
int decplaces)
981 info.commodity =
nullptr;
983 info.max_decimal_places = decplaces;
984 info.min_decimal_places = 0;
986 info.use_separators = 1;
997gnc_default_share_print_info (
void)
1000 static bool got_it =
false;
1004 info = gnc_default_print_info_helper (5);
1013gnc_share_print_info_places (
int decplaces)
1017 info = gnc_default_share_print_info ();
1018 info.max_decimal_places = decplaces;
1019 info.min_decimal_places = decplaces;
1026gnc_price_print_info (
const gnc_commodity *curr, gboolean use_symbol)
1030 GNC_PREF_PRICES_FORCE_DECIMAL);
1031 info.commodity = curr;
1036 guint8 decplaces = 0;
1037 while (frac != 1 && (frac % 10) == 0 && (frac /= 10)) ++decplaces;
1040 info.max_decimal_places = decplaces;
1041 info.min_decimal_places = decplaces;
1045 info.max_decimal_places = 6;
1046 info.min_decimal_places = 0;
1049 info.use_separators = 1;
1050 info.use_symbol = use_symbol ? 1 : 0;
1051 info.use_locale = 1;
1054 info.force_fit = force;
1060gnc_default_price_print_info (
const gnc_commodity *curr)
1062 return gnc_price_print_info (curr, FALSE);
1067gnc_integral_print_info (
void)
1070 static bool got_it =
false;
1074 info = gnc_default_print_info_helper (0);
1085 auto *lc = gnc_localeconv();
1086 constexpr size_t buf_size = 128;
1087 char temp_buf[buf_size];
1089 g_return_val_if_fail (info !=
nullptr, 0);
1091 if (gnc_numeric_check (val))
1093 PWARN (
"Bad numeric: %s.",
1105 if (!value_is_decimal && info->force_fit && info->round)
1112 const int64_t denom = info->commodity ?
1114 (info->max_decimal_places &&
1115 info->max_decimal_places <= maximum_decimals) ?
1116 pow_10[info->max_decimal_places] : pow_10[maximum_decimals];
1117 val = gnc_numeric_convert(val, denom, GNC_HOW_RND_ROUND_HALF_UP);
1120 auto min_dp = info->min_decimal_places;
1121 auto max_dp = info->max_decimal_places;
1125 if (!info->force_fit)
1129 if (value_is_decimal && info->round && info->force_fit)
1132 gnc_numeric rounding{5, pow_10[max_dp + 1]};
1135 GNC_HOW_DENOM_EXACT | GNC_HOW_RND_TRUNC);
1139 PWARN (
"Bad numeric from rounding: %s.",
1147 auto whole = gnc_numeric_convert(val, 1, GNC_HOW_RND_TRUNC);
1149 if (gnc_numeric_check (val))
1151 PWARN (
"Problem with remainder: %s.",
1160 snprintf(temp_buf, buf_size,
"%" G_GINT64_FORMAT, whole.num);
1161 auto num_whole_digits = strlen (temp_buf);
1163 if (!info->use_separators)
1164 strcpy (buf, temp_buf);
1172 separator = lc->mon_thousands_sep;
1173 group = lc->mon_grouping;
1177 separator = lc->thousands_sep;
1178 group = lc->grouping;
1182 auto temp_ptr = &temp_buf[num_whole_digits - 1];
1183 auto group_count = 0;
1185 while (temp_ptr != temp_buf)
1187 *buf_ptr++ = *temp_ptr--;
1189 if (*group != CHAR_MAX)
1193 if (group_count == *group)
1195 g_utf8_strncpy(buf_ptr, separator, 1);
1196 buf_ptr = g_utf8_find_next_char(buf_ptr,
nullptr);
1218 *buf_ptr++ = *temp_ptr;
1220 auto rev_buf = g_utf8_strreverse(buf, -1);
1221 strcpy (buf, rev_buf);
1228 if (!value_is_decimal)
1233 snprintf (temp_buf, buf_size,
"%" G_GINT64_FORMAT
"/%" G_GINT64_FORMAT,
1234 val.num, val.denom);
1236 snprintf (temp_buf, buf_size,
"%" G_GINT64_FORMAT
" * %" G_GINT64_FORMAT,
1237 val.num, -val.denom);
1241 else if (value_is_negative)
1246 strcat (buf, temp_buf);
1250 guint8 num_decimal_places = 0;
1251 char* temp_ptr = temp_buf;
1253 auto decimal_point = info->monetary
1254 ? lc->mon_decimal_point
1255 : lc->decimal_point;
1256 g_utf8_strncpy(temp_ptr, decimal_point, 1);
1257 temp_ptr = g_utf8_find_next_char(temp_ptr,
nullptr);
1261 && (num_decimal_places < max_dp))
1265 val.denom = val.denom / 10;
1267 digit = val.num / val.denom;
1269 *temp_ptr++ = digit +
'0';
1270 num_decimal_places++;
1272 val.num = val.num - (digit * val.denom);
1275 while (num_decimal_places < min_dp)
1278 num_decimal_places++;
1285 while (*temp_ptr ==
'0' && num_decimal_places > min_dp)
1288 num_decimal_places--;
1291 if (num_decimal_places > max_dp)
1293 PWARN (
"max_decimal_places too small; limit %d, value %s%s",
1294 info->max_decimal_places, buf, temp_buf);
1297 strcat (buf, temp_buf);
1309 auto orig_bufp = bufp;
1310 auto currency_symbol =
"";
1317 bool print_sign =
true;
1318 bool print_absolute =
false;
1323 auto lc = gnc_localeconv();
1324 if (info.use_locale)
1327 cs_precedes = lc->n_cs_precedes;
1328 sep_by_space = lc->n_sep_by_space;
1332 cs_precedes = lc->p_cs_precedes;
1333 sep_by_space = lc->p_sep_by_space;
1338 sep_by_space = TRUE;
1341 if (info.commodity && info.use_symbol)
1346 cs_precedes = FALSE;
1347 sep_by_space = TRUE;
1353 sign = lc->negative_sign;
1354 sign_posn = lc->n_sign_posn;
1358 sign = lc->positive_sign;
1359 sign_posn = lc->p_sign_posn;
1366 if (print_sign && (sign_posn == 1))
1367 bufp = g_stpcpy(bufp, sign);
1373 if (print_sign && (sign_posn == 3))
1374 bufp = g_stpcpy(bufp, sign);
1376 if (info.use_symbol)
1378 bufp = g_stpcpy(bufp, currency_symbol);
1380 bufp = g_stpcpy(bufp,
" ");
1384 if (print_sign && (sign_posn == 4))
1385 bufp = g_stpcpy(bufp, sign);
1389 if (print_sign && (sign_posn == 0))
1391 bufp = g_stpcpy(bufp,
"(");
1392 print_absolute = TRUE;
1396 bufp += PrintAmountInternal(bufp,
1401 if (print_sign && (sign_posn == 0))
1402 bufp = g_stpcpy(bufp,
")");
1408 if (print_sign && (sign_posn == 3))
1409 bufp = g_stpcpy(bufp, sign);
1411 if (info.use_symbol)
1414 bufp = g_stpcpy(bufp,
" ");
1415 bufp = g_stpcpy(bufp, currency_symbol);
1419 if (print_sign && (sign_posn == 4))
1420 bufp = g_stpcpy(bufp, sign);
1424 if (print_sign && (sign_posn == 2))
1425 bufp = g_stpcpy(bufp, sign);
1428 return (bufp - orig_bufp);
1437 static char buf[BUFLEN];
1450 static char buf[BUFLEN];
1451 static const char ltr_isolate[] = {
'\xe2',
'\x81',
'\xa6' };
1452 static const char ltr_pop_isolate[] = {
'\xe2',
'\x81',
'\xa9' };
1453 auto offset = info.use_symbol ? 3 : 0;
1458 memset (buf, 0, BUFLEN);
1468 memcpy (buf, ltr_isolate, 3);
1470 if (buf[BUFLEN - 4] ==
'\0')
1472 auto length = strlen (buf);
1473 memcpy (buf + length, ltr_pop_isolate, 3);
1477 buf[BUFLEN - 1] =
'\0';
1478 memcpy (buf + BUFLEN - 4, ltr_pop_isolate, 3);
1480 PWARN(
"buffer length %d exceeded, string truncated was %s", BUFLEN, buf);
1490 static const char* ltr =
"\u2066";
1491 static const char* pop =
"\u2069";
1496 return g_strconcat (ltr, text, pop,
nullptr);
1512static const char* small_numbers[] =
1520 "Zero",
"One",
"Two",
"Three",
"Four",
1521 "Five",
"Six",
"Seven",
"Eight",
"Nine",
1522 "Ten",
"Eleven",
"Twelve",
"Thirteen",
"Fourteen",
1523 "Fifteen",
"Sixteen",
"Seventeen",
"Eighteen",
"Nineteen",
1526static const char* medium_numbers[] =
1528 "Zero",
"Ten",
"Twenty",
"Thirty",
"Forty",
1529 "Fifty",
"Sixty",
"Seventy",
"Eighty",
"Ninety"
1531static const char* big_numbers[] =
1556integer_to_words(gint64 val)
1559 return g_strdup(
"zero");
1563 auto result = g_string_sized_new(100);
1567 int log_val = log10(val) / 3 + FUDGE;
1568 int pow_val = exp(log_val * 3 * G_LN10) + FUDGE;
1569 int this_part = val / pow_val;
1570 val -= this_part * pow_val;
1571 auto tmp = integer_to_words(this_part);
1572 g_string_append_printf(result,
"%s %s ", tmp, gettext(big_numbers[log_val]));
1578 int this_part = val / 100;
1579 val -= this_part * 100;
1580 g_string_append_printf(result,
"%s %s ",
1581 gettext(small_numbers[this_part]),
1582 gettext(big_numbers[0]));
1587 int this_part = val / 10;
1588 val -= this_part * 10;
1589 g_string_append(result, gettext(medium_numbers[this_part]));
1590 g_string_append_c(result,
' ');
1595 int this_part = val;
1596 g_string_append(result, gettext(small_numbers[this_part]));
1597 g_string_append_c(result,
' ');
1600 result = g_string_truncate(result, result->len - 1);
1601 return g_string_free(result, FALSE);
1605static double round(
double x)
1608 return floor(x + 0.5);
1613number_to_words(
double val, int64_t denom)
1615 if (val < 0) val = -val;
1616 if (denom < 0) denom = -denom;
1618 auto int_part = floor(val);
1619 auto frac_part =
static_cast<int64_t
>(round((val - int_part) * denom));
1621 auto int_string = integer_to_words(int_part);
1625 auto nomin_string = g_strdup_printf(
"%02" PRId64, frac_part);
1626 auto denom_string = g_strdup_printf(
"%" PRId64, denom);
1632 g_strdup_printf(
"%s and %s/%s",
1633 int_string, nomin_string, denom_string);
1635 g_free(nomin_string);
1636 g_free(denom_string);
1641numeric_to_words(gnc_numeric val)
1644 gnc_numeric_denom(val));
1648printable_value (
double val,
int denom)
1650 auto num = gnc_numeric_create(round(val * denom), denom);
1651 auto info = gnc_share_print_info_places(log10(denom));
1678#define done_state(state) (((state) == DONE_ST) || ((state) == NO_NUM_ST))
1680static inline int64_t
1681multiplier (
int num_decimals)
1683 switch (num_decimals)
1686 return 1000000000000;
1688 return 100000000000;
1712 PERR(
"bad fraction length");
1713 g_assert_not_reached();
1721xaccParseAmountInternal (
const char* in_str, gboolean monetary,
1722 gunichar negative_sign, gunichar decimal_point,
1723 gunichar group_separator,
const char* ignore_list,
1724 gboolean use_auto_decimal,
1725 gnc_numeric *result,
char** endstr)
1729 *endstr = (
char* ) in_str;
1735 if (!g_utf8_validate(in_str, -1, &in))
1737 printf(
"Invalid utf8 string '%s'. Bad character at position %ld.\n",
1738 in_str, g_utf8_pointer_to_offset (in_str, in));
1744 auto out_str = g_new(gchar, strlen(in_str) + 128);
1750 auto is_negative =
false;
1751 auto got_decimal =
false;
1752 auto need_paren =
false;
1757 auto state = START_ST;
1762 auto next_state = state;
1763 auto uc = g_utf8_get_char(in);
1766 if (ignore_list && uc && g_utf8_strchr(ignore_list, -1, uc))
1768 in = g_utf8_next_char(in);
1778 if (g_unichar_isdigit(uc))
1780 int count = g_unichar_to_utf8(uc, out);
1783 next_state = NUMER_ST;
1785 else if (uc == decimal_point)
1786 next_state = FRAC_ST;
1787 else if (g_unichar_isspace(uc))
1789 else if (uc == negative_sign)
1792 next_state = NEG_ST;
1798 next_state = NEG_ST;
1801 next_state = NO_NUM_ST;
1808 if (g_unichar_isdigit(uc))
1810 int count = g_unichar_to_utf8(uc, out);
1812 next_state = NUMER_ST;
1814 else if (uc == decimal_point)
1815 next_state = FRAC_ST;
1816 else if (g_unichar_isspace(uc))
1819 next_state = NO_NUM_ST;
1826 if (g_unichar_isdigit(uc))
1828 int count = g_unichar_to_utf8(uc, out);
1831 else if (uc == decimal_point)
1832 next_state = FRAC_ST;
1833 else if (uc == group_separator)
1835 else if (uc ==
')' && need_paren)
1837 next_state = DONE_ST;
1841 next_state = DONE_ST;
1847 if (g_unichar_isdigit(uc))
1849 int count = g_unichar_to_utf8(uc, out);
1852 else if (uc == decimal_point)
1857 if (g_unichar_isspace(decimal_point))
1858 next_state = DONE_ST;
1860 next_state = NO_NUM_ST;
1862 else if (uc == group_separator)
1867 if (g_unichar_isspace(group_separator))
1868 next_state = DONE_ST;
1870 else if (uc ==
')' && need_paren)
1872 next_state = DONE_ST;
1876 next_state = DONE_ST;
1882 g_assert_not_reached();
1888 if (((next_state == FRAC_ST) && (state != FRAC_ST)) ||
1889 ((next_state == DONE_ST) && !got_decimal))
1893 if (*out_str && sscanf(out_str,
"%" SCNd64, &numer) < 1)
1894 next_state = NO_NUM_ST;
1895 else if (next_state == FRAC_ST)
1906 if (done_state (state))
1909 in = g_utf8_next_char(in);
1913 if (need_paren || (state == NO_NUM_ST))
1923 if (got_decimal && *out_str)
1926 auto len = strlen(out_str);
1935 if (sscanf (out_str,
"%" SCNd64 , &fraction) < 1)
1941 denom = multiplier(len);
1945 else if (monetary && use_auto_decimal && !got_decimal)
1947 if ((auto_decimal_places > 0) && (auto_decimal_places <= 12))
1949 denom = multiplier(auto_decimal_places);
1961 *result = gnc_numeric_create (numer, denom);
1967 *endstr = (
char* ) in;
1976xaccParseAmountBasicInternal (
const char* in_str, gboolean monetary,
1977 gboolean use_auto_decimal, gnc_numeric *result,
1978 char** endstr, gboolean skip)
1980 struct lconv *lc = gnc_localeconv();
1981 gunichar negative_sign = g_utf8_get_char(lc->negative_sign);
1983 gunichar decimal_point;
1984 gunichar group_separator;
1987 group_separator = g_utf8_get_char(lc->mon_thousands_sep);
1988 decimal_point = g_utf8_get_char(lc->mon_decimal_point);
1992 group_separator = g_utf8_get_char(lc->thousands_sep);
1993 decimal_point = g_utf8_get_char(lc->decimal_point);
1996 const char* ignore =
nullptr;
2002 ignore = lc->positive_sign;
2003 if (!ignore || !*ignore)
2007 return xaccParseAmountInternal(in_str, monetary, negative_sign,
2008 decimal_point, group_separator,
2009 ignore, use_auto_decimal,
2018 return xaccParseAmountBasicInternal (in_str, monetary, auto_decimal_enabled,
2019 result, endstr, FALSE);
2024 gnc_numeric *result,
2025 char** endstr, gboolean skip)
2027 return xaccParseAmountBasicInternal (in_str, monetary, FALSE,
2028 result, endstr, skip);
2034 gunichar negative_sign, gunichar decimal_point,
2035 gunichar group_separator,
const char* ignore_list,
2036 gnc_numeric *result,
char** endstr)
2038 return xaccParseAmountInternal (in_str, monetary, negative_sign,
2039 decimal_point, group_separator,
2040 ignore_list, auto_decimal_enabled,
2046 gunichar negative_sign, gunichar decimal_point,
2047 gunichar group_separator,
const char* ignore_list,
2048 gnc_numeric *result,
char** endstr)
2050 return xaccParseAmountInternal (in_str, monetary, negative_sign,
2051 decimal_point, group_separator,
2059gnc_set_auto_decimal_enabled (gpointer settings,
char* key, gpointer user_data)
2061 auto_decimal_enabled =
2067gnc_set_auto_decimal_places (gpointer settings,
char* key, gpointer user_data)
2069 auto_decimal_places =
2074gnc_auto_decimal_init (
void)
2076 auto_decimal_enabled =
2078 auto_decimal_places =
2083gnc_ui_util_init (
void)
2085 gnc_configure_account_separator ();
2086 gnc_auto_decimal_init();
2089 (
void*)gnc_configure_account_separator,
nullptr);
2091 (
void*)gnc_configure_reverse_balance,
nullptr);
2093 (
void*)gnc_configure_reverse_balance,
nullptr);
2095 (
void*)gnc_configure_reverse_balance,
nullptr);
2097 (
void*)gnc_currency_changed_cb,
nullptr);
2099 (
void*)gnc_currency_changed_cb,
nullptr);
2101 (
void*)gnc_currency_changed_cb,
nullptr);
2103 (
void*)gnc_currency_changed_cb,
nullptr);
2105 (
void*)gnc_currency_changed_cb,
nullptr);
2107 (
void*)gnc_currency_changed_cb,
nullptr);
2109 (
void*)gnc_set_auto_decimal_enabled,
nullptr);
2111 (
void*)gnc_set_auto_decimal_places,
nullptr);
2116gnc_ui_util_remove_registered_prefs (
void)
2120 GNC_PREF_ACCOUNT_SEPARATOR,
2121 (
void*)gnc_configure_account_separator,
nullptr);
2123 GNC_PREF_REVERSED_ACCTS_NONE,
2124 (
void*)gnc_configure_reverse_balance,
nullptr);
2126 GNC_PREF_REVERSED_ACCTS_CREDIT,
2127 (
void*)gnc_configure_reverse_balance,
nullptr);
2129 GNC_PREF_REVERSED_ACCTS_INC_EXP,
2130 (
void*)gnc_configure_reverse_balance,
nullptr);
2132 GNC_PREF_CURRENCY_CHOICE_LOCALE,
2133 (
void*)gnc_currency_changed_cb,
nullptr);
2135 GNC_PREF_CURRENCY_CHOICE_OTHER,
2136 (
void*)gnc_currency_changed_cb,
nullptr);
2138 GNC_PREF_CURRENCY_OTHER,
2139 (
void*)gnc_currency_changed_cb,
nullptr);
2141 GNC_PREF_CURRENCY_CHOICE_LOCALE,
2142 (
void*)gnc_currency_changed_cb,
nullptr);
2144 GNC_PREF_CURRENCY_CHOICE_OTHER,
2145 (
void*)gnc_currency_changed_cb,
nullptr);
2147 GNC_PREF_CURRENCY_OTHER,
2148 (
void*)gnc_currency_changed_cb,
nullptr);
2150 GNC_PREF_AUTO_DECIMAL_POINT,
2151 (
void*)gnc_set_auto_decimal_enabled,
nullptr);
2153 GNC_PREF_AUTO_DECIMAL_PLACES,
2154 (
void*)gnc_set_auto_decimal_places,
nullptr);
2163 int32_t len =
static_cast<int32_t
> (strlen (text));
2165 result.reserve (len);
2167 const char* p = text;
2174 U8_NEXT (p, i, len, c);
2176 if (c >= 0 && !u_hasBinaryProperty (c, UCHAR_BIDI_CONTROL))
2177 result.append (p + start, i - start);
2180 return g_strdup (result.c_str ());
2184unichar_is_cntrl (gunichar uc)
2186 return (uc < 0x20 || (uc > 0x7e && uc < 0xa0));
2193 bool text_found =
false;
2198 if (!g_utf8_validate (text, -1,
nullptr))
2201 auto filtered = g_string_sized_new (strlen (text) + 1);
2207 auto uc = g_utf8_get_char (ch);
2210 if (unichar_is_cntrl (uc) && !text_found)
2212 ch = g_utf8_next_char (ch);
2216 if (!unichar_is_cntrl (uc))
2218 filtered = g_string_append_unichar (filtered, uc);
2222 if (unichar_is_cntrl (uc))
2225 ch = g_utf8_next_char (ch);
2229 auto uc2 = g_utf8_get_char (ch);
2231 if (!unichar_is_cntrl (uc2))
2232 filtered = g_string_append_unichar (filtered,
' ');
2236 return g_string_free (filtered, FALSE);
2240gnc_filter_text_set_cursor_position (
const char* incoming_text,
2242 gint *cursor_position)
2246 if (*cursor_position == 0)
2249 if (!incoming_text || !symbol)
2252 if (g_strrstr (incoming_text, symbol) ==
nullptr)
2255 auto text_len = g_utf8_strlen (incoming_text, -1);
2257 for (
int x = 0; x < text_len; x++)
2259 auto temp = g_utf8_offset_to_pointer (incoming_text, x);
2261 if (g_str_has_prefix (temp, symbol))
2264 if (g_strrstr (temp, symbol) ==
nullptr)
2267 *cursor_position = *cursor_position - (num * g_utf8_strlen (symbol, -1));
2278 return g_strdup (incoming_text);
2280 if (g_strrstr (incoming_text, symbol) ==
nullptr)
2281 return g_strdup (incoming_text);
2283 auto split = g_strsplit (incoming_text, symbol, -1);
2285 auto ret_text = g_strjoinv (
nullptr, split);
2293 const char* incoming_text,
2294 const char** symbol)
2305 return g_strdup (incoming_text);
2319 g_return_val_if_fail (strings,
nullptr);
2321 UErrorCode status = U_ZERO_ERROR;
2322 auto formatter = icu::ListFormatter::createInstance(status);
2323 std::vector<UniStr> strvec;
2327 for (
auto n = strings; n; n = g_list_next (n))
2329 auto utf8_str{
static_cast<const char*
>(n->data)};
2330 strvec.push_back (UniStr::fromUTF8(utf8_str));
2333 formatter->format (strvec.data(), strvec.size(), result, status);
2335 if (U_FAILURE(status))
2336 PERR (
"Unicode error");
2338 result.toUTF8String(retval);
2341 return g_strdup (retval.c_str());
Account handling public routines.
API for Transactions and Splits (journal entries)
All type declarations for the whole Gnucash engine.
Utility functions for file access.
Generic api to store and retrieve preferences.
utility functions for the GnuCash UI
const char * xaccAccountGetName(const Account *acc)
Get the account's name.
void xaccAccountCommitEdit(Account *acc)
ThexaccAccountCommitEdit() subroutine is the second phase of a two-phase-commit wrapper for account u...
Account * gnc_account_get_root(Account *acc)
This routine returns the root account of the account tree that the specified account belongs to.
void xaccAccountBeginEdit(Account *acc)
The xaccAccountBeginEdit() subroutine is the first phase of a two-phase-commit wrapper for account up...
gchar * gnc_account_get_full_name(const Account *account)
The gnc_account_get_full_name routine returns the fully qualified name of the account using the given...
gnc_commodity * gnc_account_get_currency_or_parent(const Account *account)
Returns a gnc_commodity that is a currency, suitable for being a Transaction's currency.
void gnc_account_append_child(Account *new_parent, Account *child)
This function will remove from the child account any pre-existing parent relationship,...
GNCAccountType xaccAccountGetType(const Account *acc)
Returns the account's account type.
int xaccAccountGetCommoditySCU(const Account *acc)
Return the SCU for the account.
void xaccAccountSetName(Account *acc, const char *str)
Set the account's name.
void xaccAccountSetType(Account *acc, GNCAccountType tip)
Set the account's type.
Account * xaccMallocAccount(QofBook *book)
Constructor.
gint gnc_account_n_children(const Account *account)
Return the number of children of the specified account.
gnc_commodity * xaccAccountGetCommodity(const Account *acc)
Get the account's commodity
void xaccAccountSetCommodity(Account *acc, gnc_commodity *com)
Set the account's commodity.
@ ACCT_TYPE_INCOME
Income accounts are used to denote income.
@ ACCT_TYPE_EXPENSE
Expense accounts are used to denote expenses.
@ ACCT_TYPE_PAYABLE
A/P account type.
@ ACCT_TYPE_LIABILITY
liability (and asset) accounts indicate generic, generalized accounts that are none of the above.
@ ACCT_TYPE_EQUITY
Equity account is used to balance the balance sheet.
@ ACCT_TYPE_CREDIT
The Credit card account is used to denote credit (e.g.
@ NUM_ACCOUNT_TYPES
stop here; the following types just aren't ready for prime time
QofBook * qof_session_get_book(const QofSession *session)
Returns the QofBook of this session.
gboolean gnc_commodity_equiv(const gnc_commodity *a, const gnc_commodity *b)
This routine returns TRUE if the two commodities are equivalent.
int gnc_commodity_get_fraction(const gnc_commodity *cm)
Retrieve the fraction for the specified commodity.
const char * gnc_commodity_get_nice_symbol(const gnc_commodity *cm)
Retrieve a symbol for the specified commodity, suitable for display to the user.
gnc_commodity_table * gnc_commodity_table_get_table(QofBook *book)
Returns the commodity table associated with a book.
gboolean gnc_commodity_is_iso(const gnc_commodity *cm)
Checks to see if the specified commodity is an ISO 4217 recognized currency.
const char * gnc_commodity_get_mnemonic(const gnc_commodity *cm)
Retrieve the mnemonic for the specified commodity.
gboolean gnc_commodity_is_currency(const gnc_commodity *cm)
Checks to see if the specified commodity is an ISO 4217 recognized currency or a legacy currency.
gint64 time64
Most systems that are currently maintained, including Microsoft Windows, BSD-derived Unixes and Linux...
void xaccTransSetDescription(Transaction *trans, const char *desc)
Sets the transaction Description.
void xaccAccountSetIsOpeningBalance(Account *acc, gboolean val)
Set the "opening-balance" flag for an account.
#define xaccTransAppendSplit(t, s)
Add a split to the transaction.
void xaccTransCommitEdit(Transaction *trans)
The xaccTransCommitEdit() method indicates that the changes to the transaction and its splits are com...
Account * gnc_account_lookup_by_opening_balance(Account *account, gnc_commodity *commodity)
Find the opening balance account for the currency.
Account * gnc_account_lookup_by_name(const Account *parent, const char *name)
The gnc_account_lookup_by_name() subroutine fetches the account by name from the descendants of the s...
Transaction * xaccMallocTransaction(QofBook *book)
The xaccMallocTransaction() will malloc memory and initialize it.
void xaccTransSetDatePostedSecsNormalized(Transaction *trans, time64 time)
This function sets the posted date of the transaction, specified by a time64 (see ctime(3)).
void xaccTransSetCurrency(Transaction *trans, gnc_commodity *curr)
Set a new currency on a transaction.
#define xaccAccountInsertSplit(acc, s)
The xaccAccountInsertSplit() method will insert the indicated split into the indicated account.
Account * gnc_account_lookup_by_full_name(const Account *any_acc, const gchar *name)
The gnc_account_lookup_full_name() subroutine works like gnc_account_lookup_by_name,...
void xaccTransBeginEdit(Transaction *trans)
The xaccTransBeginEdit() method must be called before any changes are made to a transaction or any of...
char * gnc_get_account_name_for_register(const Account *account)
Get either the full name of the account or the simple name, depending on the configuration parameter ...
gboolean xaccParseAmountExtended(const char *in_str, gboolean monetary, gunichar negative_sign, gunichar decimal_point, gunichar group_separator, const char *ignore_list, gnc_numeric *result, char **endstr)
Converts a string to a gnc_numeric.
int xaccSPrintAmount(char *bufp, gnc_numeric val, GNCPrintAmountInfo info)
Make a string representation of a gnc_numeric.
char * gnc_wrap_text_with_bidi_ltr_isolate(const char *text)
This function helps with GTK's use of 'Unicode Bidirectional Text Algorithm'.
char * gnc_filter_text_for_control_chars(const char *text)
Returns the incoming text removed of control characters.
gchar * gnc_list_formatter(GList *strings)
This function takes a GList of char*, and uses locale-sensitive list formatter.
char * gnc_filter_text_for_currency_symbol(const char *incoming_text, const char *symbol)
Returns the incoming text removed of a currency symbol.
gboolean xaccParseAmountImport(const char *in_str, gboolean monetary, gnc_numeric *result, char **endstr, gboolean skip)
Similar to xaccParseAmount, but with two differences.
Account * gnc_account_lookup_for_register(const Account *base_account, const char *name)
Retrieve the account matching the given name starting from the descendants of base_account.
const char * gnc_get_doclink_flag_order(void)
Get a string containing document link flag order.
gnc_commodity * gnc_locale_default_currency(void)
Returns the default currency of the current locale.
char * gnc_filter_text_for_currency_commodity(const gnc_commodity *comm, const char *incoming_text, const char **symbol)
Returns the incoming text removed of currency symbol.
gnc_commodity * gnc_locale_default_currency_nodefault(void)
Returns the default currency of the current locale, or NULL if no sensible currency could be identifi...
char * gnc_filter_text_for_bidi_marks(const char *text)
Returns the incoming text with Unicode bidi control characters removed.
const char * gnc_get_doclink_valid_flags(void)
Get a string containing documentation link valid flags.
const char * xaccPrintAmount(gnc_numeric val, GNCPrintAmountInfo info)
Make a string representation of a gnc_numeric.
char * gnc_get_account_name_for_split_register(const Account *account, gboolean show_leaf_accounts)
Get either the full name of the account or the simple name, depending on the show_leaf_accounts.
gnc_commodity * gnc_account_or_default_currency(const Account *account, gboolean *currency_from_account_found)
Returns a gnc_commodity that is a currency, suitable for being a Transaction's currency.
gnc_commodity * gnc_default_currency(void)
Return the default currency set by the user.
const char * gnc_print_amount_with_bidi_ltr_isolate(gnc_numeric val, GNCPrintAmountInfo info)
Make a string representation of a gnc_numeric.
gboolean xaccParseAmountExtImport(const char *in_str, gboolean monetary, gunichar negative_sign, gunichar decimal_point, gunichar group_separator, const char *ignore_list, gnc_numeric *result, char **endstr)
Similar to xaccParseAmountExtended, but will not automatically set a decimal point,...
gboolean xaccParseAmount(const char *in_str, gboolean monetary, gnc_numeric *result, char **endstr)
Parses in_str to obtain a numeric result.
const char * gnc_get_doclink_str(char link_flag)
Get a string representing the document link type.
gnc_commodity * gnc_default_report_currency(void)
Return the default currency for use in reports, as set by the user.
#define DEBUG(format, args...)
Print a debugging message.
#define PERR(format, args...)
Log a serious error.
#define PWARN(format, args...)
Log a warning.
const char * gnc_numeric_errorCode_to_string(GNCNumericErrorCode error_code)
Returns a string representation of the given GNCNumericErrorCode.
gboolean gnc_numeric_to_decimal(gnc_numeric *a, guint8 *max_decimal_places)
Attempt to convert the denominator to an exact power of ten without rounding.
double gnc_numeric_to_double(gnc_numeric in)
Convert numeric to floating-point value.
gnc_numeric gnc_numeric_sub(gnc_numeric a, gnc_numeric b, gint64 denom, gint how)
Return a-b.
#define GNC_DENOM_AUTO
Values that can be passed as the 'denom' argument.
GNCNumericErrorCode gnc_numeric_check(gnc_numeric in)
Check for error signal in value.
gnc_numeric gnc_numeric_abs(gnc_numeric a)
Returns a newly created gnc_numeric that is the absolute value of the given gnc_numeric value.
gboolean gnc_numeric_negative_p(gnc_numeric a)
Returns 1 if a < 0, otherwise returns 0.
gboolean gnc_numeric_zero_p(gnc_numeric a)
Returns 1 if the given gnc_numeric is 0 (zero), else returns 0.
gnc_numeric gnc_numeric_neg(gnc_numeric a)
Returns a newly created gnc_numeric that is the negative of the given gnc_numeric value.
gnc_numeric gnc_numeric_reduce(gnc_numeric in)
Return input after reducing it by Greater Common Factor (GCF) elimination.
gnc_numeric gnc_numeric_add(gnc_numeric a, gnc_numeric b, gint64 denom, gint how)
Return a+b.
void gnc_prefs_remove_cb_by_func(const gchar *group, const gchar *pref_name, gpointer func, gpointer user_data)
Remove a function that was registered for a callback when the given preference changed.
gulong gnc_prefs_register_cb(const char *group, const gchar *pref_name, gpointer func, gpointer user_data)
Register a callback that gets triggered when the given preference changes.
gint gnc_prefs_get_int(const gchar *group, const gchar *pref_name)
Get an integer value from the preferences backend.
gchar * gnc_prefs_get_string(const gchar *group, const gchar *pref_name)
Get a string value from the preferences backend.
gboolean gnc_prefs_get_bool(const gchar *group, const gchar *pref_name)
Get a boolean value from the preferences backend.
gboolean gnc_prefs_set_string(const gchar *group, const gchar *pref_name, const gchar *value)
Store a string into the preferences backend.
void xaccSplitSetValue(Split *split, gnc_numeric val)
The xaccSplitSetValue() method sets the value of this split in the transaction's commodity.
Split * xaccMallocSplit(QofBook *book)
Constructor.
void xaccSplitSetAmount(Split *split, gnc_numeric amt)
The xaccSplitSetAmount() method sets the amount in the account's commodity that the split should have...
#define VREC
split is void
Account * xaccSplitGetAccount(const Split *split)
Returns the account of this split, which was set through xaccAccountInsertSplit().
#define NREC
not reconciled or cleared
#define FREC
frozen into accounting period
#define CREC
The Split has been cleared
#define YREC
The Split has been reconciled.
void gnc_features_set_used(QofBook *book, const gchar *feature)
Indicate that the current book uses the given feature.