GnuCash  4.11-354-g0815ab64c1
Files | Data Structures | Macros | Typedefs | Enumerations | Functions
Utility functions for the GnuCash GUI

Files

file  gnc-ui-util.h
 utility functions for the GnuCash UI
 

Data Structures

struct  GNCPrintAmountInfo
 

Macros

#define GNC_PREFS_GROUP_OPEN_SAVE   "dialogs.open-save"
 
#define GNC_PREFS_GROUP_EXPORT   "dialogs.export-accounts"
 
#define GNC_PREFS_GROUP_REPORT   "dialogs.report"
 
#define GNC_PREF_AUTO_DECIMAL_POINT   "auto-decimal-point"
 
#define GNC_PREF_AUTO_DECIMAL_PLACES   "auto-decimal-places"
 
#define WLINK   'w'
 
#define FLINK   'f'
 

Typedefs

typedef QofSession *(* QofSessionCB) (void)
 

Enumerations

enum  GNCEquityType { EQUITY_OPENING_BALANCE, EQUITY_RETAINED_EARNINGS, NUM_EQUITY_TYPES }
 

Functions

gchar * gnc_normalize_account_separator (const gchar *separator)
 
gboolean gnc_reverse_balance (const Account *account)
 
void gnc_set_use_equity_type_opening_balance_account (QofBook *book)
 
gboolean gnc_using_equity_type_opening_balance_account (QofBook *book)
 
gchar * gnc_get_default_directory (const gchar *section)
 
void gnc_set_default_directory (const gchar *section, const gchar *directory)
 
QofBook * gnc_get_current_book (void)
 
gboolean gnc_is_new_book (void)
 
void gnc_set_current_book_tax_name_type (gboolean name_changed, const gchar *tax_name, gboolean type_changed, const gchar *tax_type)
 
const gchar * gnc_get_current_book_tax_name (void)
 
const gchar * gnc_get_current_book_tax_type (void)
 
void gnc_book_option_num_field_source_change_cb (gboolean num_action)
 Calls gnc_book_option_num_field_source_change to initiate registered callbacks when num_field_source book option changes so that registers/reports can update themselves; sets feature flag.
 
Accountgnc_get_current_root_account (void)
 
gnc_commodity_table * gnc_get_current_commodities (void)
 
gchar * 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 general/register/show_leaf_account_names. More...
 
Accountgnc_account_lookup_for_register (const Account *base_account, const gchar *name)
 Retrieve the account matching the given name starting from the descendants of base_account. More...
 
gchar * 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. More...
 
char * gnc_ui_account_get_tax_info_string (const Account *account)
 
char * gnc_ui_account_get_tax_info_sub_acct_string (const Account *account)
 
const char * gnc_get_reconcile_str (char reconciled_flag)
 
const char * gnc_get_reconcile_valid_flags (void)
 
const char * gnc_get_reconcile_flag_order (void)
 
const char * gnc_get_doclink_valid_flags (void)
 Get a string containing documentation link valid flags. More...
 
const char * gnc_get_doclink_flag_order (void)
 Get a string containing document link flag order. More...
 
const char * gnc_get_doclink_str (char link_flag)
 Get a string representing the document link type. More...
 
Accountgnc_find_or_create_equity_account (Account *root, GNCEquityType equity_type, gnc_commodity *currency)
 
gboolean gnc_account_create_opening_balance (Account *account, gnc_numeric balance, time64 date, QofBook *book)
 
gnc_commodity * gnc_locale_default_currency_nodefault (void)
 Returns the default currency of the current locale, or NULL if no sensible currency could be identified from the locale. More...
 
gnc_commodity * gnc_locale_default_currency (void)
 Returns the default currency of the current locale. More...
 
gnc_commodity * gnc_default_currency (void)
 Return the default currency set by the user. More...
 
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. More...
 
gnc_commodity * gnc_default_report_currency (void)
 Return the default currency for use in reports, as set by the user. More...
 
GNCPrintAmountInfo gnc_default_print_info (gboolean use_symbol)
 
GNCPrintAmountInfo gnc_commodity_print_info (const gnc_commodity *commodity, gboolean use_symbol)
 
GNCPrintAmountInfo gnc_account_print_info (const Account *account, gboolean use_symbol)
 
GNCPrintAmountInfo gnc_split_amount_print_info (Split *split, gboolean use_symbol)
 
GNCPrintAmountInfo gnc_price_print_info (const gnc_commodity *curr, gboolean use_symbol)
 
GNCPrintAmountInfo gnc_share_print_info_places (int decplaces)
 
GNCPrintAmountInfo gnc_default_share_print_info (void)
 
GNCPrintAmountInfo gnc_default_price_print_info (const gnc_commodity *curr)
 
GNCPrintAmountInfo gnc_integral_print_info (void)
 
const char * xaccPrintAmount (gnc_numeric val, GNCPrintAmountInfo info)
 Make a string representation of a gnc_numeric. More...
 
