1 /* nls.c -- skeletal internationalization code. */
2
3 /* Copyright (C) 1996 Free Software Foundation, Inc.
4
5 This file is part of the GNU Readline Library, a library for
6 reading lines of text with interactive input and history editing.
7
8 The GNU Readline Library is free software; you can redistribute it
9 and/or modify it under the terms of the GNU General Public License
10 as published by the Free Software Foundation; either version 2, or
11 (at your option) any later version.
12
13 The GNU Readline Library is distributed in the hope that it will be
14 useful, but WITHOUT ANY WARRANTY; without even the implied warranty
15 of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
17
18 The GNU General Public License is often shipped with GNU software, and
19 is generally kept in a file called COPYING or LICENSE. If you do not
20 have a copy of the license, write to the Free Software Foundation,
21 59 Temple Place, Suite 330, Boston, MA 02111 USA. */
22 #define READLINE_LIBRARY
23
24 #if defined (HAVE_CONFIG_H)
25 # include <config.h>
26 #endif
27
28 #include <sys/types.h>
29
30 #include <stdio.h>
31
32 #if defined (HAVE_UNISTD_H)
33 # include <unistd.h>
34 #endif /* HAVE_UNISTD_H */
35
36 #if defined (HAVE_STDLIB_H)
37 # include <stdlib.h>
38 #else
39 # include "ansi_stdlib.h"
40 #endif /* HAVE_STDLIB_H */
41
42 #if defined (HAVE_LOCALE_H)
43 # include <locale.h>
44 #endif
45
46 #include <ctype.h>
47
48 #include "rldefs.h"
49 #include "readline.h"
50 #include "rlshell.h"
51 #include "rlprivate.h"
52
53 #if !defined (HAVE_SETLOCALE)
54 /* A list of legal values for the LANG or LC_CTYPE environment variables.
55 If a locale name in this list is the value for the LC_ALL, LC_CTYPE,
56 or LANG environment variable (using the first of those with a value),
57 readline eight-bit mode is enabled. */
58 static char *legal_lang_values[] =
59 {
60 "iso88591",
61 "iso88592",
62 "iso88593",
63 "iso88594",
64 "iso88595",
65 "iso88596",
66 "iso88597",
67 "iso88598",
68 "iso88599",
69 "iso885910",
70 "koi8r",
71 0
72 };
73
74 static char *normalize_codeset PARAMS((char *));
75 static char *find_codeset PARAMS((char *, size_t *));
76 #endif /* !HAVE_SETLOCALE */
77
78 /* Check for LC_ALL, LC_CTYPE, and LANG and use the first with a value
79 to decide the defaults for 8-bit character input and output. Returns
80 1 if we set eight-bit mode. */
81 int
_rl_init_eightbit()82 _rl_init_eightbit ()
83 {
84 /* If we have setlocale(3), just check the current LC_CTYPE category
85 value, and go into eight-bit mode if it's not C or POSIX. */
86 #if defined (HAVE_SETLOCALE)
87 char *t;
88
89 /* Set the LC_CTYPE locale category from environment variables. */
90 t = setlocale (LC_CTYPE, "");
91 if (t && *t && (t[0] != 'C' || t[1]) && (STREQ (t, "POSIX") == 0))
92 {
93 _rl_meta_flag = 1;
94 _rl_convert_meta_chars_to_ascii = 0;
95 _rl_output_meta_chars = 1;
96 return (1);
97 }
98 else
99 return (0);
100
101 #else /* !HAVE_SETLOCALE */
102 char *lspec, *t;
103 int i;
104
105 /* We don't have setlocale. Finesse it. Check the environment for the
106 appropriate variables and set eight-bit mode if they have the right
107 values. */
108 lspec = sh_get_env_value ("LC_ALL");
109 if (lspec == 0) lspec = sh_get_env_value ("LC_CTYPE");
110 if (lspec == 0) lspec = sh_get_env_value ("LANG");
111 if (lspec == 0 || (t = normalize_codeset (lspec)) == 0)
112 return (0);
113 for (i = 0; t && legal_lang_values[i]; i++)
114 if (STREQ (t, legal_lang_values[i]))
115 {
116 _rl_meta_flag = 1;
117 _rl_convert_meta_chars_to_ascii = 0;
118 _rl_output_meta_chars = 1;
119 break;
120 }
121 free (t);
122 return (legal_lang_values[i] ? 1 : 0);
123
124 #endif /* !HAVE_SETLOCALE */
125 }
126
127 #if !defined (HAVE_SETLOCALE)
128 static char *
normalize_codeset(codeset)129 normalize_codeset (codeset)
130 char *codeset;
131 {
132 size_t namelen, i;
133 int len, all_digits;
134 char *wp, *retval;
135
136 codeset = find_codeset (codeset, &namelen);
137
138 if (codeset == 0)
139 return (codeset);
140
141 all_digits = 1;
142 for (len = 0, i = 0; i < namelen; i++)
143 {
144 if (ISALNUM ((unsigned char)codeset[i]))
145 {
146 len++;
147 all_digits &= _rl_digit_p (codeset[i]);
148 }
149 }
150
151 retval = (char *)malloc ((all_digits ? 3 : 0) + len + 1);
152 if (retval == 0)
153 return ((char *)0);
154
155 wp = retval;
156 /* Add `iso' to beginning of an all-digit codeset */
157 if (all_digits)
158 {
159 *wp++ = 'i';
160 *wp++ = 's';
161 *wp++ = 'o';
162 }
163
164 for (i = 0; i < namelen; i++)
165 if (ISALPHA ((unsigned char)codeset[i]))
166 *wp++ = _rl_to_lower (codeset[i]);
167 else if (_rl_digit_p (codeset[i]))
168 *wp++ = codeset[i];
169 *wp = '\0';
170
171 return retval;
172 }
173
174 /* Isolate codeset portion of locale specification. */
175 static char *
find_codeset(name,lenp)176 find_codeset (name, lenp)
177 char *name;
178 size_t *lenp;
179 {
180 char *cp, *language, *result;
181
182 cp = language = name;
183 result = (char *)0;
184
185 while (*cp && *cp != '_' && *cp != '@' && *cp != '+' && *cp != ',')
186 cp++;
187
188 /* This does not make sense: language has to be specified. As
189 an exception we allow the variable to contain only the codeset
190 name. Perhaps there are funny codeset names. */
191 if (language == cp)
192 {
193 *lenp = strlen (language);
194 result = language;
195 }
196 else
197 {
198 /* Next is the territory. */
199 if (*cp == '_')
200 do
201 ++cp;
202 while (*cp && *cp != '.' && *cp != '@' && *cp != '+' && *cp != ',' && *cp != '_');
203
204 /* Now, finally, is the codeset. */
205 result = cp;
206 if (*cp == '.')
207 do
208 ++cp;
209 while (*cp && *cp != '@');
210
211 if (cp - result > 2)
212 {
213 result++;
214 *lenp = cp - result;
215 }
216 else
217 {
218 *lenp = strlen (language);
219 result = language;
220 }
221 }
222
223 return result;
224 }
225 #endif /* !HAVE_SETLOCALE */
226