nls.c revision 26497
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
1021308Sache   as published by the Free Software Foundation; either version 1, 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,
2121308Sache   675 Mass Ave, Cambridge, MA 02139, 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
3021308Sache#if defined (HAVE_UNISTD_H)
3121308Sache#  include <unistd.h>
3221308Sache#endif /* HAVE_UNISTD_H */
3321308Sache
3421308Sache#if defined (HAVE_STDLIB_H)
3521308Sache#  include <stdlib.h>
3621308Sache#else
3721308Sache#  include "ansi_stdlib.h"
3821308Sache#endif /* HAVE_STDLIB_H */
3921308Sache
4021308Sache#if defined (HAVE_LOCALE_H)
4121308Sache#  include <locale.h>
4221308Sache#endif
4321308Sache
4421308Sache#include <ctype.h>
4521308Sache
4621308Sache#include "rldefs.h"
4721308Sache
4821308Sacheextern int _rl_convert_meta_chars_to_ascii;
4921308Sacheextern int _rl_output_meta_chars;
5021308Sacheextern int _rl_meta_flag;
5126497Sache
5226497Sache/* Functions imported from shell.c */
5326497Sacheextern char *get_env_value ();
5426497Sache
5526497Sache#if !defined (HAVE_SETLOCALE)
5621308Sache/* A list of legal values for the LANG or LC_CTYPE environment variables.
5721308Sache   If a locale name in this list is the value for the LC_ALL, LC_CTYPE,
5821308Sache   or LANG environment variable (using the first of those with a value),
5921308Sache   readline eight-bit mode is enabled. */
6021308Sachestatic char *legal_lang_values[] =
6121308Sache{
6221308Sache "iso88591",
6321308Sache "iso88592",
6421308Sache "iso88593",
6521308Sache "iso88594",
6621308Sache "iso88595",
6721308Sache "iso88596",
6821308Sache "iso88597",
6921308Sache "iso88598",
7021308Sache "iso88599",
7121308Sache "iso885910",
7221308Sache "koi8r",
7321308Sache  0
7421308Sache};
7521308Sache
7621308Sachestatic char *normalize_codeset ();
7721308Sachestatic char *find_codeset ();
7826497Sache#endif /* !HAVE_SETLOCALE */
7921308Sache
8021308Sache/* Check for LC_ALL, LC_CTYPE, and LANG and use the first with a value
8121308Sache   to decide the defaults for 8-bit character input and output.  Returns
8221308Sache   1 if we set eight-bit mode. */
8321308Sacheint
8421308Sache_rl_init_eightbit ()
8521308Sache{
8626497Sache/* If we have setlocale(3), just check the current LC_CTYPE category
8726497Sache   value, and go into eight-bit mode if it's not C or POSIX. */
8826497Sache#if defined (HAVE_SETLOCALE)
8926497Sache  char *t;
9026497Sache
9126497Sache  /* Set the LC_CTYPE locale category from environment variables. */
9226497Sache  t = setlocale (LC_CTYPE, "");
9326497Sache  if (t && *t && (t[0] != 'C' || t[1]) && (STREQ (t, "POSIX") == 0))
9426497Sache    {
9526497Sache      _rl_meta_flag = 1;
9626497Sache      _rl_convert_meta_chars_to_ascii = 0;
9726497Sache      _rl_output_meta_chars = 1;
9826497Sache      return (1);
9926497Sache    }
10026497Sache  else
10126497Sache    return (0);
10226497Sache
10326497Sache#else /* !HAVE_SETLOCALE */
10421308Sache  char *lspec, *t;
10521308Sache  int i;
10621308Sache
10726497Sache  /* We don't have setlocale.  Finesse it.  Check the environment for the
10826497Sache     appropriate variables and set eight-bit mode if they have the right
10926497Sache     values. */
11026497Sache  lspec = get_env_value ("LC_ALL");
11126497Sache  if (lspec == 0) lspec = get_env_value ("LC_CTYPE");
11226497Sache  if (lspec == 0) lspec = get_env_value ("LANG");
11321308Sache  if (lspec == 0 || (t = normalize_codeset (lspec)) == 0)
11421308Sache    return (0);
11521308Sache  for (i = 0; t && legal_lang_values[i]; i++)
11621308Sache    if (STREQ (t, legal_lang_values[i]))
11721308Sache      {
11821308Sache	_rl_meta_flag = 1;
11921308Sache	_rl_convert_meta_chars_to_ascii = 0;
12021308Sache	_rl_output_meta_chars = 1;
12121308Sache	break;
12221308Sache      }
12321308Sache  free (t);
12421308Sache  return (legal_lang_values[i] ? 1 : 0);
12526497Sache
12626497Sache#endif /* !HAVE_SETLOCALE */
12721308Sache}
12821308Sache
12926497Sache#if !defined (HAVE_SETLOCALE)
13021308Sachestatic char *
13121308Sachenormalize_codeset (codeset)
13221308Sache     char *codeset;
13321308Sache{
13421308Sache  size_t namelen, i;
13521308Sache  int len, all_digits;
13621308Sache  char *wp, *retval;
13721308Sache
13821308Sache  codeset = find_codeset (codeset, &namelen);
13921308Sache
14021308Sache  if (codeset == 0)
14121308Sache    return (codeset);
14221308Sache
14321308Sache  all_digits = 1;
14421308Sache  for (len = 0, i = 0; i < namelen; i++)
14521308Sache    {
14621308Sache      if (isalnum (codeset[i]))
14721308Sache	{
14821308Sache	  len++;
14921308Sache	  all_digits &= isdigit (codeset[i]);
15021308Sache	}
15121308Sache    }
15221308Sache
15321308Sache  retval = (char *)malloc ((all_digits ? 3 : 0) + len + 1);
15421308Sache  if (retval == 0)
15521308Sache    return ((char *)0);
15621308Sache
15721308Sache  wp = retval;
15821308Sache  /* Add `iso' to beginning of an all-digit codeset */
15921308Sache  if (all_digits)
16021308Sache    {
16121308Sache      *wp++ = 'i';
16221308Sache      *wp++ = 's';
16321308Sache      *wp++ = 'o';
16421308Sache    }
16521308Sache
16621308Sache  for (i = 0; i < namelen; i++)
16721308Sache    if (isalpha (codeset[i]))
16821308Sache      *wp++ = (isupper (codeset[i])) ? tolower (codeset[i]) : codeset[i];
16921308Sache    else if (isdigit (codeset[i]))
17021308Sache      *wp++ = codeset[i];
17121308Sache  *wp = '\0';
17221308Sache
17321308Sache  return retval;
17421308Sache}
17521308Sache
17621308Sache/* Isolate codeset portion of locale specification. */
17721308Sachestatic char *
17821308Sachefind_codeset (name, lenp)
17921308Sache     char *name;
18021308Sache     size_t *lenp;
18121308Sache{
18221308Sache  char *cp, *language, *result;
18321308Sache
18421308Sache  cp = language = name;
18521308Sache  result = (char *)0;
18621308Sache
18721308Sache  while (*cp && *cp != '_' && *cp != '@' && *cp != '+' && *cp != ',')
18821308Sache    cp++;
18921308Sache
19021308Sache  /* This does not make sense: language has to be specified.  As
19121308Sache     an exception we allow the variable to contain only the codeset
19221308Sache     name.  Perhaps there are funny codeset names.  */
19321308Sache  if (language == cp)
19421308Sache    {
19521308Sache      *lenp = strlen (language);
19621308Sache      result = language;
19721308Sache    }
19821308Sache  else
19921308Sache    {
20021308Sache      /* Next is the territory. */
20121308Sache      if (*cp == '_')
20221308Sache	do
20321308Sache	  ++cp;
20421308Sache	while (*cp && *cp != '.' && *cp != '@' && *cp != '+' && *cp != ',' && *cp != '_');
20521308Sache
20621308Sache      /* Now, finally, is the codeset. */
20721308Sache      result = cp;
20821308Sache      if (*cp == '.')
20921308Sache	do
21021308Sache	  ++cp;
21121308Sache	while (*cp && *cp != '@');
21221308Sache
21321308Sache      if (cp - result > 2)
21421308Sache	{
21521308Sache	  result++;
21621308Sache	  *lenp = cp - result;
21721308Sache	}
21821308Sache      else
21921308Sache	{
22021308Sache	  *lenp = strlen (language);
22121308Sache	  result = language;
22221308Sache	}
22321308Sache    }
22421308Sache
22521308Sache  return result;
22621308Sache}
22726497Sache#endif /* !HAVE_SETLOCALE */
228