mirror of
https://github.com/mozilla/gecko-dev.git
synced 2025-02-14 04:03:47 +00:00
checkin for bstell@netscape.com:
bug 54000; r=ftang@netscape.com, sr=erik@netscape.com get charset using ns_langinfo(CODESET) (instead of mapping setlocale(LC_LCTYPE, nsnull);)
This commit is contained in:
parent
dd072af443
commit
9a12a8c928
@ -29,6 +29,17 @@
|
||||
#include "nsLocaleCID.h"
|
||||
#include "nsUConvDll.h"
|
||||
#include "nsIComponentManager.h"
|
||||
#include "nsIServiceManager.h"
|
||||
#include "nsIUnicodeDecoder.h"
|
||||
#include "nsIUnicodeEncoder.h"
|
||||
#include "nsICharsetConverterManager.h"
|
||||
#include "nsICharsetConverterManager2.h"
|
||||
#if HAVE_GNU_LIBC_VERSION_H
|
||||
#include <gnu/libc-version.h>
|
||||
#endif
|
||||
#if HAVE_NL_LANGINFO
|
||||
#include <langinfo.h>
|
||||
#endif
|
||||
|
||||
NS_DEFINE_IID(kIPosixLocaleIID,NS_IPOSIXLOCALE_IID);
|
||||
NS_DEFINE_CID(kPosixLocaleFactoryCID,NS_POSIXLOCALEFACTORY_CID);
|
||||
@ -42,16 +53,23 @@ public:
|
||||
nsUNIXCharset();
|
||||
virtual ~nsUNIXCharset();
|
||||
|
||||
NS_IMETHOD Init();
|
||||
NS_IMETHOD GetCharset(nsPlatformCharsetSel selector, nsString& oResult);
|
||||
NS_IMETHOD GetDefaultCharsetForLocale(const PRUnichar* localeName, PRUnichar** _retValue);
|
||||
|
||||
private:
|
||||
nsString mCharset;
|
||||
nsString mLocale; // remember the locale & charset
|
||||
|
||||
NS_IMETHOD InitGetCharset(nsString&);
|
||||
NS_IMETHOD ConvertLocaleToCharsetUsingDeprecatedConfig(nsAutoString&, nsString&);
|
||||
NS_IMETHOD VerifyCharset(nsString &aCharset);
|
||||
};
|
||||
|
||||
NS_IMPL_ISUPPORTS(nsUNIXCharset, kIPlatformCharsetIID);
|
||||
|
||||
static nsURLProperties *gInfo = nsnull;
|
||||
static nsURLProperties *gNLInfo = nsnull;
|
||||
static nsURLProperties *gInfo_deprecated = nsnull;
|
||||
static PRInt32 gCnt=0;
|
||||
|
||||
nsUNIXCharset::nsUNIXCharset()
|
||||
@ -59,48 +77,61 @@ nsUNIXCharset::nsUNIXCharset()
|
||||
NS_INIT_REFCNT();
|
||||
PR_AtomicIncrement(&g_InstanceCount);
|
||||
PR_AtomicIncrement(&gCnt);
|
||||
}
|
||||
|
||||
char* locale = setlocale(LC_CTYPE, "");
|
||||
NS_ASSERTION(locale, "cannot setlocale");
|
||||
NS_IMETHODIMP
|
||||
nsUNIXCharset::ConvertLocaleToCharsetUsingDeprecatedConfig(nsAutoString& locale, nsString& oResult)
|
||||
{
|
||||
|
||||
// XXX we should make the following block critical section
|
||||
if(nsnull == gInfo)
|
||||
// XXX for thread safety the following block should be locked
|
||||
if(nsnull == gInfo_deprecated)
|
||||
{
|
||||
nsAutoString propertyURL;
|
||||
propertyURL.AssignWithConversion("resource:/res/unixcharset.properties");
|
||||
nsURLProperties *info = new nsURLProperties( propertyURL );
|
||||
NS_ASSERTION( info, "cannot create nsURLProperties");
|
||||
gInfo = info;
|
||||
gInfo_deprecated = info;
|
||||
}
|
||||
|
||||
if(gInfo && locale)
|
||||
if(gInfo_deprecated && locale.Length())
|
||||
{
|
||||
nsAutoString platformLocaleKey;
|
||||
platformLocaleKey.AssignWithConversion("locale." OSTYPE ".");
|
||||
platformLocaleKey.AppendWithConversion(locale);
|
||||
// note: NS_LITERAL_STRING("locale." OSTYPE ".") does not compile on AIX
|
||||
platformLocaleKey.Assign(NS_LITERAL_STRING("locale."));
|
||||
platformLocaleKey.AppendWithConversion(OSTYPE);
|
||||
platformLocaleKey.Append(NS_LITERAL_STRING("."));
|
||||
platformLocaleKey.Append(locale.get());
|
||||
|
||||
nsresult res = gInfo->Get(platformLocaleKey, mCharset);
|
||||
if(NS_FAILED(res))
|
||||
{
|
||||
nsAutoString localeKey;
|
||||
localeKey.AssignWithConversion("locale.all.");
|
||||
localeKey.AppendWithConversion(locale);
|
||||
res = gInfo->Get(localeKey, mCharset);
|
||||
if(NS_SUCCEEDED(res)) {
|
||||
return; // succeeded
|
||||
}
|
||||
nsresult res = gInfo_deprecated->Get(platformLocaleKey, oResult);
|
||||
if(NS_SUCCEEDED(res)) {
|
||||
return NS_OK;
|
||||
}
|
||||
nsAutoString localeKey;
|
||||
localeKey.Assign(NS_LITERAL_STRING("locale.all."));
|
||||
localeKey.Append(locale.get());
|
||||
res = gInfo_deprecated->Get(localeKey, oResult);
|
||||
if(NS_SUCCEEDED(res)) {
|
||||
return NS_OK;
|
||||
}
|
||||
}
|
||||
NS_ASSERTION(0, "unable to convert locale to charset using deprecated config");
|
||||
mCharset.AssignWithConversion("ISO-8859-1");
|
||||
return; // failed
|
||||
return NS_ERROR_USING_FALLBACK_LOCALE;
|
||||
}
|
||||
|
||||
nsUNIXCharset::~nsUNIXCharset()
|
||||
{
|
||||
PR_AtomicDecrement(&g_InstanceCount);
|
||||
PR_AtomicDecrement(&gCnt);
|
||||
if(0 == gCnt) {
|
||||
delete gInfo;
|
||||
gInfo = nsnull;
|
||||
if (gNLInfo) {
|
||||
delete gNLInfo;
|
||||
gNLInfo = nsnull;
|
||||
}
|
||||
if (gInfo_deprecated) {
|
||||
delete gInfo_deprecated;
|
||||
gInfo_deprecated = nsnull;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -114,44 +145,49 @@ nsUNIXCharset::GetCharset(nsPlatformCharsetSel selector, nsString& oResult)
|
||||
NS_IMETHODIMP
|
||||
nsUNIXCharset::GetDefaultCharsetForLocale(const PRUnichar* localeName, PRUnichar** _retValue)
|
||||
{
|
||||
nsCOMPtr<nsIPosixLocale> pPosixLocale;
|
||||
nsString charset, localeNameAsString(localeName);
|
||||
charset.AssignWithConversion("ISO-8859-1");
|
||||
char posix_locale[128];
|
||||
nsAutoString localeNameAsString(localeName);
|
||||
|
||||
//
|
||||
// convert the locale name
|
||||
//
|
||||
nsresult rv = nsComponentManager::CreateInstance(kPosixLocaleFactoryCID,nsnull,
|
||||
kIPosixLocaleIID,
|
||||
getter_AddRefs(pPosixLocale));
|
||||
if (NS_FAILED(rv)) { *_retValue = charset.ToNewUnicode(); return rv; }
|
||||
//
|
||||
// if this locale is the user's locale then use the charset
|
||||
// we already determined at initialization
|
||||
//
|
||||
if (mLocale.Equals(localeNameAsString) ||
|
||||
// support the 4.x behavior
|
||||
(mLocale.EqualsIgnoreCase("en_US") && localeNameAsString.EqualsIgnoreCase("C"))) {
|
||||
*_retValue = mCharset.ToNewUnicode();
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
rv = pPosixLocale->GetPlatformLocale(&localeNameAsString,posix_locale,sizeof(posix_locale));
|
||||
if (NS_FAILED(rv)) { *_retValue = charset.ToNewUnicode(); return rv; }
|
||||
#if HAVE_NL_LANGINFO
|
||||
//
|
||||
// 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/
|
||||
//
|
||||
NS_ASSERTION(0, "GetDefaultCharsetForLocale: need to add multi locale support");
|
||||
// until we add multi locale support: use the the charset of the user's locale
|
||||
*_retValue = mCharset.ToNewUnicode();
|
||||
return NS_ERROR_USING_FALLBACK_LOCALE;
|
||||
#endif
|
||||
|
||||
//
|
||||
// convert from locale to charset
|
||||
// using the deprecated locale to charset mapping
|
||||
//
|
||||
|
||||
if (!gInfo) { *_retValue=charset.ToNewUnicode(); return NS_ERROR_OUT_OF_MEMORY; }
|
||||
|
||||
|
||||
nsAutoString locale_key;
|
||||
locale_key.AssignWithConversion("locale." OSTYPE ".");
|
||||
locale_key.AppendWithConversion(posix_locale);
|
||||
|
||||
rv = gInfo->Get(locale_key,charset);
|
||||
if(NS_FAILED(rv)) {
|
||||
locale_key.AssignWithConversion("locale.all.");
|
||||
locale_key.AppendWithConversion(posix_locale);
|
||||
rv = gInfo->Get(locale_key,charset);
|
||||
if(NS_FAILED(rv)) { charset.AssignWithConversion("ISO-8859-1"); }
|
||||
nsAutoString localeStr(localeName);
|
||||
nsString charset;
|
||||
nsresult res = ConvertLocaleToCharsetUsingDeprecatedConfig(localeStr, charset);
|
||||
if (NS_SUCCEEDED(res)) {
|
||||
*_retValue = charset.ToNewUnicode();
|
||||
return res; // succeeded
|
||||
}
|
||||
|
||||
*_retValue = charset.ToNewUnicode();
|
||||
return rv;
|
||||
|
||||
NS_ASSERTION(0, "unable to convert locale to charset using deprecated config");
|
||||
charset.Assign(NS_LITERAL_STRING("ISO-8859-1"));
|
||||
*_retValue=charset.ToNewUnicode();
|
||||
return NS_ERROR_USING_FALLBACK_LOCALE;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
@ -173,10 +209,209 @@ NS_NewPlatformCharset(nsISupports* aOuter,
|
||||
*aResult = nsnull;
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
}
|
||||
nsresult res = inst->QueryInterface(aIID, aResult);
|
||||
nsresult res = inst->Init();
|
||||
if (NS_FAILED(res)) {
|
||||
if (res != NS_ERROR_USING_FALLBACK_LOCALE) {
|
||||
delete inst;
|
||||
return res;
|
||||
}
|
||||
}
|
||||
|
||||
res = inst->QueryInterface(aIID, aResult);
|
||||
if (NS_FAILED(res)) {
|
||||
*aResult = nsnull;
|
||||
delete inst;
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsUNIXCharset::InitGetCharset(nsString &oString)
|
||||
{
|
||||
char* nl_langinfo_codeset = nsnull;
|
||||
nsString aCharset;
|
||||
nsresult res;
|
||||
|
||||
#if HAVE_NL_LANGINFO
|
||||
nl_langinfo_codeset = nl_langinfo(CODESET);
|
||||
NS_ASSERTION(nl_langinfo_codeset, "cannot get nl_langinfo(CODESET)");
|
||||
|
||||
// XXX for thread safety the following block should be locked
|
||||
if(nsnull == gNLInfo) {
|
||||
nsAutoString propertyURL;
|
||||
// note: NS_LITERAL_STRING("resource:/res/unixcharset." OSARCH ".properties") does not compile on AIX
|
||||
propertyURL.Assign(NS_LITERAL_STRING("resource:/res/unixcharset."));
|
||||
propertyURL.AppendWithConversion(OSARCH);
|
||||
propertyURL.Append(NS_LITERAL_STRING(".properties"));
|
||||
nsURLProperties *info;
|
||||
info = new nsURLProperties( propertyURL );
|
||||
NS_ASSERTION( info, "cannot create nsURLProperties");
|
||||
if (info) {
|
||||
PRBool didLoad;
|
||||
info->DidLoad(didLoad);
|
||||
if (!didLoad) {
|
||||
delete info;
|
||||
info = nsnull;
|
||||
}
|
||||
}
|
||||
gNLInfo = info;
|
||||
}
|
||||
#endif
|
||||
|
||||
//
|
||||
// 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.Assign(NS_LITERAL_STRING("nllic."));
|
||||
localeKey.AppendWithConversion(glibc_version);
|
||||
localeKey.Append(NS_LITERAL_STRING("."));
|
||||
localeKey.AppendWithConversion(nl_langinfo_codeset);
|
||||
res = gNLInfo->Get(localeKey, aCharset);
|
||||
if (NS_SUCCEEDED(res)) {
|
||||
res = VerifyCharset(aCharset);
|
||||
if (NS_SUCCEEDED(res)) {
|
||||
oString = aCharset;
|
||||
return res;
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
//
|
||||
// look for a charset specific charset remap
|
||||
//
|
||||
localeKey.Assign(NS_LITERAL_STRING("nllic."));
|
||||
localeKey.AppendWithConversion(nl_langinfo_codeset);
|
||||
res = gNLInfo->Get(localeKey, aCharset);
|
||||
if (NS_SUCCEEDED(res)) {
|
||||
res = VerifyCharset(aCharset);
|
||||
if (NS_SUCCEEDED(res)) {
|
||||
oString = aCharset;
|
||||
return res;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// Did not find a charset override so
|
||||
// see if we can use nl_langinfo(CODESET) directly
|
||||
//
|
||||
if (nl_langinfo_codeset) {
|
||||
aCharset.AssignWithConversion(nl_langinfo_codeset);
|
||||
res = VerifyCharset(aCharset);
|
||||
if (NS_SUCCEEDED(res)) {
|
||||
oString = aCharset;
|
||||
return res;
|
||||
}
|
||||
}
|
||||
|
||||
#if HAVE_NL_LANGINFO
|
||||
NS_ASSERTION(0, "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, aCharset);
|
||||
if (NS_SUCCEEDED(res)) {
|
||||
oString = aCharset;
|
||||
return res; // succeeded
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsUNIXCharset::Init()
|
||||
{
|
||||
nsString charset;
|
||||
nsresult res;
|
||||
|
||||
//
|
||||
// remember default locale so we can use the
|
||||
// same charset when asked for the same locale
|
||||
//
|
||||
char* locale = setlocale(LC_CTYPE, nsnull);
|
||||
NS_ASSERTION(locale, "cannot setlocale");
|
||||
if (locale) {
|
||||
mLocale.AssignWithConversion(locale);
|
||||
} else {
|
||||
mLocale.Assign(NS_LITERAL_STRING("en_US"));
|
||||
}
|
||||
|
||||
res = InitGetCharset(charset);
|
||||
if (NS_SUCCEEDED(res)) {
|
||||
mCharset = charset;
|
||||
return res; // succeeded
|
||||
}
|
||||
|
||||
// last resort fallback
|
||||
NS_ASSERTION(0, "unable to convert locale to charset using deprecated config");
|
||||
mCharset.Assign(NS_LITERAL_STRING("ISO-8859-1"));
|
||||
return NS_ERROR_USING_FALLBACK_LOCALE;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsUNIXCharset::VerifyCharset(nsString &aCharset)
|
||||
{
|
||||
nsresult res;
|
||||
//
|
||||
// get the convert manager
|
||||
//
|
||||
nsCOMPtr <nsICharsetConverterManager2> charsetConverterManager;
|
||||
charsetConverterManager = do_GetService(NS_CHARSETCONVERTERMANAGER_CONTRACTID, &res);
|
||||
if (NS_FAILED(res))
|
||||
return res;
|
||||
|
||||
//
|
||||
// check if we recognize the charset string
|
||||
//
|
||||
nsCOMPtr <nsIAtom> charsetAtom;
|
||||
res = charsetConverterManager->GetCharsetAtom(aCharset.GetUnicode(),
|
||||
getter_AddRefs(charsetAtom));
|
||||
if (NS_FAILED(res)) {
|
||||
return res;
|
||||
}
|
||||
|
||||
//
|
||||
// check if we can get an input converter
|
||||
//
|
||||
nsCOMPtr <nsIUnicodeEncoder> enc;
|
||||
res = charsetConverterManager->GetUnicodeEncoder(charsetAtom, getter_AddRefs(enc));
|
||||
if (NS_FAILED(res)) {
|
||||
NS_ASSERTION(0, "failed to create encoder");
|
||||
return res;
|
||||
}
|
||||
|
||||
//
|
||||
// check if we can get an output converter
|
||||
//
|
||||
nsCOMPtr <nsIUnicodeDecoder> dec;
|
||||
res = charsetConverterManager->GetUnicodeDecoder(charsetAtom, getter_AddRefs(dec));
|
||||
if (NS_FAILED(res)) {
|
||||
NS_ASSERTION(0, "failed to create decoder");
|
||||
return res;
|
||||
}
|
||||
|
||||
//
|
||||
// return the preferred string
|
||||
//
|
||||
const PRUnichar *prefName;
|
||||
res = charsetAtom->GetUnicode(&prefName);
|
||||
if (NS_SUCCEEDED(res))
|
||||
aCharset.Assign(prefName);
|
||||
NS_ASSERTION(NS_SUCCEEDED(res), "failed to get preferred charset name, using non-preferred");
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user