252 lines
		
	
	
	
		
			5.9 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			252 lines
		
	
	
	
		
			5.9 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
/* nls.c -- skeletal internationalization code. */
 | 
						|
 | 
						|
/* Copyright (C) 1996-2009 Free Software Foundation, Inc.
 | 
						|
 | 
						|
   This file is part of the GNU Readline Library (Readline), a library
 | 
						|
   for reading lines of text with interactive input and history editing.      
 | 
						|
 | 
						|
   Readline is free software: you can redistribute it and/or modify
 | 
						|
   it under the terms of the GNU General Public License as published by
 | 
						|
   the Free Software Foundation, either version 3 of the License, or
 | 
						|
   (at your option) any later version.
 | 
						|
 | 
						|
   Readline is distributed in the hope that it will be useful,
 | 
						|
   but WITHOUT ANY WARRANTY; without even the implied warranty of
 | 
						|
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 | 
						|
   GNU General Public License for more details.
 | 
						|
 | 
						|
   You should have received a copy of the GNU General Public License
 | 
						|
   along with Readline.  If not, see <http://www.gnu.org/licenses/>.
 | 
						|
*/
 | 
						|
 | 
						|
#define READLINE_LIBRARY
 | 
						|
 | 
						|
#if defined (HAVE_CONFIG_H)
 | 
						|
#  include <config.h>
 | 
						|
#endif
 | 
						|
 | 
						|
#include <sys/types.h>
 | 
						|
 | 
						|
#include <stdio.h>
 | 
						|
 | 
						|
#if defined (HAVE_UNISTD_H)
 | 
						|
#  include <unistd.h>
 | 
						|
#endif /* HAVE_UNISTD_H */
 | 
						|
 | 
						|
#if defined (HAVE_STDLIB_H)
 | 
						|
#  include <stdlib.h>
 | 
						|
#else
 | 
						|
#  include "ansi_stdlib.h"
 | 
						|
#endif /* HAVE_STDLIB_H */
 | 
						|
 | 
						|
#if defined (HAVE_LOCALE_H)
 | 
						|
#  include <locale.h>
 | 
						|
#endif
 | 
						|
 | 
						|
#include <ctype.h>
 | 
						|
 | 
						|
#include "rldefs.h"
 | 
						|
#include "readline.h"
 | 
						|
#include "rlshell.h"
 | 
						|
#include "rlprivate.h"
 | 
						|
 | 
						|
#if !defined (HAVE_SETLOCALE)    
 | 
						|
/* A list of legal values for the LANG or LC_CTYPE environment variables.
 | 
						|
   If a locale name in this list is the value for the LC_ALL, LC_CTYPE,
 | 
						|
   or LANG environment variable (using the first of those with a value),
 | 
						|
   readline eight-bit mode is enabled. */
 | 
						|
static char *legal_lang_values[] =
 | 
						|
{
 | 
						|
 "iso88591",
 | 
						|
 "iso88592",
 | 
						|
 "iso88593",
 | 
						|
 "iso88594",
 | 
						|
 "iso88595",
 | 
						|
 "iso88596",
 | 
						|
 "iso88597",
 | 
						|
 "iso88598",
 | 
						|
 "iso88599",
 | 
						|
 "iso885910",
 | 
						|
 "koi8r",
 | 
						|
  0
 | 
						|
};
 | 
						|
 | 
						|
static char *normalize_codeset PARAMS((char *));
 | 
						|
static char *find_codeset PARAMS((char *, size_t *));
 | 
						|
#endif /* !HAVE_SETLOCALE */
 | 
						|
 | 
						|
static char *_rl_get_locale_var PARAMS((const char *));
 | 
						|
 | 
						|
static char *
 | 
						|
_rl_get_locale_var (v)
 | 
						|
     const char *v;
 | 
						|
{
 | 
						|
  char *lspec;
 | 
						|
 | 
						|
  lspec = sh_get_env_value ("LC_ALL");
 | 
						|
  if (lspec == 0 || *lspec == 0)
 | 
						|
    lspec = sh_get_env_value (v);
 | 
						|
  if (lspec == 0 || *lspec == 0)
 | 
						|
    lspec = sh_get_env_value ("LANG");
 | 
						|
 | 
						|
  return lspec;
 | 
						|
}
 | 
						|
  
 | 
						|
/* Check for LC_ALL, LC_CTYPE, and LANG and use the first with a value
 | 
						|
   to decide the defaults for 8-bit character input and output.  Returns
 | 
						|
   1 if we set eight-bit mode. */
 | 
						|
int
 | 
						|
