зеркало из https://github.com/mozilla/pjs.git
Added nsLocaleService
This commit is contained in:
Родитель
1e8968f433
Коммит
e8fafec233
|
@ -0,0 +1,454 @@
|
|||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
*
|
||||
* The contents of this file are subject to the Netscape Public License
|
||||
* Version 1.0 (the "NPL"); you may not use this file except in
|
||||
* compliance with the NPL. You may obtain a copy of the NPL at
|
||||
* http://www.mozilla.org/NPL/
|
||||
*
|
||||
* Software distributed under the NPL is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
|
||||
* for the specific language governing rights and limitations under the
|
||||
* NPL.
|
||||
*
|
||||
* The Initial Developer of this code under the NPL is Netscape
|
||||
* Communications Corporation. Portions created by Netscape are
|
||||
* Copyright (C) 1998 Netscape Communications Corporation. All Rights
|
||||
* Reserved.
|
||||
*/
|
||||
|
||||
#include "nsCOMPtr.h"
|
||||
#include "nsILocale.h"
|
||||
#include "nsILocaleService.h"
|
||||
#include "nsLocaleFactory.h"
|
||||
#include "nsLocale.h"
|
||||
#include "nsLocaleCID.h"
|
||||
#include "nsIComponentManager.h"
|
||||
|
||||
#include <ctype.h>
|
||||
|
||||
#ifdef XP_PC
|
||||
#include "nsIWin32Locale.h"
|
||||
#endif
|
||||
|
||||
//
|
||||
// iids
|
||||
//
|
||||
static NS_DEFINE_IID(kILocaleDefinitionIID,NS_ILOCALEDEFINITION_IID);
|
||||
static NS_DEFINE_IID(kILocaleServiceIID,NS_ILOCALESERVICE_IID);
|
||||
static NS_DEFINE_IID(kILocaleIID,NS_ILOCALE_IID);
|
||||
static NS_DEFINE_IID(kIFactoryIID,NS_IFACTORY_IID);
|
||||
#ifdef XP_PC
|
||||
static NS_DEFINE_IID(kIWin32LocaleIID,NS_IWIN32LOCALE_IID);
|
||||
#endif
|
||||
|
||||
//
|
||||
// cids
|
||||
//
|
||||
#ifdef XP_PC
|
||||
static NS_DEFINE_CID(kWin32LocaleFactoryCID, NS_WIN32LOCALEFACTORY_CID);
|
||||
#endif
|
||||
|
||||
//
|
||||
// implementation constants
|
||||
const int LocaleListLength = 6;
|
||||
const char* LocaleList[LocaleListLength] =
|
||||
{
|
||||
NSILOCALE_COLLATE,
|
||||
NSILOCALE_CTYPE,
|
||||
NSILOCALE_MONETARY,
|
||||
NSILOCALE_NUMERIC,
|
||||
NSILOCALE_TIME,
|
||||
NSILOCALE_MESSAGE
|
||||
};
|
||||
|
||||
#define NSILOCALE_MAX_ACCEPT_LANGUAGE 16
|
||||
#define NSILOCALE_MAX_ACCEPT_LENGTH 18
|
||||
|
||||
|
||||
//
|
||||
// nsILocaleService implementation
|
||||
//
|
||||
class nsLocaleService: public nsILocaleService {
|
||||
|
||||
public:
|
||||
|
||||
//
|
||||
// nsISupports
|
||||
//
|
||||
NS_DECL_ISUPPORTS
|
||||
|
||||
//
|
||||
// nsILocaleService
|
||||
//
|
||||
NS_IMETHOD NewLocale(const PRUnichar *aLocale, nsILocale **_retval);
|
||||
NS_IMETHOD NewLocaleObject(nsILocaleDefinition *localeDefinition, nsILocale **_retval);
|
||||
NS_IMETHOD GetSystemLocale(nsILocale **_retval);
|
||||
NS_IMETHOD GetApplicationLocale(nsILocale **_retval);
|
||||
NS_IMETHOD GetLocaleFromAcceptLanguage(const char *acceptLanguage, nsILocale **_retval);
|
||||
|
||||
//
|
||||
// implementation methods
|
||||
//
|
||||
static nsresult GetLocaleService(nsILocaleService** localeService);
|
||||
|
||||
protected:
|
||||
|
||||
nsLocaleService(void);
|
||||
virtual ~nsLocaleService(void);
|
||||
|
||||
nsresult SetSystemLocale(void);
|
||||
nsresult SetApplicationLocale(void);
|
||||
|
||||
nsILocale* mSystemLocale;
|
||||
nsILocale* mApplicationLocale;
|
||||
static nsILocaleService* gLocaleService;
|
||||
|
||||
};
|
||||
|
||||
//
|
||||
// nsILocaleDefinition implementation
|
||||
//
|
||||
class nsLocaleDefinition: public nsILocaleDefinition {
|
||||
friend class nsLocaleService;
|
||||
|
||||
public:
|
||||
|
||||
//
|
||||
// nsISupports
|
||||
//
|
||||
NS_DECL_ISUPPORTS
|
||||
|
||||
//
|
||||
// nsILocaleDefintion
|
||||
//
|
||||
NS_IMETHOD SetLocaleCategory(const PRUnichar *category, const PRUnichar *value);
|
||||
|
||||
protected:
|
||||
|
||||
nsLocaleDefinition();
|
||||
virtual ~nsLocaleDefinition();
|
||||
|
||||
nsLocale* mLocaleDefinition;
|
||||
};
|
||||
|
||||
|
||||
nsILocaleService* nsLocaleService::gLocaleService = NS_STATIC_CAST(nsILocaleService*,nsnull);
|
||||
|
||||
|
||||
//
|
||||
// nsLocaleService methods
|
||||
//
|
||||
nsLocaleService::nsLocaleService(void)
|
||||
: mSystemLocale(nsnull), mApplicationLocale(nsnull)
|
||||
{
|
||||
NS_INIT_REFCNT();
|
||||
#ifdef XP_PC
|
||||
nsIWin32Locale* win32Converter;
|
||||
nsString xpLocale;
|
||||
nsresult result = nsComponentManager::CreateInstance(kWin32LocaleFactoryCID,
|
||||
NULL,kIWin32LocaleIID,(void**)&win32Converter);
|
||||
NS_ASSERTION(win32Converter!=NULL,"nsLocaleService: can't get win32 converter\n");
|
||||
if (result==NS_OK && win32Converter!=nsnull) {
|
||||
|
||||
//
|
||||
// get the system LCID
|
||||
//
|
||||
LCID win_lcid = GetSystemDefaultLCID();
|
||||
if (win_lcid==0) { win32Converter->Release(); return;}
|
||||
result = win32Converter->GetXPLocale(win_lcid,&xpLocale);
|
||||
if (result!=NS_OK) { win32Converter->Release(); return;}
|
||||
result = NewLocale(xpLocale.ToNewUnicode(),&mSystemLocale);
|
||||
if (result!=NS_OK) { win32Converter->Release(); return;}
|
||||
|
||||
//
|
||||
// get the application LCID
|
||||
//
|
||||
win_lcid = GetSystemDefaultLCID();
|
||||
if (win_lcid==0) { win32Converter->Release(); return;}
|
||||
result = win32Converter->GetXPLocale(win_lcid,&xpLocale);
|
||||
if (result!=NS_OK) { win32Converter->Release(); return;}
|
||||
result = NewLocale(xpLocale.ToNewUnicode(),&mApplicationLocale);
|
||||
if (result!=NS_OK) { win32Converter->Release(); return;}
|
||||
|
||||
win32Converter->Release();
|
||||
}
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
nsLocaleService::~nsLocaleService(void)
|
||||
{
|
||||
gLocaleService = NS_STATIC_CAST(nsILocaleService*,nsnull);
|
||||
if (mSystemLocale) mSystemLocale->Release();
|
||||
if (mApplicationLocale) mApplicationLocale->Release();
|
||||
}
|
||||
|
||||
NS_IMETHODIMP_(nsrefcnt)
|
||||
nsLocaleService::AddRef(void)
|
||||
{
|
||||
return 2;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP_(nsrefcnt)
|
||||
nsLocaleService::Release(void)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
NS_IMPL_QUERY_INTERFACE(nsLocaleService, kILocaleServiceIID);
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsLocaleService::NewLocale(const PRUnichar *aLocale, nsILocale **_retval)
|
||||
{
|
||||
int i;
|
||||
nsresult result;
|
||||
|
||||
*_retval = (nsILocale*)nsnull;
|
||||
|
||||
nsLocale* resultLocale = new nsLocale();
|
||||
if (!resultLocale) return NS_ERROR_OUT_OF_MEMORY;
|
||||
|
||||
for(i=0;i<LocaleListLength;i++) {
|
||||
nsString category = LocaleList[i];
|
||||
result = resultLocale->AddCategory(category.ToNewUnicode(),aLocale);
|
||||
if (result!=NS_OK) { delete resultLocale; return result;}
|
||||
}
|
||||
|
||||
return resultLocale->QueryInterface(kILocaleIID,(void**)_retval);
|
||||
}
|
||||
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsLocaleService::NewLocaleObject(nsILocaleDefinition *localeDefinition, nsILocale **_retval)
|
||||
{
|
||||
if (!localeDefinition || !_retval) return NS_ERROR_INVALID_ARG;
|
||||
|
||||
nsLocale* new_locale = new nsLocale(NS_STATIC_CAST(nsLocaleDefinition*,localeDefinition)->mLocaleDefinition);
|
||||
if (!new_locale) return NS_ERROR_OUT_OF_MEMORY;
|
||||
|
||||
return new_locale->QueryInterface(kILocaleIID,(void**)_retval);
|
||||
}
|
||||
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsLocaleService::GetSystemLocale(nsILocale **_retval)
|
||||
{
|
||||
if (mSystemLocale) {
|
||||
mSystemLocale->AddRef();
|
||||
*_retval = mSystemLocale;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
*_retval = (nsILocale*)nsnull;
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsLocaleService::GetApplicationLocale(nsILocale **_retval)
|
||||
{
|
||||
if (mApplicationLocale) {
|
||||
mApplicationLocale->AddRef();
|
||||
*_retval = mApplicationLocale;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
*_retval=(nsILocale*)nsnull;
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsLocaleService::GetLocaleFromAcceptLanguage(const char *acceptLanguage, nsILocale **_retval)
|
||||
{
|
||||
char* input;
|
||||
char* cPtr;
|
||||
char* cPtr1;
|
||||
char* cPtr2;
|
||||
int i;
|
||||
int j;
|
||||
int countLang = 0;
|
||||
char acceptLanguageList[NSILOCALE_MAX_ACCEPT_LANGUAGE][NSILOCALE_MAX_ACCEPT_LENGTH];
|
||||
nsresult result;
|
||||
|
||||
input = new char[strlen(acceptLanguage)+1];
|
||||
NS_ASSERTION(input!=nsnull,"nsLocaleFactory::GetLocaleFromAcceptLanguage: memory allocation failed.");
|
||||
if (input == (char*)NULL){ return NS_ERROR_OUT_OF_MEMORY; }
|
||||
|
||||
strcpy(input, acceptLanguage);
|
||||
cPtr1 = input-1;
|
||||
cPtr2 = input;
|
||||
|
||||
/* put in standard form */
|
||||
while (*(++cPtr1)) {
|
||||
if (isalpha(*cPtr1)) *cPtr2++ = tolower(*cPtr1); /* force lower case */
|
||||
else if (isspace(*cPtr1)); /* ignore any space */
|
||||
else if (*cPtr1=='-') *cPtr2++ = '_'; /* "-" -> "_" */
|
||||
else if (*cPtr1=='*'); /* ignore "*" */
|
||||
else *cPtr2++ = *cPtr1; /* else unchanged */
|
||||
}
|
||||
*cPtr2 = '\0';
|
||||
|
||||
countLang = 0;
|
||||
|
||||
if (strchr(input,';')) {
|
||||
/* deal with the quality values */
|
||||
|
||||
float qvalue[NSILOCALE_MAX_ACCEPT_LANGUAGE];
|
||||
float qSwap;
|
||||
float bias = 0.0f;
|
||||
char* ptrLanguage[NSILOCALE_MAX_ACCEPT_LANGUAGE];
|
||||
char* ptrSwap;
|
||||
|
||||
/* cPtr = STRTOK(input,"," CPTR2); */
|
||||
cPtr = strtok(input,",");
|
||||
while (cPtr) {
|
||||
qvalue[countLang] = 1.0f;
|
||||
/* add extra parens to get rid of warning */
|
||||
if ((cPtr1 = strchr(cPtr,';'))) {
|
||||
sscanf(cPtr1,";q=%f",&qvalue[countLang]);
|
||||
*cPtr1 = '\0';
|
||||
}
|
||||
if (strlen(cPtr)<NSILOCALE_MAX_ACCEPT_LANGUAGE) { /* ignore if too long */
|
||||
qvalue[countLang] -= (bias += 0.0001f); /* to insure original order */
|
||||
ptrLanguage[countLang++] = cPtr;
|
||||
if (countLang>=NSILOCALE_MAX_ACCEPT_LANGUAGE) break; /* quit if too many */
|
||||
}
|
||||
/* cPtr = STRTOK(NULL,"," CPTR2); */
|
||||
cPtr = strtok(NULL,",");
|
||||
}
|
||||
|
||||
/* sort according to decending qvalue */
|
||||
/* not a very good algorithm, but count is not likely large */
|
||||
for ( i=0 ; i<countLang-1 ; i++ ) {
|
||||
for ( j=i+1 ; j<countLang ; j++ ) {
|
||||
if (qvalue[i]<qvalue[j]) {
|
||||
qSwap = qvalue[i];
|
||||
qvalue[i] = qvalue[j];
|
||||
qvalue[j] = qSwap;
|
||||
ptrSwap = ptrLanguage[i];
|
||||
ptrLanguage[i] = ptrLanguage[j];
|
||||
ptrLanguage[j] = ptrSwap;
|
||||
}
|
||||
}
|
||||
}
|
||||
for ( i=0 ; i<countLang ; i++ ) {
|
||||
strcpy(acceptLanguageList[i],ptrLanguage[i]);
|
||||
}
|
||||
|
||||
} else {
|
||||
/* simple case: no quality values */
|
||||
|
||||
/* cPtr = STRTOK(input,"," CPTR2); */
|
||||
cPtr = strtok(input,",");
|
||||
while (cPtr) {
|
||||
if (strlen(cPtr)<NSILOCALE_MAX_ACCEPT_LENGTH) { /* ignore if too long */
|
||||
strcpy(acceptLanguageList[countLang++],cPtr);
|
||||
if (countLang>=NSILOCALE_MAX_ACCEPT_LENGTH) break; /* quit if too many */
|
||||
}
|
||||
/* cPtr = STRTOK(NULL,"," CPTR2); */
|
||||
cPtr = strtok(NULL,",");
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// now create the locale
|
||||
//
|
||||
result = NS_ERROR_FAILURE;
|
||||
if (countLang>0) {
|
||||
PRUnichar* localeName = nsString(acceptLanguageList[0]).ToNewUnicode();
|
||||
result = NewLocale(localeName,_retval);
|
||||
delete localeName;
|
||||
}
|
||||
|
||||
//
|
||||
// clean up
|
||||
//
|
||||
delete[] input;
|
||||
return result;
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsLocaleService::GetLocaleService(nsILocaleService** localeService)
|
||||
{
|
||||
if (!gLocaleService)
|
||||
{
|
||||
nsLocaleService* locale_service = new nsLocaleService();
|
||||
if (!locale_service)
|
||||
{
|
||||
*localeService = NS_STATIC_CAST(nsILocaleService*,locale_service);
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
}
|
||||
|
||||
gLocaleService = NS_STATIC_CAST(nsILocaleService*,locale_service);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
*localeService = gLocaleService;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult
|
||||
NS_NewLocaleService(nsILocaleService** result)
|
||||
{
|
||||
return nsLocaleService::GetLocaleService(result);
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// nsLocaleDefinition methods
|
||||
//
|
||||
|
||||
NS_IMPL_ISUPPORTS(nsLocaleDefinition,kILocaleDefinitionIID)
|
||||
|
||||
nsLocaleDefinition::nsLocaleDefinition(void)
|
||||
{
|
||||
NS_INIT_REFCNT();
|
||||
|
||||
mLocaleDefinition = new nsLocale;
|
||||
if (mLocaleDefinition)
|
||||
mLocaleDefinition->AddRef();
|
||||
}
|
||||
|
||||
nsLocaleDefinition::~nsLocaleDefinition(void)
|
||||
{
|
||||
if (mLocaleDefinition)
|
||||
mLocaleDefinition->Release();
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsLocaleDefinition::SetLocaleCategory(const PRUnichar *category, const PRUnichar *value)
|
||||
{
|
||||
if (mLocaleDefinition)
|
||||
return mLocaleDefinition->AddCategory(category,value);
|
||||
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
|
||||
nsLocaleServiceFactory::nsLocaleServiceFactory()
|
||||
{
|
||||
NS_INIT_REFCNT();
|
||||
}
|
||||
|
||||
nsLocaleServiceFactory::~nsLocaleServiceFactory()
|
||||
{
|
||||
}
|
||||
|
||||
NS_IMPL_ISUPPORTS(nsLocaleServiceFactory,kIFactoryIID)
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsLocaleServiceFactory::CreateInstance(nsISupports* aOuter,
|
||||
REFNSIID aIID, void** aResult)
|
||||
{
|
||||
nsILocaleService* locale_service;
|
||||
NS_NewLocaleService(&locale_service);
|
||||
|
||||
return locale_service->QueryInterface(aIID,aResult);
|
||||
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsLocaleServiceFactory::LockFactory(PRBool aLock)
|
||||
{
|
||||
|
||||
return NS_OK;
|
||||
}
|
Загрузка…
Ссылка в новой задаче