11acd27e7Smillert /* nls.c -- skeletal internationalization code. */
21acd27e7Smillert
31acd27e7Smillert /* Copyright (C) 1996 Free Software Foundation, Inc.
41acd27e7Smillert
51acd27e7Smillert This file is part of the GNU Readline Library, a library for
61acd27e7Smillert reading lines of text with interactive input and history editing.
71acd27e7Smillert
81acd27e7Smillert The GNU Readline Library is free software; you can redistribute it
91acd27e7Smillert and/or modify it under the terms of the GNU General Public License
101acd27e7Smillert as published by the Free Software Foundation; either version 2, or
111acd27e7Smillert (at your option) any later version.
121acd27e7Smillert
131acd27e7Smillert The GNU Readline Library is distributed in the hope that it will be
141acd27e7Smillert useful, but WITHOUT ANY WARRANTY; without even the implied warranty
151acd27e7Smillert of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
161acd27e7Smillert GNU General Public License for more details.
171acd27e7Smillert
181acd27e7Smillert The GNU General Public License is often shipped with GNU software, and
191acd27e7Smillert is generally kept in a file called COPYING or LICENSE. If you do not
201acd27e7Smillert have a copy of the license, write to the Free Software Foundation,
211acd27e7Smillert 59 Temple Place, Suite 330, Boston, MA 02111 USA. */
221acd27e7Smillert #define READLINE_LIBRARY
231acd27e7Smillert
241acd27e7Smillert #if defined (HAVE_CONFIG_H)
251acd27e7Smillert # include <config.h>
261acd27e7Smillert #endif
271acd27e7Smillert
281acd27e7Smillert #include <sys/types.h>
291acd27e7Smillert
301acd27e7Smillert #include <stdio.h>
311acd27e7Smillert
321acd27e7Smillert #if defined (HAVE_UNISTD_H)
331acd27e7Smillert # include <unistd.h>
341acd27e7Smillert #endif /* HAVE_UNISTD_H */
351acd27e7Smillert
361acd27e7Smillert #if defined (HAVE_STDLIB_H)
371acd27e7Smillert # include <stdlib.h>
381acd27e7Smillert #else
391acd27e7Smillert # include "ansi_stdlib.h"
401acd27e7Smillert #endif /* HAVE_STDLIB_H */
411acd27e7Smillert
421acd27e7Smillert #if defined (HAVE_LOCALE_H)
431acd27e7Smillert # include <locale.h>
441acd27e7Smillert #endif
451acd27e7Smillert
461acd27e7Smillert #include <ctype.h>
471acd27e7Smillert
481acd27e7Smillert #include "rldefs.h"
491acd27e7Smillert #include "readline.h"
501acd27e7Smillert #include "rlshell.h"
511acd27e7Smillert #include "rlprivate.h"
521acd27e7Smillert
531acd27e7Smillert #if !defined (HAVE_SETLOCALE)
541acd27e7Smillert /* A list of legal values for the LANG or LC_CTYPE environment variables.
551acd27e7Smillert If a locale name in this list is the value for the LC_ALL, LC_CTYPE,
561acd27e7Smillert or LANG environment variable (using the first of those with a value),
571acd27e7Smillert readline eight-bit mode is enabled. */
581acd27e7Smillert static char *legal_lang_values[] =
591acd27e7Smillert {
601acd27e7Smillert "iso88591",
611acd27e7Smillert "iso88592",
621acd27e7Smillert "iso88593",
631acd27e7Smillert "iso88594",
641acd27e7Smillert "iso88595",
651acd27e7Smillert "iso88596",
661acd27e7Smillert "iso88597",
671acd27e7Smillert "iso88598",
681acd27e7Smillert "iso88599",
691acd27e7Smillert "iso885910",
701acd27e7Smillert "koi8r",
711acd27e7Smillert 0
721acd27e7Smillert };
731acd27e7Smillert
74*af70c2dfSkettenis static char *normalize_codeset PARAMS((char *));
75*af70c2dfSkettenis static char *find_codeset PARAMS((char *, size_t *));
761acd27e7Smillert #endif /* !HAVE_SETLOCALE */
771acd27e7Smillert
781acd27e7Smillert /* Check for LC_ALL, LC_CTYPE, and LANG and use the first with a value
791acd27e7Smillert to decide the defaults for 8-bit character input and output. Returns
801acd27e7Smillert 1 if we set eight-bit mode. */
811acd27e7Smillert int
_rl_init_eightbit()821acd27e7Smillert _rl_init_eightbit ()
831acd27e7Smillert {
841acd27e7Smillert /* If we have setlocale(3), just check the current LC_CTYPE category
851acd27e7Smillert value, and go into eight-bit mode if it's not C or POSIX. */
861acd27e7Smillert #if defined (HAVE_SETLOCALE)
871acd27e7Smillert char *t;
881acd27e7Smillert
891acd27e7Smillert /* Set the LC_CTYPE locale category from environment variables. */
901acd27e7Smillert t = setlocale (LC_CTYPE, "");
911acd27e7Smillert if (t && *t && (t[0] != 'C' || t[1]) && (STREQ (t, "POSIX") == 0))
921acd27e7Smillert {
931acd27e7Smillert _rl_meta_flag = 1;
941acd27e7Smillert _rl_convert_meta_chars_to_ascii = 0;
951acd27e7Smillert _rl_output_meta_chars = 1;
961acd27e7Smillert return (1);
971acd27e7Smillert }
981acd27e7Smillert else
991acd27e7Smillert return (0);
1001acd27e7Smillert
1011acd27e7Smillert #else /* !HAVE_SETLOCALE */
1021acd27e7Smillert char *lspec, *t;
1031acd27e7Smillert int i;
1041acd27e7Smillert
1051acd27e7Smillert /* We don't have setlocale. Finesse it. Check the environment for the
1061acd27e7Smillert appropriate variables and set eight-bit mode if they have the right
1071acd27e7Smillert values. */
108*af70c2dfSkettenis lspec = sh_get_env_value ("LC_ALL");
109*af70c2dfSkettenis if (lspec == 0 || *lspec == '\0') lspec = sh_get_env_value ("LC_CTYPE");
110*af70c2dfSkettenis if (lspec == 0 || *lspec == '\0') lspec = sh_get_env_value ("LANG");
11194bc1d69Smillert if (lspec == 0 || *lspec == '\0' || (t = normalize_codeset (lspec)) == 0)
1121acd27e7Smillert return (0);
1131acd27e7Smillert for (i = 0; t && legal_lang_values[i]; i++)
1141acd27e7Smillert if (STREQ (t, legal_lang_values[i]))
1151acd27e7Smillert {
1161acd27e7Smillert _rl_meta_flag = 1;
1171acd27e7Smillert _rl_convert_meta_chars_to_ascii = 0;
1181acd27e7Smillert _rl_output_meta_chars = 1;
1191acd27e7Smillert break;
1201acd27e7Smillert }
1211acd27e7Smillert free (t);
1221acd27e7Smillert return (legal_lang_values[i] ? 1 : 0);
1231acd27e7Smillert
1241acd27e7Smillert #endif /* !HAVE_SETLOCALE */
1251acd27e7Smillert }
1261acd27e7Smillert
1271acd27e7Smillert #if !defined (HAVE_SETLOCALE)
1281acd27e7Smillert static char *
normalize_codeset(codeset)1291acd27e7Smillert normalize_codeset (codeset)
1301acd27e7Smillert char *codeset;
1311acd27e7Smillert {
1321acd27e7Smillert size_t namelen, i;
1331acd27e7Smillert int len, all_digits;
1341acd27e7Smillert char *wp, *retval;
1351acd27e7Smillert
1361acd27e7Smillert codeset = find_codeset (codeset, &namelen);
1371acd27e7Smillert
1381acd27e7Smillert if (codeset == 0)
1391acd27e7Smillert return (codeset);
1401acd27e7Smillert
1411acd27e7Smillert all_digits = 1;
1421acd27e7Smillert for (len = 0, i = 0; i < namelen; i++)
1431acd27e7Smillert {
144*af70c2dfSkettenis if (ISALNUM ((unsigned char)codeset[i]))
1451acd27e7Smillert {
1461acd27e7Smillert len++;
147*af70c2dfSkettenis all_digits &= _rl_digit_p (codeset[i]);
1481acd27e7Smillert }
1491acd27e7Smillert }
1501acd27e7Smillert
1511acd27e7Smillert retval = (char *)malloc ((all_digits ? 3 : 0) + len + 1);
1521acd27e7Smillert if (retval == 0)
1531acd27e7Smillert return ((char *)0);
1541acd27e7Smillert
1551acd27e7Smillert wp = retval;
1561acd27e7Smillert /* Add `iso' to beginning of an all-digit codeset */
1571acd27e7Smillert if (all_digits)
1581acd27e7Smillert {
1591acd27e7Smillert *wp++ = 'i';
1601acd27e7Smillert *wp++ = 's';
1611acd27e7Smillert *wp++ = 'o';
1621acd27e7Smillert }
1631acd27e7Smillert
1641acd27e7Smillert for (i = 0; i < namelen; i++)
165*af70c2dfSkettenis if (ISALPHA ((unsigned char)codeset[i]))
166*af70c2dfSkettenis *wp++ = _rl_to_lower (codeset[i]);
167*af70c2dfSkettenis else if (_rl_digit_p (codeset[i]))
1681acd27e7Smillert *wp++ = codeset[i];
1691acd27e7Smillert *wp = '\0';
1701acd27e7Smillert
1711acd27e7Smillert return retval;
1721acd27e7Smillert }
1731acd27e7Smillert
1741acd27e7Smillert /* Isolate codeset portion of locale specification. */
1751acd27e7Smillert static char *
find_codeset(name,lenp)1761acd27e7Smillert find_codeset (name, lenp)
1771acd27e7Smillert char *name;
1781acd27e7Smillert size_t *lenp;
1791acd27e7Smillert {
1801acd27e7Smillert char *cp, *language, *result;
1811acd27e7Smillert
1821acd27e7Smillert cp = language = name;
1831acd27e7Smillert result = (char *)0;
1841acd27e7Smillert
1851acd27e7Smillert while (*cp && *cp != '_' && *cp != '@' && *cp != '+' && *cp != ',')
1861acd27e7Smillert cp++;
1871acd27e7Smillert
1881acd27e7Smillert /* This does not make sense: language has to be specified. As
1891acd27e7Smillert an exception we allow the variable to contain only the codeset
1901acd27e7Smillert name. Perhaps there are funny codeset names. */
1911acd27e7Smillert if (language == cp)
1921acd27e7Smillert {
1931acd27e7Smillert *lenp = strlen (language);
1941acd27e7Smillert result = language;
1951acd27e7Smillert }
1961acd27e7Smillert else
1971acd27e7Smillert {
1981acd27e7Smillert /* Next is the territory. */
1991acd27e7Smillert if (*cp == '_')
2001acd27e7Smillert do
2011acd27e7Smillert ++cp;
2021acd27e7Smillert while (*cp && *cp != '.' && *cp != '@' && *cp != '+' && *cp != ',' && *cp != '_');
2031acd27e7Smillert
2041acd27e7Smillert /* Now, finally, is the codeset. */
2051acd27e7Smillert result = cp;
2061acd27e7Smillert if (*cp == '.')
2071acd27e7Smillert do
2081acd27e7Smillert ++cp;
2091acd27e7Smillert while (*cp && *cp != '@');
2101acd27e7Smillert
2111acd27e7Smillert if (cp - result > 2)
2121acd27e7Smillert {
2131acd27e7Smillert result++;
2141acd27e7Smillert *lenp = cp - result;
2151acd27e7Smillert }
2161acd27e7Smillert else
2171acd27e7Smillert {
2181acd27e7Smillert *lenp = strlen (language);
2191acd27e7Smillert result = language;
2201acd27e7Smillert }
2211acd27e7Smillert }
2221acd27e7Smillert
2231acd27e7Smillert return result;
2241acd27e7Smillert }
2251acd27e7Smillert #endif /* !HAVE_SETLOCALE */
226