home *** CD-ROM | disk | FTP | other *** search
/ Chip 2002 January / 01_02.iso / software / netscape62win / mail.xpi / bin / chrome / messenger.jar / content / messenger / messengercompose / MsgComposeCommands.js < prev    next >
Text File  |  2001-10-16  |  75KB  |  2,328 lines

  1. /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
  2.  * The contents of this file are subject to the Netscape Public
  3.  * License Version 1.1 (the "License"); you may not use this file
  4.  * except in compliance with the License. You may obtain a copy of
  5.  * the License at http://www.mozilla.org/NPL/
  6.  *
  7.  * Software distributed under the License is distributed on an "AS
  8.  * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
  9.  * implied. See the License for the specific language governing
  10.  * rights and limitations under the License.
  11.  *
  12.  * The Original Code is Mozilla Communicator client code, released
  13.  * March 31, 1998.
  14.  *
  15.  * The Initial Developer of the Original Code is Netscape
  16.  * Communications Corporation. Portions created by Netscape are
  17.  * Copyright (C) 1998-1999 Netscape Communications Corporation. All
  18.  * Rights Reserved.
  19.  */
  20.  
  21. var msgCompDeliverMode = Components.interfaces.nsIMsgCompDeliverMode;
  22. var msgCompSendFormat = Components.interfaces.nsIMsgCompSendFormat;
  23. var msgCompConvertible = Components.interfaces.nsIMsgCompConvertible;
  24. var msgCompType = Components.interfaces.nsIMsgCompType;
  25. var msgCompFormat = Components.interfaces.nsIMsgCompFormat;
  26. var abPreferMailFormat = Components.interfaces.nsIAbPreferMailFormat;
  27. var plaintextEditor = Components.interfaces.nsIPlaintextEditor;
  28.  
  29. var accountManagerContractID   = "@mozilla.org/messenger/account-manager;1";
  30. var accountManager = Components.classes[accountManagerContractID].getService(Components.interfaces.nsIMsgAccountManager);
  31.  
  32. var ioService = Components.classes["@mozilla.org/network/io-service;1"]
  33.                            .getService(Components.interfaces.nsIIOService);
  34.  
  35. //var mailSessionContractID   = "@mozilla.org/messenger/services/session;1";
  36. //var mailSession = Components.classes[mailSessionContractID].getService(Components.interfaces.nsIMsgMailSession);
  37.  
  38. var messengerMigratorContractID   = "@mozilla.org/messenger/migrator;1";
  39.  
  40. var msgComposeService = Components.classes["@mozilla.org/messengercompose;1"].getService();
  41. msgComposeService = msgComposeService.QueryInterface(Components.interfaces.nsIMsgComposeService);
  42.  
  43. var gPromptService = null;
  44.  
  45. //This migrates the LDAPServer Preferences from 4.x to mozilla format.
  46. try {
  47.   var LDAPPrefsService = Components.classes[
  48.                        "@mozilla.org/ldapprefs-service;1"].getService();
  49.   LDAPPrefsService = LDAPPrefsService.QueryInterface(
  50.                    Components.interfaces.nsILDAPPrefsService);
  51. } catch (ex) {dump ("ERROR:" + ex + "\n");}
  52.  
  53. var msgCompose = null;
  54. var MAX_RECIPIENTS = 0;
  55. var currentAttachment = null;
  56. var windowLocked = false;
  57. var contentChanged = false;
  58. var gCurrentIdentity = null;
  59. var defaultSaveOperation = "draft";
  60. var sendOrSaveOperationInProgress = false;
  61. var isOffline = false;
  62. var sessionAdded = false;
  63. var currentAutocompleteDirectory = null;
  64. var gAutocompleteSession = null;
  65. var gSetupLdapAutocomplete = false;
  66. var gLDAPSession = null;
  67. var gComposeMsgsBundle;
  68.  
  69. const DEBUG = false;
  70.  
  71. var other_header = "";
  72. var sendFormat = msgCompSendFormat.AskUser;
  73. var prefs = Components.classes["@mozilla.org/preferences;1"].getService();
  74. if (prefs) {
  75.     prefs = prefs.QueryInterface(Components.interfaces.nsIPref);
  76.     if (prefs) {
  77.         try {
  78.             other_header = prefs.CopyCharPref("mail.compose.other.header");
  79.         }
  80.         catch (ex) {
  81.              dump("failed to get the mail.compose.other.header pref\n");
  82.         }
  83.     }
  84. }
  85.  
  86. function disableEditableFields()
  87. {
  88.   editorShell.editor.SetFlags(plaintextEditor.eEditorReadonlyMask);
  89.   document.getElementById("msgSubject").setAttribute('disabled', 'true');
  90.   var disableElements = document.getElementsByAttribute("disableonsend", "true");
  91.   for (i=0;i<disableElements.length;i++)
  92.   {
  93.     disableElements[i].setAttribute('disabled', 'true');
  94.   }
  95. }
  96.  
  97. function enableEditableFields()
  98. {
  99.   editorShell.editor.SetFlags(plaintextEditor.eEditorMailMask);
  100.   document.getElementById("msgSubject").removeAttribute("disabled");
  101.   var enableElements = document.getElementsByAttribute("disableonsend", "true");
  102.   for (i=0;i<enableElements.length;i++)
  103.   {
  104.     enableElements[i].removeAttribute('disabled');
  105.   }
  106. }
  107.  
  108. var stateListener = {
  109.     NotifyComposeFieldsReady: function() {
  110.         ComposeFieldsReady();
  111.     },
  112.  
  113.     ComposeProcessDone: function(aResult) {
  114.     dump("\n RECEIVE ComposeProcessDone\n\n");
  115.     windowLocked = false;
  116.     CommandUpdate_MsgCompose();
  117.     enableEditableFields();
  118.  
  119.     if (aResult== Components.results.NS_OK)
  120.     {
  121.       contentChanged = false;
  122.       msgCompose.bodyModified = false;
  123.     }
  124.     },
  125.  
  126.   SaveInFolderDone: function(folderURI) {
  127.     DisplaySaveFolderDlg(folderURI);
  128.   }
  129. };
  130.  
  131. // all progress notifications are done through the nsIWebProgressListener implementation...
  132. var progressListener = {
  133.     onStateChange: function(aWebProgress, aRequest, aStateFlags, aStatus)
  134.     {
  135.       if (aStateFlags & Components.interfaces.nsIWebProgressListener.STATE_START)
  136.       {
  137.         document.getElementById('compose-progressmeter').setAttribute( "mode", "undetermined" );
  138.       }
  139.       
  140.       if (aStateFlags & Components.interfaces.nsIWebProgressListener.STATE_STOP)
  141.       {
  142.         sendOrSaveOperationInProgress = false;
  143.         document.getElementById('compose-progressmeter').setAttribute( "mode", "normal" );
  144.         document.getElementById('compose-progressmeter').setAttribute( "value", 0 );
  145.         setTimeout("document.getElementById('statusText').setAttribute('label', '')", 5000);
  146.       }
  147.     },
  148.     
  149.     onProgressChange: function(aWebProgress, aRequest, aCurSelfProgress, aMaxSelfProgress, aCurTotalProgress, aMaxTotalProgress)
  150.     {
  151.       // Calculate percentage.
  152.       var percent;
  153.       if ( aMaxTotalProgress > 0 ) 
  154.       {
  155.         percent = parseInt( (aCurTotalProgress*100)/aMaxTotalProgress + .5 );
  156.         if ( percent > 100 )
  157.           percent = 100;
  158.         
  159.         document.getElementById('compose-progressmeter').removeAttribute("mode");
  160.         
  161.         // Advance progress meter.
  162.         document.getElementById('compose-progressmeter').setAttribute( "value", percent );
  163.       } 
  164.       else 
  165.       {
  166.         // Progress meter should be barber-pole in this case.
  167.         document.getElementById('compose-progressmeter').setAttribute( "mode", "undetermined" );
  168.       }
  169.     },
  170.  
  171.       onLocationChange: function(aWebProgress, aRequest, aLocation)
  172.     {
  173.       // we can ignore this notification
  174.     },
  175.  
  176.     onStatusChange: function(aWebProgress, aRequest, aStatus, aMessage)
  177.     {
  178.       // Looks like it's possible that we get call while the document has been already delete!
  179.       // therefore we need to protect ourself by using try/catch
  180.       try {
  181.         statusText = document.getElementById("statusText");
  182.         if (statusText)
  183.           statusText.setAttribute("label", aMessage);
  184.       } catch (ex) {};
  185.     },
  186.  
  187.     onSecurityChange: function(aWebProgress, aRequest, state)
  188.     {
  189.       // we can ignore this notification
  190.     },
  191.  
  192.     QueryInterface : function(iid)
  193.     {
  194.      if (iid.equals(Components.interfaces.nsIWebProgressListener) || iid.equals(Components.interfaces.nsISupportsWeakReference))
  195.       return this;
  196.      
  197.      throw Components.results.NS_NOINTERFACE;
  198.     }
  199. };
  200.  
  201. // i18n globals
  202. var g_currentMailSendCharset = null;
  203. var g_send_default_charset = null;
  204. var g_charsetTitle = null;
  205. var g_charsetConvertManager = Components.classes['@mozilla.org/charset-converter-manager;1'].getService();
  206. g_charsetConvertManager = g_charsetConvertManager.QueryInterface(Components.interfaces.nsICharsetConverterManager2);
  207.   //Create message window object
  208. var msgWindowContractID      = "@mozilla.org/messenger/msgwindow;1";
  209. var msgWindow = Components.classes[msgWindowContractID].createInstance();
  210.  
  211. var defaultController =
  212. {
  213.   supportsCommand: function(command)
  214.   {
  215.     switch (command)
  216.     {
  217.       //File Menu
  218.       case "cmd_attachFile":
  219.       case "cmd_attachPage":
  220.       case "cmd_close":
  221.       case "cmd_saveDefault":
  222.       case "cmd_saveAsFile":
  223.       case "cmd_saveAsDraft":
  224.       case "cmd_saveAsTemplate":
  225.       case "cmd_sendButton":
  226.       case "cmd_sendNow":
  227.       case "cmd_sendLater":
  228.       case "cmd_printSetup":
  229.       case "cmd_print":
  230.       case "cmd_quit":
  231.  
  232.       //Edit Menu
  233.       case "cmd_pasteQuote":
  234.       case "cmd_find":
  235.       case "cmd_findNext":
  236.       case "cmd_account":
  237.       case "cmd_preferences":
  238.  
  239.       //View Menu
  240.       case "cmd_showComposeToolbar":
  241.       case "cmd_showFormatToolbar":
  242.  
  243.       //Insert Menu
  244.       case "cmd_renderedHTMLEnabler":
  245.       case "cmd_insert":
  246.       case "cmd_link":
  247.       case "cmd_anchor":
  248.       case "cmd_image":
  249.       case "cmd_hline":
  250.       case "cmd_table":
  251.       case "cmd_insertHTML":
  252.       case "cmd_insertChars":
  253.       case "cmd_insertBreak":
  254.       case "cmd_insertBreakAll":
  255.  
  256.       //Format Menu
  257.       case "cmd_decreaseFont":
  258.       case "cmd_increaseFont":
  259.       case "cmd_bold":
  260.       case "cmd_italic":
  261.       case "cmd_underline":
  262.       case "cmd_strikethrough":
  263.       case "cmd_superscript":
  264.       case "cmd_subscript":
  265.       case "cmd_nobreak":
  266.       case "cmd_em":
  267.       case "cmd_strong":
  268.       case "cmd_cite":
  269.       case "cmd_abbr":
  270.       case "cmd_acronym":
  271.       case "cmd_code":
  272.       case "cmd_samp":
  273.       case "cmd_var":
  274.       case "cmd_removeList":
  275.       case "cmd_ul":
  276.       case "cmd_ol":
  277.       case "cmd_dt":
  278.       case "cmd_dd":
  279.       case "cmd_listProperties":
  280.       case "cmd_indent":
  281.       case "cmd_outdent":
  282.       case "cmd_objectProperties":
  283.       case "cmd_InsertTable":
  284.       case "cmd_InsertRowAbove":
  285.       case "cmd_InsertRowBelow":
  286.       case "cmd_InsertColumnBefore":
  287.       case "cmd_InsertColumnAfter":
  288.       case "cmd_SelectTable":
  289.       case "cmd_SelectRow":
  290.       case "cmd_SelectColumn":
  291.       case "cmd_SelectCell":
  292.       case "cmd_SelectAllCells":
  293.       case "cmd_DeleteTable":
  294.       case "cmd_DeleteRow":
  295.       case "cmd_DeleteColumn":
  296.       case "cmd_DeleteCell":
  297.       case "cmd_DeleteCellContents":
  298.       case "cmd_NormalizeTable":
  299.       case "cmd_tableJoinCells":
  300.       case "cmd_tableSplitCell":
  301.       case "cmd_editTable":
  302.  
  303.       //Options Menu
  304.       case "cmd_selectAddress":
  305.       case "cmd_spelling":
  306.       case "cmd_outputFormat":
  307. //      case "cmd_quoteMessage":
  308.       case "cmd_rewrap":
  309.  
  310.         return true;
  311.  
  312.       default:
  313. //        dump("##MsgCompose: command " + command + "no supported!\n");
  314.         return false;
  315.     }
  316.   },
  317.   isCommandEnabled: function(command)
  318.   {
  319.     //For some reason, when editor has the focus, focusedElement is null!.
  320.     var focusedElement = top.document.commandDispatcher.focusedElement;
  321.  
  322.     var composeHTML = msgCompose && msgCompose.composeHTML;
  323.  
  324.     switch (command)
  325.     {
  326.       //File Menu
  327.       case "cmd_attachFile":
  328.       case "cmd_attachPage":
  329.       case "cmd_close":
  330.       case "cmd_saveDefault":
  331.       case "cmd_saveAsFile":
  332.       case "cmd_saveAsDraft":
  333.       case "cmd_saveAsTemplate":
  334.       case "cmd_sendButton":
  335.       case "cmd_sendLater":
  336.       case "cmd_printSetup":
  337.       case "cmd_print":
  338.         return !windowLocked;
  339.       case "cmd_sendNow":
  340.         return !(windowLocked || (ioService && ioService.offline))
  341.       case "cmd_quit":
  342.         return true;
  343.  
  344.       //Edit Menu
  345.       case "cmd_pasteQuote":
  346.       case "cmd_find":
  347.       case "cmd_findNext":
  348.         //Disable the editor specific edit commands if the focus is not into the body
  349.         return !focusedElement;
  350.       case "cmd_account":
  351.       case "cmd_preferences":
  352.         return true;
  353.  
  354.       //View Menu
  355.       case "cmd_showComposeToolbar":
  356.         return true;
  357.       case "cmd_showFormatToolbar":
  358.         return composeHTML;
  359.  
  360.       //Insert Menu
  361.       case "cmd_renderedHTMLEnabler":
  362.       case "cmd_insert":
  363.         return !focusedElement;
  364.       case "cmd_link":
  365.       case "cmd_anchor":
  366.       case "cmd_image":
  367.       case "cmd_hline":
  368.       case "cmd_table":
  369.       case "cmd_insertHTML":
  370.       case "cmd_insertChars":
  371.       case "cmd_insertBreak":
  372.       case "cmd_insertBreakAll":
  373.         return !focusedElement;
  374.  
  375.       //Options Menu
  376.       case "cmd_selectAddress":
  377.         return !windowLocked;
  378.       case "cmd_spelling":
  379.         return !focusedElement;
  380.       case "cmd_outputFormat":
  381.         return composeHTML;
  382. //      case "cmd_quoteMessage":
  383. //        return mailSession && mailSession.topmostMsgWindow;
  384.       case "cmd_rewrap":
  385.         return !composeHTML && !focusedElement;
  386.  
  387.       //Format Menu
  388.       case "cmd_decreaseFont":
  389.       case "cmd_increaseFont":
  390.       case "cmd_bold":
  391.       case "cmd_italic":
  392.       case "cmd_underline":
  393.       case "cmd_smiley":
  394.       case "cmd_strikethrough":
  395.       case "cmd_superscript":
  396.       case "cmd_subscript":
  397.       case "cmd_nobreak":
  398.       case "cmd_em":
  399.       case "cmd_strong":
  400.       case "cmd_cite":
  401.       case "cmd_abbr":
  402.       case "cmd_acronym":
  403.       case "cmd_code":
  404.       case "cmd_samp":
  405.       case "cmd_var":
  406.       case "cmd_removeList":
  407.       case "cmd_ul":
  408.       case "cmd_ol":
  409.       case "cmd_dt":
  410.       case "cmd_dd":
  411.       case "cmd_listProperties":
  412.       case "cmd_indent":
  413.       case "cmd_outdent":
  414.       case "cmd_objectProperties":
  415.       case "cmd_InsertTable":
  416.       case "cmd_InsertRowAbove":
  417.       case "cmd_InsertRowBelow":
  418.       case "cmd_InsertColumnBefore":
  419.       case "cmd_InsertColumnAfter":
  420.       case "cmd_SelectTable":
  421.       case "cmd_SelectRow":
  422.       case "cmd_SelectColumn":
  423.       case "cmd_SelectCell":
  424.       case "cmd_SelectAllCells":
  425.       case "cmd_DeleteTable":
  426.       case "cmd_DeleteRow":
  427.       case "cmd_DeleteColumn":
  428.       case "cmd_DeleteCell":
  429.       case "cmd_DeleteCellContents":
  430.       case "cmd_NormalizeTable":
  431.       case "cmd_tableJoinCells":
  432.       case "cmd_tableSplitCell":
  433.       case "cmd_editTable":
  434.         return !focusedElement;
  435.  
  436.       default:
  437. //        dump("##MsgCompose: command " + command + " disabled!\n");
  438.         return false;
  439.     }
  440.   },
  441.  
  442.   doCommand: function(command)
  443.   { 
  444.     switch (command)
  445.     {
  446.       //File Menu
  447.       case "cmd_attachFile"         : if (defaultController.isCommandEnabled(command)) AttachFile();           break;
  448.       case "cmd_attachPage"         : AttachPage();           break;
  449.       case "cmd_close"              : DoCommandClose();       break;
  450.       case "cmd_saveDefault"        : Save();                 break;
  451.       case "cmd_saveAsFile"         : SaveAsFile(true);       break;
  452.       case "cmd_saveAsDraft"        : SaveAsDraft();          break;
  453.       case "cmd_saveAsTemplate"     : SaveAsTemplate();       break;
  454.       case "cmd_sendButton"         :
  455.         if (defaultController.isCommandEnabled(command))
  456.         {
  457.           if (ioService && ioService.offline)
  458.             SendMessageLater();
  459.           else
  460.             SendMessage();
  461.         }
  462.         break;
  463.       case "cmd_sendNow"            : if (defaultController.isCommandEnabled(command)) SendMessage();          break;
  464.       case "cmd_sendLater"          : if (defaultController.isCommandEnabled(command)) SendMessageLater();     break;
  465.       case "cmd_printSetup"         : goPageSetup();                                                           break;
  466.       case "cmd_print"              : DoCommandPrint();                                                        break;
  467.  
  468.       //Edit Menu
  469.       case "cmd_account"            : MsgAccountManager(null); break;
  470.       case "cmd_preferences"        : DoCommandPreferences(); break;
  471.  
  472.       //View Menu
  473.       case "cmd_showComposeToolbar" : goToggleToolbar('composeToolbar', 'menu_showComposeToolbar'); break;
  474.       case "cmd_showFormatToolbar"  : goToggleToolbar('FormatToolbar', 'menu_showFormatToolbar');   break;
  475.  
  476.       //Options Menu
  477.       case "cmd_selectAddress"      : if (defaultController.isCommandEnabled(command)) SelectAddress();         break;
  478. //      case "cmd_quoteMessage"       : if (defaultController.isCommandEnabled(command)) QuoteSelectedMessage();  break;
  479.       case "cmd_rewrap"             : editorShell.Rewrap(false);                                                break;
  480.  
  481.       default:
  482. //        dump("##MsgCompose: don't know what to do with command " + command + "!\n");
  483.         return;
  484.     }
  485.   },
  486.  
  487.   onEvent: function(event)
  488.   {
  489. //    dump("DefaultController:onEvent\n");
  490.   }
  491. }
  492.  
  493. function SetupCommandUpdateHandlers()
  494. {
  495. //  dump("SetupCommandUpdateHandlers\n");
  496.   top.controllers.insertControllerAt(0, defaultController);
  497. }
  498.  
  499. function CommandUpdate_MsgCompose()
  500. {
  501.   window.setTimeout("updateComposeItems()", 0);
  502. }
  503.  
  504. function updateComposeItems() {
  505.   try {
  506.   //Edit Menu
  507.  
  508.   //Insert Menu
  509.   if (msgCompose && msgCompose.composeHTML)
  510.   {
  511.     goUpdateCommand("cmd_insert");
  512.     goUpdateCommand("cmd_decreaseFont");
  513.     goUpdateCommand("cmd_increaseFont");
  514.     goUpdateCommand("cmd_bold");
  515.     goUpdateCommand("cmd_italic");
  516.     goUpdateCommand("cmd_underline");
  517.     goUpdateCommand("cmd_ul");
  518.     goUpdateCommand("cmd_ol");
  519.     goUpdateCommand("cmd_indent");
  520.     goUpdateCommand("cmd_outdent");
  521.     goUpdateCommand("cmd_align");
  522.     goUpdateCommand("cmd_smiley");
  523.   }
  524.  
  525.   //Options Menu
  526.   goUpdateCommand("cmd_spelling");
  527.  
  528.  
  529.   } catch(e) {}
  530. }
  531.  
  532. function updateEditItems() {
  533.   goUpdateCommand("cmd_pasteQuote");
  534.   goUpdateCommand("cmd_find");
  535.   goUpdateCommand("cmd_findNext");
  536. }
  537.  
  538. var messageComposeOfflineObserver = {
  539.   Observe: function(subject, topic, state) {
  540.     // sanity checks
  541.     if (topic != "network:offline-status-changed") return;
  542.     if (state == "offline")
  543.       isOffline = true;
  544.     else
  545.       isOffline = false;
  546.     MessageComposeOfflineStateChanged(isOffline);
  547.  
  548.     try {
  549.         setupLdapAutocompleteSession();
  550.     } catch (ex) {
  551.         // catch the exception and ignore it, so that if LDAP setup 
  552.         // fails, the entire compose window stuff doesn't get aborted
  553.     }
  554.   }
  555. }
  556.  
  557. function AddMessageComposeOfflineObserver()
  558. {
  559.   var observerService = Components.classes["@mozilla.org/observer-service;1"].getService(Components.interfaces.nsIObserverService);
  560.   observerService.AddObserver(messageComposeOfflineObserver, "network:offline-status-changed");
  561.   
  562.   isOffline = ioService.offline;
  563.   // set the initial state of the send button
  564.   MessageComposeOfflineStateChanged(isOffline);
  565. }
  566.  
  567. function RemoveMessageComposeOfflineObserver()
  568. {
  569.   var observerService = Components.classes["@mozilla.org/observer-service;1"].getService(Components.interfaces.nsIObserverService);
  570.   observerService.RemoveObserver(messageComposeOfflineObserver,"network:offline-status-changed");
  571. }
  572.  
  573. function MessageComposeOfflineStateChanged(goingOffline)
  574. {
  575.   try {
  576.     var sendButton = document.getElementById("button-send");
  577.  
  578.     if (goingOffline)
  579.     {
  580.       sendButton.label = sendButton.getAttribute('later_label');
  581.       sendButton.setAttribute('tooltiptext', sendButton.getAttribute('later_tooltiptext'));
  582.     }
  583.     else
  584.     {
  585.       sendButton.label = sendButton.getAttribute('now_label');
  586.       sendButton.setAttribute('tooltiptext', sendButton.getAttribute('now_tooltiptext'));
  587.     }
  588.  
  589.   } catch(e) {}
  590. }
  591.  
  592. var directoryServerObserver = {
  593.   Observe: function(subject, topic, value) {
  594.       try {
  595.           setupLdapAutocompleteSession();
  596.       } catch (ex) {
  597.           // catch the exception and ignore it, so that if LDAP setup 
  598.           // fails, the entire compose window doesn't get horked
  599.       }
  600.   }
  601. }
  602.  
  603. function AddDirectoryServerObserver(flag) {
  604.   if (flag) {
  605.     prefs.addObserver("ldap_2.autoComplete.useDirectory", directoryServerObserver);
  606.     prefs.addObserver("ldap_2.autoComplete.directoryServer", directoryServerObserver);
  607.   }
  608.   else
  609.   {
  610.     var prefstring = "mail.identity." + gCurrentIdentity.key + ".overrideGlobal_Pref";
  611.     prefs.addObserver(prefstring, directoryServerObserver);
  612.     prefstring = "mail.identity." + gCurrentIdentity.key + ".directoryServer";
  613.     prefs.addObserver(prefstring, directoryServerObserver);
  614.   }
  615. }
  616.  
  617. function RemoveDirectoryServerObserver(prefstring)
  618. {
  619.   if (!prefstring) {
  620.     prefs.removeObserver("ldap_2.autoComplete.useDirectory", directoryServerObserver);
  621.     prefs.removeObserver("ldap_2.autoComplete.directoryServer", directoryServerObserver);
  622.   }
  623.   else
  624.   {
  625.     var str = prefstring + ".overrideGlobal_Pref";
  626.     prefs.removeObserver(str, directoryServerObserver);
  627.     str = prefstring + ".directoryServer";
  628.     prefs.removeObserver(str, directoryServerObserver);
  629.   }
  630. }
  631.  
  632. function AddDirectorySettingsObserver()
  633. {
  634.   prefs.addObserver(currentAutocompleteDirectory, directoryServerObserver);
  635. }
  636.  
  637. function RemoveDirectorySettingsObserver(prefstring)
  638. {
  639.   prefs.removeObserver(prefstring, directoryServerObserver);
  640. }
  641.  
  642. function setupLdapAutocompleteSession()
  643. {
  644.     var autocompleteLdap = false;
  645.     var autocompleteDirectory = null;
  646.     var prevAutocompleteDirectory = currentAutocompleteDirectory;
  647.  
  648.     autocompleteLdap = prefs.GetBoolPref("ldap_2.autoComplete.useDirectory");
  649.     if (autocompleteLdap)
  650.         autocompleteDirectory = prefs.CopyCharPref(
  651.             "ldap_2.autoComplete.directoryServer");
  652.  
  653.     if(gCurrentIdentity.overrideGlobalPref) {
  654.         autocompleteDirectory = gCurrentIdentity.directoryServer;
  655.     }
  656.  
  657.     // use a temporary to do the setup so that we don't overwrite the
  658.     // global, then have some problem and throw an exception, and leave the
  659.     // global with a partially setup session.  we'll assign the temp
  660.     // into the global after we're done setting up the session
  661.     //
  662.     var LDAPSession;
  663.     if (gLDAPSession) {
  664.         LDAPSession = gLDAPSession;
  665.     } else {
  666.         LDAPSession = Components.classes[
  667.             "@mozilla.org/autocompleteSession;1?type=ldap"].createInstance()
  668.             .QueryInterface(Components.interfaces.nsILDAPAutoCompleteSession);
  669.     }
  670.             
  671.     if (autocompleteDirectory && !isOffline) { 
  672.         // Add observer on the directory server we are autocompleting against
  673.         // only if current server is different from previous.
  674.         // Remove observer if current server is different from previous       
  675.         currentAutocompleteDirectory = autocompleteDirectory;
  676.         if (prevAutocompleteDirectory) {
  677.           if (prevAutocompleteDirectory != currentAutocompleteDirectory) { 
  678.             RemoveDirectorySettingsObserver(prevAutocompleteDirectory);
  679.             AddDirectorySettingsObserver();
  680.           }
  681.         }
  682.         else
  683.           AddDirectorySettingsObserver();
  684.         
  685.         // fill in the session params if there is a session
  686.         //
  687.         if (LDAPSession) {
  688.             var serverURL = Components.classes[
  689.                 "@mozilla.org/network/ldap-url;1"].
  690.                 createInstance().QueryInterface(
  691.                     Components.interfaces.nsILDAPURL);
  692.  
  693.             try {
  694.                 serverURL.spec = prefs.CopyCharPref(autocompleteDirectory + 
  695.                                                     ".uri");
  696.             } catch (ex) {
  697.                 dump("ERROR: " + ex + "\n");
  698.             }
  699.             LDAPSession.serverURL = serverURL;
  700.  
  701.             // don't search on non-CJK strings shorter than this
  702.             //
  703.             try { 
  704.                 LDAPSession.minStringLength = prefs.GetIntPref(
  705.                     autocompleteDirectory + ".autoComplete.minStringLength");
  706.             } catch (ex) {
  707.                 // if this pref isn't there, no big deal.  just let
  708.                 // nsLDAPAutoCompleteSession use its default.
  709.             }
  710.  
  711.             // don't search on CJK strings shorter than this
  712.             //
  713.             try { 
  714.                 LDAPSession.cjkMinStringLength = prefs.GetIntPref(
  715.                   autocompleteDirectory + ".autoComplete.cjkMinStringLength");
  716.             } catch (ex) {
  717.                 // if this pref isn't there, no big deal.  just let
  718.                 // nsLDAPAutoCompleteSession use its default.
  719.             }
  720.  
  721.             // we don't try/catch here, because if this fails, we're outta luck
  722.             //
  723.             var ldapFormatter = Components.classes[
  724.                 "@mozilla.org/ldap-autocomplete-formatter;1?type=addrbook"]
  725.                 .createInstance().QueryInterface(
  726.                     Components.interfaces.nsIAbLDAPAutoCompFormatter);
  727.  
  728.             // override autocomplete name format?
  729.             //
  730.             try {
  731.                 ldapFormatter.nameFormat = 
  732.                     prefs.CopyUnicharPref(autocompleteDirectory + 
  733.                                           ".autoComplete.nameFormat");
  734.             } catch (ex) {
  735.                 // if this pref isn't there, no big deal.  just let
  736.                 // nsAbLDAPAutoCompFormatter use its default.
  737.             }
  738.  
  739.             // override autocomplete mail address format?
  740.             //
  741.             try {
  742.                 ldapFormatter.addressFormat = 
  743.                     prefs.CopyUnicharPref(autocompleteDirectory + 
  744.                                           ".autoComplete.addressFormat");
  745.             } catch (ex) {
  746.                 // if this pref isn't there, no big deal.  just let
  747.                 // nsAbLDAPAutoCompFormatter use its default.
  748.             }
  749.  
  750.             try {
  751.                 // figure out what goes in the comment column, if anything
  752.                 //
  753.                 // 0 = none
  754.                 // 1 = name of addressbook this card came from
  755.                 // 2 = other per-addressbook format
  756.                 //
  757.                 var showComments = 0;
  758.                 showComments = prefs.GetIntPref(
  759.                     "mail.autoComplete.commentColumn");
  760.  
  761.                 switch (showComments) {
  762.  
  763.                 case 1:
  764.                     // use the name of this directory
  765.                     //
  766.                     ldapFormatter.commentFormat = prefs.CopyUnicharPref(
  767.                         autocompleteDirectory + ".description");
  768.                     break;
  769.  
  770.                 case 2:
  771.                     // override ldap-specific autocomplete entry?
  772.                     //
  773.                     try {
  774.                         ldapFormatter.commentFormat = 
  775.                             prefs.CopyUnicharPref(autocompleteDirectory + 
  776.                                                 ".autoComplete.commentFormat");
  777.                 
  778.                     } catch (innerException) {
  779.                         // if nothing has been specified, use the ldap
  780.                         // organization field
  781.                         ldapFormatter.commentFormat = "[o]";
  782.                     }
  783.                     break;
  784.  
  785.                 case 0:
  786.                 default:
  787.                     // do nothing
  788.                 }
  789.             } catch (ex) {
  790.                 // if something went wrong while setting up comments, try and
  791.                 // proceed anyway
  792.             }
  793.  
  794.             // set the session's formatter, which also happens to
  795.             // force a call to the formatter's getAttributes() method
  796.             // -- which is why this needs to happen after we've set the
  797.             // various formats
  798.             //
  799.             LDAPSession.formatter = ldapFormatter;
  800.  
  801.             // override autocomplete entry formatting?
  802.             //
  803.             try {
  804.                 LDAPSession.outputFormat = 
  805.                     prefs.CopyUnicharPref(autocompleteDirectory + 
  806.                                           ".autoComplete.outputFormat");
  807.             } catch (ex) {
  808.                 // if this pref isn't there, no big deal.  just let
  809.                 // nsLDAPAutoCompleteSession use its default.
  810.             }
  811.  
  812.             // override default search filter template?
  813.             //
  814.             try { 
  815.                 LDAPSession.filterTemplate = prefs.CopyUnicharPref(
  816.                     autocompleteDirectory + ".autoComplete.filterTemplate");
  817.             } catch (ex) {
  818.                 // if this pref isn't there, no big deal.  just let
  819.                 // nsLDAPAutoCompleteSession use its default
  820.             }
  821.  
  822.             // override default maxHits (currently 100)
  823.             //
  824.             try { 
  825.                 // XXXdmose should really use .autocomplete.maxHits,
  826.                 // but there's no UI for that yet
  827.                 // 
  828.                 LDAPSession.maxHits = 
  829.                     prefs.GetIntPref(autocompleteDirectory + ".maxHits");
  830.             } catch (ex) {
  831.                 // if this pref isn't there, or is out of range, no big deal. 
  832.                 // just let nsLDAPAutoCompleteSession use its default.
  833.             }
  834.  
  835.             if (!sessionAdded) {
  836.                 // if we make it here, we know that session initialization has
  837.                 // succeeded; add the session for all recipients, and 
  838.                 // remember that we've done so
  839.                 var autoCompleteWidget;
  840.                 for (var i=1; i <= MAX_RECIPIENTS; i++)
  841.                 {
  842.                     autoCompleteWidget = document.getElementById("msgRecipient#" + i);
  843.                     if (autoCompleteWidget)
  844.                     {
  845.                       autoCompleteWidget.addSession(LDAPSession);
  846.                       // ldap searches don't insert a default entry with the default domain appended to it
  847.                       // so reduce the minimum results for a popup to 2 in this case. 
  848.                       autoCompleteWidget.minResultsForPopup = 2;
  849.  
  850.                     }
  851.                  }
  852.                 sessionAdded = true;
  853.             }
  854.         }
  855.     } else {
  856.       if (currentAutocompleteDirectory) {
  857.         // Remove observer on the directory server since we are not doing Ldap
  858.         // autocompletion.
  859.         RemoveDirectorySettingsObserver(currentAutocompleteDirectory);
  860.         currentAutocompleteDirectory = null;
  861.       }
  862.       if (gLDAPSession && sessionAdded) {
  863.         for (var i=1; i <= MAX_RECIPIENTS; i++) 
  864.           document.getElementById("msgRecipient#" + i).
  865.               removeSession(gLDAPSession);
  866.         sessionAdded = false;
  867.       }
  868.     }
  869.  
  870.     gLDAPSession = LDAPSession;
  871.     gSetupLdapAutocomplete = true;
  872. }
  873.  
  874. function DoCommandClose()
  875. {
  876.   var retVal;
  877.   if ((retVal = ComposeCanClose()))
  878.     MsgComposeCloseWindow();
  879.   return retVal;
  880. }
  881.  
  882. function DoCommandPrint()
  883. {
  884.   if (msgCompose)
  885.   {
  886.     var editorShell = msgCompose.editor;
  887.     if (editorShell)
  888.       try {
  889.         editorShell.FinishHTMLSource();
  890.         editorShell.Print();
  891.       } catch(ex) {dump("#PRINT ERROR: " + ex + "\n");}
  892.   }
  893. }
  894.  
  895. function DoCommandPreferences()
  896. {
  897.   goPreferences('messengercompose.xul', 'chrome://messenger/content/messengercompose/pref-composing_messages.xul')
  898. }
  899.  
  900. function ToggleWindowLock()
  901. {
  902.   windowLocked = !windowLocked;
  903.   CommandUpdate_MsgCompose();
  904. }
  905.  
  906. /* This function will go away soon as now arguments are passed to the window using a object of type nsMsgComposeParams instead of a string */
  907. function GetArgs(originalData)
  908. {
  909.     var args = new Object();
  910.  
  911.     if (originalData == "")
  912.       return null;
  913.  
  914.     var data = "";
  915.     var separator = String.fromCharCode(1);
  916.  
  917.     var quoteChar = "";
  918.     var prevChar = "";
  919.     var nextChar = "";
  920.     for (var i = 0; i < originalData.length; i ++, prevChar = aChar)
  921.     {
  922.         var aChar = originalData.charAt(i)
  923.         var aCharCode = originalData.charCodeAt(i)
  924.         if ( i < originalData.length - 1)
  925.             nextChar = originalData.charAt(i + 1);
  926.         else
  927.             nextChar = "";
  928.  
  929.         if (aChar == quoteChar && (nextChar == "," || nextChar == ""))
  930.         {
  931.             quoteChar = "";
  932.             data += aChar;
  933.         }
  934.         else if ((aCharCode == 39 || aCharCode == 34) && prevChar == "=") //quote or double quote
  935.         {
  936.             if (quoteChar == "")
  937.                 quoteChar = aChar;
  938.             data += aChar;
  939.         }
  940.         else if (aChar == ",")
  941.         {
  942.             if (quoteChar == "")
  943.                 data += separator;
  944.             else
  945.                 data += aChar
  946.         }
  947.         else
  948.             data += aChar
  949.     }
  950.  
  951.     var pairs = data.split(separator);
  952. //    dump("Compose: argument: {" + data + "}\n");
  953.  
  954.     for (i = pairs.length - 1; i >= 0; i--)
  955.     {
  956.         var pos = pairs[i].indexOf('=');
  957.         if (pos == -1)
  958.             continue;
  959.         var argname = pairs[i].substring(0, pos);
  960.         var argvalue = pairs[i].substring(pos + 1);
  961.         if (argvalue.charAt(0) == "'" && argvalue.charAt(argvalue.length - 1) == "'")
  962.             args[argname] = argvalue.substring(1, argvalue.length - 1);
  963.         else
  964.           try {
  965.         args[argname] = unescape(argvalue);
  966.       } catch (e) {args[argname] = argvalue;}
  967.         dump("[" + argname + "=" + args[argname] + "]\n");
  968.     }
  969.     return args;
  970. }
  971.  
  972. function ComposeFieldsReady(msgType)
  973. {
  974.   //If we are in plain text, we need to set the wrap column
  975.   if (! msgCompose.composeHTML) {
  976.     try {
  977.       window.editorShell.wrapColumn = msgCompose.wrapLength;
  978.     }
  979.     catch (e) {
  980.       dump("### window.editorShell.wrapColumn exception text: " + e + " - failed\n");
  981.     }
  982.   }
  983.   CompFields2Recipients(msgCompose.compFields, msgCompose.type);
  984.   SetComposeWindowTitle(13);
  985.   AdjustFocus();
  986. }
  987.  
  988. function ComposeStartup()
  989. {
  990.   var params = null; // New way to pass parameters to the compose window as a nsIMsgComposeParameters object
  991.   var args = null;   // old way, parameters are passed as a string
  992.   if (window.arguments && window.arguments[0]) {
  993.     try {
  994.       params = window.arguments[0].QueryInterface(Components.interfaces.nsIMsgComposeParams);
  995.     }
  996.     catch(ex) {
  997.     }
  998.     if (!params)
  999.       args = GetArgs(window.arguments[0]);
  1000.   }
  1001.  
  1002.   var identityList = document.getElementById("msgIdentity");
  1003.   var identityListPopup = document.getElementById("msgIdentityPopup");
  1004.  
  1005.   if (identityListPopup) {
  1006.     fillIdentityListPopup(identityListPopup);
  1007.   }
  1008.  
  1009.   if (!params) {
  1010.     // This code will go away soon as now arguments are passed to the window using a object of type nsMsgComposeParams instead of a string
  1011.  
  1012.     params = Components.classes["@mozilla.org/messengercompose/composeparams;1"].createInstance(Components.interfaces.nsIMsgComposeParams);
  1013.     params.composeFields = Components.classes["@mozilla.org/messengercompose/composefields;1"].createInstance(Components.interfaces.nsIMsgCompFields);
  1014.  
  1015.     if (args) { //Convert old fashion arguments into params
  1016.       var composeFields = params.composeFields;
  1017.       if (args.bodyislink == "true")
  1018.         params.bodyIsLink = true;
  1019.       if (args.type)
  1020.         params.type = args.type;
  1021.       if (args.format)
  1022.         params.format = args.format;
  1023.       if (args.originalMsg)
  1024.         params.originalMsgURI = args.originalMsg;
  1025.       if (args.preselectid)
  1026.         params.identity = getIdentityForKey(args.preselectid);
  1027.           if (args.to)
  1028.               composeFields.to = args.to;
  1029.           if (args.cc)
  1030.               composeFields.cc = args.cc;
  1031.           if (args.bcc)
  1032.               composeFields.bcc = args.bcc;
  1033.           if (args.newsgroups)
  1034.               composeFields.newsgroups = args.newsgroups;
  1035.           if (args.subject)
  1036.               composeFields.subject = args.subject;
  1037.           if (args.attachment)
  1038.               composeFields.attachments = args.attachment;
  1039.             if (args.newshost)
  1040.                 composeFields.newshost = args.newshost;
  1041.             if (args.body)
  1042.          composeFields.body = args.body;
  1043.     }
  1044.   }
  1045.  
  1046.   if (!params.identity) {
  1047.     // no pre selected identity, so use the default account
  1048.     var identities = accountManager.defaultAccount.identities;
  1049.     if (identities.Count() >= 1)
  1050.       params.identity = identities.QueryElementAt(0, Components.interfaces.nsIMsgIdentity);
  1051.     else
  1052.     {
  1053.       identities = GetIdentities();
  1054.       params.identity = identities[0];
  1055.     }
  1056.   }
  1057.  
  1058.   for (i = 0; i < identityListPopup.childNodes.length;i++) {
  1059.     var item = identityListPopup.childNodes[i];
  1060.     var id = item.getAttribute('id');
  1061.     if (id == params.identity.key) {
  1062.         identityList.selectedItem = item;
  1063.         break;
  1064.     }
  1065.   }
  1066.   LoadIdentity(true);
  1067.     if (msgComposeService)
  1068.     {
  1069.         msgCompose = msgComposeService.InitCompose(window, params);
  1070.         if (msgCompose)
  1071.         {
  1072.             //Creating a Editor Shell
  1073.             var editorElement = document.getElementById("content-frame");
  1074.             if (!editorElement)
  1075.             {
  1076.                 dump("Failed to get editor element!\n");
  1077.                 return;
  1078.             }
  1079.             var editorShell = editorElement.editorShell;
  1080.             if (!editorShell)
  1081.             {
  1082.                 dump("Failed to create editorShell!\n");
  1083.                 return;
  1084.             }
  1085.  
  1086.             // save the editorShell in the window. The editor JS expects to find it there.
  1087.             window.editorShell = editorShell;
  1088. //            dump("Created editorShell\n");
  1089.  
  1090.             // setEditorType MUST be call before setContentWindow
  1091.             if (msgCompose.composeHTML)
  1092.             {
  1093.                 window.editorShell.editorType = "htmlmail";
  1094.             }
  1095.             else
  1096.             {
  1097.             //Remove HTML toolbar, format and insert menus as we are editing in plain text mode
  1098.         document.getElementById("outputFormatMenu").setAttribute("hidden", true);
  1099.         document.getElementById("FormatToolbar").setAttribute("hidden", true);
  1100.         document.getElementById("formatMenu").setAttribute("hidden", true);
  1101.         document.getElementById("insertMenu").setAttribute("hidden", true);
  1102.         document.getElementById("menu_showFormatToolbar").setAttribute("hidden", true);
  1103.  
  1104.                 window.editorShell.editorType = "textmail";
  1105. //                dump("editor initialized in PLAIN TEXT mode\n");
  1106.             }
  1107.             window.editorShell.webShellWindow = window;
  1108.             window.editorShell.contentWindow = window._content;
  1109.  
  1110.             // Do setup common to Message Composer and Web Composer
  1111.             EditorSharedStartup();
  1112.  
  1113.         var msgCompFields = msgCompose.compFields;
  1114.         if (msgCompFields)
  1115.         {
  1116.         if (params.bodyIsLink)
  1117.         {
  1118.           var body = msgCompFields.body;
  1119.           if (msgCompose.composeHTML)
  1120.           {
  1121.             var cleanBody;
  1122.             try {
  1123.               cleanBody = unescape(body);
  1124.             } catch(e) { cleanBody = body;}
  1125.  
  1126.             msgCompFields.body = "<BR><A HREF=\"" + body + "\">" + cleanBody + "</A><BR>";
  1127.           }
  1128.           else
  1129.             msgCompFields.body = "\n<" + body + ">\n";
  1130.         }
  1131.  
  1132.                 var subjectValue = msgCompFields.subject;
  1133.                 if (subjectValue != "") {
  1134.                     document.getElementById("msgSubject").value = subjectValue;
  1135.                 }
  1136.  
  1137.         var attachmentValue = msgCompFields.attachments;
  1138.         if (attachmentValue != "") {
  1139.            var atts =  attachmentValue.split(",");
  1140.             for (var i=0; i < atts.length; i++)
  1141.                 AddAttachment(atts[i], null);
  1142.         }
  1143.             }
  1144.  
  1145.             // Now that we have an Editor AppCore, we can finish to initialize the Compose AppCore
  1146.             msgCompose.editor = window.editorShell;
  1147.  
  1148.             msgCompose.RegisterStateListener(stateListener);
  1149.  
  1150.  
  1151.         }
  1152.     }
  1153. }
  1154. function WizCallback(state)
  1155. {
  1156.     if (state){
  1157.         ComposeStartup();
  1158.     }
  1159.     else
  1160.     {
  1161.         if (msgCompose)
  1162.           msgCompose.CloseWindow();
  1163.         else
  1164.           window.close();
  1165. //    window.tryToClose=ComposeCanClose;
  1166.     }
  1167. }
  1168.  
  1169. function ComposeLoad()
  1170. {
  1171.   AddMessageComposeOfflineObserver();
  1172.   AddDirectoryServerObserver(true);
  1173.  
  1174.   if (DEBUG && msgComposeService)
  1175.     msgComposeService.TimeStamp("Start Initializing the compose window (ComposeLoad)", false);
  1176.   gComposeMsgsBundle = document.getElementById("bundle_composeMsgs");
  1177.  
  1178.   try {
  1179.     SetupCommandUpdateHandlers();
  1180.     var wizardcallback = true;
  1181.     var state =    verifyAccounts(wizardcallback);    // this will do migration, or create a new account if we need to.
  1182.  
  1183.     if (other_header != "") {
  1184.       var selectNode = document.getElementById('msgRecipientType#1');
  1185.       selectNode = selectNode.childNodes[0];
  1186.       var opt = document.createElement('menuitem');
  1187.       opt.setAttribute("value", "addr_other");
  1188.       opt.setAttribute("label", other_header + ":");
  1189.       selectNode.appendChild(opt);
  1190.     }
  1191.     if (state)
  1192.       ComposeStartup();
  1193.   }
  1194.   catch (ex) {
  1195.     var errorTitle = gComposeMsgsBundle.getString("initErrorDlogTitle");
  1196.     var errorMsg = gComposeMsgsBundle.getFormattedString("initErrorDlogMessage",
  1197.                                                          [ex]);
  1198.     if (!gPromptService) {
  1199.       gPromptService = Components.classes["@mozilla.org/embedcomp/prompt-service;1"].getService();
  1200.       gPromptService = gPromptService.QueryInterface(Components.interfaces.nsIPromptService);
  1201.     }
  1202.     if (gPromptService)
  1203.       gPromptService.alert(window, errorTitle, errorMsg);
  1204.     else
  1205.       window.alert(errorMsg);
  1206.  
  1207.     if (msgCompose)
  1208.       msgCompose.CloseWindow();
  1209.     else
  1210.       window.close();
  1211.     return;
  1212.   }
  1213.   window.tryToClose=ComposeCanClose;
  1214.   if (DEBUG && msgComposeService)
  1215.     msgComposeService.TimeStamp("Done with the initialization (ComposeLoad). Waiting on editor to load about::blank", false);
  1216. }
  1217.  
  1218. function ComposeUnload()
  1219. {
  1220.     dump("\nComposeUnload from XUL\n");
  1221.     RemoveMessageComposeOfflineObserver();
  1222.     RemoveDirectoryServerObserver(null);
  1223.     RemoveDirectoryServerObserver("mail.identity." + gCurrentIdentity.key);
  1224.     if (currentAutocompleteDirectory)
  1225.        RemoveDirectorySettingsObserver(currentAutocompleteDirectory);
  1226.     msgCompose.UnregisterStateListener(stateListener);
  1227. }
  1228.  
  1229. function SetDocumentCharacterSet(aCharset)
  1230. {
  1231.   dump("SetDocumentCharacterSet Callback!\n");
  1232.   dump(aCharset + "\n");
  1233.  
  1234.   if (msgCompose) {
  1235.     msgCompose.SetDocumentCharset(aCharset);
  1236.     g_currentMailSendCharset = aCharset;
  1237.     g_charsetTitle = null;
  1238.     SetComposeWindowTitle(13);
  1239.   }
  1240.   else
  1241.     dump("Compose has not been created!\n");
  1242. }
  1243.  
  1244. function UpdateMailEditCharset()
  1245. {
  1246.   var send_default_charset = prefs.getLocalizedUnicharPref("mailnews.send_default_charset");
  1247. //  dump("send_default_charset is " + send_default_charset + "\n");
  1248.  
  1249.   var compFieldsCharset = msgCompose.compFields.characterSet;
  1250. //  dump("msgCompose.compFields is " + compFieldsCharset + "\n");
  1251.  
  1252.   if (g_charsetConvertManager) {
  1253.     var charsetAtom = g_charsetConvertManager.GetCharsetAtom(compFieldsCharset);
  1254.     if (charsetAtom && (charsetAtom.GetUnicode() == "us-ascii"))
  1255.       compFieldsCharset = "ISO-8859-1";   // no menu item for "us-ascii"
  1256.   }
  1257.  
  1258.   // charset may have been set implicitly in case of reply/forward
  1259.   // or use pref default otherwise
  1260.   var menuitem = document.getElementById(send_default_charset == compFieldsCharset ? 
  1261.                                          send_default_charset : compFieldsCharset);
  1262.   if (menuitem)
  1263.     menuitem.setAttribute('checked', 'true');
  1264.  
  1265.   // Set a document charset to a default mail send charset.
  1266.   if (send_default_charset == compFieldsCharset)
  1267.     SetDocumentCharacterSet(send_default_charset);
  1268. }
  1269.  
  1270. function InitCharsetMenuCheckMark()
  1271. {
  1272.   // return if the charset is already set explitily
  1273.   if (g_currentMailSendCharset != null) {
  1274.     dump("already set to " + g_currentMailSendCharset + "\n");
  1275.     return;
  1276.   }
  1277.  
  1278.   // Check the menu
  1279.   UpdateMailEditCharset();
  1280.   // use setTimeout workaround to delay checkmark the menu
  1281.   // when onmenucomplete is ready then use it instead of oncreate
  1282.   // see bug 78290 for the detail
  1283.   setTimeout("UpdateMailEditCharset()", 0);
  1284.  
  1285. }
  1286.  
  1287. function GetCharsetUIString()
  1288. {
  1289.   var charset = msgCompose.compFields.characterSet;
  1290.   if (g_send_default_charset == null) {
  1291.     g_send_default_charset = prefs.getLocalizedUnicharPref("mailnews.send_default_charset");
  1292.   }
  1293.  
  1294.   charset = charset.toUpperCase();
  1295.   if (charset == "US-ASCII")
  1296.     charset = "ISO-8859-1";
  1297.  
  1298.   if (charset != g_send_default_charset) {
  1299.  
  1300.     if (g_charsetTitle == null) {
  1301.       try {
  1302.         // check if we have a converter for this charset
  1303.         var charsetAtom = g_charsetConvertManager.GetCharsetAtom(charset);
  1304.         var encoderList = g_charsetConvertManager.GetEncoderList();
  1305.         var n = encoderList.Count();
  1306.         var found = false;
  1307.         for (var i = 0; i < n; i++)
  1308.         {
  1309.           if (charsetAtom == encoderList.GetElementAt(i))
  1310.           {
  1311.             found = true;
  1312.             break;
  1313.           }
  1314.         }
  1315.         if (!found)
  1316.         {
  1317.           dump("no charset converter available for " +  charset + " default charset is used instead\n");
  1318.           // set to default charset, no need to show it in the window title
  1319.           msgCompose.compFields.characterSet = g_send_default_charset;
  1320.           return "";
  1321.         }
  1322.  
  1323.         // get a localized string
  1324.         g_charsetTitle = g_charsetConvertManager.GetCharsetTitle(charsetAtom);
  1325.       }
  1326.       catch (ex) {
  1327.         dump("failed to get a charset title of " + charset + "!\n");
  1328.         g_charsetTitle = charset; // just show the charset itself
  1329.       }
  1330.     }
  1331.  
  1332.     return " - " + g_charsetTitle;
  1333.   }
  1334.  
  1335.   return "";
  1336. }
  1337.  
  1338. function GenericSendMessage( msgType )
  1339. {
  1340.     dump("GenericSendMessage from XUL\n");
  1341.  
  1342.   dump("Identity = " + getCurrentIdentity() + "\n");
  1343.  
  1344.     if (msgCompose != null)
  1345.     {
  1346.         var msgCompFields = msgCompose.compFields;
  1347.         if (msgCompFields)
  1348.         {
  1349.             Recipients2CompFields(msgCompFields);
  1350.             var subject = document.getElementById("msgSubject").value;
  1351.             msgCompFields.subject = subject;
  1352.             dump("attachments = " + GenerateAttachmentsString() + "\n");
  1353.             try {
  1354.                 msgCompFields.attachments = GenerateAttachmentsString();
  1355.             }
  1356.             catch (ex) {
  1357.                 dump("failed to SetAttachments\n");
  1358.             }
  1359.  
  1360.             if (msgType == msgCompDeliverMode.Now || msgType == msgCompDeliverMode.Later)
  1361.             {
  1362.               //Do we need to check the spelling?
  1363.         if (prefs.GetBoolPref("mail.SpellCheckBeforeSend"))
  1364.             goDoCommand('cmd_spelling');
  1365.  
  1366.                 //Check if we have a subject, else ask user for confirmation
  1367.                 if (subject == "")
  1368.                 {
  1369.                 if (!gPromptService) {
  1370.                   gPromptService = Components.classes["@mozilla.org/embedcomp/prompt-service;1"].getService();
  1371.                                   gPromptService = gPromptService.QueryInterface(Components.interfaces.nsIPromptService);
  1372.                                 }
  1373.                     if (gPromptService)
  1374.                     {
  1375.                         var result = {value:gComposeMsgsBundle.getString("defaultSubject")};
  1376.                         if (gPromptService.prompt(
  1377.                             window,
  1378.                             gComposeMsgsBundle.getString("subjectDlogTitle"),
  1379.                             gComposeMsgsBundle.getString("subjectDlogMessage"),
  1380.                             result,
  1381.                             null,
  1382.                             {value:0}
  1383.                             ))
  1384.                         {
  1385.                             msgCompFields.subject = result.value;
  1386.                             var subjectInputElem = document.getElementById("msgSubject");
  1387.                             subjectInputElem.value = result.value;
  1388.                         }
  1389.                         else
  1390.                           return;
  1391.                     }
  1392.                 }
  1393.  
  1394.                 // Before sending the message, check what to do with HTML message, eventually abort.
  1395.         var convert = DetermineConvertibility();
  1396.         var action = DetermineHTMLAction(convert);
  1397.         if (action == msgCompSendFormat.AskUser)
  1398.                 {
  1399.                     var recommAction = convert == msgCompConvertible.No
  1400.                                    ? msgCompSendFormat.AskUser
  1401.                                    : msgCompSendFormat.PlainText;
  1402.                     var result2 = {action:recommAction,
  1403.                                   convertible:convert,
  1404.                                   abort:false};
  1405.                     window.openDialog("chrome://messenger/content/messengercompose/askSendFormat.xul",
  1406.                                       "askSendFormatDialog", "chrome,modal,titlebar,centerscreen",
  1407.                                       result2);
  1408.                     if (result2.abort)
  1409.                         return;
  1410.                     action = result2.action;
  1411.                 }
  1412.                 switch (action)
  1413.                 {
  1414.                     case msgCompSendFormat.PlainText:
  1415.                         msgCompFields.forcePlainText = true;
  1416.                         msgCompFields.useMultipartAlternative = false;
  1417.                         break;
  1418.                     case msgCompSendFormat.HTML:
  1419.                         msgCompFields.forcePlainText = false;
  1420.                         msgCompFields.useMultipartAlternative = false;
  1421.                         break;
  1422.                     case msgCompSendFormat.Both:
  1423.                         msgCompFields.forcePlainText = false;
  1424.                         msgCompFields.useMultipartAlternative = true;
  1425.                         break;
  1426.                    default: dump("\###SendMessage Error: invalid action value\n"); return;
  1427.                 }
  1428.             }
  1429.             try {
  1430.         windowLocked = true;
  1431.         CommandUpdate_MsgCompose();
  1432.         disableEditableFields();
  1433.  
  1434.         var progress = Components.classes["@mozilla.org/messenger/progress;1"].createInstance(Components.interfaces.nsIMsgProgress);
  1435.         if (progress)
  1436.         {
  1437.           progress.registerListener(progressListener);
  1438.           sendOrSaveOperationInProgress = true;
  1439.         }
  1440.                 msgCompose.SendMsg(msgType, getCurrentIdentity(), progress);
  1441.             }
  1442.             catch (ex) {
  1443.         dump("failed to SendMsg: " + ex + "\n");
  1444.         windowLocked = false;
  1445.         enableEditableFields();
  1446.         CommandUpdate_MsgCompose();
  1447.             }
  1448.         }
  1449.     }
  1450.     else
  1451.         dump("###SendMessage Error: composeAppCore is null!\n");
  1452. }
  1453.  
  1454. function SendMessage()
  1455. {
  1456.     dump("SendMessage from XUL\n");
  1457.   // 0 = nsMsgDeliverNow
  1458.   // RICHIE: We should really have a way of using constants and not
  1459.   // hardcoded numbers for the first argument
  1460.     GenericSendMessage(msgCompDeliverMode.Now);
  1461. }
  1462.  
  1463. function SendMessageLater()
  1464. {
  1465.     dump("SendMessageLater from XUL\n");
  1466.   // 1 = nsMsgQueueForLater
  1467.   // RICHIE: We should really have a way of using constants and not
  1468.   // hardcoded numbers for the first argument
  1469.     GenericSendMessage(msgCompDeliverMode.Later);
  1470. }
  1471.  
  1472. function Save()
  1473. {
  1474.     dump("Save from XUL\n");
  1475.     switch (defaultSaveOperation)
  1476.     {
  1477.       case "file"     : SaveAsFile(false);      break;
  1478.       case "template" : SaveAsTemplate(false);  break;
  1479.       default         : SaveAsDraft(false);     break;
  1480.     }
  1481. }
  1482.  
  1483. function SaveAsFile(saveAs)
  1484. {
  1485.     dump("SaveAsFile from XUL\n");
  1486.   if (msgCompose.bodyConvertible() == msgCompConvertible.Plain)
  1487.       editorShell.saveDocument(saveAs, false, "text/plain");
  1488.   else
  1489.       editorShell.saveDocument(saveAs, false, "text/html");
  1490.   defaultSaveOperation = "file";
  1491. }
  1492.  
  1493. function SaveAsDraft()
  1494. {
  1495.     dump("SaveAsDraft from XUL\n");
  1496.  
  1497.   // 4 = nsMsgSaveAsDraft
  1498.   // RICHIE: We should really have a way of using constants and not
  1499.   // hardcoded numbers for the first argument
  1500.   GenericSendMessage(msgCompDeliverMode.SaveAsDraft);
  1501.   defaultSaveOperation = "draft";
  1502. }
  1503.  
  1504. function SaveAsTemplate()
  1505. {
  1506.     dump("SaveAsTemplate from XUL\n");
  1507.  
  1508.   // 5 = nsMsgSaveAsTemplate
  1509.   // RICHIE: We should really have a way of using constants and not
  1510.   // hardcoded numbers for the first argument
  1511.   GenericSendMessage(msgCompDeliverMode.SaveAsTemplate);
  1512.   defaultSaveOperation = "template";
  1513. }
  1514.  
  1515.  
  1516. function MessageFcc(menuItem)
  1517. {
  1518.     // Get the id for the folder we're FCC into
  1519.   // This is the additional FCC in addition to the
  1520.   // default FCC
  1521.     destUri = menuItem.getAttribute('id');
  1522.     if (msgCompose)
  1523.     {
  1524.         var msgCompFields = msgCompose.compFields;
  1525.         if (msgCompFields)
  1526.         {
  1527.             if (msgCompFields.fcc2 == destUri)
  1528.             {
  1529.                 msgCompFields.fcc2 = "nocopy://";
  1530.                 dump("FCC2: none\n");
  1531.             }
  1532.             else
  1533.             {
  1534.                 msgCompFields.fcc2 = destUri;
  1535.                 dump("FCC2: " + destUri + "\n");
  1536.             }
  1537.         }
  1538.     }
  1539. }
  1540.  
  1541. function PriorityMenuSelect(target)
  1542. {
  1543.     dump("Set Message Priority to " + target.getAttribute('id') + "\n");
  1544.     if (msgCompose)
  1545.     {
  1546.         var msgCompFields = msgCompose.compFields;
  1547.         if (msgCompFields)
  1548.             msgCompFields.priority = target.getAttribute('id');
  1549.     }
  1550. }
  1551.  
  1552. function ReturnReceiptMenuSelect()
  1553. {
  1554.     if (msgCompose)
  1555.     {
  1556.         var msgCompFields = msgCompose.compFields;
  1557.         if (msgCompFields)
  1558.         {
  1559.             if (msgCompFields.returnReceipt)
  1560.             {
  1561.                 msgCompFields.returnReceipt = false;
  1562.             }
  1563.             else
  1564.             {
  1565.                 msgCompFields.returnReceipt = true;
  1566.             }
  1567.         }
  1568.     }
  1569. }
  1570.  
  1571. function OutputFormatMenuSelect(target)
  1572. {
  1573.     dump("Set Message Format to " + target.getAttribute('id') + "\n");
  1574.     if (msgCompose)
  1575.     {
  1576.         var msgCompFields = msgCompose.compFields;
  1577.  
  1578.         if (msgCompFields)
  1579.         {
  1580.             switch (target.getAttribute('id'))
  1581.             {
  1582.                 case "1": sendFormat = msgCompSendFormat.AskUser;     break;
  1583.                 case "2": sendFormat = msgCompSendFormat.PlainText;   break;
  1584.                 case "3": sendFormat = msgCompSendFormat.HTML;        break;
  1585.             case "4": sendFormat = msgCompSendFormat.Both;        break;
  1586.             }
  1587.         }
  1588.     }
  1589. }
  1590.  
  1591. function SelectAddress()
  1592. {
  1593.     var msgCompFields = msgCompose.compFields;
  1594.  
  1595.     Recipients2CompFields(msgCompFields);
  1596.  
  1597.     var toAddress = msgCompFields.to;
  1598.     var ccAddress = msgCompFields.cc;
  1599.     var bccAddress = msgCompFields.bcc;
  1600.  
  1601.     dump("toAddress: " + toAddress + "\n");
  1602.     window.openDialog("chrome://messenger/content/addressbook/abSelectAddressesDialog.xul",
  1603.                       "",
  1604.                       "chrome,resizable,titlebar,modal",
  1605.                       {composeWindow:top.window,
  1606.                        msgCompFields:msgCompFields,
  1607.                        toAddress:toAddress,
  1608.                        ccAddress:ccAddress,
  1609.                        bccAddress:bccAddress});
  1610.   // We have to set focus to the addressingwidget because we seem to loose focus often 
  1611.   // after opening the SelectAddresses Dialog- bug # 89950
  1612.   AdjustFocus();
  1613. }
  1614.  
  1615. function queryISupportsArray(supportsArray, iid) {
  1616.     var result = new Array;
  1617.     for (var i=0; i<supportsArray.Count(); i++) {
  1618.       // dump(i + "," + result[i] + "\n");
  1619.       result[i] = supportsArray.GetElementAt(i).QueryInterface(iid);
  1620.     }
  1621.     return result;
  1622. }
  1623.  
  1624. function GetIdentities()
  1625. {
  1626.  
  1627.     var idSupports = accountManager.allIdentities;
  1628.     var identities = queryISupportsArray(idSupports,
  1629.                                          Components.interfaces.nsIMsgIdentity);
  1630.  
  1631.     dump(identities + "\n");
  1632.     return identities;
  1633. }
  1634.  
  1635. function fillIdentityListPopup(popup)
  1636. {
  1637.     var identities = GetIdentities();
  1638.  
  1639.     for (var i=0; i<identities.length; i++)
  1640.     {
  1641.         var identity = identities[i];
  1642.  
  1643.         //dump(i + " = " + identity.identityName + "," +identity.key + "\n");
  1644.  
  1645.         //Get server prettyName for each identity
  1646.  
  1647.         var serverSupports = accountManager.GetServersForIdentity(identity);
  1648.  
  1649.         //dump(i + " = " + identity.identityName + "," +identity.key + "\n");
  1650.  
  1651.         if(serverSupports.GetElementAt(0))
  1652.             var    result = serverSupports.GetElementAt(0).QueryInterface(Components.interfaces.nsIMsgIncomingServer);
  1653.         //dump ("The account name is = "+result.prettyName+ "\n");
  1654.         var accountName = " - "+result.prettyName;
  1655.  
  1656.         var item=document.createElement('menuitem');
  1657.         item.setAttribute('label', identity.identityName);
  1658.         item.setAttribute('class', 'identity-popup-item');
  1659.         item.setAttribute('accountname', accountName);
  1660.         item.setAttribute('id', identity.key);
  1661.         popup.appendChild(item);
  1662.     }
  1663. }
  1664.  
  1665. function getCurrentIdentity()
  1666. {
  1667.     // fill in Identity combobox
  1668.     var identityList = document.getElementById("msgIdentity");
  1669.  
  1670.     var item = identityList.selectedItem;
  1671.     var identityKey = item.getAttribute('id');
  1672.  
  1673.     //dump("Looking for identity " + identityKey + "\n");
  1674.     var identity = accountManager.getIdentity(identityKey);
  1675.  
  1676.     return identity;
  1677. }
  1678.  
  1679. function getIdentityForKey(key)
  1680. {
  1681.     return accountManager.getIdentity(key);
  1682. }
  1683.  
  1684. function AdjustFocus()
  1685. {
  1686.     var element = document.getElementById("msgRecipient#" + awGetNumberOfRecipients());
  1687.     if (element.value == "")
  1688.     {
  1689.         dump("set focus on the recipient\n");
  1690.         awSetFocus(awGetNumberOfRecipients(), element);
  1691.     }
  1692.     else
  1693.     {
  1694.         element = document.getElementById("msgSubject");
  1695.         if (element.value == "")
  1696.         {
  1697.             dump("set focus on the subject\n");
  1698.             element.focus();
  1699.         }
  1700.         else
  1701.         {
  1702.             dump("set focus on the body\n");
  1703.             editorShell.contentWindow.focus();
  1704.         }
  1705.     }
  1706. }
  1707.  
  1708. function SetComposeWindowTitle(event)
  1709. {
  1710.     /* dump("event = " + event + "\n"); */
  1711.  
  1712.     /* only set the title when they hit return (or tab?)
  1713.      */
  1714.  
  1715.     var newTitle = document.getElementById('msgSubject').value;
  1716.  
  1717.     /* dump("newTitle = " + newTitle + "\n"); */
  1718.  
  1719.     if (newTitle == "" ) {
  1720.         newTitle = gComposeMsgsBundle.getString("defaultSubject");
  1721.     }
  1722.  
  1723.     newTitle += GetCharsetUIString();
  1724.  
  1725.     window.title = gComposeMsgsBundle.getString("windowTitlePrefix") + " " + newTitle;
  1726. }
  1727.  
  1728. // Check for changes to document and allow saving before closing
  1729. // This is hooked up to the OS's window close widget (e.g., "X" for Windows)
  1730. function ComposeCanClose()
  1731. {
  1732.   if (!gPromptService) {
  1733.     gPromptService = Components.classes["@mozilla.org/embedcomp/prompt-service;1"].getService();
  1734.     gPromptService = gPromptService.QueryInterface(Components.interfaces.nsIPromptService);
  1735.   }
  1736.   if (sendOrSaveOperationInProgress)
  1737.   {
  1738.  
  1739.       if (gPromptService)
  1740.       {
  1741.         var promptTitle = gComposeMsgsBundle.getString("quitComposeWindowTitle");
  1742.         var promptMsg = gComposeMsgsBundle.getString("quitComposeWindowMessage");
  1743.         var quitButtonLabel = gComposeMsgsBundle.getString("quitComposeWindowQuitButtonLabel");
  1744.         var waitButtonLabel = gComposeMsgsBundle.getString("quitComposeWindowWaitButtonLabel");
  1745.  
  1746.         var result = {value:0};
  1747.         gPromptService.confirmEx(window, promptTitle, promptMsg,
  1748.           (gPromptService.BUTTON_TITLE_IS_STRING*gPromptService.BUTTON_POS_0) +
  1749.           (gPromptService.BUTTON_TITLE_IS_STRING*gPromptService.BUTTON_POS_1),
  1750.           waitButtonLabel, quitButtonLabel, null, null, {value:0}, result);
  1751.  
  1752.         if (result.value == 1)
  1753.           {
  1754.             msgCompose.abort();
  1755.             return true;
  1756.           }
  1757.         else 
  1758.           {
  1759.             return false;
  1760.           }
  1761.       }
  1762.   }
  1763.     // Returns FALSE only if user cancels save action
  1764.     if (contentChanged || msgCompose.bodyModified)
  1765.     {
  1766.         // call window.focus, since we need to pop up a dialog
  1767.         // and therefore need to be visible (to prevent user confusion)
  1768.         window.focus();
  1769.         if (gPromptService)
  1770.         {
  1771.             var result = {value:0};
  1772.             gPromptService.confirmEx(window,
  1773.                               gComposeMsgsBundle.getString("saveDlogTitle"),
  1774.                               gComposeMsgsBundle.getString("saveDlogMessage"),
  1775.                               (gPromptService.BUTTON_TITLE_SAVE * gPromptService.BUTTON_POS_0) +
  1776.                               (gPromptService.BUTTON_TITLE_CANCEL * gPromptService.BUTTON_POS_1) +
  1777.                               (gPromptService.BUTTON_TITLE_DONT_SAVE * gPromptService.BUTTON_POS_2),
  1778.                               null, null, null,
  1779.                               null, {value:0}, result);
  1780.  
  1781.             if (result)
  1782.             {
  1783.                 switch (result.value)
  1784.                 {
  1785.                     case 0: //Save
  1786.                         if (LastToClose())
  1787.                             NotifyQuitApplication();
  1788.                         SaveAsDraft();
  1789.                         break;
  1790.                     case 1:    //Cancel
  1791.                         return false;
  1792.                     case 2:    //Don't Save
  1793.                         break;
  1794.                 }
  1795.             }
  1796.         }
  1797.  
  1798.         msgCompose.bodyModified = false;
  1799.         contentChanged = false;
  1800.     }
  1801.  
  1802.     return true;
  1803. }
  1804.  
  1805. function MsgComposeCloseWindow()
  1806. {
  1807.     if (msgCompose)
  1808.         msgCompose.CloseWindow();
  1809. }
  1810.  
  1811. function AttachFile()
  1812. {
  1813. //  dump("AttachFile()\n");
  1814.     currentAttachment = "";
  1815.     //Get file using nsIFilePicker and convert to URL
  1816.     try {
  1817.             var fp = Components.classes["@mozilla.org/filepicker;1"].createInstance(nsIFilePicker);
  1818.             fp.init(window, gComposeMsgsBundle.getString("chooseFileToAttach"), nsIFilePicker.modeOpen);
  1819.             fp.appendFilters(nsIFilePicker.filterAll);
  1820.             if (fp.show() == nsIFilePicker.returnOK) {
  1821.             currentAttachment = fp.fileURL.spec;
  1822.             dump("nsIFilePicker - "+currentAttachment+"\n");
  1823.             }
  1824.     }
  1825.     catch (ex) {
  1826.         dump("failed to get the local file to attach\n");
  1827.     }
  1828.   if (!(DuplicateFileCheck(currentAttachment)))
  1829.       AddAttachment(currentAttachment, null);
  1830.   else
  1831.   {
  1832.     dump("###ERROR ADDING DUPLICATE FILE \n");
  1833.     var errorTitle = gComposeMsgsBundle.getString("DuplicateFileErrorDlogTitle");
  1834.     var errorMsg = gComposeMsgsBundle.getString("DuplicateFileErrorDlogMessage");
  1835.     if (!gPromptService) {
  1836.       gPromptService = Components.classes["@mozilla.org/embedcomp/prompt-service;1"].getService();
  1837.       gPromptService = gPromptService.QueryInterface(Components.interfaces.nsIPromptService);
  1838.     }
  1839.     if (gPromptService)
  1840.       gPromptService.alert(window, errorTitle, errorMsg);
  1841.     else
  1842.       window.alert(errorMsg);
  1843.   }
  1844.  
  1845. }
  1846.  
  1847. function AddAttachment(attachment, prettyName)
  1848. {
  1849.     if (attachment && (attachment != ""))
  1850.     {
  1851.         var bucketBody = document.getElementById("bucketBody");
  1852.         var item = document.createElement("treeitem");
  1853.         var row = document.createElement("treerow");
  1854.         var cell = document.createElement("treecell");
  1855.  
  1856.         if (msgCompose && !prettyName)
  1857.             prettyName = msgCompose.AttachmentPrettyName(attachment);
  1858.         cell.setAttribute("label", prettyName);                //use for display only
  1859.         cell.setAttribute("attachment", attachment);        //full url stored here
  1860.         cell.setAttribute("tooltip", "aTooltip");
  1861.         try {
  1862.             cell.setAttribute("tooltiptext", unescape(attachment));
  1863.         }
  1864.         catch(e) {cell.setAttribute("tooltiptext", attachment);}
  1865.     cell.setAttribute("class", "treecell-iconic");
  1866.     cell.setAttribute('src', "moz-icon:" + attachment);
  1867.         row.appendChild(cell);
  1868.         item.appendChild(row);
  1869.         bucketBody.appendChild(item);
  1870.     }
  1871. }
  1872.  
  1873. function AttachPage()
  1874. {
  1875.      if (!gPromptService) {
  1876.        gPromptService = Components.classes["@mozilla.org/embedcomp/prompt-service;1"].getService();
  1877.        gPromptService = gPromptService.QueryInterface(Components.interfaces.nsIPromptService);
  1878.      }
  1879.      
  1880.      if (gPromptService)
  1881.      {
  1882.         var result = {value:"http://"};
  1883.         if (gPromptService.prompt(
  1884.             window,
  1885.             gComposeMsgsBundle.getString("attachPageDlogTitle"),
  1886.             gComposeMsgsBundle.getString("attachPageDlogMessage"),
  1887.             result,
  1888.             null,
  1889.             {value:0}))
  1890.         {
  1891.             AddAttachment(result.value, null);
  1892.         }
  1893.      }
  1894. }
  1895. function DuplicateFileCheck(FileUrl)
  1896. {
  1897.     var body = document.getElementById('bucketBody');
  1898.     var item, row, cell, text, colon;
  1899.  
  1900.     for (var index = 0; index < body.childNodes.length; index++)
  1901.     {
  1902.         item = body.childNodes[index];
  1903.         if (item.childNodes && item.childNodes.length)
  1904.         {
  1905.             row = item.childNodes[0];
  1906.             if (row.childNodes &&  row.childNodes.length)
  1907.             {
  1908.                 cell = row.childNodes[0];
  1909.                 if (cell)
  1910.                 {
  1911.                     text = cell.getAttribute("attachment");
  1912.                     if (text.length)
  1913.                     {
  1914.             if (FileUrl == text)
  1915.                return true;
  1916.           }
  1917.                 }
  1918.             }
  1919.         }
  1920.     }
  1921.  
  1922.     return false;
  1923. }
  1924.  
  1925. function GenerateAttachmentsString()
  1926. {
  1927.     var attachments = "";
  1928.     var body = document.getElementById('bucketBody');
  1929.     var item, row, cell, text, colon;
  1930.  
  1931.     for (var index = 0; index < body.childNodes.length; index++)
  1932.     {
  1933.         item = body.childNodes[index];
  1934.         if (item.childNodes && item.childNodes.length)
  1935.         {
  1936.             row = item.childNodes[0];
  1937.             if (row.childNodes &&  row.childNodes.length)
  1938.             {
  1939.                 cell = row.childNodes[0];
  1940.                 if (cell)
  1941.                 {
  1942.                     text = cell.getAttribute("attachment");
  1943.                     if (text.length)
  1944.                     {
  1945.             text = text.replace(/\,/g, "%2C");
  1946.                         if (attachments == "")
  1947.                             attachments = text;
  1948.                         else
  1949.                             attachments = attachments + "," + text;
  1950.                     }
  1951.                 }
  1952.             }
  1953.         }
  1954.     }
  1955.  
  1956.     return attachments;
  1957. }
  1958.  
  1959. function RemoveSelectedAttachment()
  1960. {
  1961.     var bucketTree = document.getElementById("attachmentBucket");
  1962.     if ( bucketTree )
  1963.     {
  1964.         var body = document.getElementById("bucketBody");
  1965.  
  1966.         if ( body && bucketTree.selectedItems && bucketTree.selectedItems.length )
  1967.         {
  1968.             for ( var item = bucketTree.selectedItems.length - 1; item >= 0; item-- )
  1969.                 body.removeChild(bucketTree.selectedItems[item]);
  1970.         }
  1971.     }
  1972.  
  1973. }
  1974.  
  1975. function AttachVCard()
  1976. {
  1977.     dump("AttachVCard()\n");
  1978. }
  1979.  
  1980. function DetermineHTMLAction(convertible)
  1981. {
  1982.     if (! msgCompose.composeHTML)
  1983.     {
  1984.         try {
  1985.             var obj = new Object;
  1986.             msgCompose.CheckAndPopulateRecipients(true, false, obj);
  1987.         } catch(ex) { dump("msgCompose.CheckAndPopulateRecipients failed: " + ex + "\n"); }
  1988.         return msgCompSendFormat.PlainText;
  1989.     }
  1990.  
  1991.     if (sendFormat == msgCompSendFormat.AskUser)
  1992.     {
  1993.         //Well, before we ask, see if we can figure out what to do for ourselves
  1994.  
  1995.         var noHtmlRecipients;
  1996.         var noHtmlnewsgroups;
  1997.         var preferFormat;
  1998.  
  1999.         //Check the address book for the HTML property for each recipient
  2000.         try {
  2001.             var obj = new Object;
  2002.             preferFormat = msgCompose.CheckAndPopulateRecipients(true, true, obj);
  2003.             noHtmlRecipients = obj.value;
  2004.         } catch(ex)
  2005.         {
  2006.             dump("msgCompose.CheckAndPopulateRecipients failed: " + ex + "\n");
  2007.             var msgCompFields = msgCompose.compFields;
  2008.             noHtmlRecipients = msgCompFields.to + "," + msgCompFields.cc + "," + msgCompFields.bcc;
  2009.             preferFormat = abPreferMailFormat.unknown;
  2010.         }
  2011.         dump("DetermineHTMLAction: preferFormat = " + preferFormat + ", noHtmlRecipients are " + noHtmlRecipients + "\n");
  2012.  
  2013.         //Check newsgroups now...
  2014.         try {
  2015.             noHtmlnewsgroups = msgCompose.GetNoHtmlNewsgroups(null);
  2016.         } catch(ex)
  2017.         {
  2018.            noHtmlnewsgroups = msgCompose.compFields.newsgroups;
  2019.         }
  2020.  
  2021.         if (noHtmlRecipients != "" || noHtmlnewsgroups != "")
  2022.         {
  2023.             if (convertible == msgCompConvertible.Plain)
  2024.               return msgCompSendFormat.PlainText;
  2025.  
  2026.             if (noHtmlnewsgroups == "")
  2027.             {
  2028.                 switch (preferFormat)
  2029.                 {
  2030.                   case abPreferMailFormat.plaintext :
  2031.                     return msgCompSendFormat.PlainText;
  2032.  
  2033.                   default :
  2034.                     //See if a preference has been set to tell us what to do. Note that we do not honor that
  2035.                     //preference for newsgroups. Only for e-mail addresses.
  2036.                     var action = prefs.GetIntPref("mail.default_html_action");
  2037.                     switch (action)
  2038.                     {
  2039.                         case msgCompSendFormat.PlainText    :
  2040.                         case msgCompSendFormat.HTML         :
  2041.                         case msgCompSendFormat.Both         :
  2042.                             return action;
  2043.                     }
  2044.                 }
  2045.             }
  2046.             return msgCompSendFormat.AskUser;
  2047.         }
  2048.         else
  2049.             return msgCompSendFormat.HTML;
  2050.     }
  2051.       else
  2052.       {
  2053.           try {
  2054.         var obj = new Object;
  2055.               msgCompose.CheckAndPopulateRecipients(true, false, obj);
  2056.           } catch(ex) { dump("msgCompose.CheckAndPopulateRecipients failed: " + ex + "\n"); }
  2057.       }
  2058.  
  2059.     return sendFormat;
  2060. }
  2061.  
  2062. function DetermineConvertibility()
  2063. {
  2064.     if (!msgCompose.composeHTML)
  2065.         return msgCompConvertible.Plain;
  2066.  
  2067.     try {
  2068.         return msgCompose.bodyConvertible();
  2069.     } catch(ex) {}
  2070.     return msgCompConvertible.No;
  2071. }
  2072.  
  2073. function LoadIdentity(startup)
  2074. {
  2075.     var identityElement = document.getElementById("msgIdentity");
  2076.     var prevIdentity = gCurrentIdentity;
  2077.     
  2078.     if (identityElement) {
  2079.         var item = identityElement.selectedItem;
  2080.         var idKey = item.getAttribute('id');
  2081.         gCurrentIdentity = accountManager.getIdentity(idKey);
  2082.  
  2083.         if (!startup && prevIdentity && idKey != prevIdentity.key)
  2084.         {
  2085.           var prefstring = "mail.identity." + prevIdentity.key;
  2086.           RemoveDirectoryServerObserver(prefstring);
  2087.           var prevReplyTo = prevIdentity.replyTo;
  2088.           var prevBcc = "";
  2089.           if (prevIdentity.bccSelf)
  2090.             prevBcc += prevIdentity.email;
  2091.           if (prevIdentity.bccOthers)
  2092.           {
  2093.             if (prevBcc != "")
  2094.               prevBcc += ","
  2095.             prevBcc += prevIdentity.bccList;
  2096.           }
  2097.  
  2098.           var newReplyTo = gCurrentIdentity.replyTo;
  2099.           var newBcc = "";
  2100.           if (gCurrentIdentity.bccSelf)
  2101.             newBcc += gCurrentIdentity.email;
  2102.           if (gCurrentIdentity.bccOthers)
  2103.           {
  2104.             if (newBcc != "")
  2105.               newBcc += ","
  2106.             newBcc += gCurrentIdentity.bccList;
  2107.           }
  2108.  
  2109.           var needToCleanUp = false;
  2110.           var msgCompFields = msgCompose.compFields;
  2111.  
  2112.           if (newReplyTo != prevReplyTo)
  2113.           {
  2114.             needToCleanUp = true;
  2115.             if (prevReplyTo != "")
  2116.               awRemoveRecipients(msgCompFields, "addr_reply", prevReplyTo);
  2117.             if (newReplyTo != "")
  2118.               awAddRecipients(msgCompFields, "addr_reply", newReplyTo);
  2119.           }
  2120.  
  2121.           if (newBcc != prevBcc)
  2122.           {
  2123.             needToCleanUp = true;
  2124.             if (prevBcc != "")
  2125.               awRemoveRecipients(msgCompFields, "addr_bcc", prevBcc);
  2126.             if (newBcc != "")
  2127.               awAddRecipients(msgCompFields, "addr_bcc", newBcc);
  2128.           }
  2129.  
  2130.           if (needToCleanUp)
  2131.             awCleanupRows();
  2132.  
  2133.           try {
  2134.             msgCompose.SetSignature(gCurrentIdentity);
  2135.           } catch (ex) { dump("### Cannot set the signature: " + ex + "\n");}
  2136.         }
  2137.  
  2138.       AddDirectoryServerObserver(false);
  2139.       if (!startup) {
  2140.           try {
  2141.               setupLdapAutocompleteSession();
  2142.           } catch (ex) {
  2143.               // catch the exception and ignore it, so that if LDAP setup 
  2144.               // fails, the entire compose window doesn't end up horked
  2145.           }
  2146.       }
  2147.     }
  2148. }
  2149.  
  2150.  
  2151. function setupAutocomplete()
  2152. {
  2153.   //Setup autocomplete session if we haven't done so already
  2154.   if (!gAutocompleteSession) {
  2155.     gAutocompleteSession = Components.classes["@mozilla.org/autocompleteSession;1?type=addrbook"].getService(Components.interfaces.nsIAbAutoCompleteSession);
  2156.     if (gAutocompleteSession) {
  2157.       var emailAddr = gCurrentIdentity.email;
  2158.       var start = emailAddr.lastIndexOf("@");
  2159.       gAutocompleteSession.defaultDomain = emailAddr.slice(start + 1, emailAddr.length);
  2160.  
  2161.       // if the pref is set to turn on the comment column, honor it here.
  2162.       // this element then gets cloned for subsequent rows, so they should 
  2163.       // honor it as well
  2164.       //
  2165.       try {
  2166.           if (prefs.GetIntPref("mail.autoComplete.commentColumn")) {
  2167.               document.getElementById('msgRecipient#1').showCommentColumn =
  2168.                   true;
  2169.           }
  2170.       } catch (ex) {
  2171.           // if we can't get this pref, then don't show the columns (which is
  2172.           // what the XUL defaults to)
  2173.       }
  2174.               
  2175.     } else {
  2176.       gAutocompleteSession = 1;
  2177.     }
  2178.   }
  2179.   if (!gSetupLdapAutocomplete) {
  2180.       try {
  2181.           setupLdapAutocompleteSession();
  2182.       } catch (ex) {
  2183.           // catch the exception and ignore it, so that if LDAP setup 
  2184.           // fails, the entire compose window doesn't end up horked
  2185.       }
  2186.   }
  2187. }
  2188.  
  2189. function subjectKeyPress(event)
  2190. {  
  2191.   switch(event.keyCode) {
  2192.   case 9:
  2193.     if (!event.shiftKey) {
  2194.       window._content.focus();
  2195.       event.preventDefault();
  2196.     }
  2197.     break;
  2198.   case 13:
  2199.     window._content.focus();
  2200.     break;
  2201.   }
  2202. }
  2203.  
  2204. function editorKeyPress(event)
  2205. {
  2206.   if (event.keyCode == 9) {
  2207.     if (event.shiftKey) {
  2208.       document.getElementById('msgSubject').focus();
  2209.       event.preventDefault();
  2210.     }
  2211.   }
  2212. }
  2213.  
  2214. function AttachmentBucketClicked(event)
  2215. {
  2216.   if (event.originalTarget.localName == 'treechildren')
  2217.     goDoCommand('cmd_attachFile');
  2218. }
  2219.  
  2220. var attachmentBucketObserver = {
  2221.   onDrop: function (aEvent, aData, aDragSession)
  2222.     {
  2223.       var prettyName;
  2224.       var rawData = aData.data;
  2225.       switch (aData.flavour.contentType) {
  2226.       case "text/x-moz-url":
  2227.       case "text/nsmessage":
  2228.         var separator = rawData.indexOf("\n");
  2229.         if (separator != -1) {
  2230.           prettyName = rawData.substr(separator+1);
  2231.           rawData = rawData.substr(0,separator);
  2232.         }
  2233.         break;
  2234.       case "application/x-moz-file":
  2235.           rawData = aData.data.URL;
  2236.         break;
  2237.       }
  2238.       if (!(DuplicateFileCheck(rawData)))
  2239.         AddAttachment(rawData, prettyName);
  2240.       else {
  2241.         var errorTitle = gComposeMsgsBundle.getString("DuplicateFileErrorDlogTitle");
  2242.         var errorMsg = gComposeMsgsBundle.getString("DuplicateFileErrorDlogMessage");
  2243.         if (!gPromptService) {
  2244.           gPromptService = Components.classes["@mozilla.org/embedcomp/prompt-service;1"].getService();
  2245.           gPromptService = gPromptService.QueryInterface(Components.interfaces.nsIPromptService);
  2246.         }
  2247.         if (gPromptService)
  2248.           gPromptService.alert(window, errorTitle, errorMsg);
  2249.         else
  2250.           window.alert(errorMsg);
  2251.       }
  2252.     },
  2253.  
  2254.   onDragOver: function (aEvent, aFlavour, aDragSession)
  2255.     {
  2256.       var attachmentBucket = document.getElementById("attachmentBucket");
  2257.       attachmentBucket.setAttribute("dragover", "true");
  2258.     },
  2259.  
  2260.   onDragExit: function (aEvent, aDragSession)
  2261.     {
  2262.       var attachmentBucket = document.getElementById("attachmentBucket");
  2263.       attachmentBucket.removeAttribute("dragover");
  2264.     },
  2265.  
  2266.   getSupportedFlavours: function ()
  2267.     {
  2268.       var flavourSet = new FlavourSet();
  2269.       flavourSet.appendFlavour("text/x-moz-url");
  2270.       flavourSet.appendFlavour("text/nsmessage");
  2271.       flavourSet.appendFlavour("application/x-moz-file", "nsIFile");
  2272.       return flavourSet;
  2273.     }
  2274. };
  2275.  
  2276. function GetMsgFolderFromUri(uri)
  2277. {
  2278.     try {
  2279.       var RDF = Components.classes['@mozilla.org/rdf/rdf-service;1'].getService();
  2280.       RDF = RDF.QueryInterface(Components.interfaces.nsIRDFService);
  2281.     var resource = RDF.GetResource(uri);
  2282.         var msgfolder = resource.QueryInterface(Components.interfaces.nsIMsgFolder);
  2283.         return msgfolder;
  2284.     }//try
  2285.     catch (ex) { }//catch
  2286.     return null;
  2287. }
  2288.  
  2289. function DisplaySaveFolderDlg(folderURI)
  2290. {
  2291.   try{
  2292.     showDialog = gCurrentIdentity.showSaveMsgDlg;
  2293.   }//try
  2294.   catch (e){
  2295.     return;
  2296.   }//catch
  2297.  
  2298.   if (showDialog){
  2299.     var msgfolder = GetMsgFolderFromUri(folderURI);
  2300.     if (!msgfolder)
  2301.       return;
  2302.         var checkbox = {value:0};
  2303.     var SaveDlgTitle = gComposeMsgsBundle.getString("SaveDialogTitle");
  2304.     var dlgMsg = gComposeMsgsBundle.getFormattedString("SaveDialogMsg",
  2305.                                                        [msgfolder.name,
  2306.                                                         msgfolder.hostname]);
  2307.  
  2308.     var CheckMsg = gComposeMsgsBundle.getString("CheckMsg");
  2309.     if (!gPromptService) {
  2310.       gPromptService = Components.classes["@mozilla.org/embedcomp/prompt-service;1"].getService();
  2311.       gPromptService = gPromptService.QueryInterface(Components.interfaces.nsIPromptService);
  2312.     }
  2313.     if (gPromptService)
  2314.       gPromptService.alertCheck(window, SaveDlgTitle, dlgMsg, CheckMsg, checkbox);
  2315.     else
  2316.       window.alert(dlgMsg);
  2317.     try {
  2318.           gCurrentIdentity.showSaveMsgDlg = !checkbox.value;
  2319.     }//try
  2320.     catch (e) {
  2321.     return;
  2322.     }//catch
  2323.  
  2324.   }//if
  2325.   return;
  2326. }
  2327.  
  2328.