home *** CD-ROM | disk | FTP | other *** search
/ Tools / WinSN5.0Ver.iso / NETSCAP.50 / WIN1998.ZIP / ns / cmd / xfe / src / FolderView.cpp < prev    next >
Encoding:
C/C++ Source or Header  |  1998-04-08  |  56.7 KB  |  2,094 lines

  1. /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*-
  2.  *
  3.  * The contents of this file are subject to the Netscape Public License
  4.  * Version 1.0 (the "NPL"); you may not use this file except in
  5.  * compliance with the NPL.  You may obtain a copy of the NPL at
  6.  * http://www.mozilla.org/NPL/
  7.  *
  8.  * Software distributed under the NPL is distributed on an "AS IS" basis,
  9.  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
  10.  * for the specific language governing rights and limitations under the
  11.  * NPL.
  12.  *
  13.  * The Initial Developer of this code under the NPL is Netscape
  14.  * Communications Corporation.  Portions created by Netscape are
  15.  * Copyright (C) 1998 Netscape Communications Corporation.  All Rights
  16.  * Reserved.
  17.  */
  18. /* 
  19.    FolderView.cpp -- presents view of mail folders and newsgroups/hosts.
  20.    Created: Chris Toshok <toshok@netscape.com>, 7-Aug-96.
  21.    */
  22.  
  23.  
  24.  
  25. #include "FolderView.h"
  26. #include "SubscribeDialog.h" /* for fe_showSubscribeDialog */
  27. #include "ThreadFrame.h" /* for fe_showMessages */
  28. #if defined(USE_MOTIF_DND)
  29. #include "ThreadView.h"
  30. #endif /* USE_MOTIF_DND */
  31.  
  32. #include "ViewGlue.h"
  33. #include "Outliner.h"
  34. #if defined(USE_MOTIF_DND)
  35. #include "OutlinerDrop.h"
  36. #endif /* USE_MOTIF_DND */
  37. #include "MozillaApp.h"
  38. #include "NewsServerDialog.h"
  39. #include "xfe.h"
  40. #include "icondata.h"
  41. #include "msgcom.h"
  42. #include "felocale.h" /* for fe_ConvertToLocalEncoding */
  43. #include "xp_mem.h"
  44. #include "Xfe/Xfe.h"
  45.  
  46. #include "NewsServerPropDialog.h"
  47. #include "NewsgroupPropDialog.h"
  48. #include "MailFolderPropDialog.h"
  49.  
  50. #include "MNSearchFrame.h"
  51. #include "LdapSearchFrame.h"
  52. #include "MailFilterDlg.h"
  53.  
  54. #include "prefs.h"
  55.  
  56.  
  57. #ifdef DEBUG_toshok
  58. #define D(x) x
  59. #else
  60. #define D(x)
  61. #endif
  62.  
  63. #ifdef DEBUG_dora
  64. #define DD(x) x
  65. #else
  66. #define DD(x)
  67. #endif
  68.  
  69. #define FOLDER_OUTLINER_GEOMETRY_PREF "mail.folderpane.outliner_geometry"
  70.  
  71. // bloody entrails dragging behind.... weighing me down...
  72. extern "C" CL_Compositor *fe_create_compositor(MWContext *context);
  73. extern "C" void fe_load_default_font (MWContext *context);
  74. extern "C" void fe_get_final_context_resources (MWContext *context);
  75. extern "C" void fe_sec_logo_cb (Widget, XtPointer, XtPointer);
  76.  
  77. const char *XFE_FolderView::folderSelected = "XFE_FolderView::folderSelected";
  78. const char *XFE_FolderView::folderDblClicked = "XFE_FolderView::folderDblClicked";
  79. const char *XFE_FolderView::folderAltDblClicked = "XFE_FolderView::folderAltDblClicked";
  80.  
  81. const int XFE_FolderView::OUTLINER_COLUMN_NAME = 0;
  82. const int XFE_FolderView::OUTLINER_COLUMN_UNREAD = 1;
  83. const int XFE_FolderView::OUTLINER_COLUMN_TOTAL = 2;
  84.  
  85. #include "xpgetstr.h"
  86. extern int XFE_FOLDER_OUTLINER_COLUMN_NAME;
  87. extern int XFE_FOLDER_OUTLINER_COLUMN_TOTAL;
  88. extern int XFE_FOLDER_OUTLINER_COLUMN_UNREAD;
  89. extern int XFE_DND_MESSAGE_ERROR;
  90.  
  91. MenuSpec XFE_FolderView::mailserver_popup_menu[] = {
  92. #if 0
  93.   { xfeCmdUpdateMessageCount,    PUSHBUTTON },
  94. #endif
  95.   { xfeCmdNewFolder,        PUSHBUTTON },
  96.   { xfeCmdViewProperties,        PUSHBUTTON },
  97.   { NULL }
  98. };
  99.  
  100. MenuSpec XFE_FolderView::newshost_popup_menu[] = {
  101. // From the spec:
  102. // "Open Discussion Group Server" -- is that xfeCmdGetNewGroups?
  103.   { xfeCmdAddNewsgroup,            PUSHBUTTON },
  104. #if 0
  105.   { xfeCmdUpdateMessageCount,    PUSHBUTTON },
  106. #endif
  107.   { xfeCmdDeleteFolder,            PUSHBUTTON },
  108.   { xfeCmdViewProperties,        PUSHBUTTON },
  109.   { NULL }
  110. };
  111.  
  112. MenuSpec XFE_FolderView::mailfolder_popup_menu[] = {
  113.   { xfeCmdOpenFolder,    PUSHBUTTON },
  114. //  { xfeCmdOpenFolderInNewWindow,    PUSHBUTTON },
  115.   MENU_SEPARATOR,
  116.   { xfeCmdNewFolder,        PUSHBUTTON },
  117.   { xfeCmdDeleteFolder,        PUSHBUTTON },
  118.   { xfeCmdRenameFolder,        PUSHBUTTON },
  119.   { xfeCmdCompressFolders,    PUSHBUTTON },
  120.   MENU_SEPARATOR,
  121.   { xfeCmdComposeMessage,    PUSHBUTTON },
  122.   MENU_SEPARATOR,
  123.   { xfeCmdSearch,        PUSHBUTTON },
  124.   { xfeCmdViewProperties,    PUSHBUTTON },
  125.   { NULL }
  126. };
  127.  
  128. MenuSpec XFE_FolderView::newsgroup_popup_menu[] = {
  129.   { xfeCmdOpenSelected,    PUSHBUTTON },
  130. //  open newsgroups in new window should go here
  131.   MENU_SEPARATOR,
  132.   { xfeCmdComposeMessage,    PUSHBUTTON },
  133.   { xfeCmdMarkAllMessagesRead,    PUSHBUTTON },
  134.   { xfeCmdDeleteFolder,        PUSHBUTTON },
  135.   MENU_SEPARATOR,
  136.   { xfeCmdSearch,        PUSHBUTTON },
  137.   { xfeCmdViewProperties,    PUSHBUTTON },
  138.   { NULL }
  139. };
  140.  
  141. XFE_FolderView::XFE_FolderView(XFE_Component *toplevel_component,
  142.                    Widget parent,
  143.                    XFE_View *parent_view, MWContext *context,
  144.                    MSG_Pane *p)
  145.   : XFE_MNListView(toplevel_component, parent_view, context, p)
  146. {
  147.   // initialize it
  148.   m_popup = NULL;
  149. #ifdef USE_3PANE
  150.   m_clickTimer = 0;
  151.   m_clickData = NULL;
  152.   m_cur_selected = NULL;
  153.   m_cur_count = 0;
  154. #endif
  155.  
  156.   int num_columns = 3;
  157.   static int default_column_widths[] = {30, 10, 10};
  158.  
  159.   toplevel_component->registerInterest(XFE_Component::afterRealizeCallback,
  160.                        this,
  161.                        (XFE_FunctionNotification)beforeToplevelShow_cb);
  162.  
  163.   if (!p)
  164.     setPane(MSG_CreateFolderPane(m_contextData,
  165.                  XFE_MNView::m_master));
  166.  
  167.   // create our outliner
  168.   m_outliner = new XFE_Outliner("folderList",
  169.                                 this,
  170.                                 getToplevel(),
  171.                                 parent,
  172.                                 False,  // constantSize
  173.                                 True,   // hasHeadings
  174.                                 num_columns, 
  175.                                 3,
  176.                                 default_column_widths,
  177.                                 FOLDER_OUTLINER_GEOMETRY_PREF);
  178.  
  179.   m_outliner->setPipeColumn( OUTLINER_COLUMN_NAME );
  180.   m_outliner->setMultiSelectAllowed( True );
  181.   m_outliner->setHideColumnsAllowed( True );
  182. #if defined(USE_MOTIF_DND)
  183.   m_outliner->enableDragDrop(this,
  184.                              XFE_FolderView::getDropTargets,
  185.                              XFE_FolderView::getDragTargets,
  186.                              XFE_FolderView::getDragIconData,
  187.                              XFE_FolderView::dragConvert,
  188.                              XFE_FolderView::processTargets);
  189. #else
  190.   m_outliner->setDragType( FE_DND_MAIL_FOLDER, &folderIcon, this, 
  191.                (fe_dnd_SourceDropFunc)&XFE_FolderView::source_drop_func);
  192.   fe_dnd_CreateDrop(m_outliner->getBaseWidget(), drop_func, this);
  193. #endif /* USE_MOTIF_DND */
  194.   setBaseWidget(m_outliner->getBaseWidget());
  195.  
  196.   // initialize the icons if they haven't already been
  197.   {
  198.     Pixel bg_pixel;
  199.     
  200.     XtVaGetValues(m_widget, XmNbackground, &bg_pixel, 0);
  201.  
  202.     initFolderIcons(getToplevel()->getBaseWidget(),
  203.                     bg_pixel, getToplevel()->getFGPixel());
  204.   }
  205.  
  206.   // jump start the folderview's display
  207.   FE_ListChangeStarting(m_pane,
  208.             FALSE, MSG_NotifyAll, 0, 0);
  209.   FE_ListChangeFinished(m_pane,
  210.             FALSE, MSG_NotifyAll, 0, 0);
  211.  
  212. }
  213.  
  214. XFE_FolderView::~XFE_FolderView()
  215. {
  216.   D( printf ("~XFE_FolderView()\n");)
  217.  
  218.   delete m_outliner;
  219.  
  220.   destroyPane();
  221.  
  222.   // destroy popup here
  223.   if (m_popup)
  224.     delete m_popup;
  225. }
  226.  
  227. void
  228. XFE_FolderView::initFolderIcons(Widget widget, Pixel bg_pixel, Pixel fg_pixel)
  229. {
  230.     static Boolean icons_init_done = False;
  231.  
  232.     if (icons_init_done)
  233.         return;
  234.  
  235.     icons_init_done = True;
  236.  
  237.     if (!mailLocalIcon.pixmap)
  238.         fe_NewMakeIcon(widget,
  239.                        fg_pixel,
  240.                        bg_pixel,
  241.                        &mailLocalIcon,
  242.                        NULL,
  243.                        MN_MailLocal.width, MN_MailLocal.height,
  244.                        MN_MailLocal.mono_bits, MN_MailLocal.color_bits, MN_MailLocal.mask_bits, FALSE);
  245.  
  246.     if (!mailServerIcon.pixmap)
  247.         fe_NewMakeIcon(widget,
  248.                        fg_pixel,
  249.                        bg_pixel,
  250.                        &mailServerIcon,
  251.                        NULL,
  252.                        MN_MailLocal.width, MN_MailLocal.height,
  253.                        MN_MailLocal.mono_bits, MN_MailLocal.color_bits, MN_MailLocal.mask_bits, FALSE);
  254.  
  255.     if (!inboxIcon.pixmap)
  256.         fe_NewMakeIcon(widget,
  257.                        fg_pixel,
  258.                        bg_pixel,
  259.                        &inboxIcon,
  260.                        NULL, 
  261.                        MN_Inbox.width, MN_Inbox.height,
  262.                        MN_Inbox.mono_bits, MN_Inbox.color_bits, MN_Inbox.mask_bits, FALSE);
  263.     
  264.     if (!inboxOpenIcon.pixmap)
  265.         fe_NewMakeIcon(widget,
  266.                        fg_pixel,
  267.                        bg_pixel,
  268.                        &inboxOpenIcon,
  269.                        NULL, 
  270.                        MN_InboxO.width, MN_InboxO.height,
  271.                        MN_InboxO.mono_bits, MN_InboxO.color_bits, MN_InboxO.mask_bits, FALSE);
  272.     
  273.     if (!draftsIcon.pixmap)
  274.         fe_NewMakeIcon(widget,
  275.                        fg_pixel,
  276.                        bg_pixel,
  277.                        &draftsIcon,
  278.                        NULL, 
  279.                        MN_Draft.width, MN_Draft.height,
  280.                        MN_Draft.mono_bits, MN_Draft.color_bits, MN_Draft.mask_bits, FALSE);
  281.     
  282.     if (!draftsOpenIcon.pixmap)
  283.         fe_NewMakeIcon(widget,
  284.                        fg_pixel,
  285.                        bg_pixel,
  286.                        &draftsOpenIcon,
  287.                        NULL, 
  288.                        MN_DraftO.width, MN_DraftO.height,
  289.                        MN_DraftO.mono_bits, MN_DraftO.color_bits, MN_DraftO.mask_bits, FALSE);
  290.     
  291.     if (!outboxIcon.pixmap)
  292.         fe_NewMakeIcon(widget,
  293.                        fg_pixel,
  294.                        bg_pixel,
  295.                        &outboxIcon,
  296.                        NULL, 
  297.                        MN_Outbox.width, MN_Outbox.height,
  298.                        MN_Outbox.mono_bits, MN_Outbox.color_bits, MN_Outbox.mask_bits, FALSE);
  299.     
  300.     if (!outboxOpenIcon.pixmap)
  301.         fe_NewMakeIcon(widget,
  302.                        fg_pixel,
  303.                        bg_pixel,
  304.                        &outboxOpenIcon,
  305.                        NULL, 
  306.                        MN_OutboxO.width, MN_OutboxO.height,
  307.                        MN_OutboxO.mono_bits, MN_OutboxO.color_bits, MN_OutboxO.mask_bits, FALSE);
  308.  
  309.     if (!folderIcon.pixmap)
  310.         fe_NewMakeIcon(widget,
  311.                        fg_pixel,
  312.                        bg_pixel,
  313.                        &folderIcon,
  314.                        NULL, 
  315.                        MN_Folder.width, MN_Folder.height,
  316.                        MN_Folder.mono_bits, MN_Folder.color_bits, MN_Folder.mask_bits, FALSE);
  317.     
  318.     if (!folderOpenIcon.pixmap)
  319.         fe_NewMakeIcon(widget,
  320.                        fg_pixel,
  321.                        bg_pixel,
  322.                        &folderOpenIcon,
  323.                        NULL, 
  324.                        MN_FolderO.width, MN_FolderO.height,
  325.                        MN_FolderO.mono_bits, MN_FolderO.color_bits, MN_FolderO.mask_bits, FALSE);
  326.     
  327.     if (!folderServerIcon.pixmap)
  328.         fe_NewMakeIcon(widget,
  329.                        fg_pixel,
  330.                        bg_pixel,
  331.                        &folderServerIcon,
  332.                        NULL, 
  333.                        MN_FolderServer.width, MN_FolderServer.height,
  334.                        MN_FolderServer.mono_bits, MN_FolderServer.color_bits, MN_FolderServer.mask_bits, FALSE);
  335.     
  336.     if (!folderServerOpenIcon.pixmap)
  337.         fe_NewMakeIcon(widget,
  338.                        fg_pixel,
  339.                        bg_pixel,
  340.                        &folderServerOpenIcon,
  341.                        NULL, 
  342.                        MN_FolderServerO.width, MN_FolderServerO.height,
  343.                        MN_FolderServerO.mono_bits, MN_FolderServerO.color_bits, MN_FolderServerO.mask_bits, FALSE);
  344.     
  345.     if (!newsServerIcon.pixmap)
  346.         fe_NewMakeIcon(widget,
  347.                        fg_pixel,
  348.                        bg_pixel,
  349.                        &newsServerIcon,
  350.                        NULL, 
  351.                        MN_NewsServer.width, MN_NewsServer.height,
  352.                        MN_NewsServer.mono_bits, MN_NewsServer.color_bits, MN_NewsServer.mask_bits, FALSE);
  353.  
  354.     if (!newsServerSecureIcon.pixmap)
  355.         fe_NewMakeIcon(widget,
  356.                        fg_pixel,
  357.                        bg_pixel,
  358.                        &newsServerSecureIcon,
  359.                        NULL, 
  360.                        MN_NewsServerSecure.width, MN_NewsServerSecure.height,
  361.                        MN_NewsServerSecure.mono_bits, MN_NewsServerSecure.color_bits, MN_NewsServerSecure.mask_bits, FALSE);
  362.     
  363.     if (!newsgroupIcon.pixmap)
  364.         fe_NewMakeIcon(widget,
  365.                        fg_pixel,
  366.                        bg_pixel,
  367.                        &newsgroupIcon,
  368.                        NULL, 
  369.                        MN_Newsgroup.width, MN_Newsgroup.height,
  370.                        MN_Newsgroup.mono_bits, MN_Newsgroup.color_bits, MN_Newsgroup.mask_bits, FALSE);
  371.     
  372.     if (!trashIcon.pixmap)
  373.         fe_NewMakeIcon(widget,
  374.                        fg_pixel,
  375.                        bg_pixel,
  376.                        &trashIcon,
  377.                        NULL, 
  378.                        MN_TrashSmall.width, MN_TrashSmall.height,
  379.                        MN_TrashSmall.mono_bits, MN_TrashSmall.color_bits, MN_TrashSmall.mask_bits, FALSE);
  380. }
  381.  
  382. void
  383. XFE_FolderView::paneChanged(XP_Bool asynchronous,
  384.                             MSG_PANE_CHANGED_NOTIFY_CODE code,
  385.                             int32 value)
  386. {
  387.     switch (code)
  388.         {
  389.         case MSG_PaneNotifySelectNewFolder:
  390.             {
  391.                 /* check value
  392.                  */
  393.                 if (value >=0) {
  394.                     m_outliner->makeVisible(value);
  395.                     m_outliner->selectItemExclusive(value);
  396.                 }/* if */
  397. #if defined(DEBUG_tao)
  398.                 else {
  399.                   printf("\nXFE_FolderView::paneChanged, value=%d", value);
  400.                   XP_ASSERT(value >=0);
  401.                 }/* else */
  402. #endif
  403.                 break;
  404.             }
  405.  
  406.         case MSG_PaneNotifyFolderDeleted:
  407.             XFE_MozillaApp::theApp()->notifyInterested(XFE_MNView::folderDeleted,
  408.                                                        (void *)value);
  409.  
  410.             break;
  411.  
  412.         default:
  413.             break;
  414.         }
  415.  
  416.   XFE_MNView::paneChanged(asynchronous, code, value);
  417. }
  418.  
  419. XFE_CALLBACK_DEFN(XFE_FolderView, beforeToplevelShow)(XFE_NotificationCenter *,
  420.                             void *, void*)
  421. {
  422. }
  423.  
  424. void
  425. XFE_FolderView::selectFolder(MSG_FolderInfo *info)
  426. {
  427.   MSG_ViewIndex index;
  428.   
  429.   index = MSG_GetFolderIndexForInfo(m_pane, info, TRUE);
  430.   
  431.   if (index != MSG_VIEWINDEXNONE)
  432.     {
  433.       m_outliner->makeVisible(index);
  434.       m_outliner->selectItemExclusive(index);
  435.  
  436.       getToplevel()->notifyInterested(XFE_View::chromeNeedsUpdating);
  437.     }
  438. }
  439.  
  440. Boolean
  441. XFE_FolderView::isCommandEnabled(CommandType cmd, void *call_data, XFE_CommandInfo* info)
  442. {
  443.   const int *selected;
  444.   int count;
  445.  
  446.   m_outliner->getSelection(&selected, &count);
  447.  
  448. #define IS_CMD(command) cmd == (command)
  449.   if (// from the FolderFrame edit menu.
  450.       IS_CMD(xfeCmdFindInObject)
  451.       || IS_CMD(xfeCmdFindAgain))
  452.     {
  453.       return !XP_IsContextBusy(m_contextData) && count > 0;
  454.     }
  455. #ifdef DEBUG_akkana
  456.   else if ( IS_CMD(xfeCmdExpand)
  457.       || IS_CMD(xfeCmdExpandAll)
  458.       || IS_CMD(xfeCmdCollapse)
  459.       || IS_CMD(xfeCmdCollapseAll)
  460.             )
  461.       return True;
  462. #endif
  463.   else if (IS_CMD(xfeCmdViewSecurity))
  464.       return True;
  465.   else if (IS_CMD(xfeCmdViewProperties))
  466.       {
  467.           return count == 1;
  468.       }
  469.   else if (IS_CMD(xfeCmdUpdateMessageCount))
  470.       {
  471.           return !XP_IsContextBusy(m_contextData);
  472.       }
  473.   else if (IS_CMD(xfeCmdSearch) 
  474.            || IS_CMD(xfeCmdSearchAddress))
  475.       {
  476.           return !XP_IsContextBusy(m_contextData);
  477.       }
  478.   else if (IS_CMD(xfeCmdDelete))
  479.     {
  480.       return XFE_MNListView::isCommandEnabled(xfeCmdDeleteFolder);
  481.     }
  482.   else if (IS_CMD(xfeCmdEditPreferences) || IS_CMD(xfeCmdNewNewsHost))
  483.     {
  484.       return True;
  485.     }
  486.   else if (IS_CMD(xfeCmdOpenSelected))
  487.     {
  488.         MSG_FolderLine line;
  489.         if (!MSG_GetFolderLineByIndex(m_pane, selected[0], 1, &line))
  490.             return False;
  491.         return ((line.flags & MSG_FOLDER_FLAG_NEWSGROUP)
  492.                 || ((line.flags & MSG_FOLDER_FLAG_MAIL)
  493.                     && (line.level > 1)));
  494.     }
  495.   else if (IS_CMD(xfeCmdNewFolder) && count == 1)
  496.     {
  497.         MSG_FolderLine line;
  498.         if (!MSG_GetFolderLineByIndex(m_pane, selected[0], 1, &line))
  499.             return False;
  500.         XP_Bool selectable;
  501.                     
  502.         if (line.flags & MSG_FOLDER_FLAG_NEWSGROUP
  503.             || line.flags & MSG_FOLDER_FLAG_NEWS_HOST)
  504.             MSG_CommandStatus(m_pane, MSG_NewNewsgroup,
  505.                               (MSG_ViewIndex*)selected, count, 
  506.                               &selectable, NULL, NULL, NULL);
  507.         else
  508.             MSG_CommandStatus(m_pane, MSG_NewFolder,
  509.                               (MSG_ViewIndex*)selected, count, 
  510.                               &selectable, NULL, NULL, NULL);
  511.         return selectable;
  512.     }
  513.   else
  514.     {
  515.       return XFE_MNListView::isCommandEnabled(cmd, call_data, info);
  516.     }
  517. #undef IS_CMD
  518. }
  519.  
  520. Boolean
  521. XFE_FolderView::handlesCommand(CommandType cmd, void *, XFE_CommandInfo*)
  522. {
  523. #define IS_CMD(command) cmd == (command)
  524.  
  525.   if (IS_CMD(xfeCmdOpenSelected)
  526.       || IS_CMD(xfeCmdEditPreferences)
  527.       || IS_CMD(xfeCmdOpenPage)
  528.       || IS_CMD(xfeCmdSaveAs)
  529.       || IS_CMD(xfeCmdNewFolder)
  530.       || IS_CMD(xfeCmdRenameFolder)
  531.       || IS_CMD(xfeCmdEmptyTrash)
  532.       || IS_CMD(xfeCmdCompressFolders)
  533.       || IS_CMD(xfeCmdAddNewsgroup)
  534.       || IS_CMD(xfeCmdNewNewsHost)
  535.       || IS_CMD(xfeCmdInviteToNewsgroup)
  536.       || IS_CMD(xfeCmdPrintSetup)
  537.       || IS_CMD(xfeCmdPrintPreview)
  538.       || IS_CMD(xfeCmdPrint)
  539.  
  540.       || IS_CMD(xfeCmdSearch)
  541.       || IS_CMD(xfeCmdSearchAddress)
  542.  
  543.       || IS_CMD(xfeCmdUndo)
  544.       || IS_CMD(xfeCmdRedo)
  545.       || IS_CMD(xfeCmdCut)
  546.       || IS_CMD(xfeCmdCopy)
  547.       || IS_CMD(xfeCmdPaste)
  548.  
  549.       || IS_CMD(xfeCmdGetNewMessages)
  550.  
  551.       || IS_CMD(xfeCmdExpand)
  552.       || IS_CMD(xfeCmdExpandAll)
  553.       || IS_CMD(xfeCmdCollapse)
  554.       || IS_CMD(xfeCmdCollapseAll)
  555.  
  556. #ifdef DEBUG_akkana
  557.       || IS_CMD(xfeCmdMoveFoldersInto)
  558. #endif
  559.  
  560.       || IS_CMD(xfeCmdModerateDiscussion)
  561.       || IS_CMD(xfeCmdMarkAllMessagesRead)
  562.       || IS_CMD(xfeCmdSendMessagesInOutbox)
  563.       || IS_CMD(xfeCmdDeleteFolder)
  564.       || IS_CMD(xfeCmdViewSecurity)
  565.       || IS_CMD(xfeCmdViewProperties)
  566.       || IS_CMD(xfeCmdUpdateMessageCount)
  567.       || IS_CMD(xfeCmdShowPopup))
  568.     {
  569.       return True;
  570.     }
  571.   else
  572.     {
  573.       return XFE_MNListView::handlesCommand(cmd);
  574.     }
  575.  
  576. #undef IS_CMD
  577. }
  578.  
  579. void
  580. XFE_FolderView::doCommand(CommandType cmd,
  581.                           void * calldata, 
  582.                           XFE_CommandInfo* info)
  583. {
  584. #define IS_CMD(command) cmd == (command)  
  585.     const int *selected;
  586.     int count;
  587.     
  588.     m_outliner->getSelection(&selected, &count);
  589.  
  590. D(    printf ("in XFE_FolderView::doCommand()\n");)
  591.  
  592.     if (IS_CMD(xfeCmdShowPopup))
  593.         {
  594.             XP_ASSERT(info);
  595.             XEvent *event = (XEvent *)info->event;
  596.             int x, y, clickrow;
  597.  
  598.             Widget w = XtWindowToWidget(event->xany.display, event->xany.window);
  599.             MSG_FolderLine clickline;
  600.             MenuSpec *spec;
  601.             int depth;
  602.             
  603.             if (w == NULL) w = m_widget;
  604.             
  605.             /* we create a new popup each time. */
  606.             if (m_popup)
  607.                 delete m_popup;
  608.             
  609.             m_popup = new XFE_PopupMenu("popup",
  610.                                         (XFE_Frame*)m_toplevel, // XXXXXXX
  611.                                         w,
  612.                                         NULL);
  613.             
  614.             m_outliner->translateFromRootCoords(event->xbutton.x_root,
  615.                                                 event->xbutton.y_root,
  616.                                                 &x, &y);
  617.             
  618.             // figure out which row they clicked in, and choose the
  619.             // right popup menu.
  620.             clickrow = m_outliner->XYToRow(x, y);
  621.             
  622.             D( printf ("(x,y) = (%d,%d). row is %d\n", x, y, clickrow);)
  623.             
  624.             if (clickrow == -1)
  625.                 return;
  626.             
  627.             if (! m_outliner->isSelected(clickrow))
  628.                 m_outliner->selectItemExclusive(clickrow);
  629.             
  630.             acquireLineData(clickrow);
  631.             getTreeInfo(NULL, NULL, &depth, NULL);
  632.             releaseLineData();
  633.             
  634.             if (!MSG_GetFolderLineByIndex(m_pane, clickrow, 1, &clickline))
  635.                 return;
  636.             
  637.             if (depth < 1)
  638.                 {
  639.                     if (clickline.flags & MSG_FOLDER_FLAG_NEWS_HOST)
  640.                         spec = newshost_popup_menu;
  641.                     else
  642.                         spec = mailserver_popup_menu;
  643.                 }
  644.             else
  645.                 {
  646.                     if (clickline.flags & MSG_FOLDER_FLAG_NEWSGROUP)
  647.                         spec = newsgroup_popup_menu;
  648.                     else
  649.                         spec = mailfolder_popup_menu;
  650.                 }
  651.             
  652.             m_popup->addMenuSpec(spec);
  653.             
  654.             m_popup->position(event);
  655.             
  656.             m_popup->show();
  657.         }
  658.     else if (IS_CMD(xfeCmdEditPreferences))
  659.         {
  660.             fe_showMailNewsPreferences(getToplevel(), m_contextData);
  661.         }
  662.     else if (IS_CMD(xfeCmdOpenSelected))
  663.         {
  664.             int i;
  665.             
  666.             for (i = 0; i < count; i ++)
  667.                 {
  668.                     MSG_FolderLine line;
  669.                     
  670.                     if (!MSG_GetFolderLineByIndex(m_pane, selected[i], 1, &line)) continue;
  671.                     
  672.                     if (!(line.level == 1 && line.flags & MSG_FOLDER_FLAG_DIRECTORY))
  673.                         fe_showMessages(XtParent(getToplevel()->getBaseWidget()), 
  674.                                         ViewGlue_getFrame(m_contextData),
  675.                                         NULL,
  676.                                         MSG_GetFolderInfo(m_pane, selected[i]),
  677.                                         FALSE, FALSE, MSG_MESSAGEKEYNONE);
  678.                 }
  679.         }
  680.     else if (IS_CMD(xfeCmdGetNewMessages))
  681.         {
  682.             getNewMail();
  683.         }
  684.     else if (IS_CMD(xfeCmdSendMessagesInOutbox))
  685.         {
  686.             D(    printf ("MSG_FolderPane::sendMessagesInOutbox()\n");)
  687.                 
  688.             MSG_Command(m_pane, MSG_DeliverQueuedMessages, (MSG_ViewIndex*)selected, count);
  689.         }
  690.     else if (IS_CMD(xfeCmdAddNewsgroup))
  691.         {
  692.             D(    printf ("MSG_FolderPane::addNewsgroup()\n");)
  693.  
  694.             MSG_FolderLine line;
  695.             MSG_Host *host = NULL;
  696.  
  697.             if (MSG_GetFolderLineByIndex(m_pane, selected[0], 1, &line))
  698.                 {
  699.                     if (line.flags & MSG_FOLDER_FLAG_NEWS_HOST
  700.                         || line.flags & MSG_FOLDER_FLAG_IMAP_SERVER)
  701.                         {
  702.                             host = MSG_GetHostFromIndex(m_pane, selected[0]);
  703. #ifdef DEBUG_akkana
  704.                             if (!host)
  705.                                 printf("Couldn't get host from index\n");
  706. #endif
  707.                         }
  708.                     else if (line.flags & MSG_FOLDER_FLAG_NEWSGROUP
  709.                              || line.flags & MSG_FOLDER_FLAG_IMAPBOX)
  710.                         {
  711.                             MSG_FolderInfo *info = MSG_GetFolderInfo(m_pane, selected[0]);
  712.                             
  713.                             if (info)
  714.                                 host = MSG_GetHostForFolder(info);
  715. #ifdef DEBUG_akkana
  716.                             else
  717.                                 printf("Couldn't get folder info\n");
  718.                             if (info && !host)
  719.                                 printf("Couldn't get host for folder\n");
  720. #endif
  721.                         }
  722.                 }
  723.             
  724.             fe_showSubscribeDialog(getToplevel(), getToplevel()->getBaseWidget(), m_contextData, host);
  725.         }
  726.     else if (IS_CMD(xfeCmdNewFolder))
  727.         {
  728.             D(    printf ("MSG_FolderPane::newFolder()\n");)
  729.  
  730.             MSG_FolderLine line;
  731.             
  732.             if (MSG_GetFolderLineByIndex(m_pane, selected[0], 1, &line))
  733.                 {
  734.                     if (line.flags & MSG_FOLDER_FLAG_NEWSGROUP
  735.                         || line.flags & MSG_FOLDER_FLAG_NEWS_HOST)
  736.                         MSG_Command(m_pane, MSG_NewNewsgroup, (MSG_ViewIndex*)selected, count);
  737. //                        fe_showSubscribeDialog(getToplevel(), getToplevel()->getBaseWidget(), m_contextData);
  738.                     else
  739.                         {
  740.                             MSG_Command(m_pane, MSG_NewFolder, (MSG_ViewIndex*)selected, count);
  741.                             XFE_MozillaApp::theApp()->notifyInterested(XFE_MNView::foldersHaveChanged);
  742.                         }
  743.                 }
  744.         }
  745.     else if (IS_CMD(xfeCmdRenameFolder))
  746.         {
  747.         D(    printf ("MSG_FolderPane::renameFolder()\n");)
  748.             
  749.             MSG_Command(m_pane, MSG_DoRenameFolder, (MSG_ViewIndex*)selected, count);
  750.             XFE_MozillaApp::theApp()->notifyInterested(XFE_MNView::foldersHaveChanged);
  751.         }
  752.     else if (IS_CMD(xfeCmdEmptyTrash))
  753.         {
  754.         D(    printf ("MSG_FolderPane::emptyTrash()\n");)
  755.             
  756.             MSG_Command(m_pane, MSG_EmptyTrash, (MSG_ViewIndex*)selected, count);
  757.         }
  758.     else if (IS_CMD(xfeCmdCompressFolders))
  759.         {
  760.         D(    printf ("MSG_FolderPane::compressFolders()\n");)
  761.             
  762.             MSG_Command(m_pane, MSG_CompressFolder, (MSG_ViewIndex*)selected, count);
  763.         }
  764.     else if (IS_CMD(xfeCmdDeleteFolder))
  765.         {
  766.         D(    printf ("MSG_FolderPane::deleteFolder()\n");)
  767.             MSG_Command(m_pane, MSG_DeleteFolder, (MSG_ViewIndex*)selected, count);
  768.             XFE_MozillaApp::theApp()->notifyInterested(XFE_MNView::foldersHaveChanged);
  769.         }
  770.     else if (IS_CMD(xfeCmdViewSecurity))
  771.         {
  772.             D(    printf ("MSG_FolderPane::viewSecurity()\n");)
  773.             fe_sec_logo_cb(NULL, m_contextData, NULL);
  774.             return;
  775.         }
  776.     else if (IS_CMD(xfeCmdEditMailFilterRules))
  777.         {
  778.             fe_showMailFilterDlg(getToplevel()->getBaseWidget(), 
  779.                                  m_contextData);
  780.             
  781.         }
  782.     else if (IS_CMD(xfeCmdSearchAddress))
  783.         {
  784.         DD(printf ("searchAddress\n");)
  785.             fe_showLdapSearch(XfeAncestorFindApplicationShell(getToplevel()->getBaseWidget()), 
  786.                               ViewGlue_getFrame(m_contextData),
  787.                               (Chrome*)NULL);
  788.             
  789.         }
  790.     else if (IS_CMD(xfeCmdViewProperties))
  791.         {
  792.             MSG_FolderInfo *info = MSG_GetFolderInfo(m_pane, selected[0]);
  793.             MSG_FolderLine line;
  794.  
  795.             D(printf("viewProperties\n");)
  796.             if (MSG_GetFolderLineById(XFE_MNView::m_master, info, &line))
  797.                 {
  798.                     if (line.flags & MSG_FOLDER_FLAG_NEWS_HOST)
  799.                         {
  800.                             MSG_NewsHost *host = MSG_GetNewsHostFromIndex(m_pane, selected[0]);
  801.  
  802.                             fe_showNewsServerProperties(getToplevel()->getBaseWidget(),
  803.                                                         m_contextData,
  804.                                                         host);
  805.                         }
  806.                     else if (line.flags & MSG_FOLDER_FLAG_NEWSGROUP)
  807.                         {
  808.                             fe_showNewsgroupProperties(getToplevel()->getBaseWidget(),
  809.                                                        m_contextData,
  810.                                                        info);
  811.                         }
  812.                     else if (line.flags & MSG_FOLDER_FLAG_MAIL)
  813.                         {
  814.                             if (line.level == 1)
  815.                                 fe_showMailServerPreferences(getToplevel(), m_contextData);
  816.                             else
  817.                                 fe_showMailFolderProperties(getToplevel()->getBaseWidget(),
  818.                                                             m_contextData,
  819.                                                             m_pane,
  820.                                                             info);
  821.                         }
  822.                 }
  823.         }
  824.     else if (IS_CMD(xfeCmdSearch))
  825.         {
  826.         DD(printf ("searchMailNews\n");)
  827.             
  828.             // Find current selected folder
  829.             
  830.             const int *selected;
  831.             int count;
  832.             MSG_FolderInfo *folderInfo;
  833.             
  834.             m_outliner->getSelection(&selected, &count);
  835.             
  836.             if ( count > 0 )
  837.                 {
  838.                 DD(printf("### Search Selected Folder %d\n", selected[0]);)
  839.                     folderInfo = MSG_GetFolderInfo(m_pane, (MSG_ViewIndex)(selected[0]));
  840.                 }
  841.             else
  842.                 {
  843.                 DD(printf("### Search All Folder\n");)
  844.                     folderInfo = NULL;
  845.                 }
  846.             // We have to use the parent of the base widget to get
  847.             // to the real top level widget. By doing so, when dispatching
  848.             // notification, SearchFrame will only get to its registerred
  849.             // event this way. in fe_WidgetToContext, there is an intent
  850.             // to get to the wrong frame if we don't use the real toplevel
  851.             // as the base for the toplevel frames ... dora 12/31/96
  852.             fe_showMNSearch(XfeAncestorFindApplicationShell(getToplevel()->getBaseWidget()), 
  853.                             ViewGlue_getFrame(m_contextData),
  854.                             NULL, this,
  855.                             folderInfo);
  856.         }
  857. #ifdef DEBUG_akkana
  858.     else if (IS_CMD(xfeCmdMoveFoldersInto))
  859.         {
  860.             MSG_MoveFoldersInto(m_pane, (MSG_ViewIndex*)selected, count,
  861.                                 (MSG_FolderInfo*)info);
  862.             XFE_MozillaApp::theApp()->notifyInterested(XFE_MNView::foldersHaveChanged);
  863.         }
  864.     else if (IS_CMD(xfeCmdExpand) || IS_CMD(xfeCmdExpandAll)
  865.              || IS_CMD(xfeCmdCollapse) || IS_CMD(xfeCmdCollapseAll))
  866.         {
  867.             // Nope, these are the cmds for the thread win, not folder win. :-(
  868.             //MSG_CommandType msg_cmd = commandToMsgCmd(cmd);
  869.             //MSG_Command(m_pane, msg_cmd, (MSG_ViewIndex*)selected, count);
  870.         }
  871. #endif
  872.     else if (IS_CMD(xfeCmdNewNewsHost) /* || IS_CMD(xfeCmdAddNewsServer) */)
  873.          {
  874.             // This code taken out of SubAllView::doCommand():
  875.              XFE_NewsServerDialog *d = new XFE_NewsServerDialog(getToplevel()->getBaseWidget(),
  876.                                                                 "addServer",
  877.                                                                 ViewGlue_getFrame(m_contextData));
  878.              XP_Bool ok_pressed = d->post();
  879.  
  880.              if (ok_pressed)
  881.              {
  882.                  const char *serverName = d->getServer();
  883.                  int serverPort = d->getPort();
  884.                  XP_Bool isSecure = d->isSecure();
  885.                  MSG_NewsHost *host;
  886.  
  887.                  host = MSG_CreateNewsHost(XFE_MNView::getMaster(),
  888.                                            serverName,
  889.                                            isSecure,
  890.                                            serverPort);
  891.                     
  892.                  XFE_MozillaApp::theApp()->notifyInterested(XFE_MNView::foldersHaveChanged);
  893.              }
  894.  
  895.              delete d;
  896.         }
  897.     else if (IS_CMD(xfeCmdMarkAllMessagesRead))
  898.         {
  899.             MSG_Command(m_pane, MSG_MarkAllRead,
  900.                         (MSG_ViewIndex*)selected, count);
  901. //            XFE_MozillaApp::theApp()->notifyInterested(XFE_MNView::foldersHaveChanged);
  902.         }
  903.     else if (IS_CMD(xfeCmdModerateDiscussion))
  904.         {
  905.             MSG_Command(m_pane, MSG_ModerateNewsgroup,
  906.                         (MSG_ViewIndex*)selected, count);
  907.         }
  908.     else
  909.         {
  910.             XFE_MNListView::doCommand(cmd, calldata, info);
  911.             return;
  912.         }
  913.     
  914.     getToplevel()->notifyInterested(XFE_View::chromeNeedsUpdating);
  915.  
  916. D(    printf ("leaving XFE_FolderView::doCommand()\n");)
  917. #undef IS_CMD
  918. }
  919.  
  920. char *
  921. XFE_FolderView::commandToString(CommandType cmd, void *calldata, XFE_CommandInfo* info)
  922. {
  923. #define IS_CMD(command) cmd == (command)  
  924.     const int *selected;
  925.     int count;
  926.     MSG_FolderLine line;
  927.     
  928.     m_outliner->getSelection(&selected, &count);
  929.     
  930.     // this doesn't handle selections with more than one element in them.
  931.     
  932.     if (IS_CMD(xfeCmdNewFolder)) 
  933.         {
  934.             if (count != 1)
  935.                 return stringFromResource("newFolderCmdString");
  936.             
  937.             MSG_GetFolderLineByIndex(m_pane, selected[0], 1, &line);
  938.             if (line.flags & MSG_FOLDER_FLAG_NEWSGROUP
  939.                 || line.flags & MSG_FOLDER_FLAG_NEWS_HOST)
  940.                 return stringFromResource("newNewsgroupCmdString");
  941.             else /* (line.flags & MSG_FOLDER_FLAG_MAIL) */
  942.                 if (line.level == 1)
  943.                     return stringFromResource("newFolderCmdString");
  944.                 else
  945.                     return stringFromResource("newSubFolderCmdString");
  946.         }
  947.     else if (IS_CMD(xfeCmdOpenSelected))
  948.         {
  949.             if (count != 1)
  950.                 return stringFromResource("openFolderCmdString");
  951.             
  952.             MSG_GetFolderLineByIndex(m_pane, selected[0], 1, &line);
  953.             
  954.             if ((line.flags & MSG_FOLDER_FLAG_NEWSGROUP)
  955.                 || (line.flags & MSG_FOLDER_FLAG_NEWS_HOST))
  956.                 return stringFromResource("openNewsgroupCmdString");
  957.             else
  958.                 return stringFromResource("openFolderCmdString");
  959.         }
  960.     else if (IS_CMD(xfeCmdDeleteFolder))
  961.         {
  962.             if (count != 1)
  963.                 return stringFromResource("deleteFolderCmdString");
  964.             
  965.             MSG_GetFolderLineByIndex(m_pane, selected[0], 1, &line);
  966. #if defined(DEBUG_tao)
  967.             printf("\n  line.flags=%d", line.flags);
  968. #endif
  969.             if (line.flags & MSG_FOLDER_FLAG_NEWS_HOST)
  970.                 return stringFromResource("deleteNewsHostCmdString");
  971.             else if (line.flags & MSG_FOLDER_FLAG_NEWSGROUP)
  972.                 return stringFromResource("unsubscribeNewsgroupCmdString");
  973.             else /* (line.flags & MSG_FOLDER_FLAG_MAIL) */
  974.                 if (line.level == 1)
  975.                     return stringFromResource("deleteMailHostCmdString");
  976.                 else
  977.                     return stringFromResource("deleteFolderCmdString");
  978.         }
  979.     else if (IS_CMD(xfeCmdViewProperties))
  980.         {
  981.             if (count != 1)
  982.                 return stringFromResource("folderPropsCmdString");
  983.             
  984.             MSG_GetFolderLineByIndex(m_pane, selected[0], 1, &line);
  985.             
  986.             if (line.flags & MSG_FOLDER_FLAG_NEWSGROUP)
  987.                 return stringFromResource("newsgroupPropsCmdString");
  988.             else if (line.flags & MSG_FOLDER_FLAG_NEWS_HOST)
  989.                 return stringFromResource("newsServerPropsCmdString");
  990.             else /* mail */
  991.                 if (line.level == 1)
  992.                     return stringFromResource("mailServerPropsCmdString");
  993.                 else
  994.                     return stringFromResource("folderPropsCmdString");
  995.         }
  996.     else
  997.         {
  998.             return XFE_MNListView::commandToString(cmd, calldata, info);
  999.         }
  1000.     
  1001. #undef IS_CMD
  1002. }
  1003.  
  1004. fe_icon*
  1005. XFE_FolderView::treeInfoToIcon(int depth, int flags, XP_Bool expanded, XP_Bool secure)
  1006. {
  1007.     if (depth < 1)
  1008.         {
  1009.             if (flags & MSG_FOLDER_FLAG_NEWS_HOST)
  1010.               return secure ? &newsServerSecureIcon : &newsServerIcon;
  1011.             else if (flags & MSG_FOLDER_FLAG_IMAPBOX)
  1012.                 return &mailServerIcon;
  1013.             else
  1014.                 return &mailLocalIcon;
  1015.         }
  1016.  
  1017.     if (flags & MSG_FOLDER_FLAG_NEWSGROUP)
  1018.         return &newsgroupIcon;
  1019.     else if (flags & MSG_FOLDER_FLAG_INBOX)
  1020.         return expanded ? &inboxOpenIcon : &inboxIcon;
  1021.     else if (flags & MSG_FOLDER_FLAG_DRAFTS)
  1022.         return expanded ? &draftsOpenIcon : &draftsIcon;
  1023.     else if (flags & MSG_FOLDER_FLAG_TRASH)
  1024.         return &trashIcon;
  1025.     else if (flags & MSG_FOLDER_FLAG_QUEUE)
  1026.         return expanded ? &outboxOpenIcon : &outboxIcon;
  1027.     else if (flags & MSG_FOLDER_FLAG_IMAPBOX)
  1028.         return expanded ? &folderServerOpenIcon : &folderServerIcon;
  1029.     else
  1030.         return expanded ? &folderOpenIcon : &folderIcon;
  1031. }
  1032.  
  1033. #if defined(USE_MOTIF_DND)
  1034. fe_icon_data *
  1035. XFE_FolderView::treeInfoToIconData(int depth, int flags, XP_Bool expanded)
  1036. {
  1037.     if (depth < 1)
  1038.         {
  1039.             if (flags & MSG_FOLDER_FLAG_NEWS_HOST)
  1040.                 return &MN_NewsServer;
  1041.             else if (flags & MSG_FOLDER_FLAG_IMAPBOX)
  1042.                 return &MN_MailLocal; /* XXX ? */
  1043.             else
  1044.                 return &MN_MailLocal;
  1045.         }
  1046.  
  1047.     if (flags & MSG_FOLDER_FLAG_NEWSGROUP)
  1048.         return &MN_Newsgroup;
  1049.     else if (flags & MSG_FOLDER_FLAG_INBOX)
  1050.         return expanded ? &MN_InboxO : &MN_Inbox;
  1051.     else if (flags & MSG_FOLDER_FLAG_DRAFTS)
  1052.         return expanded ? &MN_DraftO : &MN_Draft;
  1053.     else if (flags & MSG_FOLDER_FLAG_TRASH)
  1054.         return &MN_TrashSmall;
  1055.     else if (flags & MSG_FOLDER_FLAG_QUEUE)
  1056.         return expanded ? &MN_OutboxO : &MN_Outbox;
  1057.     else if (flags & MSG_FOLDER_FLAG_IMAPBOX)
  1058.         return expanded ? &MN_FolderServerO : &MN_FolderServer;
  1059.     else
  1060.         return expanded ? &MN_FolderO : &MN_Folder;
  1061. }
  1062. #endif /* USE_MOTIF_DND */
  1063.  
  1064. /* Outlinable interface methods */
  1065. char *
  1066. XFE_FolderView::getColumnTextByFolderLine(MSG_FolderLine* folderLine, 
  1067.                                           int column)
  1068. {
  1069.     static char unseen[10];
  1070.     static char total[10];
  1071.     
  1072.     switch (column)
  1073.         {
  1074.         case OUTLINER_COLUMN_NAME:
  1075.             {
  1076.                 if (folderLine->prettyName)
  1077.                     return (char*)folderLine->prettyName;
  1078.                 else
  1079.                     return (char*)folderLine->name;
  1080.             }
  1081.         
  1082.         case OUTLINER_COLUMN_UNREAD:
  1083.             {
  1084.                 if (folderLine->level == 1
  1085.                     && folderLine->flags & MSG_FOLDER_FLAG_DIRECTORY)
  1086.                     {
  1087.                         return "---";
  1088.                     }
  1089.                 else
  1090.                     {
  1091.                         /* if we know how many unseen messages there are, 
  1092.                            display the number. otherwise, we put ???'s */
  1093.                         if (folderLine->unseen >= 0)
  1094.                             {
  1095.                                 PR_snprintf(unseen, sizeof (unseen), "%d", folderLine->unseen);
  1096.                                 
  1097.                                 return unseen;
  1098.                             }
  1099.                         else 
  1100.                             {
  1101.                                 return "???";
  1102.                             }
  1103.                     }
  1104.             }
  1105.         case OUTLINER_COLUMN_TOTAL:
  1106.             {
  1107.                 /* if the folder is a directory, just put dashes
  1108.                    for the total messages. */
  1109.                 if (folderLine->level == 1
  1110.                     && folderLine->flags & MSG_FOLDER_FLAG_DIRECTORY)
  1111.                     {
  1112.                         return "---";
  1113.                     }
  1114.                 else
  1115.                     {
  1116.                         /* if we know how many unseen messages there are, 
  1117.                            we also know how many total messages there are.
  1118.                            otherwise, we put ???'s */
  1119.                         if (folderLine->total >= 0)
  1120.                             {
  1121.                                 PR_snprintf(total, sizeof (total), "%d", folderLine->total);
  1122.                                 
  1123.                                 return total;
  1124.                             }
  1125.                         else 
  1126.                             {
  1127.                                 return "???";
  1128.                             }
  1129.                     }
  1130.             }
  1131.         default:
  1132.             XP_ASSERT(0);
  1133.             return NULL;
  1134.         }
  1135. }
  1136.  
  1137. char *XFE_FolderView::getCellTipString(int row, int column)
  1138. {
  1139.     /* returned string will be duplicated by outliner
  1140.      */
  1141.     char *tmp = 0;
  1142.     if (row < 0) {
  1143.         /* header
  1144.          */
  1145.         tmp = getColumnHeaderText(column);
  1146.     }/* if */
  1147.     else {
  1148.         /* content 
  1149.          */
  1150.         m_ancestorInfo = NULL;
  1151.  
  1152.         MSG_FolderLine* folderLine = 
  1153.             (MSG_FolderLine *) XP_CALLOC(1, sizeof(MSG_FolderLine));
  1154.  
  1155.         if (!MSG_GetFolderLineByIndex(m_pane, row, 1, folderLine))
  1156.             return NULL;
  1157.  
  1158.         /* static array; do not free
  1159.          */
  1160.         tmp = getColumnTextByFolderLine(folderLine, column);
  1161.         XP_FREEIF(folderLine);
  1162.     }/* else */
  1163.     if (tmp && 
  1164.         (!m_outliner->isColTextFit(tmp, row, column)))
  1165.         return tmp;
  1166.  
  1167.     return NULL;
  1168. }
  1169.  
  1170. char *XFE_FolderView::getCellDocString(int /* row */, int /* column */)
  1171. {
  1172.     return NULL;
  1173. }
  1174.  
  1175. void *
  1176. XFE_FolderView::ConvFromIndex(int index)
  1177. {
  1178.   return MSG_GetFolderInfo(m_pane, index);
  1179. }
  1180.  
  1181. int
  1182. XFE_FolderView::ConvToIndex(void *item)
  1183. {
  1184.   MSG_ViewIndex index = MSG_GetFolderIndex(m_pane, (MSG_FolderInfo*)item);
  1185.  
  1186.   if (index == MSG_VIEWINDEXNONE)
  1187.     return -1;
  1188.   else
  1189.     return index;
  1190. }
  1191.  
  1192. void *
  1193. XFE_FolderView::acquireLineData(int line)
  1194. {
  1195.   m_ancestorInfo = NULL;
  1196.  
  1197.   if (!MSG_GetFolderLineByIndex(m_pane, line, 1, &m_folderLine))
  1198.     return NULL;
  1199.  
  1200.   if ( m_folderLine.level > 0 ) 
  1201.     {
  1202.       m_ancestorInfo = new OutlinerAncestorInfo[ m_folderLine.level ];
  1203.     }
  1204.   else
  1205.     {
  1206.       m_ancestorInfo = new OutlinerAncestorInfo[ 1 ];
  1207.     }
  1208.       
  1209.   // ripped straight from the winfe
  1210.   int i = m_folderLine.level - 1;
  1211.   int idx = line + 1;
  1212.   int total_lines = m_outliner->getTotalLines();
  1213.   while ( i >  0 ) {
  1214.     if ( idx < total_lines ) {
  1215.         int level = MSG_GetFolderLevelByIndex(m_pane, idx);
  1216.         if ( (level - 1) == i ) {
  1217.             m_ancestorInfo[i].has_prev = TRUE;
  1218.             m_ancestorInfo[i].has_next = TRUE;
  1219.             i--;
  1220.             idx++;
  1221.         } else if ( (level - 1) < i ) {
  1222.             m_ancestorInfo[i].has_prev = FALSE;
  1223.             m_ancestorInfo[i].has_next = FALSE;
  1224.             i--;
  1225.         } else {
  1226.             idx++;
  1227.         }
  1228.     } else {
  1229.         m_ancestorInfo[i].has_prev = FALSE;
  1230.         m_ancestorInfo[i].has_next = FALSE;
  1231.       i--;
  1232.     }
  1233.   }
  1234.  
  1235.   m_ancestorInfo[0].has_prev = FALSE;
  1236.   m_ancestorInfo[0].has_next = FALSE;
  1237.   
  1238.   return &m_folderLine;
  1239. }
  1240.  
  1241. void
  1242. XFE_FolderView::getTreeInfo(XP_Bool *expandable,
  1243.                             XP_Bool *is_expanded,
  1244.                             int *depth,
  1245.                             OutlinerAncestorInfo **ancestor)
  1246. {
  1247.   XP_Bool is_line_expandable;
  1248.   XP_Bool is_line_expanded;
  1249.  
  1250.   is_line_expandable = ((m_folderLine.numChildren > 0) 
  1251.                         && !(m_folderLine.flags 
  1252.                              & MSG_FOLDER_FLAG_CAT_CONTAINER));
  1253.  
  1254.   if (is_line_expandable)
  1255.     {
  1256.       is_line_expanded = !(m_folderLine.flags & MSG_FOLDER_FLAG_ELIDED);
  1257.     }
  1258.   else
  1259.     {
  1260.       is_line_expanded = FALSE;
  1261.     }
  1262.  
  1263.   if (ancestor)
  1264.     *ancestor = m_ancestorInfo;
  1265.  
  1266.   if (depth)
  1267.     *depth = m_folderLine.level - 1;
  1268.  
  1269.   if (expandable)
  1270.     *expandable =  is_line_expandable;
  1271.  
  1272.   if (is_expanded)
  1273.     *is_expanded = is_line_expanded;
  1274. }
  1275.  
  1276. EOutlinerTextStyle 
  1277. XFE_FolderView::getColumnStyle(int /*column*/)
  1278. {
  1279.   return (m_folderLine.unseen > 0) ? OUTLINER_Bold : OUTLINER_Default;
  1280. }
  1281.  
  1282. char *
  1283. XFE_FolderView::getColumnText(int column)
  1284. {
  1285.     static char unseen_a[10]; /* uniquify name for IRIX5.3 */
  1286.     static char total_a[10];
  1287.     
  1288.     switch (column)
  1289.         {
  1290.         case OUTLINER_COLUMN_NAME:
  1291.             {
  1292.                 if (m_folderLine.prettyName)
  1293.                     return (char*)m_folderLine.prettyName;
  1294.                 else
  1295.                     return (char*)m_folderLine.name;
  1296.             }
  1297.         
  1298.         case OUTLINER_COLUMN_UNREAD:
  1299.             {
  1300.                 if (m_folderLine.level == 1
  1301.                     && m_folderLine.flags & MSG_FOLDER_FLAG_DIRECTORY)
  1302.                     {
  1303.                         return "---";
  1304.                     }
  1305.                 else
  1306.                     {
  1307.                         /* if we know how many unseen messages there are, 
  1308.                            display the number. otherwise, we put ???'s */
  1309. #if defined(DEBUG_tao)
  1310.                         if (m_folderLine.unseen < 0)
  1311.                             printf("\n**OUTLINER_COLUMN_UNREAD=%d\n", 
  1312.                                    m_folderLine.unseen);
  1313. #endif
  1314.                         if (m_folderLine.unseen >= 0)
  1315.                             {
  1316.                                 PR_snprintf(unseen_a, sizeof (unseen_a), "%d", m_folderLine.unseen);
  1317.                                 
  1318.                                 return unseen_a;
  1319.                             }
  1320.                         else 
  1321.                             {
  1322.                                 return "???";
  1323.                             }
  1324.                     }
  1325.             }
  1326.         case OUTLINER_COLUMN_TOTAL:
  1327.             {
  1328.                 /* if the folder is a directory, just put dashes
  1329.                    for the total messages. */
  1330.                 if (m_folderLine.level == 1
  1331.                     && m_folderLine.flags & MSG_FOLDER_FLAG_DIRECTORY)
  1332.                     {
  1333.                         return "---";
  1334.                     }
  1335.                 else
  1336.                     {
  1337.                         /* if we know how many unseen messages there are, 
  1338.                            we also know how many total messages there are.
  1339.                            otherwise, we put ???'s */
  1340. #if defined(DEBUG_tao)
  1341.                         if (m_folderLine.total < 0)
  1342.                             printf("\n**OUTLINER_COLUMN_TOTAL=%d\n", m_folderLine.total);
  1343. #endif
  1344.                         if (m_folderLine.total >= 0)
  1345.                             {
  1346.                                 PR_snprintf(total_a, sizeof (total_a), "%d", m_folderLine.total);
  1347.                                 
  1348.                                 return total_a;
  1349.                             }
  1350.                         else 
  1351.                             {
  1352.                                 return "???";
  1353.                             }
  1354.                     }
  1355.             }
  1356.         default:
  1357.             XP_ASSERT(0);
  1358.             return NULL;
  1359.         }
  1360. }
  1361.  
  1362. fe_icon *
  1363. XFE_FolderView::getColumnIcon(int column)
  1364. {
  1365.   XP_Bool expanded;
  1366.   int depth;
  1367.  
  1368.   getTreeInfo(NULL, &expanded, &depth, NULL);
  1369.  
  1370.   if (column == OUTLINER_COLUMN_NAME)
  1371.     {
  1372.       XP_Bool secure = False;
  1373.       /* we need to check if newshosts are secure */
  1374.       if (m_folderLine.flags & MSG_FOLDER_FLAG_NEWS_HOST)
  1375.         {
  1376.           MSG_NewsHost *host = MSG_GetNewsHostForFolder(m_folderLine.id);
  1377.           if (host)
  1378.             secure = MSG_IsNewsHostSecure(host);
  1379.         }
  1380.  
  1381.         return treeInfoToIcon(depth, m_folderLine.flags, expanded, secure);
  1382.     }
  1383.   else
  1384.     {
  1385.       return 0;
  1386.     }
  1387. }
  1388.  
  1389. char *
  1390. XFE_FolderView::getColumnName(int column)
  1391. {
  1392.   switch (column)
  1393.     {
  1394.     case OUTLINER_COLUMN_NAME:
  1395.       return "Name";
  1396.     case OUTLINER_COLUMN_TOTAL:
  1397.       return "Total";
  1398.     case OUTLINER_COLUMN_UNREAD:
  1399.       return "Unread";
  1400.     default:
  1401.       XP_ASSERT(0);
  1402.       return 0;
  1403.     }
  1404. }
  1405.  
  1406. char *
  1407. XFE_FolderView::getColumnHeaderText(int column)
  1408. {
  1409.   switch (column)
  1410.     {
  1411.     case OUTLINER_COLUMN_NAME:
  1412.         return XP_GetString(XFE_FOLDER_OUTLINER_COLUMN_NAME);
  1413.     case OUTLINER_COLUMN_TOTAL:
  1414.         return XP_GetString(XFE_FOLDER_OUTLINER_COLUMN_TOTAL);
  1415.     case OUTLINER_COLUMN_UNREAD:
  1416.         return XP_GetString(XFE_FOLDER_OUTLINER_COLUMN_UNREAD);
  1417.     default:
  1418.       XP_ASSERT(0);
  1419.       return 0;
  1420.     }
  1421. }
  1422.  
  1423. fe_icon *
  1424. XFE_FolderView::getColumnHeaderIcon(int /*column*/)
  1425. {
  1426.   return 0;
  1427. }
  1428.  
  1429. EOutlinerTextStyle
  1430. XFE_FolderView::getColumnHeaderStyle(int /*column*/)
  1431. {
  1432.   return OUTLINER_Default;
  1433. }
  1434.  
  1435. void
  1436. XFE_FolderView::releaseLineData()
  1437. {
  1438.   delete [] m_ancestorInfo;
  1439.   m_ancestorInfo = NULL;
  1440. }
  1441.  
  1442. #ifdef USE_3PANE
  1443. static void
  1444. click_timer_func(XtPointer closure, XtIntervalId *)
  1445. {
  1446.     XFE_FolderView* fv = (XFE_FolderView*)closure;
  1447.     DD(printf("---::: Process timer :::---\n");)
  1448.     if (fv)
  1449.         fv->processClick();
  1450. }
  1451. #endif
  1452.  
  1453. void 
  1454. XFE_FolderView::Buttonfunc(const OutlineButtonFuncData *data)
  1455. {
  1456.   MSG_FolderLine line;
  1457.  
  1458.   // Broadcast to be in focus
  1459.   getToplevel()->notifyInterested(XFE_MNListView::changeFocus, (void*) this);
  1460.  
  1461.   if (!MSG_GetFolderLineByIndex(m_pane, data->row, 1, &line)) return;
  1462.   
  1463.  
  1464.   DD(printf("###  times folder clicked %d\n", data->clicks);)
  1465.   if (data->clicks == 2) 
  1466.       {
  1467. #ifdef USE_3PANE
  1468.         if (m_clickTimer)
  1469.             XtRemoveTimeOut(m_clickTimer);
  1470.         m_clickTimer = 0;
  1471.         DD(printf("---::: Remove timer :::---\n");)
  1472.  
  1473.         for (int i = 0; i < m_cur_count; i++ )
  1474.         {
  1475.           if ( i == 0 )
  1476.              m_outliner->selectItemExclusive(m_cur_selected[i]);
  1477.           else
  1478.              m_outliner->selectItem(m_cur_selected[i]);
  1479.         }
  1480. #else
  1481.           m_outliner->selectItemExclusive(data->row);
  1482. #endif
  1483.           
  1484.           if (line.level == 1
  1485.               && line.flags & MSG_FOLDER_FLAG_DIRECTORY)
  1486.               {
  1487.                   // they double clicked on a newshost or mail server.
  1488.                   toggleExpansion(data->row);
  1489.               }
  1490.           else
  1491.               {
  1492.                   // ok.  we're going to display a folder in a thread frame.  what
  1493.                   // is left to do now is determine whether we are going to reuse
  1494.                   // an existing one or pop up another.  This is governed by the
  1495.                   // preference reuse_thread_window and whether or not
  1496.                   // the alt button was held during the double click.
  1497.                   
  1498.                   fe_showMessages(XtParent(getToplevel()->getBaseWidget()),
  1499.                                   ViewGlue_getFrame(m_contextData),
  1500.                                   NULL,
  1501.                                   MSG_GetFolderInfo(m_pane, data->row),
  1502.                                   (( fe_globalPrefs.reuse_thread_window
  1503.                                      && !data->shift)
  1504.                                    || (!fe_globalPrefs.reuse_thread_window
  1505.                                        && data->shift)),
  1506.                                   False,
  1507.                                   MSG_MESSAGEKEYNONE);
  1508.               }
  1509.       }
  1510.   else
  1511.       {
  1512.           if (data->ctrl)
  1513.               {
  1514.                   m_outliner->toggleSelected(data->row);
  1515.               }
  1516.           else if (data->shift)
  1517.               {
  1518.                   // select the range.
  1519.                   const int *selected;
  1520.                   int count;
  1521.                   
  1522.                   m_outliner->getSelection(&selected, &count);
  1523.                   
  1524.                   if (count == 0) /* there wasn't anything selected yet. */
  1525.                       {
  1526.                           m_outliner->selectItemExclusive(data->row);
  1527.                       }
  1528.                   else if (count == 1) /* there was only one, so we select the range from
  1529.                                           that item to the new one. */
  1530.                       {
  1531.                           m_outliner->selectRangeByIndices(selected[0], data->row);
  1532.                       }
  1533.                   else /* we had a range of items selected, so let's do something really
  1534.                           nice with them. */
  1535.                       {
  1536.                           m_outliner->trimOrExpandSelection(data->row);
  1537.                       }
  1538.               }
  1539.           else
  1540.               {
  1541.  
  1542. #ifdef USE_3PANE
  1543.                 const int *selected;
  1544.                 int count;
  1545.                   m_outliner->getSelection(&selected, &count);
  1546.  
  1547.                 m_cur_selected= (int *)XP_CALLOC(count, sizeof(int));
  1548.                 for ( int i =0; i < count; i++ )
  1549.                     m_cur_selected[i] = selected[i];
  1550.                 m_cur_count = count;
  1551.  
  1552.                   m_outliner->selectItemExclusive(data->row);
  1553.                 m_clickData = (XtPointer)data;
  1554.                 if (m_clickTimer)
  1555.                     XtRemoveTimeOut(m_clickTimer);
  1556.                         m_clickTimer = XtAppAddTimeOut(fe_XtAppContext, 650,
  1557.                                               click_timer_func, this);
  1558.                 DD(printf("### ---::: Install timer :::--- ###\n");)
  1559. #else
  1560.  
  1561.                   m_outliner->selectItemExclusive(data->row);
  1562.                   
  1563.                   notifyInterested(folderSelected, MSG_GetFolderInfo(m_pane, data->row));
  1564. #endif
  1565.               }
  1566.           
  1567.           getToplevel()->notifyInterested(XFE_View::chromeNeedsUpdating);
  1568.       }
  1569. }
  1570.  
  1571.  
  1572. #ifdef USE_3PANE
  1573. // This is the routine that will select a folder for single click.
  1574. void
  1575. XFE_FolderView::processClick()
  1576. {
  1577.     OutlineButtonFuncData *data = (OutlineButtonFuncData *)m_clickData;
  1578.  
  1579.     MSG_FolderInfo *info = MSG_GetFolderInfo(m_pane, data->row);
  1580.     XFE_ThreadFrame *theFrame = XFE_ThreadFrame::frameForInfo(info);
  1581.  
  1582.     if ( theFrame)
  1583.     {
  1584.     // if the frame exists, then, single click perform the
  1585.     // same way as the double click mode by bringing the existing
  1586.     // frame to the foreground
  1587. #if 0
  1588.     for (int i = 0; i < m_cur_count; i++ )
  1589.           m_outliner->selectItemExclusive(m_cur_selected[i]);
  1590. #endif
  1591.           fe_showMessages(XtParent(getToplevel()->getBaseWidget()),
  1592.                   ViewGlue_getFrame(m_contextData),
  1593.                   NULL,
  1594.                   MSG_GetFolderInfo(m_pane, data->row),
  1595.                   (( fe_globalPrefs.reuse_thread_window
  1596.                          && !data->shift)
  1597.                    || (!fe_globalPrefs.reuse_thread_window
  1598.                        && data->shift)),
  1599.                   False,
  1600.                   MSG_MESSAGEKEYNONE);
  1601.     }
  1602.     else
  1603.     {
  1604.      m_outliner->selectItemExclusive(data->row);
  1605.      notifyInterested(folderSelected, info);
  1606.     }
  1607.     m_clickTimer = 0;
  1608.     XP_FREEIF(m_cur_selected);
  1609.     m_cur_selected = NULL;
  1610.     m_cur_count = 0 ;
  1611.                   
  1612. }
  1613. #endif
  1614.  
  1615. void
  1616. XFE_FolderView::toggleExpansion(int row)
  1617. {
  1618.     int delta;
  1619.     XP_Bool selection_needs_bubbling = False;
  1620.  
  1621.     delta = MSG_ExpansionDelta(m_pane, row);
  1622.  
  1623.     if (delta == 0)
  1624.         return;
  1625.  
  1626.     /* we're not selected and we're being collapsed.
  1627.        check if any of our children are selected, and if
  1628.        so we select this row. */
  1629.     if (!m_outliner->isSelected(row)
  1630.         && delta < 0)
  1631.         {
  1632.             int num_children = -1 * delta;
  1633.             int i;
  1634.             
  1635.             for (i = row + 1; i <= row + num_children; i ++)
  1636.                 if (m_outliner->isSelected(i))
  1637.                     {
  1638.                         selection_needs_bubbling = True;
  1639.                     }
  1640.         }
  1641.  
  1642.     MSG_ToggleExpansion(m_pane, row, NULL);
  1643.  
  1644.     if (selection_needs_bubbling)
  1645.         m_outliner->selectItem(row);
  1646.  
  1647.     getToplevel()->notifyInterested(XFE_View::chromeNeedsUpdating);
  1648. }
  1649.  
  1650. void
  1651. XFE_FolderView::Flippyfunc(const OutlineFlippyFuncData *data)
  1652. {
  1653.     toggleExpansion(data->row);
  1654. }
  1655.  
  1656. #if !defined(USE_MOTIF_DND)
  1657.  
  1658. void
  1659. XFE_FolderView::dropfunc(Widget /*dropw*/, fe_dnd_Event type,
  1660.                          fe_dnd_Source *source, XEvent *event)
  1661. {
  1662.     int row = -1;
  1663.     int x, y;
  1664.  
  1665.     /* we only understand these targets -- well, we only understand the last 3,
  1666.        and the outliner understands the first one. */
  1667.     if (source->type != FE_DND_COLUMN &&
  1668.         source->type != FE_DND_MAIL_MESSAGE &&
  1669.         source->type != FE_DND_NEWS_MESSAGE &&
  1670.         source->type != FE_DND_MAIL_FOLDER) 
  1671.         {
  1672.             return;
  1673.         }
  1674.     
  1675.     if (source->type == FE_DND_COLUMN)
  1676.         {
  1677.             m_outliner->handleDragEvent(event, type, source);
  1678.             
  1679.             return;
  1680.         }
  1681.     
  1682.     /* we've got to have a sourcedropfunc to drop things in a folder view,
  1683.        since the work must really be done by the source. */
  1684.     if (source->func == NULL)
  1685.         {
  1686.             return;
  1687.         }
  1688.     
  1689.     m_outliner->translateFromRootCoords(event->xbutton.x_root, event->xbutton.y_root, &x, &y);
  1690.     
  1691.     row = m_outliner->XYToRow(x, y);
  1692.     
  1693.     if (row >= 0) 
  1694.         {
  1695.             MSG_FolderLine folder;
  1696.             if (!MSG_GetFolderLineByIndex(m_pane,
  1697.                                           row, 1, &folder))
  1698.                 row = -1;
  1699.         }
  1700.     
  1701.     switch (type) 
  1702.         {
  1703.         case FE_DND_START:
  1704.             DD(printf("### DRAG> button press = %d\n", ((event->xany.type == ButtonPress)? 1: 0 ) );)
  1705.             DD(printf("### DRAG> button release = %d\n", ((event->xany.type == ButtonRelease)? 1: 0 ) );)
  1706.             DD(printf("### DRAG> alt key state = %d\n", ((event->xkey.state &Mod1Mask)? 1: 0 ) );)
  1707.             /* ### In outliner, we set ignoreevent to true when the event
  1708.                type is ButtonPress; therefore, we won't be getting
  1709.                button press event here. We cannot perform stealth command
  1710.                at button press time when drag take place. We can only
  1711.                perform stealth command at button release time. Need
  1712.                to find out why we set "ignoreevnt" to true in outliner. ### */
  1713. #if 0
  1714.             CONTEXT_DATA(m_contextData)->stealth_cmd =
  1715.                             ((event->xany.type == ButtonPress) &&
  1716.                                   (event->xkey.state & Mod1Mask));
  1717. #endif
  1718.             break;
  1719.         case FE_DND_DRAG:
  1720.             m_outliner->outlineLine(row);
  1721.             break;
  1722.         case FE_DND_DROP:
  1723.             DD(printf("### DROP> button press = %d\n", ((event->xany.type == ButtonPress)? 1: 0 ) );)
  1724.             DD(printf("### DROP> button release = %d\n", ((event->xany.type == ButtonRelease)? 1: 0 ) );)
  1725.             DD(printf("### DROP> alt key state = %d\n", ((event->xkey.state &Mod1Mask)? 1: 0 ) );)
  1726.             CONTEXT_DATA(m_contextData)->stealth_cmd =
  1727.                             ((event->xany.type == ButtonRelease) &&
  1728.                                   (event->xkey.state & Mod1Mask));
  1729.             if (row >= 0)
  1730.             {
  1731.                MSG_FolderInfo *drop_info = MSG_GetFolderInfo(m_pane, row);
  1732.                 
  1733.                if (drop_info)
  1734.                {
  1735.                 fe_dnd_Message  msg;
  1736.                 if ( source->type == FE_DND_NEWS_MESSAGE )
  1737.                 {
  1738.                     DD(printf("### FolderView::dropfunc:  NEWS MESSAGE_COPY ******\n");)
  1739.                     msg = FE_DND_MESSAGE_COPY;
  1740.                 }
  1741.                 else if (( source->type == FE_DND_MAIL_MESSAGE) && 
  1742.                     (CONTEXT_DATA(m_contextData)->stealth_cmd ))
  1743.                 {
  1744.                     DD(printf("### FolderView::dropfunc:  MAIL MESSAGE_COPY ******\n");)
  1745.                     msg = FE_DND_MESSAGE_COPY;
  1746.                 }
  1747.                 else 
  1748.                 {
  1749.                     DD(printf("### FolderView::dropfunc: MAIL MESSAGE_MOVE ******\n");)
  1750.                     msg = FE_DND_MESSAGE_MOVE;
  1751.                 }
  1752.                 (*source->func)(source, msg, (void*)drop_info);
  1753.                }
  1754.                     
  1755.                D(printf ("Outlining line -1\n");)
  1756.                     
  1757.                m_outliner->outlineLine(-1); // to clear the drag feedback
  1758.             }
  1759.         }
  1760. }
  1761.  
  1762. void
  1763. XFE_FolderView::drop_func(Widget dropw, void *closure, fe_dnd_Event type,
  1764.               fe_dnd_Source *source, XEvent* event)
  1765. {
  1766.   XFE_FolderView *obj = (XFE_FolderView*)closure;
  1767.  
  1768.   obj->dropfunc(dropw, type, source, event);
  1769. }
  1770.  
  1771. void
  1772. XFE_FolderView::sourcedropfunc(fe_dnd_Source *, fe_dnd_Message msg, void *closure)
  1773. {
  1774.   // folders can be moved or deleted.  The closure to this function will always
  1775.   // be a MSG_FolderInfo*.
  1776.  
  1777.   // XXX assume that nothing could have changed the selected between the time
  1778.   // we started dragging and now...  don't know how smart this is...
  1779.  
  1780.   MSG_FolderInfo *info = (MSG_FolderInfo*)closure;
  1781.   const int *indices;
  1782.   int count;
  1783.  
  1784.   DD(printf("### Enter XFE_FolderView::sourcedropfunc()\n");)
  1785.   m_outliner->getSelection(&indices, &count);
  1786.  
  1787.   MSG_DragEffect requireEffect = MSG_Default_Drag;
  1788.  
  1789.   MSG_DragEffect effect = MSG_DragFoldersIntoStatus(m_pane,
  1790.                         (MSG_ViewIndex*)indices, count,
  1791.                         info, requireEffect);
  1792.  
  1793.  
  1794.  
  1795.   if (msg == FE_DND_MESSAGE_MOVE )
  1796.     {
  1797.       DD(printf("### XFE_FolderView::sourcedropfunc:: FE_DND_MESSAGE_MOVE ##\n");)
  1798.       if (effect == MSG_Require_Move)
  1799.       {
  1800.       DD(printf("## XFE_FolderView::sourcedropfunc:: Move FOLDER REQUIRED ##\n");)
  1801.         MSG_MoveFoldersInto(m_pane, (MSG_ViewIndex*)indices, count, info);
  1802.     XFE_MozillaApp::theApp()->notifyInterested(XFE_MNView::foldersHaveChanged);
  1803.       }
  1804.       else if ( effect == MSG_Drag_Not_Allowed )
  1805.       {
  1806.         DD(printf("### Drag NOT allowed : DROP SITE \n");)
  1807.         char tmp[128];
  1808.         XP_SAFE_SPRINTF(tmp, sizeof(tmp),
  1809.                         "%s",
  1810.                         XP_GetString(XFE_DND_MESSAGE_ERROR));
  1811.         XFE_Progress (m_contextData, tmp);
  1812.       }
  1813.       else 
  1814.     XP_ASSERT(0);
  1815.  
  1816.     }
  1817.   else if (msg == FE_DND_MESSAGE_DELETE)
  1818.     {
  1819.       // do something spiffy here, like unsubscribe if it's a newsgroup,
  1820.       // and move to the trash if it's a mail folder.
  1821.     }
  1822. }
  1823.  
  1824. void
  1825. XFE_FolderView::source_drop_func(fe_dnd_Source *src, fe_dnd_Message msg, void *closure)
  1826. {
  1827.   XFE_FolderView *obj = (XFE_FolderView*)src->closure;
  1828.  
  1829.   obj->sourcedropfunc(src, msg,closure);
  1830. }
  1831.  
  1832. #else
  1833.  
  1834. fe_icon_data *
  1835. XFE_FolderView::GetDragIconData(int row, int column)
  1836. {
  1837.   D(printf("XFE_FolderView::GetDragIconData()\n");)
  1838.   XP_Bool expanded;
  1839.   int depth;
  1840.   
  1841.   if (row == -1) return &MN_Folder;
  1842.   else
  1843.     {
  1844.       acquireLineData(row);
  1845.       getTreeInfo(NULL, &expanded, &depth, NULL);
  1846.       releaseLineData();
  1847.       return treeInfoToIconData(depth, m_folderLine.flags, expanded);
  1848.     }
  1849. }
  1850.  
  1851. fe_icon_data *
  1852. XFE_FolderView::getDragIconData(void *this_ptr,
  1853.                                 int row,
  1854.                                 int column)
  1855. {
  1856.   D(printf("XFE_FolderView::getDragIconData()\n");)
  1857.   XFE_FolderView *folder_view = (XFE_FolderView*)this_ptr;
  1858.  
  1859.   return folder_view->GetDragIconData(row, column);
  1860. }
  1861.  
  1862. void
  1863. XFE_FolderView::GetDragTargets(int row, int column,
  1864.                                Atom **targets,
  1865.                                int *num_targets)
  1866. {
  1867.   D(printf("XFE_FolderView::GetDragTargets()\n");)
  1868.   int depth;
  1869.   int flags;
  1870.  
  1871.   XP_ASSERT(row > -1);
  1872.   if (row == -1)
  1873.     {
  1874.       *targets = NULL;
  1875.       *num_targets = 0;
  1876.     }
  1877.   else
  1878.     {
  1879.       if (!m_outliner->isSelected(row))
  1880.         m_outliner->selectItemExclusive(row);
  1881.  
  1882.       acquireLineData(row);
  1883.       getTreeInfo(NULL, NULL, &depth, NULL);
  1884.       flags = m_folderLine.flags;
  1885.       releaseLineData();
  1886.       
  1887.       *num_targets = 3;
  1888.       *targets = new Atom[ *num_targets ];
  1889.  
  1890.       (*targets)[1] = XFE_DragBase::_XA_NETSCAPE_URL;
  1891.       (*targets)[2] = XA_STRING;
  1892.  
  1893.       if (depth < 1)
  1894.         {
  1895.           if (flags & MSG_FOLDER_FLAG_NEWS_HOST)
  1896.             (*targets)[0] = XFE_OutlinerDrop::_XA_NETSCAPE_NEWS_SERVER;
  1897.           else
  1898.             (*targets)[0] = XFE_OutlinerDrop::_XA_NETSCAPE_MAIL_SERVER;
  1899.         }
  1900.       else if (flags & MSG_FOLDER_FLAG_NEWSGROUP)
  1901.         (*targets)[0] = XFE_OutlinerDrop::_XA_NETSCAPE_NEWSGROUP;
  1902.       else
  1903.         (*targets)[0] = XFE_OutlinerDrop::_XA_NETSCAPE_MAIL_FOLDER;
  1904.     }
  1905. }
  1906.  
  1907. void
  1908. XFE_FolderView::getDragTargets(void *this_ptr,
  1909.                                int row,
  1910.                                int column,
  1911.                                Atom **targets,
  1912.                                int *num_targets)
  1913. {
  1914.   D(printf("XFE_FolderView::getDragTargets()\n");)
  1915.   XFE_FolderView *folder_view = (XFE_FolderView*)this_ptr;
  1916.  
  1917.   folder_view->GetDragTargets(row, column, targets, num_targets);
  1918. }
  1919.  
  1920. void 
  1921. XFE_FolderView::getDropTargets(void */*this_ptr*/,
  1922.                                Atom **targets,
  1923.                                int *num_targets)
  1924. {
  1925.   D(printf("XFE_FolderView::getDropTargets()\n");)
  1926.   *num_targets = 7;
  1927.   *targets = new Atom[ *num_targets ];
  1928.  
  1929.   (*targets)[0] = XFE_OutlinerDrop::_XA_NETSCAPE_MAIL_FOLDER;
  1930.   (*targets)[1] = XFE_OutlinerDrop::_XA_NETSCAPE_MAIL_MESSAGE;
  1931.   (*targets)[2] = XFE_OutlinerDrop::_XA_NETSCAPE_MAIL_SERVER;
  1932.   (*targets)[3] = XFE_OutlinerDrop::_XA_NETSCAPE_NEWSGROUP;
  1933.   (*targets)[4] = XFE_OutlinerDrop::_XA_NETSCAPE_NEWS_MESSAGE;
  1934.   (*targets)[5] = XFE_OutlinerDrop::_XA_NETSCAPE_NEWS_SERVER;
  1935.   (*targets)[6] = XFE_OutlinerDrop::_XA_NETSCAPE_URL; /* a specialized class of urls are allowed. */
  1936. }
  1937.  
  1938. char *
  1939. XFE_FolderView::DragConvert(Atom atom)
  1940. {
  1941.   if (atom == XFE_DragBase::_XA_NETSCAPE_URL)
  1942.     {
  1943.       // translate drag data to NetscapeURL format
  1944.       XFE_URLDesktopType urlData;
  1945.       char *result;
  1946.       const int *selection;
  1947.       int count;
  1948.       int i;
  1949.  
  1950.       m_outliner->getSelection(&selection, &count);
  1951.  
  1952.       urlData.createItemList(1);
  1953.  
  1954.       for (i = 0; i < count; i ++)
  1955.         {
  1956.           MSG_FolderInfo* info = MSG_GetFolderInfo(m_pane, selection[i]);
  1957.           URL_Struct *url = MSG_ConstructUrlForFolder(m_pane,
  1958.                                                       info);
  1959.           urlData.url(i,url->address);
  1960.           
  1961.           NET_FreeURLStruct(url);
  1962.         }
  1963.  
  1964.       result = XtNewString(urlData.getString());
  1965.       
  1966.       return result;
  1967.     }
  1968.   else if (atom == XFE_OutlinerDrop::_XA_NETSCAPE_MAIL_FOLDER
  1969.            || atom == XFE_OutlinerDrop::_XA_NETSCAPE_NEWSGROUP
  1970.            || atom == XFE_OutlinerDrop::_XA_NETSCAPE_MAIL_SERVER
  1971.            || atom == XFE_OutlinerDrop::_XA_NETSCAPE_NEWS_SERVER)
  1972.     {
  1973.       /* for now we use a hack -- only transfer the index of the dragged
  1974.          folder. */
  1975.       char buf[100];
  1976.       const int *selection;
  1977.       int count;
  1978.  
  1979.       m_outliner->getSelection(&selection, &count);
  1980.  
  1981.       PR_snprintf(buf, 100, "%d",
  1982.                   selection[0]);
  1983.  
  1984.       return (char*)XtNewString(buf);
  1985.     }
  1986.   else
  1987.     {
  1988.       return (char*)XtNewString("");
  1989.     }
  1990. }
  1991.  
  1992. char *
  1993. XFE_FolderView::dragConvert(void *this_ptr,
  1994.                             Atom atom)
  1995. {
  1996.   XFE_FolderView *folder_view = (XFE_FolderView*)this_ptr;
  1997.   
  1998.   return folder_view->DragConvert(atom);
  1999. }
  2000.  
  2001. int
  2002. XFE_FolderView::ProcessTargets(int row, int col,
  2003.                                Atom *targets,
  2004.                                const char **data,
  2005.                                int numItems)
  2006. {
  2007.   int i;
  2008.  
  2009.   D(printf("XFE_FolderView::ProcessTargets()\n");)
  2010.  
  2011.   for (i = 0; i<numItems; i ++)
  2012.     {
  2013.       if (targets[i]==None || data[i]==NULL || strlen(data[i])==0)
  2014.         continue;
  2015.  
  2016.       D(("  [%d] %s: \"%s\"\n",i,XmGetAtomName(XtDisplay(m_widget),targets[i]),data[i]));
  2017.  
  2018.       if (targets[i] == XFE_OutlinerDrop::_XA_NETSCAPE_MAIL_FOLDER
  2019.           || targets[i] == XFE_OutlinerDrop::_XA_NETSCAPE_NEWSGROUP)
  2020.         {
  2021.           MSG_ViewIndex index = (MSG_ViewIndex)atoi(data[i]);
  2022.           MSG_FolderInfo *info = MSG_GetFolderInfo(m_pane, row);
  2023.  
  2024.           if (info)
  2025.             {
  2026.               MSG_MoveFoldersInto(m_pane, &index, 1, info);
  2027.               return TRUE;
  2028.             }
  2029.           else
  2030.             return FALSE;
  2031.         }
  2032.       else if (targets[i] == XFE_OutlinerDrop::_XA_NETSCAPE_MAIL_MESSAGE
  2033.                || targets[i] == XFE_OutlinerDrop::_XA_NETSCAPE_NEWS_MESSAGE)
  2034.         {
  2035.           return TRUE;
  2036.         }
  2037.       else if (targets[i] == XFE_OutlinerDrop::_XA_NETSCAPE_URL)
  2038.         {
  2039.           MSG_FolderInfo *dest_info = MSG_GetFolderInfo(m_pane, row);
  2040.           XFE_URLDesktopType urlData(data[i]);
  2041.           MSG_ViewIndex *indices;
  2042.           int num_indices = 0;
  2043.  
  2044.           if (dest_info == NULL) return FALSE;
  2045.  
  2046.           indices = new MSG_ViewIndex[ urlData.numItems() ];
  2047.           for (i = 0; i < urlData.numItems(); i ++)
  2048.             {
  2049.               const char *url = urlData.url(i);
  2050.  
  2051.               if (MSG_PaneTypeForURL(url) != MSG_FOLDERPANE)
  2052.                 continue;
  2053.               else
  2054.                 {
  2055.                   MSG_FolderInfo *info = MSG_GetFolderInfoFromURL(m_master,
  2056.                                                                   url);
  2057.                   MSG_ViewIndex new_index;
  2058.  
  2059.                   if (!info)
  2060.                     continue;
  2061.  
  2062.                   new_index = MSG_GetFolderIndexForInfo(m_pane,
  2063.                                                         info, TRUE);
  2064.  
  2065.                   if (new_index != MSG_VIEWINDEXNONE)
  2066.                     indices[num_indices ++] = new_index;
  2067.                 }
  2068.             }
  2069.  
  2070.           if (num_indices > 0)
  2071.             MSG_MoveFoldersInto(m_pane, indices, num_indices, dest_info);
  2072.  
  2073.           
  2074.           delete [] indices;
  2075.           return num_indices > 0;
  2076.         }
  2077.     }
  2078.  
  2079.   return FALSE;
  2080. }
  2081.  
  2082. int
  2083. XFE_FolderView::processTargets(void *this_ptr,
  2084.                                int row, int col,
  2085.                                Atom *targets,
  2086.                                const char **data,
  2087.                                int numItems)
  2088. {
  2089.   XFE_FolderView *folder_view = (XFE_FolderView*)this_ptr;
  2090.   
  2091.   return folder_view->ProcessTargets(row, col, targets, data, numItems);
  2092. }
  2093. #endif /* USE_MOTIF_DND */
  2094.