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