!import
(0 calls, 0 incl. v-uS, 0 excl. v-uS)
1 /* -*- Mode: Java; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
2 /* ***** BEGIN LICENSE BLOCK *****
3 * Version: MPL 1.1/GPL 2.0/LGPL 2.1
4 *
5 * The contents of this file are subject to the Mozilla Public License Version
6 * 1.1 (the "License"); you may not use this file except in compliance with
7 * the License. You may obtain a copy of the License at
8 * http://www.mozilla.org/MPL/
9 *
10 * Software distributed under the License is distributed on an "AS IS" basis,
11 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
12 * for the specific language governing rights and limitations under the
13 * License.
14 *
15 * The Original Code is Mozilla Communicator client code, released
16 * March 31, 1998.
17 *
18 * The Initial Developer of the Original Code is
19 * Netscape Communications Corporation.
20 * Portions created by the Initial Developer are Copyright (C) 1998-1999
21 * the Initial Developer. All Rights Reserved.
22 *
23 * Contributor(s):
24 * Charles Manske (cmanske@netscape.com)
25 * Neil Rashbrook (neil@parkwaycc.co.uk)
26 *
27 * Alternatively, the contents of this file may be used under the terms of
28 * either of the GNU General Public License Version 2 or later (the "GPL"),
29 * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
30 * in which case the provisions of the GPL or the LGPL are applicable instead
31 * of those above. If you wish to allow use of your version of this file only
32 * under the terms of either the GPL or the LGPL, and not to allow others to
33 * use your version of this file under the terms of the MPL, indicate your
34 * decision by deleting the provisions above and replace them with the notice
35 * and other provisions required by the GPL or the LGPL. If you do not delete
36 * the provisions above, a recipient may use your version of this file under
37 * the terms of any one of the MPL, the GPL or the LGPL.
38 *
39 * ***** END LICENSE BLOCK ***** */
40
41 var gMisspelledWord;
42 var gSpellChecker = null;
43 var gAllowSelectWord = true;
44 var gPreviousReplaceWord = "";
45 var gFirstTime = true;
46 var gLastSelectedLang = null;
47 var gDictCount = 0;
48
Startup
(0 calls, 0 incl. v-uS, 0 excl. v-uS)
49 function Startup()
50 {
51 var sendMailMessageMode = false;
52
53 var editor = GetCurrentEditor();
54 if (!editor)
55 {
56 window.close();
57 return;
58 }
59
60 // Get the spellChecker shell
61 gSpellChecker = Components.classes['@mozilla.org/editor/editorspellchecker;1'].createInstance(Components.interfaces.nsIEditorSpellCheck);
62 if (!gSpellChecker)
63 {
64 dump("SpellChecker not found!!!\n");
65 window.close();
66 return;
67 }
68
69 // Start the spell checker module.
70 try {
71 // TxtSrv Filter Contract Id
72 var filterContractId;
73 sendMailMessageMode = window.arguments[0];
74 var skipBlockQuotes = window.arguments[1];
75 var enableSelectionChecking = window.arguments[2];
76
77 if (skipBlockQuotes)
78 filterContractId = "@mozilla.org/editor/txtsrvfiltermail;1";
79 else
80 filterContractId = "@mozilla.org/editor/txtsrvfilter;1";
81
82 gSpellChecker.setFilter(Components.classes[filterContractId].createInstance(Components.interfaces.nsITextServicesFilter));
83 gSpellChecker.InitSpellChecker(editor, enableSelectionChecking);
84
85 }
86 catch(ex) {
87 dump("*** Exception error: InitSpellChecker\n");
88 window.close();
89 return;
90 }
91
92 gDialog.MisspelledWordLabel = document.getElementById("MisspelledWordLabel");
93 gDialog.MisspelledWord = document.getElementById("MisspelledWord");
94 gDialog.ReplaceButton = document.getElementById("Replace");
95 gDialog.IgnoreButton = document.getElementById("Ignore");
96 gDialog.StopButton = document.getElementById("Stop");
97 gDialog.CloseButton = document.getElementById("Close");
98 gDialog.ReplaceWordInput = document.getElementById("ReplaceWordInput");
99 gDialog.SuggestedList = document.getElementById("SuggestedList");
100 gDialog.LanguageMenulist = document.getElementById("LanguageMenulist");
101
102 // Fill in the language menulist and sync it up
103 // with the spellchecker's current language.
104
105 var curLang;
106
107 try {
108 curLang = gSpellChecker.GetCurrentDictionary();
109 } catch(ex) {
110 curLang = "";
111 }
112
113 InitLanguageMenu(curLang);
114
115 // Get the first misspelled word and setup all UI
116 NextWord();
117
118 // When startup param is true, setup different UI when spell checking
119 // just before sending mail message
120 if (sendMailMessageMode)
121 {
122 // If no misspelled words found, simply close dialog and send message
123 if (!gMisspelledWord)
124 {
125 onClose();
126 return;
127 }
128
129 // Hide "Close" button and use "Send" instead
130 gDialog.CloseButton.hidden = true;
131 gDialog.CloseButton = document.getElementById("Send");
132 gDialog.CloseButton.hidden = false;
133 }
134 else
135 {
136 // Normal spell checking - hide the "Stop" button
137 // (Note that this button is the "Cancel" button for
138 // Esc keybinding and related window close actions)
139 gDialog.StopButton.hidden = true;
140 }
141
142 // Clear flag that determines message when
143 // no misspelled word is found
144 // (different message when used for the first time)
145 gFirstTime = false;
146 }
147
(0 calls, 0 incl. v-uS, 0 excl. v-uS)
148 function InitLanguageMenu(aCurLang)
149 {
150
151 var o1 = {};
152 var o2 = {};
153
154 // Get the list of dictionaries from
155 // the spellchecker.
156
157 try
158 {
159 gSpellChecker.GetDictionaryList(o1, o2);
160 }
161 catch(ex)
162 {
163 dump("Failed to get DictionaryList!\n");
164 return;
165 }
166
167 var dictList = o1.value;
168 var count = o2.value;
169
170 // If we're not just starting up and dictionary count
171 // hasn't changed then no need to update the menu.
172 if (gDictCount == count)
173 return;
174
175 // Store current dictionary count.
176 gDictCount = count;
177
178 // Load the string bundles that will help us map
179 // RFC 1766 strings to UI strings.
180
181 // Load the language string bundle.
182 var languageBundle = document.getElementById("languageBundle");
183 var regionBundle = null;
184 // If we have a language string bundle, load the region string bundle.
185 if (languageBundle)
186 regionBundle = document.getElementById("regionBundle");
187
188 var menuStr2;
189 var isoStrArray;
190 var langId;
191 var langLabel;
192 var i;
193
194 for (i = 0; i < count; i++)
195 {
196 try
197 {
198 langId = dictList[i];
199 isoStrArray = dictList[i].split("-");
200
201 if (languageBundle && isoStrArray[0])
202 langLabel = languageBundle.getString(isoStrArray[0].toLowerCase());
203
204 if (regionBundle && langLabel && isoStrArray.length > 1 && isoStrArray[1])
205 {
206 menuStr2 = regionBundle.getString(isoStrArray[1].toLowerCase());
207 if (menuStr2)
208 langLabel += "/" + menuStr2;
209 }
210
211 if (langLabel && isoStrArray.length > 2 && isoStrArray[2])
212 langLabel += " (" + isoStrArray[2] + ")";
213
214 if (!langLabel)
215 langLabel = langId;
216 }
217 catch (ex)
218 {
219 // getString throws an exception when a key is not found in the
220 // bundle. In that case, just use the original dictList string.
221 langLabel = langId;
222 }
223 dictList[i] = [langLabel, langId];
224 }
225
226 // sort by locale-aware collation
227 dictList.sort(
compareFn
(0 calls, 0 incl. v-uS, 0 excl. v-uS)
228 function compareFn(a, b)
229 {
230 return a[0].localeCompare(b[0]);
231 }
232 );
233
234 // Remove any languages from the list.
235 var languageMenuPopup = gDialog.LanguageMenulist.firstChild;
236 while (languageMenuPopup.firstChild.localName != "menuseparator")
237 languageMenuPopup.removeChild(languageMenuPopup.firstChild);
238
239 var defaultItem = null;
240
241 for (i = 0; i < count; i++)
242 {
243 var item = gDialog.LanguageMenulist.insertItemAt(i, dictList[i][0], dictList[i][1]);
244 if (aCurLang && dictList[i][1] == aCurLang)
245 defaultItem = item;
246 }
247
248 // Now make sure the correct item in the menu list is selected.
249 if (defaultItem)
250 {
251 gDialog.LanguageMenulist.selectedItem = defaultItem;
252 gLastSelectedLang = defaultItem;
253 }
254 }
255
DoEnabling
(0 calls, 0 incl. v-uS, 0 excl. v-uS)
256 function DoEnabling()
257 {
258 if (!gMisspelledWord)
259 {
260 // No more misspelled words
261 gDialog.MisspelledWord.setAttribute("value",GetString( gFirstTime ? "NoMisspelledWord" : "CheckSpellingDone"));
262
263 gDialog.ReplaceButton.removeAttribute("default");
264 gDialog.IgnoreButton.removeAttribute("default");
265
266 gDialog.CloseButton.setAttribute("default","true");
267 // Shouldn't have to do this if "default" is true?
268 gDialog.CloseButton.focus();
269
270 SetElementEnabledById("MisspelledWordLabel", false);
271 SetElementEnabledById("ReplaceWordLabel", false);
272 SetElementEnabledById("ReplaceWordInput", false);
273 SetElementEnabledById("CheckWord", false);
274 SetElementEnabledById("SuggestedListLabel", false);
275 SetElementEnabledById("SuggestedList", false);
276 SetElementEnabledById("Ignore", false);
277 SetElementEnabledById("IgnoreAll", false);
278 SetElementEnabledById("Replace", false);
279 SetElementEnabledById("ReplaceAll", false);
280 SetElementEnabledById("AddToDictionary", false);
281 } else {
282 SetElementEnabledById("MisspelledWordLabel", true);
283 SetElementEnabledById("ReplaceWordLabel", true);
284 SetElementEnabledById("ReplaceWordInput", true);
285 SetElementEnabledById("CheckWord", true);
286 SetElementEnabledById("SuggestedListLabel", true);
287 SetElementEnabledById("SuggestedList", true);
288 SetElementEnabledById("Ignore", true);
289 SetElementEnabledById("IgnoreAll", true);
290 SetElementEnabledById("AddToDictionary", true);
291
292 gDialog.CloseButton.removeAttribute("default");
293 SetReplaceEnable();
294 }
295 }
296
NextWord
(0 calls, 0 incl. v-uS, 0 excl. v-uS)
297 function NextWord()
298 {
299 gMisspelledWord = gSpellChecker.GetNextMisspelledWord();
300 SetWidgetsForMisspelledWord();
301 }
302
SetWidgetsForMisspelledWord
(0 calls, 0 incl. v-uS, 0 excl. v-uS)
303 function SetWidgetsForMisspelledWord()
304 {
305 gDialog.MisspelledWord.setAttribute("value", TruncateStringAtWordEnd(gMisspelledWord, 30, true));
306
307
308 // Initial replace word is misspelled word
309 gDialog.ReplaceWordInput.value = gMisspelledWord;
310 gPreviousReplaceWord = gMisspelledWord;
311
312 // This sets gDialog.ReplaceWordInput to first suggested word in list
313 FillSuggestedList(gMisspelledWord);
314
315 DoEnabling();
316
317 if (gMisspelledWord)
318 SetTextboxFocus(gDialog.ReplaceWordInput);
319 }
320
CheckWord
(0 calls, 0 incl. v-uS, 0 excl. v-uS)
321 function CheckWord()
322 {
323 var word = gDialog.ReplaceWordInput.value;
324 if (word)
325 {
326 if (gSpellChecker.CheckCurrentWord(word))
327 {
328 FillSuggestedList(word);
329 SetReplaceEnable();
330 }
331 else
332 {
333 ClearListbox(gDialog.SuggestedList);
334 var item = gDialog.SuggestedList.appendItem(GetString("CorrectSpelling"), "");
335 if (item) item.setAttribute("disabled", "true");
336 // Suppress being able to select the message text
337 gAllowSelectWord = false;
338 }
339 }
340 }
341
SelectSuggestedWord
(0 calls, 0 incl. v-uS, 0 excl. v-uS)
342 function SelectSuggestedWord()
343 {
344 if (gAllowSelectWord)
345 {
346 var selectedItem
347 if (gDialog.SuggestedList.selectedItem)
348 {
349 var selValue = gDialog.SuggestedList.selectedItem.getAttribute("label");
350 gDialog.ReplaceWordInput.value = selValue;
351 gPreviousReplaceWord = selValue;
352 }
353 else
354 {
355 gDialog.ReplaceWordInput.value = gPreviousReplaceWord;
356 }
357 SetReplaceEnable();
358 }
359 }
360
ChangeReplaceWord
(0 calls, 0 incl. v-uS, 0 excl. v-uS)
361 function ChangeReplaceWord()
362 {
363 // Calling this triggers SelectSuggestedWord(),
364 // so temporarily suppress the effect of that
365 var saveAllow = gAllowSelectWord;
366 gAllowSelectWord = false;
367
368 // Select matching word in list
369 var newIndex = -1;
370 var newSelectedItem;
371 var replaceWord = TrimString(gDialog.ReplaceWordInput.value);
372 if (replaceWord)
373 {
374 for (var i = 0; i < gDialog.SuggestedList.getRowCount(); i++)
375 {
376 var item = gDialog.SuggestedList.getItemAtIndex(i);
377 if (item.getAttribute("label") == replaceWord)
378 {
379 newSelectedItem = item;
380 break;
381 }
382 }
383 }
384 gDialog.SuggestedList.selectedItem = newSelectedItem;
385
386 gAllowSelectWord = saveAllow;
387
388 // Remember the new word
389 gPreviousReplaceWord = gDialog.ReplaceWordInput.value;
390
391 SetReplaceEnable();
392 }
393
Ignore
(0 calls, 0 incl. v-uS, 0 excl. v-uS)
394 function Ignore()
395 {
396 NextWord();
397 }
398
IgnoreAll
(0 calls, 0 incl. v-uS, 0 excl. v-uS)
399 function IgnoreAll()
400 {
401 if (gMisspelledWord) {
402 gSpellChecker.IgnoreWordAllOccurrences(gMisspelledWord);
403 }
404 NextWord();
405 }
406
Replace
(0 calls, 0 incl. v-uS, 0 excl. v-uS)
407 function Replace(newWord)
408 {
409 if (!newWord)
410 return;
411
412 if (gMisspelledWord && gMisspelledWord != newWord)
413 {
414 var editor = GetCurrentEditor();
415 editor.beginTransaction();
416 try {
417 gSpellChecker.ReplaceWord(gMisspelledWord, newWord, false);
418 } catch (e) {}
419 editor.endTransaction();
420 }
421 NextWord();
422 }
423
ReplaceAll
(0 calls, 0 incl. v-uS, 0 excl. v-uS)
424 function ReplaceAll()
425 {
426 var newWord = gDialog.ReplaceWordInput.value;
427 if (gMisspelledWord && gMisspelledWord != newWord)
428 {
429 var editor = GetCurrentEditor();
430 editor.beginTransaction();
431 try {
432 gSpellChecker.ReplaceWord(gMisspelledWord, newWord, true);
433 } catch (e) {}
434 editor.endTransaction();
435 }
436 NextWord();
437 }
438
AddToDictionary
(0 calls, 0 incl. v-uS, 0 excl. v-uS)
439 function AddToDictionary()
440 {
441 if (gMisspelledWord) {
442 gSpellChecker.AddWordToDictionary(gMisspelledWord);
443 }
444 NextWord();
445 }
446
EditDictionary
(0 calls, 0 incl. v-uS, 0 excl. v-uS)
447 function EditDictionary()
448 {
449 window.openDialog("chrome://editor/content/EdDictionary.xul", "_blank", "chrome,close,titlebar,modal", "", gMisspelledWord);
450 }
451
SelectLanguage
(0 calls, 0 incl. v-uS, 0 excl. v-uS)
452 function SelectLanguage()
453 {
454 try {
455 var item = gDialog.LanguageMenulist.selectedItem;
456 if (item.value != "more-cmd") {
457 gSpellChecker.SetCurrentDictionary(item.value);
458 gLastSelectedLang = item;
459 }
460 else {
461 var dictionaryUrl = getDictionaryURL();
462
463 var ioService = Components.classes["@mozilla.org/network/io-service;1"]
464 .getService(Components.interfaces.nsIIOService);
465 uri = ioService.newURI(dictionaryUrl, null, null);
466 var protocolSvc = Components.classes["@mozilla.org/uriloader/external-protocol-service;1"]
467 .getService(Components.interfaces.nsIExternalProtocolService);
468 if (protocolSvc.isExposedProtocol(uri.scheme))
469 opener.openDialog(getBrowserURL(), "_blank", "all,dialog=no", dictionaryUrl);
470 else
471 protocolSvc.loadUrl(uri);
472
473 if (gLastSelectedLang)
474 gDialog.LanguageMenulist.selectedItem = gLastSelectedLang;
475 }
476 } catch (ex) {
477 dump(ex);
478 }
479 }
480
getDictionaryURL
(0 calls, 0 incl. v-uS, 0 excl. v-uS)
481 function getDictionaryURL()
482 {
483 var formatter = Components.classes["@mozilla.org/toolkit/URLFormatterService;1"]
484 .getService(Components.interfaces.nsIURLFormatter);
485
486 return formatter.formatURLPref("spellchecker.dictionaries.download.url");
487 }
488
Recheck
(0 calls, 0 incl. v-uS, 0 excl. v-uS)
489 function Recheck()
490 {
491 //TODO: Should we bother to add a "Recheck" method to interface?
492 try {
493 var curLang = gSpellChecker.GetCurrentDictionary();
494 gSpellChecker.UninitSpellChecker();
495 gSpellChecker.InitSpellChecker(GetCurrentEditor(), false);
496 gSpellChecker.SetCurrentDictionary(curLang);
497 gMisspelledWord = gSpellChecker.GetNextMisspelledWord();
498 SetWidgetsForMisspelledWord();
499 } catch(ex) {
500 dump(ex);
501 }
502 }
503
FillSuggestedList
(0 calls, 0 incl. v-uS, 0 excl. v-uS)
504 function FillSuggestedList(misspelledWord)
505 {
506 var list = gDialog.SuggestedList;
507
508 // Clear the current contents of the list
509 gAllowSelectWord = false;
510 ClearListbox(list);
511 var item;
512
513 if (misspelledWord.length > 0)
514 {
515 // Get suggested words until an empty string is returned
516 var count = 0;
517 var firstWord = 0;
518 do {
519 var word = gSpellChecker.GetSuggestedWord();
520 if (count==0)
521 firstWord = word;
522 if (word.length > 0)
523 {
524 list.appendItem(word, "");
525 count++;
526 }
527 } while (word.length > 0);
528
529 if (count == 0)
530 {
531 // No suggestions - show a message but don't let user select it
532 item = list.appendItem(GetString("NoSuggestedWords"));
533 if (item) item.setAttribute("disabled", "true");
534 gAllowSelectWord = false;
535 } else {
536 gAllowSelectWord = true;
537 // Initialize with first suggested list by selecting it
538 gDialog.SuggestedList.selectedIndex = 0;
539 }
540 }
541 else
542 {
543 item = list.appendItem("", "");
544 if (item)
545 item.setAttribute("disabled", "true");
546 }
547 }
548
SetReplaceEnable
(0 calls, 0 incl. v-uS, 0 excl. v-uS)
549 function SetReplaceEnable()
550 {
551 // Enable "Change..." buttons only if new word is different than misspelled
552 var newWord = gDialog.ReplaceWordInput.value;
553 var enable = newWord.length > 0 && newWord != gMisspelledWord;
554 SetElementEnabledById("Replace", enable);
555 SetElementEnabledById("ReplaceAll", enable);
556 if (enable)
557 {
558 gDialog.ReplaceButton.setAttribute("default","true");
559 gDialog.IgnoreButton.removeAttribute("default");
560 }
561 else
562 {
563 gDialog.IgnoreButton.setAttribute("default","true");
564 gDialog.ReplaceButton.removeAttribute("default");
565 }
566 }
567
doDefault
(0 calls, 0 incl. v-uS, 0 excl. v-uS)
568 function doDefault()
569 {
570 if (gDialog.ReplaceButton.getAttribute("default") == "true")
571 Replace(gDialog.ReplaceWordInput.value);
572 else if (gDialog.IgnoreButton.getAttribute("default") == "true")
573 Ignore();
574 else if (gDialog.CloseButton.getAttribute("default") == "true")
575 onClose();
576
577 return false;
578 }
579
ExitSpellChecker
(0 calls, 0 incl. v-uS, 0 excl. v-uS)
580 function ExitSpellChecker()
581 {
582 if (gSpellChecker)
583 {
584 try
585 {
586 var curLang = gSpellChecker.GetCurrentDictionary();
587 gSpellChecker.UninitSpellChecker();
588 if ("@mozilla.org/spellchecker;1" in Components.classes) {
589 var spellChecker = Components.classes["@mozilla.org/spellchecker/engine;1"]
590 .getService(Components.interfaces.mozISpellCheckingEngine);
591 spellChecker.dictionary = curLang;
592 }
593 // now check the document over again with the new dictionary
594 // if we have an inline spellchecker
595 if (("InlineSpellCheckerUI" in window.opener) &&
596 window.opener.InlineSpellCheckerUI.enabled)
597 window.opener.InlineSpellCheckerUI.mInlineSpellChecker.spellCheckRange(null);
598 }
599 finally
600 {
601 gSpellChecker = null;
602 }
603 }
604 }
605
CancelSpellCheck
(0 calls, 0 incl. v-uS, 0 excl. v-uS)
606 function CancelSpellCheck()
607 {
608 ExitSpellChecker();
609
610 // Signal to calling window that we canceled
611 window.opener.cancelSendMessage = true;
612 return true;
613 }
614
onClose
(0 calls, 0 incl. v-uS, 0 excl. v-uS)
615 function onClose()
616 {
617 ExitSpellChecker();
618
619 window.opener.cancelSendMessage = false;
620 window.close();
621 }