int xaccSPrintAmount (char *buf, gnc_numeric val, GNCPrintAmountInfo info)
 Make a string representation of a gnc_numeric. More...
 
const gchar * printable_value (gdouble val, gint denom)
 
gchar * number_to_words (gdouble val, gint64 denom)
 
gchar * numeric_to_words (gnc_numeric val)
 
gboolean xaccParseAmount (const char *in_str, gboolean monetary, gnc_numeric *result, char **endstr)
 Parses in_str to obtain a numeric result. More...
 
gboolean xaccParseAmountPosSign (const char *in_str, gboolean monetary, gnc_numeric *result, char **endstr, gboolean skip)
 Parses in_str to a gnc_numeric, with a flag to indicate whether the locale's positive sign (or in absence the '+') character is ignored. More...
 
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. More...
 
const char * gnc_print_amount_with_bidi_ltr_isolate (gnc_numeric val, GNCPrintAmountInfo info)
 Make a string representation of a gnc_numeric. More...
 
gchar * gnc_wrap_text_with_bidi_ltr_isolate (const char *text)
 This function helps with GTK's use of 'Unicode Bidirectional Text Algorithm'. More...
 
void gnc_ui_util_init (void)
 
void gnc_ui_util_remove_registered_prefs (void)
 
gchar * gnc_filter_text_for_control_chars (const gchar *incoming_text)
 Returns the incoming text removed of control characters. More...
 
void gnc_filter_text_set_cursor_position (const gchar *incoming_text, const gchar *symbol, gint *cursor_position)
 Updates cursor_position after removal of currency symbols. More...
 
gchar * gnc_filter_text_for_currency_symbol (const gchar *incoming_text, const gchar *symbol)
 Returns the incoming text removed of a currency symbol. More...
 
gchar * gnc_filter_text_for_currency_commodity (const gnc_commodity *comm, const gchar *incoming_text, const gchar **symbol)
 Returns the incoming text removed of currency symbol. More...
 

Detailed Description

Function Documentation

◆ gnc_account_lookup_for_register()

Account* gnc_account_lookup_for_register ( const Account base_account,
const gchar *  name 
)

Retrieve the account matching the given name starting from the descendants of base_account.

name is either considered to be the name of the leaf in the account tree or to be the full account path, depending on the configuration parameter general.register/show_leaf_account_names.

Parameters
base_accountThe account to start the search at.
nameThe name to search for.
Returns
A pointer to the account, or NULL if the account was not found.

◆ gnc_account_or_default_currency()

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.

The gnc_commodity is taken either from the current account, or from the next parent account that has a gnc_commodity that is a currency, or from gnc_default_currency().

If the given account or any of its parent account have a commodity that is a currency, it is returned and the gboolean currency_from_account_found is set to TRUE (if non-NULL). If neither this account nor any of its parent accounts have such a commodity, gnc_default_currency() is returned and the gboolean currency_from_account_found is set to FALSE (if non-NULL). This can be used to show an appropriate warning message.

If account is NULL, gnc_default_currency() is returned and currency_from_account_found is set to FALSE.

Parameters
accountThe account where the currency should be looked up. May be NULL.
currency_from_account_foundA gboolean pointer that takes the output argument of whether the returned currency was found in the account. May be NULL.
Returns
A currency pointer (and never NULL).

Definition at line 1066 of file gnc-ui-util.c.

1067 {
1068  gnc_commodity *currency;
1069  if (!account)
1070  {
1071  if (currency_from_account_found)
1072  *currency_from_account_found = FALSE;
1073  return gnc_default_currency();
1074  }
1075 
1076  currency = gnc_account_get_currency_or_parent(account);
1077  if (currency)
1078  {
1079  if (currency_from_account_found)
1080  *currency_from_account_found = TRUE;
1081  }
1082  else
1083  {
1084  if (currency_from_account_found)
1085  *currency_from_account_found = FALSE;
1086  currency = gnc_default_currency();
1087  }
1088  return currency;
1089 }
gnc_commodity * gnc_default_currency(void)
Return the default currency set by the user.
Definition: gnc-ui-util.c:1061
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.
Definition: Account.cpp:3455

◆ gnc_default_currency()

gnc_commodity* gnc_default_currency ( void  )

Return the default currency set by the user.

If the user's preference is invalid, then this routine will return the default currency for the user's locale.

Returns
A pointer to a currency.

Definition at line 1061 of file gnc-ui-util.c.

1062 {
1063  return gnc_default_currency_common (user_default_currency, GNC_PREFS_GROUP_GENERAL);
1064 }

◆ gnc_default_report_currency()

gnc_commodity* gnc_default_report_currency ( void  )

Return the default currency for use in reports, as set by the user.

If the user's preference is invalid, then this routine will return the default currency for the user's locale.

Returns
A pointer to a currency.

Definition at line 1094 of file gnc-ui-util.c.

1095 {
1096  return gnc_default_currency_common (user_report_currency, GNC_PREFS_GROUP_GENERAL_REPORT);
1097 }

◆ gnc_filter_text_for_control_chars()

