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> 55 #include "gnc-hooks.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" 68 using UniStr = icu::UnicodeString;
70 static QofLogModule log_module = GNC_MOD_GUI;
72 static bool auto_decimal_enabled =
false;
73 static int auto_decimal_places = 2;
75 static bool reverse_balance_inited =
false;
81 static char* user_default_currency =
nullptr;
82 static char* user_report_currency =
nullptr;
83 constexpr
int maximum_decimals = 15;
84 constexpr int64_t pow_10[] = {1, 10, 100, 1000, 10000, 100000, 1000000,
85 10000000, 100000000, 1000000000, 10000000000,
86 100000000000, 1000000000000, 10000000000000,
87 100000000000000, 1000000000000000};
90 gnc_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);
116 gnc_configure_account_separator (
void)
119 auto separator = gnc_normalize_account_separator (
string);
121 gnc_set_account_separator(separator);
129 gnc_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");
153 gnc_reverse_balance_init (
void)
155 gnc_configure_reverse_balance ();
156 reverse_balance_inited = TRUE;
160 gnc_reverse_balance (
const Account *account)
162 if (account ==
nullptr)
169 if (!reverse_balance_inited)
170 gnc_reverse_balance_init ();
172 return reverse_type[type];
175 gboolean gnc_using_equity_type_opening_balance_account (QofBook* book)
177 return gnc_features_check_used (book, GNC_FEATURE_EQUITY_TYPE_OPENING_BALANCE);
180 void gnc_set_use_equity_type_opening_balance_account (QofBook* book)
186 gnc_get_default_directory (
const char* section)
193 dir = g_strdup (g_get_user_data_dir ());
195 dir = g_strdup (g_get_home_dir ());
202 gnc_set_default_directory (
const char* section,
const char* directory)
208 gnc_get_current_book (
void)
222 gnc_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" 234 gnc_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);
328 gnc_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);
371 gnc_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);
415 gnc_get_current_root_account (
void)
417 return gnc_book_get_root_account (gnc_get_current_book ());
420 gnc_commodity_table *
421 gnc_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)
469 gnc_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");
496 gnc_get_reconcile_valid_flags (
void)
510 gnc_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 };
548 equity_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");
564 gnc_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)
667 gnc_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"));
747 static gnc_commodity*
748 gnc_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);
825 gnc_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);
834 gnc_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;
863 is_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;
886 gnc_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;
920 gnc_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;
956 gnc_account_print_info (
const Account *account, gboolean use_symbol)
958 return gnc_account_print_info_helper(account, use_symbol,
964 gnc_split_amount_print_info (Split *split, gboolean use_symbol)
969 info.use_symbol = use_symbol;
977 gnc_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;
997 gnc_default_share_print_info (
void)
1000 static bool got_it =
false;
1004 info = gnc_default_print_info_helper (5);
1013 gnc_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;
1026 gnc_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;
1060 gnc_default_price_print_info (
const gnc_commodity *curr)
1062 return gnc_price_print_info (curr, FALSE);
1067 gnc_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);
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];
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]};
1139 PWARN (
"Bad numeric from rounding: %s.",
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);
1502 #define FUDGE .00001 1512 static 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",
1526 static const char* medium_numbers[] =
1528 "Zero",
"Ten",
"Twenty",
"Thirty",
"Forty",
1529 "Fifty",
"Sixty",
"Seventy",
"Eighty",
"Ninety" 1531 static const char* big_numbers[] =
1556 integer_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);
1605 static double round(
double x)
1608 return floor(x + 0.5);
1613 number_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);
1641 numeric_to_words(gnc_numeric val)
1644 gnc_numeric_denom(val));
1648 printable_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)) 1680 static inline int64_t
1681 multiplier (
int num_decimals)
1683 switch (num_decimals)
1686 return 1000000000000;
1688 return 100000000000;
1712 PERR(
"bad fraction length");
1713 g_assert_not_reached();
1721 xaccParseAmountInternal (
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;
1976 xaccParseAmountBasicInternal (
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,
2059 gnc_set_auto_decimal_enabled (gpointer settings,
char* key, gpointer user_data)
2061 auto_decimal_enabled =
2067 gnc_set_auto_decimal_places (gpointer settings,
char* key, gpointer user_data)
2069 auto_decimal_places =
2074 gnc_auto_decimal_init (
void)
2076 auto_decimal_enabled =
2078 auto_decimal_places =
2083 gnc_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);
2116 gnc_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 ());
2184 unichar_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);
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());
void xaccAccountSetType(Account *acc, GNCAccountType tip)
Set the account's type.
void xaccSplitSetValue(Split *split, gnc_numeric val)
The xaccSplitSetValue() method sets the value of this split in the transaction's commodity.
Never round at all, and signal an error if there is a fractional result in a computation.
#define xaccTransAppendSplit(t, s)
Add a split to the transaction.
gnc_commodity_table * gnc_commodity_table_get_table(QofBook *book)
Returns the commodity table associated with a book.
Transaction * xaccMallocTransaction(QofBook *book)
The xaccMallocTransaction() will malloc memory and initialize it.
gboolean xaccParseAmount(const char *in_str, gboolean monetary, gnc_numeric *result, char **endstr)
Parses in_str to obtain a numeric result.
gboolean xaccParseAmountImport(const char *in_str, gboolean monetary, gnc_numeric *result, char **endstr, gboolean skip)
Similar to xaccParseAmount, but with two differences.
void xaccTransSetDatePostedSecsNormalized(Transaction *trans, time64 time)
This function sets the posted date of the transaction, specified by a time64 (see ctime(3))...
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...
int gnc_commodity_get_fraction(const gnc_commodity *cm)
Retrieve the fraction for the specified commodity.
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...
void gnc_account_append_child(Account *new_parent, Account *child)
This function will remove from the child account any pre-existing parent relationship, and will then add the account as a child of the new parent.
const char * gnc_print_amount_with_bidi_ltr_isolate(gnc_numeric val, GNCPrintAmountInfo info)
Make a string representation of a gnc_numeric.
gchar * gnc_prefs_get_string(const gchar *group, const gchar *pref_name)
Get a string value from the preferences backend.
const char * gnc_commodity_get_mnemonic(const gnc_commodity *cm)
Retrieve the mnemonic for the specified commodity.
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.
utility functions for the GnuCash UI
Expense accounts are used to denote expenses.
GNCAccountType xaccAccountGetType(const Account *acc)
Returns the account's account type.
int xaccAccountGetCommoditySCU(const Account *acc)
Return the SCU for the account.
gnc_numeric gnc_numeric_neg(gnc_numeric a)
Returns a newly created gnc_numeric that is the negative of the given gnc_numeric value...
#define DEBUG(format, args...)
Print a debugging message.
void gnc_features_set_used(QofBook *book, const gchar *feature)
Indicate that the current book uses the given feature.
char * gnc_wrap_text_with_bidi_ltr_isolate(const char *text)
This function helps with GTK's use of 'Unicode Bidirectional Text Algorithm'.
const char * xaccPrintAmount(gnc_numeric val, GNCPrintAmountInfo info)
Make a string representation of a gnc_numeric.
void xaccTransSetDescription(Transaction *trans, const char *desc)
Sets the transaction Description.
gnc_numeric gnc_numeric_add(gnc_numeric a, gnc_numeric b, gint64 denom, gint how)
Return a+b.
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.
gboolean gnc_numeric_zero_p(gnc_numeric a)
Returns 1 if the given gnc_numeric is 0 (zero), else returns 0.
stop here; the following types just aren't ready for prime time
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.
Use any denominator which gives an exactly correct ratio of numerator to denominator.
gboolean gnc_prefs_set_string(const gchar *group, const gchar *pref_name, const gchar *value)
Store a string into the preferences backend.
#define PERR(format, args...)
Log a serious error.
gnc_commodity * gnc_default_report_currency(void)
Return the default currency for use in reports, as set by the user.
char * gnc_filter_text_for_bidi_marks(const char *text)
Returns the incoming text with Unicode bidi control characters removed.
gint gnc_prefs_get_int(const gchar *group, const gchar *pref_name)
Get an integer value from the preferences backend.
gboolean gnc_numeric_negative_p(gnc_numeric a)
Returns 1 if a < 0, otherwise returns 0.
#define VREC
split is void
gnc_numeric gnc_numeric_reduce(gnc_numeric n)
Return input after reducing it by Greater Common Factor (GCF) elimination.
void xaccTransSetCurrency(Transaction *trans, gnc_commodity *curr)
Set a new currency on a transaction.
gnc_commodity * gnc_default_currency(void)
Return the default currency set by the user.
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...
#define PWARN(format, args...)
Log a warning.
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, regardless of what the user has set for this option.
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 ...
gdouble gnc_numeric_to_double(gnc_numeric n)
Convert numeric to floating-point value.
void xaccSplitSetAmount(Split *split, gnc_numeric amt)
The xaccSplitSetAmount() method sets the amount in the account's commodity that the split should have...
QofBook * qof_session_get_book(const QofSession *session)
Returns the QofBook of this session.
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...
Account handling public routines.
gnc_numeric gnc_numeric_convert(gnc_numeric n, gint64 denom, gint how)
Change the denominator of a gnc_numeric value to the specified denominator under standard arguments '...
Income accounts are used to denote income.
#define YREC
The Split has been reconciled.
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.
const char * gnc_numeric_errorCode_to_string(GNCNumericErrorCode error_code)
Returns a string representation of the given GNCNumericErrorCode.
const char * gnc_get_doclink_flag_order(void)
Get a string containing document link flag order.
#define FREC
frozen into accounting period
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.
void gnc_filter_text_set_cursor_position(const char *incoming_text, const char *symbol, int *zcursor_position)
Updates cursor_position after removal of currency symbols.
gchar * gnc_list_formatter(GList *strings)
This function takes a GList of char*, and uses locale-sensitive list formatter.
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, but uses fully-qualified names using the given separator.
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_numeric gnc_numeric_abs(gnc_numeric a)
Returns a newly created gnc_numeric that is the absolute value of the given gnc_numeric value...
void xaccTransCommitEdit(Transaction *trans)
The xaccTransCommitEdit() method indicates that the changes to the transaction and its splits are com...
void xaccAccountSetIsOpeningBalance(Account *acc, gboolean val)
Set the "opening-balance" flag for an account.
void xaccTransBeginEdit(Transaction *trans)
The xaccTransBeginEdit() method must be called before any changes are made to a transaction or any of...
gint gnc_account_n_children(const Account *account)
Return the number of children of the specified account.
All type declarations for the whole Gnucash engine.
#define CREC
The Split has been cleared.
int xaccSPrintAmount(char *bufp, gnc_numeric val, GNCPrintAmountInfo info)
Make a string representation of a gnc_numeric.
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.
Split * xaccMallocSplit(QofBook *book)
Constructor.
char * gnc_filter_text_for_control_chars(const char *text)
Returns the incoming text removed of control characters.
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.
Generic api to store and retrieve preferences.
gnc_numeric gnc_numeric_sub(gnc_numeric a, gnc_numeric b, gint64 denom, gint how)
Return a-b.
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.
char * gnc_filter_text_for_currency_symbol(const char *incoming_text, const char *symbol)
Returns the incoming text removed of a currency symbol.
Truncate fractions (round toward zero)
liability (and asset) accounts indicate generic, generalized accounts that are none of the above...
void xaccAccountBeginEdit(Account *acc)
The xaccAccountBeginEdit() subroutine is the first phase of a two-phase-commit wrapper for account up...
Account * xaccSplitGetAccount(const Split *split)
Returns the account of this split, which was set through xaccAccountInsertSplit().
gnc_commodity * xaccAccountGetCommodity(const Account *acc)
Get the account's commodity.
#define xaccAccountInsertSplit(acc, s)
The xaccAccountInsertSplit() method will insert the indicated split into the indicated account...
gboolean gnc_prefs_get_bool(const gchar *group, const gchar *pref_name)
Get a boolean value from the preferences backend.
Round to the nearest integer, rounding away from zero when there are two equidistant nearest integers...
Account * xaccMallocAccount(QofBook *book)
Constructor.
const char * gnc_get_doclink_str(char link_flag)
Get a string representing the document link type.
GNCNumericErrorCode gnc_numeric_check(gnc_numeric a)
Check for error signal in value.
gint64 time64
Most systems that are currently maintained, including Microsoft Windows, BSD-derived Unixes and Linux...
const char * gnc_get_doclink_valid_flags(void)
Get a string containing documentation link valid flags.
Account * gnc_account_get_root(Account *acc)
This routine returns the root account of the account tree that the specified account belongs to...
Account * gnc_account_lookup_by_opening_balance(Account *account, gnc_commodity *commodity)
Find the opening balance account for the currency.
const char * xaccAccountGetName(const Account *acc)
Get the account's name.
Equity account is used to balance the balance sheet.
#define GNC_DENOM_AUTO
Values that can be passed as the 'denom' argument.
API for Transactions and Splits (journal entries)
void xaccAccountCommitEdit(Account *acc)
ThexaccAccountCommitEdit() subroutine is the second phase of a two-phase-commit wrapper for account u...
gnc_commodity * gnc_locale_default_currency(void)
Returns the default currency of the current locale.
void xaccAccountSetName(Account *acc, const char *str)
Set the account's name.
gboolean gnc_commodity_equiv(const gnc_commodity *a, const gnc_commodity *b)
This routine returns TRUE if the two commodities are equivalent.
gboolean gnc_commodity_is_iso(const gnc_commodity *cm)
Checks to see if the specified commodity is an ISO 4217 recognized currency.
The Credit card account is used to denote credit (e.g.
void xaccAccountSetCommodity(Account *acc, gnc_commodity *com)
Set the account's commodity.
#define NREC
not reconciled or cleared
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.
Utility functions for file access.