LCOV - code coverage report
Current view: directory - toolkit/components/intl - nsCharsetMenu.cpp (source / functions) Found Hit Coverage
Test: app.info Lines: 830 3 0.4 %
Date: 2012-06-02 Functions: 92 3 3.3 %

       1                 : /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
       2                 : /* ***** BEGIN LICENSE BLOCK *****
       3                 :  * Version: MPL 1.1/GPL 2.0/LGPL 2.1
       4                 :  *
       5                 :  * The contents of this file are subject to the Mozilla Public License Version
       6                 :  * 1.1 (the "License"); you may not use this file except in compliance with
       7                 :  * the License. You may obtain a copy of the License at
       8                 :  * http://www.mozilla.org/MPL/
       9                 :  *
      10                 :  * Software distributed under the License is distributed on an "AS IS" basis,
      11                 :  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
      12                 :  * for the specific language governing rights and limitations under the
      13                 :  * License.
      14                 :  *
      15                 :  * The Original Code is Mozilla Communicator client code.
      16                 :  *
      17                 :  * The Initial Developer of the Original Code is
      18                 :  * Netscape Communications Corporation.
      19                 :  * Portions created by the Initial Developer are Copyright (C) 1998
      20                 :  * the Initial Developer. All Rights Reserved.
      21                 :  *
      22                 :  * Contributor(s):
      23                 :  *   Pierre Phaneuf <pp@ludusdesign.com>
      24                 :  *
      25                 :  * Alternatively, the contents of this file may be used under the terms of
      26                 :  * either of the GNU General Public License Version 2 or later (the "GPL"),
      27                 :  * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
      28                 :  * in which case the provisions of the GPL or the LGPL are applicable instead
      29                 :  * of those above. If you wish to allow use of your version of this file only
      30                 :  * under the terms of either the GPL or the LGPL, and not to allow others to
      31                 :  * use your version of this file under the terms of the MPL, indicate your
      32                 :  * decision by deleting the provisions above and replace them with the notice
      33                 :  * and other provisions required by the GPL or the LGPL. If you do not delete
      34                 :  * the provisions above, a recipient may use your version of this file under
      35                 :  * the terms of any one of the MPL, the GPL or the LGPL.
      36                 :  *
      37                 :  * ***** END LICENSE BLOCK ***** */
      38                 : 
      39                 : #include "nsIServiceManager.h"
      40                 : #include "nsIComponentManager.h" 
      41                 : #include "rdf.h"
      42                 : #include "nsIRDFDataSource.h"
      43                 : #include "nsIRDFService.h"
      44                 : #include "nsIRDFContainerUtils.h"
      45                 : #include "nsRDFCID.h"
      46                 : #include "nsXPIDLString.h"
      47                 : #include "nsCharsetMenu.h"
      48                 : #include "nsICharsetConverterManager.h"
      49                 : #include "nsICollation.h"
      50                 : #include "nsCollationCID.h"
      51                 : #include "nsLocaleCID.h"
      52                 : #include "nsILocaleService.h"
      53                 : #include "nsIPrefService.h"
      54                 : #include "nsIPrefBranch.h"
      55                 : #include "nsIPrefLocalizedString.h"
      56                 : #include "nsICurrentCharsetListener.h"
      57                 : #include "nsQuickSort.h"
      58                 : #include "nsIObserver.h"
      59                 : #include "nsStringEnumerator.h"
      60                 : #include "nsTArray.h"
      61                 : #include "nsIObserverService.h"
      62                 : #include "nsIRequestObserver.h"
      63                 : #include "nsCRT.h"
      64                 : #include "prmem.h"
      65                 : #include "mozilla/ModuleUtils.h"
      66                 : #include "nsCycleCollectionParticipant.h"
      67                 : 
      68                 : //----------------------------------------------------------------------------
      69                 : // Global functions and data [declaration]
      70                 : 
      71                 : static NS_DEFINE_CID(kRDFServiceCID, NS_RDFSERVICE_CID);
      72                 : static NS_DEFINE_CID(kRDFInMemoryDataSourceCID, NS_RDFINMEMORYDATASOURCE_CID);
      73                 : static NS_DEFINE_CID(kRDFContainerUtilsCID, NS_RDFCONTAINERUTILS_CID);
      74                 : static NS_DEFINE_CID(kRDFContainerCID, NS_RDFCONTAINER_CID);
      75                 : 
      76                 : static const char kURINC_BrowserAutodetMenuRoot[] = "NC:BrowserAutodetMenuRoot";
      77                 : static const char kURINC_BrowserCharsetMenuRoot[] = "NC:BrowserCharsetMenuRoot";
      78                 : static const char kURINC_BrowserMoreCharsetMenuRoot[] = "NC:BrowserMoreCharsetMenuRoot";
      79                 : static const char kURINC_BrowserMore1CharsetMenuRoot[] = "NC:BrowserMore1CharsetMenuRoot";
      80                 : static const char kURINC_BrowserMore2CharsetMenuRoot[] = "NC:BrowserMore2CharsetMenuRoot";
      81                 : static const char kURINC_BrowserMore3CharsetMenuRoot[] = "NC:BrowserMore3CharsetMenuRoot";
      82                 : static const char kURINC_BrowserMore4CharsetMenuRoot[] = "NC:BrowserMore4CharsetMenuRoot";
      83                 : static const char kURINC_BrowserMore5CharsetMenuRoot[] = "NC:BrowserMore5CharsetMenuRoot";
      84                 : static const char kURINC_BrowserUnicodeCharsetMenuRoot[] = "NC:BrowserUnicodeCharsetMenuRoot";
      85                 : static const char kURINC_MaileditCharsetMenuRoot[] = "NC:MaileditCharsetMenuRoot";
      86                 : static const char kURINC_MailviewCharsetMenuRoot[] = "NC:MailviewCharsetMenuRoot";
      87                 : static const char kURINC_ComposerCharsetMenuRoot[] = "NC:ComposerCharsetMenuRoot";
      88                 : static const char kURINC_DecodersRoot[] = "NC:DecodersRoot";
      89                 : static const char kURINC_EncodersRoot[] = "NC:EncodersRoot";
      90                 : DEFINE_RDF_VOCAB(NC_NAMESPACE_URI, NC, Name);
      91                 : DEFINE_RDF_VOCAB(NC_NAMESPACE_URI, NC, BookmarkSeparator);
      92                 : DEFINE_RDF_VOCAB(NC_NAMESPACE_URI, NC, CharsetDetector);
      93                 : DEFINE_RDF_VOCAB(RDF_NAMESPACE_URI, NC, type);
      94                 : 
      95                 : // Note here that browser and mailview have the same static area and cache 
      96                 : // size but the cache itself is separate.
      97                 : 
      98                 : #define kBrowserStaticPrefKey       "intl.charsetmenu.browser.static"
      99                 : #define kBrowserCachePrefKey        "intl.charsetmenu.browser.cache"
     100                 : #define kBrowserCacheSizePrefKey    "intl.charsetmenu.browser.cache.size"
     101                 : 
     102                 : #define kMailviewStaticPrefKey      "intl.charsetmenu.browser.static"
     103                 : #define kMailviewCachePrefKey       "intl.charsetmenu.mailview.cache"
     104                 : #define kMailviewCacheSizePrefKey   "intl.charsetmenu.browser.cache.size"
     105                 : 
     106                 : #define kComposerStaticPrefKey      "intl.charsetmenu.browser.static"
     107                 : #define kComposerCachePrefKey       "intl.charsetmenu.composer.cache"
     108                 : #define kComposerCacheSizePrefKey   "intl.charsetmenu.browser.cache.size"
     109                 : 
     110                 : #define kMaileditPrefKey            "intl.charsetmenu.mailedit"
     111                 : 
     112                 : //----------------------------------------------------------------------------
     113                 : // Class nsMenuEntry [declaration]
     114                 : 
     115                 : /**
     116                 :  * A little class holding all data needed for a menu item.
     117                 :  *
     118                 :  * @created         18/Apr/2000
     119                 :  * @author  Catalin Rotaru [CATA]
     120                 :  */
     121                 : class nsMenuEntry
     122                 : {
     123                 : public: 
     124                 :   // memory & ref counting & leak prevention stuff
     125               0 :   nsMenuEntry() { MOZ_COUNT_CTOR(nsMenuEntry); }
     126               0 :   ~nsMenuEntry() { MOZ_COUNT_DTOR(nsMenuEntry); }
     127                 : 
     128                 :   nsCAutoString mCharset;
     129                 :   nsAutoString      mTitle;
     130                 : };
     131                 : 
     132                 : //----------------------------------------------------------------------------
     133                 : // Class nsCharsetMenu [declaration]
     134                 : 
     135                 : /**
     136                 :  * The Charset Converter menu.
     137                 :  *
     138                 :  * God, our GUI programming disgusts me.
     139                 :  *
     140                 :  * @created         23/Nov/1999
     141                 :  * @author  Catalin Rotaru [CATA]
     142                 :  */
     143                 : class nsCharsetMenu : public nsIRDFDataSource, public nsICurrentCharsetListener
     144                 : {
     145               0 :   NS_DECL_CYCLE_COLLECTING_ISUPPORTS
     146            1464 :   NS_DECL_CYCLE_COLLECTION_CLASS_AMBIGUOUS(nsCharsetMenu, nsIRDFDataSource)
     147                 : 
     148                 : private:
     149                 :   static nsIRDFResource * kNC_BrowserAutodetMenuRoot;
     150                 :   static nsIRDFResource * kNC_BrowserCharsetMenuRoot;
     151                 :   static nsIRDFResource * kNC_BrowserMoreCharsetMenuRoot;
     152                 :   static nsIRDFResource * kNC_BrowserMore1CharsetMenuRoot;
     153                 :   static nsIRDFResource * kNC_BrowserMore2CharsetMenuRoot;
     154                 :   static nsIRDFResource * kNC_BrowserMore3CharsetMenuRoot;
     155                 :   static nsIRDFResource * kNC_BrowserMore4CharsetMenuRoot;
     156                 :   static nsIRDFResource * kNC_BrowserMore5CharsetMenuRoot;
     157                 :   static nsIRDFResource * kNC_BrowserUnicodeCharsetMenuRoot;
     158                 :   static nsIRDFResource * kNC_MaileditCharsetMenuRoot;
     159                 :   static nsIRDFResource * kNC_MailviewCharsetMenuRoot;
     160                 :   static nsIRDFResource * kNC_ComposerCharsetMenuRoot;
     161                 :   static nsIRDFResource * kNC_DecodersRoot;
     162                 :   static nsIRDFResource * kNC_EncodersRoot;
     163                 :   static nsIRDFResource * kNC_Name;
     164                 :   static nsIRDFResource * kNC_CharsetDetector;
     165                 :   static nsIRDFResource * kNC_BookmarkSeparator;
     166                 :   static nsIRDFResource * kRDF_type;
     167                 : 
     168                 :   static nsIRDFDataSource * mInner;
     169                 : 
     170                 :   bool mInitialized;
     171                 :   bool mBrowserMenuInitialized;
     172                 :   bool mMailviewMenuInitialized;
     173                 :   bool mComposerMenuInitialized;
     174                 :   bool mMaileditMenuInitialized;
     175                 :   bool mSecondaryTiersInitialized;
     176                 :   bool mAutoDetectInitialized;
     177                 :   bool mOthersInitialized;
     178                 : 
     179                 :   nsTArray<nsMenuEntry*> mBrowserMenu;
     180                 :   PRInt32                mBrowserCacheStart;
     181                 :   PRInt32                mBrowserCacheSize;
     182                 :   PRInt32                mBrowserMenuRDFPosition;
     183                 : 
     184                 :   nsTArray<nsMenuEntry*> mMailviewMenu;
     185                 :   PRInt32                mMailviewCacheStart;
     186                 :   PRInt32                mMailviewCacheSize;
     187                 :   PRInt32                mMailviewMenuRDFPosition;
     188                 : 
     189                 :   nsTArray<nsMenuEntry*> mComposerMenu;
     190                 :   PRInt32                mComposerCacheStart;
     191                 :   PRInt32                mComposerCacheSize;
     192                 :   PRInt32                mComposerMenuRDFPosition;
     193                 : 
     194                 :   nsCOMPtr<nsIRDFService>               mRDFService;
     195                 :   nsCOMPtr<nsICharsetConverterManager> mCCManager;
     196                 :   nsCOMPtr<nsIPrefBranch>               mPrefs;
     197                 :   nsCOMPtr<nsIObserver>                 mCharsetMenuObserver;
     198                 :   nsTArray<nsCString>                   mDecoderList;
     199                 : 
     200                 :   nsresult Done();
     201                 : 
     202                 :   nsresult FreeResources();
     203                 : 
     204                 :   nsresult InitStaticMenu(nsTArray<nsCString>& aDecs,
     205                 :                           nsIRDFResource * aResource,
     206                 :                           const char * aKey,
     207                 :                           nsTArray<nsMenuEntry*> * aArray);
     208                 :   nsresult InitCacheMenu(nsTArray<nsCString>& aDecs,
     209                 :                          nsIRDFResource * aResource,
     210                 :                          const char * aKey,
     211                 :                          nsTArray<nsMenuEntry*> * aArray);
     212                 :   
     213                 :   nsresult InitMoreMenu(nsTArray<nsCString>& aDecs,
     214                 :                         nsIRDFResource * aResource,
     215                 :                         const char * aFlag);
     216                 :   
     217                 :   nsresult InitMoreSubmenus(nsTArray<nsCString>& aDecs);
     218                 : 
     219                 :   static nsresult SetArrayFromEnumerator(nsIUTF8StringEnumerator* aEnumerator,
     220                 :                                          nsTArray<nsCString>& aArray);
     221                 :   
     222                 :   nsresult AddCharsetToItemArray(nsTArray<nsMenuEntry*>* aArray,
     223                 :                                  const nsAFlatCString& aCharset,
     224                 :                                  nsMenuEntry ** aResult,
     225                 :                                  PRInt32 aPlace);
     226                 :   nsresult AddCharsetArrayToItemArray(nsTArray<nsMenuEntry*> &aArray,
     227                 :                                       const nsTArray<nsCString>& aCharsets);
     228                 :   nsresult AddMenuItemToContainer(nsIRDFContainer * aContainer,
     229                 :     nsMenuEntry * aItem, nsIRDFResource * aType, const char * aIDPrefix,
     230                 :     PRInt32 aPlace);
     231                 :   nsresult AddMenuItemArrayToContainer(nsIRDFContainer * aContainer,
     232                 :     nsTArray<nsMenuEntry*> * aArray, nsIRDFResource * aType);
     233                 :   nsresult AddCharsetToContainer(nsTArray<nsMenuEntry*> * aArray,
     234                 :                                  nsIRDFContainer * aContainer,
     235                 :                                  const nsAFlatCString& aCharset,
     236                 :                                  const char * aIDPrefix,
     237                 :     PRInt32 aPlace, PRInt32 aRDFPlace);
     238                 : 
     239                 :   nsresult AddFromPrefsToMenu(nsTArray<nsMenuEntry*> * aArray,
     240                 :                               nsIRDFContainer * aContainer,
     241                 :                               const char * aKey,
     242                 :                               nsTArray<nsCString>& aDecs,
     243                 :                               const char * aIDPrefix);
     244                 :   nsresult AddFromNolocPrefsToMenu(nsTArray<nsMenuEntry*> * aArray,
     245                 :                                    nsIRDFContainer * aContainer,
     246                 :                                    const char * aKey,
     247                 :                                    nsTArray<nsCString>& aDecs,
     248                 :                                    const char * aIDPrefix);
     249                 :   nsresult AddFromStringToMenu(char * aCharsetList,
     250                 :                                nsTArray<nsMenuEntry*> * aArray,
     251                 :                                nsIRDFContainer * aContainer,
     252                 :                                nsTArray<nsCString>& aDecs,
     253                 :                                const char * aIDPrefix);
     254                 : 
     255                 :   nsresult AddSeparatorToContainer(nsIRDFContainer * aContainer);
     256                 :   nsresult AddCharsetToCache(const nsAFlatCString& aCharset,
     257                 :                              nsTArray<nsMenuEntry*> * aArray,
     258                 :                              nsIRDFResource * aRDFResource,
     259                 :                              PRUint32 aCacheStart, PRUint32 aCacheSize,
     260                 :                              PRInt32 aRDFPlace);
     261                 : 
     262                 :   nsresult WriteCacheToPrefs(nsTArray<nsMenuEntry*> * aArray, PRInt32 aCacheStart,
     263                 :     const char * aKey);
     264                 :   nsresult UpdateCachePrefs(const char * aCacheKey, const char * aCacheSizeKey,
     265                 :     const char * aStaticKey, const PRUnichar * aCharset);
     266                 : 
     267                 :   nsresult ClearMenu(nsIRDFContainer * aContainer, nsTArray<nsMenuEntry*> * aArray);
     268                 :   nsresult RemoveLastMenuItem(nsIRDFContainer * aContainer,
     269                 :                               nsTArray<nsMenuEntry*> * aArray);
     270                 : 
     271                 :   nsresult RemoveFlaggedCharsets(nsTArray<nsCString>& aList, const nsString& aProp);
     272                 :   nsresult NewRDFContainer(nsIRDFDataSource * aDataSource,
     273                 :     nsIRDFResource * aResource, nsIRDFContainer ** aResult);
     274                 :   void FreeMenuItemArray(nsTArray<nsMenuEntry*> * aArray);
     275                 :   PRInt32 FindMenuItemInArray(const nsTArray<nsMenuEntry*>* aArray,
     276                 :                               const nsAFlatCString& aCharset,
     277                 :                               nsMenuEntry ** aResult);
     278                 :   nsresult ReorderMenuItemArray(nsTArray<nsMenuEntry*> * aArray);
     279                 :   nsresult GetCollation(nsICollation ** aCollation);
     280                 : 
     281                 : public:
     282                 :   nsCharsetMenu();
     283                 :   virtual ~nsCharsetMenu();
     284                 : 
     285                 :   nsresult Init();
     286                 :   nsresult InitBrowserMenu();
     287                 :   nsresult InitMaileditMenu();
     288                 :   nsresult InitMailviewMenu();
     289                 :   nsresult InitComposerMenu();
     290                 :   nsresult InitOthers();
     291                 :   nsresult InitSecondaryTiers();
     292                 :   nsresult InitAutodetMenu();
     293                 :   nsresult RefreshBrowserMenu();
     294                 :   nsresult RefreshMailviewMenu();
     295                 :   nsresult RefreshMaileditMenu();
     296                 :   nsresult RefreshComposerMenu();
     297                 : 
     298                 :   //--------------------------------------------------------------------------
     299                 :   // Interface nsICurrentCharsetListener [declaration]
     300                 : 
     301                 :   NS_IMETHOD SetCurrentCharset(const PRUnichar * aCharset);
     302                 :   NS_IMETHOD SetCurrentMailCharset(const PRUnichar * aCharset);
     303                 :   NS_IMETHOD SetCurrentComposerCharset(const PRUnichar * aCharset);
     304                 : 
     305                 :   //--------------------------------------------------------------------------
     306                 :   // Interface nsIRDFDataSource [declaration]
     307                 : 
     308                 :   NS_DECL_NSIRDFDATASOURCE
     309                 : };
     310                 : 
     311                 : //----------------------------------------------------------------------------
     312                 : // Global functions and data [implementation]
     313                 : 
     314                 : nsresult
     315               0 : NS_NewCharsetMenu(nsISupports * aOuter, const nsIID & aIID, 
     316                 :                   void ** aResult)
     317                 : {
     318               0 :   if (!aResult) {
     319               0 :     return NS_ERROR_NULL_POINTER;
     320                 :   }
     321               0 :   if (aOuter) {
     322               0 :     *aResult = nsnull;
     323               0 :     return NS_ERROR_NO_AGGREGATION;
     324                 :   }
     325               0 :   nsCharsetMenu* inst = new nsCharsetMenu();
     326               0 :   if (!inst) {
     327               0 :     *aResult = nsnull;
     328               0 :     return NS_ERROR_OUT_OF_MEMORY;
     329                 :   }
     330               0 :   nsresult res = inst->QueryInterface(aIID, aResult);
     331               0 :   if (NS_FAILED(res)) {
     332               0 :     *aResult = nsnull;
     333               0 :     delete inst;
     334                 :   }
     335               0 :   return res;
     336                 : }
     337                 : 
     338                 : struct charsetMenuSortRecord {
     339                 :   nsMenuEntry* item;
     340                 :   PRUint8*     key;
     341                 :   PRUint32     len;
     342                 : 
     343                 : };
     344                 : 
     345               0 : static int CompareMenuItems(const void* aArg1, const void* aArg2, void *data)
     346                 : {
     347                 :   PRInt32 res; 
     348               0 :   nsICollation * collation = (nsICollation *) data;
     349               0 :   charsetMenuSortRecord *rec1 = (charsetMenuSortRecord *) aArg1;
     350               0 :   charsetMenuSortRecord *rec2 = (charsetMenuSortRecord *) aArg2;
     351                 : 
     352               0 :   collation->CompareRawSortKey(rec1->key, rec1->len, rec2->key, rec2->len, &res);
     353                 : 
     354               0 :   return res;
     355                 : }
     356                 : 
     357                 : nsresult
     358               0 : nsCharsetMenu::SetArrayFromEnumerator(nsIUTF8StringEnumerator* aEnumerator,
     359                 :                                       nsTArray<nsCString>& aArray)
     360                 : {
     361                 :   nsresult rv;
     362                 :   
     363                 :   bool hasMore;
     364               0 :   rv = aEnumerator->HasMore(&hasMore);
     365                 :   
     366               0 :   nsCAutoString value;
     367               0 :   while (NS_SUCCEEDED(rv) && hasMore) {
     368               0 :     rv = aEnumerator->GetNext(value);
     369               0 :     if (NS_SUCCEEDED(rv))
     370               0 :       aArray.AppendElement(value);
     371                 : 
     372               0 :     rv = aEnumerator->HasMore(&hasMore);
     373                 :   }
     374                 : 
     375               0 :   return rv;
     376                 : }
     377                 :   
     378                 : 
     379                 : class nsIgnoreCaseCStringComparator
     380                 : {
     381                 :   public:
     382               0 :     bool Equals(const nsACString& a, const nsACString& b) const
     383                 :     {
     384               0 :       return nsCString(a).Equals(b, nsCaseInsensitiveCStringComparator());
     385                 :     }
     386                 : 
     387                 :     bool LessThan(const nsACString& a, const nsACString& b) const
     388                 :     { 
     389                 :       return a < b;
     390                 :     }
     391                 : };
     392                 : 
     393                 : //----------------------------------------------------------------------------
     394                 : // Class nsCharsetMenuObserver
     395                 : 
     396                 : class nsCharsetMenuObserver : public nsIObserver {
     397                 : 
     398                 : public:
     399                 :   NS_DECL_ISUPPORTS
     400                 :   NS_DECL_NSIOBSERVER
     401                 : 
     402               0 :   nsCharsetMenuObserver(nsCharsetMenu * menu)
     403               0 :     : mCharsetMenu(menu)
     404                 :   {
     405               0 :   }
     406                 : 
     407               0 :   virtual ~nsCharsetMenuObserver() {}
     408                 : 
     409                 : private:
     410                 :   nsCharsetMenu* mCharsetMenu;
     411                 : };
     412                 : 
     413               0 : NS_IMPL_ISUPPORTS1(nsCharsetMenuObserver, nsIObserver)
     414                 : 
     415               0 : NS_IMETHODIMP nsCharsetMenuObserver::Observe(nsISupports *aSubject, const char *aTopic, const PRUnichar *someData)
     416                 : {
     417               0 :   nsresult rv = NS_OK;
     418                 :  
     419                 :   //XUL event handler
     420               0 :   if (!nsCRT::strcmp(aTopic, "charsetmenu-selected")) {
     421               0 :     nsDependentString nodeName(someData);
     422               0 :     rv = mCharsetMenu->Init();
     423               0 :     if (nodeName.EqualsLiteral("browser")) {
     424               0 :       rv = mCharsetMenu->InitBrowserMenu();
     425                 :     }
     426               0 :     if (nodeName.EqualsLiteral("composer")) {
     427               0 :       rv = mCharsetMenu->InitComposerMenu();
     428                 :     }
     429               0 :     if (nodeName.EqualsLiteral("mailview")) {
     430               0 :       rv = mCharsetMenu->InitMailviewMenu();
     431                 :     }
     432               0 :     if (nodeName.EqualsLiteral("mailedit")) {
     433               0 :       rv = mCharsetMenu->InitMaileditMenu();
     434               0 :       rv = mCharsetMenu->InitOthers();
     435                 :     }
     436               0 :     if (nodeName.EqualsLiteral("more-menu")) {
     437               0 :       rv = mCharsetMenu->InitSecondaryTiers();
     438               0 :       rv = mCharsetMenu->InitAutodetMenu();
     439                 :     }
     440               0 :     if (nodeName.EqualsLiteral("other")) {
     441               0 :       rv = mCharsetMenu->InitOthers();
     442               0 :       rv = mCharsetMenu->InitMaileditMenu();
     443                 :     }
     444                 :   }
     445                 :    
     446                 :    //pref event handler
     447               0 :   if (!nsCRT::strcmp(aTopic, NS_PREFBRANCH_PREFCHANGE_TOPIC_ID)) {
     448               0 :     nsDependentString prefName(someData);
     449                 : 
     450               0 :     if (prefName.EqualsLiteral(kBrowserStaticPrefKey)) {
     451                 :       // refresh menus which share this pref
     452               0 :       rv = mCharsetMenu->RefreshBrowserMenu();
     453               0 :       NS_ENSURE_SUCCESS(rv, rv);
     454               0 :       rv = mCharsetMenu->RefreshMailviewMenu();
     455               0 :       NS_ENSURE_SUCCESS(rv, rv);
     456               0 :       rv = mCharsetMenu->RefreshComposerMenu();
     457                 :     }
     458               0 :     else if (prefName.EqualsLiteral(kMaileditPrefKey)) {
     459               0 :       rv = mCharsetMenu->RefreshMaileditMenu();
     460                 :     }
     461                 :   }
     462                 : 
     463               0 :   return rv;
     464                 : }
     465                 : 
     466                 : //----------------------------------------------------------------------------
     467                 : // Class nsCharsetMenu [implementation]
     468                 : 
     469            1464 : NS_IMPL_CYCLE_COLLECTION_CLASS(nsCharsetMenu)
     470               0 : NS_IMPL_CYCLE_COLLECTION_UNLINK_0(nsCharsetMenu)
     471               0 : NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(nsCharsetMenu)
     472               0 :   cb.NoteXPCOMChild(nsCharsetMenu::mInner);
     473               0 : NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
     474                 : 
     475               0 : NS_IMPL_CYCLE_COLLECTING_ADDREF(nsCharsetMenu)
     476               0 : NS_IMPL_CYCLE_COLLECTING_RELEASE(nsCharsetMenu)
     477               0 : NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(nsCharsetMenu)
     478               0 :   NS_INTERFACE_MAP_ENTRY(nsIRDFDataSource)
     479               0 :   NS_INTERFACE_MAP_ENTRY(nsICurrentCharsetListener)
     480               0 :   NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIRDFDataSource)
     481               0 : NS_INTERFACE_MAP_END
     482                 : 
     483                 : nsIRDFDataSource * nsCharsetMenu::mInner = NULL;
     484                 : nsIRDFResource * nsCharsetMenu::kNC_BrowserAutodetMenuRoot = NULL;
     485                 : nsIRDFResource * nsCharsetMenu::kNC_BrowserCharsetMenuRoot = NULL;
     486                 : nsIRDFResource * nsCharsetMenu::kNC_BrowserMoreCharsetMenuRoot = NULL;
     487                 : nsIRDFResource * nsCharsetMenu::kNC_BrowserMore1CharsetMenuRoot = NULL;
     488                 : nsIRDFResource * nsCharsetMenu::kNC_BrowserMore2CharsetMenuRoot = NULL;
     489                 : nsIRDFResource * nsCharsetMenu::kNC_BrowserMore3CharsetMenuRoot = NULL;
     490                 : nsIRDFResource * nsCharsetMenu::kNC_BrowserMore4CharsetMenuRoot = NULL;
     491                 : nsIRDFResource * nsCharsetMenu::kNC_BrowserMore5CharsetMenuRoot = NULL;
     492                 : nsIRDFResource * nsCharsetMenu::kNC_BrowserUnicodeCharsetMenuRoot = NULL;
     493                 : nsIRDFResource * nsCharsetMenu::kNC_MaileditCharsetMenuRoot = NULL;
     494                 : nsIRDFResource * nsCharsetMenu::kNC_MailviewCharsetMenuRoot = NULL;
     495                 : nsIRDFResource * nsCharsetMenu::kNC_ComposerCharsetMenuRoot = NULL;
     496                 : nsIRDFResource * nsCharsetMenu::kNC_DecodersRoot = NULL;
     497                 : nsIRDFResource * nsCharsetMenu::kNC_EncodersRoot = NULL;
     498                 : nsIRDFResource * nsCharsetMenu::kNC_Name = NULL;
     499                 : nsIRDFResource * nsCharsetMenu::kNC_CharsetDetector = NULL;
     500                 : nsIRDFResource * nsCharsetMenu::kNC_BookmarkSeparator = NULL;
     501                 : nsIRDFResource * nsCharsetMenu::kRDF_type = NULL;
     502                 : 
     503               0 : nsCharsetMenu::nsCharsetMenu() 
     504                 : : mInitialized(false), 
     505                 :   mBrowserMenuInitialized(false),
     506                 :   mMailviewMenuInitialized(false),
     507                 :   mComposerMenuInitialized(false),
     508                 :   mMaileditMenuInitialized(false),
     509                 :   mSecondaryTiersInitialized(false),
     510                 :   mAutoDetectInitialized(false),
     511               0 :   mOthersInitialized(false)
     512                 : {
     513               0 :   nsresult res = NS_OK;
     514                 : 
     515                 :   //get charset manager
     516               0 :   mCCManager = do_GetService(NS_CHARSETCONVERTERMANAGER_CONTRACTID, &res);
     517                 : 
     518                 :   //initialize skeleton RDF source
     519               0 :   mRDFService = do_GetService(kRDFServiceCID, &res);
     520                 : 
     521               0 :   if (NS_SUCCEEDED(res))  {
     522               0 :     mRDFService->RegisterDataSource(this, false);
     523                 :   
     524               0 :     CallCreateInstance(kRDFInMemoryDataSourceCID, &mInner);
     525                 : 
     526               0 :     mRDFService->GetResource(NS_LITERAL_CSTRING(kURINC_BrowserCharsetMenuRoot),
     527               0 :                              &kNC_BrowserCharsetMenuRoot);
     528                 :   }
     529                 : 
     530                 :   //get pref service
     531               0 :   nsCOMPtr<nsIPrefService> PrefService = do_GetService(NS_PREFSERVICE_CONTRACTID, &res);
     532               0 :   if (NS_SUCCEEDED(res))
     533               0 :     res = PrefService->GetBranch(nsnull, getter_AddRefs(mPrefs));
     534                 : 
     535                 :   //register event listener
     536               0 :   mCharsetMenuObserver = new nsCharsetMenuObserver(this);
     537                 : 
     538               0 :   if (mCharsetMenuObserver)  {
     539                 :     nsCOMPtr<nsIObserverService> observerService = 
     540               0 :              do_GetService("@mozilla.org/observer-service;1", &res);
     541                 : 
     542               0 :     if (NS_SUCCEEDED(res))
     543               0 :       res = observerService->AddObserver(mCharsetMenuObserver, 
     544                 :                                          "charsetmenu-selected", 
     545               0 :                                          false);
     546                 :   }
     547                 : 
     548               0 :   NS_ASSERTION(NS_SUCCEEDED(res), "Failed to initialize nsCharsetMenu");
     549               0 : }
     550                 : 
     551               0 : nsCharsetMenu::~nsCharsetMenu() 
     552                 : {
     553               0 :   Done();
     554                 : 
     555               0 :   FreeMenuItemArray(&mBrowserMenu);
     556               0 :   FreeMenuItemArray(&mMailviewMenu);
     557               0 :   FreeMenuItemArray(&mComposerMenu);
     558                 : 
     559               0 :   FreeResources();
     560               0 : }
     561                 : 
     562                 : // XXX collapse these 2 in one
     563                 : 
     564               0 : nsresult nsCharsetMenu::RefreshBrowserMenu()
     565                 : {
     566               0 :   nsresult res = NS_OK;
     567                 : 
     568               0 :   nsCOMPtr<nsIRDFContainer> container;
     569               0 :   res = NewRDFContainer(mInner, kNC_BrowserCharsetMenuRoot, getter_AddRefs(container));
     570               0 :   if (NS_FAILED(res)) return res;
     571                 : 
     572                 :   // clean the menu
     573               0 :   res = ClearMenu(container, &mBrowserMenu);
     574               0 :   if (NS_FAILED(res)) return res;
     575                 : 
     576                 :   // rebuild the menu
     577               0 :   nsCOMPtr<nsIUTF8StringEnumerator> decoders;
     578               0 :   res = mCCManager->GetDecoderList(getter_AddRefs(decoders));
     579               0 :   if (NS_FAILED(res)) return res;
     580                 : 
     581               0 :   nsTArray<nsCString> decs;
     582               0 :   SetArrayFromEnumerator(decoders, decs);
     583                 :   
     584                 :   res = AddFromPrefsToMenu(&mBrowserMenu, container, kBrowserStaticPrefKey, 
     585               0 :                            decs, "charset.");
     586               0 :   NS_ASSERTION(NS_SUCCEEDED(res), "error initializing static charset menu from prefs");
     587                 : 
     588                 :   // mark the end of the static area, the rest is cache
     589               0 :   mBrowserCacheStart = mBrowserMenu.Length();
     590                 : 
     591                 :   // Remove "notForBrowser" entries before populating cache menu
     592               0 :   res = RemoveFlaggedCharsets(decs, NS_LITERAL_STRING(".notForBrowser"));
     593               0 :   NS_ASSERTION(NS_SUCCEEDED(res), "error removing flagged charsets");
     594                 : 
     595                 :   res = InitCacheMenu(decs, kNC_BrowserCharsetMenuRoot, kBrowserCachePrefKey, 
     596               0 :                       &mBrowserMenu);
     597               0 :   NS_ASSERTION(NS_SUCCEEDED(res), "error initializing browser cache charset menu");
     598                 : 
     599               0 :   return res;
     600                 : }
     601                 : 
     602               0 : nsresult nsCharsetMenu::RefreshMailviewMenu()
     603                 : {
     604               0 :   nsresult res = NS_OK;
     605                 : 
     606               0 :   nsCOMPtr<nsIRDFContainer> container;
     607               0 :   res = NewRDFContainer(mInner, kNC_MailviewCharsetMenuRoot, getter_AddRefs(container));
     608               0 :   if (NS_FAILED(res)) return res;
     609                 : 
     610                 :   // clean the menu
     611               0 :   res = ClearMenu(container, &mMailviewMenu);
     612               0 :   if (NS_FAILED(res)) return res;
     613                 : 
     614               0 :   nsCOMPtr<nsIUTF8StringEnumerator> decoders;
     615               0 :   res = mCCManager->GetDecoderList(getter_AddRefs(decoders));
     616               0 :   if (NS_FAILED(res)) return res;
     617                 : 
     618               0 :   nsTArray<nsCString> decs;
     619               0 :   SetArrayFromEnumerator(decoders, decs);
     620                 :   
     621                 :   res = AddFromPrefsToMenu(&mMailviewMenu, container, kMailviewStaticPrefKey, 
     622               0 :                            decs, "charset.");
     623               0 :   NS_ASSERTION(NS_SUCCEEDED(res), "error initializing static charset menu from prefs");
     624                 : 
     625                 :   // mark the end of the static area, the rest is cache
     626               0 :   mMailviewCacheStart = mMailviewMenu.Length();
     627                 : 
     628                 :   res = InitCacheMenu(decs, kNC_MailviewCharsetMenuRoot, 
     629               0 :     kMailviewCachePrefKey, &mMailviewMenu);
     630               0 :   NS_ASSERTION(NS_SUCCEEDED(res), "error initializing mailview cache charset menu");
     631                 : 
     632               0 :   return res;
     633                 : }
     634                 : 
     635               0 : nsresult nsCharsetMenu::RefreshMaileditMenu()
     636                 : {
     637                 :   nsresult res;
     638                 : 
     639               0 :   nsCOMPtr<nsIRDFContainer> container;
     640               0 :   res = NewRDFContainer(mInner, kNC_MaileditCharsetMenuRoot, getter_AddRefs(container));
     641               0 :   NS_ENSURE_SUCCESS(res, res);
     642                 : 
     643               0 :   nsCOMPtr<nsISimpleEnumerator> enumerator;
     644               0 :   res = container->GetElements(getter_AddRefs(enumerator));
     645               0 :   NS_ENSURE_SUCCESS(res, res);
     646                 : 
     647                 :   // clear the menu
     648               0 :   nsCOMPtr<nsIRDFNode> node;
     649               0 :   while (NS_SUCCEEDED(enumerator->GetNext(getter_AddRefs(node)))) {
     650                 : 
     651               0 :     res = mInner->Unassert(kNC_MaileditCharsetMenuRoot, kNC_Name, node);
     652               0 :     NS_ENSURE_SUCCESS(res, res);
     653                 : 
     654               0 :     res = container->RemoveElement(node, false);
     655               0 :     NS_ENSURE_SUCCESS(res, res);
     656                 :   }
     657                 : 
     658                 :   // get a list of available encoders
     659               0 :   nsCOMPtr<nsIUTF8StringEnumerator> encoders;
     660               0 :   res = mCCManager->GetEncoderList(getter_AddRefs(encoders));
     661               0 :   NS_ENSURE_SUCCESS(res, res);
     662                 : 
     663               0 :   nsTArray<nsCString> encs;
     664               0 :   SetArrayFromEnumerator(encoders, encs);
     665                 :   
     666                 :   // add menu items from pref
     667               0 :   res = AddFromPrefsToMenu(NULL, container, kMaileditPrefKey, encs, NULL);
     668               0 :   NS_ASSERTION(NS_SUCCEEDED(res), "error initializing mailedit charset menu from prefs");
     669                 : 
     670               0 :   return res;
     671                 : }
     672                 : 
     673               0 : nsresult nsCharsetMenu::RefreshComposerMenu()
     674                 : {
     675               0 :   nsresult res = NS_OK;
     676                 : 
     677               0 :   nsCOMPtr<nsIRDFContainer> container;
     678               0 :   res = NewRDFContainer(mInner, kNC_ComposerCharsetMenuRoot, getter_AddRefs(container));
     679               0 :   if (NS_FAILED(res)) return res;
     680                 : 
     681                 :   // clean the menu
     682               0 :   res = ClearMenu(container, &mComposerMenu);
     683               0 :   if (NS_FAILED(res)) return res;
     684                 : 
     685               0 :   nsCOMPtr<nsIUTF8StringEnumerator> decoders;
     686               0 :   res = mCCManager->GetDecoderList(getter_AddRefs(decoders));
     687               0 :   if (NS_FAILED(res)) return res;
     688                 : 
     689               0 :   nsTArray<nsCString> decs;
     690               0 :   SetArrayFromEnumerator(decoders, decs);
     691                 :   
     692                 :   res = AddFromPrefsToMenu(&mComposerMenu, container, kComposerStaticPrefKey, 
     693               0 :                            decs, "charset.");
     694               0 :   NS_ASSERTION(NS_SUCCEEDED(res), "error initializing static charset menu from prefs");
     695                 : 
     696                 :   // mark the end of the static area, the rest is cache
     697               0 :   mComposerCacheStart = mComposerMenu.Length();
     698                 : 
     699                 :   res = InitCacheMenu(decs, kNC_ComposerCharsetMenuRoot, 
     700               0 :     kComposerCachePrefKey, &mComposerMenu);
     701               0 :   NS_ASSERTION(NS_SUCCEEDED(res), "error initializing composer cache charset menu");
     702                 : 
     703               0 :   return res;
     704                 : }
     705                 : 
     706               0 : nsresult nsCharsetMenu::Init() 
     707                 : {
     708               0 :   nsresult res = NS_OK;
     709                 : 
     710               0 :   if (!mInitialized)  {
     711                 : 
     712                 :     //enumerate decoders
     713               0 :     nsCOMPtr<nsIUTF8StringEnumerator> decoders;
     714               0 :     res = mCCManager->GetDecoderList(getter_AddRefs(decoders));
     715               0 :     if (NS_FAILED(res)) return res;
     716                 : 
     717               0 :     SetArrayFromEnumerator(decoders, mDecoderList);
     718                 : 
     719                 :     //initialize all remaining RDF template nodes
     720               0 :     mRDFService->GetResource(NS_LITERAL_CSTRING(kURINC_BrowserAutodetMenuRoot),
     721               0 :                              &kNC_BrowserAutodetMenuRoot);
     722               0 :     mRDFService->GetResource(NS_LITERAL_CSTRING(kURINC_BrowserMoreCharsetMenuRoot),
     723               0 :                              &kNC_BrowserMoreCharsetMenuRoot);
     724               0 :     mRDFService->GetResource(NS_LITERAL_CSTRING(kURINC_BrowserMore1CharsetMenuRoot),
     725               0 :                              &kNC_BrowserMore1CharsetMenuRoot);
     726               0 :     mRDFService->GetResource(NS_LITERAL_CSTRING(kURINC_BrowserMore2CharsetMenuRoot),
     727               0 :                              &kNC_BrowserMore2CharsetMenuRoot);
     728               0 :     mRDFService->GetResource(NS_LITERAL_CSTRING(kURINC_BrowserMore3CharsetMenuRoot),
     729               0 :                              &kNC_BrowserMore3CharsetMenuRoot);
     730               0 :     mRDFService->GetResource(NS_LITERAL_CSTRING(kURINC_BrowserMore4CharsetMenuRoot),
     731               0 :                              &kNC_BrowserMore4CharsetMenuRoot);
     732               0 :     mRDFService->GetResource(NS_LITERAL_CSTRING(kURINC_BrowserMore5CharsetMenuRoot),
     733               0 :                              &kNC_BrowserMore5CharsetMenuRoot);
     734               0 :     mRDFService->GetResource(NS_LITERAL_CSTRING(kURINC_BrowserUnicodeCharsetMenuRoot),
     735               0 :                              &kNC_BrowserUnicodeCharsetMenuRoot);
     736               0 :     mRDFService->GetResource(NS_LITERAL_CSTRING(kURINC_MaileditCharsetMenuRoot),
     737               0 :                              &kNC_MaileditCharsetMenuRoot);
     738               0 :     mRDFService->GetResource(NS_LITERAL_CSTRING(kURINC_MailviewCharsetMenuRoot),
     739               0 :                              &kNC_MailviewCharsetMenuRoot);
     740               0 :     mRDFService->GetResource(NS_LITERAL_CSTRING(kURINC_ComposerCharsetMenuRoot),
     741               0 :                              &kNC_ComposerCharsetMenuRoot);
     742               0 :     mRDFService->GetResource(NS_LITERAL_CSTRING(kURINC_DecodersRoot),
     743               0 :                              &kNC_DecodersRoot);
     744               0 :     mRDFService->GetResource(NS_LITERAL_CSTRING(kURINC_EncodersRoot),
     745               0 :                              &kNC_EncodersRoot);
     746               0 :     mRDFService->GetResource(NS_LITERAL_CSTRING(kURINC_Name),
     747               0 :                              &kNC_Name);
     748               0 :     mRDFService->GetResource(NS_LITERAL_CSTRING(kURINC_CharsetDetector),
     749               0 :                              &kNC_CharsetDetector);
     750               0 :     mRDFService->GetResource(NS_LITERAL_CSTRING(kURINC_BookmarkSeparator),
     751               0 :                              &kNC_BookmarkSeparator);
     752               0 :     mRDFService->GetResource(NS_LITERAL_CSTRING(kURINC_type), &kRDF_type);
     753                 : 
     754               0 :     nsIRDFContainerUtils * rdfUtil = NULL;
     755               0 :     res = CallGetService(kRDFContainerUtilsCID, &rdfUtil);
     756               0 :     if (NS_FAILED(res)) goto done;
     757                 : 
     758               0 :     res = rdfUtil->MakeSeq(mInner, kNC_BrowserAutodetMenuRoot, NULL);
     759               0 :     if (NS_FAILED(res)) goto done;
     760               0 :     res = rdfUtil->MakeSeq(mInner, kNC_BrowserCharsetMenuRoot, NULL);
     761               0 :     if (NS_FAILED(res)) goto done;
     762               0 :     res = rdfUtil->MakeSeq(mInner, kNC_BrowserMoreCharsetMenuRoot, NULL);
     763               0 :     if (NS_FAILED(res)) goto done;
     764               0 :     res = rdfUtil->MakeSeq(mInner, kNC_BrowserMore1CharsetMenuRoot, NULL);
     765               0 :     if (NS_FAILED(res)) goto done;
     766               0 :     res = rdfUtil->MakeSeq(mInner, kNC_BrowserMore2CharsetMenuRoot, NULL);
     767               0 :     if (NS_FAILED(res)) goto done;
     768               0 :     res = rdfUtil->MakeSeq(mInner, kNC_BrowserMore3CharsetMenuRoot, NULL);
     769               0 :     if (NS_FAILED(res)) goto done;
     770               0 :     res = rdfUtil->MakeSeq(mInner, kNC_BrowserMore4CharsetMenuRoot, NULL);
     771               0 :     if (NS_FAILED(res)) goto done;
     772               0 :     res = rdfUtil->MakeSeq(mInner, kNC_BrowserMore5CharsetMenuRoot, NULL);
     773               0 :     if (NS_FAILED(res)) goto done;
     774               0 :     res = rdfUtil->MakeSeq(mInner, kNC_BrowserUnicodeCharsetMenuRoot, NULL);
     775               0 :     if (NS_FAILED(res)) goto done;
     776               0 :     res = rdfUtil->MakeSeq(mInner, kNC_MaileditCharsetMenuRoot, NULL);
     777               0 :     if (NS_FAILED(res)) goto done;
     778               0 :     res = rdfUtil->MakeSeq(mInner, kNC_MailviewCharsetMenuRoot, NULL);
     779               0 :     if (NS_FAILED(res)) goto done;
     780               0 :     res = rdfUtil->MakeSeq(mInner, kNC_ComposerCharsetMenuRoot, NULL);
     781               0 :     if (NS_FAILED(res)) goto done;
     782               0 :     res = rdfUtil->MakeSeq(mInner, kNC_DecodersRoot, NULL);
     783               0 :     if (NS_FAILED(res)) goto done;
     784               0 :     res = rdfUtil->MakeSeq(mInner, kNC_EncodersRoot, NULL);
     785               0 :     if (NS_FAILED(res)) goto done;
     786                 : 
     787                 :   done:
     788               0 :     NS_IF_RELEASE(rdfUtil);
     789               0 :     if (NS_FAILED(res)) return res;
     790                 :   }
     791               0 :   mInitialized = NS_SUCCEEDED(res);
     792               0 :   return res;
     793                 : }
     794                 : 
     795               0 : nsresult nsCharsetMenu::Done() 
     796                 : {
     797               0 :   nsresult res = NS_OK;
     798               0 :   res = mRDFService->UnregisterDataSource(this);
     799                 : 
     800               0 :   NS_IF_RELEASE(kNC_BrowserAutodetMenuRoot);
     801               0 :   NS_IF_RELEASE(kNC_BrowserCharsetMenuRoot);
     802               0 :   NS_IF_RELEASE(kNC_BrowserMoreCharsetMenuRoot);
     803               0 :   NS_IF_RELEASE(kNC_BrowserMore1CharsetMenuRoot);
     804               0 :   NS_IF_RELEASE(kNC_BrowserMore2CharsetMenuRoot);
     805               0 :   NS_IF_RELEASE(kNC_BrowserMore3CharsetMenuRoot);
     806               0 :   NS_IF_RELEASE(kNC_BrowserMore4CharsetMenuRoot);
     807               0 :   NS_IF_RELEASE(kNC_BrowserMore5CharsetMenuRoot);
     808               0 :   NS_IF_RELEASE(kNC_BrowserUnicodeCharsetMenuRoot);
     809               0 :   NS_IF_RELEASE(kNC_MaileditCharsetMenuRoot);
     810               0 :   NS_IF_RELEASE(kNC_MailviewCharsetMenuRoot);
     811               0 :   NS_IF_RELEASE(kNC_ComposerCharsetMenuRoot);
     812               0 :   NS_IF_RELEASE(kNC_DecodersRoot);
     813               0 :   NS_IF_RELEASE(kNC_EncodersRoot);
     814               0 :   NS_IF_RELEASE(kNC_Name);
     815               0 :   NS_IF_RELEASE(kNC_CharsetDetector);
     816               0 :   NS_IF_RELEASE(kNC_BookmarkSeparator);
     817               0 :   NS_IF_RELEASE(kRDF_type);
     818               0 :   NS_IF_RELEASE(mInner);
     819                 : 
     820               0 :   return res;
     821                 : }
     822                 : 
     823                 : /**
     824                 :  * Free the resources no longer needed by the component.
     825                 :  */
     826               0 : nsresult nsCharsetMenu::FreeResources()
     827                 : {
     828               0 :   nsresult res = NS_OK;
     829                 : 
     830               0 :   if (mCharsetMenuObserver) {
     831               0 :     mPrefs->RemoveObserver(kBrowserStaticPrefKey, mCharsetMenuObserver);
     832               0 :     mPrefs->RemoveObserver(kMaileditPrefKey, mCharsetMenuObserver);
     833                 :     /* nsIObserverService has to have released nsCharsetMenu already */
     834                 :   }
     835                 : 
     836               0 :   mRDFService = NULL;
     837               0 :   mCCManager  = NULL;
     838               0 :   mPrefs      = NULL;
     839                 : 
     840               0 :   return res;
     841                 : }
     842                 : 
     843               0 : nsresult nsCharsetMenu::InitBrowserMenu() 
     844                 : {
     845               0 :   nsresult res = NS_OK;
     846                 : 
     847               0 :   if (!mBrowserMenuInitialized)  {
     848               0 :     nsCOMPtr<nsIRDFContainer> container;
     849               0 :     res = NewRDFContainer(mInner, kNC_BrowserCharsetMenuRoot, getter_AddRefs(container));
     850               0 :     if (NS_FAILED(res)) return res;
     851                 : 
     852                 : 
     853                 :     // how to clone mDecoderList??
     854               0 :     nsTArray<nsCString> browserDecoderList = mDecoderList;
     855                 : 
     856                 :     res = InitStaticMenu(browserDecoderList, kNC_BrowserCharsetMenuRoot, 
     857               0 :                          kBrowserStaticPrefKey, &mBrowserMenu);
     858               0 :     NS_ASSERTION(NS_SUCCEEDED(res), "error initializing browser static charset menu");
     859                 : 
     860                 :     // mark the end of the static area, the rest is cache
     861               0 :     mBrowserCacheStart = mBrowserMenu.Length();
     862               0 :     mPrefs->GetIntPref(kBrowserCacheSizePrefKey, &mBrowserCacheSize);
     863                 : 
     864                 :     // compute the position of the menu in the RDF container
     865               0 :     res = container->GetCount(&mBrowserMenuRDFPosition);
     866               0 :     if (NS_FAILED(res)) return res;
     867                 :     // this "1" here is a correction necessary because the RDF container 
     868                 :     // elements are numbered from 1 (why god, WHY?!?!?!)
     869               0 :     mBrowserMenuRDFPosition -= mBrowserCacheStart - 1;
     870                 : 
     871                 :     // Remove "notForBrowser" entries before populating cache menu
     872               0 :     res = RemoveFlaggedCharsets(browserDecoderList, NS_LITERAL_STRING(".notForBrowser"));
     873               0 :     NS_ASSERTION(NS_SUCCEEDED(res), "error initializing static charset menu from prefs");
     874                 : 
     875                 :     res = InitCacheMenu(browserDecoderList, kNC_BrowserCharsetMenuRoot, kBrowserCachePrefKey, 
     876               0 :       &mBrowserMenu);
     877               0 :     NS_ASSERTION(NS_SUCCEEDED(res), "error initializing browser cache charset menu");
     878                 : 
     879                 :     // register prefs callback
     880               0 :     mPrefs->AddObserver(kBrowserStaticPrefKey, mCharsetMenuObserver, false);
     881                 :   }
     882                 : 
     883               0 :   mBrowserMenuInitialized = NS_SUCCEEDED(res);
     884                 : 
     885               0 :   return res;
     886                 : }
     887                 : 
     888               0 : nsresult nsCharsetMenu::InitMaileditMenu() 
     889                 : {
     890               0 :   nsresult res = NS_OK;
     891                 : 
     892               0 :   if (!mMaileditMenuInitialized)  {
     893               0 :     nsCOMPtr<nsIRDFContainer> container;
     894               0 :     res = NewRDFContainer(mInner, kNC_MaileditCharsetMenuRoot, getter_AddRefs(container));
     895               0 :     if (NS_FAILED(res)) return res;
     896                 : 
     897                 :     //enumerate encoders
     898                 :     // this would bring in a whole bunch of 'font encoders' as well as genuine 
     899                 :     // charset encoders, but it's safe because we rely on prefs to filter
     900                 :     // them out. Moreover, 'customize' menu lists only genuine charset 
     901                 :     // encoders further guarding  against  'font encoders' sneaking in. 
     902               0 :     nsCOMPtr<nsIUTF8StringEnumerator> encoders;
     903               0 :     res = mCCManager->GetEncoderList(getter_AddRefs(encoders));
     904               0 :     if (NS_FAILED(res))  return res;
     905                 : 
     906               0 :     nsTArray<nsCString> maileditEncoderList;
     907               0 :     SetArrayFromEnumerator(encoders, maileditEncoderList);
     908                 :   
     909               0 :     res = AddFromPrefsToMenu(NULL, container, kMaileditPrefKey, maileditEncoderList, NULL);
     910               0 :     NS_ASSERTION(NS_SUCCEEDED(res), "error initializing mailedit charset menu from prefs");
     911                 : 
     912                 :     // register prefs callback
     913               0 :     mPrefs->AddObserver(kMaileditPrefKey, mCharsetMenuObserver, false);
     914                 :   }
     915                 : 
     916               0 :   mMaileditMenuInitialized = NS_SUCCEEDED(res);
     917                 : 
     918               0 :   return res;
     919                 : }
     920                 : 
     921               0 : nsresult nsCharsetMenu::InitMailviewMenu() 
     922                 : {
     923               0 :   nsresult res = NS_OK;
     924                 : 
     925               0 :   if (!mMailviewMenuInitialized)  {
     926               0 :     nsCOMPtr<nsIRDFContainer> container;
     927               0 :     res = NewRDFContainer(mInner, kNC_MailviewCharsetMenuRoot, getter_AddRefs(container));
     928               0 :     if (NS_FAILED(res)) return res;
     929                 : 
     930               0 :     nsTArray<nsCString> mailviewDecoderList = mDecoderList;
     931                 : 
     932                 :     res = InitStaticMenu(mailviewDecoderList, kNC_MailviewCharsetMenuRoot, 
     933               0 :                          kMailviewStaticPrefKey, &mMailviewMenu);
     934               0 :     NS_ASSERTION(NS_SUCCEEDED(res), "error initializing mailview static charset menu");
     935                 : 
     936                 :     // mark the end of the static area, the rest is cache
     937               0 :     mMailviewCacheStart = mMailviewMenu.Length();
     938               0 :     mPrefs->GetIntPref(kMailviewCacheSizePrefKey, &mMailviewCacheSize);
     939                 : 
     940                 :     // compute the position of the menu in the RDF container
     941               0 :     res = container->GetCount(&mMailviewMenuRDFPosition);
     942               0 :     if (NS_FAILED(res)) return res;
     943                 :     // this "1" here is a correction necessary because the RDF container 
     944                 :     // elements are numbered from 1 (why god, WHY?!?!?!)
     945               0 :     mMailviewMenuRDFPosition -= mMailviewCacheStart - 1;
     946                 : 
     947                 :     res = InitCacheMenu(mailviewDecoderList, kNC_MailviewCharsetMenuRoot, 
     948               0 :       kMailviewCachePrefKey, &mMailviewMenu);
     949               0 :     NS_ASSERTION(NS_SUCCEEDED(res), "error initializing mailview cache charset menu");
     950                 :   }
     951                 : 
     952               0 :   mMailviewMenuInitialized = NS_SUCCEEDED(res);
     953                 : 
     954               0 :   return res;
     955                 : }
     956                 : 
     957               0 : nsresult nsCharsetMenu::InitComposerMenu() 
     958                 : {
     959               0 :   nsresult res = NS_OK;
     960                 : 
     961               0 :   if (!mComposerMenuInitialized)  {
     962               0 :     nsCOMPtr<nsIRDFContainer> container;
     963               0 :     res = NewRDFContainer(mInner, kNC_ComposerCharsetMenuRoot, getter_AddRefs(container));
     964               0 :     if (NS_FAILED(res)) return res;
     965                 : 
     966               0 :     nsTArray<nsCString> composerDecoderList = mDecoderList;
     967                 : 
     968                 :     // even if we fail, the show must go on
     969                 :     res = InitStaticMenu(composerDecoderList, kNC_ComposerCharsetMenuRoot, 
     970               0 :       kComposerStaticPrefKey, &mComposerMenu);
     971               0 :     NS_ASSERTION(NS_SUCCEEDED(res), "error initializing composer static charset menu");
     972                 : 
     973                 :     // mark the end of the static area, the rest is cache
     974               0 :     mComposerCacheStart = mComposerMenu.Length();
     975               0 :     mPrefs->GetIntPref(kComposerCacheSizePrefKey, &mComposerCacheSize);
     976                 : 
     977                 :     // compute the position of the menu in the RDF container
     978               0 :     res = container->GetCount(&mComposerMenuRDFPosition);
     979               0 :     if (NS_FAILED(res)) return res;
     980                 :     // this "1" here is a correction necessary because the RDF container 
     981                 :     // elements are numbered from 1 (why god, WHY?!?!?!)
     982               0 :     mComposerMenuRDFPosition -= mComposerCacheStart - 1;
     983                 : 
     984                 :     res = InitCacheMenu(composerDecoderList, kNC_ComposerCharsetMenuRoot, 
     985               0 :       kComposerCachePrefKey, &mComposerMenu);
     986               0 :     NS_ASSERTION(NS_SUCCEEDED(res), "error initializing composer cache charset menu");
     987                 :   }
     988                 : 
     989               0 :   mComposerMenuInitialized = NS_SUCCEEDED(res);
     990                 : 
     991               0 :   return res;
     992                 : }
     993                 : 
     994               0 : nsresult nsCharsetMenu::InitOthers() 
     995                 : {
     996               0 :   nsresult res = NS_OK;
     997                 : 
     998               0 :   if (!mOthersInitialized) {
     999               0 :     nsTArray<nsCString> othersDecoderList = mDecoderList;
    1000                 : 
    1001               0 :     res = InitMoreMenu(othersDecoderList, kNC_DecodersRoot, ".notForBrowser");                 
    1002               0 :     if (NS_FAILED(res))  return res;
    1003                 : 
    1004                 :     // Using mDecoderList instead of GetEncoderList(), we can avoid having to
    1005                 :     // tag a whole bunch of 'font encoders' with '.notForOutgoing' in 
    1006                 :     // charsetData.properties file. 
    1007               0 :     nsTArray<nsCString> othersEncoderList = mDecoderList;
    1008                 : 
    1009               0 :     res = InitMoreMenu(othersEncoderList, kNC_EncodersRoot, ".notForOutgoing");                 
    1010               0 :     if (NS_FAILED(res)) return res;
    1011                 :   }
    1012                 : 
    1013               0 :   mOthersInitialized = NS_SUCCEEDED(res);
    1014                 : 
    1015               0 :   return res;
    1016                 : }
    1017                 : 
    1018                 : /**
    1019                 :  * Inits the secondary tiers of the charset menu. Because currently all the CS 
    1020                 :  * menus are sharing the secondary tiers, one should call this method only 
    1021                 :  * once for all of them.
    1022                 :  */
    1023               0 : nsresult nsCharsetMenu::InitSecondaryTiers()
    1024                 : {
    1025               0 :   nsresult res = NS_OK;
    1026                 : 
    1027               0 :   if (!mSecondaryTiersInitialized)  {
    1028               0 :     nsTArray<nsCString> secondaryTiersDecoderList = mDecoderList;
    1029                 : 
    1030               0 :     res = InitMoreSubmenus(secondaryTiersDecoderList);
    1031               0 :     NS_ASSERTION(NS_SUCCEEDED(res), "err init browser charset more submenus");
    1032                 : 
    1033               0 :     res = InitMoreMenu(secondaryTiersDecoderList, kNC_BrowserMoreCharsetMenuRoot, ".notForBrowser");
    1034               0 :     NS_ASSERTION(NS_SUCCEEDED(res), "err init browser charset more menu");
    1035                 :   }
    1036                 : 
    1037               0 :   mSecondaryTiersInitialized = NS_SUCCEEDED(res);
    1038                 : 
    1039               0 :   return res;
    1040                 : }
    1041                 : 
    1042               0 : nsresult nsCharsetMenu::InitStaticMenu(nsTArray<nsCString>& aDecs,
    1043                 :                                        nsIRDFResource * aResource,
    1044                 :                                        const char * aKey,
    1045                 :                                        nsTArray<nsMenuEntry*> * aArray)
    1046                 : {
    1047               0 :   nsresult res = NS_OK;
    1048               0 :   nsCOMPtr<nsIRDFContainer> container;
    1049                 : 
    1050               0 :   res = NewRDFContainer(mInner, aResource, getter_AddRefs(container));
    1051               0 :   if (NS_FAILED(res)) return res;
    1052                 : 
    1053                 :   // XXX work around bug that causes the submenus to be first instead of last
    1054               0 :   res = AddSeparatorToContainer(container);
    1055               0 :   NS_ASSERTION(NS_SUCCEEDED(res), "error adding separator to container");
    1056                 : 
    1057               0 :   res = AddFromPrefsToMenu(aArray, container, aKey, aDecs, "charset.");
    1058               0 :   NS_ASSERTION(NS_SUCCEEDED(res), "error initializing static charset menu from prefs");
    1059                 : 
    1060               0 :   return res;
    1061                 : }
    1062                 : 
    1063               0 : nsresult nsCharsetMenu::InitCacheMenu(
    1064                 :                         nsTArray<nsCString>& aDecs,
    1065                 :                         nsIRDFResource * aResource,
    1066                 :                         const char * aKey,
    1067                 :                         nsTArray<nsMenuEntry*> * aArray)
    1068                 : {
    1069               0 :   nsresult res = NS_OK;
    1070               0 :   nsCOMPtr<nsIRDFContainer> container;
    1071                 : 
    1072               0 :   res = NewRDFContainer(mInner, aResource, getter_AddRefs(container));
    1073               0 :   if (NS_FAILED(res)) return res;
    1074                 : 
    1075               0 :   res = AddFromNolocPrefsToMenu(aArray, container, aKey, aDecs, "charset.");
    1076               0 :   NS_ASSERTION(NS_SUCCEEDED(res), "error initializing cache charset menu from prefs");
    1077                 : 
    1078               0 :   return res;
    1079                 : }
    1080                 : 
    1081               0 : nsresult nsCharsetMenu::InitAutodetMenu()
    1082                 : {
    1083               0 :   nsresult res = NS_OK;
    1084                 : 
    1085               0 :   if (!mAutoDetectInitialized) {
    1086               0 :     nsTArray<nsMenuEntry*> chardetArray;
    1087               0 :     nsCOMPtr<nsIRDFContainer> container;
    1088               0 :     nsTArray<nsCString> detectorArray;
    1089                 : 
    1090               0 :     res = NewRDFContainer(mInner, kNC_BrowserAutodetMenuRoot, getter_AddRefs(container));
    1091               0 :     if (NS_FAILED(res)) return res;
    1092                 : 
    1093               0 :     nsCOMPtr<nsIUTF8StringEnumerator> detectors;
    1094               0 :     res = mCCManager->GetCharsetDetectorList(getter_AddRefs(detectors));
    1095               0 :     if (NS_FAILED(res)) goto done;
    1096                 : 
    1097               0 :     res = SetArrayFromEnumerator(detectors, detectorArray);
    1098               0 :     if (NS_FAILED(res)) goto done;
    1099                 :     
    1100               0 :     res = AddCharsetArrayToItemArray(chardetArray, detectorArray);
    1101               0 :     if (NS_FAILED(res)) goto done;
    1102                 : 
    1103                 :     // reorder the array
    1104               0 :     res = ReorderMenuItemArray(&chardetArray);
    1105               0 :     if (NS_FAILED(res)) goto done;
    1106                 : 
    1107                 :     res = AddMenuItemArrayToContainer(container, &chardetArray, 
    1108               0 :       kNC_CharsetDetector);
    1109               0 :     if (NS_FAILED(res)) goto done;
    1110                 : 
    1111                 :   done:
    1112                 :     // free the elements in the nsTArray<nsMenuEntry*>
    1113               0 :     FreeMenuItemArray(&chardetArray);
    1114                 :   }
    1115                 : 
    1116               0 :   mAutoDetectInitialized = NS_SUCCEEDED(res);
    1117                 : 
    1118               0 :   return res;
    1119                 : }
    1120                 : 
    1121               0 : nsresult nsCharsetMenu::InitMoreMenu(nsTArray<nsCString>& aDecs, 
    1122                 :                                      nsIRDFResource * aResource, 
    1123                 :                                      const char * aFlag)
    1124                 : {
    1125               0 :   nsresult res = NS_OK;
    1126               0 :   nsCOMPtr<nsIRDFContainer> container;
    1127               0 :   nsTArray<nsMenuEntry*> moreMenu;
    1128                 : 
    1129               0 :   res = NewRDFContainer(mInner, aResource, getter_AddRefs(container));
    1130               0 :   if (NS_FAILED(res)) goto done;
    1131                 : 
    1132                 :   // remove charsets "not for browser"
    1133               0 :   res = RemoveFlaggedCharsets(aDecs, NS_ConvertASCIItoUTF16(aFlag));
    1134               0 :   if (NS_FAILED(res)) goto done;
    1135                 : 
    1136               0 :   res = AddCharsetArrayToItemArray(moreMenu, aDecs);
    1137               0 :   if (NS_FAILED(res)) goto done;
    1138                 : 
    1139                 :   // reorder the array
    1140               0 :   res = ReorderMenuItemArray(&moreMenu);
    1141               0 :   if (NS_FAILED(res)) goto done;
    1142                 : 
    1143               0 :   res = AddMenuItemArrayToContainer(container, &moreMenu, NULL);
    1144               0 :   if (NS_FAILED(res)) goto done;
    1145                 : 
    1146                 : done:
    1147                 :   // free the elements in the VoidArray
    1148               0 :   FreeMenuItemArray(&moreMenu);
    1149                 : 
    1150               0 :   return res;
    1151                 : }
    1152                 : 
    1153                 : // XXX please make this method more general; the cut&pasted code is laughable
    1154               0 : nsresult nsCharsetMenu::InitMoreSubmenus(nsTArray<nsCString>& aDecs)
    1155                 : {
    1156               0 :   nsresult res = NS_OK;
    1157                 : 
    1158               0 :   nsCOMPtr<nsIRDFContainer> container1;
    1159               0 :   nsCOMPtr<nsIRDFContainer> container2;
    1160               0 :   nsCOMPtr<nsIRDFContainer> container3;
    1161               0 :   nsCOMPtr<nsIRDFContainer> container4;
    1162               0 :   nsCOMPtr<nsIRDFContainer> container5;
    1163               0 :   nsCOMPtr<nsIRDFContainer> containerU;
    1164               0 :   const char key1[] = "intl.charsetmenu.browser.more1";
    1165               0 :   const char key2[] = "intl.charsetmenu.browser.more2";
    1166               0 :   const char key3[] = "intl.charsetmenu.browser.more3";
    1167               0 :   const char key4[] = "intl.charsetmenu.browser.more4";
    1168               0 :   const char key5[] = "intl.charsetmenu.browser.more5";
    1169               0 :   const char keyU[] = "intl.charsetmenu.browser.unicode";
    1170                 : 
    1171                 :   res = NewRDFContainer(mInner, kNC_BrowserMore1CharsetMenuRoot, 
    1172               0 :     getter_AddRefs(container1));
    1173               0 :   if (NS_FAILED(res)) return res;
    1174               0 :   AddFromNolocPrefsToMenu(NULL, container1, key1, aDecs, NULL);
    1175                 : 
    1176                 :   res = NewRDFContainer(mInner, kNC_BrowserMore2CharsetMenuRoot, 
    1177               0 :     getter_AddRefs(container2));
    1178               0 :   if (NS_FAILED(res)) return res;
    1179               0 :   AddFromNolocPrefsToMenu(NULL, container2, key2, aDecs, NULL);
    1180                 : 
    1181                 :   res = NewRDFContainer(mInner, kNC_BrowserMore3CharsetMenuRoot, 
    1182               0 :     getter_AddRefs(container3));
    1183               0 :   if (NS_FAILED(res)) return res;
    1184               0 :   AddFromNolocPrefsToMenu(NULL, container3, key3, aDecs, NULL);
    1185                 : 
    1186                 :   res = NewRDFContainer(mInner, kNC_BrowserMore4CharsetMenuRoot, 
    1187               0 :     getter_AddRefs(container4));
    1188               0 :   if (NS_FAILED(res)) return res;
    1189               0 :   AddFromNolocPrefsToMenu(NULL, container4, key4, aDecs, NULL);
    1190                 : 
    1191                 :   res = NewRDFContainer(mInner, kNC_BrowserMore5CharsetMenuRoot, 
    1192               0 :     getter_AddRefs(container5));
    1193               0 :   if (NS_FAILED(res)) return res;
    1194               0 :   AddFromNolocPrefsToMenu(NULL, container5, key5, aDecs, NULL);
    1195                 : 
    1196                 :   res = NewRDFContainer(mInner, kNC_BrowserUnicodeCharsetMenuRoot, 
    1197               0 :     getter_AddRefs(containerU));
    1198               0 :   if (NS_FAILED(res)) return res;
    1199               0 :   AddFromNolocPrefsToMenu(NULL, containerU, keyU, aDecs, NULL);
    1200                 : 
    1201               0 :   return res;
    1202                 : }
    1203                 : 
    1204               0 : nsresult nsCharsetMenu::AddCharsetToItemArray(nsTArray<nsMenuEntry*> *aArray,
    1205                 :                                               const nsAFlatCString& aCharset,
    1206                 :                                               nsMenuEntry ** aResult,
    1207                 :                                               PRInt32 aPlace)
    1208                 : {
    1209               0 :   nsresult res = NS_OK;
    1210               0 :   nsMenuEntry * item = NULL; 
    1211                 : 
    1212               0 :   if (aResult != NULL) *aResult = NULL;
    1213                 :   
    1214               0 :   item = new nsMenuEntry();
    1215               0 :   if (item == NULL) {
    1216               0 :     res = NS_ERROR_OUT_OF_MEMORY;
    1217               0 :     goto done;
    1218                 :   }
    1219                 : 
    1220               0 :   item->mCharset = aCharset;
    1221                 : 
    1222               0 :   res = mCCManager->GetCharsetTitle(aCharset.get(), item->mTitle);
    1223               0 :   if (NS_FAILED(res)) {
    1224               0 :     item->mTitle.AssignWithConversion(aCharset.get());
    1225                 :   }
    1226                 : 
    1227               0 :   if (aArray != NULL) {
    1228               0 :     if (aPlace < 0) {
    1229               0 :       res = aArray->AppendElement(item) != nsnull;
    1230               0 :       if (NS_FAILED(res)) goto done;
    1231                 :     } else {
    1232               0 :       res = aArray->InsertElementsAt(aPlace, 1, item) != nsnull;
    1233               0 :       if (NS_FAILED(res)) goto done;
    1234                 :     }
    1235                 :   }
    1236                 : 
    1237               0 :   if (aResult != NULL) *aResult = item;
    1238                 : 
    1239                 :   // if we have made another reference to "item", do not delete it 
    1240               0 :   if ((aArray != NULL) || (aResult != NULL)) item = NULL; 
    1241                 : 
    1242                 : done:
    1243               0 :   if (item != NULL) delete item;
    1244                 : 
    1245               0 :   return res;
    1246                 : }
    1247                 : 
    1248                 : nsresult
    1249               0 : nsCharsetMenu::AddCharsetArrayToItemArray(nsTArray<nsMenuEntry*>& aArray,
    1250                 :                                           const nsTArray<nsCString>& aCharsets)
    1251                 : {
    1252               0 :   PRUint32 count = aCharsets.Length();
    1253                 : 
    1254               0 :   for (PRUint32 i = 0; i < count; i++) {
    1255                 : 
    1256               0 :     const nsCString& str = aCharsets[i];
    1257               0 :     nsresult res = AddCharsetToItemArray(&aArray, str, NULL, -1);
    1258                 :     
    1259               0 :     if (NS_FAILED(res))
    1260               0 :       return res;
    1261                 :   }
    1262                 : 
    1263               0 :   return NS_OK;
    1264                 : }
    1265                 : 
    1266                 : // aPlace < -1 for Remove
    1267                 : // aPlace < 0 for Append
    1268               0 : nsresult nsCharsetMenu::AddMenuItemToContainer(
    1269                 :                         nsIRDFContainer * aContainer,
    1270                 :                         nsMenuEntry * aItem,
    1271                 :                         nsIRDFResource * aType,
    1272                 :                         const char * aIDPrefix,
    1273                 :                         PRInt32 aPlace) 
    1274                 : {
    1275               0 :   nsresult res = NS_OK;
    1276               0 :   nsCOMPtr<nsIRDFResource> node;
    1277                 : 
    1278               0 :   nsCAutoString id;
    1279               0 :   if (aIDPrefix != NULL) id.Assign(aIDPrefix);
    1280               0 :   id.Append(aItem->mCharset);
    1281                 : 
    1282                 :   // Make up a unique ID and create the RDF NODE
    1283               0 :   res = mRDFService->GetResource(id, getter_AddRefs(node));
    1284               0 :   if (NS_FAILED(res)) return res;
    1285                 : 
    1286               0 :   const PRUnichar * title = aItem->mTitle.get();
    1287                 : 
    1288                 :   // set node's title
    1289               0 :   nsCOMPtr<nsIRDFLiteral> titleLiteral;
    1290               0 :   res = mRDFService->GetLiteral(title, getter_AddRefs(titleLiteral));
    1291               0 :   if (NS_FAILED(res)) return res;
    1292                 : 
    1293               0 :   if (aPlace < -1) {
    1294               0 :     res = Unassert(node, kNC_Name, titleLiteral);
    1295               0 :     if (NS_FAILED(res)) return res;
    1296                 :   } else {
    1297               0 :     res = Assert(node, kNC_Name, titleLiteral, true);
    1298               0 :     if (NS_FAILED(res)) return res;
    1299                 :   }
    1300                 : 
    1301               0 :   if (aType != NULL) {
    1302               0 :     if (aPlace < -1) {
    1303               0 :       res = Unassert(node, kRDF_type, aType);
    1304               0 :       if (NS_FAILED(res)) return res;
    1305                 :     } else {
    1306               0 :       res = Assert(node, kRDF_type, aType, true);
    1307               0 :       if (NS_FAILED(res)) return res;
    1308                 :     }
    1309                 :   }
    1310                 : 
    1311                 :   // Add the element to the container
    1312               0 :   if (aPlace < -1) {
    1313               0 :     res = aContainer->RemoveElement(node, true);
    1314               0 :     if (NS_FAILED(res)) return res;
    1315               0 :   } else if (aPlace < 0) {
    1316               0 :     res = aContainer->AppendElement(node);
    1317               0 :     if (NS_FAILED(res)) return res;
    1318                 :   } else {
    1319               0 :     res = aContainer->InsertElementAt(node, aPlace, true);
    1320               0 :     if (NS_FAILED(res)) return res;
    1321                 :   } 
    1322                 : 
    1323               0 :   return res;
    1324                 : }
    1325                 : 
    1326               0 : nsresult nsCharsetMenu::AddMenuItemArrayToContainer(
    1327                 :                         nsIRDFContainer * aContainer,
    1328                 :                         nsTArray<nsMenuEntry*> * aArray,
    1329                 :                         nsIRDFResource * aType) 
    1330                 : {
    1331               0 :   PRUint32 count = aArray->Length();
    1332               0 :   nsresult res = NS_OK;
    1333                 : 
    1334               0 :   for (PRUint32 i = 0; i < count; i++) {
    1335               0 :     nsMenuEntry * item = aArray->ElementAt(i);
    1336               0 :     if (item == NULL) return NS_ERROR_UNEXPECTED;
    1337                 : 
    1338               0 :     res = AddMenuItemToContainer(aContainer, item, aType, NULL, -1);
    1339               0 :     if (NS_FAILED(res)) return res;
    1340                 :   }
    1341                 : 
    1342               0 :   return NS_OK;
    1343                 : }
    1344                 : 
    1345               0 : nsresult nsCharsetMenu::AddCharsetToContainer(nsTArray<nsMenuEntry*> *aArray,
    1346                 :                                               nsIRDFContainer * aContainer,
    1347                 :                                               const nsAFlatCString& aCharset,
    1348                 :                                               const char * aIDPrefix,
    1349                 :                                               PRInt32 aPlace,
    1350                 :                                               PRInt32 aRDFPlace)
    1351                 : {
    1352               0 :   nsresult res = NS_OK;
    1353               0 :   nsMenuEntry * item = NULL; 
    1354                 :   
    1355               0 :   res = AddCharsetToItemArray(aArray, aCharset, &item, aPlace);
    1356               0 :   if (NS_FAILED(res)) goto done;
    1357                 : 
    1358                 :   res = AddMenuItemToContainer(aContainer, item, NULL, aIDPrefix, 
    1359               0 :     aPlace + aRDFPlace);
    1360               0 :   if (NS_FAILED(res)) goto done;
    1361                 : 
    1362                 :   // if we have made another reference to "item", do not delete it 
    1363               0 :   if (aArray != NULL) item = NULL; 
    1364                 : 
    1365                 : done:
    1366               0 :   if (item != NULL) delete item;
    1367                 : 
    1368               0 :   return res;
    1369                 : }
    1370                 : 
    1371               0 : nsresult nsCharsetMenu::AddFromPrefsToMenu(
    1372                 :                         nsTArray<nsMenuEntry*> * aArray,
    1373                 :                         nsIRDFContainer * aContainer,
    1374                 :                         const char * aKey,
    1375                 :                         nsTArray<nsCString>& aDecs,
    1376                 :                         const char * aIDPrefix)
    1377                 : {
    1378               0 :   nsresult res = NS_OK;
    1379                 : 
    1380               0 :   nsCOMPtr<nsIPrefLocalizedString> pls;
    1381               0 :   res = mPrefs->GetComplexValue(aKey, NS_GET_IID(nsIPrefLocalizedString), getter_AddRefs(pls));
    1382               0 :   if (NS_FAILED(res)) return res;
    1383                 : 
    1384               0 :   if (pls) {
    1385               0 :     nsXPIDLString ucsval;
    1386               0 :     pls->ToString(getter_Copies(ucsval));
    1387               0 :     NS_ConvertUTF16toUTF8 utf8val(ucsval);
    1388               0 :     if (ucsval)
    1389                 :       res = AddFromStringToMenu(utf8val.BeginWriting(), aArray,
    1390               0 :                                 aContainer, aDecs, aIDPrefix);
    1391                 :   }
    1392                 : 
    1393               0 :   return res;
    1394                 : }
    1395                 : 
    1396                 : nsresult
    1397               0 : nsCharsetMenu::AddFromNolocPrefsToMenu(nsTArray<nsMenuEntry*> * aArray,
    1398                 :                                        nsIRDFContainer * aContainer,
    1399                 :                                        const char * aKey,
    1400                 :                                        nsTArray<nsCString>& aDecs,
    1401                 :                                        const char * aIDPrefix)
    1402                 : {
    1403               0 :   nsresult res = NS_OK;
    1404                 : 
    1405               0 :   char * value = NULL;
    1406               0 :   res = mPrefs->GetCharPref(aKey, &value);
    1407               0 :   if (NS_FAILED(res)) return res;
    1408                 : 
    1409               0 :   if (value != NULL) {
    1410               0 :     res = AddFromStringToMenu(value, aArray, aContainer, aDecs, aIDPrefix);
    1411               0 :     nsMemory::Free(value);
    1412                 :   }
    1413                 : 
    1414               0 :   return res;
    1415                 : }
    1416                 : 
    1417               0 : nsresult nsCharsetMenu::AddFromStringToMenu(
    1418                 :                         char * aCharsetList,
    1419                 :                         nsTArray<nsMenuEntry*> * aArray,
    1420                 :                         nsIRDFContainer * aContainer,
    1421                 :                         nsTArray<nsCString>& aDecs,
    1422                 :                         const char * aIDPrefix)
    1423                 : {
    1424               0 :   nsresult res = NS_OK;
    1425               0 :   char * p = aCharsetList;
    1426               0 :   char * q = p;
    1427               0 :   while (*p != 0) {
    1428               0 :           for (; (*q != ',') && (*q != ' ') && (*q != 0); q++) {;}
    1429               0 :     char temp = *q;
    1430               0 :     *q = 0;
    1431                 : 
    1432                 :     // if this charset is not on the accepted list of charsets, ignore it
    1433                 :     PRInt32 index;
    1434               0 :     index = aDecs.IndexOf(nsCAutoString(p), 0, nsIgnoreCaseCStringComparator());
    1435               0 :     if (index >= 0) {
    1436                 : 
    1437                 :       // else, add it to the menu
    1438               0 :       res = AddCharsetToContainer(aArray, aContainer, nsDependentCString(p),
    1439               0 :                                   aIDPrefix, -1, 0);
    1440               0 :       NS_ASSERTION(NS_SUCCEEDED(res), "cannot add charset to menu");
    1441               0 :       if (NS_FAILED(res)) break;
    1442                 : 
    1443               0 :       aDecs.RemoveElementAt(index);
    1444                 :     }
    1445                 : 
    1446               0 :     *q = temp;
    1447               0 :     for (; (*q == ',') || (*q == ' '); q++) {;}
    1448               0 :     p=q;
    1449                 :   }
    1450                 : 
    1451               0 :   return NS_OK;
    1452                 : }
    1453                 : 
    1454               0 : nsresult nsCharsetMenu::AddSeparatorToContainer(nsIRDFContainer * aContainer)
    1455                 : {
    1456               0 :   nsCAutoString str;
    1457               0 :   str.AssignLiteral("----");
    1458                 : 
    1459                 :   // hack to generate unique id's for separators
    1460                 :   static PRInt32 u = 0;
    1461               0 :   u++;
    1462               0 :   str.AppendInt(u);
    1463                 : 
    1464               0 :   nsMenuEntry item;
    1465               0 :   item.mCharset = str;
    1466               0 :   item.mTitle.AssignWithConversion(str.get());
    1467                 : 
    1468                 :   return AddMenuItemToContainer(aContainer, &item, kNC_BookmarkSeparator, 
    1469               0 :     NULL, -1);
    1470                 : }
    1471                 : 
    1472                 : nsresult
    1473               0 : nsCharsetMenu::AddCharsetToCache(const nsAFlatCString& aCharset,
    1474                 :                                  nsTArray<nsMenuEntry*> * aArray,
    1475                 :                                  nsIRDFResource * aRDFResource,
    1476                 :                                  PRUint32 aCacheStart,
    1477                 :                                  PRUint32 aCacheSize,
    1478                 :                                  PRInt32 aRDFPlace)
    1479                 : {
    1480                 :   PRInt32 i;
    1481               0 :   nsresult res = NS_OK;
    1482                 : 
    1483               0 :   i = FindMenuItemInArray(aArray, aCharset, NULL);
    1484               0 :   if (i >= 0) return res;
    1485                 : 
    1486               0 :   nsCOMPtr<nsIRDFContainer> container;
    1487               0 :   res = NewRDFContainer(mInner, aRDFResource, getter_AddRefs(container));
    1488               0 :   if (NS_FAILED(res)) return res;
    1489                 : 
    1490                 :   // if too many items, remove last one
    1491               0 :   if (aArray->Length() - aCacheStart >= aCacheSize){
    1492               0 :     res = RemoveLastMenuItem(container, aArray);
    1493               0 :     if (NS_FAILED(res)) return res;
    1494                 :   }
    1495                 : 
    1496                 :   res = AddCharsetToContainer(aArray, container, aCharset, "charset.", 
    1497               0 :                               aCacheStart, aRDFPlace);
    1498                 : 
    1499               0 :   return res;
    1500                 : }
    1501                 : 
    1502               0 : nsresult nsCharsetMenu::WriteCacheToPrefs(nsTArray<nsMenuEntry*> * aArray,
    1503                 :                                           PRInt32 aCacheStart,
    1504                 :                                           const char * aKey)
    1505                 : {
    1506               0 :   nsresult res = NS_OK;
    1507                 : 
    1508                 :   // create together the cache string
    1509               0 :   nsCAutoString cache;
    1510               0 :   nsCAutoString sep(NS_LITERAL_CSTRING(", "));
    1511               0 :   PRUint32 count = aArray->Length();
    1512                 : 
    1513               0 :   for (PRUint32 i = aCacheStart; i < count; i++) {
    1514               0 :     nsMenuEntry * item = aArray->ElementAt(i);
    1515               0 :     if (item != NULL) {    
    1516               0 :       cache.Append(item->mCharset);
    1517               0 :       if (i < count - 1) {
    1518               0 :         cache.Append(sep);
    1519                 :       }
    1520                 :     }
    1521                 :   }
    1522                 : 
    1523                 :   // write the pref
    1524               0 :   res = mPrefs->SetCharPref(aKey, cache.get());
    1525                 : 
    1526               0 :   return res;
    1527                 : }
    1528                 : 
    1529               0 : nsresult nsCharsetMenu::UpdateCachePrefs(const char * aCacheKey,
    1530                 :                                          const char * aCacheSizeKey,
    1531                 :                                          const char * aStaticKey,
    1532                 :                                          const PRUnichar * aCharset)
    1533                 : {
    1534               0 :   nsresult rv = NS_OK;
    1535               0 :   nsXPIDLCString cachePrefValue;
    1536               0 :   nsXPIDLCString staticPrefValue;
    1537               0 :   NS_LossyConvertUTF16toASCII currentCharset(aCharset);
    1538               0 :   PRInt32 cacheSize = 0;
    1539                 : 
    1540               0 :   mPrefs->GetCharPref(aCacheKey, getter_Copies(cachePrefValue));
    1541               0 :   mPrefs->GetCharPref(aStaticKey, getter_Copies(staticPrefValue));
    1542               0 :   rv = mPrefs->GetIntPref(aCacheSizeKey, &cacheSize);
    1543                 : 
    1544               0 :   if (NS_FAILED(rv) || cacheSize <= 0)
    1545               0 :     return NS_ERROR_UNEXPECTED;
    1546                 : 
    1547               0 :   if ((cachePrefValue.Find(currentCharset) == kNotFound) && 
    1548               0 :       (staticPrefValue.Find(currentCharset) == kNotFound)) {
    1549                 : 
    1550               0 :     if (!cachePrefValue.IsEmpty())
    1551               0 :       cachePrefValue.Insert(", ", 0);
    1552                 : 
    1553               0 :     cachePrefValue.Insert(currentCharset, 0);
    1554               0 :     if (cacheSize < (PRInt32) cachePrefValue.CountChar(',') + 1)
    1555               0 :       cachePrefValue.Truncate(cachePrefValue.RFindChar(','));
    1556                 : 
    1557               0 :     rv = mPrefs->SetCharPref(aCacheKey, cachePrefValue);
    1558                 :   }
    1559                 : 
    1560               0 :   return rv;
    1561                 : }
    1562                 : 
    1563               0 : nsresult nsCharsetMenu::ClearMenu(nsIRDFContainer        * aContainer,
    1564                 :                                   nsTArray<nsMenuEntry*> * aArray)
    1565                 : {
    1566               0 :   nsresult res = NS_OK;
    1567                 : 
    1568                 :   // clean the RDF data source
    1569               0 :   PRUint32 count = aArray->Length();
    1570               0 :   for (PRUint32 i = 0; i < count; i++) {
    1571               0 :     nsMenuEntry * item = aArray->ElementAt(i);
    1572               0 :     if (item != NULL) {    
    1573               0 :       res = AddMenuItemToContainer(aContainer, item, NULL, "charset.", -2);
    1574               0 :       if (NS_FAILED(res)) return res;
    1575                 :     }
    1576                 :   }
    1577                 : 
    1578                 :   // clean the internal data structures
    1579               0 :   FreeMenuItemArray(aArray);
    1580                 : 
    1581               0 :   return res;
    1582                 : }
    1583                 : 
    1584               0 : nsresult nsCharsetMenu::RemoveLastMenuItem(nsIRDFContainer * aContainer,
    1585                 :                                            nsTArray<nsMenuEntry*> * aArray)
    1586                 : {
    1587               0 :   nsresult res = NS_OK;
    1588                 : 
    1589               0 :   PRInt32 last = aArray->Length() - 1;
    1590               0 :   if (last >= 0) {
    1591               0 :     nsMenuEntry * item = aArray->ElementAt(last);
    1592               0 :     if (item != NULL) {    
    1593               0 :       res = AddMenuItemToContainer(aContainer, item, NULL, "charset.", -2);
    1594               0 :       if (NS_FAILED(res)) return res;
    1595                 : 
    1596               0 :       aArray->RemoveElementAt(last);
    1597                 :     }
    1598                 :   }
    1599                 : 
    1600               0 :   return res;
    1601                 : }
    1602                 : 
    1603               0 : nsresult nsCharsetMenu::RemoveFlaggedCharsets(nsTArray<nsCString>& aList, 
    1604                 :                                               const nsString& aProp)
    1605                 : {
    1606               0 :   nsresult res = NS_OK;
    1607                 :   PRUint32 count;
    1608                 : 
    1609               0 :   count = aList.Length();
    1610               0 :   if (NS_FAILED(res)) return res;
    1611                 : 
    1612               0 :   nsAutoString str;
    1613               0 :   for (PRUint32 i = 0; i < count; i++) {
    1614                 : 
    1615               0 :     res = mCCManager->GetCharsetData(aList[i].get(), aProp.get(), str);
    1616               0 :     if (NS_FAILED(res)) continue;
    1617                 : 
    1618               0 :     aList.RemoveElementAt(i);
    1619                 : 
    1620               0 :     i--; 
    1621               0 :     count--;
    1622                 :   }
    1623                 : 
    1624               0 :   return NS_OK;
    1625                 : }
    1626                 : 
    1627               0 : nsresult nsCharsetMenu::NewRDFContainer(nsIRDFDataSource * aDataSource, 
    1628                 :                                         nsIRDFResource * aResource, 
    1629                 :                                         nsIRDFContainer ** aResult)
    1630                 : {
    1631               0 :   nsresult res = CallCreateInstance(kRDFContainerCID, aResult);
    1632               0 :   if (NS_FAILED(res)) return res;
    1633                 : 
    1634               0 :   res = (*aResult)->Init(aDataSource, aResource);
    1635               0 :   if (NS_FAILED(res)) NS_RELEASE(*aResult);
    1636                 : 
    1637               0 :   return res;
    1638                 : }
    1639                 : 
    1640               0 : void nsCharsetMenu::FreeMenuItemArray(nsTArray<nsMenuEntry*> * aArray)
    1641                 : {
    1642               0 :   PRUint32 count = aArray->Length();
    1643               0 :   for (PRUint32 i = 0; i < count; i++) {
    1644               0 :     nsMenuEntry * item = aArray->ElementAt(i);
    1645               0 :     if (item != NULL) {
    1646               0 :       delete item;
    1647                 :     }
    1648                 :   }
    1649               0 :   aArray->Clear();
    1650               0 : }
    1651                 : 
    1652               0 : PRInt32 nsCharsetMenu::FindMenuItemInArray(const nsTArray<nsMenuEntry*>* aArray,
    1653                 :                                            const nsAFlatCString& aCharset,
    1654                 :                                            nsMenuEntry ** aResult)
    1655                 : {
    1656               0 :   PRUint32 count = aArray->Length();
    1657                 : 
    1658               0 :   for (PRUint32 i=0; i < count; i++) {
    1659               0 :     nsMenuEntry * item = aArray->ElementAt(i);
    1660               0 :     if (item->mCharset == aCharset) {
    1661               0 :       if (aResult != NULL) *aResult = item;
    1662               0 :       return i;
    1663                 :     }
    1664                 :   }
    1665                 : 
    1666               0 :   if (aResult != NULL) *aResult = NULL;
    1667               0 :   return -1;
    1668                 : }
    1669                 : 
    1670               0 : nsresult nsCharsetMenu::ReorderMenuItemArray(nsTArray<nsMenuEntry*> * aArray)
    1671                 : {
    1672               0 :   nsresult res = NS_OK;
    1673               0 :   nsCOMPtr<nsICollation> collation;
    1674               0 :   PRUint32 count = aArray->Length();
    1675                 :   PRUint32 i;
    1676                 : 
    1677                 :   // we need to use a temporary array
    1678               0 :   charsetMenuSortRecord *array = new charsetMenuSortRecord [count];
    1679               0 :   NS_ENSURE_TRUE(array, NS_ERROR_OUT_OF_MEMORY);
    1680               0 :   for (i = 0; i < count; i++)
    1681               0 :     array[i].key = nsnull;
    1682                 : 
    1683               0 :   res = GetCollation(getter_AddRefs(collation));
    1684               0 :   if (NS_FAILED(res))
    1685               0 :     goto done;
    1686                 : 
    1687               0 :   for (i = 0; i < count && NS_SUCCEEDED(res); i++) {
    1688               0 :     array[i].item = aArray->ElementAt(i);
    1689                 : 
    1690               0 :     res = collation->AllocateRawSortKey(nsICollation::kCollationCaseInSensitive, 
    1691               0 :                                        (array[i].item)->mTitle, &array[i].key, &array[i].len);
    1692                 :   }
    1693                 : 
    1694                 :   // reorder the array
    1695               0 :   if (NS_SUCCEEDED(res)) {
    1696               0 :     NS_QuickSort(array, count, sizeof(*array), CompareMenuItems, collation);
    1697                 : 
    1698                 :     // move the elements from the temporary array into the the real one
    1699               0 :     aArray->Clear();
    1700               0 :     for (i = 0; i < count; i++) {
    1701               0 :       aArray->AppendElement(array[i].item);
    1702                 :     }
    1703                 :   }
    1704                 : 
    1705                 : done:
    1706               0 :   for (i = 0; i < count; i++) {
    1707               0 :     PR_FREEIF(array[i].key);
    1708                 :   }
    1709               0 :   delete [] array;
    1710               0 :   return res;
    1711                 : }
    1712                 : 
    1713               0 : nsresult nsCharsetMenu::GetCollation(nsICollation ** aCollation)
    1714                 : {
    1715               0 :   nsresult res = NS_OK;
    1716               0 :   nsCOMPtr<nsILocale> locale = nsnull;
    1717               0 :   nsICollationFactory * collationFactory = nsnull;
    1718                 :   
    1719                 :   nsCOMPtr<nsILocaleService> localeServ = 
    1720               0 :            do_GetService(NS_LOCALESERVICE_CONTRACTID, &res);
    1721               0 :   if (NS_FAILED(res)) return res;
    1722                 : 
    1723               0 :   res = localeServ->GetApplicationLocale(getter_AddRefs(locale));
    1724               0 :   if (NS_FAILED(res)) return res;
    1725                 : 
    1726               0 :   res = CallCreateInstance(NS_COLLATIONFACTORY_CONTRACTID, &collationFactory);
    1727               0 :   if (NS_FAILED(res)) return res;
    1728                 : 
    1729               0 :   res = collationFactory->CreateCollation(locale, aCollation);
    1730               0 :   NS_RELEASE(collationFactory);
    1731               0 :   return res;
    1732                 : }
    1733                 : 
    1734                 : //----------------------------------------------------------------------------
    1735                 : // Interface nsICurrentCharsetListener [implementation]
    1736                 : 
    1737               0 : NS_IMETHODIMP nsCharsetMenu::SetCurrentCharset(const PRUnichar * aCharset)
    1738                 : {
    1739               0 :   nsresult res = NS_OK;
    1740                 : 
    1741               0 :   if (mBrowserMenuInitialized) {
    1742                 :     // Don't add item to the cache if it's marked "notForBrowser"
    1743               0 :     nsAutoString str;
    1744               0 :     res = mCCManager->GetCharsetData(NS_LossyConvertUTF16toASCII(aCharset).get(),
    1745               0 :                                      NS_LITERAL_STRING(".notForBrowser").get(), str);
    1746               0 :     if (NS_SUCCEEDED(res)) // succeeded means attribute exists
    1747               0 :       return res; // don't throw
    1748                 : 
    1749               0 :     res = AddCharsetToCache(NS_LossyConvertUTF16toASCII(aCharset),
    1750                 :                             &mBrowserMenu, kNC_BrowserCharsetMenuRoot, 
    1751                 :                             mBrowserCacheStart, mBrowserCacheSize,
    1752               0 :                             mBrowserMenuRDFPosition);
    1753               0 :     if (NS_FAILED(res)) {
    1754               0 :         return res;
    1755                 :     }
    1756                 : 
    1757                 :     res = WriteCacheToPrefs(&mBrowserMenu, mBrowserCacheStart, 
    1758               0 :       kBrowserCachePrefKey);
    1759                 :   } else {
    1760                 :     res = UpdateCachePrefs(kBrowserCachePrefKey, kBrowserCacheSizePrefKey, 
    1761               0 :                            kBrowserStaticPrefKey, aCharset);
    1762                 :   }
    1763               0 :   return res;
    1764                 : }
    1765                 : 
    1766               0 : NS_IMETHODIMP nsCharsetMenu::SetCurrentMailCharset(const PRUnichar * aCharset)
    1767                 : {
    1768               0 :   nsresult res = NS_OK;
    1769                 : 
    1770               0 :   if (mMailviewMenuInitialized) {
    1771               0 :     res = AddCharsetToCache(NS_LossyConvertUTF16toASCII(aCharset),
    1772                 :                             &mMailviewMenu, kNC_MailviewCharsetMenuRoot, 
    1773                 :                             mMailviewCacheStart, mMailviewCacheSize,
    1774               0 :                             mMailviewMenuRDFPosition);
    1775               0 :     if (NS_FAILED(res)) return res;
    1776                 : 
    1777                 :     res = WriteCacheToPrefs(&mMailviewMenu, mMailviewCacheStart, 
    1778               0 :                             kMailviewCachePrefKey);
    1779                 :   } else {
    1780                 :     res = UpdateCachePrefs(kMailviewCachePrefKey, kMailviewCacheSizePrefKey, 
    1781               0 :                            kMailviewStaticPrefKey, aCharset);
    1782                 :   }
    1783               0 :   return res;
    1784                 : }
    1785                 : 
    1786               0 : NS_IMETHODIMP nsCharsetMenu::SetCurrentComposerCharset(const PRUnichar * aCharset)
    1787                 : {
    1788               0 :   nsresult res = NS_OK;
    1789                 : 
    1790               0 :   if (mComposerMenuInitialized) {
    1791                 : 
    1792               0 :     res = AddCharsetToCache(NS_LossyConvertUTF16toASCII(aCharset),
    1793                 :                             &mComposerMenu, kNC_ComposerCharsetMenuRoot, 
    1794                 :                             mComposerCacheStart, mComposerCacheSize,
    1795               0 :                             mComposerMenuRDFPosition);
    1796               0 :     if (NS_FAILED(res)) return res;
    1797                 : 
    1798                 :     res = WriteCacheToPrefs(&mComposerMenu, mComposerCacheStart, 
    1799               0 :       kComposerCachePrefKey);
    1800                 :   } else {
    1801                 :     res = UpdateCachePrefs(kComposerCachePrefKey, kComposerCacheSizePrefKey, 
    1802               0 :                            kComposerStaticPrefKey, aCharset);
    1803                 :   }
    1804               0 :   return res;
    1805                 : }
    1806                 : 
    1807                 : //----------------------------------------------------------------------------
    1808                 : // Interface nsIRDFDataSource [implementation]
    1809                 : 
    1810               0 : NS_IMETHODIMP nsCharsetMenu::GetURI(char ** uri)
    1811                 : {
    1812               0 :   if (!uri) return NS_ERROR_NULL_POINTER;
    1813                 : 
    1814               0 :   *uri = NS_strdup("rdf:charset-menu");
    1815               0 :   if (!(*uri)) return NS_ERROR_OUT_OF_MEMORY;
    1816                 : 
    1817               0 :   return NS_OK;
    1818                 : }
    1819                 : 
    1820               0 : NS_IMETHODIMP nsCharsetMenu::GetSource(nsIRDFResource* property,
    1821                 :                                        nsIRDFNode* target,
    1822                 :                                        bool tv,
    1823                 :                                        nsIRDFResource** source)
    1824                 : {
    1825               0 :   return mInner->GetSource(property, target, tv, source);
    1826                 : }
    1827                 : 
    1828               0 : NS_IMETHODIMP nsCharsetMenu::GetSources(nsIRDFResource* property,
    1829                 :                                         nsIRDFNode* target,
    1830                 :                                         bool tv,
    1831                 :                                         nsISimpleEnumerator** sources)
    1832                 : {
    1833               0 :   return mInner->GetSources(property, target, tv, sources);
    1834                 : }
    1835                 : 
    1836               0 : NS_IMETHODIMP nsCharsetMenu::GetTarget(nsIRDFResource* source,
    1837                 :                                        nsIRDFResource* property,
    1838                 :                                        bool tv,
    1839                 :                                        nsIRDFNode** target)
    1840                 : {
    1841               0 :   return mInner->GetTarget(source, property, tv, target);
    1842                 : }
    1843                 : 
    1844               0 : NS_IMETHODIMP nsCharsetMenu::GetTargets(nsIRDFResource* source,
    1845                 :                                         nsIRDFResource* property,
    1846                 :                                         bool tv,
    1847                 :                                         nsISimpleEnumerator** targets)
    1848                 : {
    1849               0 :   return mInner->GetTargets(source, property, tv, targets);
    1850                 : }
    1851                 : 
    1852               0 : NS_IMETHODIMP nsCharsetMenu::Assert(nsIRDFResource* aSource,
    1853                 :                                     nsIRDFResource* aProperty,
    1854                 :                                     nsIRDFNode* aTarget,
    1855                 :                                     bool aTruthValue)
    1856                 : {
    1857                 :   // TODO: filter out asserts we don't care about
    1858               0 :   return mInner->Assert(aSource, aProperty, aTarget, aTruthValue);
    1859                 : }
    1860                 : 
    1861               0 : NS_IMETHODIMP nsCharsetMenu::Unassert(nsIRDFResource* aSource,
    1862                 :                                       nsIRDFResource* aProperty,
    1863                 :                                       nsIRDFNode* aTarget)
    1864                 : {
    1865                 :   // TODO: filter out unasserts we don't care about
    1866               0 :   return mInner->Unassert(aSource, aProperty, aTarget);
    1867                 : }
    1868                 : 
    1869                 : 
    1870               0 : NS_IMETHODIMP nsCharsetMenu::Change(nsIRDFResource* aSource,
    1871                 :                                     nsIRDFResource* aProperty,
    1872                 :                                     nsIRDFNode* aOldTarget,
    1873                 :                                     nsIRDFNode* aNewTarget)
    1874                 : {
    1875                 :   // TODO: filter out changes we don't care about
    1876               0 :   return mInner->Change(aSource, aProperty, aOldTarget, aNewTarget);
    1877                 : }
    1878                 : 
    1879               0 : NS_IMETHODIMP nsCharsetMenu::Move(nsIRDFResource* aOldSource,
    1880                 :                                   nsIRDFResource* aNewSource,
    1881                 :                                   nsIRDFResource* aProperty,
    1882                 :                                   nsIRDFNode* aTarget)
    1883                 : {
    1884                 :   // TODO: filter out changes we don't care about
    1885               0 :   return mInner->Move(aOldSource, aNewSource, aProperty, aTarget);
    1886                 : }
    1887                 : 
    1888                 : 
    1889               0 : NS_IMETHODIMP nsCharsetMenu::HasAssertion(nsIRDFResource* source, 
    1890                 :                                           nsIRDFResource* property, 
    1891                 :                                           nsIRDFNode* target, bool tv, 
    1892                 :                                           bool* hasAssertion)
    1893                 : {
    1894               0 :   return mInner->HasAssertion(source, property, target, tv, hasAssertion);
    1895                 : }
    1896                 : 
    1897               0 : NS_IMETHODIMP nsCharsetMenu::AddObserver(nsIRDFObserver* n)
    1898                 : {
    1899               0 :   return mInner->AddObserver(n);
    1900                 : }
    1901                 : 
    1902               0 : NS_IMETHODIMP nsCharsetMenu::RemoveObserver(nsIRDFObserver* n)
    1903                 : {
    1904               0 :   return mInner->RemoveObserver(n);
    1905                 : }
    1906                 : 
    1907                 : NS_IMETHODIMP 
    1908               0 : nsCharsetMenu::HasArcIn(nsIRDFNode *aNode, nsIRDFResource *aArc, bool *result)
    1909                 : {
    1910               0 :   return mInner->HasArcIn(aNode, aArc, result);
    1911                 : }
    1912                 : 
    1913                 : NS_IMETHODIMP 
    1914               0 : nsCharsetMenu::HasArcOut(nsIRDFResource *source, nsIRDFResource *aArc, bool *result)
    1915                 : {
    1916               0 :   return mInner->HasArcOut(source, aArc, result);
    1917                 : }
    1918                 : 
    1919               0 : NS_IMETHODIMP nsCharsetMenu::ArcLabelsIn(nsIRDFNode* node, 
    1920                 :                                          nsISimpleEnumerator** labels)
    1921                 : {
    1922               0 :   return mInner->ArcLabelsIn(node, labels);
    1923                 : }
    1924                 : 
    1925               0 : NS_IMETHODIMP nsCharsetMenu::ArcLabelsOut(nsIRDFResource* source, 
    1926                 :                                           nsISimpleEnumerator** labels)
    1927                 : {
    1928               0 :   return mInner->ArcLabelsOut(source, labels);
    1929                 : }
    1930                 : 
    1931               0 : NS_IMETHODIMP nsCharsetMenu::GetAllResources(nsISimpleEnumerator** aCursor)
    1932                 : {
    1933               0 :   return mInner->GetAllResources(aCursor);
    1934                 : }
    1935                 : 
    1936               0 : NS_IMETHODIMP nsCharsetMenu::GetAllCmds(
    1937                 :                              nsIRDFResource* source,
    1938                 :                              nsISimpleEnumerator/*<nsIRDFResource>*/** commands)
    1939                 : {
    1940               0 :   NS_NOTYETIMPLEMENTED("write me!");
    1941               0 :   return NS_ERROR_NOT_IMPLEMENTED;
    1942                 : }
    1943                 : 
    1944               0 : NS_IMETHODIMP nsCharsetMenu::IsCommandEnabled(
    1945                 :                              nsISupportsArray/*<nsIRDFResource>*/* aSources,
    1946                 :                              nsIRDFResource*   aCommand,
    1947                 :                              nsISupportsArray/*<nsIRDFResource>*/* aArguments,
    1948                 :                              bool* aResult)
    1949                 : {
    1950               0 :   NS_NOTYETIMPLEMENTED("write me!");
    1951               0 :   return NS_ERROR_NOT_IMPLEMENTED;
    1952                 : }
    1953                 : 
    1954               0 : NS_IMETHODIMP nsCharsetMenu::DoCommand(nsISupportsArray* aSources,
    1955                 :                                        nsIRDFResource*   aCommand,
    1956                 :                                        nsISupportsArray* aArguments)
    1957                 : {
    1958               0 :   NS_NOTYETIMPLEMENTED("write me!");
    1959               0 :   return NS_ERROR_NOT_IMPLEMENTED;
    1960                 : }
    1961                 : 
    1962               0 : NS_IMETHODIMP nsCharsetMenu::BeginUpdateBatch()
    1963                 : {
    1964               0 :   return mInner->BeginUpdateBatch();
    1965                 : }
    1966                 : 
    1967               0 : NS_IMETHODIMP nsCharsetMenu::EndUpdateBatch()
    1968                 : {
    1969               0 :   return mInner->EndUpdateBatch();
    1970            4392 : }

Generated by: LCOV version 1.7