gchar* gnc_filter_text_for_control_chars ( const gchar *  incoming_text)

Returns the incoming text removed of control characters.

Parameters
incoming_textThe text to filter
Returns
The incoming text filtered of control characters to be freed by the caller.

Definition at line 2460 of file gnc-ui-util.c.

2461 {
2462  gchar *normal_text, *nt;
2463  GString *filtered;
2464  gboolean cntrl = FALSE;
2465  gboolean text_found = FALSE;
2466 
2467  if (!text)
2468  return NULL;
2469 
2470  if (!g_utf8_validate (text, -1, NULL))
2471  return NULL;
2472 
2473  normal_text = g_utf8_normalize (text, -1, G_NORMALIZE_ALL_COMPOSE);
2474 
2475  filtered = g_string_sized_new (strlen (normal_text) + 1);
2476 
2477  nt = normal_text;
2478 
2479  while (*nt)
2480  {
2481  gunichar uc = g_utf8_get_char (nt);
2482 
2483  // check for starting with control characters
2484  if (unichar_is_cntrl (uc) && !text_found)
2485  {
2486  nt = g_utf8_next_char (nt);
2487  continue;
2488  }
2489  // check for alpha, num and punctuation
2490  if (!unichar_is_cntrl (uc))
2491  {
2492  filtered = g_string_append_unichar (filtered, uc);
2493  text_found = TRUE;
2494  }
2495  // check for control characters after text
2496  if (unichar_is_cntrl (uc))
2497  cntrl = TRUE;
2498 
2499  nt = g_utf8_next_char (nt);
2500 
2501  if (cntrl) // if control characters in text replace with space
2502  {
2503  gunichar uc2 = g_utf8_get_char (nt);
2504 
2505  if (!unichar_is_cntrl (uc2))
2506  filtered = g_string_append_unichar (filtered, ' ');
2507  }
2508  cntrl = FALSE;
2509  }
2510  g_free (normal_text);
2511  return g_string_free (filtered, FALSE);
2512 }

◆ gnc_filter_text_for_currency_commodity()

gchar* gnc_filter_text_for_currency_commodity ( const gnc_commodity *  comm,
const gchar *  incoming_text,
const gchar **  symbol 
)

Returns the incoming text removed of currency symbol.

Parameters
commcommodity of entry if known
incoming_textThe text to filter
symbolreturn the symbol used
Returns
The incoming text with symbol removed to be freed by the caller

Definition at line 2571 of file gnc-ui-util.c.

2574 {
2575  if (!incoming_text)
2576  {
2577  *symbol = NULL;
2578  return NULL;
2579  }
2580 
2581  if (!gnc_commodity_is_currency (comm))
2582  {
2583  *symbol = NULL;
2584  return g_strdup (incoming_text);
2585  }
2586 
2587  if (comm)
2588  *symbol = gnc_commodity_get_nice_symbol (comm);
2589  else
2591 
2592  return gnc_filter_text_for_currency_symbol (incoming_text, *symbol);
2593 }
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...
gnc_commodity * gnc_default_currency(void)
Return the default currency set by the user.
Definition: gnc-ui-util.c:1061
const char * gnc_commodity_get_nice_symbol(const gnc_commodity *cm)
Retrieve a symbol for the specified commodity, suitable for display to the user.
gchar * gnc_filter_text_for_currency_symbol(const gchar *incoming_text, const gchar *symbol)
Returns the incoming text removed of a currency symbol.
Definition: gnc-ui-util.c:2547

◆ gnc_filter_text_for_currency_symbol()

gchar* gnc_filter_text_for_currency_symbol ( const gchar *  incoming_text,
const gchar *  symbol 
)

Returns the incoming text removed of a currency symbol.

Parameters
incoming_textThe text to filter
symbolto remove
cursor_positionthe position of cursor in the incoming text
Returns
The incoming text with symbol removed to be freed by the caller

Definition at line 2547 of file gnc-ui-util.c.

2549 {
2550  gchar *ret_text = NULL;
2551  gchar **split;
2552 
2553  if (!incoming_text)
2554  return NULL;
2555 
2556  if (!symbol)
2557  return g_strdup (incoming_text);
2558 
2559  if (g_strrstr (incoming_text, symbol) == NULL)
2560  return g_strdup (incoming_text);
2561 
2562  split = g_strsplit (incoming_text, symbol, -1);
2563 
2564  ret_text = g_strjoinv (NULL, split);
2565 
2566  g_strfreev (split);
2567  return ret_text;
2568 }

◆ gnc_filter_text_set_cursor_position()

void gnc_filter_text_set_cursor_position ( const gchar *  incoming_text,
const gchar *  symbol,
gint *  cursor_position 
)

Updates cursor_position after removal of currency symbols.

Parameters
incoming_textThe text to filter
symbolto remove
cursor_positionthe position of cursor in the incoming text
Returns
nothing

Definition at line 2515 of file gnc-ui-util.c.

