GnuCash  4.12-558-g06612b8434
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...
 
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 805 of file gnc-ui-util.c.

806 {
807  gnc_commodity *currency;
808  if (!account)
809  {
810  if (currency_from_account_found)
811  *currency_from_account_found = FALSE;
812  return gnc_default_currency();
813  }
814 
815  currency = gnc_account_get_currency_or_parent(account);
816  if (currency)
817  {
818  if (currency_from_account_found)
819  *currency_from_account_found = TRUE;
820  }
821  else
822  {
823  if (currency_from_account_found)
824  *currency_from_account_found = FALSE;
825  currency = gnc_default_currency();
826  }
827  return currency;
828 }
gnc_commodity * gnc_default_currency(void)
Return the default currency set by the user.
Definition: gnc-ui-util.c:800
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 800 of file gnc-ui-util.c.

801 {
802  return gnc_default_currency_common (user_default_currency, GNC_PREFS_GROUP_GENERAL);
803 }

◆ 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 833 of file gnc-ui-util.c.

834 {
835  return gnc_default_currency_common (user_report_currency, GNC_PREFS_GROUP_GENERAL_REPORT);
836 }

◆ 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 2199 of file gnc-ui-util.c.

2200 {
2201  gchar *normal_text, *nt;
2202  GString *filtered;
2203  gboolean cntrl = FALSE;
2204  gboolean text_found = FALSE;
2205 
2206  if (!text)
2207  return NULL;
2208 
2209  if (!g_utf8_validate (text, -1, NULL))
2210  return NULL;
2211 
2212  normal_text = g_utf8_normalize (text, -1, G_NORMALIZE_ALL_COMPOSE);
2213 
2214  filtered = g_string_sized_new (strlen (normal_text) + 1);
2215 
2216  nt = normal_text;
2217 
2218  while (*nt)
2219  {
2220  gunichar uc = g_utf8_get_char (nt);
2221 
2222  // check for starting with control characters
2223  if (unichar_is_cntrl (uc) && !text_found)
2224  {
2225  nt = g_utf8_next_char (nt);
2226  continue;
2227  }
2228  // check for alpha, num and punctuation
2229  if (!unichar_is_cntrl (uc))
2230  {
2231  filtered = g_string_append_unichar (filtered, uc);
2232  text_found = TRUE;
2233  }
2234  // check for control characters after text
2235  if (unichar_is_cntrl (uc))
2236  cntrl = TRUE;
2237 
2238  nt = g_utf8_next_char (nt);
2239 
2240  if (cntrl) // if control characters in text replace with space
2241  {
2242  gunichar uc2 = g_utf8_get_char (nt);
2243 
2244  if (!unichar_is_cntrl (uc2))
2245  filtered = g_string_append_unichar (filtered, ' ');
2246  }
2247  cntrl = FALSE;
2248  }
2249  g_free (normal_text);
2250  return g_string_free (filtered, FALSE);
2251 }

◆ 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 2310 of file gnc-ui-util.c.

2313 {
2314  if (!incoming_text)
2315  {
2316  *symbol = NULL;
2317  return NULL;
2318  }
2319 
2320  if (!gnc_commodity_is_currency (comm))
2321  {
2322  *symbol = NULL;
2323  return g_strdup (incoming_text);
2324  }
2325 
2326  if (comm)
2327  *symbol = gnc_commodity_get_nice_symbol (comm);
2328  else
2330 
2331  return gnc_filter_text_for_currency_symbol (incoming_text, *symbol);
2332 }
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:800
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:2286

◆ 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 2286 of file gnc-ui-util.c.

2288 {
2289  gchar *ret_text = NULL;
2290  gchar **split;
2291 
2292  if (!incoming_text)
2293  return NULL;
2294 
2295  if (!symbol)
2296  return g_strdup (incoming_text);
2297 
2298  if (g_strrstr (incoming_text, symbol) == NULL)
2299  return g_strdup (incoming_text);
2300 
2301  split = g_strsplit (incoming_text, symbol, -1);
2302 
2303  ret_text = g_strjoinv (NULL, split);
2304 
2305  g_strfreev (split);
2306  return ret_text;
2307 }

