home *** CD-ROM | disk | FTP | other *** search
/ Chip 2004 April / CMCD0404.ISO / Software / Complet / thunderbird / chrome / mail.jar / content / editor / EdSpellCheck.js < prev    next >
Encoding:
JavaScript  |  2003-12-17  |  15.1 KB  |  546 lines

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