/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- * * The contents of this file are subject to the Netscape Public * License Version 1.1 (the "License"); you may not use this file * except in compliance with the License. You may obtain a copy of * the License at http://www.mozilla.org/NPL/ * * Software distributed under the License is distributed on an "AS * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or * implied. See the License for the specific language governing * rights and limitations under the License. * * The Original Code is mozilla.org code. * * The Initial Developer of the Original Code is Netscape * Communications Corporation. Portions created by Netscape are * Copyright (C) 1998 Netscape Communications Corporation. All * Rights Reserved. * * Contributor(s): */ /* FolderView.cpp -- presents view of mail folders and newsgroups/hosts. Created: Chris Toshok , 7-Aug-96. */ #include "rosetta.h" #include "FolderView.h" #include "SubscribeDialog.h" /* for fe_showSubscribeDialog */ #include "ThreadFrame.h" /* for fe_showMessages */ #if defined(USE_MOTIF_DND) #include "ThreadView.h" #endif /* USE_MOTIF_DND */ #include "ViewGlue.h" #include "Outliner.h" #if defined(USE_MOTIF_DND) #include "OutlinerDrop.h" #endif /* USE_MOTIF_DND */ #include "MozillaApp.h" #include "NewsServerDialog.h" #include "xfe.h" #include "icondata.h" #include "msgcom.h" #include "felocale.h" /* for fe_ConvertToLocalEncoding */ #include "xp_mem.h" #include "Xfe/Xfe.h" #include "NewsServerPropDialog.h" #include "NewsgroupPropDialog.h" #include "MailFolderPropDialog.h" #include "MNSearchFrame.h" #include "LdapSearchFrame.h" #include "MailFilterDlg.h" #include "prefs.h" #ifdef DEBUG_toshok #define D(x) x #else #define D(x) #endif #ifdef DEBUG_dora #define DD(x) x #else #define DD(x) #endif #define FOLDER_OUTLINER_GEOMETRY_PREF "mail.folderpane.outliner_geometry" // bloody entrails dragging behind.... weighing me down... extern "C" void fe_sec_logo_cb (Widget, XtPointer, XtPointer); const char *XFE_FolderView::folderSelected = "XFE_FolderView::folderSelected"; const char *XFE_FolderView::folderDblClicked = "XFE_FolderView::folderDblClicked"; const char *XFE_FolderView::folderAltDblClicked = "XFE_FolderView::folderAltDblClicked"; const int XFE_FolderView::OUTLINER_COLUMN_NAME = 0; const int XFE_FolderView::OUTLINER_COLUMN_UNREAD = 1; const int XFE_FolderView::OUTLINER_COLUMN_TOTAL = 2; #include "xpgetstr.h" extern int XFE_FOLDER_OUTLINER_COLUMN_NAME; extern int XFE_FOLDER_OUTLINER_COLUMN_TOTAL; extern int XFE_FOLDER_OUTLINER_COLUMN_UNREAD; extern int XFE_DND_MESSAGE_ERROR; MenuSpec XFE_FolderView::mailserver_popup_menu[] = { #if 0 { xfeCmdUpdateMessageCount, PUSHBUTTON }, #endif { xfeCmdNewFolder, PUSHBUTTON }, { xfeCmdViewProperties, PUSHBUTTON }, { NULL } }; MenuSpec XFE_FolderView::newshost_popup_menu[] = { // From the spec: // "Open Discussion Group Server" -- is that xfeCmdGetNewGroups? { xfeCmdAddNewsgroup, PUSHBUTTON }, #if 0 { xfeCmdUpdateMessageCount, PUSHBUTTON }, #endif { xfeCmdDeleteFolder, PUSHBUTTON }, { xfeCmdViewProperties, PUSHBUTTON }, { NULL } }; MenuSpec XFE_FolderView::mailfolder_popup_menu[] = { { xfeCmdOpenFolder, PUSHBUTTON }, // { xfeCmdOpenFolderInNewWindow, PUSHBUTTON }, MENU_SEPARATOR, { xfeCmdNewFolder, PUSHBUTTON }, { xfeCmdDeleteFolder, PUSHBUTTON }, { xfeCmdRenameFolder, PUSHBUTTON }, { xfeCmdCompressFolders, PUSHBUTTON }, { xfeCmdCompressAllFolders, PUSHBUTTON }, MENU_SEPARATOR, { xfeCmdComposeMessage, PUSHBUTTON }, MENU_SEPARATOR, { xfeCmdSearch, PUSHBUTTON }, { xfeCmdViewProperties, PUSHBUTTON }, { NULL } }; MenuSpec XFE_FolderView::newsgroup_popup_menu[] = { { xfeCmdOpenSelected, PUSHBUTTON }, // open newsgroups in new window should go here MENU_SEPARATOR, { xfeCmdComposeMessage, PUSHBUTTON }, { xfeCmdMarkAllMessagesRead, PUSHBUTTON }, { xfeCmdDeleteFolder, PUSHBUTTON }, MENU_SEPARATOR, { xfeCmdSearch, PUSHBUTTON }, { xfeCmdViewProperties, PUSHBUTTON }, { NULL } }; XFE_FolderView::XFE_FolderView(XFE_Component *toplevel_component, Widget parent, XFE_View *parent_view, MWContext *context, MSG_Pane *p) : XFE_MNListView(toplevel_component, parent_view, context, p) { // initialize it m_popup = NULL; #ifdef USE_3PANE m_clickTimer = 0; m_clickData = NULL; m_cur_selected = NULL; m_cur_count = 0; #endif int num_columns = 3; static int default_column_widths[] = {30, 10, 10}; toplevel_component->registerInterest(XFE_Component::afterRealizeCallback, this, (XFE_FunctionNotification)beforeToplevelShow_cb); if (!p) setPane(MSG_CreateFolderPane(m_contextData, XFE_MNView::m_master)); // create our outliner m_outliner = new XFE_Outliner("folderList", this, getToplevel(), parent, False, // constantSize True, // hasHeadings num_columns, 3, default_column_widths, FOLDER_OUTLINER_GEOMETRY_PREF); m_outliner->setPipeColumn( OUTLINER_COLUMN_NAME ); m_outliner->setMultiSelectAllowed( True ); m_outliner->setHideColumnsAllowed( True ); #if defined(USE_MOTIF_DND) m_outliner->enableDragDrop(this, XFE_FolderView::getDropTargets, XFE_FolderView::getDragTargets, XFE_FolderView::getDragIconData, XFE_FolderView::dragConvert, XFE_FolderView::processTargets); #else m_outliner->setDragType( FE_DND_MAIL_FOLDER, &folderIcon, this, (fe_dnd_SourceDropFunc)&XFE_FolderView::source_drop_func); fe_dnd_CreateDrop(m_outliner->getBaseWidget(), drop_func, this); #endif /* USE_MOTIF_DND */ setBaseWidget(m_outliner->getBaseWidget()); // initialize the icons if they haven't already been { Pixel bg_pixel; XtVaGetValues(m_widget, XmNbackground, &bg_pixel, 0); initFolderIcons(getToplevel()->getBaseWidget(), bg_pixel, getToplevel()->getFGPixel()); } // jump start the folderview's display FE_ListChangeStarting(m_pane, FALSE, MSG_NotifyAll, 0, 0); FE_ListChangeFinished(m_pane, FALSE, MSG_NotifyAll, 0, 0); } XFE_FolderView::~XFE_FolderView() { D( printf ("~XFE_FolderView()\n");) delete m_outliner; destroyPane(); // destroy popup here if (m_popup) delete m_popup; } void XFE_FolderView::initFolderIcons(Widget widget, Pixel bg_pixel, Pixel fg_pixel) { static Boolean icons_init_done = False; if (icons_init_done) return; icons_init_done = True; if (!mailLocalIcon.pixmap) fe_NewMakeIcon(widget, fg_pixel, bg_pixel, &mailLocalIcon, NULL, MN_MailLocal.width, MN_MailLocal.height, MN_MailLocal.mono_bits, MN_MailLocal.color_bits, MN_MailLocal.mask_bits, FALSE); if (!mailServerIcon.pixmap) fe_NewMakeIcon(widget, fg_pixel, bg_pixel, &mailServerIcon, NULL, MN_MailLocal.width, MN_MailLocal.height, MN_MailLocal.mono_bits, MN_MailLocal.color_bits, MN_MailLocal.mask_bits, FALSE); if (!inboxIcon.pixmap) fe_NewMakeIcon(widget, fg_pixel, bg_pixel, &inboxIcon, NULL, MN_Inbox.width, MN_Inbox.height, MN_Inbox.mono_bits, MN_Inbox.color_bits, MN_Inbox.mask_bits, FALSE); if (!inboxOpenIcon.pixmap) fe_NewMakeIcon(widget, fg_pixel, bg_pixel, &inboxOpenIcon, NULL, MN_InboxO.width, MN_InboxO.height, MN_InboxO.mono_bits, MN_InboxO.color_bits, MN_InboxO.mask_bits, FALSE); if (!draftsIcon.pixmap) fe_NewMakeIcon(widget, fg_pixel, bg_pixel, &draftsIcon, NULL, MN_Draft.width, MN_Draft.height, MN_Draft.mono_bits, MN_Draft.color_bits, MN_Draft.mask_bits, FALSE); if (!draftsOpenIcon.pixmap) fe_NewMakeIcon(widget, fg_pixel, bg_pixel, &draftsOpenIcon, NULL, MN_DraftO.width, MN_DraftO.height, MN_DraftO.mono_bits, MN_DraftO.color_bits, MN_DraftO.mask_bits, FALSE); if (!templatesIcon.pixmap) fe_NewMakeIcon(widget, fg_pixel, bg_pixel, &templatesIcon, NULL, MN_Template.width, MN_Template.height, MN_Template.mono_bits, MN_Template.color_bits, MN_Template.mask_bits, FALSE); if (!templatesOpenIcon.pixmap) fe_NewMakeIcon(widget, fg_pixel, bg_pixel, &templatesOpenIcon, NULL, MN_TemplateO.width, MN_TemplateO.height, MN_TemplateO.mono_bits, MN_TemplateO.color_bits, MN_TemplateO.mask_bits, FALSE); if (!outboxIcon.pixmap) fe_NewMakeIcon(widget, fg_pixel, bg_pixel, &outboxIcon, NULL, MN_Outbox.width, MN_Outbox.height, MN_Outbox.mono_bits, MN_Outbox.color_bits, MN_Outbox.mask_bits, FALSE); if (!outboxOpenIcon.pixmap) fe_NewMakeIcon(widget, fg_pixel, bg_pixel, &outboxOpenIcon, NULL, MN_OutboxO.width, MN_OutboxO.height, MN_OutboxO.mono_bits, MN_OutboxO.color_bits, MN_OutboxO.mask_bits, FALSE); if (!folderIcon.pixmap) fe_NewMakeIcon(widget, fg_pixel, bg_pixel, &folderIcon, NULL, MN_Folder.width, MN_Folder.height, MN_Folder.mono_bits, MN_Folder.color_bits, MN_Folder.mask_bits, FALSE); if (!folderOpenIcon.pixmap) fe_NewMakeIcon(widget, fg_pixel, bg_pixel, &folderOpenIcon, NULL, MN_FolderO.width, MN_FolderO.height, MN_FolderO.mono_bits, MN_FolderO.color_bits, MN_FolderO.mask_bits, FALSE); if (!folderServerIcon.pixmap) fe_NewMakeIcon(widget, fg_pixel, bg_pixel, &folderServerIcon, NULL, MN_FolderServer.width, MN_FolderServer.height, MN_FolderServer.mono_bits, MN_FolderServer.color_bits, MN_FolderServer.mask_bits, FALSE); if (!folderServerOpenIcon.pixmap) fe_NewMakeIcon(widget, fg_pixel, bg_pixel, &folderServerOpenIcon, NULL, MN_FolderServerO.width, MN_FolderServerO.height, MN_FolderServerO.mono_bits, MN_FolderServerO.color_bits, MN_FolderServerO.mask_bits, FALSE); if (!newsServerIcon.pixmap) fe_NewMakeIcon(widget, fg_pixel, bg_pixel, &newsServerIcon, NULL, MN_NewsServer.width, MN_NewsServer.height, MN_NewsServer.mono_bits, MN_NewsServer.color_bits, MN_NewsServer.mask_bits, FALSE); HG39875 if (!newsgroupIcon.pixmap) fe_NewMakeIcon(widget, fg_pixel, bg_pixel, &newsgroupIcon, NULL, MN_Newsgroup.width, MN_Newsgroup.height, MN_Newsgroup.mono_bits, MN_Newsgroup.color_bits, MN_Newsgroup.mask_bits, FALSE); if (!trashIcon.pixmap) fe_NewMakeIcon(widget, fg_pixel, bg_pixel, &trashIcon, NULL, MN_TrashSmall.width, MN_TrashSmall.height, MN_TrashSmall.mono_bits, MN_TrashSmall.color_bits, MN_TrashSmall.mask_bits, FALSE); } void XFE_FolderView::paneChanged(XP_Bool asynchronous, MSG_PANE_CHANGED_NOTIFY_CODE code, int32 value) { switch (code) { case MSG_PaneNotifySelectNewFolder: { /* check value */ if (value >=0) { m_outliner->makeVisible(value); m_outliner->selectItemExclusive(value); }/* if */ #if defined(DEBUG_tao) else { printf("\nXFE_FolderView::paneChanged, value=%d", value); XP_ASSERT(value >=0); }/* else */ #endif break; } case MSG_PaneNotifyFolderDeleted: XFE_MozillaApp::theApp()->notifyInterested(XFE_MNView::folderDeleted, (void *)value); break; default: break; } XFE_MNView::paneChanged(asynchronous, code, value); } XFE_CALLBACK_DEFN(XFE_FolderView, beforeToplevelShow)(XFE_NotificationCenter *, void *, void*) { } void XFE_FolderView::selectFolder(MSG_FolderInfo *info) { MSG_ViewIndex index; index = MSG_GetFolderIndexForInfo(m_pane, info, TRUE); if (index != MSG_VIEWINDEXNONE) { m_outliner->makeVisible(index); m_outliner->selectItemExclusive(index); getToplevel()->notifyInterested(XFE_View::chromeNeedsUpdating); } } Boolean XFE_FolderView::isCommandEnabled(CommandType cmd, void *call_data, XFE_CommandInfo* info) { const int *selected; int count; m_outliner->getSelection(&selected, &count); #define IS_CMD(command) cmd == (command) if (// from the FolderFrame edit menu. IS_CMD(xfeCmdFindInObject) || IS_CMD(xfeCmdFindAgain)) { return !XP_IsContextBusy(m_contextData) && count > 0; } #ifdef DEBUG_akkana else if ( IS_CMD(xfeCmdExpand) || IS_CMD(xfeCmdExpandAll) || IS_CMD(xfeCmdCollapse) || IS_CMD(xfeCmdCollapseAll) ) return True; #endif HG07326 else if (IS_CMD(xfeCmdViewProperties)) { return count == 1; } else if (IS_CMD(xfeCmdUpdateMessageCount)) { return !XP_IsContextBusy(m_contextData); } else if (IS_CMD(xfeCmdSearch) ) { // Find current selected folder, if none, disable this button if (XP_IsContextBusy(m_contextData) ) return False; const int *selected; int count; m_outliner->getSelection(&selected, &count); if ( count > 0 ) return True; else return False; } else if ( IS_CMD(xfeCmdSearchAddress)) { return !XP_IsContextBusy(m_contextData); } else if (IS_CMD(xfeCmdDeleteAny)) { return XFE_MNListView::isCommandEnabled(xfeCmdDeleteFolder); } else if (IS_CMD(xfeCmdEditPreferences) || IS_CMD(xfeCmdNewNewsHost)) { return True; } else if (IS_CMD(xfeCmdEditConfiguration) ) { MSG_FolderLine line; if (!MSG_GetFolderLineByIndex(m_pane, selected[0], 1, &line)) return False; return (line.flags & MSG_FOLDER_FLAG_MAIL); } else if (IS_CMD(xfeCmdModerateDiscussion) ) { MSG_FolderLine line; if (!MSG_GetFolderLineByIndex(m_pane, selected[0], 1, &line)) return False; return (line.flags & MSG_FOLDER_FLAG_NEWSGROUP); } else if (IS_CMD(xfeCmdOpenSelected)) { MSG_FolderLine line; if (!MSG_GetFolderLineByIndex(m_pane, selected[0], 1, &line)) return False; return ((line.flags & MSG_FOLDER_FLAG_NEWSGROUP) || ((line.flags & MSG_FOLDER_FLAG_MAIL) && (line.level > 1))); } else if (IS_CMD(xfeCmdNewFolder) && count == 1) { MSG_FolderLine line; if (!MSG_GetFolderLineByIndex(m_pane, selected[0], 1, &line)) return False; XP_Bool selectable; if (line.flags & MSG_FOLDER_FLAG_NEWSGROUP || line.flags & MSG_FOLDER_FLAG_NEWS_HOST) MSG_CommandStatus(m_pane, MSG_NewNewsgroup, (MSG_ViewIndex*)selected, count, &selectable, NULL, NULL, NULL); else MSG_CommandStatus(m_pane, MSG_NewFolder, (MSG_ViewIndex*)selected, count, &selectable, NULL, NULL, NULL); return selectable; } else if (IS_CMD(xfeCmdRenameFolder) && count == 1) { MSG_FolderLine line; if (!MSG_GetFolderLineByIndex(m_pane, selected[0], 1, &line)) return False; XP_Bool selectable; if (line.flags & MSG_FOLDER_FLAG_MAIL) MSG_CommandStatus(m_pane, MSG_NewFolder, (MSG_ViewIndex*)selected, count, &selectable, NULL, NULL, NULL); return selectable; } else { return XFE_MNListView::isCommandEnabled(cmd, call_data, info); } #undef IS_CMD } Boolean XFE_FolderView::handlesCommand(CommandType cmd, void *, XFE_CommandInfo*) { #define IS_CMD(command) cmd == (command) if (IS_CMD(xfeCmdOpenSelected) || IS_CMD(xfeCmdEditPreferences) || IS_CMD(xfeCmdOpenPage) || IS_CMD(xfeCmdSaveAs) || IS_CMD(xfeCmdNewFolder) || IS_CMD(xfeCmdRenameFolder) || IS_CMD(xfeCmdEmptyTrash) || IS_CMD(xfeCmdCompressFolders) || IS_CMD(xfeCmdCompressAllFolders) || IS_CMD(xfeCmdAddNewsgroup) || IS_CMD(xfeCmdNewNewsHost) || IS_CMD(xfeCmdInviteToNewsgroup) || IS_CMD(xfeCmdPrintSetup) || IS_CMD(xfeCmdPrintPreview) || IS_CMD(xfeCmdPrint) || IS_CMD(xfeCmdSearch) || IS_CMD(xfeCmdSearchAddress) || IS_CMD(xfeCmdUndo) || IS_CMD(xfeCmdRedo) || IS_CMD(xfeCmdCut) || IS_CMD(xfeCmdCopy) || IS_CMD(xfeCmdPaste) || IS_CMD(xfeCmdGetNewMessages) || IS_CMD(xfeCmdExpand) || IS_CMD(xfeCmdExpandAll) || IS_CMD(xfeCmdCollapse) || IS_CMD(xfeCmdCollapseAll) #ifdef DEBUG_akkana || IS_CMD(xfeCmdMoveFoldersInto) #endif || IS_CMD(xfeCmdMarkAllMessagesRead) || IS_CMD(xfeCmdSendMessagesInOutbox) || IS_CMD(xfeCmdDeleteAny) || IS_CMD(xfeCmdDeleteFolder) HG82883 || IS_CMD(xfeCmdViewProperties) || IS_CMD(xfeCmdUpdateMessageCount) || IS_CMD(xfeCmdShowPopup)) { return True; } else { return XFE_MNListView::handlesCommand(cmd); } #undef IS_CMD } void XFE_FolderView::doCommand(CommandType cmd, void * calldata, XFE_CommandInfo* info) { #define IS_CMD(command) cmd == (command) const int *selected; int count; m_outliner->getSelection(&selected, &count); D( printf ("in XFE_FolderView::doCommand()\n");) if (IS_CMD(xfeCmdShowPopup)) { XP_ASSERT(info); XEvent *event = (XEvent *)info->event; int x, y, clickrow; Widget w = XtWindowToWidget(event->xany.display, event->xany.window); MSG_FolderLine clickline; MenuSpec *spec; int depth; if (w == NULL) w = m_widget; /* we create a new popup each time. */ if (m_popup) delete m_popup; /* Need to switch focus for the popup menu so that menu items can be enabled in the three pane world */ getToplevel()->notifyInterested(XFE_MNListView::changeFocus, (void*)this); m_popup = new XFE_PopupMenu("popup", (XFE_Frame*)m_toplevel, // XXXXXXX w, NULL); m_outliner->translateFromRootCoords(event->xbutton.x_root, event->xbutton.y_root, &x, &y); // figure out which row they clicked in, and choose the // right popup menu. clickrow = m_outliner->XYToRow(x, y); D( printf ("(x,y) = (%d,%d). row is %d\n", x, y, clickrow);) if (clickrow == -1) return; if (! m_outliner->isSelected(clickrow)) m_outliner->selectItemExclusive(clickrow); acquireLineData(clickrow); getTreeInfo(NULL, NULL, &depth, NULL); releaseLineData(); if (!MSG_GetFolderLineByIndex(m_pane, clickrow, 1, &clickline)) return; if (depth < 1) { if (clickline.flags & MSG_FOLDER_FLAG_NEWS_HOST) spec = newshost_popup_menu; else spec = mailserver_popup_menu; } else { if (clickline.flags & MSG_FOLDER_FLAG_NEWSGROUP) spec = newsgroup_popup_menu; else spec = mailfolder_popup_menu; } m_popup->addMenuSpec(spec); m_popup->position(event); m_popup->show(); } else if (IS_CMD(xfeCmdEditPreferences)) { fe_showMailNewsPreferences(getToplevel(), m_contextData); } else if (IS_CMD(xfeCmdOpenSelected)) { int i; for (i = 0; i < count; i ++) { MSG_FolderLine line; if (!MSG_GetFolderLineByIndex(m_pane, selected[i], 1, &line)) continue; if (!(line.level == 1 && line.flags & MSG_FOLDER_FLAG_DIRECTORY)) fe_showMessages(XtParent(getToplevel()->getBaseWidget()), /* Tao: we might need to check if this returns a * non-NULL frame */ ViewGlue_getFrame(m_contextData), NULL, MSG_GetFolderInfo(m_pane, selected[i]), FALSE, FALSE, MSG_MESSAGEKEYNONE); } } else if (IS_CMD(xfeCmdGetNewMessages)) { getNewMail(); } else if (IS_CMD(xfeCmdSendMessagesInOutbox)) { D( printf ("MSG_FolderPane::sendMessagesInOutbox()\n");) MSG_Command(m_pane, MSG_DeliverQueuedMessages, (MSG_ViewIndex*)selected, count); } else if (IS_CMD(xfeCmdAddNewsgroup)) { D( printf ("MSG_FolderPane::addNewsgroup()\n");) MSG_FolderLine line; MSG_Host *host = NULL; if (MSG_GetFolderLineByIndex(m_pane, selected[0], 1, &line)) { if (line.flags & MSG_FOLDER_FLAG_NEWS_HOST || line.flags & MSG_FOLDER_FLAG_IMAP_SERVER) { host = MSG_GetHostFromIndex(m_pane, selected[0]); #ifdef DEBUG_akkana if (!host) printf("Couldn't get host from index\n"); #endif } else if (line.flags & MSG_FOLDER_FLAG_NEWSGROUP || line.flags & MSG_FOLDER_FLAG_IMAPBOX) { MSG_FolderInfo *info = MSG_GetFolderInfo(m_pane, selected[0]); if (info) host = MSG_GetHostForFolder(info); #ifdef DEBUG_akkana else printf("Couldn't get folder info\n"); if (info && !host) printf("Couldn't get host for folder\n"); #endif } } fe_showSubscribeDialog(getToplevel(), getToplevel()->getBaseWidget(), m_contextData, host); } else if (IS_CMD(xfeCmdNewFolder)) { D( printf ("MSG_FolderPane::newFolder()\n");) MSG_FolderLine line; if (MSG_GetFolderLineByIndex(m_pane, selected[0], 1, &line)) { if (line.flags & MSG_FOLDER_FLAG_NEWSGROUP || line.flags & MSG_FOLDER_FLAG_NEWS_HOST) MSG_Command(m_pane, MSG_NewNewsgroup, (MSG_ViewIndex*)selected, count); // fe_showSubscribeDialog(getToplevel(), getToplevel()->getBaseWidget(), m_contextData); else { MSG_Command(m_pane, MSG_NewFolder, (MSG_ViewIndex*)selected, count); XFE_MozillaApp::theApp()->notifyInterested(XFE_MNView::foldersHaveChanged); } } } else if (IS_CMD(xfeCmdRenameFolder)) { D( printf ("MSG_FolderPane::renameFolder()\n");) MSG_Command(m_pane, MSG_DoRenameFolder, (MSG_ViewIndex*)selected, count); XFE_MozillaApp::theApp()->notifyInterested(XFE_MNView::foldersHaveChanged); } else if (IS_CMD(xfeCmdEmptyTrash)) { D( printf ("MSG_FolderPane::emptyTrash()\n");) MSG_Command(m_pane, MSG_EmptyTrash, (MSG_ViewIndex*)selected, count); } else if (IS_CMD(xfeCmdCompressFolders)) { D( printf ("MSG_FolderPane::compressFolders()\n");) MSG_Command(m_pane, MSG_CompressFolder, (MSG_ViewIndex*)selected, count); } else if (IS_CMD(xfeCmdCompressAllFolders)) { D( printf ("MSG_FolderPane::compressAllFolders()\n");) MSG_Command(m_pane, MSG_CompressAllFolders, (MSG_ViewIndex*)selected, count); } else if (IS_CMD(xfeCmdDeleteFolder) || IS_CMD(xfeCmdDeleteAny) ) { D( printf ("MSG_FolderPane::deleteFolder()\n");) MSG_Command(m_pane, MSG_DeleteFolder, (MSG_ViewIndex*)selected, count); XFE_MozillaApp::theApp()->notifyInterested(XFE_MNView::foldersHaveChanged); } HG20388 else if (IS_CMD(xfeCmdEditMailFilterRules)) { fe_showMailFilterDlg(getToplevel()->getBaseWidget(), m_contextData,m_pane); } else if (IS_CMD(xfeCmdSearchAddress)) { DD(printf ("searchAddress\n");) fe_showLdapSearch(XfeAncestorFindApplicationShell(getToplevel()->getBaseWidget()), /* Tao: we might need to check if this returns a * non-NULL frame */ ViewGlue_getFrame(m_contextData), (Chrome*)NULL); } else if (IS_CMD(xfeCmdViewProperties)) { MSG_FolderInfo *info = MSG_GetFolderInfo(m_pane, selected[0]); MSG_FolderLine line; D(printf("viewProperties\n");) if (MSG_GetFolderLineById(XFE_MNView::m_master, info, &line)) { if (line.flags & MSG_FOLDER_FLAG_NEWS_HOST) { MSG_NewsHost *host = MSG_GetNewsHostFromIndex(m_pane, selected[0]); fe_showNewsServerProperties(getToplevel()->getBaseWidget(), m_contextData, host); } else if (line.flags & MSG_FOLDER_FLAG_NEWSGROUP) { fe_showNewsgroupProperties(getToplevel()->getBaseWidget(), m_contextData, info); } else if (line.flags & MSG_FOLDER_FLAG_MAIL) { if (line.level == 1) fe_showMailServerPreferences(getToplevel(), m_contextData); else fe_showMailFolderProperties(getToplevel()->getBaseWidget(), m_contextData, m_pane, info); } } } else if (IS_CMD(xfeCmdSearch)) { DD(printf ("searchMailNews\n");) // Find current selected folder const int *selected; int count; MSG_FolderInfo *folderInfo; m_outliner->getSelection(&selected, &count); if ( count > 0 ) { DD(printf("### Search Selected Folder %d\n", selected[0]);) folderInfo = MSG_GetFolderInfo(m_pane, (MSG_ViewIndex)(selected[0])); } else { DD(printf("### Search All Folder\n");) folderInfo = NULL; } // We have to use the parent of the base widget to get // to the real top level widget. By doing so, when dispatching // notification, SearchFrame will only get to its registerred // event this way. in fe_WidgetToContext, there is an intent // to get to the wrong frame if we don't use the real toplevel // as the base for the toplevel frames ... dora 12/31/96 fe_showMNSearch(XfeAncestorFindApplicationShell(getToplevel()->getBaseWidget()), /* Tao: we might need to check if this returns a * non-NULL frame */ ViewGlue_getFrame(m_contextData), NULL, this, folderInfo); } #ifdef DEBUG_akkana else if (IS_CMD(xfeCmdMoveFoldersInto)) { MSG_MoveFoldersInto(m_pane, (MSG_ViewIndex*)selected, count, (MSG_FolderInfo*)info); XFE_MozillaApp::theApp()->notifyInterested(XFE_MNView::foldersHaveChanged); } else if (IS_CMD(xfeCmdExpand) || IS_CMD(xfeCmdExpandAll) || IS_CMD(xfeCmdCollapse) || IS_CMD(xfeCmdCollapseAll)) { // Nope, these are the cmds for the thread win, not folder win. :-( //MSG_CommandType msg_cmd = commandToMsgCmd(cmd); //MSG_Command(m_pane, msg_cmd, (MSG_ViewIndex*)selected, count); } #endif else if (IS_CMD(xfeCmdNewNewsHost) /* || IS_CMD(xfeCmdAddNewsServer) */) { // This code taken out of SubAllView::doCommand(): XFE_NewsServerDialog *d = new XFE_NewsServerDialog(getToplevel()->getBaseWidget(), "addServer", /* Tao: we might need to check if this returns a * non-NULL frame */ ViewGlue_getFrame(m_contextData)); XP_Bool ok_pressed = d->post(); if (ok_pressed) { const char *serverName = d->getServer(); int serverPort = d->getPort(); XP_Bool isxxx = HG72988; MSG_NewsHost *host; host = MSG_CreateNewsHost(XFE_MNView::getMaster(), serverName, isxxx, serverPort); XFE_MozillaApp::theApp()->notifyInterested(XFE_MNView::foldersHaveChanged); } delete d; } else if (IS_CMD(xfeCmdMarkAllMessagesRead)) { MSG_Command(m_pane, MSG_MarkAllRead, (MSG_ViewIndex*)selected, count); // XFE_MozillaApp::theApp()->notifyInterested(XFE_MNView::foldersHaveChanged); } else if (IS_CMD(xfeCmdEditConfiguration) || IS_CMD(xfeCmdModerateDiscussion) ) { MSG_CommandType msg_cmd = commandToMsgCmd(cmd); MSG_Command(m_pane, msg_cmd, (MSG_ViewIndex*)selected, count); return; } /* Do it now */ else if ( (cmd == xfeCmdComposeMessage) || (cmd == xfeCmdComposeArticle) ) { if (info) { CONTEXT_DATA(m_contextData)->stealth_cmd = ((info->event->type == ButtonRelease) && (info->event->xkey.state & ShiftMask)); } MSG_Command(m_pane, commandToMsgCmd(cmd), (MSG_ViewIndex*)selected, count); } else if ( (cmd == xfeCmdComposeMessageHTML) || (cmd == xfeCmdComposeArticleHTML) ) { CONTEXT_DATA(m_contextData)->stealth_cmd = (fe_globalPrefs.send_html_msg == False); MSG_Command(m_pane, commandToMsgCmd(cmd), (MSG_ViewIndex*)selected, count); } else if ( (cmd == xfeCmdComposeMessagePlain) || (cmd == xfeCmdComposeArticlePlain) ) { CONTEXT_DATA(m_contextData)->stealth_cmd = (fe_globalPrefs.send_html_msg == True) ; MSG_Command(m_pane, commandToMsgCmd(cmd), (MSG_ViewIndex*)selected, count); } /* End of New message */ else { XFE_MNListView::doCommand(cmd, calldata, info); return; } getToplevel()->notifyInterested(XFE_View::chromeNeedsUpdating); D( printf ("leaving XFE_FolderView::doCommand()\n");) #undef IS_CMD } char * XFE_FolderView::commandToString(CommandType cmd, void *calldata, XFE_CommandInfo* info) { #define IS_CMD(command) cmd == (command) const int *selected; int count; MSG_FolderLine line; m_outliner->getSelection(&selected, &count); // this doesn't handle selections with more than one element in them. if (IS_CMD(xfeCmdNewFolder)) { if (count != 1) return stringFromResource("newFolderCmdString"); MSG_GetFolderLineByIndex(m_pane, selected[0], 1, &line); if (line.flags & MSG_FOLDER_FLAG_NEWSGROUP || line.flags & MSG_FOLDER_FLAG_NEWS_HOST) return stringFromResource("newNewsgroupCmdString"); else /* (line.flags & MSG_FOLDER_FLAG_MAIL) */ if (line.level == 1) return stringFromResource("newFolderCmdString"); else return stringFromResource("newSubFolderCmdString"); } else if (IS_CMD(xfeCmdOpenSelected)) { if (count != 1) return stringFromResource("openFolderCmdString"); MSG_GetFolderLineByIndex(m_pane, selected[0], 1, &line); if ((line.flags & MSG_FOLDER_FLAG_NEWSGROUP) || (line.flags & MSG_FOLDER_FLAG_NEWS_HOST)) return stringFromResource("openNewsgroupCmdString"); else return stringFromResource("openFolderCmdString"); } else if (IS_CMD(xfeCmdDeleteFolder) || IS_CMD(xfeCmdDeleteAny)) { if (count != 1) return stringFromResource("deleteFolderCmdString"); MSG_GetFolderLineByIndex(m_pane, selected[0], 1, &line); #if defined(DEBUG_tao) printf("\n line.flags=%d", line.flags); #endif if (line.flags & MSG_FOLDER_FLAG_NEWS_HOST) return stringFromResource("deleteNewsHostCmdString"); else if (line.flags & MSG_FOLDER_FLAG_NEWSGROUP) return stringFromResource("unsubscribeNewsgroupCmdString"); else /* (line.flags & MSG_FOLDER_FLAG_MAIL) */ if (line.level == 1) return stringFromResource("deleteMailHostCmdString"); else return stringFromResource("deleteFolderCmdString"); } else if (IS_CMD(xfeCmdViewProperties)) { if (count != 1) return stringFromResource("folderPropsCmdString"); MSG_GetFolderLineByIndex(m_pane, selected[0], 1, &line); if (line.flags & MSG_FOLDER_FLAG_NEWSGROUP) return stringFromResource("newsgroupPropsCmdString"); else if (line.flags & MSG_FOLDER_FLAG_NEWS_HOST) return stringFromResource("newsServerPropsCmdString"); else /* mail */ if (line.level == 1) return stringFromResource("mailServerPropsCmdString"); else return stringFromResource("folderPropsCmdString"); } else { return XFE_MNListView::commandToString(cmd, calldata, info); } #undef IS_CMD } fe_icon* XFE_FolderView::treeInfoToIcon(int depth, int flags, XP_Bool expanded, XP_Bool xxxe) { if (depth < 1) { if (flags & MSG_FOLDER_FLAG_NEWS_HOST) return HG17272 &newsServerIcon; else if (flags & MSG_FOLDER_FLAG_IMAPBOX) return &mailServerIcon; else return &mailLocalIcon; } if (flags & MSG_FOLDER_FLAG_NEWSGROUP) return HG00288 &newsgroupIcon; else if (flags & MSG_FOLDER_FLAG_INBOX) return expanded ? &inboxOpenIcon : &inboxIcon; else if (flags & MSG_FOLDER_FLAG_DRAFTS) return expanded ? &draftsOpenIcon : &draftsIcon; else if (flags & MSG_FOLDER_FLAG_TEMPLATES) return expanded ? &templatesOpenIcon : &templatesIcon; else if (flags & MSG_FOLDER_FLAG_TRASH) return &trashIcon; else if (flags & MSG_FOLDER_FLAG_QUEUE) return expanded ? &outboxOpenIcon : &outboxIcon; else if (flags & MSG_FOLDER_FLAG_IMAPBOX) return expanded ? &folderServerOpenIcon : &folderServerIcon; else return expanded ? &folderOpenIcon : &folderIcon; } #if defined(USE_MOTIF_DND) fe_icon_data * XFE_FolderView::treeInfoToIconData(int depth, int flags, XP_Bool expanded) { if (depth < 1) { if (flags & MSG_FOLDER_FLAG_NEWS_HOST) return &MN_NewsServer; else if (flags & MSG_FOLDER_FLAG_IMAPBOX) return &MN_MailLocal; /* XXX ? */ else return &MN_MailLocal; } if (flags & MSG_FOLDER_FLAG_NEWSGROUP) return &MN_Newsgroup; else if (flags & MSG_FOLDER_FLAG_INBOX) return expanded ? &MN_InboxO : &MN_Inbox; else if (flags & MSG_FOLDER_FLAG_DRAFTS) return expanded ? &MN_DraftO : &MN_Draft; else if (flags & MSG_FOLDER_FLAG_TEMPLATES) return expanded ? &MN_TemplateO : &MN_Template; else if (flags & MSG_FOLDER_FLAG_TRASH) return &MN_TrashSmall; else if (flags & MSG_FOLDER_FLAG_QUEUE) return expanded ? &MN_OutboxO : &MN_Outbox; else if (flags & MSG_FOLDER_FLAG_IMAPBOX) return expanded ? &MN_FolderServerO : &MN_FolderServer; else return expanded ? &MN_FolderO : &MN_Folder; } #endif /* USE_MOTIF_DND */ /* Outlinable interface methods */ char * XFE_FolderView::getColumnTextByFolderLine(MSG_FolderLine* folderLine, int column) { static char unseen[10]; static char total[10]; switch (column) { case OUTLINER_COLUMN_NAME: { if (folderLine->prettyName) return (char*)folderLine->prettyName; else return (char*)folderLine->name; } case OUTLINER_COLUMN_UNREAD: { if (folderLine->level == 1 && folderLine->flags & MSG_FOLDER_FLAG_DIRECTORY) { return "---"; } else { /* if we know how many unseen messages there are, display the number. otherwise, we put ???'s */ if (folderLine->unseen >= 0) { PR_snprintf(unseen, sizeof (unseen), "%d", folderLine->unseen); return unseen; } else { return "???"; } } } case OUTLINER_COLUMN_TOTAL: { /* if the folder is a directory, just put dashes for the total messages. */ if (folderLine->level == 1 && folderLine->flags & MSG_FOLDER_FLAG_DIRECTORY) { return "---"; } else { /* if we know how many unseen messages there are, we also know how many total messages there are. otherwise, we put ???'s */ if (folderLine->total >= 0) { PR_snprintf(total, sizeof (total), "%d", folderLine->total); return total; } else { return "???"; } } } default: XP_ASSERT(0); return NULL; } } char *XFE_FolderView::getCellTipString(int row, int column) { /* returned string will be duplicated by outliner */ char *tmp = 0; if (row < 0) { /* header */ tmp = getColumnHeaderText(column); }/* if */ else { /* content */ m_ancestorInfo = NULL; MSG_FolderLine* folderLine = (MSG_FolderLine *) XP_CALLOC(1, sizeof(MSG_FolderLine)); if (!MSG_GetFolderLineByIndex(m_pane, row, 1, folderLine)) return NULL; /* static array; do not free */ tmp = getColumnTextByFolderLine(folderLine, column); XP_FREEIF(folderLine); }/* else */ if (tmp && (!m_outliner->isColTextFit(tmp, row, column))) return tmp; return NULL; } char *XFE_FolderView::getCellDocString(int /* row */, int /* column */) { return NULL; } void * XFE_FolderView::ConvFromIndex(int index) { return MSG_GetFolderInfo(m_pane, index); } int XFE_FolderView::ConvToIndex(void *item) { MSG_ViewIndex index = MSG_GetFolderIndex(m_pane, (MSG_FolderInfo*)item); if (index == MSG_VIEWINDEXNONE) return -1; else return index; } void * XFE_FolderView::acquireLineData(int line) { m_ancestorInfo = NULL; if (!MSG_GetFolderLineByIndex(m_pane, line, 1, &m_folderLine)) return NULL; if ( m_folderLine.level > 0 ) { m_ancestorInfo = new OutlinerAncestorInfo[ m_folderLine.level ]; } else { m_ancestorInfo = new OutlinerAncestorInfo[ 1 ]; } // ripped straight from the winfe int i = m_folderLine.level - 1; int idx = line + 1; int total_lines = m_outliner->getTotalLines(); while ( i > 0 ) { if ( idx < total_lines ) { int level = MSG_GetFolderLevelByIndex(m_pane, idx); if ( (level - 1) == i ) { m_ancestorInfo[i].has_prev = TRUE; m_ancestorInfo[i].has_next = TRUE; i--; idx++; } else if ( (level - 1) < i ) { m_ancestorInfo[i].has_prev = FALSE; m_ancestorInfo[i].has_next = FALSE; i--; } else { idx++; } } else { m_ancestorInfo[i].has_prev = FALSE; m_ancestorInfo[i].has_next = FALSE; i--; } } m_ancestorInfo[0].has_prev = FALSE; m_ancestorInfo[0].has_next = FALSE; return &m_folderLine; } void XFE_FolderView::getTreeInfo(XP_Bool *expandable, XP_Bool *is_expanded, int *depth, OutlinerAncestorInfo **ancestor) { XP_Bool is_line_expandable; XP_Bool is_line_expanded; is_line_expandable = (m_folderLine.numChildren > 0); if (is_line_expandable) { is_line_expanded = !(m_folderLine.flags & MSG_FOLDER_FLAG_ELIDED); } else { is_line_expanded = FALSE; } if (ancestor) *ancestor = m_ancestorInfo; if (depth) *depth = m_folderLine.level - 1; if (expandable) *expandable = is_line_expandable; if (is_expanded) *is_expanded = is_line_expanded; } EOutlinerTextStyle XFE_FolderView::getColumnStyle(int /*column*/) { return (m_folderLine.unseen > 0) ? OUTLINER_Bold : OUTLINER_Default; } #define A_BIG_BUFFER_SIZE 1024 /* I have no idea what the right size is */ char * XFE_FolderView::getColumnText(int column) { static char unseen_a[10]; /* uniquify name for IRIX5.3 */ static char total_a[10]; static char a_line[A_BIG_BUFFER_SIZE]; char *loc; switch (column) { case OUTLINER_COLUMN_NAME: { if (m_folderLine.prettyName) { XP_STRNCPY_SAFE(a_line, m_folderLine.prettyName, sizeof(a_line)); } else { XP_STRNCPY_SAFE(a_line, m_folderLine.name, sizeof(a_line)); } INTL_CONVERT_BUF_TO_LOCALE(a_line, loc); return a_line; } case OUTLINER_COLUMN_UNREAD: { if (m_folderLine.level == 1 && m_folderLine.flags & MSG_FOLDER_FLAG_DIRECTORY) { return "---"; } else { /* if we know how many unseen messages there are, display the number. otherwise, we put ???'s */ #if defined(DEBUG_tao) if (m_folderLine.unseen < 0) printf("\n**OUTLINER_COLUMN_UNREAD=%d\n", m_folderLine.unseen); #endif if (m_folderLine.unseen >= 0) { PR_snprintf(unseen_a, sizeof (unseen_a), "%d", m_folderLine.unseen); return unseen_a; } else { return "???"; } } } case OUTLINER_COLUMN_TOTAL: { /* if the folder is a directory, just put dashes for the total messages. */ if (m_folderLine.level == 1 && m_folderLine.flags & MSG_FOLDER_FLAG_DIRECTORY) { return "---"; } else { /* if we know how many unseen messages there are, we also know how many total messages there are. otherwise, we put ???'s */ #if defined(DEBUG_tao) if (m_folderLine.total < 0) printf("\n**OUTLINER_COLUMN_TOTAL=%d\n", m_folderLine.total); #endif if (m_folderLine.total >= 0) { PR_snprintf(total_a, sizeof (total_a), "%d", m_folderLine.total); return total_a; } else { return "???"; } } } default: XP_ASSERT(0); return NULL; } } fe_icon * XFE_FolderView::getColumnIcon(int column) { XP_Bool expanded; int depth; getTreeInfo(NULL, &expanded, &depth, NULL); if (column == OUTLINER_COLUMN_NAME) { XP_Bool xxxe = False; /* we need to check newshosts */ if (m_folderLine.flags & MSG_FOLDER_FLAG_NEWS_HOST) { MSG_NewsHost *host = MSG_GetNewsHostForFolder(m_folderLine.id); HG82992 } return treeInfoToIcon(depth, m_folderLine.flags, expanded, xxxe); } else { return 0; } } char * XFE_FolderView::getColumnName(int column) { switch (column) { case OUTLINER_COLUMN_NAME: return "Name"; case OUTLINER_COLUMN_TOTAL: return "Total"; case OUTLINER_COLUMN_UNREAD: return "Unread"; default: XP_ASSERT(0); return 0; } } char * XFE_FolderView::getColumnHeaderText(int column) { switch (column) { case OUTLINER_COLUMN_NAME: return XP_GetString(XFE_FOLDER_OUTLINER_COLUMN_NAME); case OUTLINER_COLUMN_TOTAL: return XP_GetString(XFE_FOLDER_OUTLINER_COLUMN_TOTAL); case OUTLINER_COLUMN_UNREAD: return XP_GetString(XFE_FOLDER_OUTLINER_COLUMN_UNREAD); default: XP_ASSERT(0); return 0; } } fe_icon * XFE_FolderView::getColumnHeaderIcon(int /*column*/) { return 0; } EOutlinerTextStyle XFE_FolderView::getColumnHeaderStyle(int /*column*/) { return OUTLINER_Default; } void XFE_FolderView::releaseLineData() { delete [] m_ancestorInfo; m_ancestorInfo = NULL; } #ifdef USE_3PANE static void click_timer_func(XtPointer closure, XtIntervalId *) { XFE_FolderView* fv = (XFE_FolderView*)closure; DD(printf("---::: Process timer :::---\n");) if (fv) fv->processClick(); } #endif void XFE_FolderView::Buttonfunc(const OutlineButtonFuncData *data) { MSG_FolderLine line; // Broadcast to be in focus getToplevel()->notifyInterested(XFE_MNListView::changeFocus, (void*) this); if (!MSG_GetFolderLineByIndex(m_pane, data->row, 1, &line)) return; DD(printf("### times folder clicked %d\n", data->clicks);) if (data->clicks == 2) { #ifdef USE_3PANE if (m_clickTimer) XtRemoveTimeOut(m_clickTimer); m_clickTimer = 0; DD(printf("---::: Remove timer :::---\n");) for (int i = 0; i < m_cur_count; i++ ) { if ( i == 0 ) m_outliner->selectItemExclusive(m_cur_selected[i]); else m_outliner->selectItem(m_cur_selected[i]); } #else m_outliner->selectItemExclusive(data->row); #endif if (line.level == 1 && line.flags & MSG_FOLDER_FLAG_DIRECTORY) { // they double clicked on a newshost or mail server. toggleExpansion(data->row); } else { // ok. we're going to display a folder in a thread frame. what // is left to do now is determine whether we are going to reuse // an existing one or pop up another. This is governed by the // preference reuse_thread_window and whether or not // the alt button was held during the double click. fe_showMessages(XtParent(getToplevel()->getBaseWidget()), /* Tao: we might need to check if this return a * non-NULL frame */ ViewGlue_getFrame(m_contextData), NULL, MSG_GetFolderInfo(m_pane, data->row), (( fe_globalPrefs.reuse_thread_window && !data->shift) || (!fe_globalPrefs.reuse_thread_window && data->shift)), False, MSG_MESSAGEKEYNONE); } } else { if (data->ctrl) { m_outliner->toggleSelected(data->row); } else if (data->shift) { // select the range. const int *selected; int count; m_outliner->getSelection(&selected, &count); if (count == 0) /* there wasn't anything selected yet. */ { m_outliner->selectItemExclusive(data->row); } else if (count == 1) /* there was only one, so we select the range from that item to the new one. */ { m_outliner->selectRangeByIndices(selected[0], data->row); } else /* we had a range of items selected, so let's do something really nice with them. */ { m_outliner->trimOrExpandSelection(data->row); } } else { #ifdef USE_3PANE const int *selected; int count; m_outliner->getSelection(&selected, &count); m_cur_selected= (int *)XP_CALLOC(count, sizeof(int)); for ( int i =0; i < count; i++ ) m_cur_selected[i] = selected[i]; m_cur_count = count; m_outliner->selectItemExclusive(data->row); m_clickData = (XtPointer)data; if (m_clickTimer) XtRemoveTimeOut(m_clickTimer); m_clickTimer = XtAppAddTimeOut(fe_XtAppContext, 650, click_timer_func, this); DD(printf("### ---::: Install timer :::--- ###\n");) #else m_outliner->selectItemExclusive(data->row); notifyInterested(folderSelected, MSG_GetFolderInfo(m_pane, data->row)); #endif } getToplevel()->notifyInterested(XFE_View::chromeNeedsUpdating); } } #ifdef USE_3PANE // This is the routine that will select a folder for single click. void XFE_FolderView::processClick() { OutlineButtonFuncData *data = (OutlineButtonFuncData *)m_clickData; MSG_FolderInfo *info = MSG_GetFolderInfo(m_pane, data->row); XFE_ThreadFrame *theFrame = XFE_ThreadFrame::frameForInfo(info); if ( theFrame) { // if the frame exists, then, single click perform the // same way as the double click mode by bringing the existing // frame to the foreground #if 0 for (int i = 0; i < m_cur_count; i++ ) m_outliner->selectItemExclusive(m_cur_selected[i]); #endif fe_showMessages(XtParent(getToplevel()->getBaseWidget()), /* Tao: we might need to check if this return a * non-NULL frame */ ViewGlue_getFrame(m_contextData), NULL, MSG_GetFolderInfo(m_pane, data->row), (( fe_globalPrefs.reuse_thread_window && !data->shift) || (!fe_globalPrefs.reuse_thread_window && data->shift)), False, MSG_MESSAGEKEYNONE); } else { m_outliner->selectItemExclusive(data->row); notifyInterested(folderSelected, info); } m_clickTimer = 0; XP_FREEIF(m_cur_selected); m_cur_selected = NULL; m_cur_count = 0 ; } #endif void XFE_FolderView::toggleExpansion(int row) { int delta; XP_Bool selection_needs_bubbling = False; delta = MSG_ExpansionDelta(m_pane, row); if (delta == 0) return; /* we're not selected and we're being collapsed. check if any of our children are selected, and if so we select this row. */ if (!m_outliner->isSelected(row) && delta < 0) { int num_children = -1 * delta; int i; for (i = row + 1; i <= row + num_children; i ++) if (m_outliner->isSelected(i)) { selection_needs_bubbling = True; } } MSG_ToggleExpansion(m_pane, row, NULL); if (selection_needs_bubbling) m_outliner->selectItem(row); getToplevel()->notifyInterested(XFE_View::chromeNeedsUpdating); } void XFE_FolderView::Flippyfunc(const OutlineFlippyFuncData *data) { toggleExpansion(data->row); } #if !defined(USE_MOTIF_DND) void XFE_FolderView::dropfunc(Widget /*dropw*/, fe_dnd_Event type, fe_dnd_Source *source, XEvent *event) { int row = -1; int x, y; /* we only understand these targets -- well, we only understand the last 3, and the outliner understands the first one. */ if (source->type != FE_DND_COLUMN && source->type != FE_DND_MAIL_MESSAGE && source->type != FE_DND_NEWS_MESSAGE && source->type != FE_DND_MAIL_FOLDER) { return; } if (source->type == FE_DND_COLUMN) { m_outliner->handleDragEvent(event, type, source); return; } /* we've got to have a sourcedropfunc to drop things in a folder view, since the work must really be done by the source. */ if (source->func == NULL) { return; } m_outliner->translateFromRootCoords(event->xbutton.x_root, event->xbutton.y_root, &x, &y); row = m_outliner->XYToRow(x, y); if (row >= 0) { MSG_FolderLine folder; if (!MSG_GetFolderLineByIndex(m_pane, row, 1, &folder)) row = -1; } switch (type) { case FE_DND_START: DD(printf("### DRAG> button press = %d\n", ((event->xany.type == ButtonPress)? 1: 0 ) );) DD(printf("### DRAG> button release = %d\n", ((event->xany.type == ButtonRelease)? 1: 0 ) );) DD(printf("### DRAG> alt key state = %d\n", ((event->xkey.state &Mod1Mask)? 1: 0 ) );) /* ### In outliner, we set ignoreevent to true when the event type is ButtonPress; therefore, we won't be getting button press event here. We cannot perform stealth command at button press time when drag take place. We can only perform stealth command at button release time. Need to find out why we set "ignoreevnt" to true in outliner. ### */ #if 0 CONTEXT_DATA(m_contextData)->stealth_cmd = ((event->xany.type == ButtonPress) && (event->xkey.state & Mod1Mask)); #endif break; case FE_DND_DRAG: m_outliner->outlineLine(row); break; case FE_DND_DROP: DD(printf("### DROP> button press = %d\n", ((event->xany.type == ButtonPress)? 1: 0 ) );) DD(printf("### DROP> button release = %d\n", ((event->xany.type == ButtonRelease)? 1: 0 ) );) DD(printf("### DROP> alt key state = %d\n", ((event->xkey.state &Mod1Mask)? 1: 0 ) );) CONTEXT_DATA(m_contextData)->stealth_cmd = ((event->xany.type == ButtonRelease) && (event->xkey.state & Mod1Mask)); if (row >= 0) { MSG_FolderInfo *drop_info = MSG_GetFolderInfo(m_pane, row); if (drop_info) { fe_dnd_Message msg; if ( source->type == FE_DND_NEWS_MESSAGE ) { DD(printf("### FolderView::dropfunc: NEWS MESSAGE_COPY ******\n");) msg = FE_DND_MESSAGE_COPY; } else if (( source->type == FE_DND_MAIL_MESSAGE) && (CONTEXT_DATA(m_contextData)->stealth_cmd )) { DD(printf("### FolderView::dropfunc: MAIL MESSAGE_COPY ******\n");) msg = FE_DND_MESSAGE_COPY; } else { DD(printf("### FolderView::dropfunc: MAIL MESSAGE_MOVE ******\n");) msg = FE_DND_MESSAGE_MOVE; } (*source->func)(source, msg, (void*)drop_info); } D(printf ("Outlining line -1\n");) m_outliner->outlineLine(-1); // to clear the drag feedback } } } void XFE_FolderView::drop_func(Widget dropw, void *closure, fe_dnd_Event type, fe_dnd_Source *source, XEvent* event) { XFE_FolderView *obj = (XFE_FolderView*)closure; obj->dropfunc(dropw, type, source, event); } void XFE_FolderView::sourcedropfunc(fe_dnd_Source *, fe_dnd_Message msg, void *closure) { // folders can be moved or deleted. The closure to this function will always // be a MSG_FolderInfo*. // XXX assume that nothing could have changed the selected between the time // we started dragging and now... don't know how smart this is... MSG_FolderInfo *info = (MSG_FolderInfo*)closure; const int *indices; int count; DD(printf("### Enter XFE_FolderView::sourcedropfunc()\n");) m_outliner->getSelection(&indices, &count); MSG_DragEffect requireEffect = MSG_Default_Drag; MSG_DragEffect effect = MSG_DragFoldersIntoStatus(m_pane, (MSG_ViewIndex*)indices, count, info, requireEffect); if (msg == FE_DND_MESSAGE_MOVE ) { DD(printf("### XFE_FolderView::sourcedropfunc:: FE_DND_MESSAGE_MOVE ##\n");) if (effect == MSG_Require_Move) { DD(printf("## XFE_FolderView::sourcedropfunc:: Move FOLDER REQUIRED ##\n");) MSG_MoveFoldersInto(m_pane, (MSG_ViewIndex*)indices, count, info); XFE_MozillaApp::theApp()->notifyInterested(XFE_MNView::foldersHaveChanged); } else if ( effect == MSG_Drag_Not_Allowed ) { DD(printf("### Drag NOT allowed : DROP SITE \n");) char tmp[128]; XP_SAFE_SPRINTF(tmp, sizeof(tmp), "%s", XP_GetString(XFE_DND_MESSAGE_ERROR)); XFE_Progress (m_contextData, tmp); } else XP_ASSERT(0); } else if (msg == FE_DND_MESSAGE_DELETE) { // do something spiffy here, like unsubscribe if it's a newsgroup, // and move to the trash if it's a mail folder. } } void XFE_FolderView::source_drop_func(fe_dnd_Source *src, fe_dnd_Message msg, void *closure) { XFE_FolderView *obj = (XFE_FolderView*)src->closure; obj->sourcedropfunc(src, msg,closure); } #else fe_icon_data * XFE_FolderView::GetDragIconData(int row, int column) { D(printf("XFE_FolderView::GetDragIconData()\n");) XP_Bool expanded; int depth; if (row == -1) return &MN_Folder; else { acquireLineData(row); getTreeInfo(NULL, &expanded, &depth, NULL); releaseLineData(); return treeInfoToIconData(depth, m_folderLine.flags, expanded); } } fe_icon_data * XFE_FolderView::getDragIconData(void *this_ptr, int row, int column) { D(printf("XFE_FolderView::getDragIconData()\n");) XFE_FolderView *folder_view = (XFE_FolderView*)this_ptr; return folder_view->GetDragIconData(row, column); } void XFE_FolderView::GetDragTargets(int row, int column, Atom **targets, int *num_targets) { D(printf("XFE_FolderView::GetDragTargets()\n");) int depth; int flags; XP_ASSERT(row > -1); if (row == -1) { *targets = NULL; *num_targets = 0; } else { if (!m_outliner->isSelected(row)) m_outliner->selectItemExclusive(row); acquireLineData(row); getTreeInfo(NULL, NULL, &depth, NULL); flags = m_folderLine.flags; releaseLineData(); *num_targets = 3; *targets = new Atom[ *num_targets ]; (*targets)[1] = XFE_DragBase::_XA_NETSCAPE_URL; (*targets)[2] = XA_STRING; if (depth < 1) { if (flags & MSG_FOLDER_FLAG_NEWS_HOST) (*targets)[0] = XFE_OutlinerDrop::_XA_NETSCAPE_NEWS_SERVER; else (*targets)[0] = XFE_OutlinerDrop::_XA_NETSCAPE_MAIL_SERVER; } else if (flags & MSG_FOLDER_FLAG_NEWSGROUP) (*targets)[0] = XFE_OutlinerDrop::_XA_NETSCAPE_NEWSGROUP; else (*targets)[0] = XFE_OutlinerDrop::_XA_NETSCAPE_MAIL_FOLDER; } } void XFE_FolderView::getDragTargets(void *this_ptr, int row, int column, Atom **targets, int *num_targets) { D(printf("XFE_FolderView::getDragTargets()\n");) XFE_FolderView *folder_view = (XFE_FolderView*)this_ptr; folder_view->GetDragTargets(row, column, targets, num_targets); } void XFE_FolderView::getDropTargets(void */*this_ptr*/, Atom **targets, int *num_targets) { D(printf("XFE_FolderView::getDropTargets()\n");) *num_targets = 7; *targets = new Atom[ *num_targets ]; (*targets)[0] = XFE_OutlinerDrop::_XA_NETSCAPE_MAIL_FOLDER; (*targets)[1] = XFE_OutlinerDrop::_XA_NETSCAPE_MAIL_MESSAGE; (*targets)[2] = XFE_OutlinerDrop::_XA_NETSCAPE_MAIL_SERVER; (*targets)[3] = XFE_OutlinerDrop::_XA_NETSCAPE_NEWSGROUP; (*targets)[4] = XFE_OutlinerDrop::_XA_NETSCAPE_NEWS_MESSAGE; (*targets)[5] = XFE_OutlinerDrop::_XA_NETSCAPE_NEWS_SERVER; (*targets)[6] = XFE_OutlinerDrop::_XA_NETSCAPE_URL; /* a specialized class of urls are allowed. */ } char * XFE_FolderView::DragConvert(Atom atom) { if (atom == XFE_DragBase::_XA_NETSCAPE_URL) { // translate drag data to NetscapeURL format XFE_URLDesktopType urlData; char *result; const int *selection; int count; int i; m_outliner->getSelection(&selection, &count); urlData.createItemList(1); for (i = 0; i < count; i ++) { MSG_FolderInfo* info = MSG_GetFolderInfo(m_pane, selection[i]); URL_Struct *url = MSG_ConstructUrlForFolder(m_pane, info); urlData.url(i,url->address); NET_FreeURLStruct(url); } result = XtNewString(urlData.getString()); return result; } else if (atom == XFE_OutlinerDrop::_XA_NETSCAPE_MAIL_FOLDER || atom == XFE_OutlinerDrop::_XA_NETSCAPE_NEWSGROUP || atom == XFE_OutlinerDrop::_XA_NETSCAPE_MAIL_SERVER || atom == XFE_OutlinerDrop::_XA_NETSCAPE_NEWS_SERVER) { /* for now we use a hack -- only transfer the index of the dragged folder. */ char buf[100]; const int *selection; int count; m_outliner->getSelection(&selection, &count); PR_snprintf(buf, 100, "%d", selection[0]); return (char*)XtNewString(buf); } else { return (char*)XtNewString(""); } } char * XFE_FolderView::dragConvert(void *this_ptr, Atom atom) { XFE_FolderView *folder_view = (XFE_FolderView*)this_ptr; return folder_view->DragConvert(atom); } int XFE_FolderView::ProcessTargets(int row, int col, Atom *targets, const char **data, int numItems) { int i; D(printf("XFE_FolderView::ProcessTargets()\n");) for (i = 0; i 0) MSG_MoveFoldersInto(m_pane, indices, num_indices, dest_info); delete [] indices; return num_indices > 0; } } return FALSE; } int XFE_FolderView::processTargets(void *this_ptr, int row, int col, Atom *targets, const char **data, int numItems) { XFE_FolderView *folder_view = (XFE_FolderView*)this_ptr; return folder_view->ProcessTargets(row, col, targets, data, numItems); } #endif /* USE_MOTIF_DND */