michael@0: /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ michael@0: /* This Source Code Form is subject to the terms of the Mozilla Public michael@0: * License, v. 2.0. If a copy of the MPL was not distributed with this michael@0: * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ michael@0: michael@0: #include "nsIServiceManager.h" michael@0: #include "nsIComponentManager.h" michael@0: #include "rdf.h" michael@0: #include "nsIRDFDataSource.h" michael@0: #include "nsIRDFService.h" michael@0: #include "nsIRDFContainerUtils.h" michael@0: #include "nsRDFCID.h" michael@0: #include "nsXPIDLString.h" michael@0: #include "nsCharsetMenu.h" michael@0: #include "nsICharsetConverterManager.h" michael@0: #include "nsICollation.h" michael@0: #include "nsCollationCID.h" michael@0: #include "nsILocaleService.h" michael@0: #include "nsIPrefService.h" michael@0: #include "nsIPrefBranch.h" michael@0: #include "nsIPrefLocalizedString.h" michael@0: #include "nsICurrentCharsetListener.h" michael@0: #include "nsQuickSort.h" michael@0: #include "nsIObserver.h" michael@0: #include "nsStringEnumerator.h" michael@0: #include "nsTArray.h" michael@0: #include "nsIObserverService.h" michael@0: #include "nsIRequestObserver.h" michael@0: #include "nsCRT.h" michael@0: #include "prmem.h" michael@0: #include "mozilla/ModuleUtils.h" michael@0: #include "nsCycleCollectionParticipant.h" michael@0: michael@0: //---------------------------------------------------------------------------- michael@0: // Global functions and data [declaration] michael@0: michael@0: static NS_DEFINE_CID(kRDFServiceCID, NS_RDFSERVICE_CID); michael@0: static NS_DEFINE_CID(kRDFInMemoryDataSourceCID, NS_RDFINMEMORYDATASOURCE_CID); michael@0: static NS_DEFINE_CID(kRDFContainerUtilsCID, NS_RDFCONTAINERUTILS_CID); michael@0: static NS_DEFINE_CID(kRDFContainerCID, NS_RDFCONTAINER_CID); michael@0: michael@0: static const char kURINC_BrowserAutodetMenuRoot[] = "NC:BrowserAutodetMenuRoot"; michael@0: static const char kURINC_BrowserCharsetMenuRoot[] = "NC:BrowserCharsetMenuRoot"; michael@0: static const char kURINC_BrowserMoreCharsetMenuRoot[] = "NC:BrowserMoreCharsetMenuRoot"; michael@0: static const char kURINC_BrowserMore1CharsetMenuRoot[] = "NC:BrowserMore1CharsetMenuRoot"; michael@0: static const char kURINC_BrowserMore2CharsetMenuRoot[] = "NC:BrowserMore2CharsetMenuRoot"; michael@0: static const char kURINC_BrowserMore3CharsetMenuRoot[] = "NC:BrowserMore3CharsetMenuRoot"; michael@0: static const char kURINC_BrowserMore4CharsetMenuRoot[] = "NC:BrowserMore4CharsetMenuRoot"; michael@0: static const char kURINC_BrowserMore5CharsetMenuRoot[] = "NC:BrowserMore5CharsetMenuRoot"; michael@0: static const char kURINC_MaileditCharsetMenuRoot[] = "NC:MaileditCharsetMenuRoot"; michael@0: static const char kURINC_MailviewCharsetMenuRoot[] = "NC:MailviewCharsetMenuRoot"; michael@0: static const char kURINC_ComposerCharsetMenuRoot[] = "NC:ComposerCharsetMenuRoot"; michael@0: static const char kURINC_DecodersRoot[] = "NC:DecodersRoot"; michael@0: static const char kURINC_EncodersRoot[] = "NC:EncodersRoot"; michael@0: DEFINE_RDF_VOCAB(NC_NAMESPACE_URI, NC, Name); michael@0: DEFINE_RDF_VOCAB(NC_NAMESPACE_URI, NC, BookmarkSeparator); michael@0: DEFINE_RDF_VOCAB(NC_NAMESPACE_URI, NC, CharsetDetector); michael@0: DEFINE_RDF_VOCAB(RDF_NAMESPACE_URI, NC, type); michael@0: michael@0: // Note here that browser and mailview have the same static area and cache michael@0: // size but the cache itself is separate. michael@0: michael@0: #define kBrowserStaticPrefKey "intl.charsetmenu.browser.static" michael@0: #define kBrowserCachePrefKey "intl.charsetmenu.browser.cache" michael@0: #define kBrowserCacheSizePrefKey "intl.charsetmenu.browser.cache.size" michael@0: michael@0: #define kMailviewStaticPrefKey "intl.charsetmenu.browser.static" michael@0: #define kMailviewCachePrefKey "intl.charsetmenu.mailview.cache" michael@0: #define kMailviewCacheSizePrefKey "intl.charsetmenu.browser.cache.size" michael@0: michael@0: #define kComposerStaticPrefKey "intl.charsetmenu.browser.static" michael@0: #define kComposerCachePrefKey "intl.charsetmenu.composer.cache" michael@0: #define kComposerCacheSizePrefKey "intl.charsetmenu.browser.cache.size" michael@0: michael@0: #define kMaileditPrefKey "intl.charsetmenu.mailedit" michael@0: michael@0: //---------------------------------------------------------------------------- michael@0: // Class nsMenuEntry [declaration] michael@0: michael@0: /** michael@0: * A little class holding all data needed for a menu item. michael@0: * michael@0: * @created 18/Apr/2000 michael@0: * @author Catalin Rotaru [CATA] michael@0: */ michael@0: class nsMenuEntry michael@0: { michael@0: public: michael@0: // memory & ref counting & leak prevention stuff michael@0: nsMenuEntry() { MOZ_COUNT_CTOR(nsMenuEntry); } michael@0: ~nsMenuEntry() { MOZ_COUNT_DTOR(nsMenuEntry); } michael@0: michael@0: nsAutoCString mCharset; michael@0: nsAutoString mTitle; michael@0: }; michael@0: michael@0: //---------------------------------------------------------------------------- michael@0: // Class nsCharsetMenu [declaration] michael@0: michael@0: /** michael@0: * The Charset Converter menu. michael@0: * michael@0: * God, our GUI programming disgusts me. michael@0: * michael@0: * @created 23/Nov/1999 michael@0: * @author Catalin Rotaru [CATA] michael@0: */ michael@0: class nsCharsetMenu : public nsIRDFDataSource, public nsICurrentCharsetListener michael@0: { michael@0: NS_DECL_CYCLE_COLLECTING_ISUPPORTS michael@0: NS_DECL_CYCLE_COLLECTION_CLASS_AMBIGUOUS(nsCharsetMenu, nsIRDFDataSource) michael@0: michael@0: private: michael@0: static nsIRDFResource * kNC_BrowserAutodetMenuRoot; michael@0: static nsIRDFResource * kNC_BrowserCharsetMenuRoot; michael@0: static nsIRDFResource * kNC_BrowserMoreCharsetMenuRoot; michael@0: static nsIRDFResource * kNC_BrowserMore1CharsetMenuRoot; michael@0: static nsIRDFResource * kNC_BrowserMore2CharsetMenuRoot; michael@0: static nsIRDFResource * kNC_BrowserMore3CharsetMenuRoot; michael@0: static nsIRDFResource * kNC_BrowserMore4CharsetMenuRoot; michael@0: static nsIRDFResource * kNC_BrowserMore5CharsetMenuRoot; michael@0: static nsIRDFResource * kNC_MaileditCharsetMenuRoot; michael@0: static nsIRDFResource * kNC_MailviewCharsetMenuRoot; michael@0: static nsIRDFResource * kNC_ComposerCharsetMenuRoot; michael@0: static nsIRDFResource * kNC_DecodersRoot; michael@0: static nsIRDFResource * kNC_EncodersRoot; michael@0: static nsIRDFResource * kNC_Name; michael@0: static nsIRDFResource * kNC_CharsetDetector; michael@0: static nsIRDFResource * kNC_BookmarkSeparator; michael@0: static nsIRDFResource * kRDF_type; michael@0: michael@0: static nsIRDFDataSource * mInner; michael@0: michael@0: bool mInitialized; michael@0: bool mMailviewMenuInitialized; michael@0: bool mComposerMenuInitialized; michael@0: bool mMaileditMenuInitialized; michael@0: bool mSecondaryTiersInitialized; michael@0: bool mAutoDetectInitialized; michael@0: bool mOthersInitialized; michael@0: michael@0: nsTArray mMailviewMenu; michael@0: int32_t mMailviewCacheStart; michael@0: int32_t mMailviewCacheSize; michael@0: int32_t mMailviewMenuRDFPosition; michael@0: michael@0: nsTArray mComposerMenu; michael@0: int32_t mComposerCacheStart; michael@0: int32_t mComposerCacheSize; michael@0: int32_t mComposerMenuRDFPosition; michael@0: michael@0: nsCOMPtr mRDFService; michael@0: nsCOMPtr mCCManager; michael@0: nsCOMPtr mPrefs; michael@0: nsCOMPtr mCharsetMenuObserver; michael@0: nsTArray mDecoderList; michael@0: michael@0: nsresult Done(); michael@0: michael@0: nsresult FreeResources(); michael@0: michael@0: nsresult InitStaticMenu(nsTArray& aDecs, michael@0: nsIRDFResource * aResource, michael@0: const char * aKey, michael@0: nsTArray * aArray); michael@0: nsresult InitCacheMenu(nsTArray& aDecs, michael@0: nsIRDFResource * aResource, michael@0: const char * aKey, michael@0: nsTArray * aArray); michael@0: michael@0: nsresult InitMoreMenu(nsTArray& aDecs, michael@0: nsIRDFResource * aResource, michael@0: const char * aFlag); michael@0: michael@0: nsresult InitMoreSubmenus(nsTArray& aDecs); michael@0: michael@0: static nsresult SetArrayFromEnumerator(nsIUTF8StringEnumerator* aEnumerator, michael@0: nsTArray& aArray); michael@0: michael@0: nsresult AddCharsetToItemArray(nsTArray* aArray, michael@0: const nsAFlatCString& aCharset, michael@0: nsMenuEntry ** aResult, michael@0: int32_t aPlace); michael@0: nsresult AddCharsetArrayToItemArray(nsTArray &aArray, michael@0: const nsTArray& aCharsets); michael@0: nsresult AddMenuItemToContainer(nsIRDFContainer * aContainer, michael@0: nsMenuEntry * aItem, nsIRDFResource * aType, const char * aIDPrefix, michael@0: int32_t aPlace); michael@0: nsresult AddMenuItemArrayToContainer(nsIRDFContainer * aContainer, michael@0: nsTArray * aArray, nsIRDFResource * aType); michael@0: nsresult AddCharsetToContainer(nsTArray * aArray, michael@0: nsIRDFContainer * aContainer, michael@0: const nsAFlatCString& aCharset, michael@0: const char * aIDPrefix, michael@0: int32_t aPlace, int32_t aRDFPlace); michael@0: michael@0: nsresult AddFromPrefsToMenu(nsTArray * aArray, michael@0: nsIRDFContainer * aContainer, michael@0: const char * aKey, michael@0: nsTArray& aDecs, michael@0: const char * aIDPrefix); michael@0: nsresult AddFromNolocPrefsToMenu(nsTArray * aArray, michael@0: nsIRDFContainer * aContainer, michael@0: const char * aKey, michael@0: nsTArray& aDecs, michael@0: const char * aIDPrefix); michael@0: nsresult AddFromStringToMenu(char * aCharsetList, michael@0: nsTArray * aArray, michael@0: nsIRDFContainer * aContainer, michael@0: nsTArray& aDecs, michael@0: const char * aIDPrefix); michael@0: michael@0: nsresult AddSeparatorToContainer(nsIRDFContainer * aContainer); michael@0: nsresult AddCharsetToCache(const nsAFlatCString& aCharset, michael@0: nsTArray * aArray, michael@0: nsIRDFResource * aRDFResource, michael@0: uint32_t aCacheStart, uint32_t aCacheSize, michael@0: int32_t aRDFPlace); michael@0: michael@0: nsresult WriteCacheToPrefs(nsTArray * aArray, int32_t aCacheStart, michael@0: const char * aKey); michael@0: nsresult UpdateCachePrefs(const char * aCacheKey, const char * aCacheSizeKey, michael@0: const char * aStaticKey, const char16_t * aCharset); michael@0: michael@0: nsresult ClearMenu(nsIRDFContainer * aContainer, nsTArray * aArray); michael@0: nsresult RemoveLastMenuItem(nsIRDFContainer * aContainer, michael@0: nsTArray * aArray); michael@0: michael@0: nsresult RemoveFlaggedCharsets(nsTArray& aList, const nsString& aProp); michael@0: nsresult NewRDFContainer(nsIRDFDataSource * aDataSource, michael@0: nsIRDFResource * aResource, nsIRDFContainer ** aResult); michael@0: void FreeMenuItemArray(nsTArray * aArray); michael@0: int32_t FindMenuItemInArray(const nsTArray* aArray, michael@0: const nsAFlatCString& aCharset, michael@0: nsMenuEntry ** aResult); michael@0: nsresult ReorderMenuItemArray(nsTArray * aArray); michael@0: nsresult GetCollation(nsICollation ** aCollation); michael@0: michael@0: public: michael@0: nsCharsetMenu(); michael@0: virtual ~nsCharsetMenu(); michael@0: michael@0: nsresult Init(); michael@0: nsresult InitMaileditMenu(); michael@0: nsresult InitMailviewMenu(); michael@0: nsresult InitComposerMenu(); michael@0: nsresult InitOthers(); michael@0: nsresult InitSecondaryTiers(); michael@0: nsresult InitAutodetMenu(); michael@0: nsresult RefreshMailviewMenu(); michael@0: nsresult RefreshMaileditMenu(); michael@0: nsresult RefreshComposerMenu(); michael@0: michael@0: //-------------------------------------------------------------------------- michael@0: // Interface nsICurrentCharsetListener [declaration] michael@0: michael@0: NS_IMETHOD SetCurrentCharset(const char16_t * aCharset); michael@0: NS_IMETHOD SetCurrentMailCharset(const char16_t * aCharset); michael@0: NS_IMETHOD SetCurrentComposerCharset(const char16_t * aCharset); michael@0: michael@0: //-------------------------------------------------------------------------- michael@0: // Interface nsIRDFDataSource [declaration] michael@0: michael@0: NS_DECL_NSIRDFDATASOURCE michael@0: }; michael@0: michael@0: //---------------------------------------------------------------------------- michael@0: // Global functions and data [implementation] michael@0: michael@0: nsresult michael@0: NS_NewCharsetMenu(nsISupports * aOuter, const nsIID & aIID, michael@0: void ** aResult) michael@0: { michael@0: if (!aResult) { michael@0: return NS_ERROR_NULL_POINTER; michael@0: } michael@0: if (aOuter) { michael@0: *aResult = nullptr; michael@0: return NS_ERROR_NO_AGGREGATION; michael@0: } michael@0: nsCharsetMenu* inst = new nsCharsetMenu(); michael@0: if (!inst) { michael@0: *aResult = nullptr; michael@0: return NS_ERROR_OUT_OF_MEMORY; michael@0: } michael@0: nsresult res = inst->QueryInterface(aIID, aResult); michael@0: if (NS_FAILED(res)) { michael@0: *aResult = nullptr; michael@0: delete inst; michael@0: } michael@0: return res; michael@0: } michael@0: michael@0: struct charsetMenuSortRecord { michael@0: nsMenuEntry* item; michael@0: uint8_t* key; michael@0: uint32_t len; michael@0: michael@0: }; michael@0: michael@0: static int CompareMenuItems(const void* aArg1, const void* aArg2, void *data) michael@0: { michael@0: int32_t res; michael@0: nsICollation * collation = (nsICollation *) data; michael@0: charsetMenuSortRecord *rec1 = (charsetMenuSortRecord *) aArg1; michael@0: charsetMenuSortRecord *rec2 = (charsetMenuSortRecord *) aArg2; michael@0: michael@0: collation->CompareRawSortKey(rec1->key, rec1->len, rec2->key, rec2->len, &res); michael@0: michael@0: return res; michael@0: } michael@0: michael@0: nsresult michael@0: nsCharsetMenu::SetArrayFromEnumerator(nsIUTF8StringEnumerator* aEnumerator, michael@0: nsTArray& aArray) michael@0: { michael@0: nsresult rv; michael@0: michael@0: bool hasMore; michael@0: rv = aEnumerator->HasMore(&hasMore); michael@0: michael@0: nsAutoCString value; michael@0: while (NS_SUCCEEDED(rv) && hasMore) { michael@0: rv = aEnumerator->GetNext(value); michael@0: if (NS_SUCCEEDED(rv)) michael@0: aArray.AppendElement(value); michael@0: michael@0: rv = aEnumerator->HasMore(&hasMore); michael@0: } michael@0: michael@0: return rv; michael@0: } michael@0: michael@0: michael@0: class nsIgnoreCaseCStringComparator michael@0: { michael@0: public: michael@0: bool Equals(const nsACString& a, const nsACString& b) const michael@0: { michael@0: return nsCString(a).Equals(b, nsCaseInsensitiveCStringComparator()); michael@0: } michael@0: michael@0: bool LessThan(const nsACString& a, const nsACString& b) const michael@0: { michael@0: return a < b; michael@0: } michael@0: }; michael@0: michael@0: //---------------------------------------------------------------------------- michael@0: // Class nsCharsetMenuObserver michael@0: michael@0: class nsCharsetMenuObserver : public nsIObserver { michael@0: michael@0: public: michael@0: NS_DECL_ISUPPORTS michael@0: NS_DECL_NSIOBSERVER michael@0: michael@0: nsCharsetMenuObserver(nsCharsetMenu * menu) michael@0: : mCharsetMenu(menu) michael@0: { michael@0: } michael@0: michael@0: virtual ~nsCharsetMenuObserver() {} michael@0: michael@0: private: michael@0: nsCharsetMenu* mCharsetMenu; michael@0: }; michael@0: michael@0: NS_IMPL_ISUPPORTS(nsCharsetMenuObserver, nsIObserver) michael@0: michael@0: NS_IMETHODIMP nsCharsetMenuObserver::Observe(nsISupports *aSubject, const char *aTopic, const char16_t *someData) michael@0: { michael@0: nsresult rv = NS_OK; michael@0: michael@0: //XUL event handler michael@0: if (!nsCRT::strcmp(aTopic, "charsetmenu-selected")) { michael@0: nsDependentString nodeName(someData); michael@0: rv = mCharsetMenu->Init(); michael@0: if (nodeName.EqualsLiteral("composer")) { michael@0: rv = mCharsetMenu->InitComposerMenu(); michael@0: } michael@0: if (nodeName.EqualsLiteral("mailview")) { michael@0: rv = mCharsetMenu->InitMailviewMenu(); michael@0: } michael@0: if (nodeName.EqualsLiteral("mailedit")) { michael@0: rv = mCharsetMenu->InitMaileditMenu(); michael@0: rv = mCharsetMenu->InitOthers(); michael@0: } michael@0: if (nodeName.EqualsLiteral("more-menu")) { michael@0: rv = mCharsetMenu->InitSecondaryTiers(); michael@0: rv = mCharsetMenu->InitAutodetMenu(); michael@0: } michael@0: if (nodeName.EqualsLiteral("other")) { michael@0: rv = mCharsetMenu->InitOthers(); michael@0: rv = mCharsetMenu->InitMaileditMenu(); michael@0: } michael@0: } michael@0: michael@0: //pref event handler michael@0: if (!nsCRT::strcmp(aTopic, NS_PREFBRANCH_PREFCHANGE_TOPIC_ID)) { michael@0: nsDependentString prefName(someData); michael@0: michael@0: if (prefName.EqualsLiteral(kBrowserStaticPrefKey)) { michael@0: // refresh menus which share this pref michael@0: rv = mCharsetMenu->RefreshMailviewMenu(); michael@0: NS_ENSURE_SUCCESS(rv, rv); michael@0: rv = mCharsetMenu->RefreshComposerMenu(); michael@0: } michael@0: else if (prefName.EqualsLiteral(kMaileditPrefKey)) { michael@0: rv = mCharsetMenu->RefreshMaileditMenu(); michael@0: } michael@0: } michael@0: michael@0: return rv; michael@0: } michael@0: michael@0: //---------------------------------------------------------------------------- michael@0: // Class nsCharsetMenu [implementation] michael@0: michael@0: NS_IMPL_CYCLE_COLLECTION_CLASS(nsCharsetMenu) michael@0: michael@0: NS_IMPL_CYCLE_COLLECTION_UNLINK_0(nsCharsetMenu) michael@0: NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(nsCharsetMenu) michael@0: cb.NoteXPCOMChild(nsCharsetMenu::mInner); michael@0: NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END michael@0: michael@0: NS_IMPL_CYCLE_COLLECTING_ADDREF(nsCharsetMenu) michael@0: NS_IMPL_CYCLE_COLLECTING_RELEASE(nsCharsetMenu) michael@0: NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(nsCharsetMenu) michael@0: NS_INTERFACE_MAP_ENTRY(nsIRDFDataSource) michael@0: NS_INTERFACE_MAP_ENTRY(nsICurrentCharsetListener) michael@0: NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIRDFDataSource) michael@0: NS_INTERFACE_MAP_END michael@0: michael@0: nsIRDFDataSource * nsCharsetMenu::mInner = nullptr; michael@0: nsIRDFResource * nsCharsetMenu::kNC_BrowserAutodetMenuRoot = nullptr; michael@0: nsIRDFResource * nsCharsetMenu::kNC_BrowserCharsetMenuRoot = nullptr; michael@0: nsIRDFResource * nsCharsetMenu::kNC_BrowserMoreCharsetMenuRoot = nullptr; michael@0: nsIRDFResource * nsCharsetMenu::kNC_BrowserMore1CharsetMenuRoot = nullptr; michael@0: nsIRDFResource * nsCharsetMenu::kNC_BrowserMore2CharsetMenuRoot = nullptr; michael@0: nsIRDFResource * nsCharsetMenu::kNC_BrowserMore3CharsetMenuRoot = nullptr; michael@0: nsIRDFResource * nsCharsetMenu::kNC_BrowserMore4CharsetMenuRoot = nullptr; michael@0: nsIRDFResource * nsCharsetMenu::kNC_BrowserMore5CharsetMenuRoot = nullptr; michael@0: nsIRDFResource * nsCharsetMenu::kNC_MaileditCharsetMenuRoot = nullptr; michael@0: nsIRDFResource * nsCharsetMenu::kNC_MailviewCharsetMenuRoot = nullptr; michael@0: nsIRDFResource * nsCharsetMenu::kNC_ComposerCharsetMenuRoot = nullptr; michael@0: nsIRDFResource * nsCharsetMenu::kNC_DecodersRoot = nullptr; michael@0: nsIRDFResource * nsCharsetMenu::kNC_EncodersRoot = nullptr; michael@0: nsIRDFResource * nsCharsetMenu::kNC_Name = nullptr; michael@0: nsIRDFResource * nsCharsetMenu::kNC_CharsetDetector = nullptr; michael@0: nsIRDFResource * nsCharsetMenu::kNC_BookmarkSeparator = nullptr; michael@0: nsIRDFResource * nsCharsetMenu::kRDF_type = nullptr; michael@0: michael@0: nsCharsetMenu::nsCharsetMenu() michael@0: : mInitialized(false), michael@0: mMailviewMenuInitialized(false), michael@0: mComposerMenuInitialized(false), michael@0: mMaileditMenuInitialized(false), michael@0: mSecondaryTiersInitialized(false), michael@0: mAutoDetectInitialized(false), michael@0: mOthersInitialized(false) michael@0: { michael@0: nsresult res = NS_OK; michael@0: michael@0: //get charset manager michael@0: mCCManager = do_GetService(NS_CHARSETCONVERTERMANAGER_CONTRACTID, &res); michael@0: michael@0: //initialize skeleton RDF source michael@0: mRDFService = do_GetService(kRDFServiceCID, &res); michael@0: michael@0: if (NS_SUCCEEDED(res)) { michael@0: mRDFService->RegisterDataSource(this, false); michael@0: michael@0: CallCreateInstance(kRDFInMemoryDataSourceCID, &mInner); michael@0: michael@0: mRDFService->GetResource(NS_LITERAL_CSTRING(kURINC_BrowserCharsetMenuRoot), michael@0: &kNC_BrowserCharsetMenuRoot); michael@0: } michael@0: michael@0: //get pref service michael@0: nsCOMPtr PrefService = do_GetService(NS_PREFSERVICE_CONTRACTID, &res); michael@0: if (NS_SUCCEEDED(res)) michael@0: res = PrefService->GetBranch(nullptr, getter_AddRefs(mPrefs)); michael@0: michael@0: //register event listener michael@0: mCharsetMenuObserver = new nsCharsetMenuObserver(this); michael@0: michael@0: if (mCharsetMenuObserver) { michael@0: nsCOMPtr observerService = michael@0: do_GetService("@mozilla.org/observer-service;1", &res); michael@0: michael@0: if (NS_SUCCEEDED(res)) michael@0: res = observerService->AddObserver(mCharsetMenuObserver, michael@0: "charsetmenu-selected", michael@0: false); michael@0: } michael@0: michael@0: NS_ASSERTION(NS_SUCCEEDED(res), "Failed to initialize nsCharsetMenu"); michael@0: } michael@0: michael@0: nsCharsetMenu::~nsCharsetMenu() michael@0: { michael@0: Done(); michael@0: michael@0: FreeMenuItemArray(&mMailviewMenu); michael@0: FreeMenuItemArray(&mComposerMenu); michael@0: michael@0: FreeResources(); michael@0: } michael@0: michael@0: nsresult nsCharsetMenu::RefreshMailviewMenu() michael@0: { michael@0: nsresult res = NS_OK; michael@0: michael@0: nsCOMPtr container; michael@0: res = NewRDFContainer(mInner, kNC_MailviewCharsetMenuRoot, getter_AddRefs(container)); michael@0: if (NS_FAILED(res)) return res; michael@0: michael@0: // clean the menu michael@0: res = ClearMenu(container, &mMailviewMenu); michael@0: if (NS_FAILED(res)) return res; michael@0: michael@0: nsCOMPtr decoders; michael@0: res = mCCManager->GetDecoderList(getter_AddRefs(decoders)); michael@0: if (NS_FAILED(res)) return res; michael@0: michael@0: nsTArray decs; michael@0: SetArrayFromEnumerator(decoders, decs); michael@0: michael@0: res = AddFromPrefsToMenu(&mMailviewMenu, container, kMailviewStaticPrefKey, michael@0: decs, "charset."); michael@0: NS_ASSERTION(NS_SUCCEEDED(res), "error initializing static charset menu from prefs"); michael@0: michael@0: // mark the end of the static area, the rest is cache michael@0: mMailviewCacheStart = mMailviewMenu.Length(); michael@0: michael@0: res = InitCacheMenu(decs, kNC_MailviewCharsetMenuRoot, michael@0: kMailviewCachePrefKey, &mMailviewMenu); michael@0: NS_ASSERTION(NS_SUCCEEDED(res), "error initializing mailview cache charset menu"); michael@0: michael@0: return res; michael@0: } michael@0: michael@0: nsresult nsCharsetMenu::RefreshMaileditMenu() michael@0: { michael@0: nsresult res; michael@0: michael@0: nsCOMPtr container; michael@0: res = NewRDFContainer(mInner, kNC_MaileditCharsetMenuRoot, getter_AddRefs(container)); michael@0: NS_ENSURE_SUCCESS(res, res); michael@0: michael@0: nsCOMPtr enumerator; michael@0: res = container->GetElements(getter_AddRefs(enumerator)); michael@0: NS_ENSURE_SUCCESS(res, res); michael@0: michael@0: // clear the menu michael@0: nsCOMPtr supports; michael@0: while (NS_SUCCEEDED(enumerator->GetNext(getter_AddRefs(supports)))) { michael@0: nsCOMPtr node = do_QueryInterface(supports); michael@0: michael@0: res = mInner->Unassert(kNC_MaileditCharsetMenuRoot, kNC_Name, node); michael@0: NS_ENSURE_SUCCESS(res, res); michael@0: michael@0: res = container->RemoveElement(node, false); michael@0: NS_ENSURE_SUCCESS(res, res); michael@0: } michael@0: michael@0: // get a list of available encoders michael@0: nsCOMPtr encoders; michael@0: res = mCCManager->GetEncoderList(getter_AddRefs(encoders)); michael@0: NS_ENSURE_SUCCESS(res, res); michael@0: michael@0: nsTArray encs; michael@0: SetArrayFromEnumerator(encoders, encs); michael@0: michael@0: // add menu items from pref michael@0: res = AddFromPrefsToMenu(nullptr, container, kMaileditPrefKey, encs, nullptr); michael@0: NS_ASSERTION(NS_SUCCEEDED(res), "error initializing mailedit charset menu from prefs"); michael@0: michael@0: return res; michael@0: } michael@0: michael@0: nsresult nsCharsetMenu::RefreshComposerMenu() michael@0: { michael@0: nsresult res = NS_OK; michael@0: michael@0: nsCOMPtr container; michael@0: res = NewRDFContainer(mInner, kNC_ComposerCharsetMenuRoot, getter_AddRefs(container)); michael@0: if (NS_FAILED(res)) return res; michael@0: michael@0: // clean the menu michael@0: res = ClearMenu(container, &mComposerMenu); michael@0: if (NS_FAILED(res)) return res; michael@0: michael@0: nsCOMPtr decoders; michael@0: res = mCCManager->GetDecoderList(getter_AddRefs(decoders)); michael@0: if (NS_FAILED(res)) return res; michael@0: michael@0: nsTArray decs; michael@0: SetArrayFromEnumerator(decoders, decs); michael@0: michael@0: res = AddFromPrefsToMenu(&mComposerMenu, container, kComposerStaticPrefKey, michael@0: decs, "charset."); michael@0: NS_ASSERTION(NS_SUCCEEDED(res), "error initializing static charset menu from prefs"); michael@0: michael@0: // mark the end of the static area, the rest is cache michael@0: mComposerCacheStart = mComposerMenu.Length(); michael@0: michael@0: res = InitCacheMenu(decs, kNC_ComposerCharsetMenuRoot, michael@0: kComposerCachePrefKey, &mComposerMenu); michael@0: NS_ASSERTION(NS_SUCCEEDED(res), "error initializing composer cache charset menu"); michael@0: michael@0: return res; michael@0: } michael@0: michael@0: nsresult nsCharsetMenu::Init() michael@0: { michael@0: nsresult res = NS_OK; michael@0: michael@0: if (!mInitialized) { michael@0: michael@0: //enumerate decoders michael@0: nsCOMPtr decoders; michael@0: res = mCCManager->GetDecoderList(getter_AddRefs(decoders)); michael@0: if (NS_FAILED(res)) return res; michael@0: michael@0: SetArrayFromEnumerator(decoders, mDecoderList); michael@0: michael@0: //initialize all remaining RDF template nodes michael@0: mRDFService->GetResource(NS_LITERAL_CSTRING(kURINC_BrowserAutodetMenuRoot), michael@0: &kNC_BrowserAutodetMenuRoot); michael@0: mRDFService->GetResource(NS_LITERAL_CSTRING(kURINC_BrowserMoreCharsetMenuRoot), michael@0: &kNC_BrowserMoreCharsetMenuRoot); michael@0: mRDFService->GetResource(NS_LITERAL_CSTRING(kURINC_BrowserMore1CharsetMenuRoot), michael@0: &kNC_BrowserMore1CharsetMenuRoot); michael@0: mRDFService->GetResource(NS_LITERAL_CSTRING(kURINC_BrowserMore2CharsetMenuRoot), michael@0: &kNC_BrowserMore2CharsetMenuRoot); michael@0: mRDFService->GetResource(NS_LITERAL_CSTRING(kURINC_BrowserMore3CharsetMenuRoot), michael@0: &kNC_BrowserMore3CharsetMenuRoot); michael@0: mRDFService->GetResource(NS_LITERAL_CSTRING(kURINC_BrowserMore4CharsetMenuRoot), michael@0: &kNC_BrowserMore4CharsetMenuRoot); michael@0: mRDFService->GetResource(NS_LITERAL_CSTRING(kURINC_BrowserMore5CharsetMenuRoot), michael@0: &kNC_BrowserMore5CharsetMenuRoot); michael@0: mRDFService->GetResource(NS_LITERAL_CSTRING(kURINC_MaileditCharsetMenuRoot), michael@0: &kNC_MaileditCharsetMenuRoot); michael@0: mRDFService->GetResource(NS_LITERAL_CSTRING(kURINC_MailviewCharsetMenuRoot), michael@0: &kNC_MailviewCharsetMenuRoot); michael@0: mRDFService->GetResource(NS_LITERAL_CSTRING(kURINC_ComposerCharsetMenuRoot), michael@0: &kNC_ComposerCharsetMenuRoot); michael@0: mRDFService->GetResource(NS_LITERAL_CSTRING(kURINC_DecodersRoot), michael@0: &kNC_DecodersRoot); michael@0: mRDFService->GetResource(NS_LITERAL_CSTRING(kURINC_EncodersRoot), michael@0: &kNC_EncodersRoot); michael@0: mRDFService->GetResource(NS_LITERAL_CSTRING(kURINC_Name), michael@0: &kNC_Name); michael@0: mRDFService->GetResource(NS_LITERAL_CSTRING(kURINC_CharsetDetector), michael@0: &kNC_CharsetDetector); michael@0: mRDFService->GetResource(NS_LITERAL_CSTRING(kURINC_BookmarkSeparator), michael@0: &kNC_BookmarkSeparator); michael@0: mRDFService->GetResource(NS_LITERAL_CSTRING(kURINC_type), &kRDF_type); michael@0: michael@0: nsIRDFContainerUtils * rdfUtil = nullptr; michael@0: res = CallGetService(kRDFContainerUtilsCID, &rdfUtil); michael@0: if (NS_FAILED(res)) goto done; michael@0: michael@0: res = rdfUtil->MakeSeq(mInner, kNC_BrowserAutodetMenuRoot, nullptr); michael@0: if (NS_FAILED(res)) goto done; michael@0: res = rdfUtil->MakeSeq(mInner, kNC_BrowserCharsetMenuRoot, nullptr); michael@0: if (NS_FAILED(res)) goto done; michael@0: res = rdfUtil->MakeSeq(mInner, kNC_BrowserMoreCharsetMenuRoot, nullptr); michael@0: if (NS_FAILED(res)) goto done; michael@0: res = rdfUtil->MakeSeq(mInner, kNC_BrowserMore1CharsetMenuRoot, nullptr); michael@0: if (NS_FAILED(res)) goto done; michael@0: res = rdfUtil->MakeSeq(mInner, kNC_BrowserMore2CharsetMenuRoot, nullptr); michael@0: if (NS_FAILED(res)) goto done; michael@0: res = rdfUtil->MakeSeq(mInner, kNC_BrowserMore3CharsetMenuRoot, nullptr); michael@0: if (NS_FAILED(res)) goto done; michael@0: res = rdfUtil->MakeSeq(mInner, kNC_BrowserMore4CharsetMenuRoot, nullptr); michael@0: if (NS_FAILED(res)) goto done; michael@0: res = rdfUtil->MakeSeq(mInner, kNC_BrowserMore5CharsetMenuRoot, nullptr); michael@0: if (NS_FAILED(res)) goto done; michael@0: res = rdfUtil->MakeSeq(mInner, kNC_MaileditCharsetMenuRoot, nullptr); michael@0: if (NS_FAILED(res)) goto done; michael@0: res = rdfUtil->MakeSeq(mInner, kNC_MailviewCharsetMenuRoot, nullptr); michael@0: if (NS_FAILED(res)) goto done; michael@0: res = rdfUtil->MakeSeq(mInner, kNC_ComposerCharsetMenuRoot, nullptr); michael@0: if (NS_FAILED(res)) goto done; michael@0: res = rdfUtil->MakeSeq(mInner, kNC_DecodersRoot, nullptr); michael@0: if (NS_FAILED(res)) goto done; michael@0: res = rdfUtil->MakeSeq(mInner, kNC_EncodersRoot, nullptr); michael@0: if (NS_FAILED(res)) goto done; michael@0: michael@0: done: michael@0: NS_IF_RELEASE(rdfUtil); michael@0: if (NS_FAILED(res)) return res; michael@0: } michael@0: mInitialized = NS_SUCCEEDED(res); michael@0: return res; michael@0: } michael@0: michael@0: nsresult nsCharsetMenu::Done() michael@0: { michael@0: nsresult res = NS_OK; michael@0: res = mRDFService->UnregisterDataSource(this); michael@0: michael@0: NS_IF_RELEASE(kNC_BrowserAutodetMenuRoot); michael@0: NS_IF_RELEASE(kNC_BrowserCharsetMenuRoot); michael@0: NS_IF_RELEASE(kNC_BrowserMoreCharsetMenuRoot); michael@0: NS_IF_RELEASE(kNC_BrowserMore1CharsetMenuRoot); michael@0: NS_IF_RELEASE(kNC_BrowserMore2CharsetMenuRoot); michael@0: NS_IF_RELEASE(kNC_BrowserMore3CharsetMenuRoot); michael@0: NS_IF_RELEASE(kNC_BrowserMore4CharsetMenuRoot); michael@0: NS_IF_RELEASE(kNC_BrowserMore5CharsetMenuRoot); michael@0: NS_IF_RELEASE(kNC_MaileditCharsetMenuRoot); michael@0: NS_IF_RELEASE(kNC_MailviewCharsetMenuRoot); michael@0: NS_IF_RELEASE(kNC_ComposerCharsetMenuRoot); michael@0: NS_IF_RELEASE(kNC_DecodersRoot); michael@0: NS_IF_RELEASE(kNC_EncodersRoot); michael@0: NS_IF_RELEASE(kNC_Name); michael@0: NS_IF_RELEASE(kNC_CharsetDetector); michael@0: NS_IF_RELEASE(kNC_BookmarkSeparator); michael@0: NS_IF_RELEASE(kRDF_type); michael@0: NS_IF_RELEASE(mInner); michael@0: michael@0: return res; michael@0: } michael@0: michael@0: /** michael@0: * Free the resources no longer needed by the component. michael@0: */ michael@0: nsresult nsCharsetMenu::FreeResources() michael@0: { michael@0: nsresult res = NS_OK; michael@0: michael@0: if (mCharsetMenuObserver) { michael@0: mPrefs->RemoveObserver(kBrowserStaticPrefKey, mCharsetMenuObserver); michael@0: mPrefs->RemoveObserver(kMaileditPrefKey, mCharsetMenuObserver); michael@0: /* nsIObserverService has to have released nsCharsetMenu already */ michael@0: } michael@0: michael@0: mRDFService = nullptr; michael@0: mCCManager = nullptr; michael@0: mPrefs = nullptr; michael@0: michael@0: return res; michael@0: } michael@0: michael@0: nsresult nsCharsetMenu::InitMaileditMenu() michael@0: { michael@0: nsresult res = NS_OK; michael@0: michael@0: if (!mMaileditMenuInitialized) { michael@0: nsCOMPtr container; michael@0: res = NewRDFContainer(mInner, kNC_MaileditCharsetMenuRoot, getter_AddRefs(container)); michael@0: if (NS_FAILED(res)) return res; michael@0: michael@0: //enumerate encoders michael@0: // this would bring in a whole bunch of 'font encoders' as well as genuine michael@0: // charset encoders, but it's safe because we rely on prefs to filter michael@0: // them out. Moreover, 'customize' menu lists only genuine charset michael@0: // encoders further guarding against 'font encoders' sneaking in. michael@0: nsCOMPtr encoders; michael@0: res = mCCManager->GetEncoderList(getter_AddRefs(encoders)); michael@0: if (NS_FAILED(res)) return res; michael@0: michael@0: nsTArray maileditEncoderList; michael@0: SetArrayFromEnumerator(encoders, maileditEncoderList); michael@0: michael@0: res = AddFromPrefsToMenu(nullptr, container, kMaileditPrefKey, michael@0: maileditEncoderList, nullptr); michael@0: NS_ASSERTION(NS_SUCCEEDED(res), "error initializing mailedit charset menu from prefs"); michael@0: michael@0: // register prefs callback michael@0: mPrefs->AddObserver(kMaileditPrefKey, mCharsetMenuObserver, false); michael@0: } michael@0: michael@0: mMaileditMenuInitialized = NS_SUCCEEDED(res); michael@0: michael@0: return res; michael@0: } michael@0: michael@0: nsresult nsCharsetMenu::InitMailviewMenu() michael@0: { michael@0: nsresult res = NS_OK; michael@0: michael@0: if (!mMailviewMenuInitialized) { michael@0: nsCOMPtr container; michael@0: res = NewRDFContainer(mInner, kNC_MailviewCharsetMenuRoot, getter_AddRefs(container)); michael@0: if (NS_FAILED(res)) return res; michael@0: michael@0: nsTArray mailviewDecoderList(mDecoderList); michael@0: michael@0: res = InitStaticMenu(mailviewDecoderList, kNC_MailviewCharsetMenuRoot, michael@0: kMailviewStaticPrefKey, &mMailviewMenu); michael@0: NS_ASSERTION(NS_SUCCEEDED(res), "error initializing mailview static charset menu"); michael@0: michael@0: // mark the end of the static area, the rest is cache michael@0: mMailviewCacheStart = mMailviewMenu.Length(); michael@0: mPrefs->GetIntPref(kMailviewCacheSizePrefKey, &mMailviewCacheSize); michael@0: michael@0: // compute the position of the menu in the RDF container michael@0: res = container->GetCount(&mMailviewMenuRDFPosition); michael@0: if (NS_FAILED(res)) return res; michael@0: // this "1" here is a correction necessary because the RDF container michael@0: // elements are numbered from 1 (why god, WHY?!?!?!) michael@0: mMailviewMenuRDFPosition -= mMailviewCacheStart - 1; michael@0: michael@0: res = InitCacheMenu(mailviewDecoderList, kNC_MailviewCharsetMenuRoot, michael@0: kMailviewCachePrefKey, &mMailviewMenu); michael@0: NS_ASSERTION(NS_SUCCEEDED(res), "error initializing mailview cache charset menu"); michael@0: } michael@0: michael@0: mMailviewMenuInitialized = NS_SUCCEEDED(res); michael@0: michael@0: return res; michael@0: } michael@0: michael@0: nsresult nsCharsetMenu::InitComposerMenu() michael@0: { michael@0: nsresult res = NS_OK; michael@0: michael@0: if (!mComposerMenuInitialized) { michael@0: nsCOMPtr container; michael@0: res = NewRDFContainer(mInner, kNC_ComposerCharsetMenuRoot, getter_AddRefs(container)); michael@0: if (NS_FAILED(res)) return res; michael@0: michael@0: nsTArray composerDecoderList(mDecoderList); michael@0: michael@0: // even if we fail, the show must go on michael@0: res = InitStaticMenu(composerDecoderList, kNC_ComposerCharsetMenuRoot, michael@0: kComposerStaticPrefKey, &mComposerMenu); michael@0: NS_ASSERTION(NS_SUCCEEDED(res), "error initializing composer static charset menu"); michael@0: michael@0: // mark the end of the static area, the rest is cache michael@0: mComposerCacheStart = mComposerMenu.Length(); michael@0: mPrefs->GetIntPref(kComposerCacheSizePrefKey, &mComposerCacheSize); michael@0: michael@0: // compute the position of the menu in the RDF container michael@0: res = container->GetCount(&mComposerMenuRDFPosition); michael@0: if (NS_FAILED(res)) return res; michael@0: // this "1" here is a correction necessary because the RDF container michael@0: // elements are numbered from 1 (why god, WHY?!?!?!) michael@0: mComposerMenuRDFPosition -= mComposerCacheStart - 1; michael@0: michael@0: res = InitCacheMenu(composerDecoderList, kNC_ComposerCharsetMenuRoot, michael@0: kComposerCachePrefKey, &mComposerMenu); michael@0: NS_ASSERTION(NS_SUCCEEDED(res), "error initializing composer cache charset menu"); michael@0: } michael@0: michael@0: mComposerMenuInitialized = NS_SUCCEEDED(res); michael@0: michael@0: return res; michael@0: } michael@0: michael@0: nsresult nsCharsetMenu::InitOthers() michael@0: { michael@0: nsresult res = NS_OK; michael@0: michael@0: if (!mOthersInitialized) { michael@0: nsTArray othersDecoderList(mDecoderList); michael@0: michael@0: res = InitMoreMenu(othersDecoderList, kNC_DecodersRoot, ".notForBrowser"); michael@0: if (NS_FAILED(res)) return res; michael@0: michael@0: // Using mDecoderList instead of GetEncoderList(), we can avoid having to michael@0: // tag a whole bunch of 'font encoders' with '.notForOutgoing' in michael@0: // charsetData.properties file. michael@0: nsTArray othersEncoderList(mDecoderList); michael@0: michael@0: res = InitMoreMenu(othersEncoderList, kNC_EncodersRoot, ".notForOutgoing"); michael@0: if (NS_FAILED(res)) return res; michael@0: } michael@0: michael@0: mOthersInitialized = NS_SUCCEEDED(res); michael@0: michael@0: return res; michael@0: } michael@0: michael@0: /** michael@0: * Inits the secondary tiers of the charset menu. Because currently all the CS michael@0: * menus are sharing the secondary tiers, one should call this method only michael@0: * once for all of them. michael@0: */ michael@0: nsresult nsCharsetMenu::InitSecondaryTiers() michael@0: { michael@0: nsresult res = NS_OK; michael@0: michael@0: if (!mSecondaryTiersInitialized) { michael@0: nsTArray secondaryTiersDecoderList(mDecoderList); michael@0: michael@0: res = InitMoreSubmenus(secondaryTiersDecoderList); michael@0: NS_ASSERTION(NS_SUCCEEDED(res), "err init browser charset more submenus"); michael@0: michael@0: res = InitMoreMenu(secondaryTiersDecoderList, kNC_BrowserMoreCharsetMenuRoot, ".notForBrowser"); michael@0: NS_ASSERTION(NS_SUCCEEDED(res), "err init browser charset more menu"); michael@0: } michael@0: michael@0: mSecondaryTiersInitialized = NS_SUCCEEDED(res); michael@0: michael@0: return res; michael@0: } michael@0: michael@0: nsresult nsCharsetMenu::InitStaticMenu(nsTArray& aDecs, michael@0: nsIRDFResource * aResource, michael@0: const char * aKey, michael@0: nsTArray * aArray) michael@0: { michael@0: nsresult res = NS_OK; michael@0: nsCOMPtr container; michael@0: michael@0: res = NewRDFContainer(mInner, aResource, getter_AddRefs(container)); michael@0: if (NS_FAILED(res)) return res; michael@0: michael@0: // XXX work around bug that causes the submenus to be first instead of last michael@0: res = AddSeparatorToContainer(container); michael@0: NS_ASSERTION(NS_SUCCEEDED(res), "error adding separator to container"); michael@0: michael@0: res = AddFromPrefsToMenu(aArray, container, aKey, aDecs, "charset."); michael@0: NS_ASSERTION(NS_SUCCEEDED(res), "error initializing static charset menu from prefs"); michael@0: michael@0: return res; michael@0: } michael@0: michael@0: nsresult nsCharsetMenu::InitCacheMenu( michael@0: nsTArray& aDecs, michael@0: nsIRDFResource * aResource, michael@0: const char * aKey, michael@0: nsTArray * aArray) michael@0: { michael@0: nsresult res = NS_OK; michael@0: nsCOMPtr container; michael@0: michael@0: res = NewRDFContainer(mInner, aResource, getter_AddRefs(container)); michael@0: if (NS_FAILED(res)) return res; michael@0: michael@0: res = AddFromNolocPrefsToMenu(aArray, container, aKey, aDecs, "charset."); michael@0: NS_ASSERTION(NS_SUCCEEDED(res), "error initializing cache charset menu from prefs"); michael@0: michael@0: return res; michael@0: } michael@0: michael@0: nsresult nsCharsetMenu::InitAutodetMenu() michael@0: { michael@0: nsresult res = NS_OK; michael@0: michael@0: if (!mAutoDetectInitialized) { michael@0: nsTArray chardetArray; michael@0: nsCOMPtr container; michael@0: nsTArray detectorArray; michael@0: michael@0: res = NewRDFContainer(mInner, kNC_BrowserAutodetMenuRoot, getter_AddRefs(container)); michael@0: if (NS_FAILED(res)) return res; michael@0: michael@0: nsCOMPtr detectors; michael@0: res = mCCManager->GetCharsetDetectorList(getter_AddRefs(detectors)); michael@0: if (NS_FAILED(res)) goto done; michael@0: michael@0: res = SetArrayFromEnumerator(detectors, detectorArray); michael@0: if (NS_FAILED(res)) goto done; michael@0: michael@0: res = AddCharsetArrayToItemArray(chardetArray, detectorArray); michael@0: if (NS_FAILED(res)) goto done; michael@0: michael@0: // reorder the array michael@0: res = ReorderMenuItemArray(&chardetArray); michael@0: if (NS_FAILED(res)) goto done; michael@0: michael@0: res = AddMenuItemArrayToContainer(container, &chardetArray, michael@0: kNC_CharsetDetector); michael@0: if (NS_FAILED(res)) goto done; michael@0: michael@0: done: michael@0: // free the elements in the nsTArray michael@0: FreeMenuItemArray(&chardetArray); michael@0: } michael@0: michael@0: mAutoDetectInitialized = NS_SUCCEEDED(res); michael@0: michael@0: return res; michael@0: } michael@0: michael@0: nsresult nsCharsetMenu::InitMoreMenu(nsTArray& aDecs, michael@0: nsIRDFResource * aResource, michael@0: const char * aFlag) michael@0: { michael@0: nsresult res = NS_OK; michael@0: nsCOMPtr container; michael@0: nsTArray moreMenu; michael@0: michael@0: res = NewRDFContainer(mInner, aResource, getter_AddRefs(container)); michael@0: if (NS_FAILED(res)) goto done; michael@0: michael@0: // remove charsets "not for browser" michael@0: res = RemoveFlaggedCharsets(aDecs, NS_ConvertASCIItoUTF16(aFlag)); michael@0: if (NS_FAILED(res)) goto done; michael@0: michael@0: res = AddCharsetArrayToItemArray(moreMenu, aDecs); michael@0: if (NS_FAILED(res)) goto done; michael@0: michael@0: // reorder the array michael@0: res = ReorderMenuItemArray(&moreMenu); michael@0: if (NS_FAILED(res)) goto done; michael@0: michael@0: res = AddMenuItemArrayToContainer(container, &moreMenu, nullptr); michael@0: if (NS_FAILED(res)) goto done; michael@0: michael@0: done: michael@0: // free the elements in the nsTArray michael@0: FreeMenuItemArray(&moreMenu); michael@0: michael@0: return res; michael@0: } michael@0: michael@0: // XXX please make this method more general; the cut&pasted code is laughable michael@0: nsresult nsCharsetMenu::InitMoreSubmenus(nsTArray& aDecs) michael@0: { michael@0: nsresult res = NS_OK; michael@0: michael@0: nsCOMPtr container1; michael@0: nsCOMPtr container2; michael@0: nsCOMPtr container3; michael@0: nsCOMPtr container4; michael@0: nsCOMPtr container5; michael@0: const char key1[] = "intl.charsetmenu.browser.more1"; michael@0: const char key2[] = "intl.charsetmenu.browser.more2"; michael@0: const char key3[] = "intl.charsetmenu.browser.more3"; michael@0: const char key4[] = "intl.charsetmenu.browser.more4"; michael@0: const char key5[] = "intl.charsetmenu.browser.more5"; michael@0: michael@0: res = NewRDFContainer(mInner, kNC_BrowserMore1CharsetMenuRoot, michael@0: getter_AddRefs(container1)); michael@0: if (NS_FAILED(res)) return res; michael@0: AddFromNolocPrefsToMenu(nullptr, container1, key1, aDecs, nullptr); michael@0: michael@0: res = NewRDFContainer(mInner, kNC_BrowserMore2CharsetMenuRoot, michael@0: getter_AddRefs(container2)); michael@0: if (NS_FAILED(res)) return res; michael@0: AddFromNolocPrefsToMenu(nullptr, container2, key2, aDecs, nullptr); michael@0: michael@0: res = NewRDFContainer(mInner, kNC_BrowserMore3CharsetMenuRoot, michael@0: getter_AddRefs(container3)); michael@0: if (NS_FAILED(res)) return res; michael@0: AddFromNolocPrefsToMenu(nullptr, container3, key3, aDecs, nullptr); michael@0: michael@0: res = NewRDFContainer(mInner, kNC_BrowserMore4CharsetMenuRoot, michael@0: getter_AddRefs(container4)); michael@0: if (NS_FAILED(res)) return res; michael@0: AddFromNolocPrefsToMenu(nullptr, container4, key4, aDecs, nullptr); michael@0: michael@0: res = NewRDFContainer(mInner, kNC_BrowserMore5CharsetMenuRoot, michael@0: getter_AddRefs(container5)); michael@0: if (NS_FAILED(res)) return res; michael@0: AddFromNolocPrefsToMenu(nullptr, container5, key5, aDecs, nullptr); michael@0: michael@0: return res; michael@0: } michael@0: michael@0: nsresult nsCharsetMenu::AddCharsetToItemArray(nsTArray *aArray, michael@0: const nsAFlatCString& aCharset, michael@0: nsMenuEntry ** aResult, michael@0: int32_t aPlace) michael@0: { michael@0: nsresult res = NS_OK; michael@0: nsMenuEntry * item = nullptr; michael@0: michael@0: if (aResult != nullptr) *aResult = nullptr; michael@0: michael@0: item = new nsMenuEntry(); michael@0: if (item == nullptr) { michael@0: res = NS_ERROR_OUT_OF_MEMORY; michael@0: goto done; michael@0: } michael@0: michael@0: item->mCharset = aCharset; michael@0: michael@0: if (NS_FAILED(mCCManager->GetCharsetTitle(aCharset.get(), item->mTitle))) { michael@0: item->mTitle.AssignWithConversion(aCharset.get()); michael@0: } michael@0: michael@0: if (aArray != nullptr) { michael@0: if (aPlace < 0) { michael@0: aArray->AppendElement(item); michael@0: } else { michael@0: aArray->InsertElementsAt(aPlace, 1, item); michael@0: } michael@0: } michael@0: michael@0: if (aResult != nullptr) *aResult = item; michael@0: michael@0: // if we have made another reference to "item", do not delete it michael@0: if ((aArray != nullptr) || (aResult != nullptr)) item = nullptr; michael@0: michael@0: done: michael@0: if (item != nullptr) delete item; michael@0: michael@0: return res; michael@0: } michael@0: michael@0: nsresult michael@0: nsCharsetMenu::AddCharsetArrayToItemArray(nsTArray& aArray, michael@0: const nsTArray& aCharsets) michael@0: { michael@0: uint32_t count = aCharsets.Length(); michael@0: michael@0: for (uint32_t i = 0; i < count; i++) { michael@0: michael@0: const nsCString& str = aCharsets[i]; michael@0: nsresult res = AddCharsetToItemArray(&aArray, str, nullptr, -1); michael@0: michael@0: if (NS_FAILED(res)) michael@0: return res; michael@0: } michael@0: michael@0: return NS_OK; michael@0: } michael@0: michael@0: // aPlace < -1 for Remove michael@0: // aPlace < 0 for Append michael@0: nsresult nsCharsetMenu::AddMenuItemToContainer( michael@0: nsIRDFContainer * aContainer, michael@0: nsMenuEntry * aItem, michael@0: nsIRDFResource * aType, michael@0: const char * aIDPrefix, michael@0: int32_t aPlace) michael@0: { michael@0: nsresult res = NS_OK; michael@0: nsCOMPtr node; michael@0: michael@0: nsAutoCString id; michael@0: if (aIDPrefix != nullptr) id.Assign(aIDPrefix); michael@0: id.Append(aItem->mCharset); michael@0: michael@0: // Make up a unique ID and create the RDF NODE michael@0: res = mRDFService->GetResource(id, getter_AddRefs(node)); michael@0: if (NS_FAILED(res)) return res; michael@0: michael@0: const char16_t * title = aItem->mTitle.get(); michael@0: michael@0: // set node's title michael@0: nsCOMPtr titleLiteral; michael@0: res = mRDFService->GetLiteral(title, getter_AddRefs(titleLiteral)); michael@0: if (NS_FAILED(res)) return res; michael@0: michael@0: if (aPlace < -1) { michael@0: res = Unassert(node, kNC_Name, titleLiteral); michael@0: if (NS_FAILED(res)) return res; michael@0: } else { michael@0: res = Assert(node, kNC_Name, titleLiteral, true); michael@0: if (NS_FAILED(res)) return res; michael@0: } michael@0: michael@0: if (aType != nullptr) { michael@0: if (aPlace < -1) { michael@0: res = Unassert(node, kRDF_type, aType); michael@0: if (NS_FAILED(res)) return res; michael@0: } else { michael@0: res = Assert(node, kRDF_type, aType, true); michael@0: if (NS_FAILED(res)) return res; michael@0: } michael@0: } michael@0: michael@0: // Add the element to the container michael@0: if (aPlace < -1) { michael@0: res = aContainer->RemoveElement(node, true); michael@0: if (NS_FAILED(res)) return res; michael@0: } else if (aPlace < 0) { michael@0: res = aContainer->AppendElement(node); michael@0: if (NS_FAILED(res)) return res; michael@0: } else { michael@0: res = aContainer->InsertElementAt(node, aPlace, true); michael@0: if (NS_FAILED(res)) return res; michael@0: } michael@0: michael@0: return res; michael@0: } michael@0: michael@0: nsresult nsCharsetMenu::AddMenuItemArrayToContainer( michael@0: nsIRDFContainer * aContainer, michael@0: nsTArray * aArray, michael@0: nsIRDFResource * aType) michael@0: { michael@0: uint32_t count = aArray->Length(); michael@0: nsresult res = NS_OK; michael@0: michael@0: for (uint32_t i = 0; i < count; i++) { michael@0: nsMenuEntry * item = aArray->ElementAt(i); michael@0: if (item == nullptr) return NS_ERROR_UNEXPECTED; michael@0: michael@0: res = AddMenuItemToContainer(aContainer, item, aType, nullptr, -1); michael@0: if (NS_FAILED(res)) return res; michael@0: } michael@0: michael@0: return NS_OK; michael@0: } michael@0: michael@0: nsresult nsCharsetMenu::AddCharsetToContainer(nsTArray *aArray, michael@0: nsIRDFContainer * aContainer, michael@0: const nsAFlatCString& aCharset, michael@0: const char * aIDPrefix, michael@0: int32_t aPlace, michael@0: int32_t aRDFPlace) michael@0: { michael@0: nsresult res = NS_OK; michael@0: nsMenuEntry * item = nullptr; michael@0: michael@0: res = AddCharsetToItemArray(aArray, aCharset, &item, aPlace); michael@0: if (NS_FAILED(res)) goto done; michael@0: michael@0: res = AddMenuItemToContainer(aContainer, item, nullptr, aIDPrefix, michael@0: aPlace + aRDFPlace); michael@0: if (NS_FAILED(res)) goto done; michael@0: michael@0: // if we have made another reference to "item", do not delete it michael@0: if (aArray != nullptr) item = nullptr; michael@0: michael@0: done: michael@0: if (item != nullptr) delete item; michael@0: michael@0: return res; michael@0: } michael@0: michael@0: nsresult nsCharsetMenu::AddFromPrefsToMenu( michael@0: nsTArray * aArray, michael@0: nsIRDFContainer * aContainer, michael@0: const char * aKey, michael@0: nsTArray& aDecs, michael@0: const char * aIDPrefix) michael@0: { michael@0: nsresult res = NS_OK; michael@0: michael@0: nsCOMPtr pls; michael@0: res = mPrefs->GetComplexValue(aKey, NS_GET_IID(nsIPrefLocalizedString), getter_AddRefs(pls)); michael@0: if (NS_FAILED(res)) return res; michael@0: michael@0: if (pls) { michael@0: nsXPIDLString ucsval; michael@0: pls->ToString(getter_Copies(ucsval)); michael@0: NS_ConvertUTF16toUTF8 utf8val(ucsval); michael@0: if (ucsval) michael@0: res = AddFromStringToMenu(utf8val.BeginWriting(), aArray, michael@0: aContainer, aDecs, aIDPrefix); michael@0: } michael@0: michael@0: return res; michael@0: } michael@0: michael@0: nsresult michael@0: nsCharsetMenu::AddFromNolocPrefsToMenu(nsTArray * aArray, michael@0: nsIRDFContainer * aContainer, michael@0: const char * aKey, michael@0: nsTArray& aDecs, michael@0: const char * aIDPrefix) michael@0: { michael@0: nsresult res = NS_OK; michael@0: michael@0: char * value = nullptr; michael@0: res = mPrefs->GetCharPref(aKey, &value); michael@0: if (NS_FAILED(res)) return res; michael@0: michael@0: if (value != nullptr) { michael@0: res = AddFromStringToMenu(value, aArray, aContainer, aDecs, aIDPrefix); michael@0: nsMemory::Free(value); michael@0: } michael@0: michael@0: return res; michael@0: } michael@0: michael@0: nsresult nsCharsetMenu::AddFromStringToMenu( michael@0: char * aCharsetList, michael@0: nsTArray * aArray, michael@0: nsIRDFContainer * aContainer, michael@0: nsTArray& aDecs, michael@0: const char * aIDPrefix) michael@0: { michael@0: nsresult res = NS_OK; michael@0: char * p = aCharsetList; michael@0: char * q = p; michael@0: while (*p != 0) { michael@0: for (; (*q != ',') && (*q != ' ') && (*q != 0); q++) {;} michael@0: char temp = *q; michael@0: *q = 0; michael@0: michael@0: // if this charset is not on the accepted list of charsets, ignore it michael@0: int32_t index; michael@0: index = aDecs.IndexOf(nsAutoCString(p), 0, nsIgnoreCaseCStringComparator()); michael@0: if (index >= 0) { michael@0: michael@0: // else, add it to the menu michael@0: res = AddCharsetToContainer(aArray, aContainer, nsDependentCString(p), michael@0: aIDPrefix, -1, 0); michael@0: NS_ASSERTION(NS_SUCCEEDED(res), "cannot add charset to menu"); michael@0: if (NS_FAILED(res)) break; michael@0: michael@0: aDecs.RemoveElementAt(index); michael@0: } michael@0: michael@0: *q = temp; michael@0: for (; (*q == ',') || (*q == ' '); q++) {;} michael@0: p=q; michael@0: } michael@0: michael@0: return NS_OK; michael@0: } michael@0: michael@0: nsresult nsCharsetMenu::AddSeparatorToContainer(nsIRDFContainer * aContainer) michael@0: { michael@0: nsAutoCString str; michael@0: str.AssignLiteral("----"); michael@0: michael@0: // hack to generate unique id's for separators michael@0: static int32_t u = 0; michael@0: u++; michael@0: str.AppendInt(u); michael@0: michael@0: nsMenuEntry item; michael@0: item.mCharset = str; michael@0: item.mTitle.AssignWithConversion(str.get()); michael@0: michael@0: return AddMenuItemToContainer(aContainer, &item, kNC_BookmarkSeparator, michael@0: nullptr, -1); michael@0: } michael@0: michael@0: nsresult michael@0: nsCharsetMenu::AddCharsetToCache(const nsAFlatCString& aCharset, michael@0: nsTArray * aArray, michael@0: nsIRDFResource * aRDFResource, michael@0: uint32_t aCacheStart, michael@0: uint32_t aCacheSize, michael@0: int32_t aRDFPlace) michael@0: { michael@0: int32_t i; michael@0: nsresult res = NS_OK; michael@0: michael@0: i = FindMenuItemInArray(aArray, aCharset, nullptr); michael@0: if (i >= 0) return res; michael@0: michael@0: nsCOMPtr container; michael@0: res = NewRDFContainer(mInner, aRDFResource, getter_AddRefs(container)); michael@0: if (NS_FAILED(res)) return res; michael@0: michael@0: // if too many items, remove last one michael@0: if (aArray->Length() - aCacheStart >= aCacheSize){ michael@0: res = RemoveLastMenuItem(container, aArray); michael@0: if (NS_FAILED(res)) return res; michael@0: } michael@0: michael@0: res = AddCharsetToContainer(aArray, container, aCharset, "charset.", michael@0: aCacheStart, aRDFPlace); michael@0: michael@0: return res; michael@0: } michael@0: michael@0: nsresult nsCharsetMenu::WriteCacheToPrefs(nsTArray * aArray, michael@0: int32_t aCacheStart, michael@0: const char * aKey) michael@0: { michael@0: nsresult res = NS_OK; michael@0: michael@0: // create together the cache string michael@0: nsAutoCString cache; michael@0: nsAutoCString sep(NS_LITERAL_CSTRING(", ")); michael@0: uint32_t count = aArray->Length(); michael@0: michael@0: for (uint32_t i = aCacheStart; i < count; i++) { michael@0: nsMenuEntry * item = aArray->ElementAt(i); michael@0: if (item != nullptr) { michael@0: cache.Append(item->mCharset); michael@0: if (i < count - 1) { michael@0: cache.Append(sep); michael@0: } michael@0: } michael@0: } michael@0: michael@0: // write the pref michael@0: res = mPrefs->SetCharPref(aKey, cache.get()); michael@0: michael@0: return res; michael@0: } michael@0: michael@0: nsresult nsCharsetMenu::UpdateCachePrefs(const char * aCacheKey, michael@0: const char * aCacheSizeKey, michael@0: const char * aStaticKey, michael@0: const char16_t * aCharset) michael@0: { michael@0: nsresult rv = NS_OK; michael@0: nsXPIDLCString cachePrefValue; michael@0: nsXPIDLCString staticPrefValue; michael@0: NS_LossyConvertUTF16toASCII currentCharset(aCharset); michael@0: int32_t cacheSize = 0; michael@0: michael@0: mPrefs->GetCharPref(aCacheKey, getter_Copies(cachePrefValue)); michael@0: mPrefs->GetCharPref(aStaticKey, getter_Copies(staticPrefValue)); michael@0: rv = mPrefs->GetIntPref(aCacheSizeKey, &cacheSize); michael@0: michael@0: if (NS_FAILED(rv) || cacheSize <= 0) michael@0: return NS_ERROR_UNEXPECTED; michael@0: michael@0: if ((cachePrefValue.Find(currentCharset) == kNotFound) && michael@0: (staticPrefValue.Find(currentCharset) == kNotFound)) { michael@0: michael@0: if (!cachePrefValue.IsEmpty()) michael@0: cachePrefValue.Insert(", ", 0); michael@0: michael@0: cachePrefValue.Insert(currentCharset, 0); michael@0: if (cacheSize < (int32_t) cachePrefValue.CountChar(',') + 1) michael@0: cachePrefValue.Truncate(cachePrefValue.RFindChar(',')); michael@0: michael@0: rv = mPrefs->SetCharPref(aCacheKey, cachePrefValue); michael@0: } michael@0: michael@0: return rv; michael@0: } michael@0: michael@0: nsresult nsCharsetMenu::ClearMenu(nsIRDFContainer * aContainer, michael@0: nsTArray * aArray) michael@0: { michael@0: nsresult res = NS_OK; michael@0: michael@0: // clean the RDF data source michael@0: uint32_t count = aArray->Length(); michael@0: for (uint32_t i = 0; i < count; i++) { michael@0: nsMenuEntry * item = aArray->ElementAt(i); michael@0: if (item != nullptr) { michael@0: res = AddMenuItemToContainer(aContainer, item, nullptr, "charset.", -2); michael@0: if (NS_FAILED(res)) return res; michael@0: } michael@0: } michael@0: michael@0: // clean the internal data structures michael@0: FreeMenuItemArray(aArray); michael@0: michael@0: return res; michael@0: } michael@0: michael@0: nsresult nsCharsetMenu::RemoveLastMenuItem(nsIRDFContainer * aContainer, michael@0: nsTArray * aArray) michael@0: { michael@0: nsresult res = NS_OK; michael@0: michael@0: int32_t last = aArray->Length() - 1; michael@0: if (last >= 0) { michael@0: nsMenuEntry * item = aArray->ElementAt(last); michael@0: if (item != nullptr) { michael@0: res = AddMenuItemToContainer(aContainer, item, nullptr, "charset.", -2); michael@0: if (NS_FAILED(res)) return res; michael@0: michael@0: aArray->RemoveElementAt(last); michael@0: } michael@0: } michael@0: michael@0: return res; michael@0: } michael@0: michael@0: nsresult nsCharsetMenu::RemoveFlaggedCharsets(nsTArray& aList, michael@0: const nsString& aProp) michael@0: { michael@0: nsresult res = NS_OK; michael@0: uint32_t count; michael@0: michael@0: count = aList.Length(); michael@0: if (NS_FAILED(res)) return res; michael@0: michael@0: nsAutoString str; michael@0: for (uint32_t i = 0; i < count; i++) { michael@0: michael@0: res = mCCManager->GetCharsetData(aList[i].get(), aProp.get(), str); michael@0: if (NS_FAILED(res)) continue; michael@0: michael@0: aList.RemoveElementAt(i); michael@0: michael@0: i--; michael@0: count--; michael@0: } michael@0: michael@0: return NS_OK; michael@0: } michael@0: michael@0: nsresult nsCharsetMenu::NewRDFContainer(nsIRDFDataSource * aDataSource, michael@0: nsIRDFResource * aResource, michael@0: nsIRDFContainer ** aResult) michael@0: { michael@0: nsresult res = CallCreateInstance(kRDFContainerCID, aResult); michael@0: if (NS_FAILED(res)) return res; michael@0: michael@0: res = (*aResult)->Init(aDataSource, aResource); michael@0: if (NS_FAILED(res)) NS_RELEASE(*aResult); michael@0: michael@0: return res; michael@0: } michael@0: michael@0: void nsCharsetMenu::FreeMenuItemArray(nsTArray * aArray) michael@0: { michael@0: uint32_t count = aArray->Length(); michael@0: for (uint32_t i = 0; i < count; i++) { michael@0: nsMenuEntry * item = aArray->ElementAt(i); michael@0: if (item != nullptr) { michael@0: delete item; michael@0: } michael@0: } michael@0: aArray->Clear(); michael@0: } michael@0: michael@0: int32_t nsCharsetMenu::FindMenuItemInArray(const nsTArray* aArray, michael@0: const nsAFlatCString& aCharset, michael@0: nsMenuEntry ** aResult) michael@0: { michael@0: uint32_t count = aArray->Length(); michael@0: michael@0: for (uint32_t i=0; i < count; i++) { michael@0: nsMenuEntry * item = aArray->ElementAt(i); michael@0: if (item->mCharset == aCharset) { michael@0: if (aResult != nullptr) *aResult = item; michael@0: return i; michael@0: } michael@0: } michael@0: michael@0: if (aResult != nullptr) *aResult = nullptr; michael@0: return -1; michael@0: } michael@0: michael@0: nsresult nsCharsetMenu::ReorderMenuItemArray(nsTArray * aArray) michael@0: { michael@0: nsresult res = NS_OK; michael@0: nsCOMPtr collation; michael@0: uint32_t count = aArray->Length(); michael@0: uint32_t i; michael@0: michael@0: // we need to use a temporary array michael@0: charsetMenuSortRecord *array = new charsetMenuSortRecord [count]; michael@0: NS_ENSURE_TRUE(array, NS_ERROR_OUT_OF_MEMORY); michael@0: for (i = 0; i < count; i++) michael@0: array[i].key = nullptr; michael@0: michael@0: res = GetCollation(getter_AddRefs(collation)); michael@0: if (NS_FAILED(res)) michael@0: goto done; michael@0: michael@0: for (i = 0; i < count && NS_SUCCEEDED(res); i++) { michael@0: array[i].item = aArray->ElementAt(i); michael@0: michael@0: res = collation->AllocateRawSortKey(nsICollation::kCollationCaseInSensitive, michael@0: (array[i].item)->mTitle, &array[i].key, &array[i].len); michael@0: } michael@0: michael@0: // reorder the array michael@0: if (NS_SUCCEEDED(res)) { michael@0: NS_QuickSort(array, count, sizeof(*array), CompareMenuItems, collation); michael@0: michael@0: // move the elements from the temporary array into the the real one michael@0: aArray->Clear(); michael@0: for (i = 0; i < count; i++) { michael@0: aArray->AppendElement(array[i].item); michael@0: } michael@0: } michael@0: michael@0: done: michael@0: for (i = 0; i < count; i++) { michael@0: PR_FREEIF(array[i].key); michael@0: } michael@0: delete [] array; michael@0: return res; michael@0: } michael@0: michael@0: nsresult nsCharsetMenu::GetCollation(nsICollation ** aCollation) michael@0: { michael@0: nsresult res = NS_OK; michael@0: nsCOMPtr locale = nullptr; michael@0: nsICollationFactory * collationFactory = nullptr; michael@0: michael@0: nsCOMPtr localeServ = michael@0: do_GetService(NS_LOCALESERVICE_CONTRACTID, &res); michael@0: if (NS_FAILED(res)) return res; michael@0: michael@0: res = localeServ->GetApplicationLocale(getter_AddRefs(locale)); michael@0: if (NS_FAILED(res)) return res; michael@0: michael@0: res = CallCreateInstance(NS_COLLATIONFACTORY_CONTRACTID, &collationFactory); michael@0: if (NS_FAILED(res)) return res; michael@0: michael@0: res = collationFactory->CreateCollation(locale, aCollation); michael@0: NS_RELEASE(collationFactory); michael@0: return res; michael@0: } michael@0: michael@0: //---------------------------------------------------------------------------- michael@0: // Interface nsICurrentCharsetListener [implementation] michael@0: michael@0: NS_IMETHODIMP nsCharsetMenu::SetCurrentCharset(const char16_t * aCharset) michael@0: { michael@0: return NS_OK; michael@0: } michael@0: michael@0: NS_IMETHODIMP nsCharsetMenu::SetCurrentMailCharset(const char16_t * aCharset) michael@0: { michael@0: nsresult res = NS_OK; michael@0: michael@0: if (mMailviewMenuInitialized) { michael@0: res = AddCharsetToCache(NS_LossyConvertUTF16toASCII(aCharset), michael@0: &mMailviewMenu, kNC_MailviewCharsetMenuRoot, michael@0: mMailviewCacheStart, mMailviewCacheSize, michael@0: mMailviewMenuRDFPosition); michael@0: if (NS_FAILED(res)) return res; michael@0: michael@0: res = WriteCacheToPrefs(&mMailviewMenu, mMailviewCacheStart, michael@0: kMailviewCachePrefKey); michael@0: } else { michael@0: res = UpdateCachePrefs(kMailviewCachePrefKey, kMailviewCacheSizePrefKey, michael@0: kMailviewStaticPrefKey, aCharset); michael@0: } michael@0: return res; michael@0: } michael@0: michael@0: NS_IMETHODIMP nsCharsetMenu::SetCurrentComposerCharset(const char16_t * aCharset) michael@0: { michael@0: nsresult res = NS_OK; michael@0: michael@0: if (mComposerMenuInitialized) { michael@0: michael@0: res = AddCharsetToCache(NS_LossyConvertUTF16toASCII(aCharset), michael@0: &mComposerMenu, kNC_ComposerCharsetMenuRoot, michael@0: mComposerCacheStart, mComposerCacheSize, michael@0: mComposerMenuRDFPosition); michael@0: if (NS_FAILED(res)) return res; michael@0: michael@0: res = WriteCacheToPrefs(&mComposerMenu, mComposerCacheStart, michael@0: kComposerCachePrefKey); michael@0: } else { michael@0: res = UpdateCachePrefs(kComposerCachePrefKey, kComposerCacheSizePrefKey, michael@0: kComposerStaticPrefKey, aCharset); michael@0: } michael@0: return res; michael@0: } michael@0: michael@0: //---------------------------------------------------------------------------- michael@0: // Interface nsIRDFDataSource [implementation] michael@0: michael@0: NS_IMETHODIMP nsCharsetMenu::GetURI(char ** uri) michael@0: { michael@0: if (!uri) return NS_ERROR_NULL_POINTER; michael@0: michael@0: *uri = NS_strdup("rdf:charset-menu"); michael@0: if (!(*uri)) return NS_ERROR_OUT_OF_MEMORY; michael@0: michael@0: return NS_OK; michael@0: } michael@0: michael@0: NS_IMETHODIMP nsCharsetMenu::GetSource(nsIRDFResource* property, michael@0: nsIRDFNode* target, michael@0: bool tv, michael@0: nsIRDFResource** source) michael@0: { michael@0: return mInner->GetSource(property, target, tv, source); michael@0: } michael@0: michael@0: NS_IMETHODIMP nsCharsetMenu::GetSources(nsIRDFResource* property, michael@0: nsIRDFNode* target, michael@0: bool tv, michael@0: nsISimpleEnumerator** sources) michael@0: { michael@0: return mInner->GetSources(property, target, tv, sources); michael@0: } michael@0: michael@0: NS_IMETHODIMP nsCharsetMenu::GetTarget(nsIRDFResource* source, michael@0: nsIRDFResource* property, michael@0: bool tv, michael@0: nsIRDFNode** target) michael@0: { michael@0: return mInner->GetTarget(source, property, tv, target); michael@0: } michael@0: michael@0: NS_IMETHODIMP nsCharsetMenu::GetTargets(nsIRDFResource* source, michael@0: nsIRDFResource* property, michael@0: bool tv, michael@0: nsISimpleEnumerator** targets) michael@0: { michael@0: return mInner->GetTargets(source, property, tv, targets); michael@0: } michael@0: michael@0: NS_IMETHODIMP nsCharsetMenu::Assert(nsIRDFResource* aSource, michael@0: nsIRDFResource* aProperty, michael@0: nsIRDFNode* aTarget, michael@0: bool aTruthValue) michael@0: { michael@0: // TODO: filter out asserts we don't care about michael@0: return mInner->Assert(aSource, aProperty, aTarget, aTruthValue); michael@0: } michael@0: michael@0: NS_IMETHODIMP nsCharsetMenu::Unassert(nsIRDFResource* aSource, michael@0: nsIRDFResource* aProperty, michael@0: nsIRDFNode* aTarget) michael@0: { michael@0: // TODO: filter out unasserts we don't care about michael@0: return mInner->Unassert(aSource, aProperty, aTarget); michael@0: } michael@0: michael@0: michael@0: NS_IMETHODIMP nsCharsetMenu::Change(nsIRDFResource* aSource, michael@0: nsIRDFResource* aProperty, michael@0: nsIRDFNode* aOldTarget, michael@0: nsIRDFNode* aNewTarget) michael@0: { michael@0: // TODO: filter out changes we don't care about michael@0: return mInner->Change(aSource, aProperty, aOldTarget, aNewTarget); michael@0: } michael@0: michael@0: NS_IMETHODIMP nsCharsetMenu::Move(nsIRDFResource* aOldSource, michael@0: nsIRDFResource* aNewSource, michael@0: nsIRDFResource* aProperty, michael@0: nsIRDFNode* aTarget) michael@0: { michael@0: // TODO: filter out changes we don't care about michael@0: return mInner->Move(aOldSource, aNewSource, aProperty, aTarget); michael@0: } michael@0: michael@0: michael@0: NS_IMETHODIMP nsCharsetMenu::HasAssertion(nsIRDFResource* source, michael@0: nsIRDFResource* property, michael@0: nsIRDFNode* target, bool tv, michael@0: bool* hasAssertion) michael@0: { michael@0: return mInner->HasAssertion(source, property, target, tv, hasAssertion); michael@0: } michael@0: michael@0: NS_IMETHODIMP nsCharsetMenu::AddObserver(nsIRDFObserver* n) michael@0: { michael@0: return mInner->AddObserver(n); michael@0: } michael@0: michael@0: NS_IMETHODIMP nsCharsetMenu::RemoveObserver(nsIRDFObserver* n) michael@0: { michael@0: return mInner->RemoveObserver(n); michael@0: } michael@0: michael@0: NS_IMETHODIMP michael@0: nsCharsetMenu::HasArcIn(nsIRDFNode *aNode, nsIRDFResource *aArc, bool *result) michael@0: { michael@0: return mInner->HasArcIn(aNode, aArc, result); michael@0: } michael@0: michael@0: NS_IMETHODIMP michael@0: nsCharsetMenu::HasArcOut(nsIRDFResource *source, nsIRDFResource *aArc, bool *result) michael@0: { michael@0: return mInner->HasArcOut(source, aArc, result); michael@0: } michael@0: michael@0: NS_IMETHODIMP nsCharsetMenu::ArcLabelsIn(nsIRDFNode* node, michael@0: nsISimpleEnumerator** labels) michael@0: { michael@0: return mInner->ArcLabelsIn(node, labels); michael@0: } michael@0: michael@0: NS_IMETHODIMP nsCharsetMenu::ArcLabelsOut(nsIRDFResource* source, michael@0: nsISimpleEnumerator** labels) michael@0: { michael@0: return mInner->ArcLabelsOut(source, labels); michael@0: } michael@0: michael@0: NS_IMETHODIMP nsCharsetMenu::GetAllResources(nsISimpleEnumerator** aCursor) michael@0: { michael@0: return mInner->GetAllResources(aCursor); michael@0: } michael@0: michael@0: NS_IMETHODIMP nsCharsetMenu::GetAllCmds( michael@0: nsIRDFResource* source, michael@0: nsISimpleEnumerator/**/** commands) michael@0: { michael@0: NS_NOTYETIMPLEMENTED("nsCharsetMenu::GetAllCmds"); michael@0: return NS_ERROR_NOT_IMPLEMENTED; michael@0: } michael@0: michael@0: NS_IMETHODIMP nsCharsetMenu::IsCommandEnabled( michael@0: nsISupportsArray/**/* aSources, michael@0: nsIRDFResource* aCommand, michael@0: nsISupportsArray/**/* aArguments, michael@0: bool* aResult) michael@0: { michael@0: NS_NOTYETIMPLEMENTED("nsCharsetMenu::IsCommandEnabled"); michael@0: return NS_ERROR_NOT_IMPLEMENTED; michael@0: } michael@0: michael@0: NS_IMETHODIMP nsCharsetMenu::DoCommand(nsISupportsArray* aSources, michael@0: nsIRDFResource* aCommand, michael@0: nsISupportsArray* aArguments) michael@0: { michael@0: NS_NOTYETIMPLEMENTED("nsCharsetMenu::DoCommand"); michael@0: return NS_ERROR_NOT_IMPLEMENTED; michael@0: } michael@0: michael@0: NS_IMETHODIMP nsCharsetMenu::BeginUpdateBatch() michael@0: { michael@0: return mInner->BeginUpdateBatch(); michael@0: } michael@0: michael@0: NS_IMETHODIMP nsCharsetMenu::EndUpdateBatch() michael@0: { michael@0: return mInner->EndUpdateBatch(); michael@0: }