2518 {
2519  gint text_len;
2520  gint num = 0;
2521 
2522  if (*cursor_position == 0)
2523  return;
2524 
2525  if (!incoming_text || !symbol)
2526  return;
2527 
2528  if (g_strrstr (incoming_text, symbol) == NULL)
2529  return;
2530 
2531  text_len = g_utf8_strlen (incoming_text, -1);
2532 
2533  for (gint x = 0; x < text_len; x++)
2534  {
2535  gchar *temp = g_utf8_offset_to_pointer (incoming_text, x);
2536 
2537  if (g_str_has_prefix (temp, symbol))
2538  num++;
2539 
2540  if (g_strrstr (temp, symbol) == NULL)
2541  break;
2542  }
2543  *cursor_position = *cursor_position - (num * g_utf8_strlen (symbol, -1));
2544 }

◆ gnc_get_account_name_for_register()

gchar* 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 general/register/show_leaf_account_names.

Parameters
accountThe account to retrieve the name for.
Returns
A newly allocated string.

Definition at line 448 of file gnc-ui-util.c.

449 {
450  gboolean show_leaf_accounts;
451  show_leaf_accounts = gnc_prefs_get_bool(GNC_PREFS_GROUP_GENERAL_REGISTER,
452  GNC_PREF_SHOW_LEAF_ACCT_NAMES);
453 
454  return gnc_get_account_name_for_split_register(account, show_leaf_accounts);
455 }
gchar * 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.
Definition: gnc-ui-util.c:439
gboolean gnc_prefs_get_bool(const gchar *group, const gchar *pref_name)
Get a boolean value from the preferences backend.

◆ gnc_get_account_name_for_split_register()

gchar* 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.

Parameters
accountThe account to retrieve the name for.
show_leaf_accountsWhether the full name will be returned.
Returns
A newly allocated string.

Definition at line 439 of file gnc-ui-util.c.

440 {
441  if (show_leaf_accounts)
442  return g_strdup (xaccAccountGetName (account));
443  else
444  return gnc_account_get_full_name (account);
445 }
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...
Definition: Account.cpp:3308
const char * xaccAccountGetName(const Account *acc)
Get the account&#39;s name.
Definition: Account.cpp:3301

◆ gnc_get_doclink_flag_order()

const char* gnc_get_doclink_flag_order ( void  )

Get a string containing document link flag order.

Returns
a string containing the document link flag change order

Definition at line 807 of file gnc-ui-util.c.

808 {
809  static const char flags[] = { FLINK, WLINK, ' ', 0 };
810  return flags;
811 }

◆ gnc_get_doclink_str()

const char* gnc_get_doclink_str ( char  link_flag)

Get a string representing the document link type.

Parameters
link_flagThe flag to convert into a string
Returns
the i18n'd doclink string

Definition at line 783 of file gnc-ui-util.c.

784 {
785  switch (link_flag)
786  {
787  case WLINK:
788  return C_("Document Link flag for 'web'", "w");
789  case FLINK:
790  return C_("Document Link flag for 'file'", "f");
791  case ' ':
792  return " ";
793  default:
794  PERR("Bad link flag");
795  return NULL;
796  }
797 }
#define PERR(format, args...)
Log a serious error.
Definition: qoflog.h:244

◆ gnc_get_doclink_valid_flags()

const char* gnc_get_doclink_valid_flags ( void  )

Get a string containing documentation link valid flags.

Returns
a string containing the list of valid link_flags

Definition at line 800 of file gnc-ui-util.c.

801 {
802  static const char flags[] = { FLINK, WLINK, ' ', 0 };
803  return flags;
804 }

◆ gnc_locale_default_currency()

gnc_commodity* gnc_locale_default_currency ( void  )

Returns the default currency of the current locale.

WATCH OUT: If no currency could be identified from the locale, this one returns "USD", but this will have nothing to do with the actual locale.

Definition at line 1018 of file gnc-ui-util.c.

1019 {
1020  gnc_commodity * currency = gnc_locale_default_currency_nodefault ();
1021 
1022  return (currency ? currency :
1023  gnc_commodity_table_lookup (gnc_get_current_commodities (),
1024  GNC_COMMODITY_NS_CURRENCY, "USD"));
1025 }
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...
Definition: gnc-ui-util.c:1003

◆ gnc_locale_default_currency_nodefault()

gnc_commodity* gnc_locale_default_currency_nodefault ( void  )

Returns the default currency of the current locale, or NULL if no sensible currency could be identified from the locale.

Definition at line 1003 of file gnc-ui-util.c.

1004 {
1005  gnc_commodity * currency;
1006  gnc_commodity_table *table;
1007  const char *code;
1008 
1009  table = gnc_get_current_commodities ();
1010  code = gnc_locale_default_iso_currency_code ();
1011 
1012  currency = gnc_commodity_table_lookup (table, GNC_COMMODITY_NS_CURRENCY, code);
1013 
1014  return (currency ? currency : NULL);
1015 }

◆ gnc_print_amount_with_bidi_ltr_isolate()