◆ 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 2254 of file gnc-ui-util.c.

2257 {
2258  gint text_len;
2259  gint num = 0;
2260 
2261  if (*cursor_position == 0)
2262  return;
2263 
2264  if (!incoming_text || !symbol)
2265  return;
2266 
2267  if (g_strrstr (incoming_text, symbol) == NULL)
2268  return;
2269 
2270  text_len = g_utf8_strlen (incoming_text, -1);
2271 
2272  for (gint x = 0; x < text_len; x++)
2273  {
2274  gchar *temp = g_utf8_offset_to_pointer (incoming_text, x);
2275 
2276  if (g_str_has_prefix (temp, symbol))
2277  num++;
2278 
2279  if (g_strrstr (temp, symbol) == NULL)
2280  break;
2281  }
2282  *cursor_position = *cursor_position - (num * g_utf8_strlen (symbol, -1));
2283 }

◆ 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 444 of file gnc-ui-util.c.

445 {
446  gboolean show_leaf_accounts;
447  show_leaf_accounts = gnc_prefs_get_bool(GNC_PREFS_GROUP_GENERAL_REGISTER,
448  GNC_PREF_SHOW_LEAF_ACCT_NAMES);
449 
450  return gnc_get_account_name_for_split_register(account, show_leaf_accounts);
451 }
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:435
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 435 of file gnc-ui-util.c.

436 {
437  if (show_leaf_accounts)
438  return g_strdup (xaccAccountGetName (account));
439  else
440  return gnc_account_get_full_name (account);
441 }
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 546 of file gnc-ui-util.c.

547 {
548  static const char flags[] = { FLINK, WLINK, ' ', 0 };
549  return flags;
550 }

◆ 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 522 of file gnc-ui-util.c.

523 {
524  switch (link_flag)
525  {
526  case WLINK:
527  return C_("Document Link flag for 'web'", "w");
528  case FLINK:
529  return C_("Document Link flag for 'file'", "f");
530  case ' ':
531  return " ";
532  default:
533  PERR("Bad link flag");
534  return NULL;
535  }
536 }
#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 539 of file gnc-ui-util.c.

540 {
541  static const char flags[] = { FLINK, WLINK, ' ', 0 };
542  return flags;
543 }

◆ 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 757 of file gnc-ui-util.c.

758 {
759  gnc_commodity * currency = gnc_locale_default_currency_nodefault ();
760 
761  return (currency ? currency :
762  gnc_commodity_table_lookup (gnc_get_current_commodities (),
763  GNC_COMMODITY_NS_CURRENCY, "USD"));
764 }
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:742

◆ 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 742 of file gnc-ui-util.c.

743 {
744  gnc_commodity * currency;
745  gnc_commodity_table *table;
746  const char *code;
747 
748  table = gnc_get_current_commodities ();
749  code = gnc_locale_default_iso_currency_code ();
750 
751  currency = gnc_commodity_table_lookup (table, GNC_COMMODITY_NS_CURRENCY, code);
752 
753  return (currency ? currency : NULL);
754 }

◆ 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 1475 of file gnc-ui-util.c.

