Index: common/shared.c =================================================================== RCS file: /home/freeciv/CVS/freeciv/common/shared.c,v retrieving revision 1.57 diff -u -r1.57 shared.c --- shared.c 2000/08/22 08:56:19 1.57 +++ shared.c 2000/08/22 20:32:39 @@ -14,11 +14,12 @@ #include #endif +#include +#include +#include #include #include #include -#include -#include #ifdef HAVE_UNISTD_H #include @@ -46,6 +47,18 @@ "~/.freeciv" #endif +/* Cached locale numeric formatting information. If compiled without + ENABLE_NLS, use constants appropriate for the US instead. */ +#ifdef ENABLE_NLS +static char *grouping; +static char *grouping_sep; +static size_t grouping_sep_len; +#else +static const char grouping[] = { 3, 0 }; +static const char grouping_sep[] = ","; +static const size_t grouping_sep_len = 1; +#endif + /************************************************************************** FIXME: This is an inelegant, English-specific kludge that fails to work correctly even in the limited case of English, e.g. "An hour". @@ -169,60 +182,53 @@ /*************************************************************** Returns a statically allocated string containing a nicely-formatted - version of the given number. - FIXME: This is not internationalised at all. + version of the given number according to the user's locale. ***************************************************************/ -#define SPLITS 3 -#define N_DIGS 20 char *int_to_text(int nr) { - char tmpbuf[N_DIGS+1]; - static char buf[N_DIGS+((N_DIGS-1)/SPLITS)+1]; - char *to=buf; - char *from=tmpbuf; - my_snprintf(tmpbuf, sizeof(tmpbuf), "%d", nr); - while (*from) { - *to++ = *from++; - if (strlen(from)%SPLITS==0 && *from) - *to++=','; - } - *to=0; - return buf; -#if 0 - /* FIXME: Some code which may help when i18n'd using localeconv(). */ - int neg; - static char buf[1 + (2 * N_DIGS - 1) + 1]; + static char buf[64]; /* Note that we'll be filling this in right to left. */ char *ptr; - int inx; + char *grp = grouping; + int i; + assert(nr >= 0); + if (nr == 0) { return "0"; } - - if ((neg = (nr < 0))) { - nr = -nr; - } - ptr = &(buf[sizeof(buf) - 1]); - *ptr-- = '\0'; + ptr = &buf[sizeof(buf) - 1]; + *ptr = 0; - inx = 0; + i = 0; while (nr != 0) { int dig = nr % 10; - *ptr-- = '0' + dig; + assert(ptr > buf); + *(--ptr) = '0' + dig; nr /= 10; - inx++; - if ((inx % SPLITS == 0) && (nr != 0)) { - *ptr-- = ','; - } - } - if (neg) { - *ptr-- = '-'; - } + i++; - return ptr + 1; -#endif + if (nr != 0 && i == *grp) { + /* Reached count of digits in group: insert separator and reset count. */ + i = 0; + if (*grp == CHAR_MAX) { + /* This test for is unlikely to be necessary since we would + need at least 421-bit ints to break the 127 digit barrier, + but why not. */ + break; + } + ptr -= grouping_sep_len; + assert(ptr >= buf); + memcpy(ptr, grouping_sep, grouping_sep_len); + if (*(grp + 1) != 0) { + /* Zero indicates that we should repeat the present group-size + indefinitely. */ + grp++; + } + } + } + return ptr; } /*************************************************************** @@ -694,20 +700,49 @@ } } - /*************************************************************************** Setup for Native Language Support, if configured to use it. ***************************************************************************/ void init_nls(void) { #ifdef ENABLE_NLS + char *s_grouping; + size_t i; + setlocale (LC_ALL, ""); bindtextdomain (PACKAGE, LOCALEDIR); textdomain(PACKAGE); + + if (!strcmp(setlocale(LC_NUMERIC, NULL), "C")) { + /* This is intended to cater for the common case where + 1) The user is from North America. + 2) The user has not set the proper environment variables. + (Most applications are (unfortunately) US-centric by + default, so why bother?) + This results in the "C" locale being used, with grouping "" + and thousands_sep "" where we really want "\3" and ",". */ + s_grouping = "\3"; + grouping_sep = ","; + grouping_sep_len = 1; + } else { + struct lconv *lc = localeconv(); + grouping_sep = mystrdup(lc->thousands_sep); + grouping_sep_len = strlen(grouping_sep); + s_grouping = lc->grouping; + } + + for (i = 0; s_grouping[i] && s_grouping[i] != CHAR_MAX; i++) + ; + i++; + + /* Clone the grouping data. */ + grouping = fc_malloc(i); + memcpy(grouping, s_grouping, i); #endif } - /*************************************************************************** If we have root privileges, die with an error. (Eg, for security reasons.) @@ -731,7 +766,6 @@ } #endif } - /*************************************************************************** Return a description string of the result.