const char* gnc_print_amount_with_bidi_ltr_isolate ( gnc_numeric  val,
GNCPrintAmountInfo  info 
)

Make a string representation of a gnc_numeric.

Warning, the gnc_numeric is not checked for validity and the returned char* may point to random garbage.

This is the same as xaccPrintAmount but wraps the output with BiDi left to right isolate if a symbol is displayed.

Definition at line 1736 of file gnc-ui-util.c.

1737 {
1738  /* hack alert -- this is not thread safe ... */
1739  static char buf[BUFLEN];
1740  static const char ltr_isolate[] = { 0xe2, 0x81, 0xa6 };
1741  static const char ltr_pop_isolate[] = { 0xe2, 0x81, 0xa9 };
1742  size_t offset = info.use_symbol ? 3 : 0;
1743 
1744  memset (buf, 0, BUFLEN);
1745  if (!xaccSPrintAmount (buf + offset, val, info))
1746  {
1747  buf[0] = '\0';
1748  return buf;
1749  };
1750 
1751  if (!info.use_symbol)
1752  return buf;
1753 
1754  memcpy (buf, ltr_isolate, 3);
1755 
1756  if (buf[BUFLEN - 4] == '\0')
1757  {
1758  size_t length = strlen (buf);
1759  memcpy (buf + length, ltr_pop_isolate, 3);
1760  }
1761  else
1762  {
1763  buf[BUFLEN - 1] = '\0';
1764  memcpy (buf + BUFLEN - 4, ltr_pop_isolate, 3);
1765 
1766  PWARN("buffer length %d exceeded, string truncated was %s", BUFLEN, buf);
1767  }
1768  /* its OK to return buf, since we declared it static
1769  and is immediately g_strdup'd */
1770  return buf;
1771 }
#define PWARN(format, args...)
Log a warning.
Definition: qoflog.h:250
int xaccSPrintAmount(char *bufp, gnc_numeric val, GNCPrintAmountInfo info)
Make a string representation of a gnc_numeric.
Definition: gnc-ui-util.c:1592

◆ gnc_wrap_text_with_bidi_ltr_isolate()

gchar* gnc_wrap_text_with_bidi_ltr_isolate ( const char *  text)

This function helps with GTK's use of 'Unicode Bidirectional Text Algorithm'.

To keep the format of the text, this function wraps the text with a BiDi isolate charatcter and a BiDi closing character.

This helps with monetary values in RTL languages that display the currency symbol.

◆ xaccParseAmount()

gboolean xaccParseAmount ( const char *  in_str,
gboolean  monetary,
gnc_numeric *  result,
char **  endstr 
)

Parses in_str to obtain a numeric result.

The routine will parse as much of in_str as it can to obtain a single number. The number is parsed using the current locale information and the 'monetary' flag. The routine will return TRUE if it successfully parsed a number and FALSE otherwise. If TRUE is returned and result is non-NULL, the value of the parsed number is stored in *result. If FALSE is returned, *result is unchanged. If TRUE is returned and endstr is non-NULL, the location of the first character in in_str not used by the parser will be returned in *endstr. If FALSE is returned and endstr is non-NULL, *endstr will point to in_str.

Definition at line 2018 of file gnc-ui-util.c.

2020 {
2021  return xaccParseAmountPosSign (in_str, monetary, result, endstr, FALSE);
2022 }
gboolean xaccParseAmountPosSign(const char *in_str, gboolean monetary, gnc_numeric *result, char **endstr, gboolean skip)
Parses in_str to a gnc_numeric, with a flag to indicate whether the locale&#39;s positive sign (or in abs...
Definition: gnc-ui-util.c:2025

◆ xaccParseAmountExtended()

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.

The caller must provide all the locale-specific information.

ignore_list is a list of characters that are completely ignored while processing the input string. If ignore_list is NULL, nothing is ignored.

Definition at line 2064 of file gnc-ui-util.c.

