bug-gnulib
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: nl_langinfo and localized day/month names


From: Eli Zaretskii
Subject: Re: nl_langinfo and localized day/month names
Date: Sat, 05 Jul 2014 20:57:30 +0300

> Date: Sat, 05 Jul 2014 10:12:29 -0700
> From: Paul Eggert <address@hidden>
> 
> Eli Zaretskii wrote:
> > Ping!  Could someone please respond, and either accept the patch or
> > explain why it cannot be accepted?
> 
> Since nobody has commented and it works for you I'm inclined to apply 
> it, unless Daiki speaks up.

Thanks!

> Could you write a proper ChangeLog entry for it please?  Typical
> Gnulib style is an initial line "modulenames: brief phrase".  Also,
> please use only spaces to indent.  Thanks.

Modified patch with ChangeLog entries attached below.

diff --git a/ChangeLog b/ChangeLog
index eccf03e..8a1a9c8 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,24 @@
+2014-07-05  Eli Zaretskii  <address@hidden>
+
+       nl_langinfo: CODESET on MS-Windows and more items from localeconv.
+       * lib/nl_langinfo.c (nl_langinfo) <known_tm>: New static variable.
+       [_WIN32 || __WIN32__ && !__CYGWIN__] <CODESET>: Try extracting the
+       codeset from the value returned by 'setlocale', before falling
+       back on GetACP.  Compute the values of RADIXCHAR, THOUSEP,
+       GROUPING, CRNCYSTR, INT_CURR_SYMBOL, MON_DECIMAL_POINT,
+       MON_THOUSANDS_SEP, MON_GROUPING, POSITIVE_SIGN, NEGATIVE_SIGN,
+       FRAC_DIGITS, INT_FRAC_DIGITS, P_CS_PRECEDES, N_CS_PRECEDES,
+       P_SEP_BY_SPACE, N_SEP_BY_SPACE, P_SIGN_POSN, and N_SIGN_POSN from
+       the corresponding values returned by 'localeconv'.  Compute the
+       values of AM_STR, PM_STR, DAY_n, ABDAY_n, MON_n, and ABMON_n by
+       calling 'strftime' with a suitably modified known_tm structure.
+
+       * lib/langinfo.in.h (DECIMAL_POINT, THOUSANDS_SEP, GROUPING)
+       (CURRENCY_SYMBOL, INT_CURR_SYMBOL, MON_DECIMAL_POINT)
+       (MON_THOUSANDS_SEP, MON_GROUPING, POSITIVE_SIGN, NEGATIVE_SIGN)
+       (FRAC_DIGITS, INT_FRAC_DIGITS, P_CS_PRECEDES, N_CS_PRECEDES)
+       (P_SEP_BY_SPACE, N_SEP_BY_SPACE, P_SIGN_POSN, N_SIGN_POSN): Define.
+
 2014-07-05  Paul Eggert  <address@hidden>
 
        Bruno Haible has stepped down as maintainer.
diff --git a/lib/langinfo.in.h b/lib/langinfo.in.h
index 17f4b9b..d118d5d 100644
--- a/lib/langinfo.in.h
+++ b/lib/langinfo.in.h
@@ -49,7 +49,10 @@ typedef int nl_item;
 # define CODESET     10000
 /* nl_langinfo items of the LC_NUMERIC category */
 # define RADIXCHAR   10001
+# define DECIMAL_POINT RADIXCHAR
 # define THOUSEP     10002
+# define THOUSANDS_SEP THOUSEP
+# define GROUPING    10114
 /* nl_langinfo items of the LC_TIME category */
 # define D_T_FMT     10003
 # define D_FMT       10004
@@ -102,6 +105,21 @@ typedef int nl_item;
 # define ALT_DIGITS  10051
 /* nl_langinfo items of the LC_MONETARY category */
 # define CRNCYSTR    10052
+# define CURRENCY_SYMBOL   CRNCYSTR
+# define INT_CURR_SYMBOL   10100
+# define MON_DECIMAL_POINT 10101
+# define MON_THOUSANDS_SEP 10102
+# define MON_GROUPING      10103
+# define POSITIVE_SIGN     10104
+# define NEGATIVE_SIGN     10105
+# define FRAC_DIGITS       10106
+# define INT_FRAC_DIGITS   10107
+# define P_CS_PRECEDES     10108
+# define N_CS_PRECEDES     10109
+# define P_SEP_BY_SPACE    10110
+# define N_SEP_BY_SPACE    10111
+# define P_SIGN_POSN       10112
+# define N_SIGN_POSN       10113
 /* nl_langinfo items of the LC_MESSAGES category */
 # define YESEXPR     10053
 # define NOEXPR      10054
diff --git a/lib/nl_langinfo.c b/lib/nl_langinfo.c
index 287abfd..1fef26e 100644
--- a/lib/nl_langinfo.c
+++ b/lib/nl_langinfo.c
@@ -121,6 +121,7 @@ rpl_nl_langinfo (nl_item item)
 #  include <windows.h>
 
 #  include <stdio.h>
