Convert all locations that parse input using the locale

thousands/decimal point characters to use unicode functions.  This
should allow multi-byte unicode characters to work as these separators
on input.


git-svn-id: svn+ssh://svn.gnucash.org/repo/gnucash/trunk@13434 57a11ea4-9604-0410-9ed3-97b8803252fd
This commit is contained in:
David Hampton 2006-03-02 00:24:54 +00:00
parent 7694d2f473
commit cbedb5a5e9
8 changed files with 110 additions and 84 deletions

View File

@ -1,5 +1,15 @@
2006-03-01 David Hampton <hampton@employees.org> 2006-03-01 David Hampton <hampton@employees.org>
* src/register/register-core/pricecell.c:
* src/register/register-core/formulacell.c:
* src/calculation/fin_spl_protos.h:
* src/calculation/expression_parser.c:
* src/app-utils/gnc-ui-util.[ch]:
* src/app-utils/gnc-exp-parser.c: Convert all locations that parse
input using the locale thousands/decimal point characters to use
unicode functions. This should allow multi-byte unicode
characters to work as these separators on input.
* src/app-utils/gnc-ui-util.c: Rework of Sylvain Defresne's patch * src/app-utils/gnc-ui-util.c: Rework of Sylvain Defresne's patch
to support multi-byte unicode thousands separator and decimal to support multi-byte unicode thousands separator and decimal
point characters when printing numbers. point characters when printing numbers.

View File

