toolkit/components/intl/nsCharsetMenu.cpp

Sat, 03 Jan 2015 20:18:00 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Sat, 03 Jan 2015 20:18:00 +0100
branch
TOR_BUG_3246
changeset 7
129ffea94266
permissions
-rw-r--r--

Conditionally enable double key logic according to:
private browsing mode or privacy.thirdparty.isolate preference and
implement in GetCookieStringCommon and FindCookie where it counts...
With some reservations of how to convince FindCookie users to test
condition and pass a nullptr when disabling double key logic.

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

mercurial