2068 {
2069  gboolean is_negative;
2070  gboolean got_decimal;
2071  gboolean need_paren;
2072  long long int numer;
2073  long long int denom;
2074  int count;
2075 
2076  ParseState state;
2077 
2078  const gchar *in;
2079  gunichar uc;
2080  gchar *out_str;
2081  gchar *out;
2082 
2083  /* Initialize *endstr to in_str */
2084  if (endstr != NULL)
2085  *endstr = (char *) in_str;
2086 
2087  if (in_str == NULL)
2088  return FALSE;
2089 
2090  if (!g_utf8_validate(in_str, -1, &in))
2091  {
2092  printf("Invalid utf8 string '%s'. Bad character at position %ld.\n",
2093  in_str, g_utf8_pointer_to_offset (in_str, in));
2094  return FALSE;
2095  }
2096 
2097  /* 'out_str' will be used to store digits for numeric conversion.
2098  * 'out' will be used to traverse out_str. */
2099  out = out_str = g_new(gchar, strlen(in_str) + 128);
2100 
2101  /* 'in' is used to traverse 'in_str'. */
2102  in = in_str;
2103 
2104  is_negative = FALSE;
2105  got_decimal = FALSE;
2106  need_paren = FALSE;
2107  numer = 0;
2108  denom = 1;
2109 
2110  /* Initialize the state machine */
2111  state = START_ST;
2112 
2113  /* This while loop implements a state machine for parsing numbers. */
2114  while (TRUE)
2115  {
2116  ParseState next_state = state;
2117 
2118  uc = g_utf8_get_char(in);
2119 
2120  /* Ignore anything in the 'ignore list' */
2121  if (ignore_list && uc && g_utf8_strchr(ignore_list, -1, uc) != NULL)
2122  {
2123  in = g_utf8_next_char(in);
2124  continue;
2125  }
2126 
2127  /* Note we never need to check for the end of 'in_str' explicitly.
2128  * The 'else' clauses on all the state transitions will handle that. */
2129  switch (state)
2130  {
2131  /* START_ST means we have parsed 0 or more whitespace characters */
2132  case START_ST:
2133  if (g_unichar_isdigit(uc))
2134  {
2135  count = g_unichar_to_utf8(uc, out);
2136  out += count; /* we record the digits themselves in out_str
2137  * for later conversion by libc routines */
2138  next_state = NUMER_ST;
2139  }
2140  else if (uc == decimal_point)
2141  {
2142  next_state = FRAC_ST;
2143  }
2144  else if (g_unichar_isspace(uc))
2145  {
2146  }
2147  else if (uc == negative_sign)
2148  {
2149  is_negative = TRUE;
2150  next_state = NEG_ST;
2151  }
2152  else if (uc == '(')
2153  {
2154  is_negative = TRUE;
2155  need_paren = TRUE;
2156  next_state = NEG_ST;
2157  }
2158  else
2159  {
2160  next_state = NO_NUM_ST;
2161  }
2162 
2163  break;
2164 
2165  /* NEG_ST means we have just parsed a negative sign. For now,
2166  * we only recognize formats where the negative sign comes first. */
2167  case NEG_ST:
2168  if (g_unichar_isdigit(uc))
2169  {
2170  count = g_unichar_to_utf8(uc, out);
2171  out += count;
2172  next_state = NUMER_ST;
2173  }
2174  else if (uc == decimal_point)
2175  {
2176  next_state = FRAC_ST;
2177  }
2178  else if (g_unichar_isspace(uc))
2179  {
2180  }
2181  else
2182  {
2183  next_state = NO_NUM_ST;
2184  }
2185 
2186  break;
2187 
2188  /* NUMER_ST means we have started parsing the number, but
2189  * have not encountered a decimal separator. */
2190  case NUMER_ST:
2191  if (g_unichar_isdigit(uc))
2192  {
2193  count = g_unichar_to_utf8(uc, out);
2194  out += count;
2195  }
2196  else if (uc == decimal_point)
2197  {
2198  next_state = FRAC_ST;
2199  }
2200  else if (uc == group_separator)
2201  {
2202  ; //ignore it
2203  }
2204  else if (uc == ')' && need_paren)
2205  {
2206  next_state = DONE_ST;
2207  need_paren = FALSE;
2208  }
2209  else
2210  {
2211  next_state = DONE_ST;
2212  }
2213 
2214  break;
2215 
2216  /* FRAC_ST means we are now parsing fractional digits. */
2217  case FRAC_ST:
2218  if (g_unichar_isdigit(uc))
2219  {
2220  count = g_unichar_to_utf8(uc, out);
2221  out += count;
2222  }
2223  else if (uc == decimal_point)
2224  {
2225  /* If a subsequent decimal point is also whitespace,
2226  * assume it was intended as such and stop parsing.
2227  * Otherwise, there is a problem. */
2228  if (g_unichar_isspace(decimal_point))
2229  next_state = DONE_ST;
2230  else
2231  next_state = NO_NUM_ST;
2232  }
2233  else if (uc == group_separator)
2234  {
2235  /* If a subsequent group separator is also whitespace,
2236  * assume it was intended as such and stop parsing.
2237  * Otherwise ignore it. */
2238  if (g_unichar_isspace(group_separator))
2239  next_state = DONE_ST;
2240  }
2241  else if (uc == ')' && need_paren)
2242  {
2243  next_state = DONE_ST;
2244  need_paren = FALSE;
2245  }
2246  else
2247  {
2248  next_state = DONE_ST;
2249  }
2250 
2251  break;
2252 
2253  default:
2254  PERR("bad state");
2255  g_assert_not_reached();
2256  break;
2257  }
2258 
2259  /* If we're moving into the FRAC_ST or out of the machine
2260  * without going through FRAC_ST, record the integral value. */
2261  if (((next_state == FRAC_ST) && (state != FRAC_ST)) ||
2262  ((next_state == DONE_ST) && !got_decimal))
2263  {
2264  *out = '\0';
2265 
2266  if (*out_str != '\0' && sscanf(out_str, QOF_SCANF_LLD, &numer) < 1)
2267  {
2268  next_state = NO_NUM_ST;
2269  }
2270  else if (next_state == FRAC_ST)
2271  {
2272  /* reset the out pointer to record the fraction */
2273  out = out_str;
2274  *out = '\0';
2275 
2276  got_decimal = TRUE;
2277  }
2278  }
2279 
2280  state = next_state;
2281  if (done_state (state))
2282  break;
2283 
2284  in = g_utf8_next_char(in);
2285  }
2286 
2287  /* If there was an error, just quit */
2288  if (need_paren || (state == NO_NUM_ST))
2289  {
2290  g_free(out_str);
2291  return FALSE;
2292  }
2293 
2294  /* Cap the end of the fraction string, if any */
2295  *out = '\0';
2296 
2297  /* Add in fractional value */
2298  if (got_decimal && (*out_str != '\0'))
2299  {
2300  size_t len;
2301  long long int fraction;
2302 
2303  len = strlen(out_str);
2304 
2305  if (len > 12)
2306  {
2307  out_str[12] = '\0';
2308  len = 12;
2309  }
2310 
2311  if (sscanf (out_str, QOF_SCANF_LLD, &fraction) < 1)
2312  {
2313  g_free(out_str);
2314  return FALSE;
2315  }
2316 
2317  denom = multiplier(len);
2318  numer *= denom;
2319  numer += fraction;
2320  }
2321  else if (monetary && auto_decimal_enabled && !got_decimal)
2322  {
2323  if ((auto_decimal_places > 0) && (auto_decimal_places <= 12))
2324  {
2325  denom = multiplier(auto_decimal_places);
2326 
2327  /* No need to multiply numer by denom at this point,
2328  * since by specifying the auto decimal places the
2329  * user has effectively determined the scaling factor
2330  * for the numerator they entered.
2331  */
2332  }
2333  }
2334 
2335  if (result != NULL)
2336  {
2337  *result = gnc_numeric_create (numer, denom);
2338  if (is_negative)
2339  *result = gnc_numeric_neg (*result);
2340  }
2341 
2342  if (endstr != NULL)
2343  *endstr = (char *) in;
2344 
2345  g_free (out_str);
2346 
2347  return TRUE;
2348 }
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 PERR(format, args...)
Log a serious error.
Definition: qoflog.h:244