_rl_init_eightbit ()
 | 
						|
{
 | 
						|
/* If we have setlocale(3), just check the current LC_CTYPE category
 | 
						|
   value, and go into eight-bit mode if it's not C or POSIX. */
 | 
						|
#if defined (HAVE_SETLOCALE)
 | 
						|
  char *lspec, *t;
 | 
						|
 | 
						|
  /* Set the LC_CTYPE locale category from environment variables. */
 | 
						|
  lspec = _rl_get_locale_var ("LC_CTYPE");
 | 
						|
  /* Since _rl_get_locale_var queries the right environment variables,
 | 
						|
     we query the current locale settings with setlocale(), and, if
 | 
						|
     that doesn't return anything, we set lspec to the empty string to
 | 
						|
     force the subsequent call to setlocale() to define the `native'
 | 
						|
     environment. */
 | 
						|
  if (lspec == 0 || *lspec == 0)
 | 
						|
    lspec = setlocale (LC_CTYPE, (char *)NULL);
 | 
						|
  if (lspec == 0)
 | 
						|
    lspec = "";
 | 
						|
  t = setlocale (LC_CTYPE, lspec);
 | 
						|
 | 
						|
  if (t && *t && (t[0] != 'C' || t[1]) && (STREQ (t, "POSIX") == 0))
 | 
						|
    {
 | 
						|
      _rl_meta_flag = 1;
 | 
						|
      _rl_convert_meta_chars_to_ascii = 0;
 | 
						|
      _rl_output_meta_chars = 1;
 | 
						|
      return (1);
 | 
						|
    }
 | 
						|
  else
 | 
						|
    return (0);
 | 
						|
 | 
						|
#else /* !HAVE_SETLOCALE */
 | 
						|
  char *lspec, *t;
 | 
						|
  int i;
 | 
						|
 | 
						|
  /* We don't have setlocale.  Finesse it.  Check the environment for the
 | 
						|
     appropriate variables and set eight-bit mode if they have the right
 | 
						|
     values. */
 | 
						|
  lspec = _rl_get_locale_var ("LC_CTYPE");
 | 
						|
 | 
						|
  if (lspec == 0 || (t = normalize_codeset (lspec)) == 0)
 | 
						|
    return (0);
 | 
						|
  for (i = 0; t && legal_lang_values[i]; i++)
 | 
						|
    if (STREQ (t, legal_lang_values[i]))
 | 
						|
      {
 | 
						|
	_rl_meta_flag = 1;
 | 
						|
	_rl_convert_meta_chars_to_ascii = 0;
 | 
						|
	_rl_output_meta_chars = 1;
 | 
						|
	break;
 | 
						|
      }
 | 
						|
  xfree (t);
 | 
						|
  return (legal_lang_values[i] ? 1 : 0);
 | 
						|
 | 
						|
#endif /* !HAVE_SETLOCALE */
 | 
						|
}
 | 
						|
 | 
						|
#if !defined (HAVE_SETLOCALE)
 | 
						|
static char *
 | 
						|
normalize_codeset (codeset)
 | 
						|
     char *codeset;
 | 
						|
{
 | 
						|
  size_t namelen, i;
 | 
						|
  int len, all_digits;
 | 
						|
  char *wp, *retval;
 | 
						|
 | 
						|
  codeset = find_codeset (codeset, &namelen);
 | 
						|
 | 
						|
  if (codeset == 0)
 | 
						|
    return (codeset);
 | 
						|
 | 
						|
  all_digits = 1;
 | 
						|
  for (len = 0, i = 0; i < namelen; i++)
 | 
						|
    {
 | 
						|
      if (ISALNUM ((unsigned char)codeset[i]))
 | 
						|
	{
 | 
						|
	  len++;
 | 
						|
	  all_digits &= _rl_digit_p (codeset[i]);
 | 
						|
	}
 | 
						|
    }
 | 
						|
 | 
						|
  retval = (char *)malloc ((all_digits ? 3 : 0) + len + 1);
 | 
						|
  if (retval == 0)
 | 
						|
    return ((char *)0);
 | 
						|
 | 
						|
  wp = retval;
 | 
						|
  /* Add `iso' to beginning of an all-digit codeset */
 | 
						|
  if (all_digits)
 | 
						|
    {
 | 
						|
      *wp++ = 'i';
 | 
						|
      *wp++ = 's';
 | 
						|
      *wp++ = 'o';
 | 
						|
    }
 | 
						|
 | 
						|
  for (i = 0; i < namelen; i++)
 | 
						|
    if (ISALPHA ((unsigned char)codeset[i]))
 | 
						|
      *wp++ = _rl_to_lower (codeset[i]);
 | 
						|
    else if (_rl_digit_p (codeset[i]))
 | 
						|
      *wp++ = codeset[i];
 | 
						|
  *wp = '\0';
 | 
						|
 | 
						|
  return retval;
 | 
						|
}
 | 
						|
 | 
						|
/* Isolate codeset portion of locale specification. */
 | 
						|
static char *
 | 
						|
find_codeset (name, lenp)
 | 
						|
     char *name;
 | 
						|
     size_t *lenp;
 | 
						|
{
 | 
						|
  char *cp, *language, *result;
 | 
						|
 | 
						|
  cp = language = name;
 | 
						|
  result = (char *)0;
 | 
						|
 | 
						|
  while (*cp && *cp != '_' && *cp != '@' && *cp != '+' && *cp != ',')
 | 
						|
    cp++;
 | 
						|
 | 
						|
  /* This does not make sense: language has to be specified.  As
 | 
						|
     an exception we allow the variable to contain only the codeset
 | 
						|
     name.  Perhaps there are funny codeset names.  */
 | 
						|
  if (language == cp) 
 | 
						|
    {
 | 
						|
      *lenp = strlen (language);
 | 
						|
      result = language;
 | 
						|
    }
 | 
						|
  else
 | 
						|
    {
 | 
						|
      /* Next is the territory. */
 | 
						|
      if (*cp == '_')
 | 
						|
	do
 | 
						|
	  ++cp;
 | 
						|
	while (*cp && *cp != '.' && *cp != '@' && *cp != '+' && *cp != ',' && *cp != '_');
 | 
						|
 | 
						|
      /* Now, finally, is the codeset. */
 | 
						|
      result = cp;
 | 
						|
      if (*cp == '.')
 | 
						|
	do
 | 
						|
	  ++cp;
 | 
						|
	while (*cp && *cp != '@');
 | 
						|
 | 
						|
      if (cp - result > 2)
 | 
						|
	{
 | 
						|
	  result++;
 | 
						|
	  *lenp = cp - result;
 | 
						|
	}
 | 
						|
      else
 | 
						|
	{
 | 
						|
	  *lenp = strlen (language);
 | 
						|
	  result = language;
 | 
						|
	}
 | 
						|
    }
 | 
						|
 | 
						|
  return result;
 | 
						|
}
 | 
						|
#endif /* !HAVE_SETLOCALE */
 |