1476 {
1477  /* hack alert -- this is not thread safe ... */
1478  static char buf[BUFLEN];
1479  static const char ltr_isolate[] = { 0xe2, 0x81, 0xa6 };
1480  static const char ltr_pop_isolate[] = { 0xe2, 0x81, 0xa9 };
1481  size_t offset = info.use_symbol ? 3 : 0;
1482 
1483  memset (buf, 0, BUFLEN);
1484  if (!xaccSPrintAmount (buf + offset, val, info))
1485  {
1486  buf[0] = '\0';
1487  return buf;
1488  };
1489 
1490  if (!info.use_symbol)
1491  return buf;
1492 
1493  memcpy (buf, ltr_isolate, 3);
1494 
1495  if (buf[BUFLEN - 4] == '\0')
1496  {
1497  size_t length = strlen (buf);
1498  memcpy (buf + length, ltr_pop_isolate, 3);
1499  }
1500  else
1501  {
1502  buf[BUFLEN - 1] = '\0';
1503  memcpy (buf + BUFLEN - 4, ltr_pop_isolate, 3);
1504 
1505  PWARN("buffer length %d exceeded, string truncated was %s", BUFLEN, buf);
1506  }
1507  /* its OK to return buf, since we declared it static
1508  and is immediately g_strdup'd */
1509  return buf;
1510 }
#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:1331

◆ 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 1757 of file gnc-ui-util.c.

1759 {
1760  return xaccParseAmountPosSign (in_str, monetary, result, endstr, FALSE);
1761 }
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:1764

◆ 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 1803 of file gnc-ui-util.c.

1807 {
1808  gboolean is_negative;
1809  gboolean got_decimal;
1810  gboolean need_paren;
1811  long long int numer;
1812  long long int denom;
1813  int count;
1814 
1815  ParseState state;
1816 
1817  const gchar *in;
1818  gunichar uc;
1819  gchar *out_str;
1820  gchar *out;
1821 
1822  /* Initialize *endstr to in_str */
1823  if (endstr != NULL)
1824  *endstr = (char *) in_str;
1825 
1826  if (in_str == NULL)
1827  return FALSE;
1828 
1829  if (!g_utf8_validate(in_str, -1, &in))
1830  {
1831  printf("Invalid utf8 string '%s'. Bad character at position %ld.\n",
1832  in_str, g_utf8_pointer_to_offset (in_str, in));
1833  return FALSE;
1834  }
1835 
1836  /* 'out_str' will be used to store digits for numeric conversion.
1837  * 'out' will be used to traverse out_str. */
1838  out = out_str = g_new(gchar, strlen(in_str) + 128);
1839 
1840  /* 'in' is used to traverse 'in_str'. */
1841  in = in_str;
1842 
1843  is_negative = FALSE;
1844  got_decimal = FALSE;
1845  need_paren = FALSE;
1846  numer = 0;
1847  denom = 1;
1848 
1849  /* Initialize the state machine */
1850  state = START_ST;
1851 
1852  /* This while loop implements a state machine for parsing numbers. */
1853  while (TRUE)
1854  {
1855  ParseState next_state = state;
1856 
1857  uc = g_utf8_get_char(in);
1858 
1859  /* Ignore anything in the 'ignore list' */
1860  if (ignore_list && uc && g_utf8_strchr(ignore_list, -1, uc) != NULL)
1861  {
1862  in = g_utf8_next_char(in);
1863  continue;
1864  }
1865 
1866  /* Note we never need to check for the end of 'in_str' explicitly.
1867  * The 'else' clauses on all the state transitions will handle that. */
1868  switch (state)
1869  {
1870  /* START_ST means we have parsed 0 or more whitespace characters */
1871  case START_ST:
1872  if (g_unichar_isdigit(uc))
1873  {
1874  count = g_unichar_to_utf8(uc, out);
1875  out += count; /* we record the digits themselves in out_str
1876  * for later conversion by libc routines */
1877  next_state = NUMER_ST;
1878  }
1879  else if (uc == decimal_point)
1880  {
1881  next_state = FRAC_ST;
1882  }
1883  else if (g_unichar_isspace(uc))
1884  {
1885  }
1886  else if (uc == negative_sign)
1887  {
1888  is_negative = TRUE;
1889  next_state = NEG_ST;
1890  }
1891  else if (uc == '(')
1892  {
1893  is_negative = TRUE;
1894  need_paren = TRUE;
1895  next_state = NEG_ST;
1896  }
1897  else
1898  {
1899  next_state = NO_NUM_ST;
1900  }
1901 
1902  break;
1903 
1904  /* NEG_ST means we have just parsed a negative sign. For now,
1905  * we only recognize formats where the negative sign comes first. */
1906  case NEG_ST:
1907  if (g_unichar_isdigit(uc))
1908  {
1909  count = g_unichar_to_utf8(uc, out);
1910  out += count;
1911  next_state = NUMER_ST;
1912  }
1913  else if (uc == decimal_point)
1914  {
1915  next_state = FRAC_ST;
1916  }
1917  else if (g_unichar_isspace(uc))
1918  {
1919  }
1920  else
1921  {
1922  next_state = NO_NUM_ST;
1923  }
1924 
1925  break;
1926 
1927  /* NUMER_ST means we have started parsing the number, but
1928  * have not encountered a decimal separator. */
1929  case NUMER_ST:
1930  if (g_unichar_isdigit(uc))
1931  {
1932  count = g_unichar_to_utf8(uc, out);
1933  out += count;
1934  }
1935  else if (uc == decimal_point)
1936  {
1937  next_state = FRAC_ST;
1938  }
1939  else if (uc == group_separator)
1940  {
1941  ; //ignore it
1942  }
1943  else if (uc == ')' && need_paren)
1944  {
1945  next_state = DONE_ST;
1946  need_paren = FALSE;
1947  }
1948  else
1949  {
1950  next_state = DONE_ST;
1951  }
1952 
1953  break;
1954 
1955  /* FRAC_ST means we are now parsing fractional digits. */
1956  case FRAC_ST:
1957  if (g_unichar_isdigit(uc))
1958  {
1959  count = g_unichar_to_utf8(uc, out);
1960  out += count;
1961  }
1962  else if (uc == decimal_point)
1963  {
1964  /* If a subsequent decimal point is also whitespace,
1965  * assume it was intended as such and stop parsing.
1966  * Otherwise, there is a problem. */
1967  if (g_unichar_isspace(decimal_point))
1968  next_state = DONE_ST;
1969  else
1970  next_state = NO_NUM_ST;
1971  }
1972  else if (uc == group_separator)
1973  {
1974  /* If a subsequent group separator is also whitespace,
1975  * assume it was intended as such and stop parsing.
1976  * Otherwise ignore it. */
1977  if (g_unichar_isspace(group_separator))
1978  next_state = DONE_ST;
1979  }
1980  else if (uc == ')' && need_paren)
1981  {
1982  next_state = DONE_ST;
1983  need_paren = FALSE;
1984  }
1985  else
1986  {
1987  next_state = DONE_ST;
1988  }
1989 
1990  break;
1991 
1992  default:
1993  PERR("bad state");
1994  g_assert_not_reached();
1995  break;
1996  }
1997 
1998  /* If we're moving into the FRAC_ST or out of the machine
1999  * without going through FRAC_ST, record the integral value. */
2000  if (((next_state == FRAC_ST) && (state != FRAC_ST)) ||
2001  ((next_state == DONE_ST) && !got_decimal))
2002  {
2003  *out = '\0';
2004 
2005  if (*out_str != '\0' && sscanf(out_str, QOF_SCANF_LLD, &numer) < 1)
2006  {
2007  next_state = NO_NUM_ST;
2008  }
2009  else if (next_state == FRAC_ST)
2010  {
2011  /* reset the out pointer to record the fraction */
2012  out = out_str;
2013  *out = '\0';
2014 
2015  got_decimal = TRUE;
2016  }
2017  }
2018 
2019  state = next_state;
2020  if (done_state (state))
2021  break;
2022 
2023  in = g_utf8_next_char(in);
2024  }
2025 
2026  /* If there was an error, just quit */
2027  if (need_paren || (state == NO_NUM_ST))
2028  {
2029  g_free(out_str);
2030  return FALSE;
2031  }
2032 
2033  /* Cap the end of the fraction string, if any */
2034  *out = '\0';
2035 
2036  /* Add in fractional value */
2037  if (got_decimal && (*out_str != '\0'))
2038  {
2039  size_t len;
2040  long long int fraction;
2041 
2042  len = strlen(out_str);
2043 
2044  if (len > 12)
2045  {
2046  out_str[12] = '\0';
2047  len = 12;
2048  }
2049 
2050  if (sscanf (out_str, QOF_SCANF_LLD, &fraction) < 1)
2051  {
2052  g_free(out_str);
2053  return FALSE;
2054  }
2055 
2056  denom = multiplier(len);
2057  numer *= denom;
2058  numer += fraction;
2059  }
2060  else if (monetary && auto_decimal_enabled && !got_decimal)
2061  {
2062  if ((auto_decimal_places > 0) && (auto_decimal_places <= 12))
2063  {
2064  denom = multiplier(auto_decimal_places);
2065 
2066  /* No need to multiply numer by denom at this point,
2067  * since by specifying the auto decimal places the
2068  * user has effectively determined the scaling factor
2069  * for the numerator they entered.
2070  */
2071  }
2072  }
2073 
2074  if (result != NULL)
2075  {
2076  *result = gnc_numeric_create (numer, denom);
2077  if (is_negative)
2078  *result = gnc_numeric_neg (*result);
2079  }
2080 
2081  if (endstr != NULL)
2082  *endstr = (char *) in;
2083 
2084  g_free (out_str);
2085 
2086  return TRUE;
2087 }
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 1764 of file gnc-ui-util.c.

