1/* nl_langinfo() replacement: query locale dependent information.
2
3   Copyright (C) 2007-2014 Free Software Foundation, Inc.
4
5   This program is free software: you can redistribute it and/or modify
6   it under the terms of the GNU General Public License as published by
7   the Free Software Foundation; either version 3 of the License, or
8   (at your option) any later version.
9
10   This program is distributed in the hope that it will be useful,
11   but WITHOUT ANY WARRANTY; without even the implied warranty of
12   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13   GNU General Public License for more details.
14
15   You should have received a copy of the GNU General Public License
16   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
17
18#include <config.h>
19
20/* Specification.  */
21#include <langinfo.h>
22
23#if REPLACE_NL_LANGINFO
24
25/* Override nl_langinfo with support for added nl_item values.  */
26
27# include <locale.h>
28# include <string.h>
29
30# undef nl_langinfo
31
32char *
33rpl_nl_langinfo (nl_item item)
34{
35  switch (item)
36    {
37# if GNULIB_defined_CODESET
38    case CODESET:
39      {
40        const char *locale;
41        static char buf[2 + 10 + 1];
42
43        locale = setlocale (LC_CTYPE, NULL);
44        if (locale != NULL && locale[0] != '\0')
45          {
46            /* If the locale name contains an encoding after the dot, return
47               it.  */
48            const char *dot = strchr (locale, '.');
49
50            if (dot != NULL)
51              {
52                const char *modifier;
53
54                dot++;
55                /* Look for the possible @... trailer and remove it, if any.  */
56                modifier = strchr (dot, '@');
57                if (modifier == NULL)
58                  return dot;
59                if (modifier - dot < sizeof (buf))
60                  {
61                    memcpy (buf, dot, modifier - dot);
62                    buf [modifier - dot] = '\0';
63                    return buf;
64                  }
65              }
66          }
67        return "";
68      }
69# endif
70# if GNULIB_defined_T_FMT_AMPM
71    case T_FMT_AMPM:
72      return "%I:%M:%S %p";
73# endif
74# if GNULIB_defined_ERA
75    case ERA:
76      /* The format is not standardized.  In glibc it is a sequence of strings
77         of the form "direction:offset:start_date:end_date:era_name:era_format"
78         with an empty string at the end.  */
79      return "";
80    case ERA_D_FMT:
81      /* The %Ex conversion in strftime behaves like %x if the locale does not
82         have an alternative time format.  */
83      item = D_FMT;
84      break;
85    case ERA_D_T_FMT:
86      /* The %Ec conversion in strftime behaves like %c if the locale does not
87         have an alternative time format.  */
88      item = D_T_FMT;
89      break;
90    case ERA_T_FMT:
91      /* The %EX conversion in strftime behaves like %X if the locale does not
92         have an alternative time format.  */
93      item = T_FMT;
94      break;
95    case ALT_DIGITS:
96      /* The format is not standardized.  In glibc it is a sequence of 10
97         strings, appended in memory.  */
98      return "\0\0\0\0\0\0\0\0\0\0";
99# endif
100# if GNULIB_defined_YESEXPR || !FUNC_NL_LANGINFO_YESEXPR_WORKS
101    case YESEXPR:
102      return "^[yY]";
103    case NOEXPR:
104      return "^[nN]";
105# endif
106    default:
107      break;
108    }
109  return nl_langinfo (item);
110}
111
112#else
113
114/* Provide nl_langinfo from scratch.  */
115
116# if (defined _WIN32 || defined __WIN32__) && ! defined __CYGWIN__
117
118/* Native Windows platforms.  */
119
120#  define WIN32_LEAN_AND_MEAN  /* avoid including junk */
121#  include <windows.h>
122
123#  include <stdio.h>
124
125# else
126
127/* An old Unix platform without locales, such as Linux libc5 or BeOS.  */
128
129# endif
130
131# include <locale.h>
132
133char *
134nl_langinfo (nl_item item)
135{
136  switch (item)
137    {
138    /* nl_langinfo items of the LC_CTYPE category */
139    case CODESET:
140# if (defined _WIN32 || defined __WIN32__) && ! defined __CYGWIN__
141      {
142        static char buf[2 + 10 + 1];
143
144        /* The Windows API has a function returning the locale's codepage as
145           a number.  */
146        sprintf (buf, "CP%u", GetACP ());
147        return buf;
148      }
149# elif defined __BEOS__
150      return "UTF-8";
151# else
152      return "ISO-8859-1";
153# endif
154    /* nl_langinfo items of the LC_NUMERIC category */
155    case RADIXCHAR:
156      return localeconv () ->decimal_point;
157    case THOUSEP:
158      return localeconv () ->thousands_sep;
159    /* nl_langinfo items of the LC_TIME category.
160       TODO: Really use the locale.  */
161    case D_T_FMT:
162    case ERA_D_T_FMT:
163      return "%a %b %e %H:%M:%S %Y";
164    case D_FMT:
165    case ERA_D_FMT:
166      return "%m/%d/%y";
167    case T_FMT:
168    case ERA_T_FMT:
169      return "%H:%M:%S";
170    case T_FMT_AMPM:
171      return "%I:%M:%S %p";
172    case AM_STR:
173      return "AM";
174    case PM_STR:
175      return "PM";
176    case DAY_1:
177      return "Sunday";
178    case DAY_2:
179      return "Monday";
180    case DAY_3:
181      return "Tuesday";
182    case DAY_4:
183      return "Wednesday";
184    case DAY_5:
185      return "Thursday";
186    case DAY_6:
187      return "Friday";
188    case DAY_7:
189      return "Saturday";
190    case ABDAY_1:
191      return "Sun";
192    case ABDAY_2:
193      return "Mon";
194    case ABDAY_3:
195      return "Tue";
196    case ABDAY_4:
197      return "Wed";
198    case ABDAY_5:
199      return "Thu";
200    case ABDAY_6:
201      return "Fri";
202    case ABDAY_7:
203      return "Sat";
204    case MON_1:
205      return "January";
206    case MON_2:
207      return "February";
208    case MON_3:
209      return "March";
210    case MON_4:
211      return "April";
212    case MON_5:
213      return "May";
214    case MON_6:
215      return "June";
216    case MON_7:
217      return "July";
218    case MON_8:
219      return "August";
220    case MON_9:
221      return "September";
222    case MON_10:
223      return "October";
224    case MON_11:
225      return "November";
226    case MON_12:
227      return "December";
228    case ABMON_1:
229      return "Jan";
230    case ABMON_2:
231      return "Feb";
232    case ABMON_3:
233      return "Mar";
234    case ABMON_4:
235      return "Apr";
236    case ABMON_5:
237      return "May";
238    case ABMON_6:
239      return "Jun";
240    case ABMON_7:
241      return "Jul";
242    case ABMON_8:
243      return "Aug";
244    case ABMON_9:
245      return "Sep";
246    case ABMON_10:
247      return "Oct";
248    case ABMON_11:
249      return "Nov";
250    case ABMON_12:
251      return "Dec";
252    case ERA:
253      return "";
254    case ALT_DIGITS:
255      return "\0\0\0\0\0\0\0\0\0\0";
256    /* nl_langinfo items of the LC_MONETARY category
257       TODO: Really use the locale. */
258    case CRNCYSTR:
259      return "-";
260    /* nl_langinfo items of the LC_MESSAGES category
261       TODO: Really use the locale. */
262    case YESEXPR:
263      return "^[yY]";
264    case NOEXPR:
265      return "^[nN]";
266    default:
267      return "";
268    }
269}
270
271#endif
272