+#  include <limits.h>
 
 # else
 
@@ -129,22 +130,46 @@ rpl_nl_langinfo (nl_item item)
 # endif
 
 # include <locale.h>
+# include <time.h>
 
 char *
 nl_langinfo (nl_item item)
 {
+  static struct tm known_tm = {
+    0, 0, 0,   /* 00:00:00 */
+    5, 0, 114, /* Sunday January 5, 2014 */
+    0, 4, -1
+  };
+  struct tm tmm;
+  static char nlbuf[100];
+
   switch (item)
     {
     /* nl_langinfo items of the LC_CTYPE category */
     case CODESET:
 # if (defined _WIN32 || defined __WIN32__) && ! defined __CYGWIN__
+      /* The Windows API has a function returning the locale's
+         codepage as a number, but the value doesn't change according
+         to what the 'setlocale' call specified.  So we use it as a
+         last resort, in case the string returned by 'setlocale'
+         doesn't specify the codepage.  */
       {
-        static char buf[2 + 10 + 1];
+        char *current_locale = setlocale (LC_ALL, NULL);
+        char *pdot;
+
+       /* If they set different locales for different categories,
+          'setlocale' will return a semi-colon separated list of
+          locale values.  To make sure we use the correct one, we
+          choose LC_CTYPE.  */
+       if (strchr (current_locale, ';'))
+         current_locale = setlocale (LC_CTYPE, NULL);
 
-        /* The Windows API has a function returning the locale's codepage as
-           a number.  */
-        sprintf (buf, "CP%u", GetACP ());
-        return buf;
+       pdot = strrchr (current_locale, '.');
+       if (pdot)
+         sprintf (nlbuf, "CP%s", pdot + 1);
+       else
+         sprintf (nlbuf, "CP%u", GetACP ());
+       return nlbuf;
       }
 # elif defined __BEOS__
       return "UTF-8";
@@ -153,9 +178,23 @@ nl_langinfo (nl_item item)
 # endif
     /* nl_langinfo items of the LC_NUMERIC category */
     case RADIXCHAR:
-      return localeconv () ->decimal_point;
+      {
+        char *c = localeconv () ->decimal_point;
+
+        if (*c == CHAR_MAX || *c == -1)
+          return "";
+        return c;
+      }
     case THOUSEP:
-      return localeconv () ->thousands_sep;
+      {
+        char *c = localeconv () ->thousands_sep;
+
+        if (*c == CHAR_MAX || *c == -1)
+          return "";
+        return c;
+      }
+    case GROUPING:
+      return localeconv () ->grouping;
     /* nl_langinfo items of the LC_TIME category.
        TODO: Really use the locale.  */
     case D_T_FMT:
@@ -170,93 +209,163 @@ nl_langinfo (nl_item item)
     case T_FMT_AMPM:
       return "%I:%M:%S %p";
     case AM_STR:
-      return "AM";
+      memcpy (&tmm, &known_tm, sizeof (known_tm));
+      tmm.tm_hour = 10;
+      if (!strftime (nlbuf, sizeof(nlbuf), "%p", &tmm))
+        return "AM";
+      return nlbuf;
     case PM_STR:
-      return "PM";
+      memcpy (&tmm, &known_tm, sizeof (known_tm));
+      tmm.tm_hour = 22;
+      if (!strftime (nlbuf, sizeof(nlbuf), "%p", &tmm))
+        return "PM";
+      return nlbuf;
     case DAY_1:
-      return "Sunday";
     case DAY_2:
-      return "Monday";
     case DAY_3:
-      return "Tuesday";
     case DAY_4:
-      return "Wednesday";
     case DAY_5:
-      return "Thursday";
     case DAY_6:
-      return "Friday";
     case DAY_7:
-      return "Saturday";
+      {
+        static char *days[] = {
+          "Sunday", "Monday", "Tuesday", "Wednesday", "Thursday",
+          "Friday", "Saturday"
+        };
+        memcpy (&tmm, &known_tm, sizeof (known_tm));
+        tmm.tm_mday += item - DAY_1;
+        tmm.tm_wday += item - DAY_1;
+        if (!strftime (nlbuf, sizeof(nlbuf), "%A", &tmm))
+          return days[item - DAY_1];
+        return nlbuf;
+      }
     case ABDAY_1:
-      return "Sun";
     case ABDAY_2:
-      return "Mon";
     case ABDAY_3:
-      return "Tue";
     case ABDAY_4:
-      return "Wed";
     case ABDAY_5:
-      return "Thu";
     case ABDAY_6:
-      return "Fri";
     case ABDAY_7:
-      return "Sat";
+      {
+        static char *abdays[] = {
+          "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"
+        };
+        memcpy (&tmm, &known_tm, sizeof (known_tm));
+        tmm.tm_mday += item - ABDAY_1;
+        tmm.tm_wday += item - ABDAY_1;
+        if (!strftime (nlbuf, sizeof(nlbuf), "%a", &tmm))
+          return abdays[item - ABDAY_1];
+        return nlbuf;
+      }
     case MON_1:
-      return "January";
     case MON_2:
-      return "February";
     case MON_3:
-      return "March";
     case MON_4:
-      return "April";
     case MON_5:
-      return "May";
     case MON_6:
-      return "June";
     case MON_7:
-      return "July";
     case MON_8:
-      return "August";
     case MON_9:
-      return "September";
     case MON_10:
-      return "October";
     case MON_11:
-      return "November";
     case MON_12:
-      return "December";
+      {
+        static char *months[] = {
+          "January", "February", "March", "April", "May", "June", "July",
+          "September", "October", "November", "December"
+        };
+        memcpy (&tmm, &known_tm, sizeof (known_tm));
+        tmm.tm_mon += item - MON_1;
+        if (!strftime (nlbuf, sizeof(nlbuf), "%B", &tmm))
+          return months[item - MON_1];
+        return nlbuf;
+      }
     case ABMON_1:
-      return "Jan";
     case ABMON_2:
-      return "Feb";
     case ABMON_3:
-      return "Mar";
     case ABMON_4:
-      return "Apr";
     case ABMON_5:
-      return "May";
     case ABMON_6:
-      return "Jun";
     case ABMON_7:
-      return "Jul";
     case ABMON_8:
-      return "Aug";
     case ABMON_9:
-      return "Sep";
     case ABMON_10:
-      return "Oct";
     case ABMON_11:
-      return "Nov";
     case ABMON_12:
-      return "Dec";
+      {
+        static char *abmonths[] = {
+          "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul",
+          "Sep", "Oct", "Nov", "Dec"
+        };
+        memcpy (&tmm, &known_tm, sizeof (known_tm));
+        tmm.tm_mon += item - ABMON_1;
+        if (!strftime (nlbuf, sizeof(nlbuf), "%b", &tmm))
+          return abmonths[item - ABMON_1];
+        return nlbuf;
+      }
     case ERA:
       return "";
     case ALT_DIGITS:
       return "\0\0\0\0\0\0\0\0\0\0";
-    /* nl_langinfo items of the LC_MONETARY category
-       TODO: Really use the locale. */
+    /* nl_langinfo items of the LC_MONETARY category.  */
     case CRNCYSTR:
-      return "-";
+      return localeconv () ->currency_symbol;
+    case INT_CURR_SYMBOL:
+      return localeconv () ->int_curr_symbol;
+    case MON_DECIMAL_POINT:
+      {
+        char *c = localeconv () ->mon_decimal_point;
+
+        if (*c == CHAR_MAX || *c == -1)
+          return "";
+        return c;
+      }
+    case MON_THOUSANDS_SEP:
+      {
+        char *c = localeconv () ->mon_thousands_sep;
+
+        if (*c == CHAR_MAX || *c == -1)
+          return "";
+        return c;
+      }
+    case MON_GROUPING:
+      return localeconv () ->mon_grouping;
+    case POSITIVE_SIGN:
+      return localeconv () ->positive_sign;
+    case NEGATIVE_SIGN:
+      return localeconv () ->negative_sign;
+    case FRAC_DIGITS:
+      nlbuf[0] = localeconv () ->frac_digits;
+      nlbuf[1] = '\0';
+      return nlbuf;
+    case INT_FRAC_DIGITS:
+      nlbuf[0] = localeconv () ->int_frac_digits;
+      nlbuf[1] = '\0';
+      return nlbuf;
+    case P_CS_PRECEDES:
+      nlbuf[0] = localeconv () ->p_cs_precedes;
+      nlbuf[1] = '\0';
+      return nlbuf;
+    case N_CS_PRECEDES:
+      nlbuf[0] = localeconv () ->n_cs_precedes;
+      nlbuf[1] = '\0';
+      return nlbuf;
+    case P_SEP_BY_SPACE:
+      nlbuf[0] = localeconv () ->p_sep_by_space;
+      nlbuf[1] = '\0';
+      return nlbuf;
+    case N_SEP_BY_SPACE:
+      nlbuf[0] = localeconv () ->n_sep_by_space;
+      nlbuf[1] = '\0';
+      return nlbuf;
+    case P_SIGN_POSN:
+      nlbuf[0] = localeconv () ->p_sign_posn;
+      nlbuf[1] = '\0';
+      return nlbuf;
+    case N_SIGN_POSN:
+      nlbuf[0] = localeconv () ->n_sign_posn;
+      nlbuf[1] = '\0';
+      return nlbuf;
     /* nl_langinfo items of the LC_MESSAGES category
        TODO: Really use the locale. */
     case YESEXPR:



reply via email to

[Prev in Thread] Current Thread [Next in Thread]