Bug 153586 - Date.toLocaleString() not returning locale string.

r=jst, sr=brendan
This commit is contained in:
tor%cs.brown.edu 2004-06-15 16:38:43 +00:00
parent 8f8f2a8f03
commit 9f26f1dadb
9 changed files with 112 additions and 18 deletions

View File

@ -78,6 +78,9 @@
#include "nsContentUtils.h"
// For locale aware string methods
#include "plstr.h"
#include "nsIPlatformCharset.h"
#include "nsICharsetConverterManager.h"
#include "nsUnicharUtils.h"
#include "nsILocaleService.h"
#include "nsICollation.h"
@ -139,6 +142,7 @@ static nsIScriptSecurityManager *sSecurityManager;
static nsICollation *gCollation;
static nsIUnicodeDecoder *gDecoder;
void JS_DLL_CALLBACK
NS_ScriptErrorReporter(JSContext *cx,
@ -300,6 +304,80 @@ NS_ScriptErrorReporter(JSContext *cx,
::JS_ClearPendingException(cx);
}
JS_STATIC_DLL_CALLBACK(JSBool)
LocaleToUnicode(JSContext *cx, char *src, jsval *rval)
{
nsresult rv;
if (!gDecoder) {
// use app default locale
nsCOMPtr<nsILocaleService> localeService =
do_GetService(NS_LOCALESERVICE_CONTRACTID, &rv);
if (NS_SUCCEEDED(rv)) {
nsCOMPtr<nsILocale> appLocale;
rv = localeService->GetApplicationLocale(getter_AddRefs(appLocale));
if (NS_SUCCEEDED(rv)) {
nsAutoString localeStr;
rv = appLocale->
GetCategory(NS_LITERAL_STRING(NSILOCALE_TIME), localeStr);
NS_ASSERTION(NS_SUCCEEDED(rv), "failed to get app locale info");
nsCOMPtr<nsIPlatformCharset> platformCharset =
do_GetService(NS_PLATFORMCHARSET_CONTRACTID, &rv);
if (NS_SUCCEEDED(rv)) {
nsCAutoString charset;
rv = platformCharset->GetDefaultCharsetForLocale(localeStr, charset);
if (NS_SUCCEEDED(rv)) {
// get/create unicode decoder for charset
nsCOMPtr<nsICharsetConverterManager> ccm =
do_GetService(NS_CHARSETCONVERTERMANAGER_CONTRACTID, &rv);
if (NS_SUCCEEDED(rv))
ccm->GetUnicodeDecoder(charset.get(), &gDecoder);
}
}
}
}
}
JSString *str = nsnull;
PRInt32 srcLength = PL_strlen(src);
if (gDecoder) {
PRInt32 unicharLength = srcLength;
PRUnichar *unichars = (PRUnichar *)malloc((srcLength + 1) * sizeof(PRUnichar));
if (unichars) {
rv = gDecoder->Convert(src, &srcLength, unichars, &unicharLength);
if (NS_SUCCEEDED(rv)) {
// terminate the returned string
unichars[unicharLength] = 0;
// nsIUnicodeDecoder::Convert may use fewer than srcLength PRUnichars
if (unicharLength + 1 < srcLength + 1) {
PRUnichar *shrunkUnichars =
(PRUnichar *)realloc(unichars, (unicharLength + 1) * sizeof(PRUnichar));
if (shrunkUnichars)
unichars = shrunkUnichars;
}
str = JS_NewUCString(cx,
NS_REINTERPRET_CAST(jschar*, unichars),
unicharLength);
}
if (!str)
free(unichars);
}
}
if (!str) {
nsDOMClassInfo::ThrowJSException(cx, NS_ERROR_OUT_OF_MEMORY);
return JS_FALSE;
}
*rval = STRING_TO_JSVAL(str);
return JS_TRUE;
}
static JSBool
ChangeCase(JSContext *cx, JSString *src, jsval *rval,
void(* changeCaseFnc)(const nsAString&, nsAString&))
@ -577,7 +655,8 @@ nsJSContext::nsJSContext(JSRuntime *aRuntime) : mGCOnDestruction(PR_TRUE)
{
LocaleToUpperCase,
LocaleToLowerCase,
LocaleCompare
LocaleCompare,
LocaleToUnicode
};
::JS_SetLocaleCallbacks(mContext, &localeCallbacks);
@ -634,6 +713,7 @@ nsJSContext::~nsJSContext()
NS_IF_RELEASE(sRuntimeService);
NS_IF_RELEASE(sSecurityManager);
NS_IF_RELEASE(gCollation);
NS_IF_RELEASE(gDecoder);
}
}
@ -2045,6 +2125,7 @@ void nsJSEnvironment::ShutDown()
NS_IF_RELEASE(sRuntimeService);
NS_IF_RELEASE(sSecurityManager);
NS_IF_RELEASE(gCollation);
NS_IF_RELEASE(gDecoder);
}
sDidShutdown = PR_TRUE;

View File

