toolkit/components/intl/nsCharsetMenu.cpp

branch
TOR_BUG_9701
changeset 14
925c144e1f1f
equal deleted inserted replaced
-1:000000000000 0:50fb4e060c59
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/. */
5
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"
33
34 //----------------------------------------------------------------------------
35 // Global functions and data [declaration]
36
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);
41
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);
59
60 // Note here that browser and mailview have the same static area and cache
61 // size but the cache itself is separate.
62
63 #define kBrowserStaticPrefKey "intl.charsetmenu.browser.static"
64 #define kBrowserCachePrefKey "intl.charsetmenu.browser.cache"
65 #define kBrowserCacheSizePrefKey "intl.charsetmenu.browser.cache.size"
66
67 #define kMailviewStaticPrefKey "intl.charsetmenu.browser.static"
68 #define kMailviewCachePrefKey "intl.charsetmenu.mailview.cache"
69 #define kMailviewCacheSizePrefKey "intl.charsetmenu.browser.cache.size"
70
71 #define kComposerStaticPrefKey "intl.charsetmenu.browser.static"
72 #define kComposerCachePrefKey "intl.charsetmenu.composer.cache"
73 #define kComposerCacheSizePrefKey "intl.charsetmenu.browser.cache.size"
74
75 #define kMaileditPrefKey "intl.charsetmenu.mailedit"
76
77 //----------------------------------------------------------------------------
78 // Class nsMenuEntry [declaration]
79
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); }
92
93 nsAutoCString mCharset;
94 nsAutoString mTitle;
95 };
96
97 //----------------------------------------------------------------------------
98 // Class nsCharsetMenu [declaration]
99
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)
112
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;
131
132 static nsIRDFDataSource * mInner;
133
134 bool mInitialized;
135 bool mMailviewMenuInitialized;
136 bool mComposerMenuInitialized;
137 bool mMaileditMenuInitialized;
138 bool mSecondaryTiersInitialized;
139 bool mAutoDetectInitialized;
140 bool mOthersInitialized;
141
142 nsTArray<nsMenuEntry*> mMailviewMenu;
143 int32_t mMailviewCacheStart;
144 int32_t mMailviewCacheSize;
145 int32_t mMailviewMenuRDFPosition;
146
147 nsTArray<nsMenuEntry*> mComposerMenu;
148 int32_t mComposerCacheStart;
149 int32_t mComposerCacheSize;
150 int32_t mComposerMenuRDFPosition;
151
152 nsCOMPtr<nsIRDFService> mRDFService;
153 nsCOMPtr<nsICharsetConverterManager> mCCManager;
154 nsCOMPtr<nsIPrefBranch> mPrefs;
155 nsCOMPtr<nsIObserver> mCharsetMenuObserver;
156 nsTArray<nsCString> mDecoderList;
157
158 nsresult Done();
159
160 nsresult FreeResources();
161
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);
170
171 nsresult InitMoreMenu(nsTArray<nsCString>& aDecs,
172 nsIRDFResource * aResource,
173 const char * aFlag);
174
175 nsresult InitMoreSubmenus(nsTArray<nsCString>& aDecs);
176
177 static nsresult SetArrayFromEnumerator(nsIUTF8StringEnumerator* aEnumerator,
178 nsTArray<nsCString>& aArray);
179
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);
196
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);
212
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);
219
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);
224
225 nsresult ClearMenu(nsIRDFContainer * aContainer, nsTArray<nsMenuEntry*> * aArray);
226 nsresult RemoveLastMenuItem(nsIRDFContainer * aContainer,
227 nsTArray<nsMenuEntry*> * aArray);
228
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);
238
239 public:
240 nsCharsetMenu();
241 virtual ~nsCharsetMenu();
242
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();
253
254 //--------------------------------------------------------------------------
255 // Interface nsICurrentCharsetListener [declaration]
256
257 NS_IMETHOD SetCurrentCharset(const char16_t * aCharset);
258 NS_IMETHOD SetCurrentMailCharset(const char16_t * aCharset);
259 NS_IMETHOD SetCurrentComposerCharset(const char16_t * aCharset);
260
261 //--------------------------------------------------------------------------
262 // Interface nsIRDFDataSource [declaration]
263
264 NS_DECL_NSIRDFDATASOURCE
265 };
266
267 //----------------------------------------------------------------------------
268 // Global functions and data [implementation]
269
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 }
293
294 struct charsetMenuSortRecord {
295 nsMenuEntry* item;
296 uint8_t* key;
297 uint32_t len;
298
299 };
300
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;
307
308 collation->CompareRawSortKey(rec1->key, rec1->len, rec2->key, rec2->len, &res);
309
310 return res;
311 }
312
313 nsresult
314 nsCharsetMenu::SetArrayFromEnumerator(nsIUTF8StringEnumerator* aEnumerator,
315 nsTArray<nsCString>& aArray)
316 {
317 nsresult rv;
318
319 bool hasMore;
320 rv = aEnumerator->HasMore(&hasMore);
321
322 nsAutoCString value;
323 while (NS_SUCCEEDED(rv) && hasMore) {
324 rv = aEnumerator->GetNext(value);
325 if (NS_SUCCEEDED(rv))
326 aArray.AppendElement(value);
327
328 rv = aEnumerator->HasMore(&hasMore);
329 }
330
331 return rv;
332 }
333
334
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 }
342
343 bool LessThan(const nsACString& a, const nsACString& b) const
344 {
345 return a < b;
346 }
347 };
348
349 //----------------------------------------------------------------------------
350 // Class nsCharsetMenuObserver
351
352 class nsCharsetMenuObserver : public nsIObserver {
353
354 public:
355 NS_DECL_ISUPPORTS
356 NS_DECL_NSIOBSERVER
357
358 nsCharsetMenuObserver(nsCharsetMenu * menu)
359 : mCharsetMenu(menu)
360 {
361 }
362
363 virtual ~nsCharsetMenuObserver() {}
364
365 private:
366 nsCharsetMenu* mCharsetMenu;
367 };
368
369 NS_IMPL_ISUPPORTS(nsCharsetMenuObserver, nsIObserver)
370
371 NS_IMETHODIMP nsCharsetMenuObserver::Observe(nsISupports *aSubject, const char *aTopic, const char16_t *someData)
372 {
373 nsresult rv = NS_OK;
374
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 }
398
399 //pref event handler
400 if (!nsCRT::strcmp(aTopic, NS_PREFBRANCH_PREFCHANGE_TOPIC_ID)) {
401 nsDependentString prefName(someData);
402
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 }
413
414 return rv;
415 }
416
417 //----------------------------------------------------------------------------
418 // Class nsCharsetMenu [implementation]
419
420 NS_IMPL_CYCLE_COLLECTION_CLASS(nsCharsetMenu)
421
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
426
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
434
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;
453
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;
464
465 //get charset manager
466 mCCManager = do_GetService(NS_CHARSETCONVERTERMANAGER_CONTRACTID, &res);
467
468 //initialize skeleton RDF source
469 mRDFService = do_GetService(kRDFServiceCID, &res);
470
471 if (NS_SUCCEEDED(res)) {
472 mRDFService->RegisterDataSource(this, false);
473
474 CallCreateInstance(kRDFInMemoryDataSourceCID, &mInner);
475
476 mRDFService->GetResource(NS_LITERAL_CSTRING(kURINC_BrowserCharsetMenuRoot),
477 &kNC_BrowserCharsetMenuRoot);
478 }
479
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));
484
485 //register event listener
486 mCharsetMenuObserver = new nsCharsetMenuObserver(this);
487
488 if (mCharsetMenuObserver) {
489 nsCOMPtr<nsIObserverService> observerService =
490 do_GetService("@mozilla.org/observer-service;1", &res);
491
492 if (NS_SUCCEEDED(res))
493 res = observerService->AddObserver(mCharsetMenuObserver,
494 "charsetmenu-selected",
495 false);
496 }
497
498 NS_ASSERTION(NS_SUCCEEDED(res), "Failed to initialize nsCharsetMenu");
499 }
500
501 nsCharsetMenu::~nsCharsetMenu()
502 {
503 Done();
504
505 FreeMenuItemArray(&mMailviewMenu);
506 FreeMenuItemArray(&mComposerMenu);
507
508 FreeResources();
509 }
510
511 nsresult nsCharsetMenu::RefreshMailviewMenu()
512 {
513 nsresult res = NS_OK;
514
515 nsCOMPtr<nsIRDFContainer> container;
516 res = NewRDFContainer(mInner, kNC_MailviewCharsetMenuRoot, getter_AddRefs(container));
517 if (NS_FAILED(res)) return res;
518
519 // clean the menu
520 res = ClearMenu(container, &mMailviewMenu);
521 if (NS_FAILED(res)) return res;
522
523 nsCOMPtr<nsIUTF8StringEnumerator> decoders;
524 res = mCCManager->GetDecoderList(getter_AddRefs(decoders));
525 if (NS_FAILED(res)) return res;
526
527 nsTArray<nsCString> decs;
528 SetArrayFromEnumerator(decoders, decs);
529
530 res = AddFromPrefsToMenu(&mMailviewMenu, container, kMailviewStaticPrefKey,
531 decs, "charset.");
532 NS_ASSERTION(NS_SUCCEEDED(res), "error initializing static charset menu from prefs");
533
534 // mark the end of the static area, the rest is cache
535 mMailviewCacheStart = mMailviewMenu.Length();
536
537 res = InitCacheMenu(decs, kNC_MailviewCharsetMenuRoot,
538 kMailviewCachePrefKey, &mMailviewMenu);
539 NS_ASSERTION(NS_SUCCEEDED(res), "error initializing mailview cache charset menu");
540
541 return res;
542 }
543
544 nsresult nsCharsetMenu::RefreshMaileditMenu()
545 {
546 nsresult res;
547
548 nsCOMPtr<nsIRDFContainer> container;
549 res = NewRDFContainer(mInner, kNC_MaileditCharsetMenuRoot, getter_AddRefs(container));
550 NS_ENSURE_SUCCESS(res, res);
551
552 nsCOMPtr<nsISimpleEnumerator> enumerator;
553 res = container->GetElements(getter_AddRefs(enumerator));
554 NS_ENSURE_SUCCESS(res, res);
555
556 // clear the menu
557 nsCOMPtr<nsISupports> supports;
558 while (NS_SUCCEEDED(enumerator->GetNext(getter_AddRefs(supports)))) {
559 nsCOMPtr<nsIRDFNode> node = do_QueryInterface(supports);
560
561 res = mInner->Unassert(kNC_MaileditCharsetMenuRoot, kNC_Name, node);
562 NS_ENSURE_SUCCESS(res, res);
563
564 res = container->RemoveElement(node, false);
565 NS_ENSURE_SUCCESS(res, res);
566 }
567
568 // get a list of available encoders
569 nsCOMPtr<nsIUTF8StringEnumerator> encoders;
570 res = mCCManager->GetEncoderList(getter_AddRefs(encoders));
571 NS_ENSURE_SUCCESS(res, res);
572
573 nsTArray<nsCString> encs;
574 SetArrayFromEnumerator(encoders, encs);
575
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");
579
580 return res;
581 }
582
583 nsresult nsCharsetMenu::RefreshComposerMenu()
584 {
585 nsresult res = NS_OK;
586
587 nsCOMPtr<nsIRDFContainer> container;
588 res = NewRDFContainer(mInner, kNC_ComposerCharsetMenuRoot, getter_AddRefs(container));
589 if (NS_FAILED(res)) return res;
590
591 // clean the menu
592 res = ClearMenu(container, &mComposerMenu);
593 if (NS_FAILED(res)) return res;
594
595 nsCOMPtr<nsIUTF8StringEnumerator> decoders;
596 res = mCCManager->GetDecoderList(getter_AddRefs(decoders));
597 if (NS_FAILED(res)) return res;
598
599 nsTArray<nsCString> decs;
600 SetArrayFromEnumerator(decoders, decs);
601
602 res = AddFromPrefsToMenu(&mComposerMenu, container, kComposerStaticPrefKey,
603 decs, "charset.");
604 NS_ASSERTION(NS_SUCCEEDED(res), "error initializing static charset menu from prefs");
605
606 // mark the end of the static area, the rest is cache
607 mComposerCacheStart = mComposerMenu.Length();
608
609 res = InitCacheMenu(decs, kNC_ComposerCharsetMenuRoot,
610 kComposerCachePrefKey, &mComposerMenu);
611 NS_ASSERTION(NS_SUCCEEDED(res), "error initializing composer cache charset menu");
612
613 return res;
614 }
615
616 nsresult nsCharsetMenu::Init()
617 {
618 nsresult res = NS_OK;
619
620 if (!mInitialized) {
621
622 //enumerate decoders
623 nsCOMPtr<nsIUTF8StringEnumerator> decoders;
624 res = mCCManager->GetDecoderList(getter_AddRefs(decoders));
625 if (NS_FAILED(res)) return res;
626
627 SetArrayFromEnumerator(decoders, mDecoderList);
628
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);
661
662 nsIRDFContainerUtils * rdfUtil = nullptr;
663 res = CallGetService(kRDFContainerUtilsCID, &rdfUtil);
664 if (NS_FAILED(res)) goto done;
665
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;
692
693 done:
694 NS_IF_RELEASE(rdfUtil);
695 if (NS_FAILED(res)) return res;
696 }
697 mInitialized = NS_SUCCEEDED(res);
698 return res;
699 }
700
701 nsresult nsCharsetMenu::Done()
702 {
703 nsresult res = NS_OK;
704 res = mRDFService->UnregisterDataSource(this);
705
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);
724
725 return res;
726 }
727
728 /**
729 * Free the resources no longer needed by the component.
730 */
731 nsresult nsCharsetMenu::FreeResources()
732 {
733 nsresult res = NS_OK;
734
735 if (mCharsetMenuObserver) {
736 mPrefs->RemoveObserver(kBrowserStaticPrefKey, mCharsetMenuObserver);
737 mPrefs->RemoveObserver(kMaileditPrefKey, mCharsetMenuObserver);
738 /* nsIObserverService has to have released nsCharsetMenu already */
739 }
740
741 mRDFService = nullptr;
742 mCCManager = nullptr;
743 mPrefs = nullptr;
744
745 return res;
746 }
747
748 nsresult nsCharsetMenu::InitMaileditMenu()
749 {
750 nsresult res = NS_OK;
751
752 if (!mMaileditMenuInitialized) {
753 nsCOMPtr<nsIRDFContainer> container;
754 res = NewRDFContainer(mInner, kNC_MaileditCharsetMenuRoot, getter_AddRefs(container));
755 if (NS_FAILED(res)) return res;
756
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;
765
766 nsTArray<nsCString> maileditEncoderList;
767 SetArrayFromEnumerator(encoders, maileditEncoderList);
768
769 res = AddFromPrefsToMenu(nullptr, container, kMaileditPrefKey,
770 maileditEncoderList, nullptr);
771 NS_ASSERTION(NS_SUCCEEDED(res), "error initializing mailedit charset menu from prefs");
772
773 // register prefs callback
774 mPrefs->AddObserver(kMaileditPrefKey, mCharsetMenuObserver, false);
775 }
776
777 mMaileditMenuInitialized = NS_SUCCEEDED(res);
778
779 return res;
780 }
781
782 nsresult nsCharsetMenu::InitMailviewMenu()
783 {
784 nsresult res = NS_OK;
785
786 if (!mMailviewMenuInitialized) {
787 nsCOMPtr<nsIRDFContainer> container;
788 res = NewRDFContainer(mInner, kNC_MailviewCharsetMenuRoot, getter_AddRefs(container));
789 if (NS_FAILED(res)) return res;
790
791 nsTArray<nsCString> mailviewDecoderList(mDecoderList);
792
793 res = InitStaticMenu(mailviewDecoderList, kNC_MailviewCharsetMenuRoot,
794 kMailviewStaticPrefKey, &mMailviewMenu);
795 NS_ASSERTION(NS_SUCCEEDED(res), "error initializing mailview static charset menu");
796
797 // mark the end of the static area, the rest is cache
798 mMailviewCacheStart = mMailviewMenu.Length();
799 mPrefs->GetIntPref(kMailviewCacheSizePrefKey, &mMailviewCacheSize);
800
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;
807
808 res = InitCacheMenu(mailviewDecoderList, kNC_MailviewCharsetMenuRoot,
809 kMailviewCachePrefKey, &mMailviewMenu);
810 NS_ASSERTION(NS_SUCCEEDED(res), "error initializing mailview cache charset menu");
811 }
812
813 mMailviewMenuInitialized = NS_SUCCEEDED(res);
814
815 return res;
816 }
817
818 nsresult nsCharsetMenu::InitComposerMenu()
819 {
820 nsresult res = NS_OK;
821
822 if (!mComposerMenuInitialized) {
823 nsCOMPtr<nsIRDFContainer> container;
824 res = NewRDFContainer(mInner, kNC_ComposerCharsetMenuRoot, getter_AddRefs(container));
825 if (NS_FAILED(res)) return res;
826
827 nsTArray<nsCString> composerDecoderList(mDecoderList);
828
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");
833
834 // mark the end of the static area, the rest is cache
835 mComposerCacheStart = mComposerMenu.Length();
836 mPrefs->GetIntPref(kComposerCacheSizePrefKey, &mComposerCacheSize);
837
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;
844
845 res = InitCacheMenu(composerDecoderList, kNC_ComposerCharsetMenuRoot,
846 kComposerCachePrefKey, &mComposerMenu);
847 NS_ASSERTION(NS_SUCCEEDED(res), "error initializing composer cache charset menu");
848 }
849
850 mComposerMenuInitialized = NS_SUCCEEDED(res);
851
852 return res;
853 }
854
855 nsresult nsCharsetMenu::InitOthers()
856 {
857 nsresult res = NS_OK;
858
859 if (!mOthersInitialized) {
860 nsTArray<nsCString> othersDecoderList(mDecoderList);
861
862 res = InitMoreMenu(othersDecoderList, kNC_DecodersRoot, ".notForBrowser");
863 if (NS_FAILED(res)) return res;
864
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);
869
870 res = InitMoreMenu(othersEncoderList, kNC_EncodersRoot, ".notForOutgoing");
871 if (NS_FAILED(res)) return res;
872 }
873
874 mOthersInitialized = NS_SUCCEEDED(res);
875
876 return res;
877 }
878
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;
887
888 if (!mSecondaryTiersInitialized) {
889 nsTArray<nsCString> secondaryTiersDecoderList(mDecoderList);
890
891 res = InitMoreSubmenus(secondaryTiersDecoderList);
892 NS_ASSERTION(NS_SUCCEEDED(res), "err init browser charset more submenus");
893
894 res = InitMoreMenu(secondaryTiersDecoderList, kNC_BrowserMoreCharsetMenuRoot, ".notForBrowser");
895 NS_ASSERTION(NS_SUCCEEDED(res), "err init browser charset more menu");
896 }
897
898 mSecondaryTiersInitialized = NS_SUCCEEDED(res);
899
900 return res;
901 }
902
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;
910
911 res = NewRDFContainer(mInner, aResource, getter_AddRefs(container));
912 if (NS_FAILED(res)) return res;
913
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");
917
918 res = AddFromPrefsToMenu(aArray, container, aKey, aDecs, "charset.");
919 NS_ASSERTION(NS_SUCCEEDED(res), "error initializing static charset menu from prefs");
920
921 return res;
922 }
923
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;
932
933 res = NewRDFContainer(mInner, aResource, getter_AddRefs(container));
934 if (NS_FAILED(res)) return res;
935
936 res = AddFromNolocPrefsToMenu(aArray, container, aKey, aDecs, "charset.");
937 NS_ASSERTION(NS_SUCCEEDED(res), "error initializing cache charset menu from prefs");
938
939 return res;
940 }
941
942 nsresult nsCharsetMenu::InitAutodetMenu()
943 {
944 nsresult res = NS_OK;
945
946 if (!mAutoDetectInitialized) {
947 nsTArray<nsMenuEntry*> chardetArray;
948 nsCOMPtr<nsIRDFContainer> container;
949 nsTArray<nsCString> detectorArray;
950
951 res = NewRDFContainer(mInner, kNC_BrowserAutodetMenuRoot, getter_AddRefs(container));
952 if (NS_FAILED(res)) return res;
953
954 nsCOMPtr<nsIUTF8StringEnumerator> detectors;
955 res = mCCManager->GetCharsetDetectorList(getter_AddRefs(detectors));
956 if (NS_FAILED(res)) goto done;
957
958 res = SetArrayFromEnumerator(detectors, detectorArray);
959 if (NS_FAILED(res)) goto done;
960
961 res = AddCharsetArrayToItemArray(chardetArray, detectorArray);
962 if (NS_FAILED(res)) goto done;
963
964 // reorder the array
965 res = ReorderMenuItemArray(&chardetArray);
966 if (NS_FAILED(res)) goto done;
967
968 res = AddMenuItemArrayToContainer(container, &chardetArray,
969 kNC_CharsetDetector);
970 if (NS_FAILED(res)) goto done;
971
972 done:
973 // free the elements in the nsTArray<nsMenuEntry*>
974 FreeMenuItemArray(&chardetArray);
975 }
976
977 mAutoDetectInitialized = NS_SUCCEEDED(res);
978
979 return res;
980 }
981
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;
989
990 res = NewRDFContainer(mInner, aResource, getter_AddRefs(container));
991 if (NS_FAILED(res)) goto done;
992
993 // remove charsets "not for browser"
994 res = RemoveFlaggedCharsets(aDecs, NS_ConvertASCIItoUTF16(aFlag));
995 if (NS_FAILED(res)) goto done;
996
997 res = AddCharsetArrayToItemArray(moreMenu, aDecs);
998 if (NS_FAILED(res)) goto done;
999
1000 // reorder the array
1001 res = ReorderMenuItemArray(&moreMenu);
1002 if (NS_FAILED(res)) goto done;
1003
1004 res = AddMenuItemArrayToContainer(container, &moreMenu, nullptr);
1005 if (NS_FAILED(res)) goto done;
1006
1007 done:
1008 // free the elements in the nsTArray<nsMenuEntry*>
1009 FreeMenuItemArray(&moreMenu);
1010
1011 return res;
1012 }
1013
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;
1018
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";
1029
1030 res = NewRDFContainer(mInner, kNC_BrowserMore1CharsetMenuRoot,
1031 getter_AddRefs(container1));
1032 if (NS_FAILED(res)) return res;
1033 AddFromNolocPrefsToMenu(nullptr, container1, key1, aDecs, nullptr);
1034
1035 res = NewRDFContainer(mInner, kNC_BrowserMore2CharsetMenuRoot,
1036 getter_AddRefs(container2));
1037 if (NS_FAILED(res)) return res;
1038 AddFromNolocPrefsToMenu(nullptr, container2, key2, aDecs, nullptr);
1039
1040 res = NewRDFContainer(mInner, kNC_BrowserMore3CharsetMenuRoot,
1041 getter_AddRefs(container3));
1042 if (NS_FAILED(res)) return res;
1043 AddFromNolocPrefsToMenu(nullptr, container3, key3, aDecs, nullptr);
1044
1045 res = NewRDFContainer(mInner, kNC_BrowserMore4CharsetMenuRoot,
1046 getter_AddRefs(container4));
1047 if (NS_FAILED(res)) return res;
1048 AddFromNolocPrefsToMenu(nullptr, container4, key4, aDecs, nullptr);
1049
1050 res = NewRDFContainer(mInner, kNC_BrowserMore5CharsetMenuRoot,
1051 getter_AddRefs(container5));
1052 if (NS_FAILED(res)) return res;
1053 AddFromNolocPrefsToMenu(nullptr, container5, key5, aDecs, nullptr);
1054
1055 return res;
1056 }
1057
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;
1065
1066 if (aResult != nullptr) *aResult = nullptr;
1067
1068 item = new nsMenuEntry();
1069 if (item == nullptr) {
1070 res = NS_ERROR_OUT_OF_MEMORY;
1071 goto done;
1072 }
1073
1074 item->mCharset = aCharset;
1075
1076 if (NS_FAILED(mCCManager->GetCharsetTitle(aCharset.get(), item->mTitle))) {
1077 item->mTitle.AssignWithConversion(aCharset.get());
1078 }
1079
1080 if (aArray != nullptr) {
1081 if (aPlace < 0) {
1082 aArray->AppendElement(item);
1083 } else {
1084 aArray->InsertElementsAt(aPlace, 1, item);
1085 }
1086 }
1087
1088 if (aResult != nullptr) *aResult = item;
1089
1090 // if we have made another reference to "item", do not delete it
1091 if ((aArray != nullptr) || (aResult != nullptr)) item = nullptr;
1092
1093 done:
1094 if (item != nullptr) delete item;
1095
1096 return res;
1097 }
1098
1099 nsresult
1100 nsCharsetMenu::AddCharsetArrayToItemArray(nsTArray<nsMenuEntry*>& aArray,
1101 const nsTArray<nsCString>& aCharsets)
1102 {
1103 uint32_t count = aCharsets.Length();
1104
1105 for (uint32_t i = 0; i < count; i++) {
1106
1107 const nsCString& str = aCharsets[i];
1108 nsresult res = AddCharsetToItemArray(&aArray, str, nullptr, -1);
1109
1110 if (NS_FAILED(res))
1111 return res;
1112 }
1113
1114 return NS_OK;
1115 }
1116
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;
1128
1129 nsAutoCString id;
1130 if (aIDPrefix != nullptr) id.Assign(aIDPrefix);
1131 id.Append(aItem->mCharset);
1132
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;
1136
1137 const char16_t * title = aItem->mTitle.get();
1138
1139 // set node's title
1140 nsCOMPtr<nsIRDFLiteral> titleLiteral;
1141 res = mRDFService->GetLiteral(title, getter_AddRefs(titleLiteral));
1142 if (NS_FAILED(res)) return res;
1143
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 }
1151
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 }
1161
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 }
1173
1174 return res;
1175 }
1176
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;
1184
1185 for (uint32_t i = 0; i < count; i++) {
1186 nsMenuEntry * item = aArray->ElementAt(i);
1187 if (item == nullptr) return NS_ERROR_UNEXPECTED;
1188
1189 res = AddMenuItemToContainer(aContainer, item, aType, nullptr, -1);
1190 if (NS_FAILED(res)) return res;
1191 }
1192
1193 return NS_OK;
1194 }
1195
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;
1205
1206 res = AddCharsetToItemArray(aArray, aCharset, &item, aPlace);
1207 if (NS_FAILED(res)) goto done;
1208
1209 res = AddMenuItemToContainer(aContainer, item, nullptr, aIDPrefix,
1210 aPlace + aRDFPlace);
1211 if (NS_FAILED(res)) goto done;
1212
1213 // if we have made another reference to "item", do not delete it
1214 if (aArray != nullptr) item = nullptr;
1215
1216 done:
1217 if (item != nullptr) delete item;
1218
1219 return res;
1220 }
1221
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;
1230
1231 nsCOMPtr<nsIPrefLocalizedString> pls;
1232 res = mPrefs->GetComplexValue(aKey, NS_GET_IID(nsIPrefLocalizedString), getter_AddRefs(pls));
1233 if (NS_FAILED(res)) return res;
1234
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 }
1243
1244 return res;
1245 }
1246
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;
1255
1256 char * value = nullptr;
1257 res = mPrefs->GetCharPref(aKey, &value);
1258 if (NS_FAILED(res)) return res;
1259
1260 if (value != nullptr) {
1261 res = AddFromStringToMenu(value, aArray, aContainer, aDecs, aIDPrefix);
1262 nsMemory::Free(value);
1263 }
1264
1265 return res;
1266 }
1267
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;
1282
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) {
1287
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;
1293
1294 aDecs.RemoveElementAt(index);
1295 }
1296
1297 *q = temp;
1298 for (; (*q == ',') || (*q == ' '); q++) {;}
1299 p=q;
1300 }
1301
1302 return NS_OK;
1303 }
1304
1305 nsresult nsCharsetMenu::AddSeparatorToContainer(nsIRDFContainer * aContainer)
1306 {
1307 nsAutoCString str;
1308 str.AssignLiteral("----");
1309
1310 // hack to generate unique id's for separators
1311 static int32_t u = 0;
1312 u++;
1313 str.AppendInt(u);
1314
1315 nsMenuEntry item;
1316 item.mCharset = str;
1317 item.mTitle.AssignWithConversion(str.get());
1318
1319 return AddMenuItemToContainer(aContainer, &item, kNC_BookmarkSeparator,
1320 nullptr, -1);
1321 }
1322
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;
1333
1334 i = FindMenuItemInArray(aArray, aCharset, nullptr);
1335 if (i >= 0) return res;
1336
1337 nsCOMPtr<nsIRDFContainer> container;
1338 res = NewRDFContainer(mInner, aRDFResource, getter_AddRefs(container));
1339 if (NS_FAILED(res)) return res;
1340
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 }
1346
1347 res = AddCharsetToContainer(aArray, container, aCharset, "charset.",
1348 aCacheStart, aRDFPlace);
1349
1350 return res;
1351 }
1352
1353 nsresult nsCharsetMenu::WriteCacheToPrefs(nsTArray<nsMenuEntry*> * aArray,
1354 int32_t aCacheStart,
1355 const char * aKey)
1356 {
1357 nsresult res = NS_OK;
1358
1359 // create together the cache string
1360 nsAutoCString cache;
1361 nsAutoCString sep(NS_LITERAL_CSTRING(", "));
1362 uint32_t count = aArray->Length();
1363
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 }
1373
1374 // write the pref
1375 res = mPrefs->SetCharPref(aKey, cache.get());
1376
1377 return res;
1378 }
1379
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;
1390
1391 mPrefs->GetCharPref(aCacheKey, getter_Copies(cachePrefValue));
1392 mPrefs->GetCharPref(aStaticKey, getter_Copies(staticPrefValue));
1393 rv = mPrefs->GetIntPref(aCacheSizeKey, &cacheSize);
1394
1395 if (NS_FAILED(rv) || cacheSize <= 0)
1396 return NS_ERROR_UNEXPECTED;
1397
1398 if ((cachePrefValue.Find(currentCharset) == kNotFound) &&
1399 (staticPrefValue.Find(currentCharset) == kNotFound)) {
1400
1401 if (!cachePrefValue.IsEmpty())
1402 cachePrefValue.Insert(", ", 0);
1403
1404 cachePrefValue.Insert(currentCharset, 0);
1405 if (cacheSize < (int32_t) cachePrefValue.CountChar(',') + 1)
1406 cachePrefValue.Truncate(cachePrefValue.RFindChar(','));
1407
1408 rv = mPrefs->SetCharPref(aCacheKey, cachePrefValue);
1409 }
1410
1411 return rv;
1412 }
1413
1414 nsresult nsCharsetMenu::ClearMenu(nsIRDFContainer * aContainer,
1415 nsTArray<nsMenuEntry*> * aArray)
1416 {
1417 nsresult res = NS_OK;
1418
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 }
1428
1429 // clean the internal data structures
1430 FreeMenuItemArray(aArray);
1431
1432 return res;
1433 }
1434
1435 nsresult nsCharsetMenu::RemoveLastMenuItem(nsIRDFContainer * aContainer,
1436 nsTArray<nsMenuEntry*> * aArray)
1437 {
1438 nsresult res = NS_OK;
1439
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;
1446
1447 aArray->RemoveElementAt(last);
1448 }
1449 }
1450
1451 return res;
1452 }
1453
1454 nsresult nsCharsetMenu::RemoveFlaggedCharsets(nsTArray<nsCString>& aList,
1455 const nsString& aProp)
1456 {
1457 nsresult res = NS_OK;
1458 uint32_t count;
1459
1460 count = aList.Length();
1461 if (NS_FAILED(res)) return res;
1462
1463 nsAutoString str;
1464 for (uint32_t i = 0; i < count; i++) {
1465
1466 res = mCCManager->GetCharsetData(aList[i].get(), aProp.get(), str);
1467 if (NS_FAILED(res)) continue;
1468
1469 aList.RemoveElementAt(i);
1470
1471 i--;
1472 count--;
1473 }
1474
1475 return NS_OK;
1476 }
1477
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;
1484
1485 res = (*aResult)->Init(aDataSource, aResource);
1486 if (NS_FAILED(res)) NS_RELEASE(*aResult);
1487
1488 return res;
1489 }
1490
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 }
1502
1503 int32_t nsCharsetMenu::FindMenuItemInArray(const nsTArray<nsMenuEntry*>* aArray,
1504 const nsAFlatCString& aCharset,
1505 nsMenuEntry ** aResult)
1506 {
1507 uint32_t count = aArray->Length();
1508
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 }
1516
1517 if (aResult != nullptr) *aResult = nullptr;
1518 return -1;
1519 }
1520
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;
1527
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;
1533
1534 res = GetCollation(getter_AddRefs(collation));
1535 if (NS_FAILED(res))
1536 goto done;
1537
1538 for (i = 0; i < count && NS_SUCCEEDED(res); i++) {
1539 array[i].item = aArray->ElementAt(i);
1540
1541 res = collation->AllocateRawSortKey(nsICollation::kCollationCaseInSensitive,
1542 (array[i].item)->mTitle, &array[i].key, &array[i].len);
1543 }
1544
1545 // reorder the array
1546 if (NS_SUCCEEDED(res)) {
1547 NS_QuickSort(array, count, sizeof(*array), CompareMenuItems, collation);
1548
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 }
1555
1556 done:
1557 for (i = 0; i < count; i++) {
1558 PR_FREEIF(array[i].key);
1559 }
1560 delete [] array;
1561 return res;
1562 }
1563
1564 nsresult nsCharsetMenu::GetCollation(nsICollation ** aCollation)
1565 {
1566 nsresult res = NS_OK;
1567 nsCOMPtr<nsILocale> locale = nullptr;
1568 nsICollationFactory * collationFactory = nullptr;
1569
1570 nsCOMPtr<nsILocaleService> localeServ =
1571 do_GetService(NS_LOCALESERVICE_CONTRACTID, &res);
1572 if (NS_FAILED(res)) return res;
1573
1574 res = localeServ->GetApplicationLocale(getter_AddRefs(locale));
1575 if (NS_FAILED(res)) return res;
1576
1577 res = CallCreateInstance(NS_COLLATIONFACTORY_CONTRACTID, &collationFactory);
1578 if (NS_FAILED(res)) return res;
1579
1580 res = collationFactory->CreateCollation(locale, aCollation);
1581 NS_RELEASE(collationFactory);
1582 return res;
1583 }
1584
1585 //----------------------------------------------------------------------------
1586 // Interface nsICurrentCharsetListener [implementation]
1587
1588 NS_IMETHODIMP nsCharsetMenu::SetCurrentCharset(const char16_t * aCharset)
1589 {
1590 return NS_OK;
1591 }
1592
1593 NS_IMETHODIMP nsCharsetMenu::SetCurrentMailCharset(const char16_t * aCharset)
1594 {
1595 nsresult res = NS_OK;
1596
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;
1603
1604 res = WriteCacheToPrefs(&mMailviewMenu, mMailviewCacheStart,
1605 kMailviewCachePrefKey);
1606 } else {
1607 res = UpdateCachePrefs(kMailviewCachePrefKey, kMailviewCacheSizePrefKey,
1608 kMailviewStaticPrefKey, aCharset);
1609 }
1610 return res;
1611 }
1612
1613 NS_IMETHODIMP nsCharsetMenu::SetCurrentComposerCharset(const char16_t * aCharset)
1614 {
1615 nsresult res = NS_OK;
1616
1617 if (mComposerMenuInitialized) {
1618
1619 res = AddCharsetToCache(NS_LossyConvertUTF16toASCII(aCharset),
1620 &mComposerMenu, kNC_ComposerCharsetMenuRoot,
1621 mComposerCacheStart, mComposerCacheSize,
1622 mComposerMenuRDFPosition);
1623 if (NS_FAILED(res)) return res;
1624
1625 res = WriteCacheToPrefs(&mComposerMenu, mComposerCacheStart,
1626 kComposerCachePrefKey);
1627 } else {
1628 res = UpdateCachePrefs(kComposerCachePrefKey, kComposerCacheSizePrefKey,
1629 kComposerStaticPrefKey, aCharset);
1630 }
1631 return res;
1632 }
1633
1634 //----------------------------------------------------------------------------
1635 // Interface nsIRDFDataSource [implementation]
1636
1637 NS_IMETHODIMP nsCharsetMenu::GetURI(char ** uri)
1638 {
1639 if (!uri) return NS_ERROR_NULL_POINTER;
1640
1641 *uri = NS_strdup("rdf:charset-menu");
1642 if (!(*uri)) return NS_ERROR_OUT_OF_MEMORY;
1643
1644 return NS_OK;
1645 }
1646
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 }
1654
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 }
1662
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 }
1670
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 }
1678
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 }
1687
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 }
1695
1696
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 }
1705
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 }
1714
1715
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 }
1723
1724 NS_IMETHODIMP nsCharsetMenu::AddObserver(nsIRDFObserver* n)
1725 {
1726 return mInner->AddObserver(n);
1727 }
1728
1729 NS_IMETHODIMP nsCharsetMenu::RemoveObserver(nsIRDFObserver* n)
1730 {
1731 return mInner->RemoveObserver(n);
1732 }
1733
1734 NS_IMETHODIMP
1735 nsCharsetMenu::HasArcIn(nsIRDFNode *aNode, nsIRDFResource *aArc, bool *result)
1736 {
1737 return mInner->HasArcIn(aNode, aArc, result);
1738 }
1739
1740 NS_IMETHODIMP
1741 nsCharsetMenu::HasArcOut(nsIRDFResource *source, nsIRDFResource *aArc, bool *result)
1742 {
1743 return mInner->HasArcOut(source, aArc, result);
1744 }
1745
1746 NS_IMETHODIMP nsCharsetMenu::ArcLabelsIn(nsIRDFNode* node,
1747 nsISimpleEnumerator** labels)
1748 {
1749 return mInner->ArcLabelsIn(node, labels);
1750 }
1751
1752 NS_IMETHODIMP nsCharsetMenu::ArcLabelsOut(nsIRDFResource* source,
1753 nsISimpleEnumerator** labels)
1754 {
1755 return mInner->ArcLabelsOut(source, labels);
1756 }
1757
1758 NS_IMETHODIMP nsCharsetMenu::GetAllResources(nsISimpleEnumerator** aCursor)
1759 {
1760 return mInner->GetAllResources(aCursor);
1761 }
1762
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 }
1770
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 }
1780
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 }
1788
1789 NS_IMETHODIMP nsCharsetMenu::BeginUpdateBatch()
1790 {
1791 return mInner->BeginUpdateBatch();
1792 }
1793
1794 NS_IMETHODIMP nsCharsetMenu::EndUpdateBatch()
1795 {
1796 return mInner->EndUpdateBatch();
1797 }

mercurial