toolkit/components/intl/nsCharsetMenu.cpp

Fri, 16 Jan 2015 18:13:44 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Fri, 16 Jan 2015 18:13:44 +0100
branch
TOR_BUG_9701
changeset 14
925c144e1f1f
permissions
-rw-r--r--

Integrate suggestion from review to improve consistency with existing code.

     1 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
     2 /* This Source Code Form is subject to the terms of the Mozilla Public
     3  * License, v. 2.0. If a copy of the MPL was not distributed with this
     4  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
     6 #include "nsIServiceManager.h"
     7 #include "nsIComponentManager.h" 
     8 #include "rdf.h"
     9 #include "nsIRDFDataSource.h"
    10 #include "nsIRDFService.h"
    11 #include "nsIRDFContainerUtils.h"
    12 #include "nsRDFCID.h"
    13 #include "nsXPIDLString.h"
    14 #include "nsCharsetMenu.h"
    15 #include "nsICharsetConverterManager.h"
    16 #include "nsICollation.h"
    17 #include "nsCollationCID.h"
    18 #include "nsILocaleService.h"
    19 #include "nsIPrefService.h"
    20 #include "nsIPrefBranch.h"
    21 #include "nsIPrefLocalizedString.h"
    22 #include "nsICurrentCharsetListener.h"
    23 #include "nsQuickSort.h"
    24 #include "nsIObserver.h"
    25 #include "nsStringEnumerator.h"
    26 #include "nsTArray.h"
    27 #include "nsIObserverService.h"
    28 #include "nsIRequestObserver.h"
    29 #include "nsCRT.h"
    30 #include "prmem.h"
    31 #include "mozilla/ModuleUtils.h"
    32 #include "nsCycleCollectionParticipant.h"
    34 //----------------------------------------------------------------------------
    35 // Global functions and data [declaration]
    37 static NS_DEFINE_CID(kRDFServiceCID, NS_RDFSERVICE_CID);
    38 static NS_DEFINE_CID(kRDFInMemoryDataSourceCID, NS_RDFINMEMORYDATASOURCE_CID);
    39 static NS_DEFINE_CID(kRDFContainerUtilsCID, NS_RDFCONTAINERUTILS_CID);
    40 static NS_DEFINE_CID(kRDFContainerCID, NS_RDFCONTAINER_CID);
    42 static const char kURINC_BrowserAutodetMenuRoot[] = "NC:BrowserAutodetMenuRoot";
    43 static const char kURINC_BrowserCharsetMenuRoot[] = "NC:BrowserCharsetMenuRoot";
    44 static const char kURINC_BrowserMoreCharsetMenuRoot[] = "NC:BrowserMoreCharsetMenuRoot";
    45 static const char kURINC_BrowserMore1CharsetMenuRoot[] = "NC:BrowserMore1CharsetMenuRoot";
    46 static const char kURINC_BrowserMore2CharsetMenuRoot[] = "NC:BrowserMore2CharsetMenuRoot";
    47 static const char kURINC_BrowserMore3CharsetMenuRoot[] = "NC:BrowserMore3CharsetMenuRoot";
    48 static const char kURINC_BrowserMore4CharsetMenuRoot[] = "NC:BrowserMore4CharsetMenuRoot";
    49 static const char kURINC_BrowserMore5CharsetMenuRoot[] = "NC:BrowserMore5CharsetMenuRoot";
    50 static const char kURINC_MaileditCharsetMenuRoot[] = "NC:MaileditCharsetMenuRoot";
    51 static const char kURINC_MailviewCharsetMenuRoot[] = "NC:MailviewCharsetMenuRoot";
    52 static const char kURINC_ComposerCharsetMenuRoot[] = "NC:ComposerCharsetMenuRoot";
    53 static const char kURINC_DecodersRoot[] = "NC:DecodersRoot";
    54 static const char kURINC_EncodersRoot[] = "NC:EncodersRoot";
    55 DEFINE_RDF_VOCAB(NC_NAMESPACE_URI, NC, Name);
    56 DEFINE_RDF_VOCAB(NC_NAMESPACE_URI, NC, BookmarkSeparator);
    57 DEFINE_RDF_VOCAB(NC_NAMESPACE_URI, NC, CharsetDetector);
    58 DEFINE_RDF_VOCAB(RDF_NAMESPACE_URI, NC, type);
    60 // Note here that browser and mailview have the same static area and cache 
    61 // size but the cache itself is separate.
    63 #define kBrowserStaticPrefKey       "intl.charsetmenu.browser.static"
    64 #define kBrowserCachePrefKey        "intl.charsetmenu.browser.cache"
    65 #define kBrowserCacheSizePrefKey    "intl.charsetmenu.browser.cache.size"
    67 #define kMailviewStaticPrefKey      "intl.charsetmenu.browser.static"
    68 #define kMailviewCachePrefKey       "intl.charsetmenu.mailview.cache"
    69 #define kMailviewCacheSizePrefKey   "intl.charsetmenu.browser.cache.size"
    71 #define kComposerStaticPrefKey      "intl.charsetmenu.browser.static"
    72 #define kComposerCachePrefKey       "intl.charsetmenu.composer.cache"
    73 #define kComposerCacheSizePrefKey   "intl.charsetmenu.browser.cache.size"
    75 #define kMaileditPrefKey            "intl.charsetmenu.mailedit"
    77 //----------------------------------------------------------------------------
    78 // Class nsMenuEntry [declaration]
    80 /**
    81  * A little class holding all data needed for a menu item.
    82  *
    83  * @created         18/Apr/2000
    84  * @author  Catalin Rotaru [CATA]
    85  */
    86 class nsMenuEntry
    87 {
    88 public: 
    89   // memory & ref counting & leak prevention stuff
    90   nsMenuEntry() { MOZ_COUNT_CTOR(nsMenuEntry); }
    91   ~nsMenuEntry() { MOZ_COUNT_DTOR(nsMenuEntry); }
    93   nsAutoCString mCharset;
    94   nsAutoString      mTitle;
    95 };
    97 //----------------------------------------------------------------------------
    98 // Class nsCharsetMenu [declaration]
   100 /**
   101  * The Charset Converter menu.
   102  *
   103  * God, our GUI programming disgusts me.
   104  *
   105  * @created         23/Nov/1999
   106  * @author  Catalin Rotaru [CATA]
   107  */
   108 class nsCharsetMenu : public nsIRDFDataSource, public nsICurrentCharsetListener
   109 {
   110   NS_DECL_CYCLE_COLLECTING_ISUPPORTS
   111   NS_DECL_CYCLE_COLLECTION_CLASS_AMBIGUOUS(nsCharsetMenu, nsIRDFDataSource)
   113 private:
   114   static nsIRDFResource * kNC_BrowserAutodetMenuRoot;
   115   static nsIRDFResource * kNC_BrowserCharsetMenuRoot;
   116   static nsIRDFResource * kNC_BrowserMoreCharsetMenuRoot;
   117   static nsIRDFResource * kNC_BrowserMore1CharsetMenuRoot;
   118   static nsIRDFResource * kNC_BrowserMore2CharsetMenuRoot;
   119   static nsIRDFResource * kNC_BrowserMore3CharsetMenuRoot;
   120   static nsIRDFResource * kNC_BrowserMore4CharsetMenuRoot;
   121   static nsIRDFResource * kNC_BrowserMore5CharsetMenuRoot;
   122   static nsIRDFResource * kNC_MaileditCharsetMenuRoot;
   123   static nsIRDFResource * kNC_MailviewCharsetMenuRoot;
   124   static nsIRDFResource * kNC_ComposerCharsetMenuRoot;
   125   static nsIRDFResource * kNC_DecodersRoot;
   126   static nsIRDFResource * kNC_EncodersRoot;
   127   static nsIRDFResource * kNC_Name;
   128   static nsIRDFResource * kNC_CharsetDetector;
   129   static nsIRDFResource * kNC_BookmarkSeparator;
   130   static nsIRDFResource * kRDF_type;
   132   static nsIRDFDataSource * mInner;
   134   bool mInitialized;
   135   bool mMailviewMenuInitialized;
   136   bool mComposerMenuInitialized;
   137   bool mMaileditMenuInitialized;
   138   bool mSecondaryTiersInitialized;
   139   bool mAutoDetectInitialized;
   140   bool mOthersInitialized;
   142   nsTArray<nsMenuEntry*> mMailviewMenu;
   143   int32_t                mMailviewCacheStart;
   144   int32_t                mMailviewCacheSize;
   145   int32_t                mMailviewMenuRDFPosition;
   147   nsTArray<nsMenuEntry*> mComposerMenu;
   148   int32_t                mComposerCacheStart;
   149   int32_t                mComposerCacheSize;
   150   int32_t                mComposerMenuRDFPosition;
   152   nsCOMPtr<nsIRDFService>               mRDFService;
   153   nsCOMPtr<nsICharsetConverterManager> mCCManager;
   154   nsCOMPtr<nsIPrefBranch>               mPrefs;
   155   nsCOMPtr<nsIObserver>                 mCharsetMenuObserver;
   156   nsTArray<nsCString>                   mDecoderList;
   158   nsresult Done();
   160   nsresult FreeResources();
   162   nsresult InitStaticMenu(nsTArray<nsCString>& aDecs,
   163                           nsIRDFResource * aResource,
   164                           const char * aKey,
   165                           nsTArray<nsMenuEntry*> * aArray);
   166   nsresult InitCacheMenu(nsTArray<nsCString>& aDecs,
   167                          nsIRDFResource * aResource,
   168                          const char * aKey,
   169                          nsTArray<nsMenuEntry*> * aArray);
   171   nsresult InitMoreMenu(nsTArray<nsCString>& aDecs,
   172                         nsIRDFResource * aResource,
   173                         const char * aFlag);
   175   nsresult InitMoreSubmenus(nsTArray<nsCString>& aDecs);
   177   static nsresult SetArrayFromEnumerator(nsIUTF8StringEnumerator* aEnumerator,
   178                                          nsTArray<nsCString>& aArray);
   180   nsresult AddCharsetToItemArray(nsTArray<nsMenuEntry*>* aArray,
   181                                  const nsAFlatCString& aCharset,
   182                                  nsMenuEntry ** aResult,
   183                                  int32_t aPlace);
   184   nsresult AddCharsetArrayToItemArray(nsTArray<nsMenuEntry*> &aArray,
   185                                       const nsTArray<nsCString>& aCharsets);
   186   nsresult AddMenuItemToContainer(nsIRDFContainer * aContainer,
   187     nsMenuEntry * aItem, nsIRDFResource * aType, const char * aIDPrefix,
   188     int32_t aPlace);
   189   nsresult AddMenuItemArrayToContainer(nsIRDFContainer * aContainer,
   190     nsTArray<nsMenuEntry*> * aArray, nsIRDFResource * aType);
   191   nsresult AddCharsetToContainer(nsTArray<nsMenuEntry*> * aArray,
   192                                  nsIRDFContainer * aContainer,
   193                                  const nsAFlatCString& aCharset,
   194                                  const char * aIDPrefix,
   195     int32_t aPlace, int32_t aRDFPlace);
   197   nsresult AddFromPrefsToMenu(nsTArray<nsMenuEntry*> * aArray,
   198                               nsIRDFContainer * aContainer,
   199                               const char * aKey,
   200                               nsTArray<nsCString>& aDecs,
   201                               const char * aIDPrefix);
   202   nsresult AddFromNolocPrefsToMenu(nsTArray<nsMenuEntry*> * aArray,
   203                                    nsIRDFContainer * aContainer,
   204                                    const char * aKey,
   205                                    nsTArray<nsCString>& aDecs,
   206                                    const char * aIDPrefix);
   207   nsresult AddFromStringToMenu(char * aCharsetList,
   208                                nsTArray<nsMenuEntry*> * aArray,
   209                                nsIRDFContainer * aContainer,
   210                                nsTArray<nsCString>& aDecs,
   211                                const char * aIDPrefix);
   213   nsresult AddSeparatorToContainer(nsIRDFContainer * aContainer);
   214   nsresult AddCharsetToCache(const nsAFlatCString& aCharset,
   215                              nsTArray<nsMenuEntry*> * aArray,
   216                              nsIRDFResource * aRDFResource,
   217                              uint32_t aCacheStart, uint32_t aCacheSize,
   218                              int32_t aRDFPlace);
   220   nsresult WriteCacheToPrefs(nsTArray<nsMenuEntry*> * aArray, int32_t aCacheStart,
   221     const char * aKey);
   222   nsresult UpdateCachePrefs(const char * aCacheKey, const char * aCacheSizeKey,
   223     const char * aStaticKey, const char16_t * aCharset);
   225   nsresult ClearMenu(nsIRDFContainer * aContainer, nsTArray<nsMenuEntry*> * aArray);
   226   nsresult RemoveLastMenuItem(nsIRDFContainer * aContainer,
   227                               nsTArray<nsMenuEntry*> * aArray);
   229   nsresult RemoveFlaggedCharsets(nsTArray<nsCString>& aList, const nsString& aProp);
   230   nsresult NewRDFContainer(nsIRDFDataSource * aDataSource,
   231     nsIRDFResource * aResource, nsIRDFContainer ** aResult);
   232   void FreeMenuItemArray(nsTArray<nsMenuEntry*> * aArray);
   233   int32_t FindMenuItemInArray(const nsTArray<nsMenuEntry*>* aArray,
   234                               const nsAFlatCString& aCharset,
   235                               nsMenuEntry ** aResult);
   236   nsresult ReorderMenuItemArray(nsTArray<nsMenuEntry*> * aArray);
   237   nsresult GetCollation(nsICollation ** aCollation);
   239 public:
   240   nsCharsetMenu();
   241   virtual ~nsCharsetMenu();
   243   nsresult Init();
   244   nsresult InitMaileditMenu();
   245   nsresult InitMailviewMenu();
   246   nsresult InitComposerMenu();
   247   nsresult InitOthers();
   248   nsresult InitSecondaryTiers();
   249   nsresult InitAutodetMenu();
   250   nsresult RefreshMailviewMenu();
   251   nsresult RefreshMaileditMenu();
   252   nsresult RefreshComposerMenu();
   254   //--------------------------------------------------------------------------
   255   // Interface nsICurrentCharsetListener [declaration]
   257   NS_IMETHOD SetCurrentCharset(const char16_t * aCharset);
   258   NS_IMETHOD SetCurrentMailCharset(const char16_t * aCharset);
   259   NS_IMETHOD SetCurrentComposerCharset(const char16_t * aCharset);
   261   //--------------------------------------------------------------------------
   262   // Interface nsIRDFDataSource [declaration]
   264   NS_DECL_NSIRDFDATASOURCE
   265 };
   267 //----------------------------------------------------------------------------
   268 // Global functions and data [implementation]
   270 nsresult
   271 NS_NewCharsetMenu(nsISupports * aOuter, const nsIID & aIID, 
   272                   void ** aResult)
   273 {
   274   if (!aResult) {
   275     return NS_ERROR_NULL_POINTER;
   276   }
   277   if (aOuter) {
   278     *aResult = nullptr;
   279     return NS_ERROR_NO_AGGREGATION;
   280   }
   281   nsCharsetMenu* inst = new nsCharsetMenu();
   282   if (!inst) {
   283     *aResult = nullptr;
   284     return NS_ERROR_OUT_OF_MEMORY;
   285   }
   286   nsresult res = inst->QueryInterface(aIID, aResult);
   287   if (NS_FAILED(res)) {
   288     *aResult = nullptr;
   289     delete inst;
   290   }
   291   return res;
   292 }
   294 struct charsetMenuSortRecord {
   295   nsMenuEntry* item;
   296   uint8_t*     key;
   297   uint32_t     len;
   299 };
   301 static int CompareMenuItems(const void* aArg1, const void* aArg2, void *data)
   302 {
   303   int32_t res; 
   304   nsICollation * collation = (nsICollation *) data;
   305   charsetMenuSortRecord *rec1 = (charsetMenuSortRecord *) aArg1;
   306   charsetMenuSortRecord *rec2 = (charsetMenuSortRecord *) aArg2;
   308   collation->CompareRawSortKey(rec1->key, rec1->len, rec2->key, rec2->len, &res);
   310   return res;
   311 }
   313 nsresult
   314 nsCharsetMenu::SetArrayFromEnumerator(nsIUTF8StringEnumerator* aEnumerator,
   315                                       nsTArray<nsCString>& aArray)
   316 {
   317   nsresult rv;
   319   bool hasMore;
   320   rv = aEnumerator->HasMore(&hasMore);
   322   nsAutoCString value;
   323   while (NS_SUCCEEDED(rv) && hasMore) {
   324     rv = aEnumerator->GetNext(value);
   325     if (NS_SUCCEEDED(rv))
   326       aArray.AppendElement(value);
   328     rv = aEnumerator->HasMore(&hasMore);
   329   }
   331   return rv;
   332 }
   335 class nsIgnoreCaseCStringComparator
   336 {
   337   public:
   338     bool Equals(const nsACString& a, const nsACString& b) const
   339     {
   340       return nsCString(a).Equals(b, nsCaseInsensitiveCStringComparator());
   341     }
   343     bool LessThan(const nsACString& a, const nsACString& b) const
   344     { 
   345       return a < b;
   346     }
   347 };
   349 //----------------------------------------------------------------------------
   350 // Class nsCharsetMenuObserver
   352 class nsCharsetMenuObserver : public nsIObserver {
   354 public:
   355   NS_DECL_ISUPPORTS
   356   NS_DECL_NSIOBSERVER
   358   nsCharsetMenuObserver(nsCharsetMenu * menu)
   359     : mCharsetMenu(menu)
   360   {
   361   }
   363   virtual ~nsCharsetMenuObserver() {}
   365 private:
   366   nsCharsetMenu* mCharsetMenu;
   367 };
   369 NS_IMPL_ISUPPORTS(nsCharsetMenuObserver, nsIObserver)
   371 NS_IMETHODIMP nsCharsetMenuObserver::Observe(nsISupports *aSubject, const char *aTopic, const char16_t *someData)
   372 {
   373   nsresult rv = NS_OK;
   375   //XUL event handler
   376   if (!nsCRT::strcmp(aTopic, "charsetmenu-selected")) {
   377     nsDependentString nodeName(someData);
   378     rv = mCharsetMenu->Init();
   379     if (nodeName.EqualsLiteral("composer")) {
   380       rv = mCharsetMenu->InitComposerMenu();
   381     }
   382     if (nodeName.EqualsLiteral("mailview")) {
   383       rv = mCharsetMenu->InitMailviewMenu();
   384     }
   385     if (nodeName.EqualsLiteral("mailedit")) {
   386       rv = mCharsetMenu->InitMaileditMenu();
   387       rv = mCharsetMenu->InitOthers();
   388     }
   389     if (nodeName.EqualsLiteral("more-menu")) {
   390       rv = mCharsetMenu->InitSecondaryTiers();
   391       rv = mCharsetMenu->InitAutodetMenu();
   392     }
   393     if (nodeName.EqualsLiteral("other")) {
   394       rv = mCharsetMenu->InitOthers();
   395       rv = mCharsetMenu->InitMaileditMenu();
   396     }
   397   }
   399    //pref event handler
   400   if (!nsCRT::strcmp(aTopic, NS_PREFBRANCH_PREFCHANGE_TOPIC_ID)) {
   401     nsDependentString prefName(someData);
   403     if (prefName.EqualsLiteral(kBrowserStaticPrefKey)) {
   404       // refresh menus which share this pref
   405       rv = mCharsetMenu->RefreshMailviewMenu();
   406       NS_ENSURE_SUCCESS(rv, rv);
   407       rv = mCharsetMenu->RefreshComposerMenu();
   408     }
   409     else if (prefName.EqualsLiteral(kMaileditPrefKey)) {
   410       rv = mCharsetMenu->RefreshMaileditMenu();
   411     }
   412   }
   414   return rv;
   415 }
   417 //----------------------------------------------------------------------------
   418 // Class nsCharsetMenu [implementation]
   420 NS_IMPL_CYCLE_COLLECTION_CLASS(nsCharsetMenu)
   422 NS_IMPL_CYCLE_COLLECTION_UNLINK_0(nsCharsetMenu)
   423 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(nsCharsetMenu)
   424   cb.NoteXPCOMChild(nsCharsetMenu::mInner);
   425 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
   427 NS_IMPL_CYCLE_COLLECTING_ADDREF(nsCharsetMenu)
   428 NS_IMPL_CYCLE_COLLECTING_RELEASE(nsCharsetMenu)
   429 NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(nsCharsetMenu)
   430   NS_INTERFACE_MAP_ENTRY(nsIRDFDataSource)
   431   NS_INTERFACE_MAP_ENTRY(nsICurrentCharsetListener)
   432   NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIRDFDataSource)
   433 NS_INTERFACE_MAP_END
   435 nsIRDFDataSource * nsCharsetMenu::mInner = nullptr;
   436 nsIRDFResource * nsCharsetMenu::kNC_BrowserAutodetMenuRoot = nullptr;
   437 nsIRDFResource * nsCharsetMenu::kNC_BrowserCharsetMenuRoot = nullptr;
   438 nsIRDFResource * nsCharsetMenu::kNC_BrowserMoreCharsetMenuRoot = nullptr;
   439 nsIRDFResource * nsCharsetMenu::kNC_BrowserMore1CharsetMenuRoot = nullptr;
   440 nsIRDFResource * nsCharsetMenu::kNC_BrowserMore2CharsetMenuRoot = nullptr;
   441 nsIRDFResource * nsCharsetMenu::kNC_BrowserMore3CharsetMenuRoot = nullptr;
   442 nsIRDFResource * nsCharsetMenu::kNC_BrowserMore4CharsetMenuRoot = nullptr;
   443 nsIRDFResource * nsCharsetMenu::kNC_BrowserMore5CharsetMenuRoot = nullptr;
   444 nsIRDFResource * nsCharsetMenu::kNC_MaileditCharsetMenuRoot = nullptr;
   445 nsIRDFResource * nsCharsetMenu::kNC_MailviewCharsetMenuRoot = nullptr;
   446 nsIRDFResource * nsCharsetMenu::kNC_ComposerCharsetMenuRoot = nullptr;
   447 nsIRDFResource * nsCharsetMenu::kNC_DecodersRoot = nullptr;
   448 nsIRDFResource * nsCharsetMenu::kNC_EncodersRoot = nullptr;
   449 nsIRDFResource * nsCharsetMenu::kNC_Name = nullptr;
   450 nsIRDFResource * nsCharsetMenu::kNC_CharsetDetector = nullptr;
   451 nsIRDFResource * nsCharsetMenu::kNC_BookmarkSeparator = nullptr;
   452 nsIRDFResource * nsCharsetMenu::kRDF_type = nullptr;
   454 nsCharsetMenu::nsCharsetMenu() 
   455 : mInitialized(false), 
   456   mMailviewMenuInitialized(false),
   457   mComposerMenuInitialized(false),
   458   mMaileditMenuInitialized(false),
   459   mSecondaryTiersInitialized(false),
   460   mAutoDetectInitialized(false),
   461   mOthersInitialized(false)
   462 {
   463   nsresult res = NS_OK;
   465   //get charset manager
   466   mCCManager = do_GetService(NS_CHARSETCONVERTERMANAGER_CONTRACTID, &res);
   468   //initialize skeleton RDF source
   469   mRDFService = do_GetService(kRDFServiceCID, &res);
   471   if (NS_SUCCEEDED(res))  {
   472     mRDFService->RegisterDataSource(this, false);
   474     CallCreateInstance(kRDFInMemoryDataSourceCID, &mInner);
   476     mRDFService->GetResource(NS_LITERAL_CSTRING(kURINC_BrowserCharsetMenuRoot),
   477                              &kNC_BrowserCharsetMenuRoot);
   478   }
   480   //get pref service
   481   nsCOMPtr<nsIPrefService> PrefService = do_GetService(NS_PREFSERVICE_CONTRACTID, &res);
   482   if (NS_SUCCEEDED(res))
   483     res = PrefService->GetBranch(nullptr, getter_AddRefs(mPrefs));
   485   //register event listener
   486   mCharsetMenuObserver = new nsCharsetMenuObserver(this);
   488   if (mCharsetMenuObserver)  {
   489     nsCOMPtr<nsIObserverService> observerService = 
   490              do_GetService("@mozilla.org/observer-service;1", &res);
   492     if (NS_SUCCEEDED(res))
   493       res = observerService->AddObserver(mCharsetMenuObserver, 
   494                                          "charsetmenu-selected", 
   495                                          false);
   496   }
   498   NS_ASSERTION(NS_SUCCEEDED(res), "Failed to initialize nsCharsetMenu");
   499 }
   501 nsCharsetMenu::~nsCharsetMenu() 
   502 {
   503   Done();
   505   FreeMenuItemArray(&mMailviewMenu);
   506   FreeMenuItemArray(&mComposerMenu);
   508   FreeResources();
   509 }
   511 nsresult nsCharsetMenu::RefreshMailviewMenu()
   512 {
   513   nsresult res = NS_OK;
   515   nsCOMPtr<nsIRDFContainer> container;
   516   res = NewRDFContainer(mInner, kNC_MailviewCharsetMenuRoot, getter_AddRefs(container));
   517   if (NS_FAILED(res)) return res;
   519   // clean the menu
   520   res = ClearMenu(container, &mMailviewMenu);
   521   if (NS_FAILED(res)) return res;
   523   nsCOMPtr<nsIUTF8StringEnumerator> decoders;
   524   res = mCCManager->GetDecoderList(getter_AddRefs(decoders));
   525   if (NS_FAILED(res)) return res;
   527   nsTArray<nsCString> decs;
   528   SetArrayFromEnumerator(decoders, decs);
   530   res = AddFromPrefsToMenu(&mMailviewMenu, container, kMailviewStaticPrefKey, 
   531                            decs, "charset.");
   532   NS_ASSERTION(NS_SUCCEEDED(res), "error initializing static charset menu from prefs");
   534   // mark the end of the static area, the rest is cache
   535   mMailviewCacheStart = mMailviewMenu.Length();
   537   res = InitCacheMenu(decs, kNC_MailviewCharsetMenuRoot, 
   538     kMailviewCachePrefKey, &mMailviewMenu);
   539   NS_ASSERTION(NS_SUCCEEDED(res), "error initializing mailview cache charset menu");
   541   return res;
   542 }
   544 nsresult nsCharsetMenu::RefreshMaileditMenu()
   545 {
   546   nsresult res;
   548   nsCOMPtr<nsIRDFContainer> container;
   549   res = NewRDFContainer(mInner, kNC_MaileditCharsetMenuRoot, getter_AddRefs(container));
   550   NS_ENSURE_SUCCESS(res, res);
   552   nsCOMPtr<nsISimpleEnumerator> enumerator;
   553   res = container->GetElements(getter_AddRefs(enumerator));
   554   NS_ENSURE_SUCCESS(res, res);
   556   // clear the menu
   557   nsCOMPtr<nsISupports> supports;
   558   while (NS_SUCCEEDED(enumerator->GetNext(getter_AddRefs(supports)))) {
   559     nsCOMPtr<nsIRDFNode> node = do_QueryInterface(supports);
   561     res = mInner->Unassert(kNC_MaileditCharsetMenuRoot, kNC_Name, node);
   562     NS_ENSURE_SUCCESS(res, res);
   564     res = container->RemoveElement(node, false);
   565     NS_ENSURE_SUCCESS(res, res);
   566   }
   568   // get a list of available encoders
   569   nsCOMPtr<nsIUTF8StringEnumerator> encoders;
   570   res = mCCManager->GetEncoderList(getter_AddRefs(encoders));
   571   NS_ENSURE_SUCCESS(res, res);
   573   nsTArray<nsCString> encs;
   574   SetArrayFromEnumerator(encoders, encs);
   576   // add menu items from pref
   577   res = AddFromPrefsToMenu(nullptr, container, kMaileditPrefKey, encs, nullptr);
   578   NS_ASSERTION(NS_SUCCEEDED(res), "error initializing mailedit charset menu from prefs");
   580   return res;
   581 }
   583 nsresult nsCharsetMenu::RefreshComposerMenu()
   584 {
   585   nsresult res = NS_OK;
   587   nsCOMPtr<nsIRDFContainer> container;
   588   res = NewRDFContainer(mInner, kNC_ComposerCharsetMenuRoot, getter_AddRefs(container));
   589   if (NS_FAILED(res)) return res;
   591   // clean the menu
   592   res = ClearMenu(container, &mComposerMenu);
   593   if (NS_FAILED(res)) return res;
   595   nsCOMPtr<nsIUTF8StringEnumerator> decoders;
   596   res = mCCManager->GetDecoderList(getter_AddRefs(decoders));
   597   if (NS_FAILED(res)) return res;
   599   nsTArray<nsCString> decs;
   600   SetArrayFromEnumerator(decoders, decs);
   602   res = AddFromPrefsToMenu(&mComposerMenu, container, kComposerStaticPrefKey, 
   603                            decs, "charset.");
   604   NS_ASSERTION(NS_SUCCEEDED(res), "error initializing static charset menu from prefs");
   606   // mark the end of the static area, the rest is cache
   607   mComposerCacheStart = mComposerMenu.Length();
   609   res = InitCacheMenu(decs, kNC_ComposerCharsetMenuRoot, 
   610     kComposerCachePrefKey, &mComposerMenu);
   611   NS_ASSERTION(NS_SUCCEEDED(res), "error initializing composer cache charset menu");
   613   return res;
   614 }
   616 nsresult nsCharsetMenu::Init() 
   617 {
   618   nsresult res = NS_OK;
   620   if (!mInitialized)  {
   622     //enumerate decoders
   623     nsCOMPtr<nsIUTF8StringEnumerator> decoders;
   624     res = mCCManager->GetDecoderList(getter_AddRefs(decoders));
   625     if (NS_FAILED(res)) return res;
   627     SetArrayFromEnumerator(decoders, mDecoderList);
   629     //initialize all remaining RDF template nodes
   630     mRDFService->GetResource(NS_LITERAL_CSTRING(kURINC_BrowserAutodetMenuRoot),
   631                              &kNC_BrowserAutodetMenuRoot);
   632     mRDFService->GetResource(NS_LITERAL_CSTRING(kURINC_BrowserMoreCharsetMenuRoot),
   633                              &kNC_BrowserMoreCharsetMenuRoot);
   634     mRDFService->GetResource(NS_LITERAL_CSTRING(kURINC_BrowserMore1CharsetMenuRoot),
   635                              &kNC_BrowserMore1CharsetMenuRoot);
   636     mRDFService->GetResource(NS_LITERAL_CSTRING(kURINC_BrowserMore2CharsetMenuRoot),
   637                              &kNC_BrowserMore2CharsetMenuRoot);
   638     mRDFService->GetResource(NS_LITERAL_CSTRING(kURINC_BrowserMore3CharsetMenuRoot),
   639                              &kNC_BrowserMore3CharsetMenuRoot);
   640     mRDFService->GetResource(NS_LITERAL_CSTRING(kURINC_BrowserMore4CharsetMenuRoot),
   641                              &kNC_BrowserMore4CharsetMenuRoot);
   642     mRDFService->GetResource(NS_LITERAL_CSTRING(kURINC_BrowserMore5CharsetMenuRoot),
   643                              &kNC_BrowserMore5CharsetMenuRoot);
   644     mRDFService->GetResource(NS_LITERAL_CSTRING(kURINC_MaileditCharsetMenuRoot),
   645                              &kNC_MaileditCharsetMenuRoot);
   646     mRDFService->GetResource(NS_LITERAL_CSTRING(kURINC_MailviewCharsetMenuRoot),
   647                              &kNC_MailviewCharsetMenuRoot);
   648     mRDFService->GetResource(NS_LITERAL_CSTRING(kURINC_ComposerCharsetMenuRoot),
   649                              &kNC_ComposerCharsetMenuRoot);
   650     mRDFService->GetResource(NS_LITERAL_CSTRING(kURINC_DecodersRoot),
   651                              &kNC_DecodersRoot);
   652     mRDFService->GetResource(NS_LITERAL_CSTRING(kURINC_EncodersRoot),
   653                              &kNC_EncodersRoot);
   654     mRDFService->GetResource(NS_LITERAL_CSTRING(kURINC_Name),
   655                              &kNC_Name);
   656     mRDFService->GetResource(NS_LITERAL_CSTRING(kURINC_CharsetDetector),
   657                              &kNC_CharsetDetector);
   658     mRDFService->GetResource(NS_LITERAL_CSTRING(kURINC_BookmarkSeparator),
   659                              &kNC_BookmarkSeparator);
   660     mRDFService->GetResource(NS_LITERAL_CSTRING(kURINC_type), &kRDF_type);
   662     nsIRDFContainerUtils * rdfUtil = nullptr;
   663     res = CallGetService(kRDFContainerUtilsCID, &rdfUtil);
   664     if (NS_FAILED(res)) goto done;
   666     res = rdfUtil->MakeSeq(mInner, kNC_BrowserAutodetMenuRoot, nullptr);
   667     if (NS_FAILED(res)) goto done;
   668     res = rdfUtil->MakeSeq(mInner, kNC_BrowserCharsetMenuRoot, nullptr);
   669     if (NS_FAILED(res)) goto done;
   670     res = rdfUtil->MakeSeq(mInner, kNC_BrowserMoreCharsetMenuRoot, nullptr);
   671     if (NS_FAILED(res)) goto done;
   672     res = rdfUtil->MakeSeq(mInner, kNC_BrowserMore1CharsetMenuRoot, nullptr);
   673     if (NS_FAILED(res)) goto done;
   674     res = rdfUtil->MakeSeq(mInner, kNC_BrowserMore2CharsetMenuRoot, nullptr);
   675     if (NS_FAILED(res)) goto done;
   676     res = rdfUtil->MakeSeq(mInner, kNC_BrowserMore3CharsetMenuRoot, nullptr);
   677     if (NS_FAILED(res)) goto done;
   678     res = rdfUtil->MakeSeq(mInner, kNC_BrowserMore4CharsetMenuRoot, nullptr);
   679     if (NS_FAILED(res)) goto done;
   680     res = rdfUtil->MakeSeq(mInner, kNC_BrowserMore5CharsetMenuRoot, nullptr);
   681     if (NS_FAILED(res)) goto done;
   682     res = rdfUtil->MakeSeq(mInner, kNC_MaileditCharsetMenuRoot, nullptr);
   683     if (NS_FAILED(res)) goto done;
   684     res = rdfUtil->MakeSeq(mInner, kNC_MailviewCharsetMenuRoot, nullptr);
   685     if (NS_FAILED(res)) goto done;
   686     res = rdfUtil->MakeSeq(mInner, kNC_ComposerCharsetMenuRoot, nullptr);
   687     if (NS_FAILED(res)) goto done;
   688     res = rdfUtil->MakeSeq(mInner, kNC_DecodersRoot, nullptr);
   689     if (NS_FAILED(res)) goto done;
   690     res = rdfUtil->MakeSeq(mInner, kNC_EncodersRoot, nullptr);
   691     if (NS_FAILED(res)) goto done;
   693   done:
   694     NS_IF_RELEASE(rdfUtil);
   695     if (NS_FAILED(res)) return res;
   696   }
   697   mInitialized = NS_SUCCEEDED(res);
   698   return res;
   699 }
   701 nsresult nsCharsetMenu::Done() 
   702 {
   703   nsresult res = NS_OK;
   704   res = mRDFService->UnregisterDataSource(this);
   706   NS_IF_RELEASE(kNC_BrowserAutodetMenuRoot);
   707   NS_IF_RELEASE(kNC_BrowserCharsetMenuRoot);
   708   NS_IF_RELEASE(kNC_BrowserMoreCharsetMenuRoot);
   709   NS_IF_RELEASE(kNC_BrowserMore1CharsetMenuRoot);
   710   NS_IF_RELEASE(kNC_BrowserMore2CharsetMenuRoot);
   711   NS_IF_RELEASE(kNC_BrowserMore3CharsetMenuRoot);
   712   NS_IF_RELEASE(kNC_BrowserMore4CharsetMenuRoot);
   713   NS_IF_RELEASE(kNC_BrowserMore5CharsetMenuRoot);
   714   NS_IF_RELEASE(kNC_MaileditCharsetMenuRoot);
   715   NS_IF_RELEASE(kNC_MailviewCharsetMenuRoot);
   716   NS_IF_RELEASE(kNC_ComposerCharsetMenuRoot);
   717   NS_IF_RELEASE(kNC_DecodersRoot);
   718   NS_IF_RELEASE(kNC_EncodersRoot);
   719   NS_IF_RELEASE(kNC_Name);
   720   NS_IF_RELEASE(kNC_CharsetDetector);
   721   NS_IF_RELEASE(kNC_BookmarkSeparator);
   722   NS_IF_RELEASE(kRDF_type);
   723   NS_IF_RELEASE(mInner);
   725   return res;
   726 }
   728 /**
   729  * Free the resources no longer needed by the component.
   730  */
   731 nsresult nsCharsetMenu::FreeResources()
   732 {
   733   nsresult res = NS_OK;
   735   if (mCharsetMenuObserver) {
   736     mPrefs->RemoveObserver(kBrowserStaticPrefKey, mCharsetMenuObserver);
   737     mPrefs->RemoveObserver(kMaileditPrefKey, mCharsetMenuObserver);
   738     /* nsIObserverService has to have released nsCharsetMenu already */
   739   }
   741   mRDFService = nullptr;
   742   mCCManager  = nullptr;
   743   mPrefs      = nullptr;
   745   return res;
   746 }
   748 nsresult nsCharsetMenu::InitMaileditMenu() 
   749 {
   750   nsresult res = NS_OK;
   752   if (!mMaileditMenuInitialized)  {
   753     nsCOMPtr<nsIRDFContainer> container;
   754     res = NewRDFContainer(mInner, kNC_MaileditCharsetMenuRoot, getter_AddRefs(container));
   755     if (NS_FAILED(res)) return res;
   757     //enumerate encoders
   758     // this would bring in a whole bunch of 'font encoders' as well as genuine 
   759     // charset encoders, but it's safe because we rely on prefs to filter
   760     // them out. Moreover, 'customize' menu lists only genuine charset 
   761     // encoders further guarding  against  'font encoders' sneaking in. 
   762     nsCOMPtr<nsIUTF8StringEnumerator> encoders;
   763     res = mCCManager->GetEncoderList(getter_AddRefs(encoders));
   764     if (NS_FAILED(res))  return res;
   766     nsTArray<nsCString> maileditEncoderList;
   767     SetArrayFromEnumerator(encoders, maileditEncoderList);
   769     res = AddFromPrefsToMenu(nullptr, container, kMaileditPrefKey,
   770                              maileditEncoderList, nullptr);
   771     NS_ASSERTION(NS_SUCCEEDED(res), "error initializing mailedit charset menu from prefs");
   773     // register prefs callback
   774     mPrefs->AddObserver(kMaileditPrefKey, mCharsetMenuObserver, false);
   775   }
   777   mMaileditMenuInitialized = NS_SUCCEEDED(res);
   779   return res;
   780 }
   782 nsresult nsCharsetMenu::InitMailviewMenu() 
   783 {
   784   nsresult res = NS_OK;
   786   if (!mMailviewMenuInitialized)  {
   787     nsCOMPtr<nsIRDFContainer> container;
   788     res = NewRDFContainer(mInner, kNC_MailviewCharsetMenuRoot, getter_AddRefs(container));
   789     if (NS_FAILED(res)) return res;
   791     nsTArray<nsCString> mailviewDecoderList(mDecoderList);
   793     res = InitStaticMenu(mailviewDecoderList, kNC_MailviewCharsetMenuRoot, 
   794                          kMailviewStaticPrefKey, &mMailviewMenu);
   795     NS_ASSERTION(NS_SUCCEEDED(res), "error initializing mailview static charset menu");
   797     // mark the end of the static area, the rest is cache
   798     mMailviewCacheStart = mMailviewMenu.Length();
   799     mPrefs->GetIntPref(kMailviewCacheSizePrefKey, &mMailviewCacheSize);
   801     // compute the position of the menu in the RDF container
   802     res = container->GetCount(&mMailviewMenuRDFPosition);
   803     if (NS_FAILED(res)) return res;
   804     // this "1" here is a correction necessary because the RDF container 
   805     // elements are numbered from 1 (why god, WHY?!?!?!)
   806     mMailviewMenuRDFPosition -= mMailviewCacheStart - 1;
   808     res = InitCacheMenu(mailviewDecoderList, kNC_MailviewCharsetMenuRoot, 
   809       kMailviewCachePrefKey, &mMailviewMenu);
   810     NS_ASSERTION(NS_SUCCEEDED(res), "error initializing mailview cache charset menu");
   811   }
   813   mMailviewMenuInitialized = NS_SUCCEEDED(res);
   815   return res;
   816 }
   818 nsresult nsCharsetMenu::InitComposerMenu() 
   819 {
   820   nsresult res = NS_OK;
   822   if (!mComposerMenuInitialized)  {
   823     nsCOMPtr<nsIRDFContainer> container;
   824     res = NewRDFContainer(mInner, kNC_ComposerCharsetMenuRoot, getter_AddRefs(container));
   825     if (NS_FAILED(res)) return res;
   827     nsTArray<nsCString> composerDecoderList(mDecoderList);
   829     // even if we fail, the show must go on
   830     res = InitStaticMenu(composerDecoderList, kNC_ComposerCharsetMenuRoot, 
   831       kComposerStaticPrefKey, &mComposerMenu);
   832     NS_ASSERTION(NS_SUCCEEDED(res), "error initializing composer static charset menu");
   834     // mark the end of the static area, the rest is cache
   835     mComposerCacheStart = mComposerMenu.Length();
   836     mPrefs->GetIntPref(kComposerCacheSizePrefKey, &mComposerCacheSize);
   838     // compute the position of the menu in the RDF container
   839     res = container->GetCount(&mComposerMenuRDFPosition);
   840     if (NS_FAILED(res)) return res;
   841     // this "1" here is a correction necessary because the RDF container 
   842     // elements are numbered from 1 (why god, WHY?!?!?!)
   843     mComposerMenuRDFPosition -= mComposerCacheStart - 1;
   845     res = InitCacheMenu(composerDecoderList, kNC_ComposerCharsetMenuRoot, 
   846       kComposerCachePrefKey, &mComposerMenu);
   847     NS_ASSERTION(NS_SUCCEEDED(res), "error initializing composer cache charset menu");
   848   }
   850   mComposerMenuInitialized = NS_SUCCEEDED(res);
   852   return res;
   853 }
   855 nsresult nsCharsetMenu::InitOthers() 
   856 {
   857   nsresult res = NS_OK;
   859   if (!mOthersInitialized) {
   860     nsTArray<nsCString> othersDecoderList(mDecoderList);
   862     res = InitMoreMenu(othersDecoderList, kNC_DecodersRoot, ".notForBrowser");                 
   863     if (NS_FAILED(res))  return res;
   865     // Using mDecoderList instead of GetEncoderList(), we can avoid having to
   866     // tag a whole bunch of 'font encoders' with '.notForOutgoing' in 
   867     // charsetData.properties file. 
   868     nsTArray<nsCString> othersEncoderList(mDecoderList);
   870     res = InitMoreMenu(othersEncoderList, kNC_EncodersRoot, ".notForOutgoing");                 
   871     if (NS_FAILED(res)) return res;
   872   }
   874   mOthersInitialized = NS_SUCCEEDED(res);
   876   return res;
   877 }
   879 /**
   880  * Inits the secondary tiers of the charset menu. Because currently all the CS 
   881  * menus are sharing the secondary tiers, one should call this method only 
   882  * once for all of them.
   883  */
   884 nsresult nsCharsetMenu::InitSecondaryTiers()
   885 {
   886   nsresult res = NS_OK;
   888   if (!mSecondaryTiersInitialized)  {
   889     nsTArray<nsCString> secondaryTiersDecoderList(mDecoderList);
   891     res = InitMoreSubmenus(secondaryTiersDecoderList);
   892     NS_ASSERTION(NS_SUCCEEDED(res), "err init browser charset more submenus");
   894     res = InitMoreMenu(secondaryTiersDecoderList, kNC_BrowserMoreCharsetMenuRoot, ".notForBrowser");
   895     NS_ASSERTION(NS_SUCCEEDED(res), "err init browser charset more menu");
   896   }
   898   mSecondaryTiersInitialized = NS_SUCCEEDED(res);
   900   return res;
   901 }
   903 nsresult nsCharsetMenu::InitStaticMenu(nsTArray<nsCString>& aDecs,
   904                                        nsIRDFResource * aResource,
   905                                        const char * aKey,
   906                                        nsTArray<nsMenuEntry*> * aArray)
   907 {
   908   nsresult res = NS_OK;
   909   nsCOMPtr<nsIRDFContainer> container;
   911   res = NewRDFContainer(mInner, aResource, getter_AddRefs(container));
   912   if (NS_FAILED(res)) return res;
   914   // XXX work around bug that causes the submenus to be first instead of last
   915   res = AddSeparatorToContainer(container);
   916   NS_ASSERTION(NS_SUCCEEDED(res), "error adding separator to container");
   918   res = AddFromPrefsToMenu(aArray, container, aKey, aDecs, "charset.");
   919   NS_ASSERTION(NS_SUCCEEDED(res), "error initializing static charset menu from prefs");
   921   return res;
   922 }
   924 nsresult nsCharsetMenu::InitCacheMenu(
   925                         nsTArray<nsCString>& aDecs,
   926                         nsIRDFResource * aResource,
   927                         const char * aKey,
   928                         nsTArray<nsMenuEntry*> * aArray)
   929 {
   930   nsresult res = NS_OK;
   931   nsCOMPtr<nsIRDFContainer> container;
   933   res = NewRDFContainer(mInner, aResource, getter_AddRefs(container));
   934   if (NS_FAILED(res)) return res;
   936   res = AddFromNolocPrefsToMenu(aArray, container, aKey, aDecs, "charset.");
   937   NS_ASSERTION(NS_SUCCEEDED(res), "error initializing cache charset menu from prefs");
   939   return res;
   940 }
   942 nsresult nsCharsetMenu::InitAutodetMenu()
   943 {
   944   nsresult res = NS_OK;
   946   if (!mAutoDetectInitialized) {
   947     nsTArray<nsMenuEntry*> chardetArray;
   948     nsCOMPtr<nsIRDFContainer> container;
   949     nsTArray<nsCString> detectorArray;
   951     res = NewRDFContainer(mInner, kNC_BrowserAutodetMenuRoot, getter_AddRefs(container));
   952     if (NS_FAILED(res)) return res;
   954     nsCOMPtr<nsIUTF8StringEnumerator> detectors;
   955     res = mCCManager->GetCharsetDetectorList(getter_AddRefs(detectors));
   956     if (NS_FAILED(res)) goto done;
   958     res = SetArrayFromEnumerator(detectors, detectorArray);
   959     if (NS_FAILED(res)) goto done;
   961     res = AddCharsetArrayToItemArray(chardetArray, detectorArray);
   962     if (NS_FAILED(res)) goto done;
   964     // reorder the array
   965     res = ReorderMenuItemArray(&chardetArray);
   966     if (NS_FAILED(res)) goto done;
   968     res = AddMenuItemArrayToContainer(container, &chardetArray, 
   969       kNC_CharsetDetector);
   970     if (NS_FAILED(res)) goto done;
   972   done:
   973     // free the elements in the nsTArray<nsMenuEntry*>
   974     FreeMenuItemArray(&chardetArray);
   975   }
   977   mAutoDetectInitialized = NS_SUCCEEDED(res);
   979   return res;
   980 }
   982 nsresult nsCharsetMenu::InitMoreMenu(nsTArray<nsCString>& aDecs, 
   983                                      nsIRDFResource * aResource, 
   984                                      const char * aFlag)
   985 {
   986   nsresult res = NS_OK;
   987   nsCOMPtr<nsIRDFContainer> container;
   988   nsTArray<nsMenuEntry*> moreMenu;
   990   res = NewRDFContainer(mInner, aResource, getter_AddRefs(container));
   991   if (NS_FAILED(res)) goto done;
   993   // remove charsets "not for browser"
   994   res = RemoveFlaggedCharsets(aDecs, NS_ConvertASCIItoUTF16(aFlag));
   995   if (NS_FAILED(res)) goto done;
   997   res = AddCharsetArrayToItemArray(moreMenu, aDecs);
   998   if (NS_FAILED(res)) goto done;
  1000   // reorder the array
  1001   res = ReorderMenuItemArray(&moreMenu);
  1002   if (NS_FAILED(res)) goto done;
  1004   res = AddMenuItemArrayToContainer(container, &moreMenu, nullptr);
  1005   if (NS_FAILED(res)) goto done;
  1007 done:
  1008   // free the elements in the nsTArray<nsMenuEntry*>
  1009   FreeMenuItemArray(&moreMenu);
  1011   return res;
  1014 // XXX please make this method more general; the cut&pasted code is laughable
  1015 nsresult nsCharsetMenu::InitMoreSubmenus(nsTArray<nsCString>& aDecs)
  1017   nsresult res = NS_OK;
  1019   nsCOMPtr<nsIRDFContainer> container1;
  1020   nsCOMPtr<nsIRDFContainer> container2;
  1021   nsCOMPtr<nsIRDFContainer> container3;
  1022   nsCOMPtr<nsIRDFContainer> container4;
  1023   nsCOMPtr<nsIRDFContainer> container5;
  1024   const char key1[] = "intl.charsetmenu.browser.more1";
  1025   const char key2[] = "intl.charsetmenu.browser.more2";
  1026   const char key3[] = "intl.charsetmenu.browser.more3";
  1027   const char key4[] = "intl.charsetmenu.browser.more4";
  1028   const char key5[] = "intl.charsetmenu.browser.more5";
  1030   res = NewRDFContainer(mInner, kNC_BrowserMore1CharsetMenuRoot, 
  1031     getter_AddRefs(container1));
  1032   if (NS_FAILED(res)) return res;
  1033   AddFromNolocPrefsToMenu(nullptr, container1, key1, aDecs, nullptr);
  1035   res = NewRDFContainer(mInner, kNC_BrowserMore2CharsetMenuRoot, 
  1036     getter_AddRefs(container2));
  1037   if (NS_FAILED(res)) return res;
  1038   AddFromNolocPrefsToMenu(nullptr, container2, key2, aDecs, nullptr);
  1040   res = NewRDFContainer(mInner, kNC_BrowserMore3CharsetMenuRoot, 
  1041     getter_AddRefs(container3));
  1042   if (NS_FAILED(res)) return res;
  1043   AddFromNolocPrefsToMenu(nullptr, container3, key3, aDecs, nullptr);
  1045   res = NewRDFContainer(mInner, kNC_BrowserMore4CharsetMenuRoot, 
  1046     getter_AddRefs(container4));
  1047   if (NS_FAILED(res)) return res;
  1048   AddFromNolocPrefsToMenu(nullptr, container4, key4, aDecs, nullptr);
  1050   res = NewRDFContainer(mInner, kNC_BrowserMore5CharsetMenuRoot, 
  1051     getter_AddRefs(container5));
  1052   if (NS_FAILED(res)) return res;
  1053   AddFromNolocPrefsToMenu(nullptr, container5, key5, aDecs, nullptr);
  1055   return res;
  1058 nsresult nsCharsetMenu::AddCharsetToItemArray(nsTArray<nsMenuEntry*> *aArray,
  1059                                               const nsAFlatCString& aCharset,
  1060                                               nsMenuEntry ** aResult,
  1061                                               int32_t aPlace)
  1063   nsresult res = NS_OK;
  1064   nsMenuEntry * item = nullptr; 
  1066   if (aResult != nullptr) *aResult = nullptr;
  1068   item = new nsMenuEntry();
  1069   if (item == nullptr) {
  1070     res = NS_ERROR_OUT_OF_MEMORY;
  1071     goto done;
  1074   item->mCharset = aCharset;
  1076   if (NS_FAILED(mCCManager->GetCharsetTitle(aCharset.get(), item->mTitle))) {
  1077     item->mTitle.AssignWithConversion(aCharset.get());
  1080   if (aArray != nullptr) {
  1081     if (aPlace < 0) {
  1082       aArray->AppendElement(item);
  1083     } else {
  1084       aArray->InsertElementsAt(aPlace, 1, item);
  1088   if (aResult != nullptr) *aResult = item;
  1090   // if we have made another reference to "item", do not delete it 
  1091   if ((aArray != nullptr) || (aResult != nullptr)) item = nullptr; 
  1093 done:
  1094   if (item != nullptr) delete item;
  1096   return res;
  1099 nsresult
  1100 nsCharsetMenu::AddCharsetArrayToItemArray(nsTArray<nsMenuEntry*>& aArray,
  1101                                           const nsTArray<nsCString>& aCharsets)
  1103   uint32_t count = aCharsets.Length();
  1105   for (uint32_t i = 0; i < count; i++) {
  1107     const nsCString& str = aCharsets[i];
  1108     nsresult res = AddCharsetToItemArray(&aArray, str, nullptr, -1);
  1110     if (NS_FAILED(res))
  1111       return res;
  1114   return NS_OK;
  1117 // aPlace < -1 for Remove
  1118 // aPlace < 0 for Append
  1119 nsresult nsCharsetMenu::AddMenuItemToContainer(
  1120                         nsIRDFContainer * aContainer,
  1121                         nsMenuEntry * aItem,
  1122                         nsIRDFResource * aType,
  1123                         const char * aIDPrefix,
  1124                         int32_t aPlace) 
  1126   nsresult res = NS_OK;
  1127   nsCOMPtr<nsIRDFResource> node;
  1129   nsAutoCString id;
  1130   if (aIDPrefix != nullptr) id.Assign(aIDPrefix);
  1131   id.Append(aItem->mCharset);
  1133   // Make up a unique ID and create the RDF NODE
  1134   res = mRDFService->GetResource(id, getter_AddRefs(node));
  1135   if (NS_FAILED(res)) return res;
  1137   const char16_t * title = aItem->mTitle.get();
  1139   // set node's title
  1140   nsCOMPtr<nsIRDFLiteral> titleLiteral;
  1141   res = mRDFService->GetLiteral(title, getter_AddRefs(titleLiteral));
  1142   if (NS_FAILED(res)) return res;
  1144   if (aPlace < -1) {
  1145     res = Unassert(node, kNC_Name, titleLiteral);
  1146     if (NS_FAILED(res)) return res;
  1147   } else {
  1148     res = Assert(node, kNC_Name, titleLiteral, true);
  1149     if (NS_FAILED(res)) return res;
  1152   if (aType != nullptr) {
  1153     if (aPlace < -1) {
  1154       res = Unassert(node, kRDF_type, aType);
  1155       if (NS_FAILED(res)) return res;
  1156     } else {
  1157       res = Assert(node, kRDF_type, aType, true);
  1158       if (NS_FAILED(res)) return res;
  1162   // Add the element to the container
  1163   if (aPlace < -1) {
  1164     res = aContainer->RemoveElement(node, true);
  1165     if (NS_FAILED(res)) return res;
  1166   } else if (aPlace < 0) {
  1167     res = aContainer->AppendElement(node);
  1168     if (NS_FAILED(res)) return res;
  1169   } else {
  1170     res = aContainer->InsertElementAt(node, aPlace, true);
  1171     if (NS_FAILED(res)) return res;
  1174   return res;
  1177 nsresult nsCharsetMenu::AddMenuItemArrayToContainer(
  1178                         nsIRDFContainer * aContainer,
  1179                         nsTArray<nsMenuEntry*> * aArray,
  1180                         nsIRDFResource * aType) 
  1182   uint32_t count = aArray->Length();
  1183   nsresult res = NS_OK;
  1185   for (uint32_t i = 0; i < count; i++) {
  1186     nsMenuEntry * item = aArray->ElementAt(i);
  1187     if (item == nullptr) return NS_ERROR_UNEXPECTED;
  1189     res = AddMenuItemToContainer(aContainer, item, aType, nullptr, -1);
  1190     if (NS_FAILED(res)) return res;
  1193   return NS_OK;
  1196 nsresult nsCharsetMenu::AddCharsetToContainer(nsTArray<nsMenuEntry*> *aArray,
  1197                                               nsIRDFContainer * aContainer,
  1198                                               const nsAFlatCString& aCharset,
  1199                                               const char * aIDPrefix,
  1200                                               int32_t aPlace,
  1201                                               int32_t aRDFPlace)
  1203   nsresult res = NS_OK;
  1204   nsMenuEntry * item = nullptr; 
  1206   res = AddCharsetToItemArray(aArray, aCharset, &item, aPlace);
  1207   if (NS_FAILED(res)) goto done;
  1209   res = AddMenuItemToContainer(aContainer, item, nullptr, aIDPrefix, 
  1210     aPlace + aRDFPlace);
  1211   if (NS_FAILED(res)) goto done;
  1213   // if we have made another reference to "item", do not delete it 
  1214   if (aArray != nullptr) item = nullptr; 
  1216 done:
  1217   if (item != nullptr) delete item;
  1219   return res;
  1222 nsresult nsCharsetMenu::AddFromPrefsToMenu(
  1223                         nsTArray<nsMenuEntry*> * aArray,
  1224                         nsIRDFContainer * aContainer,
  1225                         const char * aKey,
  1226                         nsTArray<nsCString>& aDecs,
  1227                         const char * aIDPrefix)
  1229   nsresult res = NS_OK;
  1231   nsCOMPtr<nsIPrefLocalizedString> pls;
  1232   res = mPrefs->GetComplexValue(aKey, NS_GET_IID(nsIPrefLocalizedString), getter_AddRefs(pls));
  1233   if (NS_FAILED(res)) return res;
  1235   if (pls) {
  1236     nsXPIDLString ucsval;
  1237     pls->ToString(getter_Copies(ucsval));
  1238     NS_ConvertUTF16toUTF8 utf8val(ucsval);
  1239     if (ucsval)
  1240       res = AddFromStringToMenu(utf8val.BeginWriting(), aArray,
  1241                                 aContainer, aDecs, aIDPrefix);
  1244   return res;
  1247 nsresult
  1248 nsCharsetMenu::AddFromNolocPrefsToMenu(nsTArray<nsMenuEntry*> * aArray,
  1249                                        nsIRDFContainer * aContainer,
  1250                                        const char * aKey,
  1251                                        nsTArray<nsCString>& aDecs,
  1252                                        const char * aIDPrefix)
  1254   nsresult res = NS_OK;
  1256   char * value = nullptr;
  1257   res = mPrefs->GetCharPref(aKey, &value);
  1258   if (NS_FAILED(res)) return res;
  1260   if (value != nullptr) {
  1261     res = AddFromStringToMenu(value, aArray, aContainer, aDecs, aIDPrefix);
  1262     nsMemory::Free(value);
  1265   return res;
  1268 nsresult nsCharsetMenu::AddFromStringToMenu(
  1269                         char * aCharsetList,
  1270                         nsTArray<nsMenuEntry*> * aArray,
  1271                         nsIRDFContainer * aContainer,
  1272                         nsTArray<nsCString>& aDecs,
  1273                         const char * aIDPrefix)
  1275   nsresult res = NS_OK;
  1276   char * p = aCharsetList;
  1277   char * q = p;
  1278   while (*p != 0) {
  1279 	  for (; (*q != ',') && (*q != ' ') && (*q != 0); q++) {;}
  1280     char temp = *q;
  1281     *q = 0;
  1283     // if this charset is not on the accepted list of charsets, ignore it
  1284     int32_t index;
  1285     index = aDecs.IndexOf(nsAutoCString(p), 0, nsIgnoreCaseCStringComparator());
  1286     if (index >= 0) {
  1288       // else, add it to the menu
  1289       res = AddCharsetToContainer(aArray, aContainer, nsDependentCString(p),
  1290                                   aIDPrefix, -1, 0);
  1291       NS_ASSERTION(NS_SUCCEEDED(res), "cannot add charset to menu");
  1292       if (NS_FAILED(res)) break;
  1294       aDecs.RemoveElementAt(index);
  1297     *q = temp;
  1298     for (; (*q == ',') || (*q == ' '); q++) {;}
  1299     p=q;
  1302   return NS_OK;
  1305 nsresult nsCharsetMenu::AddSeparatorToContainer(nsIRDFContainer * aContainer)
  1307   nsAutoCString str;
  1308   str.AssignLiteral("----");
  1310   // hack to generate unique id's for separators
  1311   static int32_t u = 0;
  1312   u++;
  1313   str.AppendInt(u);
  1315   nsMenuEntry item;
  1316   item.mCharset = str;
  1317   item.mTitle.AssignWithConversion(str.get());
  1319   return AddMenuItemToContainer(aContainer, &item, kNC_BookmarkSeparator, 
  1320     nullptr, -1);
  1323 nsresult
  1324 nsCharsetMenu::AddCharsetToCache(const nsAFlatCString& aCharset,
  1325                                  nsTArray<nsMenuEntry*> * aArray,
  1326                                  nsIRDFResource * aRDFResource,
  1327                                  uint32_t aCacheStart,
  1328                                  uint32_t aCacheSize,
  1329                                  int32_t aRDFPlace)
  1331   int32_t i;
  1332   nsresult res = NS_OK;
  1334   i = FindMenuItemInArray(aArray, aCharset, nullptr);
  1335   if (i >= 0) return res;
  1337   nsCOMPtr<nsIRDFContainer> container;
  1338   res = NewRDFContainer(mInner, aRDFResource, getter_AddRefs(container));
  1339   if (NS_FAILED(res)) return res;
  1341   // if too many items, remove last one
  1342   if (aArray->Length() - aCacheStart >= aCacheSize){
  1343     res = RemoveLastMenuItem(container, aArray);
  1344     if (NS_FAILED(res)) return res;
  1347   res = AddCharsetToContainer(aArray, container, aCharset, "charset.", 
  1348                               aCacheStart, aRDFPlace);
  1350   return res;
  1353 nsresult nsCharsetMenu::WriteCacheToPrefs(nsTArray<nsMenuEntry*> * aArray,
  1354                                           int32_t aCacheStart,
  1355                                           const char * aKey)
  1357   nsresult res = NS_OK;
  1359   // create together the cache string
  1360   nsAutoCString cache;
  1361   nsAutoCString sep(NS_LITERAL_CSTRING(", "));
  1362   uint32_t count = aArray->Length();
  1364   for (uint32_t i = aCacheStart; i < count; i++) {
  1365     nsMenuEntry * item = aArray->ElementAt(i);
  1366     if (item != nullptr) {    
  1367       cache.Append(item->mCharset);
  1368       if (i < count - 1) {
  1369         cache.Append(sep);
  1374   // write the pref
  1375   res = mPrefs->SetCharPref(aKey, cache.get());
  1377   return res;
  1380 nsresult nsCharsetMenu::UpdateCachePrefs(const char * aCacheKey,
  1381                                          const char * aCacheSizeKey,
  1382                                          const char * aStaticKey,
  1383                                          const char16_t * aCharset)
  1385   nsresult rv = NS_OK;
  1386   nsXPIDLCString cachePrefValue;
  1387   nsXPIDLCString staticPrefValue;
  1388   NS_LossyConvertUTF16toASCII currentCharset(aCharset);
  1389   int32_t cacheSize = 0;
  1391   mPrefs->GetCharPref(aCacheKey, getter_Copies(cachePrefValue));
  1392   mPrefs->GetCharPref(aStaticKey, getter_Copies(staticPrefValue));
  1393   rv = mPrefs->GetIntPref(aCacheSizeKey, &cacheSize);
  1395   if (NS_FAILED(rv) || cacheSize <= 0)
  1396     return NS_ERROR_UNEXPECTED;
  1398   if ((cachePrefValue.Find(currentCharset) == kNotFound) && 
  1399       (staticPrefValue.Find(currentCharset) == kNotFound)) {
  1401     if (!cachePrefValue.IsEmpty())
  1402       cachePrefValue.Insert(", ", 0);
  1404     cachePrefValue.Insert(currentCharset, 0);
  1405     if (cacheSize < (int32_t) cachePrefValue.CountChar(',') + 1)
  1406       cachePrefValue.Truncate(cachePrefValue.RFindChar(','));
  1408     rv = mPrefs->SetCharPref(aCacheKey, cachePrefValue);
  1411   return rv;
  1414 nsresult nsCharsetMenu::ClearMenu(nsIRDFContainer        * aContainer,
  1415                                   nsTArray<nsMenuEntry*> * aArray)
  1417   nsresult res = NS_OK;
  1419   // clean the RDF data source
  1420   uint32_t count = aArray->Length();
  1421   for (uint32_t i = 0; i < count; i++) {
  1422     nsMenuEntry * item = aArray->ElementAt(i);
  1423     if (item != nullptr) {    
  1424       res = AddMenuItemToContainer(aContainer, item, nullptr, "charset.", -2);
  1425       if (NS_FAILED(res)) return res;
  1429   // clean the internal data structures
  1430   FreeMenuItemArray(aArray);
  1432   return res;
  1435 nsresult nsCharsetMenu::RemoveLastMenuItem(nsIRDFContainer * aContainer,
  1436                                            nsTArray<nsMenuEntry*> * aArray)
  1438   nsresult res = NS_OK;
  1440   int32_t last = aArray->Length() - 1;
  1441   if (last >= 0) {
  1442     nsMenuEntry * item = aArray->ElementAt(last);
  1443     if (item != nullptr) {    
  1444       res = AddMenuItemToContainer(aContainer, item, nullptr, "charset.", -2);
  1445       if (NS_FAILED(res)) return res;
  1447       aArray->RemoveElementAt(last);
  1451   return res;
  1454 nsresult nsCharsetMenu::RemoveFlaggedCharsets(nsTArray<nsCString>& aList, 
  1455                                               const nsString& aProp)
  1457   nsresult res = NS_OK;
  1458   uint32_t count;
  1460   count = aList.Length();
  1461   if (NS_FAILED(res)) return res;
  1463   nsAutoString str;
  1464   for (uint32_t i = 0; i < count; i++) {
  1466     res = mCCManager->GetCharsetData(aList[i].get(), aProp.get(), str);
  1467     if (NS_FAILED(res)) continue;
  1469     aList.RemoveElementAt(i);
  1471     i--; 
  1472     count--;
  1475   return NS_OK;
  1478 nsresult nsCharsetMenu::NewRDFContainer(nsIRDFDataSource * aDataSource, 
  1479                                         nsIRDFResource * aResource, 
  1480                                         nsIRDFContainer ** aResult)
  1482   nsresult res = CallCreateInstance(kRDFContainerCID, aResult);
  1483   if (NS_FAILED(res)) return res;
  1485   res = (*aResult)->Init(aDataSource, aResource);
  1486   if (NS_FAILED(res)) NS_RELEASE(*aResult);
  1488   return res;
  1491 void nsCharsetMenu::FreeMenuItemArray(nsTArray<nsMenuEntry*> * aArray)
  1493   uint32_t count = aArray->Length();
  1494   for (uint32_t i = 0; i < count; i++) {
  1495     nsMenuEntry * item = aArray->ElementAt(i);
  1496     if (item != nullptr) {
  1497       delete item;
  1500   aArray->Clear();
  1503 int32_t nsCharsetMenu::FindMenuItemInArray(const nsTArray<nsMenuEntry*>* aArray,
  1504                                            const nsAFlatCString& aCharset,
  1505                                            nsMenuEntry ** aResult)
  1507   uint32_t count = aArray->Length();
  1509   for (uint32_t i=0; i < count; i++) {
  1510     nsMenuEntry * item = aArray->ElementAt(i);
  1511     if (item->mCharset == aCharset) {
  1512       if (aResult != nullptr) *aResult = item;
  1513       return i;
  1517   if (aResult != nullptr) *aResult = nullptr;
  1518   return -1;
  1521 nsresult nsCharsetMenu::ReorderMenuItemArray(nsTArray<nsMenuEntry*> * aArray)
  1523   nsresult res = NS_OK;
  1524   nsCOMPtr<nsICollation> collation;
  1525   uint32_t count = aArray->Length();
  1526   uint32_t i;
  1528   // we need to use a temporary array
  1529   charsetMenuSortRecord *array = new charsetMenuSortRecord [count];
  1530   NS_ENSURE_TRUE(array, NS_ERROR_OUT_OF_MEMORY);
  1531   for (i = 0; i < count; i++)
  1532     array[i].key = nullptr;
  1534   res = GetCollation(getter_AddRefs(collation));
  1535   if (NS_FAILED(res))
  1536     goto done;
  1538   for (i = 0; i < count && NS_SUCCEEDED(res); i++) {
  1539     array[i].item = aArray->ElementAt(i);
  1541     res = collation->AllocateRawSortKey(nsICollation::kCollationCaseInSensitive, 
  1542                                        (array[i].item)->mTitle, &array[i].key, &array[i].len);
  1545   // reorder the array
  1546   if (NS_SUCCEEDED(res)) {
  1547     NS_QuickSort(array, count, sizeof(*array), CompareMenuItems, collation);
  1549     // move the elements from the temporary array into the the real one
  1550     aArray->Clear();
  1551     for (i = 0; i < count; i++) {
  1552       aArray->AppendElement(array[i].item);
  1556 done:
  1557   for (i = 0; i < count; i++) {
  1558     PR_FREEIF(array[i].key);
  1560   delete [] array;
  1561   return res;
  1564 nsresult nsCharsetMenu::GetCollation(nsICollation ** aCollation)
  1566   nsresult res = NS_OK;
  1567   nsCOMPtr<nsILocale> locale = nullptr;
  1568   nsICollationFactory * collationFactory = nullptr;
  1570   nsCOMPtr<nsILocaleService> localeServ = 
  1571            do_GetService(NS_LOCALESERVICE_CONTRACTID, &res);
  1572   if (NS_FAILED(res)) return res;
  1574   res = localeServ->GetApplicationLocale(getter_AddRefs(locale));
  1575   if (NS_FAILED(res)) return res;
  1577   res = CallCreateInstance(NS_COLLATIONFACTORY_CONTRACTID, &collationFactory);
  1578   if (NS_FAILED(res)) return res;
  1580   res = collationFactory->CreateCollation(locale, aCollation);
  1581   NS_RELEASE(collationFactory);
  1582   return res;
  1585 //----------------------------------------------------------------------------
  1586 // Interface nsICurrentCharsetListener [implementation]
  1588 NS_IMETHODIMP nsCharsetMenu::SetCurrentCharset(const char16_t * aCharset)
  1590   return NS_OK;
  1593 NS_IMETHODIMP nsCharsetMenu::SetCurrentMailCharset(const char16_t * aCharset)
  1595   nsresult res = NS_OK;
  1597   if (mMailviewMenuInitialized) {
  1598     res = AddCharsetToCache(NS_LossyConvertUTF16toASCII(aCharset),
  1599                             &mMailviewMenu, kNC_MailviewCharsetMenuRoot, 
  1600                             mMailviewCacheStart, mMailviewCacheSize,
  1601                             mMailviewMenuRDFPosition);
  1602     if (NS_FAILED(res)) return res;
  1604     res = WriteCacheToPrefs(&mMailviewMenu, mMailviewCacheStart, 
  1605                             kMailviewCachePrefKey);
  1606   } else {
  1607     res = UpdateCachePrefs(kMailviewCachePrefKey, kMailviewCacheSizePrefKey, 
  1608                            kMailviewStaticPrefKey, aCharset);
  1610   return res;
  1613 NS_IMETHODIMP nsCharsetMenu::SetCurrentComposerCharset(const char16_t * aCharset)
  1615   nsresult res = NS_OK;
  1617   if (mComposerMenuInitialized) {
  1619     res = AddCharsetToCache(NS_LossyConvertUTF16toASCII(aCharset),
  1620                             &mComposerMenu, kNC_ComposerCharsetMenuRoot, 
  1621                             mComposerCacheStart, mComposerCacheSize,
  1622                             mComposerMenuRDFPosition);
  1623     if (NS_FAILED(res)) return res;
  1625     res = WriteCacheToPrefs(&mComposerMenu, mComposerCacheStart, 
  1626       kComposerCachePrefKey);
  1627   } else {
  1628     res = UpdateCachePrefs(kComposerCachePrefKey, kComposerCacheSizePrefKey, 
  1629                            kComposerStaticPrefKey, aCharset);
  1631   return res;
  1634 //----------------------------------------------------------------------------
  1635 // Interface nsIRDFDataSource [implementation]
  1637 NS_IMETHODIMP nsCharsetMenu::GetURI(char ** uri)
  1639   if (!uri) return NS_ERROR_NULL_POINTER;
  1641   *uri = NS_strdup("rdf:charset-menu");
  1642   if (!(*uri)) return NS_ERROR_OUT_OF_MEMORY;
  1644   return NS_OK;
  1647 NS_IMETHODIMP nsCharsetMenu::GetSource(nsIRDFResource* property,
  1648                                        nsIRDFNode* target,
  1649                                        bool tv,
  1650                                        nsIRDFResource** source)
  1652   return mInner->GetSource(property, target, tv, source);
  1655 NS_IMETHODIMP nsCharsetMenu::GetSources(nsIRDFResource* property,
  1656                                         nsIRDFNode* target,
  1657                                         bool tv,
  1658                                         nsISimpleEnumerator** sources)
  1660   return mInner->GetSources(property, target, tv, sources);
  1663 NS_IMETHODIMP nsCharsetMenu::GetTarget(nsIRDFResource* source,
  1664                                        nsIRDFResource* property,
  1665                                        bool tv,
  1666                                        nsIRDFNode** target)
  1668   return mInner->GetTarget(source, property, tv, target);
  1671 NS_IMETHODIMP nsCharsetMenu::GetTargets(nsIRDFResource* source,
  1672                                         nsIRDFResource* property,
  1673                                         bool tv,
  1674                                         nsISimpleEnumerator** targets)
  1676   return mInner->GetTargets(source, property, tv, targets);
  1679 NS_IMETHODIMP nsCharsetMenu::Assert(nsIRDFResource* aSource,
  1680                                     nsIRDFResource* aProperty,
  1681                                     nsIRDFNode* aTarget,
  1682                                     bool aTruthValue)
  1684   // TODO: filter out asserts we don't care about
  1685   return mInner->Assert(aSource, aProperty, aTarget, aTruthValue);
  1688 NS_IMETHODIMP nsCharsetMenu::Unassert(nsIRDFResource* aSource,
  1689                                       nsIRDFResource* aProperty,
  1690                                       nsIRDFNode* aTarget)
  1692   // TODO: filter out unasserts we don't care about
  1693   return mInner->Unassert(aSource, aProperty, aTarget);
  1697 NS_IMETHODIMP nsCharsetMenu::Change(nsIRDFResource* aSource,
  1698                                     nsIRDFResource* aProperty,
  1699                                     nsIRDFNode* aOldTarget,
  1700                                     nsIRDFNode* aNewTarget)
  1702   // TODO: filter out changes we don't care about
  1703   return mInner->Change(aSource, aProperty, aOldTarget, aNewTarget);
  1706 NS_IMETHODIMP nsCharsetMenu::Move(nsIRDFResource* aOldSource,
  1707                                   nsIRDFResource* aNewSource,
  1708                                   nsIRDFResource* aProperty,
  1709                                   nsIRDFNode* aTarget)
  1711   // TODO: filter out changes we don't care about
  1712   return mInner->Move(aOldSource, aNewSource, aProperty, aTarget);
  1716 NS_IMETHODIMP nsCharsetMenu::HasAssertion(nsIRDFResource* source, 
  1717                                           nsIRDFResource* property, 
  1718                                           nsIRDFNode* target, bool tv, 
  1719                                           bool* hasAssertion)
  1721   return mInner->HasAssertion(source, property, target, tv, hasAssertion);
  1724 NS_IMETHODIMP nsCharsetMenu::AddObserver(nsIRDFObserver* n)
  1726   return mInner->AddObserver(n);
  1729 NS_IMETHODIMP nsCharsetMenu::RemoveObserver(nsIRDFObserver* n)
  1731   return mInner->RemoveObserver(n);
  1734 NS_IMETHODIMP 
  1735 nsCharsetMenu::HasArcIn(nsIRDFNode *aNode, nsIRDFResource *aArc, bool *result)
  1737   return mInner->HasArcIn(aNode, aArc, result);
  1740 NS_IMETHODIMP 
  1741 nsCharsetMenu::HasArcOut(nsIRDFResource *source, nsIRDFResource *aArc, bool *result)
  1743   return mInner->HasArcOut(source, aArc, result);
  1746 NS_IMETHODIMP nsCharsetMenu::ArcLabelsIn(nsIRDFNode* node, 
  1747                                          nsISimpleEnumerator** labels)
  1749   return mInner->ArcLabelsIn(node, labels);
  1752 NS_IMETHODIMP nsCharsetMenu::ArcLabelsOut(nsIRDFResource* source, 
  1753                                           nsISimpleEnumerator** labels)
  1755   return mInner->ArcLabelsOut(source, labels);
  1758 NS_IMETHODIMP nsCharsetMenu::GetAllResources(nsISimpleEnumerator** aCursor)
  1760   return mInner->GetAllResources(aCursor);
  1763 NS_IMETHODIMP nsCharsetMenu::GetAllCmds(
  1764                              nsIRDFResource* source,
  1765                              nsISimpleEnumerator/*<nsIRDFResource>*/** commands)
  1767   NS_NOTYETIMPLEMENTED("nsCharsetMenu::GetAllCmds");
  1768   return NS_ERROR_NOT_IMPLEMENTED;
  1771 NS_IMETHODIMP nsCharsetMenu::IsCommandEnabled(
  1772                              nsISupportsArray/*<nsIRDFResource>*/* aSources,
  1773                              nsIRDFResource*   aCommand,
  1774                              nsISupportsArray/*<nsIRDFResource>*/* aArguments,
  1775                              bool* aResult)
  1777   NS_NOTYETIMPLEMENTED("nsCharsetMenu::IsCommandEnabled");
  1778   return NS_ERROR_NOT_IMPLEMENTED;
  1781 NS_IMETHODIMP nsCharsetMenu::DoCommand(nsISupportsArray* aSources,
  1782                                        nsIRDFResource*   aCommand,
  1783                                        nsISupportsArray* aArguments)
  1785   NS_NOTYETIMPLEMENTED("nsCharsetMenu::DoCommand");
  1786   return NS_ERROR_NOT_IMPLEMENTED;
  1789 NS_IMETHODIMP nsCharsetMenu::BeginUpdateBatch()
  1791   return mInner->BeginUpdateBatch();
  1794 NS_IMETHODIMP nsCharsetMenu::EndUpdateBatch()
  1796   return mInner->EndUpdateBatch();

mercurial