28 #include <glib/gi18n.h>
36 #if defined(G_OS_WIN32) && !defined(_MSC_VER)
46 #include "guile-mappings.h"
48 #include "gnc-module/gnc-module.h"
52 #include "app-utils/gnc-euro.h"
53 #include "engine/gnc-hooks.h"
54 #include "engine/gnc-session.h"
55 #include "engine-helpers.h"
56 #include "gnc-locale-utils.h"
57 #include "gnc-component-manager.h"
59 #include "gnc-guile-utils.h"
61 #define GNC_PREF_CURRENCY_CHOICE_LOCALE "currency-choice-locale"
62 #define GNC_PREF_CURRENCY_CHOICE_OTHER "currency-choice-other"
63 #define GNC_PREF_CURRENCY_OTHER "currency-other"
64 #define GNC_PREF_REVERSED_ACCTS_NONE "reversed-accounts-none"
65 #define GNC_PREF_REVERSED_ACCTS_CREDIT "reversed-accounts-credit"
66 #define GNC_PREF_REVERSED_ACCTS_INC_EXP "reversed-accounts-incomeexpense"
70 static gboolean auto_decimal_enabled = FALSE;
71 static int auto_decimal_places = 2;
73 static gboolean reverse_balance_inited = FALSE;
79 static gchar *user_default_currency = NULL;
80 static gchar *user_report_currency = NULL;
82 gchar *gnc_normalize_account_separator (
const gchar* separator)
86 if (!separator || !*separator || g_strcmp0(separator,
"colon") == 0)
87 new_sep = g_strdup (
":");
88 else if (g_strcmp0(separator,
"slash") == 0)
89 new_sep = g_strdup (
"/");
90 else if (g_strcmp0(separator,
"backslash") == 0)
91 new_sep = g_strdup (
"\\");
92 else if (g_strcmp0(separator,
"dash") == 0)
93 new_sep = g_strdup (
"-");
94 else if (g_strcmp0(separator,
"period") == 0)
95 new_sep = g_strdup (
".");
97 new_sep = g_strdup (separator);
108 gnc_configure_account_separator (
void)
114 separator = gnc_normalize_account_separator (
string);
116 gnc_set_account_separator(separator);
124 gnc_configure_reverse_balance (
void)
129 reverse_type[i] = FALSE;
136 else if (
gnc_prefs_get_bool (GNC_PREFS_GROUP_GENERAL, GNC_PREF_REVERSED_ACCTS_CREDIT))
145 PWARN(
"no reversed account preference set, using none");
150 gnc_reverse_balance_init (
void)
152 gnc_configure_reverse_balance ();
153 reverse_balance_inited = TRUE;
157 gnc_reverse_balance (
const Account *account)
165 if ((type < 0) || (type >= NUM_ACCOUNT_TYPES))
168 if (!reverse_balance_inited)
169 gnc_reverse_balance_init ();
171 return reverse_type[type];
176 gnc_get_default_directory (
const gchar *section)
183 dir = g_strdup (g_get_user_data_dir ());
185 dir = g_strdup (g_get_home_dir ());
192 gnc_set_default_directory (
const gchar *section,
const gchar *directory)
198 gnc_get_current_book (
void)
212 gnc_is_new_book (
void)
214 return ((!gnc_current_session_exist() ||
215 (gnc_current_session_exist() &&
217 gnc_book_get_root_account(
218 gnc_get_current_book()))))
222 #define OPTION_TAXUS_NAME "book/tax_US/name"
223 #define OPTION_TAXUS_TYPE "book/tax_US/type"
226 gnc_set_current_book_tax_name (
const gchar *tax_name)
228 qof_book_set_string_option(gnc_get_current_book(), OPTION_TAXUS_NAME, tax_name);
232 gnc_get_current_book_tax_name (
void)
234 return qof_book_get_string_option(gnc_get_current_book(), OPTION_TAXUS_NAME);
238 gnc_set_current_book_tax_type (
const gchar *tax_type)
240 qof_book_set_string_option(gnc_get_current_book(), OPTION_TAXUS_TYPE, tax_type);
244 gnc_get_current_book_tax_type (
void)
246 return qof_book_get_string_option(gnc_get_current_book(), OPTION_TAXUS_TYPE);
255 gnc_suspend_gui_refresh ();
262 GNC_FEATURE_NUM_FIELD_SOURCE);
264 gnc_book_option_num_field_source_change (num_action);
265 gnc_resume_gui_refresh ();
266 gnc_gui_refresh_all ();
270 gnc_get_current_root_account (
void)
272 return gnc_book_get_root_account (gnc_get_current_book ());
276 gnc_get_current_commodities (
void)
284 gboolean show_leaf_accounts;
286 GNC_PREF_SHOW_LEAF_ACCT_NAMES);
288 if (show_leaf_accounts)
297 gboolean show_leaf_accounts;
299 GNC_PREF_SHOW_LEAF_ACCT_NAMES);
301 if (show_leaf_accounts)
310 gnc_ui_account_get_tax_info_string (
const Account *account)
312 static SCM get_form = SCM_UNDEFINED;
313 static SCM get_desc = SCM_UNDEFINED;
315 gboolean tax_related = FALSE;
339 return g_strdup (_(
"Tax-related but has no tax code"));
343 const gchar *tax_type;
347 gchar *num_code = NULL;
348 const gchar *prefix =
"N";
349 gchar *return_string = NULL;
351 tax_type = gnc_get_current_book_tax_type ();
352 if (tax_type == NULL || (g_strcmp0 (tax_type,
"") == 0))
353 return g_strdup (_(
"Tax entity type not specified"));
356 tax_entity_type = scm_from_utf8_string (tax_type);
358 if (get_form == SCM_UNDEFINED)
361 const gchar *tax_module;
363 #ifdef LOCALE_SPECIFIC_TAX
368 gchar *thislocale = g_win32_getlocale();
369 gboolean is_de_DE = (strncmp(thislocale,
"de_DE", 5) == 0);
372 const char *thislocale = setlocale(LC_ALL, NULL);
373 gboolean is_de_DE = (strncmp(thislocale,
"de_DE", 5) == 0);
376 gboolean is_de_DE = FALSE;
378 tax_module = is_de_DE ?
379 "gnucash/tax/de_DE" :
382 module = gnc_module_load ((
char *)tax_module, 0);
384 g_return_val_if_fail (module, NULL);
386 get_form = scm_c_eval_string
387 (
"(false-if-exception gnc:txf-get-form)");
388 get_desc = scm_c_eval_string
389 (
"(false-if-exception gnc:txf-get-description)");
392 g_return_val_if_fail (scm_is_procedure (get_form), NULL);
393 g_return_val_if_fail (scm_is_procedure (get_desc), NULL);
396 "txf-income-categories" :
398 "txf-expense-categories" :
405 "txf-asset-categories" :
410 "txf-liab-eq-categories" :
""))));
412 if (g_str_has_prefix (code, prefix))
414 const gchar *num_code_tmp;
415 num_code_tmp = g_strdup (code);
417 num_code = g_strdup (num_code_tmp);
419 g_free ((gpointer *) num_code_tmp);
423 num_code = g_strdup (code);
426 if (category == SCM_UNDEFINED)
429 return_string = g_strdup_printf
430 (_(
"Tax type %s: invalid code %s for account type"),
433 return_string = g_strdup_printf
434 (_(
"Not tax-related; tax type %s: invalid code %s for account type"),
441 code_scm = scm_from_locale_symbol (code);
442 form_scm = scm_call_3 (get_form, category, code_scm, tax_entity_type);
443 if (!scm_is_string (form_scm))
446 return_string = g_strdup_printf
447 (_(
"Invalid code %s for tax type %s"),
450 return_string = g_strdup_printf
451 (_(
"Not tax-related; invalid code %s for tax type %s"),
464 form = scm_to_utf8_string (form_scm);
468 return_string = g_strdup_printf
469 (_(
"No form: code %s, tax type %s"), num_code,
472 return_string = g_strdup_printf
473 (_(
"Not tax-related; no form: code %s, tax type %s"),
482 scm_dynwind_begin (0);
483 scm_dynwind_free (form);
484 desc_scm = scm_call_3 (get_desc, category, code_scm,
486 if (!scm_is_string (desc_scm))
489 return_string = g_strdup_printf
490 (_(
"No description: form %s, code %s, tax type %s"),
491 form, num_code, tax_type);
493 return_string = g_strdup_printf
494 (_(
"Not tax-related; no description: form %s, code %s, tax type %s"),
495 form, num_code, tax_type);
500 desc = gnc_scm_to_utf8_string (desc_scm);
504 return_string = g_strdup_printf
505 (_(
"No description: form %s, code %s, tax type %s"),
506 form, num_code, tax_type);
508 return_string = g_strdup_printf
509 (_(
"Not tax-related; no description: form %s, code %s, tax type %s"),
510 form, num_code, tax_type);
515 gchar *copy_txt = NULL;
517 copy_txt = (copy_number == 1) ?
519 g_strdup_printf (
"(%d)",
523 if (g_strcmp0 (form,
"") == 0)
524 return_string = g_strdup_printf (
"%s", desc);
526 return_string = g_strdup_printf (
"%s%s: %s",
527 form, copy_txt, desc);
531 return_string = g_strdup_printf
532 (_(
"Not tax-related; %s%s: %s (code %s, tax type %s)"),
533 form, copy_txt, desc, num_code, tax_type);
544 return return_string;
550 gnc_ui_account_get_tax_info_sub_acct_string (
const Account *account)
552 GList *descendant, *account_descendants;
558 if (account_descendants)
560 gint sub_acct_tax_number = 0;
561 for (descendant = account_descendants; descendant;
562 descendant = g_list_next(descendant))
565 sub_acct_tax_number++;
567 g_list_free (account_descendants);
568 g_list_free (descendant);
578 return (sub_acct_tax_number == 0) ? NULL :
579 g_strdup_printf (_(
"(Tax-related subaccounts: %d)"),
580 sub_acct_tax_number);
587 string_after_colon (
const char *msgstr)
589 const char *string_at_colon;
591 string_at_colon = strchr(msgstr,
':');
593 return string_at_colon + 1;
608 gnc_get_reconcile_str (
char reconciled_flag)
610 switch (reconciled_flag)
616 return string_after_colon(_(
"not cleared:n"));
619 return string_after_colon(_(
"cleared:c"));
622 return string_after_colon(_(
"reconciled:y"));
625 return string_after_colon(_(
"frozen:f"));
628 return string_after_colon(_(
"void:v"));
630 PERR(
"Bad reconciled flag\n");
642 gnc_get_reconcile_valid_flags (
void)
656 gnc_get_reconcile_flag_order (
void)
658 static const char flags[] = {
NREC,
CREC, 0 };
664 equity_base_name (GNCEquityType equity_type)
668 case EQUITY_OPENING_BALANCE:
669 return N_(
"Opening Balances");
671 case EQUITY_RETAINED_EARNINGS:
672 return N_(
"Retained Earnings");
680 gnc_find_or_create_equity_account (
Account *root,
681 GNCEquityType equity_type,
686 gboolean name_exists;
687 gboolean base_name_exists;
688 const char *base_name;
691 g_return_val_if_fail (equity_type >= 0, NULL);
692 g_return_val_if_fail (equity_type < NUM_EQUITY_TYPES, NULL);
693 g_return_val_if_fail (currency != NULL, NULL);
694 g_return_val_if_fail (root != NULL, NULL);
696 base_name = equity_base_name (equity_type);
704 base_name = base_name && *base_name ? _(base_name) :
"";
711 base_name_exists = (account != NULL);
717 name = g_strconcat (base_name,
" - ",
723 name_exists = (account != NULL);
730 if (name_exists && base_name_exists)
732 PWARN (
"equity account with unexpected currency");
737 if (!base_name_exists &&
741 name = g_strdup (base_name);
769 gnc_account_create_opening_balance (
Account *account,
781 g_return_val_if_fail (account != NULL, FALSE);
785 EQUITY_OPENING_BALANCE,
828 gnc_lconv_set_utf8 (
char **p_value,
char *default_value)
830 char *value = *p_value;
833 if ((value == NULL) || (value[0] == 0))
834 value = default_value;
839 size_t count = mbstowcs (NULL, value, 0);
843 wchar_t *wvalue = g_malloc ((count + 1) *
sizeof(
wchar_t));
844 count = mbstowcs (wvalue, value, count + 1);
847 *p_value = g_utf16_to_utf8 (wvalue, -1, NULL, NULL, NULL);
853 *p_value = g_locale_to_utf8 (value, -1, NULL, NULL, NULL);
856 if (*p_value == NULL)
860 *p_value = default_value;
865 gnc_lconv_set_char (
char *p_value,
char default_value)
867 if ((p_value != NULL) && (*p_value == CHAR_MAX))
868 *p_value = default_value;
873 gnc_locale_default_currency_nodefault (
void)
879 table = gnc_get_current_commodities ();
880 code = gnc_locale_default_iso_currency_code ();
882 currency = gnc_commodity_table_lookup (table, GNC_COMMODITY_NS_CURRENCY, code);
888 if (gnc_is_euro_currency (currency))
889 currency = gnc_get_euro();
891 return (currency ? currency : NULL);
895 gnc_locale_default_currency (
void)
897 gnc_commodity * currency = gnc_locale_default_currency_nodefault ();
899 return (currency ? currency :
900 gnc_commodity_table_lookup (gnc_get_current_commodities (),
901 GNC_COMMODITY_NS_CURRENCY,
"USD"));
906 gnc_default_currency_common (gchar *requested_currency,
907 const gchar *section)
912 if (requested_currency)
913 return gnc_commodity_table_lookup(gnc_get_current_commodities(),
914 GNC_COMMODITY_NS_CURRENCY,
920 currency = gnc_commodity_table_lookup(gnc_get_current_commodities(),
921 GNC_COMMODITY_NS_CURRENCY, mnemonic);
922 DEBUG(
"mnemonic %s, result %p", mnemonic ? mnemonic :
"(null)", currency);
927 currency = gnc_locale_default_currency ();
930 mnemonic = requested_currency;
941 return gnc_default_currency_common (user_default_currency, GNC_PREFS_GROUP_GENERAL);
949 if (currency_from_account_found)
950 *currency_from_account_found = FALSE;
957 if (currency_from_account_found)
958 *currency_from_account_found = TRUE;
962 if (currency_from_account_found)
963 *currency_from_account_found = FALSE;
974 return gnc_default_currency_common (user_report_currency, GNC_PREFS_GROUP_GENERAL_REPORT);
978 gnc_currency_changed_cb (GSettings *settings, gchar *key, gpointer user_data)
980 user_default_currency = NULL;
981 user_report_currency = NULL;
982 gnc_hook_run(HOOK_CURRENCY_CHANGED, NULL);
987 gnc_default_print_info (gboolean use_symbol)
990 static gboolean got_it = FALSE;
994 info.use_symbol = use_symbol ? 1 : 0;
1000 lc = gnc_localeconv ();
1002 info.max_decimal_places = lc->frac_digits;
1003 info.min_decimal_places = lc->frac_digits;
1005 info.use_separators = 1;
1006 info.use_locale = 1;
1017 is_decimal_fraction (
int fraction, guint8 *max_decimal_places_p)
1019 guint8 max_decimal_places = 0;
1024 while (fraction != 1)
1026 if (fraction % 10 != 0)
1029 fraction = fraction / 10;
1030 max_decimal_places += 1;
1033 if (max_decimal_places_p)
1034 *max_decimal_places_p = max_decimal_places;
1041 gboolean use_symbol)
1046 if (commodity == NULL)
1047 return gnc_default_print_info (use_symbol);
1049 info.commodity = commodity;
1054 &info.max_decimal_places))
1057 info.min_decimal_places = info.max_decimal_places;
1059 info.min_decimal_places = 0;
1062 info.max_decimal_places = info.min_decimal_places = 0;
1064 info.use_separators = 1;
1065 info.use_symbol = use_symbol ? 1 : 0;
1066 info.use_locale = is_iso ? 1 : 0;
1075 gnc_account_print_info_helper(
const Account *account, gboolean use_symbol,
1077 int (*scufunc)(
const Account*))
1083 if (account == NULL)
1084 return gnc_default_print_info (use_symbol);
1086 info.commodity = efffunc (account);
1090 scu = scufunc (account);
1092 if (is_decimal_fraction (scu, &info.max_decimal_places))
1095 info.min_decimal_places = info.max_decimal_places;
1097 info.min_decimal_places = 0;
1100 info.max_decimal_places = info.min_decimal_places = 0;
1102 info.use_separators = 1;
1103 info.use_symbol = use_symbol ? 1 : 0;
1104 info.use_locale = is_iso ? 1 : 0;
1113 gnc_account_print_info (
const Account *account, gboolean use_symbol)
1115 return gnc_account_print_info_helper(account, use_symbol,
1121 gnc_split_amount_print_info (
Split *split, gboolean use_symbol)
1126 info.use_symbol = use_symbol;
1134 gnc_default_print_info_helper (
int decplaces)
1138 info.commodity = NULL;
1140 info.max_decimal_places = decplaces;
1141 info.min_decimal_places = 0;
1143 info.use_separators = 1;
1144 info.use_symbol = 0;
1145 info.use_locale = 1;
1154 gnc_default_share_print_info (
void)
1157 static gboolean got_it = FALSE;
1161 info = gnc_default_print_info_helper (5);
1169 gnc_share_print_info_places (
int decplaces)
1173 info = gnc_default_share_print_info ();
1174 info.max_decimal_places = decplaces;
1175 info.min_decimal_places = decplaces;
1182 gnc_default_price_print_info (
void)
1185 static gboolean got_it = FALSE;
1189 info = gnc_default_print_info_helper (6);
1197 gnc_integral_print_info (
void)
1200 static gboolean got_it = FALSE;
1204 info = gnc_default_print_info_helper (0);
1215 struct lconv *lc = gnc_localeconv();
1216 int num_whole_digits;
1220 gboolean value_is_negative, value_is_decimal;
1222 g_return_val_if_fail (info != NULL, 0);
1226 PWARN (
"Bad numeric: %s.",
1240 if (auto_decimal_enabled)
1242 min_dp = MAX(auto_decimal_places, info->min_decimal_places);
1243 max_dp = MAX(auto_decimal_places, info->max_decimal_places);
1247 min_dp = info->min_decimal_places;
1248 max_dp = info->max_decimal_places;
1253 if (!info->force_fit)
1257 if (value_is_decimal && info->round && info->force_fit)
1260 rounding.denom = pow(10, max_dp + 1);
1265 PWARN (
"Bad numeric from rounding: %s.",
1277 PWARN (
"Problem with remainder: %s.",
1284 sprintf(temp_buf,
"%" G_GINT64_FORMAT, whole.num);
1285 num_whole_digits = strlen (temp_buf);
1287 if (!info->use_separators)
1288 strcpy (buf, temp_buf);
1300 separator = lc->mon_thousands_sep;
1301 group = lc->mon_grouping;
1305 separator = lc->thousands_sep;
1306 group = lc->grouping;
1310 temp_ptr = &temp_buf[num_whole_digits - 1];
1313 while (temp_ptr != temp_buf)
1315 *buf_ptr++ = *temp_ptr--;
1317 if (*group != CHAR_MAX)
1321 if (group_count == *group)
1323 g_utf8_strncpy(buf_ptr, separator, 1);
1324 buf_ptr = g_utf8_find_next_char(buf_ptr, NULL);
1346 *buf_ptr++ = *temp_ptr;
1348 rev_buf = g_utf8_strreverse(buf, -1);
1349 strcpy (buf, rev_buf);
1356 if (!value_is_decimal)
1361 sprintf (temp_buf,
"%" G_GINT64_FORMAT
"/%" G_GINT64_FORMAT,
1362 val.num, val.denom);
1364 sprintf (temp_buf,
"%" G_GINT64_FORMAT
" * %" G_GINT64_FORMAT,
1365 val.num, -val.denom);
1369 else if (value_is_negative)
1374 strcat (buf, temp_buf);
1378 char *decimal_point;
1379 guint8 num_decimal_places = 0;
1380 char *temp_ptr = temp_buf;
1382 decimal_point = info->monetary
1383 ? lc->mon_decimal_point
1384 : lc->decimal_point;
1385 g_utf8_strncpy(temp_ptr, decimal_point, 1);
1386 temp_ptr = g_utf8_find_next_char(temp_ptr, NULL);
1390 && (num_decimal_places < max_dp))
1394 val.denom = val.denom / 10;
1396 digit = val.num / val.denom;
1398 *temp_ptr++ = digit +
'0';
1399 num_decimal_places++;
1401 val.num = val.num - (digit * val.denom);
1404 while (num_decimal_places < min_dp)
1407 num_decimal_places++;
1414 while (*temp_ptr ==
'0' && num_decimal_places > min_dp)
1417 num_decimal_places--;
1420 if (num_decimal_places > max_dp)
1422 PWARN (
"max_decimal_places too small; limit %d, value %s%s",
1423 info->max_decimal_places, buf, temp_buf);
1426 if (num_decimal_places > 0)
1427 strcat (buf, temp_buf);
1441 char *orig_bufp = bufp;
1442 const char *currency_symbol;
1449 gboolean print_sign = TRUE;
1450 gboolean is_shares = FALSE;
1451 gboolean print_absolute = FALSE;
1456 lc = gnc_localeconv();
1457 if (info.use_locale)
1460 cs_precedes = lc->n_cs_precedes;
1461 sep_by_space = lc->n_sep_by_space;
1465 cs_precedes = lc->p_cs_precedes;
1466 sep_by_space = lc->p_sep_by_space;
1471 sep_by_space = TRUE;
1474 if (info.commodity && info.use_symbol)
1481 cs_precedes = FALSE;
1482 sep_by_space = TRUE;
1486 currency_symbol =
"";
1490 sign = lc->negative_sign;
1491 sign_posn = lc->n_sign_posn;
1495 sign = lc->positive_sign;
1496 sign_posn = lc->p_sign_posn;
1503 if (print_sign && (sign_posn == 1))
1504 bufp = g_stpcpy(bufp, sign);
1510 if (print_sign && (sign_posn == 3))
1511 bufp = g_stpcpy(bufp, sign);
1513 if (info.use_symbol)
1515 bufp = g_stpcpy(bufp, currency_symbol);
1517 bufp = g_stpcpy(bufp,
" ");
1521 if (print_sign && (sign_posn == 4))
1522 bufp = g_stpcpy(bufp, sign);
1526 if (print_sign && (sign_posn == 0))
1528 bufp = g_stpcpy(bufp,
"(");
1529 print_absolute = TRUE;
1533 bufp += PrintAmountInternal(bufp,
1538 if (print_sign && (sign_posn == 0))
1539 bufp = g_stpcpy(bufp,
")");
1545 if (print_sign && (sign_posn == 3))
1546 bufp = g_stpcpy(bufp, sign);
1548 if (info.use_symbol)
1551 bufp = g_stpcpy(bufp,
" ");
1552 bufp = g_stpcpy(bufp, currency_symbol);
1556 if (print_sign && (sign_posn == 4))
1557 bufp = g_stpcpy(bufp, sign);
1561 if (print_sign && (sign_posn == 2))
1562 bufp = g_stpcpy(bufp, sign);
1565 return (bufp - orig_bufp);
1572 static char buf[1024];
1585 #define FUDGE .00001
1595 static gchar *small_numbers[] =
1603 "Zero",
"One",
"Two",
"Three",
"Four",
1604 "Five",
"Six",
"Seven",
"Eight",
"Nine",
1605 "Ten",
"Eleven",
"Twelve",
"Thirteen",
"Fourteen",
1606 "Fifteen",
"Sixteen",
"Seventeen",
"Eighteen",
"Nineteen",
1609 static gchar *medium_numbers[] =
1611 "Zero",
"Ten",
"Twenty",
"Thirty",
"Forty",
1612 "Fifty",
"Sixty",
"Seventy",
"Eighty",
"Ninety"
1614 static gchar *big_numbers[] =
1639 integer_to_words(gint64 val)
1641 gint64 log_val, pow_val, this_part;
1646 return g_strdup(
"zero");
1650 result = g_string_sized_new(100);
1654 log_val = log10(val) / 3 + FUDGE;
1655 pow_val = exp(log_val * 3 * G_LN10) + FUDGE;
1656 this_part = val / pow_val;
1657 val -= this_part * pow_val;
1658 tmp = integer_to_words(this_part);
1659 g_string_append_printf(result,
"%s %s ", tmp,
1660 gettext(big_numbers[log_val]));
1666 this_part = val / 100;
1667 val -= this_part * 100;
1668 g_string_append_printf(result,
"%s %s ",
1669 gettext(small_numbers[this_part]),
1670 gettext(big_numbers[0]));
1675 this_part = val / 10;
1676 val -= this_part * 10;
1677 g_string_append(result, gettext(medium_numbers[this_part]));
1678 g_string_append_c(result,
' ');
1685 g_string_append(result, gettext(small_numbers[this_part]));
1686 g_string_append_c(result,
' ');
1689 result = g_string_truncate(result, result->len - 1);
1690 return g_string_free(result, FALSE);
1694 static double round(
double x)
1697 return floor(x + 0.5);
1702 number_to_words(gdouble val, gint64 denom)
1704 gint64 int_part, frac_part;
1705 gchar *int_string, *nomin_string, *denom_string, *full_string;
1707 if (val < 0) val = -val;
1708 if (denom < 0) denom = -denom;
1710 int_part = floor(val);
1711 frac_part = round((val - int_part) * denom);
1713 int_string = integer_to_words(int_part);
1717 nomin_string = g_strdup_printf(
"%02" G_GINT64_FORMAT, frac_part);
1718 denom_string = g_strdup_printf(
"%" G_GINT64_FORMAT, denom);
1724 g_strdup_printf(
"%s and %s/%s",
1725 int_string, nomin_string, denom_string);
1727 g_free(nomin_string);
1728 g_free(denom_string);
1736 gnc_numeric_denom(val));
1740 printable_value (gdouble val, gint denom)
1745 num = gnc_numeric_create(round(val * denom), denom);
1746 info = gnc_share_print_info_places(log10(denom));
1747 return xaccPrintAmount (num, info);
1775 #define done_state(state) (((state) == DONE_ST) || ((state) == NO_NUM_ST))
1777 G_INLINE_FUNC
long long int multiplier (
int num_decimals);
1780 multiplier (
int num_decimals)
1782 switch (num_decimals)
1801 PERR(
"bad fraction length");
1802 g_assert_not_reached();
1810 xaccParseAmount (
const char * in_str, gboolean monetary,
gnc_numeric *result,
1813 struct lconv *lc = gnc_localeconv();
1815 gunichar negative_sign;
1816 gunichar decimal_point;
1817 gunichar group_separator;
1820 negative_sign = g_utf8_get_char(lc->negative_sign);
1823 group_separator = g_utf8_get_char(lc->mon_thousands_sep);
1824 decimal_point = g_utf8_get_char(lc->mon_decimal_point);
1825 group = lc->mon_grouping;
1829 group_separator = g_utf8_get_char(lc->thousands_sep);
1830 decimal_point = g_utf8_get_char(lc->decimal_point);
1831 group = lc->grouping;
1834 return xaccParseAmountExtended(in_str, monetary, negative_sign, decimal_point,
1835 group_separator, group, NULL, result, endstr);
1843 xaccParseAmountExtended (
const char * in_str, gboolean monetary,
1844 gunichar negative_sign, gunichar decimal_point,
1845 gunichar group_separator,
char *group,
char *ignore_list,
1848 gboolean is_negative;
1849 gboolean got_decimal;
1850 gboolean need_paren;
1852 long long int numer;
1853 long long int denom;
1854 int count, group_count;
1865 *endstr = (
char *) in_str;
1870 if (!g_utf8_validate(in_str, -1, &in))
1872 printf(
"Invalid utf8 string '%s'. Bad character at position %ld.\n",
1873 in_str, g_utf8_pointer_to_offset (in_str, in));
1879 out = out_str = g_new(gchar, strlen(in_str) + 128);
1884 is_negative = FALSE;
1885 got_decimal = FALSE;
1898 ParseState next_state = state;
1900 uc = g_utf8_get_char(in);
1903 if (ignore_list && uc && g_utf8_strchr(ignore_list, -1, uc) != NULL)
1905 in = g_utf8_next_char(in);
1915 if (g_unichar_isdigit(uc))
1917 count = g_unichar_to_utf8(uc, out);
1920 next_state = PRE_GROUP_ST;
1922 else if (uc == decimal_point)
1924 next_state = FRAC_ST;
1926 else if (g_unichar_isspace(uc))
1929 else if (uc == negative_sign)
1932 next_state = NEG_ST;
1938 next_state = NEG_ST;
1942 next_state = NO_NUM_ST;
1950 if (g_unichar_isdigit(uc))
1952 count = g_unichar_to_utf8(uc, out);
1954 next_state = PRE_GROUP_ST;
1956 else if (uc == decimal_point)
1958 next_state = FRAC_ST;
1960 else if (g_unichar_isspace(uc))
1965 next_state = NO_NUM_ST;
1973 if (g_unichar_isdigit(uc))
1975 count = g_unichar_to_utf8(uc, out);
1978 else if (uc == decimal_point)
1980 next_state = FRAC_ST;
1982 else if (uc == group_separator)
1984 next_state = START_GROUP_ST;
1986 else if (uc ==
')' && need_paren)
1988 next_state = DONE_ST;
1993 next_state = DONE_ST;
2003 case START_GROUP_ST:
2004 if (g_unichar_isdigit(uc))
2006 count = g_unichar_to_utf8(uc, out);
2010 next_state = IN_GROUP_ST;
2012 else if (uc == decimal_point)
2018 if (g_unichar_isspace(group_separator) &&
2019 g_unichar_isspace(decimal_point))
2020 next_state = DONE_ST;
2022 next_state = NO_NUM_ST;
2024 else if (uc ==
')' && need_paren)
2026 if (g_unichar_isspace(group_separator))
2028 next_state = DONE_ST;
2032 next_state = NO_NUM_ST;
2039 if (g_unichar_isspace(group_separator))
2040 next_state = DONE_ST;
2042 next_state = NO_NUM_ST;
2049 if (g_unichar_isdigit(uc))
2051 count = g_unichar_to_utf8(uc, out);
2056 else if (uc == decimal_point)
2058 next_state = FRAC_ST;
2060 else if (uc == group_separator)
2062 next_state = START_GROUP_ST;
2064 else if (uc ==
')' && need_paren)
2066 next_state = DONE_ST;
2071 next_state = DONE_ST;
2078 if (g_unichar_isdigit(uc))
2080 count = g_unichar_to_utf8(uc, out);
2083 else if (uc == decimal_point)
2088 if (g_unichar_isspace(decimal_point))
2089 next_state = DONE_ST;
2091 next_state = NO_NUM_ST;
2093 else if (uc == group_separator)
2098 if (g_unichar_isspace(group_separator))
2099 next_state = DONE_ST;
2101 next_state = NO_NUM_ST;
2103 else if (uc ==
')' && need_paren)
2105 next_state = DONE_ST;
2110 next_state = DONE_ST;
2117 g_assert_not_reached();
2122 if ((state == IN_GROUP_ST) && (next_state != IN_GROUP_ST))
2124 group_data = g_list_prepend(group_data, GINT_TO_POINTER(group_count));
2130 if (((next_state == FRAC_ST) && (state != FRAC_ST)) ||
2131 ((next_state == DONE_ST) && !got_decimal))
2135 if (*out_str !=
'\0' && sscanf(out_str, QOF_SCANF_LLD, &numer) < 1)
2137 next_state = NO_NUM_ST;
2139 else if (next_state == FRAC_ST)
2150 if (done_state (state))
2153 in = g_utf8_next_char(in);
2157 if (need_paren || (state == NO_NUM_ST))
2160 g_list_free(group_data);
2165 if (group_data != NULL)
2167 gboolean good_grouping = TRUE;
2172 for (node = group_data; group && node; node = node->next)
2175 if (*group != GPOINTER_TO_INT(node->data))
2177 good_grouping = FALSE;
2189 if (node->next != NULL)
2190 good_grouping = FALSE;
2202 g_list_free(group_data);
2215 if (got_decimal && (*out_str !=
'\0'))
2218 long long int fraction;
2220 len = strlen(out_str);
2228 if (sscanf (out_str, QOF_SCANF_LLD, &fraction) < 1)
2234 denom = multiplier(len);
2238 else if (monetary && auto_decimal_enabled && !got_decimal)
2240 if ((auto_decimal_places > 0) && (auto_decimal_places < 9))
2242 denom = multiplier(auto_decimal_places);
2254 *result = gnc_numeric_create (numer, denom);
2260 *endstr = (
char *) in;
2269 gnc_set_auto_decimal_enabled (gpointer settings, gchar *key, gpointer user_data)
2271 auto_decimal_enabled =
2277 gnc_set_auto_decimal_places (gpointer settings, gchar *key, gpointer user_data)
2279 auto_decimal_places =
2284 gnc_auto_decimal_init (
void)
2286 auto_decimal_enabled =
2288 auto_decimal_places =
2293 gnc_ui_util_init (
void)
2295 gnc_configure_account_separator ();
2296 gnc_auto_decimal_init();
2299 gnc_configure_account_separator, NULL);
2301 gnc_configure_reverse_balance, NULL);
2303 gnc_configure_reverse_balance, NULL);
2305 gnc_configure_reverse_balance, NULL);
2307 gnc_currency_changed_cb, NULL);
2309 gnc_currency_changed_cb, NULL);
2311 gnc_currency_changed_cb, NULL);
2313 gnc_currency_changed_cb, NULL);
2315 gnc_currency_changed_cb, NULL);
2317 gnc_currency_changed_cb, NULL);
2319 gnc_set_auto_decimal_enabled, NULL);
2321 gnc_set_auto_decimal_places, NULL);
void xaccAccountSetType(Account *acc, GNCAccountType tip)
void xaccSplitSetValue(Split *s, gnc_numeric amt)
#define xaccTransAppendSplit(t, s)
gnc_commodity_table * gnc_commodity_table_get_table(QofBook *book)
Transaction * xaccMallocTransaction(QofBook *book)
void xaccTransSetDatePostedSecsNormalized(Transaction *trans, time64 time)
int gnc_commodity_get_fraction(const gnc_commodity *cm)
void gnc_account_append_child(Account *new_parent, Account *child)
gchar * gnc_prefs_get_string(const gchar *group, const gchar *pref_name)
gint64 xaccAccountGetTaxUSCopyNumber(const Account *acc)
const char * gnc_commodity_get_mnemonic(const gnc_commodity *cm)
gulong gnc_prefs_register_cb(const char *group, const gchar *pref_name, gpointer func, gpointer user_data)
utility functions for the GnuCash UI
GNCAccountType xaccAccountGetType(const Account *acc)
int xaccAccountGetCommoditySCU(const Account *acc)
gnc_numeric gnc_numeric_neg(gnc_numeric a)
#define DEBUG(format, args...)
void gnc_features_set_used(QofBook *book, const gchar *feature)
void xaccTransSetDescription(Transaction *trans, const char *desc)
gnc_numeric gnc_numeric_add(gnc_numeric a, gnc_numeric b, gint64 denom, gint how)
gboolean gnc_numeric_to_decimal(gnc_numeric *a, guint8 *max_decimal_places)
void gnc_book_option_num_field_source_change_cb(gboolean num_action)
gboolean gnc_numeric_zero_p(gnc_numeric a)
gboolean gnc_prefs_set_string(const gchar *group, const gchar *pref_name, const gchar *value)
#define PERR(format, args...)
gnc_commodity * gnc_default_report_currency(void)
gint gnc_prefs_get_int(const gchar *group, const gchar *pref_name)
gboolean gnc_numeric_negative_p(gnc_numeric a)
gnc_numeric gnc_numeric_reduce(gnc_numeric n)
void xaccTransSetCurrency(Transaction *trans, gnc_commodity *curr)
gnc_commodity * gnc_default_currency(void)
Account * gnc_account_lookup_by_name(const Account *parent, const char *name)
#define PWARN(format, args...)
gchar * gnc_get_account_name_for_register(const Account *account)
gdouble gnc_numeric_to_double(gnc_numeric n)
void xaccSplitSetAmount(Split *s, gnc_numeric amt)
QofBook * qof_session_get_book(const QofSession *session)
gchar * gnc_account_get_full_name(const Account *account)
Account handling public routines.
gnc_numeric gnc_numeric_convert(gnc_numeric n, gint64 denom, gint how)
const char * gnc_numeric_errorCode_to_string(GNCNumericErrorCode error_code)
Account * gnc_account_lookup_by_full_name(const Account *any_acc, const gchar *name)
const char * gnc_commodity_get_nice_symbol(const gnc_commodity *cm)
const char * xaccAccountGetTaxUSCode(const Account *acc)
gnc_numeric gnc_numeric_abs(gnc_numeric a)
void xaccTransCommitEdit(Transaction *trans)
gboolean xaccAccountGetTaxRelated(const Account *acc)
void xaccTransBeginEdit(Transaction *trans)
All type declarations for the whole Gnucash engine.
int xaccSPrintAmount(char *bufp, gnc_numeric val, GNCPrintAmountInfo info)
gnc_commodity * gnc_account_get_currency_or_parent(const Account *account)
Split * xaccMallocSplit(QofBook *book)
Generic api to store and retrieve preferences.
gnc_numeric gnc_numeric_sub(gnc_numeric a, gnc_numeric b, gint64 denom, gint how)
GList * gnc_account_get_descendants(const Account *account)
gnc_commodity * gnc_account_or_default_currency(const Account *account, gboolean *currency_from_account_found)
GList * gnc_account_get_children(const Account *account)
void xaccAccountBeginEdit(Account *acc)
Account * xaccSplitGetAccount(const Split *s)
gnc_commodity * xaccAccountGetCommodity(const Account *acc)
#define xaccAccountInsertSplit(acc, s)
gboolean gnc_prefs_get_bool(const gchar *group, const gchar *pref_name)
Account * xaccMallocAccount(QofBook *book)
GNCNumericErrorCode gnc_numeric_check(gnc_numeric a)
Account * gnc_account_get_root(Account *acc)
const char * xaccAccountGetName(const Account *acc)
Account * gnc_account_lookup_for_register(const Account *base_account, const gchar *name)
API for Transactions and Splits (journal entries)
void xaccAccountCommitEdit(Account *acc)
void xaccAccountSetName(Account *acc, const char *str)
gboolean gnc_commodity_equiv(const gnc_commodity *a, const gnc_commodity *b)
gboolean gnc_commodity_is_iso(const gnc_commodity *cm)
const gchar * QofLogModule
void xaccAccountSetCommodity(Account *acc, gnc_commodity *com)
Utility functions for file access.