1/* nl_langinfo() replacement: query locale dependent information.
2
3   Copyright (C) 2007-2010 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_ERA
71    case ERA:
72      /* The format is not standardized.  In glibc it is a sequence of strings
73         of the form "direction:offset:start_date:end_date:era_name:era_format"
74         with an empty string at the end.  */
75      return "";
76    case ERA_D_FMT:
77      /* The %Ex conversion in strftime behaves like %x if the locale does not
78         have an alternative time format.  */
79      item = D_FMT;
80      break;
81    case ERA_D_T_FMT:
82      /* The %Ec conversion in strftime behaves like %c if the locale does not
83         have an alternative time format.  */
84      item = D_T_FMT;
85      break;
86    case ERA_T_FMT:
87      /* The %EX conversion in strftime behaves like %X if the locale does not
88         have an alternative time format.  */
89      item = T_FMT;
90      break;
91    case ALT_DIGITS:
92      /* The format is not standardized.  In glibc it is a sequence of 10
93         strings, appended in memory.  */
94      return "\0\0\0\0\0\0\0\0\0\0";
95# endif
96    default:
97      break;
98    }
99  return nl_langinfo (item);
100}
101
102#else
103
104/* Provide nl_langinfo from scratch.  */
105
106# if (defined _WIN32 || defined __WIN32__) && ! defined __CYGWIN__
107
108/* Native Windows platforms.  */
109
110#  define WIN32_LEAN_AND_MEAN  /* avoid including junk */
111#  include <windows.h>
112
113#  include <stdio.h>
114
115# else
116
117/* An old Unix platform without locales, such as Linux libc5 or BeOS.  */
118
119# endif
120
121# include <locale.h>
122
123char *
124nl_langinfo (nl_item item)
125{
126  switch (item)
127    {
128    /* nl_langinfo items of the LC_CTYPE category */
129    case CODESET:
130# if (defined _WIN32 || defined __WIN32__) && ! defined __CYGWIN__
131      {
132        static char buf[2 + 10 + 1];
133
134        /* Woe32 has a function returning the locale's codepage as a number.  */
135        sprintf (buf, "CP%u", GetACP ());
136        return buf;
137      }
138# elif defined __BEOS__
139      return "UTF-8";
140# else
141      return "ISO-8859-1";
142# endif
143    /* nl_langinfo items of the LC_NUMERIC category */
144    case RADIXCHAR:
145      return localeconv () ->decimal_point;
146    case THOUSEP:
147      return localeconv () ->thousands_sep;
148    /* nl_langinfo items of the LC_TIME category.
149       TODO: Really use the locale.  */
150    case D_T_FMT:
151    case ERA_D_T_FMT:
152      return "%a %b %e %H:%M:%S %Y";
153    case D_FMT:
154    case ERA_D_FMT:
155      return "%m/%d/%y";
156    case T_FMT:
157    case ERA_T_FMT:
158      return "%H:%M:%S";
159    case T_FMT_AMPM:
160      return "%I:%M:%S %p";
161    case AM_STR:
162      return "AM";
163    case PM_STR:
164      return "PM";
165    case DAY_1:
166      return "Sunday";
167    case DAY_2:
168      return "Monday";
169    case DAY_3:
170      return "Tuesday";
171    case DAY_4:
172      return "Wednesday";
173    case DAY_5:
174      return "Thursday";
175    case DAY_6:
176      return "Friday";
177    case DAY_7:
178      return "Saturday";
179    case ABDAY_1:
180      return "Sun";
181    case ABDAY_2:
182      return "Mon";
183    case ABDAY_3:
184      return "Tue";
185    case ABDAY_4:
186      return "Wed";
187    case ABDAY_5:
188      return "Thu";
189    case ABDAY_6:
190      return "Fri";
191    case ABDAY_7:
192      return "Sat";
193    case MON_1:
194      return "January";
195    case MON_2:
196      return "February";
197    case MON_3:
198      return "March";
199    case MON_4:
200      return "April";
201    case MON_5:
202      return "May";
203    case MON_6:
204      return "June";
205    case MON_7:
206      return "July";
207    case MON_8:
208      return "August";
209    case MON_9:
210      return "September";
211    case MON_10:
212      return "October";
213    case MON_11:
214      return "November";
215    case MON_12:
216      return "December";
217    case ABMON_1:
218      return "Jan";
219    case ABMON_2:
220      return "Feb";
221    case ABMON_3:
222      return "Mar";
223    case ABMON_4:
224      return "Apr";
225    case ABMON_5:
226      return "May";
227    case ABMON_6:
228      return "Jun";
229    case ABMON_7:
230      return "Jul";
231    case ABMON_8:
232      return "Aug";
233    case ABMON_9:
234      return "Sep";
235    case ABMON_10:
236      return "Oct";
237    case ABMON_11:
238      return "Nov";
239    case ABMON_12:
240      return "Dec";
241    case ERA:
242      return "";
243    case ALT_DIGITS:
244      return "\0\0\0\0\0\0\0\0\0\0";
245    /* nl_langinfo items of the LC_MONETARY category
246       TODO: Really use the locale. */
247    case CRNCYSTR:
248      return "-";
249    /* nl_langinfo items of the LC_MESSAGES category
250       TODO: Really use the locale. */
251    case YESEXPR:
252      return "^[yY]";
253    case NOEXPR:
254      return "^[nN]";
255    default:
256      return "";
257    }
258}
259
260#endif
261