@ -192,9 +192,9 @@ nsLocaleService::nsLocaleService(void)
#if (defined(XP_UNIX) && !defined(XP_MACOSX)) || defined(XP_BEOS)
nsCOMPtr<nsIPosixLocale> posixConverter = do_CreateInstance(NS_POSIXLOCALE_CONTRACTID);
nsAutoString xpLocale, platformLocale;
nsAutoString xpLocale;
if (posixConverter) {
nsAutoString category, category_platform;
nsAutoString category;
nsLocale* resultLocale;
int i;
@ -206,27 +206,19 @@ nsLocaleService::nsLocaleService(void)
nsresult result;
char* lc_temp = setlocale(posix_locale_category[i], "");
category.AssignWithConversion(LocaleList[i]);
category_platform.AssignWithConversion(LocaleList[i]);
category_platform.Append(NS_LITERAL_STRING("##PLATFORM"));
if (lc_temp != nsnull) {
result = posixConverter->GetXPLocale(lc_temp, xpLocale);
platformLocale.AssignWithConversion(lc_temp);
} else {
char* lang = getenv("LANG");
if ( lang == nsnull ) {
platformLocale.Assign(NS_LITERAL_STRING("en_US"));
if ( lang == nsnull )
result = posixConverter->GetXPLocale("en-US", xpLocale);
}
else {
else
result = posixConverter->GetXPLocale(lang, xpLocale);
platformLocale.AssignWithConversion(lang);
}
}
if (NS_FAILED(result)) {
return;
}
resultLocale->AddCategory(category, xpLocale);
resultLocale->AddCategory(category_platform, platformLocale);
}
mSystemLocale = do_QueryInterface(resultLocale);
mApplicationLocale = do_QueryInterface(resultLocale);

View File

@ -115,7 +115,7 @@ nsresult nsCollationUnix::Initialize(nsILocale* locale)
mLocale.Assign('C');
nsAutoString localeStr;
NS_NAMED_LITERAL_STRING(aCategory, "NSILOCALE_COLLATE##PLATFORM");
NS_NAMED_LITERAL_STRING(aCategory, "NSILOCALE_COLLATE");
// get locale string, use app default if no locale specified
if (locale == nsnull) {

View File

@ -55,7 +55,7 @@ NS_IMPL_THREADSAFE_ISUPPORTS1(nsDateTimeFormatUnix, nsIDateTimeFormat)
nsresult nsDateTimeFormatUnix::Initialize(nsILocale* locale)
{
nsAutoString localeStr;
NS_NAMED_LITERAL_STRING(aCategory, "NSILOCALE_TIME##PLATFORM");
NS_NAMED_LITERAL_STRING(aCategory, "NSILOCALE_TIME");
nsresult res = NS_OK;
// use cached info if match with stored locale

View File

@ -62,6 +62,7 @@
#include "nsAutoLock.h"
#include "prinit.h"
#include "nsUnicharUtils.h"
#include "nsIPosixLocale.h"
NS_IMPL_THREADSAFE_ISUPPORTS1(nsPlatformCharset, nsIPlatformCharset)
@ -325,7 +326,7 @@ NS_IMETHODIMP
nsPlatformCharset::Init()
{
nsCAutoString charset;
nsresult res;
nsresult res = NS_OK;
//
// remember default locale so we can use the
@ -334,9 +335,14 @@ nsPlatformCharset::Init()
char* locale = setlocale(LC_CTYPE, nsnull);
NS_ASSERTION(locale, "cannot setlocale");
if (locale) {
mLocale.AssignWithConversion(locale);
nsCOMPtr<nsIPosixLocale> posixConverter =
do_CreateInstance(NS_POSIXLOCALE_CONTRACTID);
if (posixConverter)
res = posixConverter->GetXPLocale(locale, mLocale);
if (NS_FAILED(res))
return res;
} else {
mLocale.Assign(NS_LITERAL_STRING("en_US"));
mLocale.Assign(NS_LITERAL_STRING("en-US"));
}
res = InitGetCharset(charset);

View File

@ -1562,6 +1562,7 @@ struct JSLocaleCallbacks {
JSLocaleToUpperCase localeToUpperCase;
JSLocaleToLowerCase localeToLowerCase;
JSLocaleCompare localeCompare;
JSLocaleToUnicode localeToUnicode;
};
/*

View File

@ -52,6 +52,7 @@
#include "jsstddef.h"
#include <ctype.h>
#include <locale.h>
#include <math.h>
#include <stdlib.h>
#include <string.h>
@ -1645,6 +1646,9 @@ date_toLocaleHelper(JSContext *cx, JSObject *obj, uintN argc,
}
if (cx->localeCallbacks && cx->localeCallbacks->localeToUnicode)
return cx->localeCallbacks->localeToUnicode(cx, buf, rval);
str = JS_NewStringCopyZ(cx, buf);
if (!str)
return JS_FALSE;

View File

@ -547,6 +547,9 @@ typedef JSBool
JSString *src1, JSString *src2,
jsval *rval);
typedef JSBool
(* JS_DLL_CALLBACK JSLocaleToUnicode)(JSContext *cx, char *src, jsval *rval);
/*
* Security protocol types.
*/

View File

@ -112,6 +112,8 @@
#include "SpecialSystemDirectory.h"
#include <locale.h>
// Registry Factory creation function defined in nsRegistry.cpp
// We hook into this function locally to create and register the registry
// Since noone outside xpcom needs to know about this and nsRegistry.cpp
@ -440,6 +442,11 @@ nsresult NS_COM NS_InitXPCOM2(nsIServiceManager* *result,
rv = nsMemoryImpl::Startup();
if (NS_FAILED(rv)) return rv;
// If the locale hasn't already been setup by our embedder,
// get us out of the "C" locale and into the system
if (strcmp(setlocale(LC_ALL, NULL), "C") == 0)
setlocale(LC_ALL, "");
#if defined(XP_UNIX) || defined(XP_OS2)
NS_StartupNativeCharsetUtils();
#endif