◆ xaccParseAmountPosSign()

gboolean xaccParseAmountPosSign ( const char *  in_str,
gboolean  monetary,
gnc_numeric *  result,
char **  endstr,
gboolean  skip 
)

Parses in_str to a gnc_numeric, with a flag to indicate whether the locale's positive sign (or in absence the '+') character is ignored.

Setting skip to TRUE will cause the function to ignore any positive sign. Setting it to FALSE, and positive signs will be treated as unrecognized characters. xaccParseAmount will run as if skip is FALSE for compatibility reasons (gnc-expression-parser depends on this behaviour).

Definition at line 2025 of file gnc-ui-util.c.

2027 {
2028  struct lconv *lc = gnc_localeconv();
2029 
2030  gunichar negative_sign;
2031  gunichar decimal_point;
2032  gunichar group_separator;
2033  gchar *ignore = NULL;
2034  char *plus_sign = "+";
2035 
2036  negative_sign = g_utf8_get_char(lc->negative_sign);
2037  if (monetary)
2038  {
2039  group_separator = g_utf8_get_char(lc->mon_thousands_sep);
2040  decimal_point = g_utf8_get_char(lc->mon_decimal_point);
2041  }
2042  else
2043  {
2044  group_separator = g_utf8_get_char(lc->thousands_sep);
2045  decimal_point = g_utf8_get_char(lc->decimal_point);
2046  }
2047 
2048  if (skip)
2049  {
2050  /* We want the locale's positive sign to be ignored.
2051  * If the locale doesn't specify one, we assume "+" as
2052  * an optional positive sign and ignore that */
2053  ignore = lc->positive_sign;
2054  if (!ignore || !*ignore)
2055  ignore = plus_sign;
2056  }
2057 
2058  return xaccParseAmountExtended(in_str, monetary, negative_sign,
2059  decimal_point, group_separator,
2060  ignore, result, endstr);
2061 }
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.
Definition: gnc-ui-util.c:2064

◆ xaccPrintAmount()

const char* xaccPrintAmount ( gnc_numeric  val,
GNCPrintAmountInfo  info 
)

Make a string representation of a gnc_numeric.

Warning, the gnc_numeric is not checked for validity and the returned char* may point to random garbage.

Definition at line 1723 of file gnc-ui-util.c.

1724 {
1725  /* hack alert -- this is not thread safe ... */
1726  static char buf[BUFLEN];
1727 
1728  if (!xaccSPrintAmount (buf, val, info))
1729  buf[0] = '\0';
1730 
1731  /* its OK to return buf, since we declared it static */
1732  return buf;
1733 }
int xaccSPrintAmount(char *bufp, gnc_numeric val, GNCPrintAmountInfo info)
Make a string representation of a gnc_numeric.
Definition: gnc-ui-util.c:1592

