Skip to content

Commit

Permalink
Bug797501 - Currency symbols in Hebrew (RTL) language
Browse files Browse the repository at this point in the history
When Gnucash is run in Hebrew which is a RTL language, on the accounts
page the tree view is displaying the required number as the following...

TreeView entry is   '1,500.00 ₪' or '-1,500.00 ₪'
TreeModel string is '₪ 1,500.00‬' or '₪ 1,500.00-‬'

This seems to be down to the GTK 'Unicode Bidirectional Text Algorithm'
which is changing the representation of the model string based on the
first strongly typed character, in this case the Israeli shekel sign.

To fix this, when creating the displayed monetary amount insert a BiDi
ltr isolate uni-character at the start of the string.
  • Loading branch information
Bob-IT committed Mar 14, 2022
1 parent 7e299cb commit f8fc796
Show file tree
Hide file tree
Showing 4 changed files with 88 additions and 8 deletions.
5 changes: 4 additions & 1 deletion gnucash/gnome-utils/gnc-tree-model-account.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;

Expand All @@ -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
Expand Down
12 changes: 8 additions & 4 deletions libgnucash/app-utils/gnc-ui-balances.c
Original file line number Diff line number Diff line change
Expand Up @@ -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));
}


Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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));
}

/**
Expand All @@ -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));
}

53 changes: 52 additions & 1 deletion libgnucash/app-utils/gnc-ui-util.c
Original file line number Diff line number Diff line change
Expand Up @@ -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';
Expand All @@ -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);
}

/********************************************************************\
********************************************************************/
Expand Down
26 changes: 24 additions & 2 deletions libgnucash/app-utils/gnc-ui-util.h
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down Expand Up @@ -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
Expand Down

0 comments on commit f8fc796

Please sign in to comment.