@ -391,8 +391,8 @@ func_op(const char *fname, int argc, void **argv)
static void * static void *
trans_numeric(const char *digit_str, trans_numeric(const char *digit_str,
char radix_point, gchar *radix_point,
char group_char, gchar *group_char,
char **rstr) char **rstr)
{ {
ParserNum *pnum; ParserNum *pnum;
@ -548,7 +548,7 @@ gnc_exp_parser_parse_separate_vars (const char * expression,
lc = gnc_localeconv (); lc = gnc_localeconv ();
pe = init_parser (vars, *lc->mon_decimal_point, *lc->mon_thousands_sep, pe = init_parser (vars, lc->mon_decimal_point, lc->mon_thousands_sep,
trans_numeric, numeric_ops, negate_numeric, g_free, trans_numeric, numeric_ops, negate_numeric, g_free,
func_op); func_op);

View File

@ -1573,22 +1573,22 @@ xaccParseAmount (const char * in_str, gboolean monetary, gnc_numeric *result,
{ {
struct lconv *lc = gnc_localeconv(); struct lconv *lc = gnc_localeconv();
char negative_sign; gunichar negative_sign;
char decimal_point; gunichar decimal_point;
char group_separator; gunichar group_separator;
char *group; char *group;
negative_sign = lc->negative_sign[0]; negative_sign = g_utf8_get_char(lc->negative_sign);
if (monetary) if (monetary)
{ {
group_separator = lc->mon_thousands_sep[0]; group_separator = g_utf8_get_char(lc->mon_thousands_sep);
decimal_point = lc->mon_decimal_point[0]; decimal_point = g_utf8_get_char(lc->mon_decimal_point);
group = lc->mon_grouping; group = lc->mon_grouping;
} }
else else
{ {
group_separator = lc->thousands_sep[0]; group_separator = g_utf8_get_char(lc->thousands_sep);
decimal_point = lc->decimal_point[0]; decimal_point = g_utf8_get_char(lc->decimal_point);
group = lc->grouping; group = lc->grouping;
} }
@ -1598,8 +1598,8 @@ xaccParseAmount (const char * in_str, gboolean monetary, gnc_numeric *result,
gboolean gboolean
xaccParseAmountExtended (const char * in_str, gboolean monetary, xaccParseAmountExtended (const char * in_str, gboolean monetary,
char negative_sign, unsigned char decimal_point, gunichar negative_sign, gunichar decimal_point,
unsigned char group_separator, char *group, char *ignore_list, gunichar group_separator, char *group, char *ignore_list,
gnc_numeric *result, char **endstr) gnc_numeric *result, char **endstr)
{ {
gboolean is_negative; gboolean is_negative;
@ -1608,13 +1608,14 @@ xaccParseAmountExtended (const char * in_str, gboolean monetary,
GList * group_data; GList * group_data;
long long int numer; long long int numer;
long long int denom; long long int denom;
int group_count; int count, group_count;
ParseState state; ParseState state;
const unsigned char *in; const gchar *in;
char *out_str; gunichar uc;
char *out; gchar *out_str;
gchar *out;
/* Initialize *endstr to in_str */ /* Initialize *endstr to in_str */
if (endstr != NULL) if (endstr != NULL)
@ -1623,9 +1624,15 @@ xaccParseAmountExtended (const char * in_str, gboolean monetary,
if (in_str == NULL) if (in_str == NULL)
return FALSE; return FALSE;
if (!g_utf8_validate(in_str, -1, &in)) {
printf("Invalid utf8 string '%s'. Bad character at position %ld.\n",
in_str, g_utf8_pointer_to_offset (in_str, in));
return FALSE;
}
/* 'out_str' will be used to store digits for numeric conversion. /* 'out_str' will be used to store digits for numeric conversion.
* 'out' will be used to traverse out_str. */ * 'out' will be used to traverse out_str. */
out = out_str = g_new(char, strlen(in_str) + 1); out = out_str = g_new(gchar, strlen(in_str) + 128);
/* 'in' is used to traverse 'in_str'. */ /* 'in' is used to traverse 'in_str'. */
in = in_str; in = in_str;
@ -1646,9 +1653,11 @@ xaccParseAmountExtended (const char * in_str, gboolean monetary,
{ {
ParseState next_state = state; ParseState next_state = state;
uc = g_utf8_get_char(in);
/* Ignore anything in the 'ignore list' */ /* Ignore anything in the 'ignore list' */
if (ignore_list && *in != '\0' && strchr(ignore_list, *in) != NULL) { if (ignore_list && uc && g_utf8_strchr(ignore_list, -1, uc) != NULL) {
in++; in = g_utf8_next_char(in);
continue; continue;
} }
@ -1658,25 +1667,26 @@ xaccParseAmountExtended (const char * in_str, gboolean monetary,
{ {
/* START_ST means we have parsed 0 or more whitespace characters */ /* START_ST means we have parsed 0 or more whitespace characters */
case START_ST: case START_ST:
if (isdigit(*in)) if (g_unichar_isdigit(uc))
{ {
*out++ = *in; /* we record the digits themselves in out_str count = g_unichar_to_utf8(uc, out);
out += count; /* we record the digits themselves in out_str
* for later conversion by libc routines */ * for later conversion by libc routines */
next_state = PRE_GROUP_ST; next_state = PRE_GROUP_ST;
} }
else if (*in == decimal_point) else if (uc == decimal_point)
{ {
next_state = FRAC_ST; next_state = FRAC_ST;
} }
else if (isspace(*in)) else if (g_unichar_isspace(uc))
{ {
} }
else if (*in == negative_sign) else if (uc == negative_sign)
{ {
is_negative = TRUE; is_negative = TRUE;
next_state = NEG_ST; next_state = NEG_ST;
} }
else if (*in == '(') else if (uc == '(')
{ {
is_negative = TRUE; is_negative = TRUE;
need_paren = TRUE; need_paren = TRUE;
@ -1692,16 +1702,17 @@ xaccParseAmountExtended (const char * in_str, gboolean monetary,
/* NEG_ST means we have just parsed a negative sign. For now, /* NEG_ST means we have just parsed a negative sign. For now,
* we only recognize formats where the negative sign comes first. */ * we only recognize formats where the negative sign comes first. */
case NEG_ST: case NEG_ST:
if (isdigit(*in)) if (g_unichar_isdigit(uc))
{ {
*out++ = *in; count = g_unichar_to_utf8(uc, out);
out += count;
next_state = PRE_GROUP_ST; next_state = PRE_GROUP_ST;
} }
else if (*in == decimal_point) else if (uc == decimal_point)
{ {
next_state = FRAC_ST; next_state = FRAC_ST;
} }
else if (isspace(*in)) else if (g_unichar_isspace(uc))
{ {
} }
else else
@ -1714,19 +1725,20 @@ xaccParseAmountExtended (const char * in_str, gboolean monetary,
/* PRE_GROUP_ST means we have started parsing the number, but /* PRE_GROUP_ST means we have started parsing the number, but
* have not encountered a decimal point or a grouping character. */ * have not encountered a decimal point or a grouping character. */
case PRE_GROUP_ST: case PRE_GROUP_ST:
if (isdigit(*in)) if (g_unichar_isdigit(uc))
{ {
*out++ = *in; count = g_unichar_to_utf8(uc, out);
out += count;
} }
else if (*in == decimal_point) else if (uc == decimal_point)
{ {
next_state = FRAC_ST; next_state = FRAC_ST;
} }
else if (*in == group_separator) else if (uc == group_separator)
{ {
next_state = START_GROUP_ST; next_state = START_GROUP_ST;
} }
else if (*in == ')' && need_paren) else if (uc == ')' && need_paren)
{ {
next_state = DONE_ST; next_state = DONE_ST;
need_paren = FALSE; need_paren = FALSE;
@ -1744,27 +1756,29 @@ xaccParseAmountExtended (const char * in_str, gboolean monetary,
* try to interpret it in the fashion that will allow parsing * try to interpret it in the fashion that will allow parsing
* of the current number to continue. */ * of the current number to continue. */
case START_GROUP_ST: case START_GROUP_ST:
if (isdigit(*in)) if (g_unichar_isdigit(uc))
{ {
*out++ = *in; count = g_unichar_to_utf8(uc, out);
out += count;
group_count++; /* We record the number of digits group_count++; /* We record the number of digits
* in the group for later checking. */ * in the group for later checking. */
next_state = IN_GROUP_ST; next_state = IN_GROUP_ST;
} }
else if (*in == decimal_point) else if (uc == decimal_point)
{ {
/* If we now get a decimal point, and both the decimal /* If we now get a decimal point, and both the decimal
* and the group separator are also whitespace, assume * and the group separator are also whitespace, assume
* the last group separator was actually whitespace and * the last group separator was actually whitespace and
* stop parsing. Otherwise, there's a problem. */ * stop parsing. Otherwise, there's a problem. */
if (isspace(group_separator) && isspace(decimal_point)) if (g_unichar_isspace(group_separator) &&
g_unichar_isspace(decimal_point))
next_state = DONE_ST; next_state = DONE_ST;
else else
next_state = NO_NUM_ST; next_state = NO_NUM_ST;
} }
else if (*in == ')' && need_paren) else if (uc == ')' && need_paren)
{ {
if (isspace(group_separator)) if (g_unichar_isspace(group_separator))
{ {
next_state = DONE_ST; next_state = DONE_ST;
need_paren = FALSE; need_paren = FALSE;
@ -1777,7 +1791,7 @@ xaccParseAmountExtended (const char * in_str, gboolean monetary,
/* If the last group separator is also whitespace, /* If the last group separator is also whitespace,
* assume it was intended as such and stop parsing. * assume it was intended as such and stop parsing.
* Otherwise, there is a problem. */ * Otherwise, there is a problem. */
if (isspace(group_separator)) if (g_unichar_isspace(group_separator))
next_state = DONE_ST; next_state = DONE_ST;
else else
next_state = NO_NUM_ST; next_state = NO_NUM_ST;
@ -1787,21 +1801,22 @@ xaccParseAmountExtended (const char * in_str, gboolean monetary,
/* IN_GROUP_ST means we are in the middle of parsing /* IN_GROUP_ST means we are in the middle of parsing
* a group of digits. */ * a group of digits. */
case IN_GROUP_ST: case IN_GROUP_ST:
if (isdigit(*in)) if (g_unichar_isdigit(uc))
{ {
*out++ = *in; count = g_unichar_to_utf8(uc, out);
out += count;
group_count++; /* We record the number of digits group_count++; /* We record the number of digits
* in the group for later checking. */ * in the group for later checking. */
} }
else if (*in == decimal_point) else if (uc == decimal_point)
{ {
next_state = FRAC_ST; next_state = FRAC_ST;
} }
else if (*in == group_separator) else if (uc == group_separator)
{ {
next_state = START_GROUP_ST; next_state = START_GROUP_ST;
} }
else if (*in == ')' && need_paren) else if (uc == ')' && need_paren)
{ {
next_state = DONE_ST; next_state = DONE_ST;
need_paren = FALSE; need_paren = FALSE;
@ -1815,31 +1830,32 @@ xaccParseAmountExtended (const char * in_str, gboolean monetary,
/* FRAC_ST means we are now parsing fractional digits. */ /* FRAC_ST means we are now parsing fractional digits. */
case FRAC_ST: case FRAC_ST:
if (isdigit(*in)) if (g_unichar_isdigit(uc))
{ {
*out++ = *in; count = g_unichar_to_utf8(uc, out);
out += count;
} }
else if (*in == decimal_point) else if (uc == decimal_point)
{ {
/* If a subsequent decimal point is also whitespace, /* If a subsequent decimal point is also whitespace,
* assume it was intended as such and stop parsing. * assume it was intended as such and stop parsing.
* Otherwise, there is a problem. */ * Otherwise, there is a problem. */
if (isspace(decimal_point)) if (g_unichar_isspace(decimal_point))
next_state = DONE_ST; next_state = DONE_ST;
else else
next_state = NO_NUM_ST; next_state = NO_NUM_ST;
} }
else if (*in == group_separator) else if (uc == group_separator)
{ {
/* If a subsequent group separator is also whitespace, /* If a subsequent group separator is also whitespace,
* assume it was intended as such and stop parsing. * assume it was intended as such and stop parsing.
* Otherwise, there is a problem. */ * Otherwise, there is a problem. */
if (isspace(group_separator)) if (g_unichar_isspace(group_separator))
next_state = DONE_ST; next_state = DONE_ST;
else else
next_state = NO_NUM_ST; next_state = NO_NUM_ST;
} }
else if (*in == ')' && need_paren) else if (uc == ')' && need_paren)
{ {
next_state = DONE_ST; next_state = DONE_ST;
need_paren = FALSE; need_paren = FALSE;
@ -1889,7 +1905,7 @@ xaccParseAmountExtended (const char * in_str, gboolean monetary,
if (done_state (state)) if (done_state (state))
break; break;
in++; in = g_utf8_next_char(in);
} }
/* If there was an error, just quit */ /* If there was an error, just quit */

View File

@ -327,8 +327,8 @@ gboolean xaccParseAmount (const char * in_str, gboolean monetary,
*/ */
gboolean gboolean
xaccParseAmountExtended (const char * in_str, gboolean monetary, xaccParseAmountExtended (const char * in_str, gboolean monetary,
char negative_sign, unsigned char decimal_point, gunichar negative_sign, gunichar decimal_point,
unsigned char group_separator, char *group, char *ignore_list, gunichar group_separator, char *group, char *ignore_list,
gnc_numeric *result, char **endstr); gnc_numeric *result, char **endstr);
/* Initialization ***************************************************/ /* Initialization ***************************************************/

View File

@ -276,11 +276,11 @@
* *vp), "vp" is the pointer returned by the "init_parser" function. * *vp), "vp" is the pointer returned by the "init_parser" function.
* *
* void *init_parser(var_store_ptr predefined_vars, * void *init_parser(var_store_ptr predefined_vars,
* char radix_point, * gchar *radix_point,
* char group_char, * gchar *group_char,
* void *trans_numeric(char *digit_str, * void *trans_numeric(char *digit_str,
* char radix_point, * gchar *radix_point,
* char group_char, * gchar *group_char,
* char **rstr), * char **rstr),
* void *numeric_ops(char op_sym, * void *numeric_ops(char op_sym,
* void *left_value, * void *left_value,
@ -406,8 +406,8 @@ typedef struct parser_env
var_store_ptr unnamed_vars; var_store_ptr unnamed_vars;
const char *parse_str; const char *parse_str;
char radix_point; gchar *radix_point;
char group_char; gchar *group_char;
char name[128]; char name[128];
char Token; char Token;
@ -421,7 +421,7 @@ typedef struct parser_env
void *numeric_value; void *numeric_value;
void *(*trans_numeric) (const char *digit_str, void *(*trans_numeric) (const char *digit_str,
char radix_point, char group_char, char **rstr); gchar *radix_point, gchar *group_char, char **rstr);
void *(*numeric_ops) (char op_sym, void *left_value, void *right_value); void *(*numeric_ops) (char op_sym, void *left_value, void *right_value);
void *(*negate_numeric) (void *value); void *(*negate_numeric) (void *value);
void (*free_numeric) (void *numeric_value); void (*free_numeric) (void *numeric_value);
@ -449,11 +449,11 @@ static char allowed_operators[] = "+-*/()=:";
parser_env_ptr parser_env_ptr
init_parser (var_store_ptr predefined_vars, init_parser (var_store_ptr predefined_vars,
char radix_point, gchar *radix_point,
char group_char, gchar *group_char,
void *trans_numeric (const char *digit_str, void *trans_numeric (const char *digit_str,
char radix_point, gchar *radix_point,
char group_char, gchar *group_char,
char **rstr), char **rstr),
void *numeric_ops (char op_sym, void *numeric_ops (char op_sym,
void *left_value, void *left_value,

View File

@ -27,11 +27,11 @@
/* Line Number: 344 */ /* Line Number: 344 */
parser_env_ptr init_parser( parser_env_ptr init_parser(
var_store_ptr predefined_vars, var_store_ptr predefined_vars,
char radix_point, gchar *radix_point,
char group_char, gchar *group_char,
void *trans_numeric(const char *digit_str, void *trans_numeric(const char *digit_str,
char radix_point, gchar *radix_point,
char group_char, gchar *group_char,
char **rstr), char **rstr),
void *numeric_ops(char op_sym, void *numeric_ops(char op_sym,
void *left_value, void *left_value,

View File

@ -124,8 +124,8 @@ gnc_formula_cell_modify_verify( BasicCell *_cell,
FormulaCell *cell = (FormulaCell *)_cell; FormulaCell *cell = (FormulaCell *)_cell;
struct lconv *lc = gnc_localeconv (); struct lconv *lc = gnc_localeconv ();
const char *toks = "+-*/=()_:"; const char *toks = "+-*/=()_:";
unsigned char decimal_point; gunichar decimal_point;
unsigned char thousands_sep; gunichar thousands_sep;
const char *c; const char *c;
gunichar uc; gunichar uc;
@ -141,14 +141,14 @@ gnc_formula_cell_modify_verify( BasicCell *_cell,
} }
if (cell->print_info.monetary) if (cell->print_info.monetary)
decimal_point = lc->mon_decimal_point[0]; decimal_point = g_utf8_get_char(lc->mon_decimal_point);
else else
decimal_point = lc->decimal_point[0]; decimal_point = g_utf8_get_char(lc->decimal_point);
if (cell->print_info.monetary) if (cell->print_info.monetary)
thousands_sep = lc->mon_thousands_sep[0]; thousands_sep = g_utf8_get_char(lc->mon_thousands_sep);
else else
thousands_sep = lc->thousands_sep[0]; thousands_sep = g_utf8_get_char(lc->thousands_sep);
c = change; c = change;
while (*c) while (*c)

View File

@ -78,8 +78,8 @@ gnc_price_cell_modify_verify (BasicCell *_cell,
PriceCell *cell = (PriceCell *) _cell; PriceCell *cell = (PriceCell *) _cell;
struct lconv *lc = gnc_localeconv (); struct lconv *lc = gnc_localeconv ();
const char *toks = "+-*/=()_"; const char *toks = "+-*/=()_";
unsigned char decimal_point; gunichar decimal_point;
unsigned char thousands_sep; gunichar thousands_sep;
const char *c; const char *c;
gunichar uc; gunichar uc;
@ -92,14 +92,14 @@ gnc_price_cell_modify_verify (BasicCell *_cell,
} }
if (cell->print_info.monetary) if (cell->print_info.monetary)
decimal_point = lc->mon_decimal_point[0]; decimal_point = g_utf8_get_char(lc->mon_decimal_point);
else else
decimal_point = lc->decimal_point[0]; decimal_point = g_utf8_get_char(lc->decimal_point);
if (cell->print_info.monetary) if (cell->print_info.monetary)
thousands_sep = lc->mon_thousands_sep[0]; thousands_sep = g_utf8_get_char(lc->mon_thousands_sep);
else else
thousands_sep = lc->thousands_sep[0]; thousands_sep = g_utf8_get_char(lc->thousands_sep);
c = change; c = change;
while (*c) while (*c)