◆ xaccSPrintAmount()

int xaccSPrintAmount ( char *  bufp,
gnc_numeric  val,
GNCPrintAmountInfo  info 
)

Make a string representation of a gnc_numeric.

Warning, the gnc_numeric is not checked for validity and the contents of the buffer will be unchanged. It is up to the calling function to ensure that buf is large enough for the results.

Parameters
bufpShould be at least 64 chars.

Definition at line 1592 of file gnc-ui-util.c.

1593 {
1594  struct lconv *lc;
1595 
1596  char *orig_bufp = bufp;
1597  const char *currency_symbol;
1598  const char *sign;
1599 
1600  char cs_precedes;
1601  char sep_by_space;
1602  char sign_posn;
1603 
1604  gboolean print_sign = TRUE;
1605  gboolean print_absolute = FALSE;
1606 
1607  if (!bufp)
1608  return 0;
1609 
1610  lc = gnc_localeconv();
1611  if (info.use_locale)
1612  if (gnc_numeric_negative_p (val))
1613  {
1614  cs_precedes = lc->n_cs_precedes;
1615  sep_by_space = lc->n_sep_by_space;
1616  }
1617  else
1618  {
1619  cs_precedes = lc->p_cs_precedes;
1620  sep_by_space = lc->p_sep_by_space;
1621  }
1622  else
1623  {
1624  cs_precedes = TRUE;
1625  sep_by_space = TRUE;
1626  }
1627 
1628  if (info.commodity && info.use_symbol)
1629  {
1630  currency_symbol = gnc_commodity_get_nice_symbol (info.commodity);
1631  if (!gnc_commodity_is_iso (info.commodity))
1632  {
1633  cs_precedes = FALSE;
1634  sep_by_space = TRUE;
1635  }
1636  }
1637  else /* !info.use_symbol || !info.commodity */
1638  currency_symbol = "";
1639 
1640  if (gnc_numeric_negative_p (val))
1641  {
1642  sign = lc->negative_sign;
1643  sign_posn = lc->n_sign_posn;
1644  }
1645  else
1646  {
1647  sign = lc->positive_sign;
1648  sign_posn = lc->p_sign_posn;
1649  }
1650 
1651  if (gnc_numeric_zero_p (val) || (sign == NULL) || (sign[0] == 0))
1652  print_sign = FALSE;
1653 
1654  /* See if we print sign now */
1655  if (print_sign && (sign_posn == 1))
1656  bufp = g_stpcpy(bufp, sign);
1657 
1658  /* Now see if we print currency */
1659  if (cs_precedes)
1660  {
1661  /* See if we print sign now */
1662  if (print_sign && (sign_posn == 3))
1663  bufp = g_stpcpy(bufp, sign);
1664 
1665  if (info.use_symbol)
1666  {
1667  bufp = g_stpcpy(bufp, currency_symbol);
1668  if (sep_by_space)
1669  bufp = g_stpcpy(bufp, " ");
1670  }
1671 
1672  /* See if we print sign now */
1673  if (print_sign && (sign_posn == 4))
1674  bufp = g_stpcpy(bufp, sign);
1675  }
1676 
1677  /* Now see if we print parentheses */
1678  if (print_sign && (sign_posn == 0))
1679  {
1680  bufp = g_stpcpy(bufp, "(");
1681  print_absolute = TRUE;
1682  }
1683 
1684  /* Now print the value */
1685  bufp += PrintAmountInternal(bufp,
1686  print_absolute ? gnc_numeric_abs(val) : val,
1687  &info);
1688 
1689  /* Now see if we print parentheses */
1690  if (print_sign && (sign_posn == 0))
1691  bufp = g_stpcpy(bufp, ")");
1692 
1693  /* Now see if we print currency */
1694  if (!cs_precedes)
1695  {
1696  /* See if we print sign now */
1697  if (print_sign && (sign_posn == 3))
1698  bufp = g_stpcpy(bufp, sign);
1699 
1700  if (info.use_symbol)
1701  {
1702  if (sep_by_space)
1703  bufp = g_stpcpy(bufp, " ");
1704  bufp = g_stpcpy(bufp, currency_symbol);
1705  }
1706 
1707  /* See if we print sign now */
1708  if (print_sign && (sign_posn == 4))
1709  bufp = g_stpcpy(bufp, sign);
1710  }
1711 
1712  /* See if we print sign now */
1713  if (print_sign && (sign_posn == 2))
1714  bufp = g_stpcpy(bufp, sign);
1715 
1716  /* return length of printed string */
1717  return (bufp - orig_bufp);
1718 }
gboolean gnc_numeric_zero_p(gnc_numeric a)
Returns 1 if the given gnc_numeric is 0 (zero), else returns 0.
gboolean gnc_numeric_negative_p(gnc_numeric a)
Returns 1 if a < 0, otherwise returns 0.
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...
gboolean gnc_commodity_is_iso(const gnc_commodity *cm)
Checks to see if the specified commodity is an ISO 4217 recognized currency.