00001 00005 #include "system.h" 00006 #include <langinfo.h> 00007 #include <iconv.h> 00008 #include "debug.h" 00009 00010 static char *locale_encoding = NULL; 00011 static int locale_encoding_is_utf8; 00012 00013 const char * xstrtolocale(const char *str) 00014 { 00015 iconv_t cd; 00016 size_t src_size, dest_size; 00017 char *result, *src, *dest; 00018 00019 if (locale_encoding == NULL) { 00020 const char *encoding = nl_langinfo(CODESET); 00021 locale_encoding = xmalloc(strlen(encoding) + 11); 00022 sprintf(locale_encoding, "%s//TRANSLIT", encoding); 00023 locale_encoding_is_utf8 = strcasecmp(encoding, "UTF-8") == 0; 00024 } 00025 00026 if (!str || !*str || locale_encoding_is_utf8) 00027 return str; 00028 00029 cd = iconv_open(locale_encoding, "UTF-8"); 00030 if (cd == (iconv_t)-1) 00031 return str; 00032 00033 src_size = strlen(str); 00034 dest_size = src_size + 1; 00035 result = xmalloc(dest_size); 00036 src = (char *)str; 00037 dest = result; 00038 for(;;) { 00039 size_t status = iconv(cd, &src, &src_size, &dest, &dest_size); 00040 if (status == (size_t)-1) { 00041 size_t dest_offset; 00042 if (errno != E2BIG) { 00043 free(result); 00044 iconv_close(cd); 00045 return str; 00046 } 00047 dest_offset = dest - result; 00048 dest_size += 16; 00049 result = xrealloc(result, dest_offset + dest_size); 00050 dest = result + dest_offset; 00051 } else if (src_size == 0) { 00052 if (src == NULL) break; 00053 src = NULL; 00054 } 00055 } 00056 iconv_close(cd); 00057 free((void *)str); 00058 if (dest_size == 0) { 00059 size_t dest_offset = dest - result; 00060 result = xrealloc(result, dest_offset + 1); 00061 dest = result + dest_offset; 00062 } 00063 *dest = '\0'; 00064 return result; 00065 }