1766 {
1767  struct lconv *lc = gnc_localeconv();
1768 
1769  gunichar negative_sign;
1770  gunichar decimal_point;
1771  gunichar group_separator;
1772  gchar *ignore = NULL;
1773  char *plus_sign = "+";
1774 
1775  negative_sign = g_utf8_get_char(lc->negative_sign);
1776  if (monetary)
1777  {
1778  group_separator = g_utf8_get_char(lc->mon_thousands_sep);
1779  decimal_point = g_utf8_get_char(lc->mon_decimal_point);
1780  }
1781  else
1782  {
1783  group_separator = g_utf8_get_char(lc->thousands_sep);
1784  decimal_point = g_utf8_get_char(lc->decimal_point);
1785  }
1786 
1787  if (skip)
1788  {
1789  /* We want the locale's positive sign to be ignored.
1790  * If the locale doesn't specify one, we assume "+" as
1791  * an optional positive sign and ignore that */
1792  ignore = lc->positive_sign;
1793  if (!ignore || !*ignore)
1794  ignore = plus_sign;
1795  }
1796 
1797  return xaccParseAmountExtended(in_str, monetary, negative_sign,
1798  decimal_point, group_separator,
1799  ignore, result, endstr);
1800 }
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:1803

◆ 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 1462 of file gnc-ui-util.c.

1463 {
1464  /* hack alert -- this is not thread safe ... */
1465  static char buf[BUFLEN];
1466 
1467  if (!xaccSPrintAmount (buf, val, info))
1468  buf[0] = '\0';
1469 
1470  /* its OK to return buf, since we declared it static */
1471  return buf;
1472 }
int xaccSPrintAmount(char *bufp, gnc_numeric val, GNCPrintAmountInfo info)
Make a string representation of a gnc_numeric.
Definition: gnc-ui-util.c:1331

◆ 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 1331 of file gnc-ui-util.c.

