charset.c
上传用户:riyaled888
上传日期:2009-03-27
资源大小:7338k
文件大小:10k
源码类别:

多媒体

开发平台:

MultiPlatform

  1. /*****************************************************************************
  2.  * charset.c: Determine a canonical name for the current locale's character
  3.  *            encoding.
  4.  *****************************************************************************
  5.  * Copyright (C) 2003-2004 VideoLAN
  6.  * $Id: charset.c 8905 2004-10-04 13:34:42Z gbazin $
  7.  *
  8.  * Author: Derk-Jan Hartman <thedj at users.sf.net>
  9.  *
  10.  * vlc_current_charset() an adaption of mp_locale_charset():
  11.  *
  12.  *  Copyright (C) 2001-2003 The Mape Project
  13.  *  Written by Karel Zak  <zakkr@zf.jcu.cz>.
  14.  *
  15.  * This program is free software; you can redistribute it and/or modify
  16.  * it under the terms of the GNU General Public License as published by
  17.  * the Free Software Foundation; either version 2 of the License, or
  18.  * (at your option) any later version.
  19.  *
  20.  * This program is distributed in the hope that it will be useful,
  21.  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  22.  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  23.  * GNU General Public License for more details.
  24.  *
  25.  * You should have received a copy of the GNU General Public License
  26.  * along with this program; if not, write to the Free Software
  27.  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111, USA.
  28.  *****************************************************************************/
  29. #include <stdlib.h>
  30. #include <stdio.h>
  31. #include <vlc/vlc.h>
  32. #if !defined WIN32
  33. # if HAVE_LANGINFO_CODESET
  34. #  include <langinfo.h>
  35. # else
  36. #  if HAVE_SETLOCALE
  37. #   include <locale.h>
  38. #  endif
  39. # endif
  40. #elif defined WIN32
  41. # include <windows.h>
  42. #endif
  43. #include "charset.h"
  44. typedef struct VLCCharsetAlias
  45. {
  46.     char *psz_alias, *psz_name;
  47. } VLCCharsetAlias;
  48. /*
  49.  * The libcharset load all from external text file, but it's strange and
  50.  * slow solution, we rather use array(s) compiled into source. In the
  51.  * "good" libc this is not needful -- for example in linux.
  52.  *
  53.  * Please, put to this funtion exotic aliases only. The libc 'iconv' knows
  54.  * a lot of basic aliases (check it first by iconv -l).
  55.  *
  56.  */
  57. static const char* vlc_encoding_from_language( const char *l )
  58. {
  59.     /* check for language (and perhaps country) codes */
  60.     if (strstr(l, "zh_TW")) return "Big5";
  61.     if (strstr(l, "zh_HK")) return "Big5HKSCS";   /* no MIME charset */
  62.     if (strstr(l, "zh")) return "GB2312";
  63.     if (strstr(l, "th")) return "TIS-620";
  64.     if (strstr(l, "ja")) return "EUC-JP";
  65.     if (strstr(l, "ko")) return "EUC-KR";
  66.     if (strstr(l, "ru")) return "KOI8-R";
  67.     if (strstr(l, "uk")) return "KOI8-U";
  68.     if (strstr(l, "pl") || strstr(l, "hr") ||
  69.         strstr(l, "hu") || strstr(l, "cs") ||
  70.         strstr(l, "sk") || strstr(l, "sl")) return "ISO-8859-2";
  71.     if (strstr(l, "eo") || strstr(l, "mt")) return "ISO-8859-3";
  72.     if (strstr(l, "lt") || strstr(l, "la")) return "ISO-8859-4";
  73.     if (strstr(l, "bg") || strstr(l, "be") ||
  74.         strstr(l, "mk") || strstr(l, "uk")) return "ISO-8859-5";
  75.     if (strstr(l, "ar")) return "ISO-8859-6";
  76.     if (strstr(l, "el")) return "ISO-8859-7";
  77.     if (strstr(l, "he") || strstr(l, "iw")) return "ISO-8859-8";
  78.     if (strstr(l, "tr")) return "ISO-8859-9";
  79.     if (strstr(l, "th")) return "ISO-8859-11";
  80.     if (strstr(l, "lv")) return "ISO-8859-13";
  81.     if (strstr(l, "cy")) return "ISO-8859-14";
  82.     if (strstr(l, "et")) return "ISO-8859-15"; /* all latin1 could be iso15 as well */
  83.     if (strstr(l, "ro")) return "ISO-8859-2";   /* or ISO-8859-16 */
  84.     if (strstr(l, "am") || strstr(l, "vi")) return "UTF-8";
  85.     /* We don't know. This ain't working go to default. */
  86.     return "ISO-8859-1";
  87. }
  88. static const char* vlc_charset_aliases( const char *psz_name )
  89. {
  90.     VLCCharsetAlias     *a;
  91. #if defined WIN32
  92.     VLCCharsetAlias aliases[] =
  93.     {
  94.         { "CP936",      "GBK" },
  95.         { "CP1361",     "JOHAB" },
  96.         { "CP20127",    "ASCII" },
  97.         { "CP20866",    "KOI8-R" },
  98.         { "CP21866",    "KOI8-RU" },
  99.         { "CP28591",    "ISO-8859-1" },
  100.         { "CP28592",    "ISO-8859-2" },
  101.         { "CP28593",    "ISO-8859-3" },
  102.         { "CP28594",    "ISO-8859-4" },
  103.         { "CP28595",    "ISO-8859-5" },
  104.         { "CP28596",    "ISO-8859-6" },
  105.         { "CP28597",    "ISO-8859-7" },
  106.         { "CP28598",    "ISO-8859-8" },
  107.         { "CP28599",    "ISO-8859-9" },
  108.         { "CP28605",    "ISO-8859-15" },
  109.         { NULL,         NULL }
  110.     };
  111. #elif SYS_AIX
  112.     VLCCharsetAlias aliases[] =
  113.     {
  114.         { "IBM-850",    "CP850" },
  115.         { "IBM-856",    "CP856" },
  116.         { "IBM-921",    "ISO-8859-13" },
  117.         { "IBM-922",    "CP922" },
  118.         { "IBM-932",    "CP932" },
  119.         { "IBM-943",    "CP943" },
  120.         { "IBM-1046",   "CP1046" },
  121.         { "IBM-1124",   "CP1124" },
  122.         { "IBM-1129",   "CP1129" },
  123.         { "IBM-1252",   "CP1252" },
  124.         { "IBM-EUCCN",  "GB2312" },
  125.         { "IBM-EUCJP",  "EUC-JP" },
  126.         { "IBM-EUCKR",  "EUC-KR" },
  127.         { "IBM-EUCTW",  "EUC-TW" },
  128.         { NULL, NULL }
  129.     };
  130. #elif SYS_HPUX
  131.     VLCCharsetAlias aliases[] =
  132.     {
  133.         { "ROMAN8",     "HP-ROMAN8" },
  134.         { "ARABIC8",    "HP-ARABIC8" },
  135.         { "GREEK8",     "HP-GREEK8" },
  136.         { "HEBREW8",    "HP-HEBREW8" },
  137.         { "TURKISH8",   "HP-TURKISH8" },
  138.         { "KANA8",      "HP-KANA8" },
  139.         { "HP15CN",     "GB2312" },
  140.         { NULL, NULL }
  141.     };
  142. #elif SYS_IRIX
  143.     VLCCharsetAlias aliases[] =
  144.     {
  145.         { "EUCCN",      "GB2312" },
  146.         { NULL, NULL }
  147.     };
  148. #elif SYS_OSF
  149.     VLCCharsetAlias aliases[] =
  150.     {
  151.         { "KSC5601",    "CP949" },
  152.         { "SDECKANJI",  "EUC-JP" },
  153.         { "TACTIS",     "TIS-620" },
  154.         { NULL, NULL }
  155.     };
  156. #elif SYS_SOLARIS
  157.     VLCCharsetAlias aliases[] =
  158.     {
  159.         { "646",        "ASCII" },
  160.         { "CNS11643",   "EUC-TW" },
  161.         { "5601",       "EUC-KR" },
  162.         { "JOHAP92",    "JOHAB" },
  163.         { "PCK",        "SHIFT_JIS" },
  164.         { "2533",       "TIS-620" },
  165.         { NULL, NULL }
  166.     };
  167. #elif SYS_BSD
  168.     VLCCharsetAlias aliases[] =
  169.     {
  170.         { "646", " ASCII" },
  171.         { "EUCCN", "GB2312" },
  172.         { NULL, NULL }
  173.     };
  174. #else
  175.     VLCCharsetAlias aliases[] = {{NULL, NULL}};
  176. #endif
  177.     if( aliases )
  178.     {
  179.         for (a = aliases; a->psz_alias; a++)
  180.             if (strcasecmp (a->psz_alias, psz_name) == 0)
  181.                 return a->psz_name;
  182.     }
  183.     /* we return original name beacuse iconv() probably will know
  184.      * something better about name if we don't know it :-) */
  185.     return psz_name;
  186. }
  187. /* Returns charset from "language_COUNTRY.charset@modifier" string */
  188. static char *vlc_encoding_from_locale( char *psz_locale )
  189. {
  190.     char *psz_dot = strchr( psz_locale, '.' );
  191.     if( psz_dot != NULL )
  192.     {
  193.         const char *psz_modifier;
  194.         static char buf[2 + 10 + 1];
  195.         psz_dot++;
  196.         /* Look for the possible @... trailer and remove it, if any.  */
  197.         psz_modifier = strchr( psz_dot, '@' );
  198.         if( psz_modifier == NULL )
  199.             return psz_dot;
  200.         if( 0 < ( psz_modifier - psz_dot ) < sizeof( buf ))
  201.         {
  202.             memcpy( buf, psz_dot, psz_modifier - psz_dot );
  203.             buf[ psz_modifier - psz_dot ] = '';
  204.             return buf;
  205.         }
  206.     }
  207.     /* try language mapping */
  208.     return (char *)vlc_encoding_from_language( psz_locale );
  209. }
  210. vlc_bool_t vlc_current_charset( char **psz_charset )
  211. {
  212.     const char *psz_codeset;
  213. #if !(defined WIN32 || defined OS2)
  214. # if HAVE_LANGINFO_CODESET
  215.     /* Most systems support nl_langinfo( CODESET ) nowadays.  */
  216.     psz_codeset = nl_langinfo( CODESET );
  217. # else
  218.     /* On old systems which lack it, use setlocale or getenv.  */
  219.     const char *psz_locale = NULL;
  220.     /* But most old systems don't have a complete set of locales.  Some
  221.      * (like SunOS 4 or DJGPP) have only the C locale.  Therefore we don't
  222.      * use setlocale here; it would return "C" when it doesn't support the
  223.      * locale name the user has set. Darwin's setlocale is broken. */
  224. #  if HAVE_SETLOCALE && !SYS_DARWIN
  225.     psz_locale = setlocale( LC_ALL, NULL );
  226. #  endif
  227.     if( psz_locale == NULL || psz_locale[0] == '' )
  228.     {
  229.         psz_locale = getenv( "LC_ALL" );
  230.         if( psz_locale == NULL || psz_locale[0] == '' )
  231.         {
  232.             psz_locale = getenv( "LC_CTYPE" );
  233.             if( psz_locale == NULL || psz_locale[0] == '')
  234.                 psz_locale = getenv( "LANG" );
  235.         }
  236.     }
  237.     /* On some old systems, one used to set locale = "iso8859_1". On others,
  238.      * you set it to "language_COUNTRY.charset". Darwin only has LANG :( */
  239.     psz_codeset = vlc_encoding_from_locale( (char *)psz_locale );
  240. # endif /* HAVE_LANGINFO_CODESET */
  241. #elif defined WIN32
  242.     static char buf[2 + 10 + 1];
  243.     /* Woe32 has a function returning the locale's codepage as a number.  */
  244.     sprintf( buf, "CP%u", GetACP() );
  245.     psz_codeset = buf;
  246. #elif defined OS2
  247.     const char *psz_locale;
  248.     static char buf[2 + 10 + 1];
  249.     ULONG cp[3];
  250.     ULONG cplen;
  251.     /* Allow user to override the codeset, as set in the operating system,
  252.      * with standard language environment variables. */
  253.     psz_locale = getenv( "LC_ALL" );
  254.     if( psz_locale == NULL || psz_locale[0] == '' )
  255.     {
  256.         psz+locale = getenv( "LC_CTYPE" );
  257.         if( psz_locale == NULL || locale[0] == '' )
  258.             locale = getenv( "LANG" );
  259.     }
  260.     if( psz_locale != NULL && psz_locale[0] != '' )
  261.         psz_codeset = vlc_encoding_from_locale( psz_locale );
  262.     else
  263.     {
  264.         /* OS/2 has a function returning the locale's codepage as a number. */
  265.         if( DosQueryCp( sizeof( cp ), cp, &cplen ) )
  266.             psz_codeset = "";
  267.         else
  268.         {
  269.             sprintf( buf, "CP%u", cp[0] );
  270.             psz_codeset = buf;
  271.         }
  272.     }
  273. #endif
  274.     if( psz_codeset == NULL )
  275.         /* The canonical name cannot be determined. */
  276.         psz_codeset = "";
  277.     else
  278.         psz_codeset = vlc_charset_aliases( psz_codeset );
  279.     /* Don't return an empty string.  GNU libc and GNU libiconv interpret
  280.      * the empty string as denoting "the locale's character encoding",
  281.      * thus GNU libiconv would call this function a second time. */
  282.     if( psz_codeset[0] == '' )
  283.     {
  284.         /* Last possibility is 'CHARSET' enviroment variable */
  285.         if( !( psz_codeset = getenv( "CHARSET" ) ) )
  286.             psz_codeset = "ISO-8859-1";
  287.     }
  288.     if( psz_charset )
  289.         *psz_charset = strdup((char *)psz_codeset);
  290.     if( !strcasecmp(psz_codeset, "UTF8") || !strcasecmp(psz_codeset, "UTF-8") )
  291.         return VLC_TRUE;
  292.     return VLC_FALSE;
  293. }