Commit 92871bdc authored by Rémi Denis-Courmont's avatar Rémi Denis-Courmont

- Make FromLocale() usable any time (after setlocale()) - refs #838

- Fix re-entrancy problem for multiple LibVLC in the same process
parent d4fc12ea
...@@ -101,8 +101,6 @@ static volatile unsigned int i_instances = 0; ...@@ -101,8 +101,6 @@ static volatile unsigned int i_instances = 0;
/***************************************************************************** /*****************************************************************************
* Local prototypes * Local prototypes
*****************************************************************************/ *****************************************************************************/
void LocaleInit( vlc_object_t * );
void LocaleDeinit( void );
static void SetLanguage ( char const * ); static void SetLanguage ( char const * );
static inline int LoadMessages (void); static inline int LoadMessages (void);
static int GetFilenames ( libvlc_int_t *, int, char *[] ); static int GetFilenames ( libvlc_int_t *, int, char *[] );
...@@ -277,12 +275,6 @@ int libvlc_InternalInit( libvlc_int_t *p_libvlc, int i_argc, char *ppsz_argv[] ) ...@@ -277,12 +275,6 @@ int libvlc_InternalInit( libvlc_int_t *p_libvlc, int i_argc, char *ppsz_argv[] )
setlocale( LC_CTYPE, "" ); setlocale( LC_CTYPE, "" );
LoadMessages (); LoadMessages ();
/*
* Global iconv, must be done after setlocale()
* so that vlc_current_charset() works.
*/
LocaleInit( (vlc_object_t *)p_libvlc );
/* Translate "C" to the language code: "fr", "en_GB", "nl", "ru"... */ /* Translate "C" to the language code: "fr", "en_GB", "nl", "ru"... */
msg_Dbg( p_libvlc, "translation test: code is \"%s\"", _("C") ); msg_Dbg( p_libvlc, "translation test: code is \"%s\"", _("C") );
...@@ -1052,9 +1044,6 @@ int libvlc_InternalDestroy( libvlc_int_t *p_libvlc, vlc_bool_t b_release ) ...@@ -1052,9 +1044,6 @@ int libvlc_InternalDestroy( libvlc_int_t *p_libvlc, vlc_bool_t b_release )
{ {
/* System specific cleaning code */ /* System specific cleaning code */
system_End( p_libvlc ); system_End( p_libvlc );
/* Destroy global iconv */
LocaleDeinit();
} }
vlc_mutex_unlock( lockval.p_address ); vlc_mutex_unlock( lockval.p_address );
var_Destroy( p_libvlc_global, "libvlc" ); var_Destroy( p_libvlc_global, "libvlc" );
......
...@@ -72,89 +72,40 @@ ...@@ -72,89 +72,40 @@
# error No UTF8 charset conversion implemented on this platform! # error No UTF8 charset conversion implemented on this platform!
#endif #endif
typedef struct locale_data_t
{
#if defined (USE_ICONV) #if defined (USE_ICONV)
vlc_iconv_t hd; static char charset[sizeof ("CSISO11SWEDISHFORNAMES//translit")] = "";
vlc_mutex_t lock;
#elif defined (USE_MB2MB)
UINT fromCP;
UINT toCP;
#endif
} locale_data_t;
static locale_data_t from_locale, to_locale;
void LocaleInit( vlc_object_t *p_this ) static void find_charset_once (void)
{ {
#if defined USE_ICONV
char *psz_charset; char *psz_charset;
if (vlc_current_charset (&psz_charset)
|| (psz_charset == NULL)
|| ((size_t)snprintf (charset, sizeof (charset), "%s//translit",
psz_charset) >= sizeof (charset)))
strcpy (charset, "UTF-8");
if( vlc_current_charset( &psz_charset ) ) free (psz_charset);
/* UTF-8 */
from_locale.hd = to_locale.hd = (vlc_iconv_t)(-1);
else
{
/* not UTF-8 */
char psz_buf[strlen( psz_charset ) + sizeof( "//translit" )];
const char *psz_conv;
/*
* Still allow non-ASCII characters when the locale is not set.
* Western Europeans are being favored for historical reasons.
*/
if( strcmp( psz_charset, "ASCII" ) )
{
sprintf( psz_buf, "%s//translit", psz_charset );
psz_conv = psz_buf;
}
else
psz_conv = "ISO-8859-1//translit";
vlc_mutex_init( p_this, &from_locale.lock );
vlc_mutex_init( p_this, &to_locale.lock );
from_locale.hd = vlc_iconv_open( "UTF-8", psz_conv );
to_locale.hd = vlc_iconv_open( psz_conv, "UTF-8" );
}
free( psz_charset );
assert( (from_locale.hd == (vlc_iconv_t)(-1))
== (to_locale.hd == (vlc_iconv_t)(-1)) );
#elif defined (USE_MB2MB)
to_locale.toCP = from_locale.fromCP = CP_ACP;
from_locale.toCP = to_locale.fromCP = CP_UTF8;
#else
(void)p_this;
#endif
} }
void LocaleDeinit( void ) static int find_charset (void)
{ {
#ifdef USE_ICONV static pthread_once_t once = PTHREAD_ONCE_INIT;
if( to_locale.hd != (vlc_iconv_t)(-1) ) pthread_once (&once, find_charset_once);
{ return strcmp (charset, "UTF-8");
vlc_iconv_close( to_locale.hd );
vlc_mutex_destroy( &to_locale.lock );
}
if( from_locale.hd != (vlc_iconv_t)(-1) )
{
vlc_iconv_close( from_locale.hd );
vlc_mutex_destroy( &from_locale.lock );
}
#endif
} }
#endif
static char *locale_fast (const char *string, locale_data_t *p) static char *locale_fast (const char *string, vlc_bool_t from)
{ {
#if defined (USE_ICONV) #if defined (USE_ICONV)
vlc_iconv_t hd = p->hd; if (find_charset ())
return (char *)string;
vlc_iconv_t hd = vlc_iconv_open (from ? "UTF-8" : charset,
from ? charset : "UTF-8");
if (hd == (vlc_iconv_t)(-1)) if (hd == (vlc_iconv_t)(-1))
return (char *)string; return strdup (string); /* Uho! */
const char *iptr = string; const char *iptr = string;
size_t inb = strlen (string); size_t inb = strlen (string);
...@@ -164,9 +115,6 @@ static char *locale_fast (const char *string, locale_data_t *p) ...@@ -164,9 +115,6 @@ static char *locale_fast (const char *string, locale_data_t *p)
if (string == NULL) if (string == NULL)
return NULL; return NULL;
vlc_mutex_lock (&p->lock);
vlc_iconv (hd, NULL, NULL, NULL, NULL);
while (vlc_iconv (hd, &iptr, &inb, &optr, &outb) == (size_t)(-1)) while (vlc_iconv (hd, &iptr, &inb, &optr, &outb) == (size_t)(-1))
{ {
*optr++ = '?'; *optr++ = '?';
...@@ -175,8 +123,8 @@ static char *locale_fast (const char *string, locale_data_t *p) ...@@ -175,8 +123,8 @@ static char *locale_fast (const char *string, locale_data_t *p)
inb--; inb--;
vlc_iconv (hd, NULL, NULL, NULL, NULL); vlc_iconv (hd, NULL, NULL, NULL, NULL);
} }
vlc_mutex_unlock (&p->lock);
*optr = '\0'; *optr = '\0';
vlc_iconv_close (hd);
assert (inb == 0); assert (inb == 0);
assert (*iptr == '\0'); assert (*iptr == '\0');
...@@ -190,10 +138,11 @@ static char *locale_fast (const char *string, locale_data_t *p) ...@@ -190,10 +138,11 @@ static char *locale_fast (const char *string, locale_data_t *p)
if (string == NULL) if (string == NULL)
return NULL; return NULL;
len = 1 + MultiByteToWideChar (p->fromCP, 0, string, -1, NULL, 0); len = 1 + MultiByteToWideChar (from ? CP_ACP : CP_UTF8,
0, string, -1, NULL, 0);
wchar_t wide[len]; wchar_t wide[len];
MultiByteToWideChar (p->fromCP, 0, string, -1, wide, len); MultiByteToWideChar (from ? CP_UTF8 : CP_ACP, 0, string, -1, wide, len);
len = 1 + WideCharToMultiByte (p->toCP, 0, wide, -1, NULL, 0, NULL, NULL); len = 1 + WideCharToMultiByte (p->toCP, 0, wide, -1, NULL, 0, NULL, NULL);
out = malloc (len); out = malloc (len);
if (out == NULL) if (out == NULL)
...@@ -207,14 +156,14 @@ static char *locale_fast (const char *string, locale_data_t *p) ...@@ -207,14 +156,14 @@ static char *locale_fast (const char *string, locale_data_t *p)
} }
static inline char *locale_dup (const char *string, locale_data_t *p) static inline char *locale_dup (const char *string, vlc_bool_t from)
{ {
#if defined (USE_ICONV) #if defined (USE_ICONV)
return (p->hd == (vlc_iconv_t)(-1)) if (find_charset ())
? strdup (string) return strdup (string);
: locale_fast (string, p); return locale_fast (string, from);
#elif defined (USE_MB2MB) #elif defined (USE_MB2MB)
return locale_fast (string, p); return locale_fast (string, from);
#else #else
return strdup (string); return strdup (string);
#endif #endif
...@@ -224,10 +173,7 @@ static inline char *locale_dup (const char *string, locale_data_t *p) ...@@ -224,10 +173,7 @@ static inline char *locale_dup (const char *string, locale_data_t *p)
void LocaleFree (const char *str) void LocaleFree (const char *str)
{ {
#if defined (USE_ICONV) #if defined (USE_ICONV)
assert ((to_locale.hd == (vlc_iconv_t)(-1)) if (strcmp (charset, "UTF-8"))
== (from_locale.hd == (vlc_iconv_t)(-1)));
if( to_locale.hd != (vlc_iconv_t)(-1) )
free ((char *)str); free ((char *)str);
#elif defined (USE_MB2MB) #elif defined (USE_MB2MB)
free ((char *)str); free ((char *)str);
...@@ -246,12 +192,12 @@ void LocaleFree (const char *str) ...@@ -246,12 +192,12 @@ void LocaleFree (const char *str)
*/ */
char *FromLocale (const char *locale) char *FromLocale (const char *locale)
{ {
return locale_fast (locale, &from_locale); return locale_fast (locale, VLC_TRUE);
} }
char *FromLocaleDup (const char *locale) char *FromLocaleDup (const char *locale)
{ {
return locale_dup (locale, &from_locale); return locale_dup (locale, VLC_TRUE);
} }
...@@ -266,13 +212,13 @@ char *FromLocaleDup (const char *locale) ...@@ -266,13 +212,13 @@ char *FromLocaleDup (const char *locale)
*/ */
char *ToLocale (const char *utf8) char *ToLocale (const char *utf8)
{ {
return locale_fast (utf8, &to_locale); return locale_fast (utf8, VLC_FALSE);
} }
static char *ToLocaleDup (const char *utf8) static char *ToLocaleDup (const char *utf8)
{ {
return locale_dup (utf8, &to_locale); return locale_dup (utf8, VLC_FALSE);
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment