diff --git a/gnucash/gnome-utils/gnc-tree-model-account.c b/gnucash/gnome-utils/gnc-tree-model-account.c index 5c3160e5acc..e04eac9adc0 100644 --- a/gnucash/gnome-utils/gnc-tree-model-account.c +++ b/gnucash/gnome-utils/gnc-tree-model-account.c @@ -560,6 +560,7 @@ gnc_tree_model_account_compute_period_balance (GncTreeModelAccount *model, gboolean *negative) { GncTreeModelAccountPrivate *priv; + GNCPrintAmountInfo print_info; time64 t1, t2; gnc_numeric b3; @@ -583,7 +584,9 @@ gnc_tree_model_account_compute_period_balance (GncTreeModelAccount *model, if (negative) *negative = gnc_numeric_negative_p (b3); - return g_strdup(xaccPrintAmount (b3, gnc_account_print_info (acct, TRUE))); + print_info = gnc_account_print_info (acct, TRUE); + + return g_strdup (gnc_print_amount_with_bidi_ltr_isolate (b3, print_info)); } static gboolean diff --git a/libgnucash/app-utils/gnc-ui-balances.c b/libgnucash/app-utils/gnc-ui-balances.c index b46b531996c..9227aefb2c4 100644 --- a/libgnucash/app-utils/gnc-ui-balances.c +++ b/libgnucash/app-utils/gnc-ui-balances.c @@ -146,7 +146,8 @@ gnc_ui_account_get_print_balance (xaccGetBalanceInCurrencyFn fn, balance = gnc_ui_account_get_balance_full(fn, account, recurse, negative, NULL); print_info = gnc_account_print_info(account, TRUE); - return g_strdup(xaccPrintAmount(balance, print_info)); + + return g_strdup (gnc_print_amount_with_bidi_ltr_isolate (balance, print_info)); } @@ -178,7 +179,8 @@ gnc_ui_account_get_print_report_balance (xaccGetBalanceInCurrencyFn fn, balance = gnc_ui_account_get_balance_full(fn, account, recurse, negative, report_commodity); print_info = gnc_commodity_print_info(report_commodity, TRUE); - return g_strdup(xaccPrintAmount(balance, print_info)); + + return g_strdup (gnc_print_amount_with_bidi_ltr_isolate (balance, print_info)); } static gnc_numeric @@ -312,7 +314,8 @@ gnc_ui_owner_get_print_balance (GncOwner *owner, balance = gnc_ui_owner_get_balance_full (owner, negative, NULL); print_info = gnc_commodity_print_info (gncOwnerGetCurrency (owner), TRUE); - return g_strdup (xaccPrintAmount (balance, print_info)); + + return g_strdup (gnc_print_amount_with_bidi_ltr_isolate (balance, print_info)); } /** @@ -338,6 +341,7 @@ gnc_ui_owner_get_print_report_balance (GncOwner *owner, balance = gnc_ui_owner_get_balance_full (owner, negative, report_commodity); print_info = gnc_commodity_print_info (report_commodity, TRUE); - return g_strdup (xaccPrintAmount (balance, print_info)); + + return g_strdup (gnc_print_amount_with_bidi_ltr_isolate (balance, print_info)); } diff --git a/libgnucash/app-utils/gnc-ui-util.c b/libgnucash/app-utils/gnc-ui-util.c index 5bcb8eb638c..d391bb3a9e0 100644 --- a/libgnucash/app-utils/gnc-ui-util.c +++ b/libgnucash/app-utils/gnc-ui-util.c @@ -1850,11 +1850,13 @@ xaccSPrintAmount (char * bufp, gnc_numeric val, GNCPrintAmountInfo info) return (bufp - orig_bufp); } +#define BUFLEN 1024 + const char * xaccPrintAmount (gnc_numeric val, GNCPrintAmountInfo info) { /* hack alert -- this is not thread safe ... */ - static char buf[1024]; + static char buf[BUFLEN]; if (!xaccSPrintAmount (buf, val, info)) buf[0] = '\0'; @@ -1863,6 +1865,55 @@ xaccPrintAmount (gnc_numeric val, GNCPrintAmountInfo info) return buf; } +const char * +gnc_print_amount_with_bidi_ltr_isolate (gnc_numeric val, GNCPrintAmountInfo info) +{ + /* hack alert -- this is not thread safe ... */ + static char buf[BUFLEN]; + static const char ltr_isolate[] = { 0xe2, 0x81, 0xa6 }; + static const char ltr_pop_isolate[] = { 0xe2, 0x81, 0xa9 }; + size_t offset = info.use_symbol ? 3 : 0; + + memset (buf, 0, BUFLEN); + if (!xaccSPrintAmount (buf + offset, val, info)) + { + buf[0] = '\0'; + return buf; + }; + + if (!info.use_symbol) + return buf; + + memcpy (buf, ltr_isolate, 3); + + if (buf[BUFLEN - 4] == '\0') + { + size_t length = strlen (buf); + memcpy (buf + length, ltr_pop_isolate, 3); + } + else + { + buf[BUFLEN - 1] = '\0'; + memcpy (buf + BUFLEN - 4, ltr_pop_isolate, 3); + + PWARN("buffer length %d exceeded, string truncated was %s", BUFLEN, buf); + } + /* its OK to return buf, since we declared it static + and is immediately g_strdup'd */ + return buf; +} + +gchar * +gnc_wrap_text_with_bidi_ltr_isolate (const gchar *text) +{ + static const char *ltr = "\u2066"; // ltr isolate + static const char *pop = "\u2069"; // pop directional formatting + + if (!text) + return NULL; + + return g_strconcat (ltr, text, pop, NULL); +} /********************************************************************\ ********************************************************************/ diff --git a/libgnucash/app-utils/gnc-ui-util.h b/libgnucash/app-utils/gnc-ui-util.h index b9bb385c60b..4e8867d1039 100644 --- a/libgnucash/app-utils/gnc-ui-util.h +++ b/libgnucash/app-utils/gnc-ui-util.h @@ -401,6 +401,28 @@ xaccParseAmountExtended (const char * in_str, gboolean monetary, gunichar group_separator, const char *ignore_list, gnc_numeric *result, char **endstr); +/** + * 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. + */ +const char * +gnc_print_amount_with_bidi_ltr_isolate (gnc_numeric val, GNCPrintAmountInfo info); + +/** + * 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. + */ +gchar * +gnc_wrap_text_with_bidi_ltr_isolate (const char *text); + /* Initialization ***************************************************/ void gnc_ui_util_init (void); @@ -446,9 +468,9 @@ gchar * gnc_filter_text_for_currency_symbol (const gchar *incoming_text, const gchar *symbol); /** Returns the incoming text removed of currency symbol - * + * * @param comm commodity of entry if known - * + * * @param incoming_text The text to filter * * @param symbol return the symbol used