зеркало из https://github.com/mozilla/gecko-dev.git
fix for bug 172004 - provide a mechanism for embeddors to override specific strings in any string bundle with a single "string manifest" file.
r=tao, sr=sfraser, a=asa
This commit is contained in:
Родитель
9ab0709805
Коммит
ddd2411b69
|
@ -302,7 +302,11 @@ static nsModuleComponentInfo components[] =
|
|||
NS_HANKAKUTOZENKAKU_CONTRACTID, CreateNewHankakuToZenkaku},
|
||||
|
||||
// strres
|
||||
{ "String Bundle", NS_STRINGBUNDLESERVICE_CID, NS_STRINGBUNDLE_CONTRACTID, nsStringBundleServiceConstructor},
|
||||
{ "String Bundle", NS_STRINGBUNDLESERVICE_CID, NS_STRINGBUNDLE_CONTRACTID,
|
||||
nsStringBundleServiceConstructor},
|
||||
{ "String Textfile Overrides", NS_STRINGBUNDLETEXTOVERRIDE_CID,
|
||||
NS_STRINGBUNDLETEXTOVERRIDE_CONTRACTID,
|
||||
nsStringBundleTextOverrideConstructor },
|
||||
|
||||
// locale
|
||||
{ "nsLocaleService component",
|
||||
|
|
|
@ -1201,6 +1201,13 @@
|
|||
<FILEKIND>Text</FILEKIND>
|
||||
<FILEFLAGS>Debug</FILEFLAGS>
|
||||
</FILE>
|
||||
<FILE>
|
||||
<PATHTYPE>Name</PATHTYPE>
|
||||
<PATH>nsStringBundleTextOverride.cpp</PATH>
|
||||
<PATHFORMAT>MacOS</PATHFORMAT>
|
||||
<FILEKIND>Text</FILEKIND>
|
||||
<FILEFLAGS>Debug</FILEFLAGS>
|
||||
</FILE>
|
||||
<FILE>
|
||||
<PATHTYPE>Name</PATHTYPE>
|
||||
<PATH>nsCaseConversionImp2.cpp</PATH>
|
||||
|
@ -1398,6 +1405,11 @@
|
|||
<PATH>nsStringBundle.cpp</PATH>
|
||||
<PATHFORMAT>MacOS</PATHFORMAT>
|
||||
</FILEREF>
|
||||
<FILEREF>
|
||||
<PATHTYPE>Name</PATHTYPE>
|
||||
<PATH>nsStringBundleTextOverride.cpp</PATH>
|
||||
<PATHFORMAT>MacOS</PATHFORMAT>
|
||||
</FILEREF>
|
||||
<FILEREF>
|
||||
<PATHTYPE>Name</PATHTYPE>
|
||||
<PATH>nsCaseConversionImp2.cpp</PATH>
|
||||
|
@ -2573,6 +2585,13 @@
|
|||
<FILEKIND>Text</FILEKIND>
|
||||
<FILEFLAGS>Debug</FILEFLAGS>
|
||||
</FILE>
|
||||
<FILE>
|
||||
<PATHTYPE>Name</PATHTYPE>
|
||||
<PATH>nsStringBundleTextOverride.cpp</PATH>
|
||||
<PATHFORMAT>MacOS</PATHFORMAT>
|
||||
<FILEKIND>Text</FILEKIND>
|
||||
<FILEFLAGS>Debug</FILEFLAGS>
|
||||
</FILE>
|
||||
<FILE>
|
||||
<PATHTYPE>Name</PATHTYPE>
|
||||
<PATH>nsCaseConversionImp2.cpp</PATH>
|
||||
|
@ -2770,6 +2789,11 @@
|
|||
<PATH>nsStringBundle.cpp</PATH>
|
||||
<PATHFORMAT>MacOS</PATHFORMAT>
|
||||
</FILEREF>
|
||||
<FILEREF>
|
||||
<PATHTYPE>Name</PATHTYPE>
|
||||
<PATH>nsStringBundleTextOverride.cpp</PATH>
|
||||
<PATHFORMAT>MacOS</PATHFORMAT>
|
||||
</FILEREF>
|
||||
<FILEREF>
|
||||
<PATHTYPE>Name</PATHTYPE>
|
||||
<PATH>nsCaseConversionImp2.cpp</PATH>
|
||||
|
@ -3024,6 +3048,12 @@
|
|||
<PATH>nsStringBundle.cpp</PATH>
|
||||
<PATHFORMAT>MacOS</PATHFORMAT>
|
||||
</FILEREF>
|
||||
<FILEREF>
|
||||
<TARGETNAME>i18n.shlb</TARGETNAME>
|
||||
<PATHTYPE>Name</PATHTYPE>
|
||||
<PATH>nsStringBundleTextOverride.cpp</PATH>
|
||||
<PATHFORMAT>MacOS</PATHFORMAT>
|
||||
</FILEREF>
|
||||
</GROUP>
|
||||
<GROUP><NAME>Static Libs</NAME>
|
||||
<FILEREF>
|
||||
|
|
|
@ -717,6 +717,13 @@
|
|||
<FILEKIND>Text</FILEKIND>
|
||||
<FILEFLAGS></FILEFLAGS>
|
||||
</FILE>
|
||||
<FILE>
|
||||
<PATHTYPE>Name</PATHTYPE>
|
||||
<PATH>nsIStringBundleOverride.idl</PATH>
|
||||
<PATHFORMAT>MacOS</PATHFORMAT>
|
||||
<FILEKIND>Text</FILEKIND>
|
||||
<FILEFLAGS></FILEFLAGS>
|
||||
</FILE>
|
||||
<FILE>
|
||||
<PATHTYPE>Name</PATHTYPE>
|
||||
<PATH>nsIAcceptLang.idl</PATH>
|
||||
|
@ -731,6 +738,11 @@
|
|||
<PATH>nsIStringBundle.idl</PATH>
|
||||
<PATHFORMAT>MacOS</PATHFORMAT>
|
||||
</FILEREF>
|
||||
<FILEREF>
|
||||
<PATHTYPE>Name</PATHTYPE>
|
||||
<PATH>nsIStringBundleOverride.idl</PATH>
|
||||
<PATHFORMAT>MacOS</PATHFORMAT>
|
||||
</FILEREF>
|
||||
<FILEREF>
|
||||
<PATHTYPE>Name</PATHTYPE>
|
||||
<PATH>nsIAcceptLang.idl</PATH>
|
||||
|
@ -1402,6 +1414,13 @@
|
|||
<FILEKIND>Text</FILEKIND>
|
||||
<FILEFLAGS></FILEFLAGS>
|
||||
</FILE>
|
||||
<FILE>
|
||||
<PATHTYPE>Name</PATHTYPE>
|
||||
<PATH>nsIStringBundleOverride.idl</PATH>
|
||||
<PATHFORMAT>MacOS</PATHFORMAT>
|
||||
<FILEKIND>Text</FILEKIND>
|
||||
<FILEFLAGS></FILEFLAGS>
|
||||
</FILE>
|
||||
<FILE>
|
||||
<PATHTYPE>Name</PATHTYPE>
|
||||
<PATH>nsIAcceptLang.idl</PATH>
|
||||
|
@ -1416,6 +1435,11 @@
|
|||
<PATH>nsIStringBundle.idl</PATH>
|
||||
<PATHFORMAT>MacOS</PATHFORMAT>
|
||||
</FILEREF>
|
||||
<FILEREF>
|
||||
<PATHTYPE>Name</PATHTYPE>
|
||||
<PATH>nsIStringBundleOverride.idl</PATH>
|
||||
<PATHFORMAT>MacOS</PATHFORMAT>
|
||||
</FILEREF>
|
||||
<FILEREF>
|
||||
<PATHTYPE>Name</PATHTYPE>
|
||||
<PATH>nsIAcceptLang.idl</PATH>
|
||||
|
@ -1437,6 +1461,12 @@
|
|||
<PATH>nsIStringBundle.idl</PATH>
|
||||
<PATHFORMAT>MacOS</PATHFORMAT>
|
||||
</FILEREF>
|
||||
<FILEREF>
|
||||
<TARGETNAME>headers</TARGETNAME>
|
||||
<PATHTYPE>Name</PATHTYPE>
|
||||
<PATH>nsIStringBundleOverride.idl</PATH>
|
||||
<PATHFORMAT>MacOS</PATHFORMAT>
|
||||
</FILEREF>
|
||||
<FILEREF>
|
||||
<TARGETNAME>headers</TARGETNAME>
|
||||
<PATHTYPE>Name</PATHTYPE>
|
||||
|
|
|
@ -28,7 +28,10 @@ include $(DEPTH)/config/autoconf.mk
|
|||
|
||||
MODULE = intl
|
||||
|
||||
XPIDLSRCS = nsIStringBundle.idl
|
||||
XPIDLSRCS = \
|
||||
nsIStringBundle.idl \
|
||||
nsIStringBundleOverride.idl \
|
||||
$(NULL)
|
||||
|
||||
include $(topsrcdir)/config/rules.mk
|
||||
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* -*- Mode: IDL; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: NPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
|
@ -85,9 +85,8 @@ interface nsIStringBundle : nsISupports
|
|||
[scriptable, uuid(D85A17C0-AA7C-11d2-9B8C-00805F8A16D9)]
|
||||
interface nsIStringBundleService : nsISupports
|
||||
{
|
||||
nsIStringBundle createBundle([const] in string aURLSpec);
|
||||
nsIStringBundle createAsyncBundle([const] in string aURLSpec);
|
||||
nsIStringBundle createExtensibleBundle([const] in string aRegistryKey);
|
||||
nsIStringBundle createBundle(in string aURLSpec);
|
||||
nsIStringBundle createExtensibleBundle(in string aRegistryKey);
|
||||
|
||||
/**
|
||||
* Formats a message string from a status code and status arguments.
|
||||
|
|
|
@ -0,0 +1,57 @@
|
|||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is __________________________________________.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* ____________________________________________.
|
||||
* Portions created by the Initial Developer are Copyright (C) 2___
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
#include "nsISupports.idl"
|
||||
|
||||
interface nsISimpleEnumerator;
|
||||
|
||||
// to be implemented by an embeddor that wants to override some strings
|
||||
[scriptable, uuid(965eb278-5678-456b-82a7-20a0c86a803c)]
|
||||
interface nsIStringBundleOverride : nsISupports
|
||||
{
|
||||
/**
|
||||
* get the override value for a particular key in a particular
|
||||
* string bundle
|
||||
*/
|
||||
AString getStringFromName(in AUTF8String url,
|
||||
in ACString key);
|
||||
|
||||
/**
|
||||
* get all override keys for a given string bundle
|
||||
*/
|
||||
nsISimpleEnumerator enumerateKeysInBundle(in AUTF8String url);
|
||||
};
|
|
@ -36,7 +36,10 @@ REQUIRES = xpcom \
|
|||
necko \
|
||||
$(NULL)
|
||||
|
||||
CPPSRCS = nsStringBundle.cpp
|
||||
CPPSRCS = \
|
||||
nsStringBundle.cpp \
|
||||
nsStringBundleTextOverride.cpp \
|
||||
$(NULL)
|
||||
|
||||
|
||||
include $(topsrcdir)/config/rules.mk
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
|
||||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: NPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
|
@ -39,8 +39,10 @@
|
|||
#ifndef nsStrBundleConstructors_h__
|
||||
#define nsStrBundleConstructors_h__
|
||||
|
||||
#include "nsStringBundle.h"
|
||||
#include "nsStringBundleService.h"
|
||||
#include "nsStringBundleTextOverride.h"
|
||||
|
||||
NS_GENERIC_FACTORY_CONSTRUCTOR_INIT(nsStringBundleService, Init)
|
||||
NS_GENERIC_FACTORY_CONSTRUCTOR_INIT(nsStringBundleTextOverride, Init)
|
||||
|
||||
#endif
|
||||
|
|
|
@ -42,9 +42,15 @@
|
|||
#include "nsString.h"
|
||||
#include "nsReadableUtils.h"
|
||||
#include "nsIStringBundle.h"
|
||||
#include "nsStringBundleService.h"
|
||||
#include "nsStringBundle.h"
|
||||
#include "nsStringBundleTextOverride.h"
|
||||
#include "nsXPCOM.h"
|
||||
#include "nsISupportsPrimitives.h"
|
||||
#include "nsArray.h"
|
||||
#include "nsArrayEnumerator.h"
|
||||
#include "nscore.h"
|
||||
#include "nsHashtable.h"
|
||||
#include "nsMemory.h"
|
||||
#include "plstr.h"
|
||||
#include "nsNetUtil.h"
|
||||
|
@ -56,7 +62,7 @@
|
|||
#include "pratom.h"
|
||||
#include "prmem.h"
|
||||
#include "nsIModule.h"
|
||||
#include "nsISupportsArray.h"
|
||||
#include "nsCOMArray.h"
|
||||
#include "nsAutoLock.h"
|
||||
#include "nsTextFormatter.h"
|
||||
#include "nsIErrorService.h"
|
||||
|
@ -78,54 +84,14 @@
|
|||
static NS_DEFINE_CID(kErrorServiceCID, NS_ERRORSERVICE_CID);
|
||||
static NS_DEFINE_CID(kPersistentPropertiesCID, NS_IPERSISTENTPROPERTIES_CID);
|
||||
|
||||
// XXX investigate need for proper locking in this module
|
||||
//static PRInt32 gLockCount = 0;
|
||||
|
||||
NS_DEFINE_IID(kStringBundleServiceCID, NS_STRINGBUNDLESERVICE_CID);
|
||||
|
||||
class nsStringBundle : public nsIStringBundle
|
||||
#ifdef ASYNC_LOADING
|
||||
, public nsIStreamLoaderObserver
|
||||
#endif
|
||||
{
|
||||
public:
|
||||
// init version
|
||||
nsStringBundle(const char* aURLSpec);
|
||||
nsresult LoadProperties();
|
||||
virtual ~nsStringBundle();
|
||||
|
||||
NS_DECL_ISUPPORTS
|
||||
NS_DECL_NSISTRINGBUNDLE
|
||||
#ifdef ASYNC_LOADING
|
||||
NS_DECL_NSISTREAMLOADEROBSERVER
|
||||
#endif
|
||||
|
||||
nsCOMPtr<nsIPersistentProperties> mProps;
|
||||
|
||||
protected:
|
||||
//
|
||||
// functional decomposition of the funitions repeatively called
|
||||
//
|
||||
nsresult GetStringFromID(PRInt32 aID, nsAString& aResult);
|
||||
nsresult GetStringFromName(const nsAString& aName, nsAString& aResult);
|
||||
|
||||
private:
|
||||
nsCString mPropertiesURL;
|
||||
PRPackedBool mAttemptedLoad;
|
||||
PRPackedBool mLoaded;
|
||||
|
||||
public:
|
||||
static nsresult FormatString(const PRUnichar *formatStr,
|
||||
const PRUnichar **aParams, PRUint32 aLength,
|
||||
PRUnichar **aResult);
|
||||
};
|
||||
|
||||
nsStringBundle::~nsStringBundle()
|
||||
{
|
||||
}
|
||||
|
||||
nsStringBundle::nsStringBundle(const char* aURLSpec) :
|
||||
nsStringBundle::nsStringBundle(const char* aURLSpec,
|
||||
nsIStringBundleOverride* aOverrideStrings) :
|
||||
mPropertiesURL(aURLSpec),
|
||||
mOverrideStrings(aOverrideStrings),
|
||||
mAttemptedLoad(PR_FALSE),
|
||||
mLoaded(PR_FALSE)
|
||||
{
|
||||
|
@ -150,142 +116,31 @@ nsStringBundle::LoadProperties()
|
|||
|
||||
nsresult rv;
|
||||
|
||||
// to be turned on once we figure out how to ensure we're loading on
|
||||
// the main thread
|
||||
#ifdef ASYNC_LOADING
|
||||
|
||||
// load the string bundle asynchronously on another thread,
|
||||
// but make sure we block this thread so that LoadProperties() is
|
||||
// synchronous
|
||||
|
||||
// create an event queue for this thread.
|
||||
nsCOMPtr<nsIEventQueueService> service = do_GetService(NS_EVENTQUEUESERVICE_CONTRACTID, &rv);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
nsCOMPtr<nsIEventQueue> currentThreadQ;
|
||||
rv = service->PushThreadEventQueue(getter_AddRefs(currentThreadQ));
|
||||
NS_ENSURE_SUCCESS(rv, NS_ERROR_FAILURE);
|
||||
|
||||
// do it synchronously
|
||||
nsCOMPtr<nsIURI> uri;
|
||||
rv = NS_NewURI(getter_AddRefs(uri), mPropertiesURL);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
// create and loader, then wait
|
||||
nsCOMPtr<nsIStreamLoader> loader;
|
||||
rv = NS_NewStreamLoader(getter_AddRefs(loader),
|
||||
uri,
|
||||
this /*the load observer*/);
|
||||
NS_ASSERTION(NS_SUCCEEDED(rv), "\n-->nsStringBundle::Init: NS_NewStreamLoader failed...\n");
|
||||
|
||||
// process events until we're finished.
|
||||
PLEvent *event;
|
||||
while (!mLoaded) {
|
||||
rv = currentThreadQ->WaitForEvent(&event);
|
||||
NS_ASSERTION(NS_SUCCEEDED(rv), "\n-->nsStringBundle::Init: currentThreadQ->WaitForEvent failed...\n");
|
||||
if (NS_FAILED(rv)) break;
|
||||
|
||||
rv = currentThreadQ->HandleEvent(event);
|
||||
NS_ASSERTION(NS_SUCCEEDED(rv), "\n-->nsStringBundle::Init: currentThreadQ->HandleEvent failed...\n");
|
||||
if (NS_FAILED(rv)) break;
|
||||
}
|
||||
|
||||
rv = service->PopThreadEventQueue(currentThreadQ);
|
||||
|
||||
#else
|
||||
|
||||
// do it synchronously
|
||||
nsCOMPtr<nsIURI> uri;
|
||||
rv = NS_NewURI(getter_AddRefs(uri), mPropertiesURL);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
nsCOMPtr<nsIInputStream> in;
|
||||
rv = NS_OpenURI(getter_AddRefs(in), uri);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
NS_TIMELINE_MARK_FUNCTION("loading properties");
|
||||
|
||||
NS_ASSERTION(NS_SUCCEEDED(rv) && in, "Error in OpenBlockingStream");
|
||||
NS_ENSURE_TRUE(NS_SUCCEEDED(rv) && in, NS_ERROR_FAILURE);
|
||||
|
||||
mProps = do_CreateInstance(kPersistentPropertiesCID, &rv);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
mAttemptedLoad = mLoaded = PR_TRUE;
|
||||
rv = mProps->Load(in);
|
||||
|
||||
mLoaded = NS_SUCCEEDED(rv);
|
||||
#endif
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
||||
#ifdef ASYNC_LOADING
|
||||
NS_IMETHODIMP
|
||||
nsStringBundle::OnStreamComplete(nsIStreamLoader* aLoader,
|
||||
nsISupports* context,
|
||||
nsresult aStatus,
|
||||
PRUint32 stringLen,
|
||||
const char* string)
|
||||
{
|
||||
|
||||
nsXPIDLCString uriSpec;
|
||||
if (NS_FAILED(aStatus)) {
|
||||
// print a load error on bad status
|
||||
#if defined(DEBUG)
|
||||
if (aLoader) {
|
||||
nsCOMPtr<nsIRequest> request;
|
||||
aLoader->GetRequest(getter_AddRefs(request));
|
||||
nsCOMPtr<nsIChannel> channel(do_QueryInterface(request));
|
||||
|
||||
if (channel) {
|
||||
nsCOMPtr<nsIURI> uri;
|
||||
channel->GetURI(getter_AddRefs(uri));
|
||||
if (uri) {
|
||||
uri->GetSpec(getter_Copies(uriSpec));
|
||||
printf("\n -->nsStringBundle::OnStreamComplete: Failed to load %s\n",
|
||||
uriSpec ? (const char *) uriSpec : "");
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
return aStatus;
|
||||
}
|
||||
|
||||
nsresult rv;
|
||||
nsCOMPtr<nsISupports> stringStreamSupports;
|
||||
rv = NS_NewByteInputStream(getter_AddRefs(stringStreamSupports),
|
||||
string, stringLen);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
nsCOMPtr<nsIInputStream> in = do_QueryInterface(stringStreamSupports, &rv);
|
||||
nsCOMPtr<nsIInputStream> in;
|
||||
rv = NS_OpenURI(getter_AddRefs(in), uri);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
NS_TIMELINE_MARK_FUNCTION("loading properties");
|
||||
|
||||
NS_ASSERTION(NS_SUCCEEDED(rv) && in, "Error in OpenBlockingStream");
|
||||
NS_ENSURE_TRUE(NS_SUCCEEDED(rv) && in, NS_ERROR_FAILURE);
|
||||
|
||||
mProps = do_CreateInstance(kPersistentPropertiesCID, &rv);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
// load the stream
|
||||
mAttemptedLoad = mLoaded = PR_TRUE;
|
||||
rv = mProps->Load(in);
|
||||
|
||||
mLoaded = NS_SUCCEEDED(rv);
|
||||
|
||||
//
|
||||
// notify
|
||||
if (NS_SUCCEEDED(rv)) {
|
||||
mLoaded = PR_TRUE;
|
||||
|
||||
// observer notification
|
||||
nsCOMPtr<nsIObserverService> os = do_GetService("@mozilla.org/observer-service;1");
|
||||
if (os)
|
||||
(void) os->NotifyObservers((nsIStringBundle *) this,
|
||||
NS_STRBUNDLE_LOADED_TOPIC,
|
||||
nsnull);
|
||||
|
||||
#if defined(DEBUG_tao)
|
||||
printf("\n --> nsStringBundle::OnStreamComplete: end sending NOTIFICATIONS!!\n");
|
||||
#endif
|
||||
}
|
||||
return rv;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
nsresult
|
||||
nsStringBundle::GetStringFromID(PRInt32 aID, nsAString& aResult)
|
||||
|
@ -293,7 +148,18 @@ nsStringBundle::GetStringFromID(PRInt32 aID, nsAString& aResult)
|
|||
nsAutoCMonitor(this);
|
||||
nsCAutoString name;
|
||||
name.AppendInt(aID, 10);
|
||||
nsresult rv = mProps->GetStringProperty(name, aResult);
|
||||
|
||||
nsresult rv;
|
||||
|
||||
// try override first
|
||||
if (mOverrideStrings) {
|
||||
rv = mOverrideStrings->GetStringFromName(mPropertiesURL,
|
||||
name,
|
||||
aResult);
|
||||
if (NS_SUCCEEDED(rv)) return rv;
|
||||
}
|
||||
|
||||
rv = mProps->GetStringProperty(name, aResult);
|
||||
|
||||
#ifdef DEBUG_tao_
|
||||
char *s = ToNewCString(aResult);
|
||||
|
@ -311,6 +177,14 @@ nsStringBundle::GetStringFromName(const nsAString& aName,
|
|||
{
|
||||
nsresult rv;
|
||||
|
||||
// try override first
|
||||
if (mOverrideStrings) {
|
||||
rv = mOverrideStrings->GetStringFromName(mPropertiesURL,
|
||||
NS_ConvertUCS2toUTF8(aName),
|
||||
aResult);
|
||||
if (NS_SUCCEEDED(rv)) return rv;
|
||||
}
|
||||
|
||||
rv = mProps->GetStringProperty(NS_ConvertUCS2toUTF8(aName), aResult);
|
||||
#ifdef DEBUG_tao_
|
||||
char *s = ToNewCString(aResult),
|
||||
|
@ -353,13 +227,8 @@ nsStringBundle::FormatStringFromName(const PRUnichar *aName,
|
|||
}
|
||||
|
||||
|
||||
#ifdef ASYNC_LOADING
|
||||
NS_IMPL_THREADSAFE_ISUPPORTS2(nsStringBundle,
|
||||
nsIStringBundle, nsIStreamLoaderObserver)
|
||||
#else
|
||||
NS_IMPL_THREADSAFE_ISUPPORTS1(nsStringBundle,
|
||||
nsIStringBundle)
|
||||
#endif
|
||||
|
||||
/* void GetStringFromID (in long aID, out wstring aResult); */
|
||||
NS_IMETHODIMP
|
||||
|
@ -396,6 +265,67 @@ nsStringBundle::GetStringFromName(const PRUnichar *aName, PRUnichar **aResult)
|
|||
return rv;
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsStringBundle::GetCombinedEnumeration(nsISimpleEnumerator* aOverrideEnumerator,
|
||||
nsISimpleEnumerator** aResult)
|
||||
{
|
||||
nsCOMPtr<nsISupports> supports;
|
||||
nsCOMPtr<nsIPropertyElement> propElement;
|
||||
|
||||
nsresult rv;
|
||||
|
||||
PRBool hasMore;
|
||||
|
||||
nsCOMPtr<nsIMutableArray> resultArray;
|
||||
NS_NewArray(getter_AddRefs(resultArray));
|
||||
|
||||
// first, append the override elements only if
|
||||
// they don't already exist in mProps
|
||||
do {
|
||||
|
||||
rv = aOverrideEnumerator->GetNext(getter_AddRefs(supports));
|
||||
if (NS_SUCCEEDED(rv) &&
|
||||
(propElement = do_QueryInterface(supports, &rv))) {
|
||||
|
||||
nsCAutoString key;
|
||||
rv = propElement->GetKey(key);
|
||||
if (NS_SUCCEEDED(rv)) {
|
||||
|
||||
PRBool hasKey;
|
||||
mProps->Has(key.get(), &hasKey);
|
||||
if (!hasKey)
|
||||
resultArray->AppendElement(propElement, PR_FALSE);
|
||||
}
|
||||
}
|
||||
|
||||
aOverrideEnumerator->HasMoreElements(&hasMore);
|
||||
} while (hasMore);
|
||||
|
||||
// ok, now we have the "unique" elements in resultArray
|
||||
nsCOMPtr<nsISimpleEnumerator> propEnumerator;
|
||||
rv = mProps->Enumerate(getter_AddRefs(propEnumerator));
|
||||
if (NS_FAILED(rv)) {
|
||||
// no elements in mProps anyway, just return what we have
|
||||
return NS_NewArrayEnumerator(aResult, resultArray);
|
||||
}
|
||||
|
||||
// second, append all the elements that are in mProps
|
||||
do {
|
||||
rv = propEnumerator->GetNext(getter_AddRefs(supports));
|
||||
if (NS_SUCCEEDED(rv) &&
|
||||
(propElement = do_QueryInterface(supports, &rv)))
|
||||
|
||||
resultArray->AppendElement(propElement, PR_FALSE);
|
||||
|
||||
propEnumerator->HasMoreElements(&hasMore);
|
||||
} while (hasMore);
|
||||
|
||||
NS_ADDREF(*aResult = propEnumerator);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsStringBundle::GetSimpleEnumeration(nsISimpleEnumerator** elements)
|
||||
{
|
||||
|
@ -406,6 +336,14 @@ nsStringBundle::GetSimpleEnumeration(nsISimpleEnumerator** elements)
|
|||
rv = LoadProperties();
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
if (mOverrideStrings) {
|
||||
nsCOMPtr<nsISimpleEnumerator> overrideEnumerator;
|
||||
rv = mOverrideStrings->EnumerateKeysInBundle(mPropertiesURL,
|
||||
getter_AddRefs(overrideEnumerator));
|
||||
if (NS_SUCCEEDED(rv))
|
||||
return GetCombinedEnumeration(overrideEnumerator, elements);
|
||||
}
|
||||
|
||||
return mProps->Enumerate(elements);
|
||||
}
|
||||
|
||||
|
@ -438,39 +376,13 @@ nsStringBundle::FormatString(const PRUnichar *aFormatStr,
|
|||
return NS_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* An extesible implementation of the StringBudle interface.
|
||||
*
|
||||
* @created 28/Dec/1999
|
||||
* @author Catalin Rotaru [CATA]
|
||||
*/
|
||||
class nsExtensibleStringBundle : public nsIStringBundle
|
||||
{
|
||||
NS_DECL_ISUPPORTS
|
||||
NS_DECL_NSISTRINGBUNDLE
|
||||
|
||||
nsresult Init(const char * aCategory, nsIStringBundleService *);
|
||||
private:
|
||||
|
||||
nsISupportsArray * mBundle;
|
||||
PRBool mLoaded;
|
||||
|
||||
public:
|
||||
|
||||
nsExtensibleStringBundle();
|
||||
virtual ~nsExtensibleStringBundle();
|
||||
};
|
||||
|
||||
NS_IMPL_ISUPPORTS1(nsExtensibleStringBundle, nsIStringBundle)
|
||||
|
||||
nsExtensibleStringBundle::nsExtensibleStringBundle()
|
||||
:mBundle(NULL)
|
||||
{
|
||||
NS_INIT_ISUPPORTS();
|
||||
|
||||
mLoaded = PR_FALSE;
|
||||
|
||||
|
||||
}
|
||||
|
||||
nsresult
|
||||
|
@ -487,10 +399,6 @@ nsExtensibleStringBundle::Init(const char * aCategory,
|
|||
rv = catman->EnumerateCategory(aCategory, getter_AddRefs(enumerator));
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
// create the bundles array
|
||||
rv = NS_NewISupportsArray(&mBundle);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
PRBool hasMore;
|
||||
while (NS_SUCCEEDED(enumerator->HasMoreElements(&hasMore)) && hasMore) {
|
||||
nsCOMPtr<nsISupports> supports;
|
||||
|
@ -512,7 +420,7 @@ nsExtensibleStringBundle::Init(const char * aCategory,
|
|||
if (NS_FAILED(rv))
|
||||
continue;
|
||||
|
||||
mBundle->AppendElement(bundle);
|
||||
mBundles.AppendObject(bundle);
|
||||
}
|
||||
|
||||
return rv;
|
||||
|
@ -520,7 +428,6 @@ nsExtensibleStringBundle::Init(const char * aCategory,
|
|||
|
||||
nsExtensibleStringBundle::~nsExtensibleStringBundle()
|
||||
{
|
||||
NS_IF_RELEASE(mBundle);
|
||||
}
|
||||
|
||||
nsresult nsExtensibleStringBundle::GetStringFromID(PRInt32 aID, PRUnichar ** aResult)
|
||||
|
@ -529,13 +436,11 @@ nsresult nsExtensibleStringBundle::GetStringFromID(PRInt32 aID, PRUnichar ** aRe
|
|||
|
||||
PRUint32 size, i;
|
||||
|
||||
rv = mBundle->Count(&size);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
size = mBundles.Count();
|
||||
|
||||
for (i = 0; i < size; i++) {
|
||||
nsCOMPtr<nsIStringBundle> bundle;
|
||||
rv = mBundle->QueryElementAt(i, NS_GET_IID(nsIStringBundle), getter_AddRefs(bundle));
|
||||
if (NS_SUCCEEDED(rv)) {
|
||||
nsIStringBundle *bundle = mBundles[i];
|
||||
if (bundle) {
|
||||
rv = bundle->GetStringFromID(aID, aResult);
|
||||
if (NS_SUCCEEDED(rv))
|
||||
return NS_OK;
|
||||
|
@ -551,13 +456,11 @@ nsresult nsExtensibleStringBundle::GetStringFromName(const PRUnichar *aName,
|
|||
nsresult res = NS_OK;
|
||||
PRUint32 size, i;
|
||||
|
||||
res = mBundle->Count(&size);
|
||||
if (NS_FAILED(res)) return res;
|
||||
size = mBundles.Count();
|
||||
|
||||
for (i = 0; i < size; i++) {
|
||||
nsCOMPtr<nsIStringBundle> bundle;
|
||||
res = mBundle->QueryElementAt(i, NS_GET_IID(nsIStringBundle), getter_AddRefs(bundle));
|
||||
if (NS_SUCCEEDED(res)) {
|
||||
nsIStringBundle* bundle = mBundles[i];
|
||||
if (bundle) {
|
||||
res = bundle->GetStringFromName(aName, aResult);
|
||||
if (NS_SUCCEEDED(res))
|
||||
return NS_OK;
|
||||
|
@ -647,6 +550,11 @@ nsStringBundleService::Init()
|
|||
os->AddObserver(this, "profile-do-change", PR_TRUE);
|
||||
}
|
||||
|
||||
// instantiate the override service, if there is any.
|
||||
// at some point we probably want to make this a category, and
|
||||
// support multiple overrides
|
||||
mOverrideStrings = do_GetService(NS_STRINGBUNDLETEXTOVERRIDE_CONTRACTID);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
@ -706,7 +614,7 @@ nsStringBundleService::getStringBundle(const char *aURLSpec,
|
|||
} else {
|
||||
|
||||
// hasn't been cached, so insert it into the hash table
|
||||
nsStringBundle* bundle = new nsStringBundle(aURLSpec);
|
||||
nsStringBundle* bundle = new nsStringBundle(aURLSpec, mOverrideStrings);
|
||||
if (!bundle) return NS_ERROR_OUT_OF_MEMORY;
|
||||
NS_ADDREF(bundle);
|
||||
|
||||
|
@ -798,12 +706,6 @@ nsStringBundleService::CreateBundle(const char* aURLSpec,
|
|||
return getStringBundle(aURLSpec,aResult);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsStringBundleService::CreateAsyncBundle(const char* aURLSpec, nsIStringBundle** aResult)
|
||||
{
|
||||
return getStringBundle(aURLSpec, aResult);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsStringBundleService::CreateExtensibleBundle(const char* aCategory,
|
||||
nsIStringBundle** aResult)
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
|
||||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: NPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
|
@ -39,52 +39,70 @@
|
|||
#ifndef nsStringBundle_h__
|
||||
#define nsStringBundle_h__
|
||||
|
||||
#include "prclist.h"
|
||||
#include "plarena.h"
|
||||
|
||||
#include "nsCOMPtr.h"
|
||||
#include "nsHashtable.h"
|
||||
#include "nsIPersistentProperties2.h"
|
||||
#include "nsIStringBundle.h"
|
||||
#include "nsIObserver.h"
|
||||
#include "nsWeakReference.h"
|
||||
#include "nsIErrorService.h"
|
||||
#include "nsCOMPtr.h"
|
||||
#include "nsIPersistentProperties2.h"
|
||||
#include "nsString.h"
|
||||
#include "nsCOMArray.h"
|
||||
#include "nsIStringBundleOverride.h"
|
||||
|
||||
struct bundleCacheEntry_t;
|
||||
|
||||
class nsStringBundleService : public nsIStringBundleService,
|
||||
public nsIObserver,
|
||||
public nsSupportsWeakReference
|
||||
class nsStringBundle : public nsIStringBundle
|
||||
{
|
||||
public:
|
||||
nsStringBundleService();
|
||||
virtual ~nsStringBundleService();
|
||||
// init version
|
||||
nsStringBundle(const char* aURLSpec, nsIStringBundleOverride*);
|
||||
nsresult LoadProperties();
|
||||
virtual ~nsStringBundle();
|
||||
|
||||
NS_DECL_ISUPPORTS
|
||||
NS_DECL_NSISTRINGBUNDLE
|
||||
|
||||
nsresult Init();
|
||||
nsCOMPtr<nsIPersistentProperties> mProps;
|
||||
|
||||
NS_DECL_ISUPPORTS
|
||||
NS_DECL_NSISTRINGBUNDLESERVICE
|
||||
NS_DECL_NSIOBSERVER
|
||||
|
||||
protected:
|
||||
//
|
||||
// functional decomposition of the funitions repeatively called
|
||||
//
|
||||
nsresult GetStringFromID(PRInt32 aID, nsAString& aResult);
|
||||
nsresult GetStringFromName(const nsAString& aName, nsAString& aResult);
|
||||
|
||||
nsresult GetCombinedEnumeration(nsISimpleEnumerator* aOverrideEnumerator,
|
||||
nsISimpleEnumerator** aResult);
|
||||
private:
|
||||
nsresult getStringBundle(const char *aUrl, nsIStringBundle** aResult);
|
||||
nsresult FormatWithBundle(nsIStringBundle* bundle, nsresult aStatus,
|
||||
PRUint32 argCount, PRUnichar** argArray,
|
||||
PRUnichar* *result);
|
||||
|
||||
void flushBundleCache();
|
||||
|
||||
bundleCacheEntry_t *insertIntoCache(nsIStringBundle *aBundle,
|
||||
nsCStringKey *aHashKey);
|
||||
|
||||
static void recycleEntry(bundleCacheEntry_t*);
|
||||
|
||||
nsHashtable mBundleMap;
|
||||
PRCList mBundleCache;
|
||||
PLArenaPool mCacheEntryPool;
|
||||
|
||||
nsCOMPtr<nsIErrorService> mErrorService;
|
||||
|
||||
nsCString mPropertiesURL;
|
||||
nsCOMPtr<nsIStringBundleOverride> mOverrideStrings;
|
||||
PRPackedBool mAttemptedLoad;
|
||||
PRPackedBool mLoaded;
|
||||
|
||||
public:
|
||||
static nsresult FormatString(const PRUnichar *formatStr,
|
||||
const PRUnichar **aParams, PRUint32 aLength,
|
||||
PRUnichar **aResult);
|
||||
};
|
||||
|
||||
/**
|
||||
* An extesible implementation of the StringBudle interface.
|
||||
*
|
||||
* @created 28/Dec/1999
|
||||
* @author Catalin Rotaru [CATA]
|
||||
*/
|
||||
class nsExtensibleStringBundle : public nsIStringBundle
|
||||
{
|
||||
NS_DECL_ISUPPORTS
|
||||
NS_DECL_NSISTRINGBUNDLE
|
||||
|
||||
nsresult Init(const char * aCategory, nsIStringBundleService *);
|
||||
private:
|
||||
|
||||
nsCOMArray<nsIStringBundle> mBundles;
|
||||
PRBool mLoaded;
|
||||
|
||||
public:
|
||||
|
||||
nsExtensibleStringBundle();
|
||||
virtual ~nsExtensibleStringBundle();
|
||||
};
|
||||
|
||||
|
||||
|
||||
#endif
|
||||
|
|
|
@ -0,0 +1,91 @@
|
|||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: NPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Netscape Public License
|
||||
* Version 1.1 (the "License"); you may not use this file except in
|
||||
* compliance with the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/NPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is mozilla.org code.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Netscape Communications Corporation.
|
||||
* Portions created by the Initial Developer are Copyright (C) 1998
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
*
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the NPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the NPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
#ifndef nsStringBundleService_h__
|
||||
#define nsStringBundleService_h__
|
||||
|
||||
#include "prclist.h"
|
||||
#include "plarena.h"
|
||||
|
||||
#include "nsCOMPtr.h"
|
||||
#include "nsHashtable.h"
|
||||
#include "nsIPersistentProperties2.h"
|
||||
#include "nsIStringBundle.h"
|
||||
#include "nsIObserver.h"
|
||||
#include "nsWeakReference.h"
|
||||
#include "nsIErrorService.h"
|
||||
#include "nsIStringBundleOverride.h"
|
||||
|
||||
struct bundleCacheEntry_t;
|
||||
|
||||
class nsStringBundleService : public nsIStringBundleService,
|
||||
public nsIObserver,
|
||||
public nsSupportsWeakReference
|
||||
{
|
||||
public:
|
||||
nsStringBundleService();
|
||||
virtual ~nsStringBundleService();
|
||||
|
||||
nsresult Init();
|
||||
|
||||
NS_DECL_ISUPPORTS
|
||||
NS_DECL_NSISTRINGBUNDLESERVICE
|
||||
NS_DECL_NSIOBSERVER
|
||||
|
||||
private:
|
||||
nsresult getStringBundle(const char *aUrl, nsIStringBundle** aResult);
|
||||
nsresult FormatWithBundle(nsIStringBundle* bundle, nsresult aStatus,
|
||||
PRUint32 argCount, PRUnichar** argArray,
|
||||
PRUnichar* *result);
|
||||
|
||||
void flushBundleCache();
|
||||
|
||||
bundleCacheEntry_t *insertIntoCache(nsIStringBundle *aBundle,
|
||||
nsCStringKey *aHashKey);
|
||||
|
||||
static void recycleEntry(bundleCacheEntry_t*);
|
||||
|
||||
nsHashtable mBundleMap;
|
||||
PRCList mBundleCache;
|
||||
PLArenaPool mCacheEntryPool;
|
||||
|
||||
nsCOMPtr<nsIErrorService> mErrorService;
|
||||
nsCOMPtr<nsIStringBundleOverride> mOverrideStrings;
|
||||
};
|
||||
|
||||
#endif
|
|
@ -0,0 +1,237 @@
|
|||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
|
||||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is the string bundle override service.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Netscape Communications Corp.
|
||||
* Portions created by the Initial Developer are Copyright (C) 2002
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Alec Flett <alecf@netscape.com>
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
|
||||
#include "nsStringBundleTextOverride.h"
|
||||
#include "nsString.h"
|
||||
#include "nsEscape.h"
|
||||
|
||||
#include "nsNetUtil.h"
|
||||
#include "nsAppDirectoryServiceDefs.h"
|
||||
|
||||
static NS_DEFINE_CID(kPersistentPropertiesCID, NS_IPERSISTENTPROPERTIES_CID);
|
||||
|
||||
class nsPropertyEnumeratorByURL : public nsISimpleEnumerator
|
||||
{
|
||||
public:
|
||||
nsPropertyEnumeratorByURL(const nsACString& aURL,
|
||||
nsISimpleEnumerator* aOuter) :
|
||||
mURL(aURL),
|
||||
mOuter(aOuter)
|
||||
{
|
||||
// persistent properties uses ":" as a delimiter, so escape
|
||||
// that character
|
||||
mURL.ReplaceSubstring(":", "%3A");
|
||||
// append the hash mark now, so we don't have to add it after each
|
||||
// compare
|
||||
mURL.Append('#');
|
||||
}
|
||||
|
||||
NS_DECL_ISUPPORTS
|
||||
NS_DECL_NSISIMPLEENUMERATOR
|
||||
|
||||
virtual ~nsPropertyEnumeratorByURL() {}
|
||||
private:
|
||||
|
||||
// actual enumerator of all strings from nsIProperties
|
||||
nsCOMPtr<nsISimpleEnumerator> mOuter;
|
||||
nsCOMPtr<nsIPropertyElement> mCurrent;
|
||||
nsCString mURL;
|
||||
};
|
||||
|
||||
//
|
||||
// nsStringBundleTextOverride implementation
|
||||
//
|
||||
|
||||
NS_IMPL_ISUPPORTS1(nsStringBundleTextOverride,
|
||||
nsIStringBundleOverride)
|
||||
|
||||
nsresult
|
||||
nsStringBundleTextOverride::Init()
|
||||
{
|
||||
nsresult rv;
|
||||
|
||||
// check for existence of custom-strings.txt
|
||||
|
||||
nsCOMPtr<nsIFile> customStringsFile;
|
||||
rv = NS_GetSpecialDirectory(NS_APP_CHROME_DIR,
|
||||
getter_AddRefs(customStringsFile));
|
||||
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
// bail if not found - this will cause the service creation to
|
||||
// bail as well, and cause this object to go away
|
||||
|
||||
customStringsFile->AppendNative(NS_LITERAL_CSTRING("custom-strings.txt"));
|
||||
|
||||
PRBool exists;
|
||||
rv = customStringsFile->Exists(&exists);
|
||||
if (NS_FAILED(rv) || !exists)
|
||||
return NS_ERROR_FAILURE;
|
||||
|
||||
NS_WARNING("Using custom-strings.txt to override string bundles.");
|
||||
// read in the custom bundle. Keys are in the form
|
||||
// chrome://package/locale/foo.properties:keyname
|
||||
|
||||
nsCAutoString customStringsURLSpec;
|
||||
rv = NS_GetURLSpecFromFile(customStringsFile, customStringsURLSpec);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
nsCOMPtr<nsIURI> uri;
|
||||
rv = NS_NewURI(getter_AddRefs(uri), customStringsURLSpec);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
nsCOMPtr<nsIInputStream> in;
|
||||
rv = NS_OpenURI(getter_AddRefs(in), uri);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
mValues = do_CreateInstance(kPersistentPropertiesCID, &rv);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
rv = mValues->Load(in);
|
||||
|
||||
// turn this on to see the contents of custom-strings.txt
|
||||
#ifdef DEBUG_alecf
|
||||
nsCOMPtr<nsISimpleEnumerator> enumerator;
|
||||
mValues->Enumerate(getter_AddRefs(enumerator));
|
||||
NS_ASSERTION(enumerator, "no enumerator!\n");
|
||||
|
||||
printf("custom-strings.txt contains:\n");
|
||||
printf("----------------------------\n");
|
||||
|
||||
PRBool hasMore;
|
||||
enumerator->HasMoreElements(&hasMore);
|
||||
do {
|
||||
nsCOMPtr<nsISupports> sup;
|
||||
enumerator->GetNext(getter_AddRefs(sup));
|
||||
|
||||
nsCOMPtr<nsIPropertyElement> prop = do_QueryInterface(sup);
|
||||
|
||||
nsCAutoString key;
|
||||
nsAutoString value;
|
||||
prop->GetKey(key);
|
||||
prop->GetValue(value);
|
||||
|
||||
printf("%s = '%s'\n", key.get(), NS_ConvertUCS2toUTF8(value).get());
|
||||
|
||||
enumerator->HasMoreElements(&hasMore);
|
||||
} while (hasMore);
|
||||
#endif
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsStringBundleTextOverride::GetStringFromName(const nsACString& aURL,
|
||||
const nsACString& key,
|
||||
nsAString& aResult)
|
||||
{
|
||||
// concatenate url#key to get the key to read
|
||||
nsCAutoString combinedURL(aURL + NS_LITERAL_CSTRING("#") + key);
|
||||
|
||||
// persistent properties uses ":" as a delimiter, so escape that character
|
||||
combinedURL.ReplaceSubstring(":", "%3A");
|
||||
|
||||
return mValues->GetStringProperty(combinedURL, aResult);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsStringBundleTextOverride::EnumerateKeysInBundle(const nsACString& aURL,
|
||||
nsISimpleEnumerator** aResult)
|
||||
{
|
||||
// enumerate all strings, and let the enumerator know
|
||||
nsCOMPtr<nsISimpleEnumerator> enumerator;
|
||||
mValues->Enumerate(getter_AddRefs(enumerator));
|
||||
|
||||
// make the enumerator wrapper and pass it off
|
||||
nsPropertyEnumeratorByURL* propEnum =
|
||||
new nsPropertyEnumeratorByURL(aURL, enumerator);
|
||||
|
||||
if (!propEnum) return NS_ERROR_OUT_OF_MEMORY;
|
||||
|
||||
NS_ADDREF(*aResult = propEnum);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
//
|
||||
// nsPropertyEnumeratorByURL implementation
|
||||
//
|
||||
|
||||
|
||||
NS_IMPL_ISUPPORTS1(nsPropertyEnumeratorByURL, nsISimpleEnumerator)
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsPropertyEnumeratorByURL::GetNext(nsISupports **aResult)
|
||||
{
|
||||
if (!mCurrent) return NS_ERROR_UNEXPECTED;
|
||||
|
||||
NS_ADDREF(*aResult = mCurrent);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsPropertyEnumeratorByURL::HasMoreElements(PRBool * aResult)
|
||||
{
|
||||
PRBool hasMore;
|
||||
do {
|
||||
|
||||
nsCOMPtr<nsISupports> supports;
|
||||
mOuter->GetNext(getter_AddRefs(supports));
|
||||
|
||||
mCurrent = do_QueryInterface(supports);
|
||||
|
||||
if (mCurrent) {
|
||||
nsCAutoString curKey;
|
||||
mCurrent->GetKey(curKey);
|
||||
|
||||
if (mURL.Equals(Substring(curKey, 0, mURL.Length())))
|
||||
break;
|
||||
}
|
||||
|
||||
mOuter->HasMoreElements(&hasMore);
|
||||
} while (hasMore);
|
||||
|
||||
if (!hasMore)
|
||||
mCurrent = PR_FALSE;
|
||||
|
||||
*aResult = mCurrent ? PR_TRUE : PR_FALSE;
|
||||
|
||||
return NS_OK;
|
||||
}
|
|
@ -0,0 +1,74 @@
|
|||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
|
||||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is the string bundle override service.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Netscape Communications Corp.
|
||||
* Portions created by the Initial Developer are Copyright (C) 2002
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Alec Flett <alecf@netscape.com>
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
|
||||
#ifndef nsStringBundleTextOverride_h__
|
||||
#define nsStringBundleTextOverride_h__
|
||||
|
||||
#include "nsIStringBundleOverride.h"
|
||||
#include "nsCOMPtr.h"
|
||||
#include "nsIPersistentProperties2.h"
|
||||
|
||||
// {6316C6CE-12D3-479e-8F53-E289351412B8}
|
||||
#define NS_STRINGBUNDLETEXTOVERRIDE_CID \
|
||||
{ 0x6316c6ce, 0x12d3, 0x479e, \
|
||||
{ 0x8f, 0x53, 0xe2, 0x89, 0x35, 0x14, 0x12, 0xb8 } }
|
||||
|
||||
|
||||
#define NS_STRINGBUNDLETEXTOVERRIDE_CONTRACTID \
|
||||
"@mozilla.org/intl/stringbundle/text-override;1"
|
||||
|
||||
// an implementation which does overrides from a text file
|
||||
|
||||
class nsStringBundleTextOverride : public nsIStringBundleOverride
|
||||
{
|
||||
public:
|
||||
nsStringBundleTextOverride() { NS_INIT_ISUPPORTS(); }
|
||||
virtual ~nsStringBundleTextOverride() {}
|
||||
|
||||
nsresult Init();
|
||||
|
||||
NS_DECL_ISUPPORTS
|
||||
NS_DECL_NSISTRINGBUNDLEOVERRIDE
|
||||
|
||||
private:
|
||||
nsCOMPtr<nsIPersistentProperties> mValues;
|
||||
|
||||
};
|
||||
|
||||
#endif
|
Загрузка…
Ссылка в новой задаче