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/23 01:00:12 @@ -14,11 +14,12 @@ #include #endif +#include +#include +#include #include #include #include -#include -#include #ifdef HAVE_UNISTD_H #include @@ -46,6 +47,17 @@ "~/.freeciv" #endif +/* Cached locale numeric formatting information. + Defaults are as appropriate for the US. */ +#ifdef ENABLE_NLS +#define FC_NLS_CONST +#else +#define FC_NLS_CONST const +#endif +static FC_NLS_CONST char *grouping = "\3"; +static FC_NLS_CONST char *grouping_sep = ","; +static FC_NLS_CONST size_t grouping_sep_len = 1; + /************************************************************************** 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 +181,55 @@ /*************************************************************** 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. + (Only works for numbers >= zero.) ***************************************************************/ -#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++; + if (i == *grp && nr != 0) { + /* Reached count of digits in group: insert separator + and reset count. */ + i = 0; + if (*grp == CHAR_MAX) { + /* This test 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 means to repeat the present group-size indefinitely. */ + grp++; + } + } } - return ptr + 1; -#endif + return ptr; } /*************************************************************** @@ -700,10 +707,41 @@ ***************************************************************************/ void init_nls(void) { -#ifdef ENABLE_NLS - setlocale (LC_ALL, ""); - bindtextdomain (PACKAGE, LOCALEDIR); +#ifdef ENABLE_NLS + setlocale(LC_ALL, ""); + bindtextdomain(PACKAGE, LOCALEDIR); textdomain(PACKAGE); + + /* Don't touch the defaults when LC_NUMERIC == "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 would result in the "C" locale being used, with grouping "" + and thousands_sep "", where we really want "\3" and ",". */ + + if (strcmp(setlocale(LC_NUMERIC, NULL), "C")) { + size_t i; + struct lconv *lc = localeconv(); + + grouping_sep = mystrdup(lc->thousands_sep); + grouping_sep_len = strlen(grouping_sep); + + for (i = 0; lc->grouping[i] && lc->grouping[i] != CHAR_MAX; i++) + ; + i++; + + if (lc->grouping[0] == 0) { + /* This actually indicates no grouping at all. */ + static char m = CHAR_MAX; + grouping = &m; + return; + } + + grouping = fc_malloc(i); + memcpy(grouping, lc->grouping, i); + } #endif }