121308Sache/* nls.c -- skeletal internationalization code. */ 221308Sache 321308Sache/* Copyright (C) 1996 Free Software Foundation, Inc. 421308Sache 521308Sache This file is part of the GNU Readline Library, a library for 621308Sache reading lines of text with interactive input and history editing. 721308Sache 821308Sache The GNU Readline Library is free software; you can redistribute it 921308Sache and/or modify it under the terms of the GNU General Public License 1058310Sache as published by the Free Software Foundation; either version 2, or 1121308Sache (at your option) any later version. 1221308Sache 1321308Sache The GNU Readline Library is distributed in the hope that it will be 1421308Sache useful, but WITHOUT ANY WARRANTY; without even the implied warranty 1521308Sache of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 1621308Sache GNU General Public License for more details. 1721308Sache 1821308Sache The GNU General Public License is often shipped with GNU software, and 1921308Sache is generally kept in a file called COPYING or LICENSE. If you do not 2021308Sache have a copy of the license, write to the Free Software Foundation, 2158310Sache 59 Temple Place, Suite 330, Boston, MA 02111 USA. */ 2221308Sache#define READLINE_LIBRARY 2321308Sache 2421308Sache#if defined (HAVE_CONFIG_H) 2521308Sache# include <config.h> 2621308Sache#endif 2721308Sache 2826497Sache#include <sys/types.h> 2926497Sache 3058310Sache#include <stdio.h> 3158310Sache 3221308Sache#if defined (HAVE_UNISTD_H) 3321308Sache# include <unistd.h> 3421308Sache#endif /* HAVE_UNISTD_H */ 3521308Sache 3621308Sache#if defined (HAVE_STDLIB_H) 3721308Sache# include <stdlib.h> 3821308Sache#else 3921308Sache# include "ansi_stdlib.h" 4021308Sache#endif /* HAVE_STDLIB_H */ 4121308Sache 4221308Sache#if defined (HAVE_LOCALE_H) 4321308Sache# include <locale.h> 4421308Sache#endif 4521308Sache 4621308Sache#include <ctype.h> 4721308Sache 4821308Sache#include "rldefs.h" 4958310Sache#include "readline.h" 5058310Sache#include "rlshell.h" 5158310Sache#include "rlprivate.h" 5221308Sache 5326497Sache#if !defined (HAVE_SETLOCALE) 5421308Sache/* A list of legal values for the LANG or LC_CTYPE environment variables. 5521308Sache If a locale name in this list is the value for the LC_ALL, LC_CTYPE, 5621308Sache or LANG environment variable (using the first of those with a value), 5721308Sache readline eight-bit mode is enabled. */ 5821308Sachestatic char *legal_lang_values[] = 5921308Sache{ 6021308Sache "iso88591", 6121308Sache "iso88592", 6221308Sache "iso88593", 6321308Sache "iso88594", 6421308Sache "iso88595", 6521308Sache "iso88596", 6621308Sache "iso88597", 6721308Sache "iso88598", 6821308Sache "iso88599", 6921308Sache "iso885910", 7035486Sache "koi8r", 7121308Sache 0 7221308Sache}; 7321308Sache 74119610Sachestatic char *normalize_codeset PARAMS((char *)); 75119610Sachestatic char *find_codeset PARAMS((char *, size_t *)); 7626497Sache#endif /* !HAVE_SETLOCALE */ 7721308Sache 78136644Sachestatic char *_rl_get_locale_var PARAMS((const char *)); 79136644Sache 80136644Sachestatic char * 81136644Sache_rl_get_locale_var (v) 82136644Sache const char *v; 83136644Sache{ 84136644Sache char *lspec; 85136644Sache 86136644Sache lspec = sh_get_env_value ("LC_ALL"); 87136644Sache if (lspec == 0 || *lspec == 0) 88136644Sache lspec = sh_get_env_value (v); 89136644Sache if (lspec == 0 || *lspec == 0) 90136644Sache lspec = sh_get_env_value ("LANG"); 91136644Sache 92136644Sache return lspec; 93136644Sache} 94136644Sache 9521308Sache/* Check for LC_ALL, LC_CTYPE, and LANG and use the first with a value 9621308Sache to decide the defaults for 8-bit character input and output. Returns 9721308Sache 1 if we set eight-bit mode. */ 9821308Sacheint 9921308Sache_rl_init_eightbit () 10021308Sache{ 10126497Sache/* If we have setlocale(3), just check the current LC_CTYPE category 10226497Sache value, and go into eight-bit mode if it's not C or POSIX. */ 10326497Sache#if defined (HAVE_SETLOCALE) 104136644Sache char *lspec, *t; 10526497Sache 10626497Sache /* Set the LC_CTYPE locale category from environment variables. */ 107136644Sache lspec = _rl_get_locale_var ("LC_CTYPE"); 108136644Sache /* Since _rl_get_locale_var queries the right environment variables, 109136644Sache we query the current locale settings with setlocale(), and, if 110136644Sache that doesn't return anything, we set lspec to the empty string to 111136644Sache force the subsequent call to setlocale() to define the `native' 112136644Sache environment. */ 113136644Sache if (lspec == 0 || *lspec == 0) 114136644Sache lspec = setlocale (LC_CTYPE, (char *)NULL); 115136644Sache if (lspec == 0) 116136644Sache lspec = ""; 117136644Sache t = setlocale (LC_CTYPE, lspec); 118136644Sache 11926497Sache if (t && *t && (t[0] != 'C' || t[1]) && (STREQ (t, "POSIX") == 0)) 12026497Sache { 12126497Sache _rl_meta_flag = 1; 12226497Sache _rl_convert_meta_chars_to_ascii = 0; 12326497Sache _rl_output_meta_chars = 1; 12426497Sache return (1); 12526497Sache } 12626497Sache else 12726497Sache return (0); 12826497Sache 12926497Sache#else /* !HAVE_SETLOCALE */ 13021308Sache char *lspec, *t; 13121308Sache int i; 13221308Sache 13326497Sache /* We don't have setlocale. Finesse it. Check the environment for the 13426497Sache appropriate variables and set eight-bit mode if they have the right 13526497Sache values. */ 136136644Sache lspec = _rl_get_locale_var ("LC_CTYPE"); 137136644Sache 13821308Sache if (lspec == 0 || (t = normalize_codeset (lspec)) == 0) 13921308Sache return (0); 14021308Sache for (i = 0; t && legal_lang_values[i]; i++) 14121308Sache if (STREQ (t, legal_lang_values[i])) 14221308Sache { 14321308Sache _rl_meta_flag = 1; 14421308Sache _rl_convert_meta_chars_to_ascii = 0; 14521308Sache _rl_output_meta_chars = 1; 14621308Sache break; 14721308Sache } 14821308Sache free (t); 14921308Sache return (legal_lang_values[i] ? 1 : 0); 15026497Sache 15126497Sache#endif /* !HAVE_SETLOCALE */ 15221308Sache} 15321308Sache 15426497Sache#if !defined (HAVE_SETLOCALE) 15521308Sachestatic char * 15621308Sachenormalize_codeset (codeset) 15721308Sache char *codeset; 15821308Sache{ 15921308Sache size_t namelen, i; 16021308Sache int len, all_digits; 16121308Sache char *wp, *retval; 16221308Sache 16321308Sache codeset = find_codeset (codeset, &namelen); 16421308Sache 16521308Sache if (codeset == 0) 16621308Sache return (codeset); 16721308Sache 16821308Sache all_digits = 1; 16921308Sache for (len = 0, i = 0; i < namelen; i++) 17021308Sache { 171119610Sache if (ISALNUM ((unsigned char)codeset[i])) 17221308Sache { 17321308Sache len++; 174119610Sache all_digits &= _rl_digit_p (codeset[i]); 17521308Sache } 17621308Sache } 17721308Sache 17821308Sache retval = (char *)malloc ((all_digits ? 3 : 0) + len + 1); 17921308Sache if (retval == 0) 18021308Sache return ((char *)0); 18121308Sache 18221308Sache wp = retval; 18321308Sache /* Add `iso' to beginning of an all-digit codeset */ 18421308Sache if (all_digits) 18521308Sache { 18621308Sache *wp++ = 'i'; 18721308Sache *wp++ = 's'; 18821308Sache *wp++ = 'o'; 18921308Sache } 19021308Sache 19121308Sache for (i = 0; i < namelen; i++) 192119610Sache if (ISALPHA ((unsigned char)codeset[i])) 193119610Sache *wp++ = _rl_to_lower (codeset[i]); 194119610Sache else if (_rl_digit_p (codeset[i])) 19521308Sache *wp++ = codeset[i]; 19621308Sache *wp = '\0'; 19721308Sache 19821308Sache return retval; 19921308Sache} 20021308Sache 20121308Sache/* Isolate codeset portion of locale specification. */ 20221308Sachestatic char * 20321308Sachefind_codeset (name, lenp) 20421308Sache char *name; 20521308Sache size_t *lenp; 20621308Sache{ 20721308Sache char *cp, *language, *result; 20821308Sache 20921308Sache cp = language = name; 21021308Sache result = (char *)0; 21121308Sache 21221308Sache while (*cp && *cp != '_' && *cp != '@' && *cp != '+' && *cp != ',') 21321308Sache cp++; 21421308Sache 21521308Sache /* This does not make sense: language has to be specified. As 21621308Sache an exception we allow the variable to contain only the codeset 21721308Sache name. Perhaps there are funny codeset names. */ 21821308Sache if (language == cp) 21921308Sache { 22021308Sache *lenp = strlen (language); 22121308Sache result = language; 22221308Sache } 22321308Sache else 22421308Sache { 22521308Sache /* Next is the territory. */ 22621308Sache if (*cp == '_') 22721308Sache do 22821308Sache ++cp; 22921308Sache while (*cp && *cp != '.' && *cp != '@' && *cp != '+' && *cp != ',' && *cp != '_'); 23021308Sache 23121308Sache /* Now, finally, is the codeset. */ 23221308Sache result = cp; 23321308Sache if (*cp == '.') 23421308Sache do 23521308Sache ++cp; 23621308Sache while (*cp && *cp != '@'); 23721308Sache 23821308Sache if (cp - result > 2) 23921308Sache { 24021308Sache result++; 24121308Sache *lenp = cp - result; 24221308Sache } 24321308Sache else 24421308Sache { 24521308Sache *lenp = strlen (language); 24621308Sache result = language; 24721308Sache } 24821308Sache } 24921308Sache 25021308Sache return result; 25121308Sache} 25226497Sache#endif /* !HAVE_SETLOCALE */ 253