NS_IMETHODIMP 
nsPlatformCharset::GetDefaultCharsetForLocale(const nsAString& localeName, nsACString &oResult)
{
  // 
  // if this locale is the user's locale then use the charset 
  // we already determined at initialization
  // 
  if (mLocale.Equals(localeName) ||
    // support the 4.x behavior
    (mLocale.LowerCaseEqualsLiteral("en_us") && 
     localeName.LowerCaseEqualsLiteral("c"))) {
    oResult = mCharset;
    return NS_OK;
  }

#if HAVE_LANGINFO_CODESET
  //
  // This locale appears to be a different locale from the user's locale. 
  // To do this we would need to lock the global resource we are currently 
  // using or use a library that provides multi locale support. 
  // ICU is a possible example of a multi locale library.
  //     http://oss.software.ibm.com/icu/
  //
  // A more common cause of hitting this warning than the above is that 
  // Mozilla is launched under an ll_CC.UTF-8 locale. In xpLocale, 
  // we only store the language and the region (ll-CC) losing 'UTF-8', which
  // leads |mLocale| to be different from |localeName|. Although we lose
  // 'UTF-8', we init'd |mCharset| with the value obtained via 
  // |nl_langinfo(CODESET)| so that we're all right here.
  // 
  NS_WARNING("GetDefaultCharsetForLocale: need to add multi locale support");
#ifdef DEBUG_jungshik
  printf("localeName=%s mCharset=%s\n", NS_ConvertUTF16toUTF8(localeName).get(),
         mCharset.get());
#endif
  // until we add multi locale support: use the the charset of the user's locale
  oResult = mCharset;
  return NS_SUCCESS_USING_FALLBACK_LOCALE;
#else
  //
  // convert from locale to charset
  // using the deprecated locale to charset mapping 
  //
  nsAutoString localeStr(localeName);
  nsresult res = ConvertLocaleToCharsetUsingDeprecatedConfig(localeStr, oResult);
  if (NS_SUCCEEDED(res))
    return res;

  NS_ERROR("unable to convert locale to charset using deprecated config");
  oResult.AssignLiteral("ISO-8859-1");
  return NS_SUCCESS_USING_FALLBACK_LOCALE;
#endif
}
nsresult
nsPlatformCharset::InitGetCharset(nsACString &oString)
{
  char* nl_langinfo_codeset = nsnull;
  nsCString aCharset;
  nsresult res;

#if HAVE_LANGINFO_CODESET
  nl_langinfo_codeset = nl_langinfo(CODESET);
  NS_ASSERTION(nl_langinfo_codeset, "cannot get nl_langinfo(CODESET)");

  //
  // see if we can use nl_langinfo(CODESET) directly
  //
  if (nl_langinfo_codeset) {
    aCharset.Assign(nl_langinfo_codeset);
    res = VerifyCharset(aCharset);
    if (NS_SUCCEEDED(res)) {
      oString = aCharset;
      return res;
    }
  }

  NS_ERROR("unable to use nl_langinfo(CODESET)");
#endif

  //
  // try falling back on a deprecated (locale based) name
  //
  char* locale = setlocale(LC_CTYPE, nsnull);
  nsAutoString localeStr;
  localeStr.AssignWithConversion(locale);
  res = ConvertLocaleToCharsetUsingDeprecatedConfig(localeStr, oString);
  if (NS_SUCCEEDED(res)) {
    return res; // succeeded
  }

  oString.Truncate();
  return res;
}
nsresult
nsPlatformCharset::InitGetCharset(nsACString &oString)
{
  char* nl_langinfo_codeset = nsnull;
  nsCString aCharset;
  nsresult res;

#if HAVE_LANGINFO_CODESET
  nl_langinfo_codeset = nl_langinfo(CODESET);
  NS_ASSERTION(nl_langinfo_codeset, "cannot get nl_langinfo(CODESET)");

  //
  // see if we can use nl_langinfo(CODESET) directly
  //
  if (nl_langinfo_codeset) {
    aCharset.Assign(nl_langinfo_codeset);
    res = VerifyCharset(aCharset);
    if (NS_SUCCEEDED(res)) {
      oString = aCharset;
      return res;
    }
  }

  // locked for thread safety 
  {
    nsAutoLock guard(gLock);

    if (!gNLInfo) {
      nsCAutoString propertyFile;
      // note: NS_LITERAL_CSTRING("unixcharset." OSARCH ".properties") does not compile on AIX
      propertyFile.AssignLiteral("unixcharset.");
      propertyFile.AppendLiteral(NS_STRINGIFY(OSARCH));
      propertyFile.AppendLiteral(".properties");
      nsGREResProperties *info = new nsGREResProperties(propertyFile);
      NS_ASSERTION(info, "cannot create nsGREResProperties");
      if (info) {
        PRBool didLoad = info->DidLoad();
        if (!didLoad) {
          delete info;
          info = nsnull;
        }
      }
      gNLInfo = info;
    }
  }

  //
  // See if we are remapping nl_langinfo(CODESET)
  //
  if (gNLInfo && nl_langinfo_codeset) {
    nsAutoString localeKey;

#if HAVE_GNU_GET_LIBC_VERSION
    //
    // look for an glibc version specific charset remap
    //
    const char *glibc_version = gnu_get_libc_version();
    if ((glibc_version != nsnull) && (strlen(glibc_version))) {
      localeKey.AssignLiteral("nllic.");
      localeKey.AppendWithConversion(glibc_version);
      localeKey.AppendLiteral(".");
      localeKey.AppendWithConversion(nl_langinfo_codeset);
      nsAutoString uCharset;
      res = gNLInfo->Get(localeKey, uCharset);
      if (NS_SUCCEEDED(res)) {
        aCharset.AssignWithConversion(uCharset);
        res = VerifyCharset(aCharset);
        if (NS_SUCCEEDED(res)) {
          oString = aCharset;
          return res;
        }
      }
    }
#endif

    //
    // look for a charset specific charset remap
    //
    localeKey.AssignLiteral("nllic.");
    localeKey.AppendWithConversion(nl_langinfo_codeset);
    nsAutoString uCharset;
    res = gNLInfo->Get(localeKey, uCharset);
    if (NS_SUCCEEDED(res)) {
      aCharset.AssignWithConversion(uCharset);
      res = VerifyCharset(aCharset);
      if (NS_SUCCEEDED(res)) {
        oString = aCharset;
        return res;
      }
    }
  }

  NS_ERROR("unable to use nl_langinfo(CODESET)");
#endif

  //
  // try falling back on a deprecated (locale based) name
  //
  char* locale = setlocale(LC_CTYPE, nsnull);
  nsAutoString localeStr;
  localeStr.AssignWithConversion(locale);
  res = ConvertLocaleToCharsetUsingDeprecatedConfig(localeStr, oString);
  if (NS_SUCCEEDED(res)) {
    return res; // succeeded
  }

  oString.Truncate();
  return res;
}