1332 {
1333  struct lconv *lc;
1334 
1335  char *orig_bufp = bufp;
1336  const char *currency_symbol;
1337  const char *sign;
1338 
1339  char cs_precedes;
1340  char sep_by_space;
1341  char sign_posn;
1342 
1343  gboolean print_sign = TRUE;
1344  gboolean print_absolute = FALSE;
1345 
1346  if (!bufp)
1347  return 0;
1348 
1349  lc = gnc_localeconv();
1350  if (info.use_locale)
1351  if (gnc_numeric_negative_p (val))
1352  {
1353  cs_precedes = lc->n_cs_precedes;
1354  sep_by_space = lc->n_sep_by_space;
1355  }
1356  else
1357  {
1358  cs_precedes = lc->p_cs_precedes;
1359  sep_by_space = lc->p_sep_by_space;
1360  }
1361  else
1362  {
1363  cs_precedes = TRUE;
1364  sep_by_space = TRUE;
1365  }
1366 
1367  if (info.commodity && info.use_symbol)
1368  {
1369  currency_symbol = gnc_commodity_get_nice_symbol (info.commodity);
1370  if (!gnc_commodity_is_iso (info.commodity))
1371  {
1372  cs_precedes = FALSE;
1373  sep_by_space = TRUE;
1374  }
1375  }
1376  else /* !info.use_symbol || !info.commodity */
1377  currency_symbol = "";
1378 
1379  if (gnc_numeric_negative_p (val))
1380  {
1381  sign = lc->negative_sign;
1382  sign_posn = lc->n_sign_posn;
1383  }
1384  else
1385  {
1386  sign = lc->positive_sign;
1387  sign_posn = lc->p_sign_posn;
1388  }
1389 
1390  if (gnc_numeric_zero_p (val) || (sign == NULL) || (sign[0] == 0))
1391  print_sign = FALSE;
1392 
1393  /* See if we print sign now */
1394  if (print_sign && (sign_posn == 1))
1395  bufp = g_stpcpy(bufp, sign);
1396 
1397  /* Now see if we print currency */
1398  if (cs_precedes)
1399  {
1400  /* See if we print sign now */
1401  if (print_sign && (sign_posn == 3))
1402  bufp = g_stpcpy(bufp, sign);
1403 
1404  if (info.use_symbol)
1405  {
1406  bufp = g_stpcpy(bufp, currency_symbol);
1407  if (sep_by_space)
1408  bufp = g_stpcpy(bufp, " ");
1409  }
1410 
1411  /* See if we print sign now */
1412  if (print_sign && (sign_posn == 4))
1413  bufp = g_stpcpy(bufp, sign);
1414  }
1415 
1416  /* Now see if we print parentheses */
1417  if (print_sign && (sign_posn == 0))
1418  {
1419  bufp = g_stpcpy(bufp, "(");
1420  print_absolute = TRUE;
1421  }
1422 
1423  /* Now print the value */
1424  bufp += PrintAmountInternal(bufp,
1425  print_absolute ? gnc_numeric_abs(val) : val,
1426  &info);
1427 
1428  /* Now see if we print parentheses */
1429  if (print_sign && (sign_posn == 0))
1430  bufp = g_stpcpy(bufp, ")");
1431 
1432  /* Now see if we print currency */
1433  if (!cs_precedes)
1434  {
1435  /* See if we print sign now */
1436  if (print_sign && (sign_posn == 3))
1437  bufp = g_stpcpy(bufp, sign);
1438 
1439  if (info.use_symbol)
1440  {
1441  if (sep_by_space)
1442  bufp = g_stpcpy(bufp, " ");
1443  bufp = g_stpcpy(bufp, currency_symbol);
1444  }
1445 
1446  /* See if we print sign now */
1447  if (print_sign && (sign_posn == 4))
1448  bufp = g_stpcpy(bufp, sign);
1449  }
1450 
1451  /* See if we print sign now */
1452  if (print_sign && (sign_posn == 2))
1453  bufp = g_stpcpy(bufp, sign);
1454 
1455  /* return length of printed string */
1456  return (bufp - orig_bufp);
1457 }
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.