home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 35 Internet / 35-Internet.zip / mozil06.zip / bin / chrome / messenger.jar / content / messenger / commandglue.js < prev    next >
Text File  |  2001-02-14  |  24KB  |  890 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.  
  22. /*
  23.  * Command-specific code. This stuff should be called by the widgets
  24.  */
  25.  
  26. //The eventual goal is for this file to go away and for the functions to either be brought into
  27. //mailCommands.js or into 3pane specific code.
  28.  
  29. var gFolderJustSwitched = false;
  30. var gBeforeFolderLoadTime;
  31. var gRDFNamespace = "http://www.w3.org/1999/02/22-rdf-syntax-ns#";
  32. function OpenURL(url)
  33. {
  34.   dump("\n\nOpenURL from XUL\n\n\n");
  35.   messenger.SetWindow(window, msgWindow);
  36.   messenger.OpenURL(url);
  37. }
  38.  
  39.  
  40.  
  41.  
  42. function GetMsgFolderFromNode(folderNode)
  43. {
  44.     var folderURI = folderNode.getAttribute("id");
  45.     return GetMsgFolderFromURI(folderURI);
  46. }
  47.  
  48. function GetMsgFolderFromURI(folderURI)
  49. {
  50.     var folderResource = RDF.GetResource(folderURI);
  51.     if(folderResource)
  52.     {
  53.         var msgFolder = folderResource.QueryInterface(Components.interfaces.nsIMsgFolder);
  54.         return msgFolder;
  55.     }
  56.  
  57.     return null;
  58.  
  59.  
  60. }
  61.  
  62. function LoadMessage(messageNode)
  63. {
  64.     var uri = messageNode.getAttribute('id');
  65.     dump(uri + "\n");
  66.  
  67.     LoadMessageByUri(uri);
  68.  
  69. }
  70.  
  71. function LoadMessageByUri(uri)
  72. {  
  73.     if(uri != gCurrentDisplayedMessage)
  74.     {
  75.         var resource = RDF.GetResource(uri);
  76.         var message = resource.QueryInterface(Components.interfaces.nsIMessage); 
  77.         if (message)
  78.             setTitleFromFolder(message.msgFolder, message.mime2DecodedSubject);
  79.  
  80.         var nsIMsgFolder = Components.interfaces.nsIMsgFolder;
  81.         if (message.msgFolder.server.downloadOnBiff)
  82.             message.msgFolder.biffState = nsIMsgFolder.nsMsgBiffState_NoMail;
  83.  
  84.         gCurrentDisplayedMessage = uri;
  85.         gHaveLoadedMessage = true;
  86.         OpenURL(uri);
  87.     }
  88.  
  89. }
  90.  
  91. function ChangeFolderByDOMNode(folderNode)
  92. {
  93.   var uri = folderNode.getAttribute('id');
  94.   dump(uri + "\n");
  95.   
  96.   var isThreaded = folderNode.getAttribute('threaded');
  97.   var sortResource = folderNode.getAttribute('sortResource');
  98.   if(!sortResource)
  99.     sortResource = "";
  100.  
  101.   var sortDirection = folderNode.getAttribute('sortDirection');
  102.  
  103.   if (uri)
  104.       ChangeFolderByURI(uri, isThreaded == "true", sortResource, sortDirection);
  105. }
  106.  
  107. function setTitleFromFolder(msgfolder, subject)
  108. {
  109.     if (!msgfolder) return;
  110.  
  111.     var title;
  112.     var server = msgfolder.server;
  113.  
  114.     if (null != subject)
  115.       title = subject+" - ";
  116.     else
  117.       title = "";
  118.  
  119.     if (msgfolder.isServer) {
  120.             // <hostname>
  121.             title += server.hostName;
  122.     }
  123.     else {
  124.         var middle;
  125.         var end;
  126.         if (server.type == "nntp") {
  127.             // <folder> on <hostname>
  128.             middle = Bundle.GetStringFromName("titleNewsPreHost");
  129.             end = server.hostName;
  130.         } else {
  131.             var identity;
  132.             try {
  133.                 var identities = accountManager.GetIdentitiesForServer(server);
  134.  
  135.                 identity = identities.QueryElementAt(0, Components.interfaces.nsIMsgIdentity);
  136.                 // <folder> for <email>
  137.                 middle = Bundle.GetStringFromName("titleMailPreHost");
  138.                 end = identity.email;
  139.             } catch (ex) {
  140.             }
  141.             
  142.         }
  143.  
  144.         title += msgfolder.prettyName;
  145.         if (middle) title += " " + middle;
  146.         if (end) title += " " + end;
  147.     }
  148.  
  149.     title += " - " + BrandBundle.GetStringFromName("brandShortName");
  150.     window.title = title;
  151. }
  152.  
  153. function ChangeFolderByURI(uri, isThreaded, sortID, sortDirection)
  154. {
  155.   dump('In ChangeFolderByURI uri = ' + uri + "\n");
  156.   if (uri == gCurrentLoadingFolderURI)
  157.     return;
  158.   var resource = RDF.GetResource(uri);
  159.   var msgfolder =
  160.       resource.QueryInterface(Components.interfaces.nsIMsgFolder);
  161.  
  162.   try {
  163.       setTitleFromFolder(msgfolder, null);
  164.   } catch (ex) {
  165.       dump("error setting title: " + ex + "\n");
  166.   }
  167.  
  168.   
  169.   //if it's a server, clear the threadpane and don't bother trying to load.
  170.   if(msgfolder.isServer)
  171.   {
  172.     ClearThreadPane();
  173.     return;
  174.   }
  175.     
  176.   gBeforeFolderLoadTime = new Date();
  177.   gCurrentLoadingFolderURI = uri;
  178.   gNextMessageAfterDelete = null; // forget what message to select, if any
  179.  
  180.   if(msgfolder.manyHeadersToDownload())
  181.   {
  182.     try
  183.     {
  184.         SetBusyCursor(window, true);
  185.         gCurrentFolderToReroot = uri;
  186.         gCurrentLoadingFolderIsThreaded = isThreaded;
  187.         gCurrentLoadingFolderSortID = sortID;
  188.         gCurrentLoadingFolderSortDirection = sortDirection;
  189.         msgfolder.startFolderLoading();
  190.         msgfolder.updateFolder(msgWindow);
  191.     }
  192.     catch(ex)
  193.     {
  194.         dump("Error loading with many headers to download: " + ex + "\n");
  195.     }
  196.   }
  197.   else
  198.   {
  199.     SetBusyCursor(window, true);
  200.     gCurrentFolderToReroot = "";
  201.     gCurrentLoadingFolderIsThreaded = false;
  202.     gCurrentLoadingFolderSortID = "";
  203.     RerootFolder(uri, msgfolder, isThreaded, sortID, sortDirection);
  204.  
  205.     //Need to do this after rerooting folder.  Otherwise possibility of receiving folder loaded
  206.     //notification before folder has actually changed.
  207.     msgfolder.updateFolder(msgWindow);
  208.   }
  209. }
  210.  
  211. function RerootFolder(uri, newFolder, isThreaded, sortID, sortDirection)
  212. {
  213.   dump('In reroot folder\n');
  214.     
  215.   // workaround for #39655
  216.   gFolderJustSwitched = true;
  217.  
  218.   var folder = GetThreadTreeFolder();
  219.   ClearThreadTreeSelection();
  220.  
  221.   //Set the window's new open folder.
  222.   msgWindow.openFolder = newFolder;
  223.  
  224.   //Set threaded state
  225.   ShowThreads(isThreaded);
  226.   
  227.  
  228.   //Clear the new messages of the old folder
  229.   var oldFolderURI = folder.getAttribute("ref");
  230.   if(oldFolderURI && (oldFolderURI != "null") && (oldFolderURI !=""))
  231.   {
  232.    var oldFolder = GetMsgFolderFromURI(oldFolderURI);
  233.    if(oldFolder)
  234.    {
  235.        if (oldFolder.hasNewMessages)
  236.            oldFolder.clearNewMessages();
  237.    }
  238.   }
  239.  
  240.   //the new folder being selected should have its biff state get cleared.   
  241.   if(newFolder)
  242.   {
  243.     newFolder.biffState = 
  244.           Components.interfaces.nsIMsgFolder.nsMsgBiffState_NoMail;
  245.   }
  246.  
  247.   //Clear out the thread pane so that we can sort it with the new sort id without taking any time.
  248.   folder.setAttribute('ref', "");
  249.  
  250.   var column = FindThreadPaneColumnBySortResource(sortID);
  251.  
  252.   if(column)
  253.     SortThreadPane(column, sortID, "http://home.netscape.com/NC-rdf#Date", false, sortDirection, false);
  254.   else
  255.     SortThreadPane("DateColumn", "http://home.netscape.com/NC-rdf#Date", "", false, null, false);
  256.  
  257.   SetSentFolderColumns(IsSpecialFolder(newFolder, "Sent"));
  258.  
  259.   // Since SetSentFolderColumns() may alter the template's structure,
  260.   // we need to explicitly force the builder to recompile its rules.
  261.   //when switching folders, switch back to closing threads
  262.   SetTemplateTreeItemOpen(false);
  263.   folder.builder.rebuild();
  264.  
  265.   folder.setAttribute('ref', uri);
  266.     msgNavigationService.EnsureDocumentIsLoaded(document);
  267.  
  268.   UpdateStatusMessageCounts(newFolder);
  269.  
  270. }
  271.  
  272. function SetSentFolderColumns(isSentFolder)
  273. {
  274.     var senderColumn = document.getElementById("SenderColumnHeader");
  275.     var senderColumnTemplate = document.getElementById("SenderColumnTemplate");
  276.     var authorColumnHeader = document.getElementById("AuthorColumn");
  277.  
  278.     if(isSentFolder)
  279.     {
  280.         senderColumn.setAttribute("value", Bundle.GetStringFromName("recipientColumnHeader"));
  281.         senderColumn.setAttribute("onclick", "return top.MsgSortByRecipient();");
  282.         senderColumnTemplate.setAttribute("value", "rdf:http://home.netscape.com/NC-rdf#Recipient");
  283.         authorColumnHeader.setAttribute("resource", "http://home.netscape.com/NC-rdf#Recipient");
  284.     }
  285.     else
  286.     {
  287.         senderColumn.setAttribute("value", Bundle.GetStringFromName("senderColumnHeader"));
  288.         senderColumn.setAttribute("onclick", "return top.MsgSortBySender();");
  289.         senderColumnTemplate.setAttribute("value", "rdf:http://home.netscape.com/NC-rdf#Sender");
  290.         authorColumnHeader.setAttribute("resource", "http://home.netscape.com/NC-rdf#Sender");
  291.     }
  292.  
  293.  
  294. }
  295.  
  296. function UpdateStatusMessageCounts(folder)
  297. {
  298.     var unreadElement = GetUnreadCountElement();
  299.     var totalElement = GetTotalCountElement();
  300.     if(folder && unreadElement && totalElement)
  301.     {
  302.         var numUnread =
  303.             Bundle.formatStringFromName("unreadMsgStatus",
  304.                                         [ folder.getNumUnread(false)], 1);
  305.         var numTotal =
  306.             Bundle.formatStringFromName("totalMsgStatus",
  307.                                         [folder.getTotalMessages(false)], 1);
  308.  
  309.         unreadElement.setAttribute("value", numUnread);
  310.         totalElement.setAttribute("value", numTotal);
  311.  
  312.     }
  313.  
  314. }
  315.  
  316. function SaveThreadPaneSelection()
  317. {
  318.     var tree = GetThreadTree();
  319.     var selectedItems = tree.selectedItems;
  320.     var numSelected = selectedItems.length;
  321.  
  322.     var selectionArray = new Array(numSelected);
  323.  
  324.     for(var i = 0; i < numSelected; i++)
  325.     {
  326.         selectionArray[i] = selectedItems[i].getAttribute("id");
  327.     }
  328.  
  329.     return selectionArray;
  330. }
  331.  
  332. function RestoreThreadPaneSelection(selectionArray)
  333. {
  334.     var tree = GetThreadTree();
  335.     var numSelected = selectionArray.length;
  336.  
  337.     msgNavigationService.EnsureDocumentIsLoaded(document);
  338.  
  339.     var messageElement;
  340.     for(var i = 0 ; i < numSelected; i++)
  341.     {
  342.         messageElement = document.getElementById(selectionArray[i]);
  343.  
  344.         if(!messageElement && messageView.showThreads)
  345.         {
  346.             var treeFolder = GetThreadTreeFolder();
  347.             var folderURI = treeFolder.getAttribute('ref');
  348.             var folderResource = RDF.GetResource(folderURI);
  349.             var folder = folderResource.QueryInterface(Components.interfaces.nsIMsgFolder);
  350.  
  351.             var messageResource = RDF.GetResource(selectionArray[i]);
  352.             var message = messageResource.QueryInterface(Components.interfaces.nsIMessage);
  353.  
  354.             var topLevelMessage = GetTopLevelMessageForMessage(message, folder);
  355.             var topLevelResource = topLevelMessage.QueryInterface(Components.interfaces.nsIRDFResource);
  356.             var topLevelURI = topLevelResource.Value;
  357.             var topElement = document.getElementById(topLevelURI);
  358.             if(topElement)
  359.             {
  360.                 msgNavigationService.OpenTreeitemAndDescendants(topElement);
  361.             }
  362.  
  363.             messageElement = document.getElementById(selectionArray[i]);
  364.  
  365.         }
  366.         if(messageElement)
  367.         {
  368.             dump("We have a messageElement\n");
  369.             tree.addItemToSelection(messageElement);
  370.             if(i==0)
  371.                 tree.ensureElementIsVisible(messageElement);
  372.         }
  373.     }
  374.  
  375. }
  376.  
  377. function FindThreadPaneColumnBySortResource(sortID)
  378. {
  379.  
  380.     if(sortID == "http://home.netscape.com/NC-rdf#Date")
  381.         return "DateColumn";
  382.     else if(sortID == "http://home.netscape.com/NC-rdf#Sender")
  383.         return "AuthorColumn";
  384.     else if(sortID == "http://home.netscape.com/NC-rdf#Recipient")
  385.         return "AuthorColumn";
  386.     else if(sortID == "http://home.netscape.com/NC-rdf#Status")
  387.         return "StatusColumn";
  388.     else if(sortID == "http://home.netscape.com/NC-rdf#Subject")
  389.         return "SubjectColumn";
  390.     else if(sortID == "http://home.netscape.com/NC-rdf#Flagged")
  391.         return "FlaggedButtonColumn";
  392.     else if(sortID == "http://home.netscape.com/NC-rdf#Priority")
  393.         return "PriorityColumn";
  394.     else if(sortID == "http://home.netscape.com/NC-rdf#Size")
  395.         return "SizeColumn";
  396.     else if(sortID == "http://home.netscape.com/NC-rdf#IsUnread")
  397.         return "UnreadButtonColumn";
  398.     else if(sortID == "http://home.netscape.com/NC-rdf#TotalUnreadMessages")
  399.         return "UnreadColumn";
  400.     else if(sortID == "http://home.netscape.com/NC-rdf#TotalMessages")
  401.         return "TotalColumn";
  402.     else if(sortID == "http://home.netscape.com/NC-rdf#OrderReceived")
  403.         return "OrderReceivedColumn";
  404.  
  405.     return null;
  406.  
  407.  
  408. }
  409.  
  410. //If toggleCurrentDirection is true, then get current direction and flip to opposite.
  411. //If it's not true then use the direction passed in.
  412. function SortThreadPane(column, sortKey, secondarySortKey, toggleCurrentDirection, direction, changeCursor)
  413. {
  414.     //dump("In SortThreadPane\n");
  415.     var node = document.getElementById(column);
  416.     if(!node)
  417.         return false;
  418.  
  419.     if(!direction)
  420.     {
  421.         direction = "ascending";
  422.         //If we just clicked on the same column, then change the direction
  423.         if(toggleCurrentDirection)
  424.         {
  425.             var currentDirection = node.getAttribute('sortDirection');
  426.             if (currentDirection == "ascending")
  427.                     direction = "descending";
  428.             else if (currentDirection == "descending")
  429.                     direction = "ascending";
  430.         }
  431.     }
  432.  
  433.     UpdateSortIndicator(column, direction);
  434.     UpdateSortMenu(column);
  435.  
  436.    var folder = GetSelectedFolder();
  437.     if(folder)
  438.     {
  439.         folder.setAttribute("sortResource", sortKey);
  440.         folder.setAttribute("sortDirection", direction);
  441.     }
  442.  
  443.     SetActiveThreadPaneSortColumn(column);
  444.  
  445.     var selection = SaveThreadPaneSelection();
  446.     var beforeSortTime = new Date();
  447.  
  448.     if(changeCursor)
  449.         SetBusyCursor(window, true);
  450.     var result = SortColumn(node, sortKey, secondarySortKey, direction);
  451.     if(changeCursor)
  452.         SetBusyCursor(window, false);
  453.     var afterSortTime = new Date();
  454.     var timeToSort = (afterSortTime.getTime() - beforeSortTime.getTime())/1000;
  455.  
  456.     if(showPerformance)
  457.         dump("timeToSort is " + timeToSort + "seconds\n");
  458.     RestoreThreadPaneSelection(selection);
  459.     return result;
  460. }
  461.  
  462. //------------------------------------------------------------
  463. // Sets the column header sort icon based on the requested 
  464. // column and direction.
  465. // 
  466. // Notes:
  467. // (1) This function relies on the first part of the 
  468. //     <treecell id> matching the <treecol id>.  The treecell
  469. //     id must have a "Header" suffix.
  470. // (2) By changing the "sortDirection" attribute, a different
  471. //     CSS style will be used, thus changing the icon based on
  472. //     the "sortDirection" parameter.
  473. //------------------------------------------------------------
  474. function UpdateSortIndicator(column,sortDirection)
  475. {
  476.     // Find the <treerow> element
  477.     var treerow = document.getElementById("headRow");
  478.  
  479.     //The SortThreadPane function calls the Sender/Recipient column 'AuthorColumn' 
  480.     //but it's treecell header id is actually 'SenderColumnHeader', so we need to flip
  481.     //it here so that the css can handle changing it's style correctly.
  482.     if(column == "AuthorColumn"){
  483.         column = "SenderColumn";
  484.     }
  485.  
  486.     var id = column + "Header";
  487.     
  488.     if (treerow)
  489.     {
  490.         // Grab all of the <treecell> elements
  491.         var treecell = treerow.getElementsByTagName("treecell");
  492.         if (treecell)
  493.         {
  494.             // Loop through each treecell...
  495.             var node_count = treecell.length;
  496.             for (var i=0; i < node_count; i++)
  497.             {
  498.                 // Is this the requested column ?
  499.                 if (id == treecell[i].getAttribute("id"))
  500.                 {
  501.                     // Set the sortDirection so the class (CSS) will add the
  502.                     // appropriate icon to the header cell
  503.                     treecell[i].setAttribute('sortDirection',sortDirection);
  504.                 }
  505.                 else
  506.                 {
  507.                     // This is not the sorted row
  508.                     treecell[i].removeAttribute('sortDirection');
  509.                 }
  510.             }
  511.         }
  512.     }
  513. }
  514.  
  515. function UpdateSortMenu(currentSortColumn)
  516. {
  517.     UpdateSortMenuitem(currentSortColumn, "sortByDateMenuitem", "DateColumn");
  518.     UpdateSortMenuitem(currentSortColumn, "sortByFlagMenuitem", "FlaggedButtonColumn");
  519.     UpdateSortMenuitem(currentSortColumn, "sortByOrderReceivedMenuitem", "OrderReceivedColumn");
  520.     UpdateSortMenuitem(currentSortColumn, "sortByPriorityMenuitem", "PriorityColumn");
  521.     UpdateSortMenuitem(currentSortColumn, "sortBySenderMenuitem", "AuthorColumn");
  522.     UpdateSortMenuitem(currentSortColumn, "sortBySizeMenuitem", "SizeColumn");
  523.     UpdateSortMenuitem(currentSortColumn, "sortByStatusMenuitem", "StatusColumn");
  524.     UpdateSortMenuitem(currentSortColumn, "sortBySubjectMenuitem", "SubjectColumn");
  525.     UpdateSortMenuitem(currentSortColumn, "sortByUnreadMenuitem", "UnreadButtonColumn");
  526.  
  527. }
  528.  
  529. function UpdateSortMenuitem(currentSortColumnID, menuItemID, columnID)
  530. {
  531.     var menuItem = document.getElementById(menuItemID);
  532.     if(menuItem)
  533.     {
  534.         menuItem.setAttribute("checked", currentSortColumnID == columnID);
  535.     }
  536. }
  537.  
  538. function SortFolderPane(column, sortKey)
  539. {
  540.     var node = FindInSidebar(window, column);
  541.     if(!node)
  542.     {
  543.         dump('Couldnt find sort column\n');
  544.         return false;
  545.     }
  546.     SortColumn(node, sortKey, null, null);
  547.     //Remove the sortActive attribute because we don't want this pane to have any
  548.     //sort styles.
  549.     node.setAttribute("sortActive", "false");
  550.     return true;
  551. }
  552.  
  553. function SortColumn(node, sortKey, secondarySortKey, direction)
  554. {
  555.     dump('In SortColumn\n');
  556.     var xulSortService = Components.classes["@mozilla.org/rdf/xul-sort-service;1"].getService();
  557.  
  558.     if (xulSortService)
  559.     {
  560.         xulSortService = xulSortService.QueryInterface(Components.interfaces.nsIXULSortService);
  561.         if (xulSortService)
  562.         {
  563.             // sort!!!
  564.             var sortDirection;
  565.             if(direction)
  566.                 sortDirection = direction;
  567.             else
  568.             {
  569.                 var currentDirection = node.getAttribute('sortDirection');
  570.                 if (currentDirection == "ascending")
  571.                         sortDirection = "descending";
  572.                 else if (currentDirection == "descending")
  573.                         sortDirection = "ascending";
  574.                 else    sortDirection = "ascending";
  575.             }
  576.  
  577.             try
  578.             {
  579.                 if(secondarySortKey)
  580.                     node.setAttribute('resource2', secondarySortKey);
  581.                 xulSortService.Sort(node, sortKey, sortDirection);
  582.             }
  583.             catch(e)
  584.             {
  585.                         //dump("Sort failed: " + e + "\n");
  586.             }
  587.         }
  588.     }
  589.  
  590. }
  591.  
  592. function GetSelectedFolderResource()
  593. {
  594.     var folderTree = GetFolderTree();
  595.     var selectedFolderList = folderTree.selectedItems;
  596.     var selectedFolder = selectedFolderList[0];
  597.     var uri = selectedFolder.getAttribute('id');
  598.  
  599.  
  600.     var folderResource = RDF.GetResource(uri);
  601.     return folderResource;
  602.  
  603. }
  604.  
  605. function SetFolderCharset(folderResource, aCharset)
  606. {
  607.     var db = GetFolderDatasource();
  608.  
  609.     var charsetResource = RDF.GetLiteral(aCharset);
  610.     var charsetProperty = RDF.GetResource("http://home.netscape.com/NC-rdf#Charset");
  611.  
  612.     db.Assert(folderResource, charsetProperty, charsetResource, true);
  613. }
  614.  
  615.  
  616.  
  617. function ToggleMessageRead(treeItem)
  618. {
  619.  
  620.     var tree = GetThreadTree();
  621.  
  622.     var messageResource = RDF.GetResource(treeItem.getAttribute('id'));
  623.  
  624.     var property = RDF.GetResource('http://home.netscape.com/NC-rdf#IsUnread');
  625.     var result = tree.database.GetTarget(messageResource, property , true);
  626.     result = result.QueryInterface(Components.interfaces.nsIRDFLiteral);
  627.     var isUnread = (result.Value == "true")
  628.  
  629.     var message = messageResource.QueryInterface(Components.interfaces.nsIMessage);
  630.     var messageArray = new Array(1);
  631.     messageArray[0] = message;
  632.  
  633.     MarkMessagesRead(tree.database, messageArray, isUnread);
  634. }
  635.  
  636. function ToggleMessageFlagged(treeItem)
  637. {
  638.  
  639.     var tree = GetThreadTree();
  640.  
  641.     var messageResource = RDF.GetResource(treeItem.getAttribute('id'));
  642.  
  643.     var property = RDF.GetResource('http://home.netscape.com/NC-rdf#Flagged');
  644.     var result = tree.database.GetTarget(messageResource, property , true);
  645.     result = result.QueryInterface(Components.interfaces.nsIRDFLiteral);
  646.     var flagged = (result.Value == "flagged")
  647.  
  648.     var message = messageResource.QueryInterface(Components.interfaces.nsIMessage);
  649.     var messageArray = new Array(1);
  650.     messageArray[0] = message;
  651.  
  652.     MarkMessagesFlagged(tree.database, messageArray, !flagged);
  653.  
  654. }
  655.  
  656. //Called when the splitter in between the thread and message panes is clicked.
  657. function OnClickThreadAndMessagePaneSplitter()
  658. {
  659.     dump("We are in OnClickThreadAndMessagePaneSplitter()\n");
  660.     var collapsed = IsThreadAndMessagePaneSplitterCollapsed();
  661.     //collapsed is the previous state so we know we are opening.
  662.     if(collapsed)
  663.         LoadSelectionIntoMessagePane();    
  664. }
  665.  
  666.  
  667. //takes the selection from the thread pane and loads it into the message pane
  668. function LoadSelectionIntoMessagePane()
  669. {
  670.     var tree = GetThreadTree();
  671.     
  672.     var selArray = tree.selectedItems;
  673.     if (!gNextMessageAfterDelete && selArray && (selArray.length == 1) )
  674.         LoadMessage(selArray[0]);
  675.     else
  676.   {
  677.     // don't necessarily clear the message pane...if you uncomment this,
  678.     // you'll be introducing a large inefficiency when deleting messages...as deleting
  679.     // a msg brings us here twice...so we end up clearing the message pane twice for no
  680.     // good reason...
  681.         // ClearMessagePane();
  682.   }
  683. }
  684.  
  685. function FolderPaneSelectionChange()
  686. {
  687.     var tree = GetFolderTree();
  688.     if(tree)
  689.     {
  690.         var selArray = tree.selectedItems;
  691.         if ( selArray && (selArray.length == 1) )
  692.         {
  693.             ChangeFolderByDOMNode(selArray[0]);
  694.         }
  695.         else
  696.         {
  697.             ClearThreadPane();
  698.         }
  699.     }
  700.     ClearMessagePane();
  701.  
  702. }
  703.  
  704. function ClearThreadPane()
  705. {
  706.     var threadTree = GetThreadTree();
  707.     ClearThreadTreeSelection();
  708.     threadTree.setAttribute('ref', null);
  709. }
  710.  
  711. function OpenFolderTreeToFolder(folderURI)
  712. {
  713.     var tree = GetFolderTree();
  714.     return OpenToFolder(tree, folderURI);
  715.  
  716. }
  717.  
  718. function OpenToFolder(item, folderURI)
  719. {
  720.  
  721.     if(item.nodeType != Node.ELEMENT_NODE)
  722.         return null;
  723.  
  724.     var uri = item.getAttribute('id');
  725.     dump(uri);
  726.     dump('\n');
  727.     if(uri == folderURI)
  728.     {
  729.         dump('found folder: ' + uri);
  730.         dump('\n');
  731.         return item;
  732.     }
  733.  
  734.     var children = item.childNodes;
  735.     var length = children.length;
  736.     var i;
  737.     dump('folder ' + uri);
  738.     dump('has ' + length);
  739.     dump('children\n');
  740.     for(i = 0; i < length; i++)
  741.     {
  742.         var child = children[i];
  743.         var folder = OpenToFolder(child, folderURI);
  744.         if(folder)
  745.         {
  746.             child.setAttribute('open', 'true');
  747.             return folder;
  748.         }
  749.     }
  750.     return null;
  751. }
  752.  
  753.  
  754. function IsSpecialFolder(msgFolder, specialFolderName)
  755. {
  756.     var db = GetFolderDatasource();
  757.     var folderResource = msgFolder.QueryInterface(Components.interfaces.nsIRDFResource);
  758.     if(folderResource)
  759.     {
  760.         var property =
  761.             RDF.GetResource('http://home.netscape.com/NC-rdf#SpecialFolder');
  762.         if (!property) return false;
  763.         var result = db.GetTarget(folderResource, property , true);
  764.         if (!result) return false;
  765.         result = result.QueryInterface(Components.interfaces.nsIRDFLiteral);
  766.         if (!result) return false;
  767.         dump("We are looking for " + specialFolderName + "\n");
  768.         dump("special folder name = " + result.Value + "\n");
  769.         if(result.Value == specialFolderName)
  770.             return true;
  771.     }
  772.  
  773.     return false;
  774. }
  775.  
  776.  
  777. function ShowThreads(showThreads)
  778. {
  779.     dump('in showthreads\n');
  780.     if(messageView)
  781.     {
  782.         messageView.showThreads = showThreads;
  783.         var threadColumn = document.getElementById('ThreadColumnHeader');
  784.         if(threadColumn)
  785.         {
  786.             if(showThreads)
  787.             {
  788.                 threadColumn.setAttribute('currentView', 'threaded');
  789.             }
  790.             else
  791.             {
  792.                 threadColumn.setAttribute('currentView', 'unthreaded');
  793.             }
  794.         }
  795.     }
  796. }
  797.  
  798.  
  799. function GetNextMessageAfterDelete(messages)
  800. {
  801.     var count = messages.length;
  802.  
  803.     var curMessage = messages[0];
  804.     var nextMessage = null;
  805.     var tree = GetThreadTree();
  806.  
  807.     //search forward
  808.     while(curMessage)
  809.     {
  810.         nextMessage = msgNavigationService.FindNextMessage(navigateAny, tree, curMessage, RDF, document, false, messageView.showThreads);
  811.         if(nextMessage)
  812.         {
  813.             if(nextMessage.getAttribute("selected") != "true")
  814.             {
  815.                 break;
  816.             }
  817.         }
  818.         curMessage = nextMessage;
  819.     }
  820.     //if no nextmessage then search backwards
  821.     if(!nextMessage)
  822.     {
  823.  
  824.         curMessage = messages[0];
  825.         nextMessage = null;
  826.         //search forward
  827.         while(curMessage)
  828.         {
  829.             nextMessage = msgNavigationService.FindPreviousMessage(navigateAny, tree, curMessage, RDF, document, false, messageView.showThreads);
  830.             if(nextMessage)
  831.             {
  832.                 if(nextMessage.getAttribute("selected") != "true")
  833.                 {
  834.                     break;
  835.                 }
  836.             }
  837.             curMessage = nextMessage;
  838.         }
  839.  
  840.  
  841.  
  842.     }
  843.     return nextMessage;
  844. }
  845.  
  846.  
  847. function SelectNextMessage(nextMessage)
  848. {
  849.     var tree = GetThreadTree();
  850.     ChangeSelection(tree, nextMessage);
  851.  
  852. }
  853.  
  854. function GetSelectTrashUri(folder)
  855. {
  856.     if (!folder) return null;
  857.     var uri = folder.getAttribute('id');
  858.     dump (uri + "\n");
  859.     var resource = RDF.GetResource(uri);
  860.     var msgFolder =
  861.         resource.QueryInterface(Components.interfaces.nsIMsgFolder);
  862.     if (msgFolder)
  863.     {
  864.         dump("GetSelectTrashUri" + "\n");
  865.         var rootFolder = msgFolder.rootFolder;
  866.         var numFolder;
  867.         var out = new Object();
  868.         var trashFolder = rootFolder.getFoldersWithFlag(0x0100, 1, out); 
  869.         numFolder = out.value;
  870.         dump (numFolder + "\n");
  871.         if (trashFolder)
  872.         {
  873.             dump (trashFolder.URI + "\n");
  874.             return trashFolder.URI;
  875.         }
  876.     }
  877.     return null;
  878. }
  879.  
  880. function Undo()
  881. {
  882.     messenger.Undo(msgWindow);
  883. }
  884.  
  885. function Redo()
  886. {
  887.     messenger.Redo(msgWindow);
  888. }
  889.  
  890.