diff --git a/cmd/macfe/MailNews/CMessageFolderView.cp b/cmd/macfe/MailNews/CMessageFolderView.cp index d8ca157b3b2..e69de29bb2d 100644 --- a/cmd/macfe/MailNews/CMessageFolderView.cp +++ b/cmd/macfe/MailNews/CMessageFolderView.cp @@ -1,1184 +0,0 @@ -/* -*- 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.0 (the "NPL"); you may not use this file except in - * compliance with the NPL. You may obtain a copy of the NPL at - * http://www.mozilla.org/NPL/ - * - * Software distributed under the NPL is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL - * for the specific language governing rights and limitations under the - * NPL. - * - * The Initial Developer of this code under the NPL is Netscape - * Communications Corporation. Portions created by Netscape are - * Copyright (C) 1996 Netscape Communications Corporation. All Rights - * Reserved. - */ - - - - -#include "CMessageFolderView.h" - -// PowerPlant -#include -#include - -#include "prefapi.h" -#include "shist.h" -#include "uprefd.h" -#include "Secnav.h" - -// MacFE -#include "macutil.h" -#include "ufilemgr.h" - -// Netscape Mac Libs -#include "UGraphicGizmos.h" -#include "resgui.h" - -// Mail/News Specific -#include "UOffline.h" -#include "MailNewsgroupWindow_Defines.h" -#include "CThreadWindow.h" -#include "CMailProgressWindow.h" -#include "LTableViewHeader.h" -#include "CProgressListener.h" -#include "CMessageFolder.h" -#include "CMailNewsContext.h" -#include "CNewsSubscriber.h" -#include "UMailFolderMenus.h" -#include "StGetInfoHandler.h" -#include "UNewFolderDialog.h" -#include "CMessageWindow.h" -#include "UMailSelection.h" -#include "UMessageLibrary.h" - -#include "CPrefsDialog.h" -#include "CProxyDragTask.h" -#include "UDeferredTask.h" -#include "CInlineEditField.h" - -//======================================================================================== -class CFolderWatchingTask -//======================================================================================== -: public CDeferredTask -{ - public: - CFolderWatchingTask( - CMessageFolderView* inFolderView, - MSG_FolderInfo* inFolderInfo) - : mFolderView(inFolderView) - , mWatchedFolder(inFolderInfo, inFolderView->GetMessagePane()) - , mWatchedFolderChildCount( mWatchedFolder.CountSubFolders()) - , mAnotherExecuteAttemptCount(0) - { - } - virtual ExecuteResult ExecuteSelf(); - protected: - CMessageFolderView* mFolderView; - CMessageFolder mWatchedFolder; - UInt32 mWatchedFolderChildCount; - UInt32 mAnotherExecuteAttemptCount; -}; - -//---------------------------------------------------------------------------------------- -CDeferredTask::ExecuteResult CFolderWatchingTask::ExecuteSelf() -//---------------------------------------------------------------------------------------- -{ - // This is here for the case when folders were dragged into (or deleted into) - // a folder which was closed in the message center. We need to refresh the - // cache, because the newly added children have changed their level in the - // hierarchy. We don't get notified unless the new parent is expanded. - // Currently, this only goes one folder deep, which covers the most common case - // of folder deletion (move to trash). - if (++mAnotherExecuteAttemptCount >= 500) - return eDoneDelete; // give up and die - CNSContext* context = mFolderView->GetContext(); - if (context->GetCurrentCommand() == cmd_MoveMailMessages ) - context->SetCurrentCommand(cmd_Nothing); - mWatchedFolder.FolderInfoChanged(mFolderView->GetMessagePane()); // get new backend data - if (!mWatchedFolder.GetFolderInfo()) - return eDoneDelete; - UInt32 childCount = mWatchedFolder.CountSubFolders(); - if (childCount <= mWatchedFolderChildCount) - return eWaitStepBack; // no change yet, but ok to run another task. - // OK, it's stale. Fix it. - mWatchedFolder.FolderLevelChanged(mFolderView->GetMessagePane()); - MSG_ViewIndex index = ::MSG_GetFolderIndex(mFolderView->GetMessagePane(), mWatchedFolder); - if (index != MSG_VIEWINDEXNONE) - mFolderView->RefreshRowRange(index + 1, index + 1); - return eDoneDelete; -} // CFolderWatchingTask::ExecuteSelf - -#pragma mark -- CDeleteSelectionTask - -//======================================================================================== -class CDeleteSelectionTask -//======================================================================================== -: public CDeferredTask -{ - public: - CDeleteSelectionTask( - CMessageFolderView* inFolderView, - const CMailSelection& inSelection) - : mSelection(inSelection) - , mFolderView(inFolderView) - {} - virtual ExecuteResult ExecuteSelf(); - protected: - CPersistentFolderSelection mSelection; - CMessageFolderView* mFolderView; -}; // class CDeleteSelectionTask - -//---------------------------------------------------------------------------------------- -CDeferredTask::ExecuteResult CDeleteSelectionTask::ExecuteSelf() -//---------------------------------------------------------------------------------------- -{ - CNetscapeWindow* win = dynamic_cast - (LWindow::FetchWindowObject(mFolderView->GetMacPort())); - // Wait till any pending URLs are finished - if (win->IsAnyContextBusy()) - return eWaitStayFront; - const MSG_ViewIndex* indices = mSelection.GetSelectionList(); - MSG_ViewIndex numIndices = mSelection.selectionSize; - mFolderView->DoDeleteSelection(mSelection); - return eDoneDelete; -} // CDeleteSelectionTask::ExecuteSelf - -#pragma mark -- CDeferredDragTask - -//======================================================================================== -class CDeferredDragTask -//======================================================================================== -: public CDeferredTask -{ - public: - CDeferredDragTask( - CMessageFolderView* inFolderView, - const CMessageFolder& inDestFolder, - Boolean inDoCopy) - : mFolderView(inFolderView) - , mDestFolder(inDestFolder) - , mDoCopy(inDoCopy) - {} - protected: - CMessageFolderView* mFolderView; - CMessageFolder mDestFolder; - Boolean mDoCopy; // rather than move -}; - -//======================================================================================== -class CDeferredDragFolderTask -//======================================================================================== -: public CDeferredDragTask -{ - public: - CDeferredDragFolderTask( - CMessageFolderView* inFolderView, - const CMailSelection& inSelection, - const CMessageFolder& inDestFolder, - Boolean inDoCopy) - : CDeferredDragTask( - inFolderView - , inDestFolder - , inDoCopy) - , mSelection(inSelection) - {} - virtual ExecuteResult ExecuteSelf(); - protected: - CPersistentFolderSelection mSelection; -}; // class CDeferredDragFolderTask - -//---------------------------------------------------------------------------------------- -CDeferredTask::ExecuteResult CDeferredDragFolderTask::ExecuteSelf() -//---------------------------------------------------------------------------------------- -{ - // display modal dialog -// if (!NET_IsOffline()) // ? 97/08/13 someone removed this line. - // 98/01/26 it's because moving messages can take some time - even offline - { - short stringID = 15; // Copying / Moving Messages - CStr255 commandString; - ::GetIndString(commandString, 7099, stringID); - CMailProgressWindow* progressWindow = CMailProgressWindow::CreateModalParasite( - CMailProgressWindow::res_ID_modal, - mSelection.xpPane, - commandString); - if (progressWindow) - progressWindow->SetDelay(0); - } - - // copy / move messages - if (mDestFolder.IsTrash()) - { - // Special case. Back-end doesn't translate this into a delete, and - // presents an alert unless you're dragging mail folders. But it should - // work for news servers etc. So: - XP_Bool confirmPref; // Don't ever confirm a drag. - PREF_GetBoolPref("mailnews.confirm.moveFoldersToTrash", &confirmPref); - if (confirmPref) - PREF_SetBoolPref("mailnews.confirm.moveFoldersToTrash", FALSE); - mFolderView->DoDeleteSelection(mSelection); - if (confirmPref) - PREF_SetBoolPref("mailnews.confirm.moveFoldersToTrash", confirmPref); - } - else - { - mFolderView->GetContext()->SetCurrentCommand(cmd_MoveMailMessages); - mFolderView->WatchFolderForChildren(mDestFolder); - ::MSG_MoveFoldersInto( - mSelection.xpPane, - mSelection.GetSelectionList(), - mSelection.selectionSize, - mDestFolder - ); - } - return eDoneDelete; -} // CDeferredDragFolderTask::ExecuteSelf - -//======================================================================================== -class CDeferredDragMessageTask -//======================================================================================== -: public CDeferredDragTask -{ - public: - CDeferredDragMessageTask( - CMessageFolderView* inFolderView, - const CMailSelection& inSelection, - const CMessageFolder& inDestFolder, - Boolean inDoCopy) - : CDeferredDragTask( - inFolderView - , inDestFolder - , inDoCopy) - , mSelection(inSelection) - {} - virtual ExecuteResult ExecuteSelf(); - protected: - CPersistentMessageSelection mSelection; -}; // class CDeferredDragMessageTask - -//---------------------------------------------------------------------------------------- -CDeferredTask::ExecuteResult CDeferredDragMessageTask::ExecuteSelf() -//---------------------------------------------------------------------------------------- -{ - mFolderView->DropMessages(mSelection, mDestFolder, mDoCopy); - return eDoneDelete; -} // CDeferredDragMessageTask::ExecuteSelf - -#pragma mark -- CMessageFolderView - -//---------------------------------------------------------------------------------------- -CMessageFolderView::CMessageFolderView(LStream *inStream) -//---------------------------------------------------------------------------------------- -: Inherited(inStream) -, mUpdateMailFolderMenus(false) -{ - mAllowDropAfterLastRow = false; -} // CMessageFolderView::CMessageFolderView - - -//---------------------------------------------------------------------------------------- -CMessageFolderView::~CMessageFolderView() -//---------------------------------------------------------------------------------------- -{ -} // CMessageFolderView::~CMessageFolderView - -//---------------------------------------------------------------------------------------- -Boolean CMessageFolderView::ItemIsAcceptable( - DragReference inDragRef, - ItemReference inItemRef ) -//---------------------------------------------------------------------------------------- -{ - FlavorFlags flavorFlags; - if (::GetFlavorFlags(inDragRef, inItemRef, kMailNewsSelectionDragFlavor, &flavorFlags) == noErr) - { - CMailSelection selection; - if (!mIsInternalDrop && GetSelectionFromDrag(inDragRef, selection)) - mIsInternalDrop = (selection.xpPane == GetMessagePane()); - return true; - } - return false; -} // CMessageFolderView::ItemIsAcceptable - -//---------------------------------------------------------------------------------------- -Boolean CMessageFolderView::GetSelectionAndCopyStatusFromDrag( - DragReference inDragRef, - CMessageFolder& inDestFolder, - CMailSelection& outSelection, - Boolean& outCopy) -// Return true if this is an OK drop operation. -//---------------------------------------------------------------------------------------- -{ - if (!GetSelectionFromDrag(inDragRef, outSelection)) - return false; - Boolean isFolderDrop = (::MSG_GetPaneType(outSelection.xpPane) == MSG_FOLDERPANE); - // Don't do anything if the user aborted by dragging back into the same first row. - // There are other cases, but the backend will alert anyway. In this simple case, - // the back-end alert is annoying. - - SInt16 modifiers; - ::GetDragModifiers(inDragRef, NULL, &modifiers, NULL); - outCopy = ((modifiers & optionKey) != 0); - MSG_DragEffect effect = outCopy ? MSG_Require_Copy : MSG_Default_Drag; - - // Ask the back end for guidance on what is possible: - if (isFolderDrop) - { - effect = ::MSG_DragFoldersIntoStatus( - outSelection.xpPane, - outSelection.GetSelectionList(), - outSelection.selectionSize, - inDestFolder, - effect); - if (effect == MSG_Drag_Not_Allowed && outCopy) - { - // Well, maybe a move is ok - effect = ::MSG_DragFoldersIntoStatus( - outSelection.xpPane, - outSelection.GetSelectionList(), - outSelection.selectionSize, - inDestFolder, - MSG_Default_Drag); - } - } - else - { - effect = ::MSG_DragMessagesIntoFolderStatus( - outSelection.xpPane, - outSelection.GetSelectionList(), - outSelection.selectionSize, - inDestFolder, - effect); - if (effect == MSG_Drag_Not_Allowed && outCopy) - { - // Well, maybe a move is ok - effect = ::MSG_DragMessagesIntoFolderStatus( - outSelection.xpPane, - outSelection.GetSelectionList(), - outSelection.selectionSize, - inDestFolder, - MSG_Default_Drag); - } - } - outCopy = (effect & MSG_Require_Copy) != 0; - return (effect != MSG_Drag_Not_Allowed); // this looks ok as a drop operation. -} // CMessageFolderView::GetSelectionAndCopyStatusFromDrag - -//---------------------------------------------------------------------------------------- -void CMessageFolderView::DropMessages( - const CMailSelection& inSelection, - const CMessageFolder& inDestFolder, - Boolean inDoCopy) -//---------------------------------------------------------------------------------------- -{ - // display modal dialog -// if (!NET_IsOffline()) // ? 97/08/13 someone removed this line. - // 98/01/26 it's because moving messages can take some time - even offline - { - short stringID = (inDoCopy ? 19 : 15 ); // Copying / Moving Messages - CStr255 commandString; - ::GetIndString(commandString, 7099, stringID); - CMailProgressWindow* progressWindow = CMailProgressWindow::CreateModalParasite( - CMailProgressWindow::res_ID_modal, - inSelection.xpPane, - commandString); - if (progressWindow) - progressWindow->SetDelay(0); - } - - // Close any windows associated with these messages, if the preferences - // say we should. - CMessageWindow::NoteSelectionFiledOrDeleted(inSelection); - if (!inDoCopy) - ::MSG_MoveMessagesIntoFolder( - inSelection.xpPane, - inSelection.GetSelectionList(), - inSelection.selectionSize, - inDestFolder - ); - else - ::MSG_CopyMessagesIntoFolder( - inSelection.xpPane, - inSelection.GetSelectionList(), - inSelection.selectionSize, - inDestFolder - ); - -} // CMessageFolderView::DropMessages - -//---------------------------------------------------------------------------------------- -Boolean CMessageFolderView::CanDoInlineEditing() -// (override from CStandardFlexTable) -//---------------------------------------------------------------------------------------- -{ - CMessageFolder folder(mRowBeingEdited, GetMessagePane()); - Boolean outEnabled; - Boolean outUsesMark; - Char16 outMark; - Str255 outName; - FindCommandStatus(cmd_RenameFolder, outEnabled, outUsesMark, outMark, outName); - return outEnabled; -} - -//---------------------------------------------------------------------------------------- -void CMessageFolderView::InlineEditorTextChanged() -// (override from CStandardFlexTable) -//---------------------------------------------------------------------------------------- -{ -} -//---------------------------------------------------------------------------------------- -void CMessageFolderView::InlineEditorDone() -// (override from CStandardFlexTable) -//---------------------------------------------------------------------------------------- -{ - if (mRowBeingEdited == LArray::index_Bad || !mNameEditor) - return; - CMessageFolder folder(mRowBeingEdited, GetMessagePane()); - char oldName[256]; - CMailFolderMixin::GetFolderNameForDisplay(oldName, folder); - CStr255 newName; - mNameEditor->GetDescriptor(newName); - if (newName != oldName) - { - char* newNameC = XP_STRDUP(newName); - if (newNameC) - { - ::MSG_RenameMailFolder(GetMessagePane(), folder, newNameC); - folder.FolderInfoChanged(GetMessagePane()); - XP_FREE(newNameC); - } - } -} // CMessageFolderView::InlineEditorDone - -//---------------------------------------------------------------------------------------- -Boolean CMessageFolderView::RowCanAcceptDrop( - DragReference inDragRef, - TableIndexT inDropRow) -// (override from CStandardFlexTable) -//---------------------------------------------------------------------------------------- -{ - Boolean dropOK = false; - - SInt16 modifiers; - ::GetDragModifiers(inDragRef, NULL, &modifiers, NULL); - Boolean doCopy = ((modifiers & optionKey) != 0); - - if (inDropRow >= 1 && inDropRow <= mRows) - { - CMessageFolder destFolder(inDropRow, GetMessagePane()); - CMailSelection selection; - dropOK = (GetSelectionAndCopyStatusFromDrag( - inDragRef, destFolder, - selection, doCopy)); - } - if (dropOK && doCopy) - { - CursHandle copyDragCursor = ::GetCursor(curs_CopyDrag); // finder's copy-drag cursor - if (copyDragCursor != nil) - ::SetCursor(*copyDragCursor); - } - else - ::SetCursor(&qd.arrow); - return dropOK; -} // CMessageFolderView::RowCanAcceptDrop - -//---------------------------------------------------------------------------------------- -Boolean CMessageFolderView::RowCanAcceptDropBetweenAbove( - DragReference inDragRef, - TableIndexT inDropRow) -// (override from CStandardFlexTable) -//---------------------------------------------------------------------------------------- -{ - if (inDropRow >= 1 && inDropRow <= mRows) - { - CMailSelection selection; - if (GetSelectionFromDrag(inDragRef, selection)) - { - // Dropping between rows signifies reordering. This is only allowed when the - // source pane of the drag is our own pane. - if (selection.xpPane != GetMessagePane()) - return false; - CMessageFolder destFolder(inDropRow, GetMessagePane()); - CMailSelection selection; - Boolean doCopy; - return GetSelectionAndCopyStatusFromDrag( - inDragRef, destFolder, - selection, doCopy); - } - } - return false; -} // CMessageFolderView::RowCanAcceptDropBetweenAbove - -//---------------------------------------------------------------------------------------- -void CMessageFolderView::ReceiveDragItem( - DragReference inDragRef, - DragAttributes /*inDragAttrs*/, - ItemReference /*inItemRef*/, - Rect& /*inItemBounds*/) -//---------------------------------------------------------------------------------------- -{ - if (mDropRow == 0) return; // FIXME: when move to top level is implemented, do that! - - // What is the destination folder? - CMessageFolder destFolder(mDropRow, GetMessagePane()); - - // What are the items being dragged? - CMailSelection selection; - Boolean doCopy = false; - if (!GetSelectionAndCopyStatusFromDrag(inDragRef, destFolder, selection, doCopy)) - return; - - // We have to delay the drag in order to display any confirmation dialog - // from the BE (when moving a folder to the trash, for instance). - // Displaying a dialog in here crashes the Mac. - CDeferredDragTask* task = nil; - MSG_PaneType paneType = ::MSG_GetPaneType(selection.xpPane); - if (paneType == MSG_FOLDERPANE) - CDeferredTaskManager::Post( - new CDeferredDragFolderTask(this, selection, destFolder, doCopy), this); - else if (paneType == MSG_MESSAGEPANE) - CDeferredTaskManager::Post( - new CDeferredDragMessageTask(this, selection, destFolder, doCopy), this); - else // search pane? - DropMessages(selection, destFolder, doCopy); // devil take the hindmost. -} // CMessageFolderView::ReceiveDragItem - -//---------------------------------------------------------------------------------------- -void CMessageFolderView::WatchFolderForChildren(MSG_FolderInfo* inFolderInfo) -//---------------------------------------------------------------------------------------- -{ - CFolderWatchingTask* task = new CFolderWatchingTask(this, inFolderInfo); - CDeferredTaskManager::Post(task, this); -} // CMessageFolderView::WatchFolderForChildren - -//---------------------------------------------------------------------------------------- -void CMessageFolderView::DoAddNewsGroup() -//---------------------------------------------------------------------------------------- -{ - try - { - MSG_ViewIndex* indexList = NULL; - UInt32 numIndices = 0; - CMailSelection selection; - if (GetSelection(selection)) - { - //...unless there's a single item selected, and it's a newsgroup - if (selection.selectionSize == 1) - { - MSG_ViewIndex index = *(MSG_ViewIndex*)selection.GetSelectionList(); - MSG_FolderInfo* info = ::MSG_GetFolderInfo(GetMessagePane(), index); - CMessageFolder folder(info, GetMessagePane()); - if (folder.IsNewsHost()) - { - indexList = &index; - numIndices = 1; - } - } - } - MSG_Command( - GetMessagePane(), - MSG_AddNewsGroup, - indexList, - numIndices); - Refresh(); // works around a bug - we don't get notified. - } - catch(...) - { - } -} // CMessageFolderView::DoOpenNewsHost() - -//---------------------------------------------------------------------------------------- -void CMessageFolderView::DeleteSelection() -// Delete all selected folders -//---------------------------------------------------------------------------------------- -{ - CMailSelection selection; - if (GetSelection(selection)) - { - // Deletion cannot occur if we are viewing the contents in a thread pane. - // So make a task (which clones the selection) then unselect the selected - // item (triggering an unload of the folder pane). Then post a delete - // task. - CDeleteSelectionTask* task = new CDeleteSelectionTask(this, selection); - UnselectAllCells(); - CDeferredTaskManager::Post(task, this); - } -} // CMessageFolderView::DeleteSelection - -//---------------------------------------------------------------------------------------- -void CMessageFolderView::DoDeleteSelection(const CMailSelection& inSelection) -//---------------------------------------------------------------------------------------- -{ - try - { - mContext->SetCurrentCommand(cmd_Clear); // in case it was a keystroke - // If there's one mail folder in the selection being deleted, then - // watch the destination folder until the folder count changes. Otherwise - // (eg dragging newsgroups) we will wait forever, in vain... - MSG_ViewIndex* cur = (MSG_ViewIndex*)inSelection.GetSelectionList(); - MSG_FolderInfo* folderToWatch = nil; - for (int i = 0; i < inSelection.selectionSize; i++, cur++) - { - MSG_FolderInfo* info = ::MSG_GetFolderInfo(GetMessagePane(), *cur); - CMessageFolder folder(info, GetMessagePane()); - if (folder.IsMailFolder()) - { - ::MSG_GetFoldersWithFlag( - CMailNewsContext::GetMailMaster(), - MSG_FOLDER_FLAG_TRASH, - &folderToWatch, - 1); - break; - } - } - MSG_CommandType cmd = UMessageLibrary::GetMSGCommand(cmd_Clear); -#if 1 // (MSG_Delete != MSG_DeleteFolder) - if (cmd == MSG_Delete) - cmd = MSG_DeleteFolder; // This can go away when winfe becomes compliant. -#endif - ::MSG_Command( - GetMessagePane(), - cmd, - const_cast(inSelection.GetSelectionList()), - inSelection.selectionSize); - if (folderToWatch) - WatchFolderForChildren(folderToWatch); - } - catch(...) - { - } -} // CMessageFolderView::DoDeleteSelection() - -//---------------------------------------------------------------------------------------- -void CMessageFolderView::AddRowDataToDrag(TableIndexT inRow, DragReference inDragRef) -//---------------------------------------------------------------------------------------- -{ - if (inRow == LArray::index_Bad || inRow > mRows) - return; - - Inherited::AddRowDataToDrag(inRow, inDragRef); // does nothing right now - - CMessageFolder folder(inRow, GetMessagePane()); - - // allow newsgroup text drags into compose window - if (folder.IsNewsgroup()) - { - MSG_FolderInfo *folderInfo = folder.GetFolderInfo(); - - URL_Struct *theURLStruct = ::MSG_ConstructUrlForFolder(GetMessagePane(), folderInfo); - - if (theURLStruct != nil) - { - - OSErr err = ::AddDragItemFlavor( inDragRef, inRow, 'TEXT', - theURLStruct->address, XP_STRLEN(theURLStruct->address), flavorSenderOnly); - - NET_FreeURLStruct(theURLStruct); - } - } - -} // CMessageFolderView::AddRowToDrag - -//---------------------------------------------------------------------------------------- -Boolean CMessageFolderView::CellInitiatesDrag(const STableCell& inCell) const -//---------------------------------------------------------------------------------------- -{ - return (GetCellDataType(inCell) == kFolderNameColumn); -} // CMessageFolderView::CellInitiatesDrag - -//---------------------------------------------------------------------------------------- -Boolean CMessageFolderView::GetRowDragRgn(TableIndexT inRow, RgnHandle ioHiliteRgn) const -// The drag region is the hilite region plus the icon -// Note that the row we are dragging may or may not be selected, so don't rely -// on the selection for anything. -//---------------------------------------------------------------------------------------- -{ - ::SetEmptyRgn(ioHiliteRgn); - Rect cellRect; - - TableIndexT col = GetHiliteColumn(); - if ( !col ) - col = 1; - STableCell cell(inRow, col); - if (!GetLocalCellRect(cell, cellRect)) - return false; - ResIDT iconID = GetIconID(inRow); - if (iconID) - { - GetIconRect(cell, cellRect, cellRect); - ::IconIDToRgn(ioHiliteRgn, &cellRect, kAlignNone, iconID); - } - StRegion cellRgn; - GetRowHiliteRgn(inRow, cellRgn); - ::UnionRgn(ioHiliteRgn, cellRgn, ioHiliteRgn); - - CMessageFolder folder(inRow, GetMessagePane()); - - // If this row is an expanded folder with children, then we need to - // add each child row to the drag also. - // If one of these child rows is selected, and we are dragging the selection, - // then it will get added twice, but this should not be a problem. - if (folder.CountSubFolders() > 0 && folder.IsOpen()) - { - UInt32 folderLevel = folder.GetLevel(); - STableCell nextCell(cell.row + 1, 1); - StRegion tempRgn; - - while (GetNextCell(nextCell)) - { - CMessageFolder subFolder(nextCell.row, GetMessagePane()); - UInt32 subFolderLevel = subFolder.GetLevel(); - - if (subFolderLevel <= folderLevel) - break; - - Inherited::GetRowDragRgn(nextCell.row, tempRgn); - ::UnionRgn(tempRgn, ioHiliteRgn, ioHiliteRgn); - } - } - - return true; -} // CStandardFlexTable::GetRowHiliteRgn - -//---------------------------------------------------------------------------------------- -void CMessageFolderView::GetInfo() -//---------------------------------------------------------------------------------------- -{ - CMessageFolder folder(GetSelectedFolder()); - if (folder.GetFolderInfo()) - UGetInfo::ConductFolderInfoDialog(folder, this); -} - -//---------------------------------------------------------------------------------------- -void CMessageFolderView::OpenRow(TableIndexT inRow) -// See also CFolderThreadController::ListenToMessage -//---------------------------------------------------------------------------------------- -{ - CMessageFolder folder(inRow, GetMessagePane()); - if (folder.IsMailServer()) - { - UGetInfo::ConductFolderInfoDialog(folder, this); - return; - } - if (folder.IsNewsHost()) - { - MSG_Host* selectedHost = MSG_GetHostForFolder(folder); - CNewsSubscriber::DoSubscribeNewsGroup(selectedHost); - return; - } - if (!folder.CanContainThreads()) - return; - - Boolean forceNewWindow = false; - if (GetSelectedRowCount() > 1 && inRow != GetTableSelector()->GetFirstSelectedRow()) - { - STableCell cell(inRow, 1); - if (CellIsSelected(cell)) - forceNewWindow = true; - } - - CThreadWindow* threadWindow - = CThreadWindow::FindAndShow( - folder.GetFolderInfo(), - CThreadWindow::kMakeNew, - cmd_Nothing, - forceNewWindow); // Force new window for multiple selection. -} // CMessageFolderView::OpenRow - -//---------------------------------------------------------------------------------------- -void CMessageFolderView::GetLongWindowDescription(CStr255& outDescription) -//---------------------------------------------------------------------------------------- -{ - ::GetIndString(outDescription, 7099, 11); // "Message Center For ^0" - char buffer[256]; int bufferLength = sizeof(buffer); - ::PREF_GetCharPref("mail.identity.username", buffer, &bufferLength); - ::StringParamText(outDescription, buffer); -} - -//---------------------------------------------------------------------------------------- -void CMessageFolderView::SelectionChanged() -//---------------------------------------------------------------------------------------- -{ - Inherited::SelectionChanged(); - TableIndexT rowCount = GetSelectedRowCount(); - URL_Struct* url = nil; - char entryName[128]; - entryName[0] = '\0'; - if (rowCount == 1) - { - CMailSelection selection; - GetSelection( selection ); - MSG_ViewIndex index = *(MSG_ViewIndex*)selection.GetSelectionList(); - MSG_FolderInfo* info = MSG_GetFolderInfo(GetMessagePane(), index); - MSG_FolderLine folderLine; - XP_Bool gotIt = ::MSG_GetFolderLineById( - CMailNewsContext::GetMailMaster(), - info, - &folderLine); - if (gotIt) - { - url = ::MSG_ConstructUrlForFolder(GetMessagePane(), info); - strcpy(entryName, folderLine.name); - } - } - else - { - // Use the name in the location bar for any potential bookmarks... - url = ::MSG_ConstructUrlForPane(GetMessagePane()); - CStr255 tempString; - GetLongWindowDescription(tempString); - strcpy(entryName, tempString); - } - if (url && *entryName) - { - History_entry* theNewEntry = SHIST_CreateHistoryEntry( - url, - entryName); - SHIST_AddDocument(*mContext, theNewEntry); - } - XP_FREEIF(url); -} - -//---------------------------------------------------------------------------------------- -void CMessageFolderView::ListenToMessage(MessageT inMessage, void* ioParam) -//---------------------------------------------------------------------------------------- -{ - // button messages. - if (!IsOnDuty() || !ObeyCommand(inMessage, ioParam)) - { - Inherited::ListenToMessage(inMessage, ioParam); - } -} // CMessageFolderView::ListenToMessage - -//---------------------------------------------------------------------------------------- -Boolean CMessageFolderView::FindMessageLibraryCommandStatus( - CommandT inCommand, - Boolean &outEnabled, - Boolean &outUsesMark, - Char16 &outMark, - Str255 outName) -// returns false if not a msglib command. -//---------------------------------------------------------------------------------------- -{ - // Interpret MarkSelectedRead as "mark all read" (ie, in this folder) - if (inCommand == cmd_MarkSelectedRead) - inCommand = cmd_MarkAllRead; - return Inherited::FindMessageLibraryCommandStatus(inCommand, outEnabled, outUsesMark, outMark, outName); -} - -//---------------------------------------------------------------------------------------- -void CMessageFolderView::FindCommandStatus( - CommandT inCommand, - Boolean &outEnabled, - Boolean &outUsesMark, - Char16 &outMark, - Str255 outName) -//---------------------------------------------------------------------------------------- -{ - // Preprocessing before calling UMessageLibrary - switch (inCommand) - { - case cmd_NewFolder: - outEnabled = true; - return; - case cmd_NewNewsgroup: - MSG_FolderInfo* folderInfo = GetSelectedFolder(); - inCommand = cmd_NewFolder; - if (folderInfo != nil) - { - CMessageFolder folder(folderInfo, GetMessagePane()); - if (folder.IsNewsgroup() || folder.IsNewsHost()) - inCommand = cmd_NewNewsgroup; - } - break; - - case cmd_OpenSelection: // enabled in base class - { - MSG_FolderInfo* folderInfo = GetSelectedFolder(); - if (folderInfo != nil) - { - CMessageFolder folder(folderInfo, GetMessagePane()); - short strID = 0; - if (folder.IsNewsgroup()) - strID = kOpenDiscussionStrID; - else if (folder.IsMailServer()) - strID = kOpenMailServerStrID; - else if (folder.IsNewsHost()) - strID = kOpenNewsServerStrID; - else if (folder.IsMailFolder()) - strID = kOpenFolderStrID; - if (strID != 0) - ::GetIndString(outName, kMailNewsMenuStrings, strID); - } - break; - } - case cmd_OpenSelectionNewWindow: - { - MSG_FolderInfo* folderInfo = GetSelectedFolder(); - if (folderInfo != nil) - { - CMessageFolder folder(folderInfo, GetMessagePane()); - if (folder.IsMailServer() || folder.IsNewsHost()) - { - outEnabled = false; - return; - } - } - break; - } - case cmd_GetMoreMessages: - CStr255 cmdStr; - CStr255 numStr; - ::GetIndString(cmdStr, kMailNewsMenuStrings, kNextChunkMessagesStrID); - ::NumToString(CPrefs::GetLong(CPrefs::NewsArticlesMax), numStr); - cmdStr += numStr; - memcpy(outName, (StringPtr)cmdStr, cmdStr.Length() + 1); - break; - - case cmd_Stop: - if (mStillLoading) - { - outEnabled = true; // stop button on, nothing else. - return; - } - break; - #if 0 - // 97/10/20. Fall through to the inherited version. - // We don't handle it as a menu command - only internally. - case cmd_NewsGroups: // Expand news host - case cmd_MailNewsFolderWindow: // Expand mail host - outEnabled = true; - return; -#endif // 0 - case cmd_GetInfo: - if (GetSelectedRowCount() != 1) - { - outEnabled = false; - return; - } - outEnabled = true; - return; - - case cmd_Clear: - folderInfo = GetSelectedFolder(); - if (folderInfo != nil) { - CMessageFolder folder(folderInfo, GetMessagePane()); - if (!folder.IsMailServer()) - outEnabled = true; - } - return; - - case cmd_AddToBookmarks: - { - MSG_FolderInfo* folderInfo = GetSelectedFolder(); - if (folderInfo != nil) - { - CMessageFolder folder(folderInfo, GetMessagePane()); - if (folder.IsIMAPMailFolder() || folder.IsNewsHost()) - { - outEnabled = false; - return; - } - } - break; // call inherited:: - } - } // switch - - if (!mStillLoading && FindMessageLibraryCommandStatus(inCommand, outEnabled, outUsesMark, outMark, outName)) - return; - - switch (inCommand) - { - case cmd_OpenNewsHost: - case cmd_AddNewsgroup: - case cmd_SubscribeNewsgroups: - outEnabled = !mStillLoading; - break; - default: - Inherited::FindCommandStatus( - inCommand, outEnabled, outUsesMark, outMark, outName); - break; - } -} // CMessageFolderView::FindCommandStatus - -//---------------------------------------------------------------------------------------- -Boolean CMessageFolderView::ObeyCommand( - CommandT inCommand, - void *ioParam) -//---------------------------------------------------------------------------------------- -{ - if (!mContext) - return false; - - Boolean cmdHandled = false; - CNSContext* originalContext = mContext; // in case we close the window & delete it! - CommandT saveCommand = mContext->GetCurrentCommand(); - mContext->SetCurrentCommand(inCommand); - switch (inCommand) - { - case msg_TabSelect: - return (IsVisible()); // Allow selection only if pane is visible -#if 0 - // This now HAS to be handled by the top commander (application), because the behavior - // has to be different depending on whether we are in a message center window or a 3-pane - // thread window. - case cmd_NewsGroups: // Select first news host - case cmd_MailNewsFolderWindow: // Select first mail host - SelectFirstFolderWithFlags( - inCommand == cmd_NewsGroups - ? MSG_FOLDER_FLAG_NEWS_HOST - : MSG_FOLDER_FLAG_MAIL); - cmdHandled = true; - break; -#endif // 0 - case cmd_SecurityInfo: - MWContext * context = *mContext; - SECNAV_SecurityAdvisor( context, NULL ); - cmdHandled =true; - break; - //----------------------------------- - // News - //---------------------------------------------------------------------------------------- - case cmd_OpenNewsHost: - CNewsSubscriber::DoAddNewsHost(); - cmdHandled = true; - break; - case cmd_SubscribeNewsgroups: - MSG_Host* selectedHost = MSG_GetHostForFolder(GetSelectedFolder()); - CNewsSubscriber::DoSubscribeNewsGroup(selectedHost); - cmdHandled = true; - break; - case cmd_AddNewsgroup: - DoAddNewsGroup(); - cmdHandled = true; - break; - //----------------------------------- - // Special cases - //---------------------------------------------------------------------------------------- -#if 0 - // Not needed - have inline editing now (and the menu item is gone). - case cmd_RenameFolder: - UpdateMailFolderMenusOnNextUpdate(); - break; -#endif - case cmd_NewFolder: - case cmd_NewNewsgroup: - { - MSG_FolderInfo* folderInfo = GetSelectedFolder(); - CMessageFolder folder(folderInfo, GetMessagePane()); - if (folderInfo && (folder.IsNewsgroup() || folder.IsNewsHost())) - inCommand = cmd_NewNewsgroup; // no 'cmdHandled = true' here - else - { - UFolderDialogs::ConductNewFolderDialog(folder); - cmdHandled = true; - } - break; - } - } - //----------------------------------- - // MSGLIB commands - //----------------------------------- - if (!cmdHandled) - cmdHandled = ObeyMessageLibraryCommand(inCommand, ioParam) - || Inherited::ObeyCommand(inCommand, ioParam); - //----------------------------------- - // Cleanup - //----------------------------------- - // The following test against originalContext protects against the cases (quit, close) - // when the object has been deleted. The test against cmdHandled protects against - // re-entrant calls to ListenToMessage. - - if (cmdHandled && mContext == originalContext) - mContext->SetCurrentCommand(cmd_Nothing); - - if (! cmdHandled) - mContext->SetCurrentCommand(saveCommand); - return cmdHandled; -} // CMessageFolderView::ObeyCommand - -#if defined(QAP_BUILD) -//---------------------------------------------------------------------------------------- -void CMessageFolderView::GetQapRowText( - TableIndexT inRow, - char* outText, - UInt16 inMaxBufferLength) const -// Calculate the text and (if ioRect is not passed in as null) a rectangle that fits it. -// Return result indicates if any of the text is visible in the cell -//---------------------------------------------------------------------------------------- -{ - if (!outText || inMaxBufferLength == 0) - return; - - cstring rowText(""); - char tempStr[cMaxMailFolderNameLength]; - CMessageFolder folder(inRow, GetMessagePane()); - short colCount = mTableHeader->CountVisibleColumns(); - - CMailNewsWindow * myWindow = dynamic_cast(LWindow::FetchWindowObject(GetMacPort())); - if (!myWindow) return; - - for (short col = 1; col <= colCount; col ++) - { - STableCell aCell(inRow, col); - LTableHeader::SColumnData * colData = mTableHeader->GetColumnData(col); - if (!colData) break; - LPane * colPane = myWindow->FindPaneByID(colData->paneID); - if (!colPane) break; - - // get column name - CStr255 descriptor; - colPane->GetDescriptor(descriptor); - rowText += descriptor; - rowText += "=\042"; - - // add cell text - switch (GetCellDataType(aCell)) - { - case kFolderNameColumn: - Boolean expanded; - if (CellHasDropFlag(aCell, expanded)) - { - if (expanded) - rowText += "-"; - else - rowText += "+"; - } - else - rowText += " "; - - CMailFolderMixin::GetFolderNameForDisplay(tempStr, folder); - NET_UnEscape(tempStr); - rowText += tempStr; - break; - - case kFolderNumUnreadColumn: - if (folder.CanContainThreads()) - if (folder.CountMessages() != 0) - { - sprintf(tempStr, "%d", folder.CountUnseen()); - rowText += tempStr; - } - break; - - case kFolderNumTotalColumn: - if (folder.CanContainThreads()) - if (folder.CountMessages() != 0) - { - sprintf(tempStr, "%d", folder.CountMessages()); - rowText += tempStr; - } - break; - } - if (col < colCount) - rowText += "\042 | "; - else - rowText += "\042\r"; - } - strncpy(outText, (char*)rowText, inMaxBufferLength); - outText[inMaxBufferLength - 1] = '\0'; -} // CMessageFolderView::GetQapRowText -#endif //QAP_BUILD diff --git a/cmd/macfe/MailNews/CThreadView.cp b/cmd/macfe/MailNews/CThreadView.cp index 53db865296b..e69de29bb2d 100644 --- a/cmd/macfe/MailNews/CThreadView.cp +++ b/cmd/macfe/MailNews/CThreadView.cp @@ -1,3261 +0,0 @@ -/* -*- 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.0 (the "NPL"); you may not use this file except in - * compliance with the NPL. You may obtain a copy of the NPL at - * http://www.mozilla.org/NPL/ - * - * Software distributed under the NPL is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL - * for the specific language governing rights and limitations under the - * NPL. - * - * The Initial Developer of this code under the NPL is Netscape - * Communications Corporation. Portions created by Netscape are - * Copyright (C) 1997 Netscape Communications Corporation. All Rights - * Reserved. - */ - - -// Created 3/25/96 - Tim Craycroft - -#include "CThreadView.h" - -// App specific -#include "resgui.h" -#include "macutil.h" -#include "Netscape_Constants.h" -#include "CBrowserContext.h" - -#include "libi18n.h" - -// Mail/News Specific -#include "CNewsSubscriber.h" -#include "Netscape_Constants.h" -#include "CMailNewsContext.h" -#include "CMessageWindow.h" -#include "CMessageView.h" -#include "MailNewsgroupWindow_Defines.h" -#include "LTableViewHeader.h" -#include "CThreadWindow.h" -#include "UMailFolderMenus.h" -#include "CMailFolderButtonPopup.h" -#include "UMessageLibrary.h" -#include "CMailProgressWindow.h" -#include "CProgressListener.h" -#include "UMailSelection.h" - -// utility -#include "UPropFontSwitcher.h" -#include "UUTF8TextHandler.h" -#include "SearchHelpers.h" -#include "CDrawingState.h" -#include "URobustCreateWindow.h" -#include "CApplicationEventAttachment.h" -// remove next line when we move the PlaceUTF8TextInRect to utility classes -#include "UGraphicGizmos.h" -#include "CTargetedUpdateMenuRegistry.h" -#include "CProxyDragTask.h" -#include "UNewFolderDialog.h" -#include "UDeferredTask.h" - -// XP -#include "ntypes.h" -#include "msg_srch.h" // for MSG_GetPriorityName, MSG_GetStatusName - -// application -#include "uapp.h" -#include "prefapi.h" -#include "secnav.h" -#include "shist.h" - -// PowerPlant -#include -#include -#include -#include -#include -#include - -// Mac -#include - -// ANSI -#include -#include - -#define kPriorityMenuID 10528 - -enum { - kThreadedIcon = 10501, - kUnthreadedIcon = 10502 -}; - -static const UInt16 kMaxSubjectLength = 256; - -#pragma mark - - -MSG_MessageLine CMessage::sMessageLineData; -MSG_Pane* CMessage::sCacheMessageList = NULL; -MSG_ViewIndex CMessage::sCacheIndex = 0; - -//---------------------------------------------------------------------------------------- -CMessage::CMessage(MSG_ViewIndex inIndex, MSG_Pane* inMessageList) -//---------------------------------------------------------------------------------------- -: mIndex(inIndex-1) -, mMessageList(inMessageList) -{ -} - -//---------------------------------------------------------------------------------------- -CMessage::~CMessage() -//---------------------------------------------------------------------------------------- -{ -} - -//---------------------------------------------------------------------------------------- -Boolean CMessage::UpdateMessageCache() const -//---------------------------------------------------------------------------------------- -{ - if (mMessageList && (mIndex != sCacheIndex || mMessageList != sCacheMessageList)) - { - if (!::MSG_GetThreadLineByIndex(mMessageList, mIndex, 1, &sMessageLineData)) - { - InvalidateCache(); - return false; - } - sCacheIndex = mIndex; - sCacheMessageList = mMessageList; - } - return true; -} // CMessage::UpdateMessageCache - -//---------------------------------------------------------------------------------------- -void CMessage::InvalidateCache() -//---------------------------------------------------------------------------------------- -{ - sCacheMessageList = NULL; -} - -//---------------------------------------------------------------------------------------- -inline Boolean CMessage::TestXPFlag(UInt32 inMask) const -//---------------------------------------------------------------------------------------- -{ - UpdateMessageCache(); - return ((sMessageLineData.flags & inMask) != 0); -} - -//---------------------------------------------------------------------------------------- -inline Boolean CMessage::IsOffline() const // db has offline news article -//---------------------------------------------------------------------------------------- -{ - return TestXPFlag(MSG_FLAG_OFFLINE); -} - -//---------------------------------------------------------------------------------------- -inline Boolean CMessage::IsDeleted() const -//---------------------------------------------------------------------------------------- -{ - return TestXPFlag(MSG_FLAG_IMAP_DELETED); -} - -//---------------------------------------------------------------------------------------- -inline Boolean CMessage::IsTemplate() const -//---------------------------------------------------------------------------------------- -{ - return TestXPFlag(MSG_FLAG_TEMPLATE); -} - -//---------------------------------------------------------------------------------------- -inline Boolean CMessage::HasBeenRead() const -//---------------------------------------------------------------------------------------- -{ - return TestXPFlag(MSG_FLAG_READ); -} - -//---------------------------------------------------------------------------------------- -inline Boolean CMessage::IsFlagged() const -//---------------------------------------------------------------------------------------- -{ - return TestXPFlag(MSG_FLAG_MARKED); -} - -//---------------------------------------------------------------------------------------- -inline Boolean CMessage::IsThread() const -//---------------------------------------------------------------------------------------- -{ - UpdateMessageCache(); - return (sMessageLineData.numChildren > 0); -} - -//---------------------------------------------------------------------------------------- -inline Boolean CMessage::HasAttachments() const -//---------------------------------------------------------------------------------------- -{ - return TestXPFlag(MSG_FLAG_ATTACHMENT); -} - -//---------------------------------------------------------------------------------------- -inline Boolean CMessage::IsOpenThread() const -//---------------------------------------------------------------------------------------- -{ - Assert_(IsThread()); - return !TestXPFlag(MSG_FLAG_ELIDED); -} - -//---------------------------------------------------------------------------------------- -inline Boolean CMessage::HasBeenRepliedTo() const -//---------------------------------------------------------------------------------------- -{ - return TestXPFlag(MSG_FLAG_REPLIED); -} - -//---------------------------------------------------------------------------------------- -inline MessageId CMessage::GetThreadID() const -//---------------------------------------------------------------------------------------- -{ - UpdateMessageCache(); - return sMessageLineData.threadId; -} - -//---------------------------------------------------------------------------------------- -MessageKey CMessage::GetMessageKey() const -//---------------------------------------------------------------------------------------- -{ - UpdateMessageCache(); - return sMessageLineData.messageKey; -} - -//---------------------------------------------------------------------------------------- -uint16 CMessage::GetNumChildren() const -//---------------------------------------------------------------------------------------- -{ - UpdateMessageCache(); - return sMessageLineData.numChildren; -} - -//---------------------------------------------------------------------------------------- -uint16 CMessage::GetNumNewChildren() const -//---------------------------------------------------------------------------------------- -{ - UpdateMessageCache(); - return sMessageLineData.numNewChildren; -} - -//---------------------------------------------------------------------------------------- -/* static */ const char* CMessage::GetSubject( - MSG_MessageLine* data, - char* buffer, - UInt16 bufSize) -//---------------------------------------------------------------------------------------- -{ - *buffer = 0; - if ((data->flags & MSG_FLAG_HAS_RE) != 0) - { - const CString** sh = (const CString**)GetString(REPLY_FORM_RESID); - if (sh) - { - Assert_(bufSize > (**sh).Length()); - XP_SAFE_SPRINTF(buffer, bufSize - 1, (const char*)(**sh), data->subject); - ::ReleaseResource((Handle)sh); - return buffer; - } - } - return XP_STRNCPY_SAFE(buffer, data->subject, bufSize); -} - -//---------------------------------------------------------------------------------------- -const char* CMessage::GetSubject(char* buffer, UInt16 bufSize) const -//---------------------------------------------------------------------------------------- -{ - UpdateMessageCache(); - return GetSubject(&sMessageLineData, buffer, bufSize); -} - -//---------------------------------------------------------------------------------------- -const char* CMessage::GetSubject() const -//---------------------------------------------------------------------------------------- -{ - UpdateMessageCache(); - return sMessageLineData.subject; -} - -//---------------------------------------------------------------------------------------- -inline MSG_PRIORITY CMessage::GetPriority() const -//---------------------------------------------------------------------------------------- -{ - UpdateMessageCache(); - return sMessageLineData.priority; -} - -//---------------------------------------------------------------------------------------- -void CMessage::GetPriorityColor(MSG_PRIORITY priority, RGBColor& priorityColor) /* static */ -//---------------------------------------------------------------------------------------- -{ - // Initialize to black - memset(&priorityColor, 0, sizeof(RGBColor)); - switch (priority) - { - case MSG_LowestPriority: // green - priorityColor.green = 0x7FFF; - break; - case MSG_LowPriority: // blue - priorityColor.blue = 0xFFFF; - break; - case MSG_HighPriority: // purple - priorityColor.red = 0x7FFF; - priorityColor.blue = 0x7FFF; - break; - case MSG_HighestPriority: // red - priorityColor.red = 0xFFFF; - break; - case MSG_NormalPriority: - case MSG_PriorityNotSet: - case MSG_NoPriority: - default: - break; - } -} // CMessage::GetPriorityColor - -//---------------------------------------------------------------------------------------- -void CMessage::GetPriorityColor(RGBColor& priorityColor) const -//---------------------------------------------------------------------------------------- -{ - // Don't draw deleted messages in color. - MSG_PRIORITY priority = IsDeleted() ? MSG_NormalPriority : GetPriority(); - GetPriorityColor(priority, priorityColor); -} // CMessage::GetPriorityColor - -//---------------------------------------------------------------------------------------- -inline Int16 CMessage::PriorityToMenuItem(MSG_PRIORITY inPriority) /* static */ -//---------------------------------------------------------------------------------------- -{ - return (inPriority > MSG_NoPriority) ? inPriority - 1 : 3; -} - -//---------------------------------------------------------------------------------------- -inline MSG_PRIORITY CMessage::MenuItemToPriority(Int16 inMenuItem) /* static */ -//---------------------------------------------------------------------------------------- -{ - return (MSG_PRIORITY)(inMenuItem + 1); -} - -//---------------------------------------------------------------------------------------- -inline const char* CMessage::GetSender() const -//---------------------------------------------------------------------------------------- -{ - UpdateMessageCache(); - return sMessageLineData.author; -} - -//---------------------------------------------------------------------------------------- -inline const char* CMessage::GetDateString() const -//---------------------------------------------------------------------------------------- -{ -// UpdateMessageCache(); - return MSG_FormatDate(mMessageList, GetDate()); -} - -//---------------------------------------------------------------------------------------- -inline const char* CMessage::GetAddresseeString() const -//---------------------------------------------------------------------------------------- -{ - UpdateMessageCache(); - return sMessageLineData.author; -} - -//---------------------------------------------------------------------------------------- -const char * CMessage::GetSizeStr() const -// ¥ FIX ME: Is there an XP call for constructing the size string ? -//---------------------------------------------------------------------------------------- -{ - static char sizeString[32]; - UInt32 messageSize = GetSize(); - CStr255 formatString; - if (messageSize > (1024*1000)) - { - ::GetIndString(formatString, 7099, 4); - float floatSize = (float)messageSize / (1024*1000); - sprintf(sizeString, formatString, floatSize); - } - else - { - if (messageSize > 1024) - { - ::GetIndString(formatString, 7099, 5); - messageSize /= 1024; - } - else - { - ::GetIndString(formatString, 7099, 6); - } - sprintf(sizeString, formatString, messageSize); - } - return sizeString; -} - -//---------------------------------------------------------------------------------------- -const char * CMessage::GetPriorityStr() const -//---------------------------------------------------------------------------------------- -{ - static char buffer[256]; - buffer[0] = '\0'; - MSG_PRIORITY priority = GetPriority(); - if (priority == MSG_PriorityNotSet - || priority == MSG_NoPriority - || priority == MSG_NormalPriority) - return buffer; - MSG_GetPriorityName(priority, buffer, sizeof(buffer)-1); - return buffer; -} - - -//---------------------------------------------------------------------------------------- -const char * CMessage::GetStatusStr() const -//---------------------------------------------------------------------------------------- -{ - static char buffer[256]; - MSG_GetStatusName(GetStatus(), buffer, sizeof(buffer)-1); - return buffer; -} - -//---------------------------------------------------------------------------------------- -inline time_t CMessage::GetDate() const -//---------------------------------------------------------------------------------------- -{ - UpdateMessageCache(); - return sMessageLineData.date; -} - -//---------------------------------------------------------------------------------------- -inline UInt32 CMessage::GetSize() const -//---------------------------------------------------------------------------------------- -{ - UpdateMessageCache(); - return sMessageLineData.messageLines; // bytes for mail, lines for news. Oh well! -} - -//---------------------------------------------------------------------------------------- -inline UInt32 CMessage::GetStatus() const -//---------------------------------------------------------------------------------------- -{ - UpdateMessageCache(); - return sMessageLineData.flags; - // actually, not all bits are relevant, but there's no mask in msgcom.h. -} - -//---------------------------------------------------------------------------------------- -inline int8 CMessage::GetThreadLevel() const -//---------------------------------------------------------------------------------------- -{ - UpdateMessageCache(); - return sMessageLineData.level; -} - -//====================================== -// Icon suite IDs -//====================================== -#pragma mark -enum IconTable -{ - kMessageReadIcon = 15234 // icon to mark a message as read -, kFlagIcon = 15236 // icon to mark a message as read - - // Icons for representing mail messages -, kMailMessageIcon = 15228 -, kReadMailMessageIcon = 15229 -, kMailMessageWithAttachmentIcon = 10511 -, kFlaggedMailMessageIcon = 10512 -, kFlaggedMailMessageWithAttachmentIcon = 10513 - - // News articles -, kNewsArticleMessageIcon = 15231 -, kReadNewsArticleMessageIcon = 15232 -, kNewsArticleReadFlaggedMessageIcon = 15232 -, kNewsArticleFlaggedMessageIcon = 15234 -}; - -static ResIDT gIconIDTable[] = { -//------------------------------------------------------------------------------------------------------------- -// NAME UNREAD READ NEW (UNUSED) -// LOCAL ONLINE LOCAL ONLINE LOCAL ONLINE LOCAL ONLINE -//------------------------------------------------------------------------------------------------------------- -/* POP */ 15228 , 0 , 15229 , 0 , 15407 , 0 , 0 , 0 , -/* IMAP */ 15228 , 15226 , 15229 , 15226 , 15407 , 15407 , 15523 , 15523 , -/* Art */ 15518 , 15233 , 15519 , 15396 , 0 , 0 , 0 , 0 , -/* Drft */ 15230 , 15230 , 15230 , 15230 , 15230 , 15230 , 0 , 0 , -}; //---------------------------------------------------------------------------------------------------- - -enum { - kOnline = 1 // offset -, kRead = 2 // offset -, kNew = 4 // offset -, kDeleted = 6 // offset -, kKindsPerRow = 8 -, kMessageIx = 0 -, kIMAPIx = 1 * kKindsPerRow -, kArticleIx = 2 * kKindsPerRow -, kDraftIx = 3 * kKindsPerRow -}; - -//---------------------------------------------------------------------------------------- -ResIDT CMessage::GetIconID(UInt16 inFolderFlags) const -//---------------------------------------------------------------------------------------- -{ - UpdateMessageCache(); - return GetIconID(inFolderFlags, sMessageLineData.flags); -} // CMessage::GetIconID - -//---------------------------------------------------------------------------------------- -ResIDT CMessage::GetIconID(UInt16 inFolderFlags, UInt32 inMessageFlags) -//---------------------------------------------------------------------------------------- -{ -#define IMAP_FOLDER (MSG_FOLDER_FLAG_IMAPBOX | MSG_FOLDER_FLAG_MAIL) - short iconIndex = 0; - // Special case of pop folder because MSG_FLAG_OFFLINE is not correct for pop folders. - Boolean isPopFolder = (inFolderFlags & IMAP_FOLDER) == MSG_FOLDER_FLAG_MAIL; - Boolean isNews = (inFolderFlags & MSG_FOLDER_FLAG_NEWSGROUP) == MSG_FOLDER_FLAG_NEWSGROUP; - - // First, what kind of folder are we in (determines the basic icon type, the row in - // the table above) - if ((inFolderFlags & IMAP_FOLDER) == IMAP_FOLDER) - iconIndex = kIMAPIx; - else if (inFolderFlags & MSG_FOLDER_FLAG_MAIL) - iconIndex = kMessageIx; // FIXME: How do we tell whether it has attachments? - else if (inFolderFlags & MSG_FOLDER_FLAG_NEWSGROUP) - iconIndex = kArticleIx; - else if (inFolderFlags & MSG_FOLDER_FLAG_DRAFTS) - iconIndex = kDraftIx; - - // Next, which of the four major columns are we in. - if (!isNews && !isPopFolder && (inMessageFlags & MSG_FLAG_IMAP_DELETED) != 0) - iconIndex += kDeleted; - else if (!isNews && (inMessageFlags & MSG_FLAG_NEW) != 0) - iconIndex += kNew; - else if ((inMessageFlags & MSG_FLAG_READ) != 0) - iconIndex += kRead; - - // Finally, choose the local/offline column. - // Note: pop does not support the "offline" flag bit, it should always be set - // (but isn't) - if (!isPopFolder && (inMessageFlags & MSG_FLAG_OFFLINE) == 0) - iconIndex += kOnline; - - return gIconIDTable[iconIndex]; -} // CMessage::GetIconID - -//====================================== -// Thread Icon IDs -//====================================== -enum ThreadIconTable -{ - // Icons for representing threaded messages - kThreadIcon = 15399 -, kNewThreadIcon = 15401 -, kWatchedThreadIcon = 15403 -, kWatchedNewThreadIcon = 15404 -, kIgnoredThreadIcon = 15429 - -}; - -static ResIDT gThreadIconIDTable[] = { -//----------------------------------------------------------- -// NAME UNWATCHED WATCHED -// OLD UNREAD OLD UNREAD -//----------------------------------------------------------- -/* Thread */ 15399 , 15401 , 15403 , 15404 -}; //-------------------------------------------------- - -enum { - kUnread = 1 // offset -, kWatched = 2 // offset -}; - -//---------------------------------------------------------------------------------------- -ResIDT CMessage::GetThreadIconID() const -//---------------------------------------------------------------------------------------- -{ - UpdateMessageCache(); - short iconIndex = 0; - if ((sMessageLineData.flags & MSG_FLAG_IGNORED) != 0) - return kIgnoredThreadIcon; - if (GetNumNewChildren() > 0) - iconIndex += kUnread; - if ((sMessageLineData.flags & MSG_FLAG_WATCHED) != 0) - iconIndex += kWatched; - return gThreadIconIDTable[iconIndex]; -} // CMessage::GetIconID - -#pragma mark - - -//======================================================================================== -class CDeferredLoadFolderTask -//======================================================================================== -: public CDeferredTask -{ - public: - CDeferredLoadFolderTask( - CThreadView* inView, - CNSContext* inContext, - CMessageFolder inFolder); - protected: - virtual ExecuteResult ExecuteSelf(); -// data - protected: - CThreadView* mThreadView; - CNSContext* mContextToLoadAtIdle; - CMessageFolder mFolderToLoadAtIdle; - UInt32 mEarliestExecuteTime; -}; // class CDeferredLoadFolderTask - -//---------------------------------------------------------------------------------------- -CDeferredLoadFolderTask::CDeferredLoadFolderTask( - CThreadView* inView, - CNSContext* inContext, - CMessageFolder inFolder) -//---------------------------------------------------------------------------------------- -: mThreadView(inView) -, mContextToLoadAtIdle(inContext) -, mFolderToLoadAtIdle(inFolder) -, mEarliestExecuteTime(::TickCount() + GetDblTime()) -{ -} - -//---------------------------------------------------------------------------------------- -CDeferredTask::ExecuteResult CDeferredLoadFolderTask::ExecuteSelf() -//---------------------------------------------------------------------------------------- -{ - // Wait for the earliest execute time. It's expensive to load a folder, and if the - // user is nervously clicking on multiple folders, we only want to load the last one. - if (::TickCount() < mEarliestExecuteTime) - return eWaitStayFront; - if (CMailProgressWindow::GetModal()) - return eWaitStayFront; // wait until other modal tasks are done. - mThreadView->LoadMessageFolder(mContextToLoadAtIdle, mFolderToLoadAtIdle, true); - return eDoneDelete; -} // CDeferredLoadFolderTask::ExecuteSelf - -#pragma mark - - -//======================================================================================== -class CDeferredUndoTask -//======================================================================================== -: public CDeferredTask -{ - public: - CDeferredUndoTask( - CThreadView* inView); - void SetUndoStatus(UndoStatus inStatus) - { - mUndoStatus = inStatus; - } - protected: - virtual ExecuteResult ExecuteSelf(); -// data - protected: - CThreadView* mThreadView; - UndoStatus mUndoStatus; -}; // class CDeferredUndoTask - -//---------------------------------------------------------------------------------------- -CDeferredUndoTask::CDeferredUndoTask( - CThreadView* inView) -//---------------------------------------------------------------------------------------- -: mThreadView(inView) -, mUndoStatus(UndoInProgress) -{ -} - -//---------------------------------------------------------------------------------------- -CDeferredTask::ExecuteResult CDeferredUndoTask::ExecuteSelf() -//---------------------------------------------------------------------------------------- -{ - if (mUndoStatus == UndoComplete) - return eDoneDelete; // remove from queue - else if (mUndoStatus == UndoInProgress) - { - mUndoStatus = MSG_GetUndoStatus(mThreadView->GetMessagePane()); - switch (mUndoStatus) - { - case UndoComplete: - MSG_FolderInfo* finfo; - MessageKey key; - MSG_Pane* pane = mThreadView->GetMessagePane(); - if (MSG_GetUndoMessageKey(pane, &finfo, &key)) - { - if (finfo && finfo != mThreadView->GetOwningFolder()) - { - mThreadView->LoadMessageFolder(mThreadView->GetContext(), finfo, false); - } - mThreadView->SelectMessageWhenReady(key); - } - break; - case UndoInProgress: - return eWaitStayFront; // block, leave in queue - default: - return eDoneDelete; - } // switch - } - return eDoneDelete; // remove from queue -} // CDeferredUndoTask::ExecuteSelf - -#pragma mark - - -//======================================================================================== -class CDeferredSelectRowTask -//======================================================================================== -: public CDeferredTask -{ - public: - CDeferredSelectRowTask( - CThreadView* inView, - TableIndexT inRow); - protected: - virtual ExecuteResult ExecuteSelf(); -// data - protected: - CThreadView* mThreadView; - TableIndexT mRow; -}; // class CDeferredSelectRowTask - -//---------------------------------------------------------------------------------------- -CDeferredSelectRowTask::CDeferredSelectRowTask( - CThreadView* inView, - TableIndexT inRow) -//---------------------------------------------------------------------------------------- -: mThreadView(inView) -, mRow(inRow) -{ -} - -//---------------------------------------------------------------------------------------- -CDeferredTask::ExecuteResult CDeferredSelectRowTask::ExecuteSelf() -//---------------------------------------------------------------------------------------- -{ - mThreadView->SelectAfterDelete(mRow); - return eDoneDelete; // remove from queue -} // CDeferredSelectRowTask::ExecuteSelf - -#pragma mark - - -//======================================================================================== -class CScrollToNewMailTask -//======================================================================================== -: public CDeferredTask -{ - public: - CScrollToNewMailTask( - CThreadView* inView); - protected: - virtual ExecuteResult ExecuteSelf(); -// data - protected: - CThreadView* mThreadView; -}; // class CScrollToNewMailTask - -//---------------------------------------------------------------------------------------- -CScrollToNewMailTask::CScrollToNewMailTask( - CThreadView* inView) -//---------------------------------------------------------------------------------------- -: mThreadView(inView) -{ -} - -//---------------------------------------------------------------------------------------- -CDeferredTask::ExecuteResult CScrollToNewMailTask::ExecuteSelf() -//---------------------------------------------------------------------------------------- -{ - mThreadView->ScrollToGoodPlace(); - return eDoneDelete; // remove from queue -} // CScrollToNewMailTask::ExecuteSelf - -#pragma mark - - -//======================================================================================== -class CDeferredSelectKeyTask -//======================================================================================== -: public CDeferredTask -{ - public: - CDeferredSelectKeyTask( - CThreadView* inView, - MessageKey inKey); - protected: - virtual ExecuteResult ExecuteSelf(); -// data - protected: - CThreadView* mThreadView; - MessageKey mPendingMessageKeyToSelect; // Hack to support ShowSearchMessage() -}; // class CDeferredSelectKeyTask - -//---------------------------------------------------------------------------------------- -CDeferredSelectKeyTask::CDeferredSelectKeyTask( - CThreadView* inView, - MessageKey inKey) -//---------------------------------------------------------------------------------------- -: mThreadView(inView) -, mPendingMessageKeyToSelect(inKey) -{ -} - -//---------------------------------------------------------------------------------------- -CDeferredTask::ExecuteResult CDeferredSelectKeyTask::ExecuteSelf() -//---------------------------------------------------------------------------------------- -{ - mThreadView->SelectMessageWhenReady(mPendingMessageKeyToSelect); - return eDoneDelete; -} // CDeferredSelectKeyTask::ExecuteSelf - -#pragma mark - - -//======================================================================================== -class CDeferredThreadViewCommand -//======================================================================================== -: public CDeferredCommand -{ - private: - typedef CDeferredCommand Inherited; - public: - CDeferredThreadViewCommand( - CThreadView* inView, - CommandT inCommand, - void* ioParam); - protected: - virtual ExecuteResult ExecuteSelf(); -// data - protected: - CThreadView* mThreadView; -}; // class CDeferredThreadViewCommand - -//---------------------------------------------------------------------------------------- -CDeferredThreadViewCommand::CDeferredThreadViewCommand( - CThreadView* inView, - CommandT inCommand, - void* ioParam) -//---------------------------------------------------------------------------------------- -: CDeferredCommand(inView, inCommand, ioParam) -, mThreadView(inView) -{ -} - -//---------------------------------------------------------------------------------------- -CDeferredTask::ExecuteResult CDeferredThreadViewCommand::ExecuteSelf() -//---------------------------------------------------------------------------------------- -{ - if (mCommand == cmd_GetNewMail) - { - if (mThreadView->IsStillLoading()) - return eWaitStayFront; // don't stop idling -// && ((mXPFolder.GetFolderFlags() & MSG_FOLDER_FLAG_INBOX) != 0) && // if this is an inbox -// ((mXPFolder.GetFolderFlags() & MSG_FOLDER_FLAG_IMAPBOX) == 0) // and our server is pop - } - return Inherited::ExecuteSelf(); -} // CDeferredThreadViewCommand::ExecuteSelf - -#pragma mark - - -//---------------------------------------------------------------------------------------- -CThreadView::CThreadView(LStream *inStream) -//---------------------------------------------------------------------------------------- -: Inherited(inStream) -, mXPFolder(NULL) -, mSavedSelection(nil) -, mExpectingNewMail(false) -, mGotNewMail(false) -, mRowToSelect(0) -, mSelectAfterDelete(false) // This new "hidden" pref was a demand from a big customer -, mMotionPendingCommand((MSG_MotionType)-1) -, mUndoTask(nil) -, mScrollToShowNew(false) -{ - XP_Bool noNextRowSelection; - if (PREF_GetBoolPref("mail.no_select_after_delete", &noNextRowSelection) == PREF_NOERROR - && noNextRowSelection) - SetSelectAfterDelete(false); -} - -//---------------------------------------------------------------------------------------- -CThreadView::~CThreadView() -//---------------------------------------------------------------------------------------- -{ - SaveSelectedMessage(); - delete mSavedSelection; -} - -//---------------------------------------------------------------------------------------- -void CThreadView::ApplyTextStyle(TableIndexT inRow) const -//---------------------------------------------------------------------------------------- -{ - CMessage message(inRow, GetMessagePane()); - // Set bold if new - if (!message.HasBeenRead()) - ::TextFace(bold); - else if (message.IsThread() && !message.IsOpenThread() && message.GetNumNewChildren() > 0) - ::TextFace(underline); - else - ::TextFace(normal); - ::TextMode(message.IsDeleted() ? grayishTextOr : srcOr); -} // CMessageFolderView::ApplyTextStyle - -//---------------------------------------------------------------------------------------- -void CThreadView::ApplyTextColor(TableIndexT inRow) const -//---------------------------------------------------------------------------------------- -{ - CMessage message(inRow, GetMessagePane()); - // Set up the text color based on priority - RGBColor priorityColor; - message.GetPriorityColor(priorityColor); - ::RGBForeColor(&priorityColor); -} // CMessageFolderView::ApplyTextStyle - -//---------------------------------------------------------------------------------------- -void CThreadView::DrawCellContents( - const STableCell &inCell, - const Rect &inLocalRect) -//---------------------------------------------------------------------------------------- -{ - ApplyTextColor(inCell.row); - - CMessage message(inCell.row, GetMessagePane()); - PaneIDT cellType = GetCellDataType(inCell); - switch (cellType) - { - case kThreadMessageColumn: - { - // draw a "thread dragger" /*if we're sorted by thread and*/ this - // message is a thread header... or if we are watched/ignored - //if (GetSortedColumn() == kThreadMessageColumn && message.IsThread()) - - ResIDT iconID = message.GetThreadIconID(); - if( /*GetSortedColumn() == kThreadMessageColumn &&*/ ( message.IsThread() || iconID >= kWatchedThreadIcon ) ) - DrawIconFamily( iconID, 16, 16, 0, inLocalRect); - break; - - } - case kMarkedReadMessageColumn: - { - if (!message.HasBeenRead()) - DrawIconFamily(kMessageReadIcon, 16, 16, 0, inLocalRect); - break; - } - case kFlagMessageColumn: - if (message.IsFlagged()) - DrawIconFamily(kFlagIcon, 16, 16, 0, inLocalRect); - break; - case kSubjectMessageColumn: - SInt16 newLeft = DrawIcons(inCell, inLocalRect); - Rect subjectRect = inLocalRect; - subjectRect.left = newLeft; - DrawMessageSubject(inCell.row, subjectRect); - break; - case kSenderMessageColumn: - { - const char* raw = message.GetSender(); - char* conv = IntlDecodeMimePartIIStr(raw, mContext->GetWinCSID(), FALSE); - - if(mContext->GetWinCSID() == CS_UTF8) - DrawUTF8TextString((conv ? conv : raw), &mTextFontInfo, 2, inLocalRect); - else - DrawTextString((conv ? conv : raw), &mTextFontInfo, 2, inLocalRect); - - if(conv) - XP_FREE(conv); - } - break; - case kDateMessageColumn: - DrawTextString(message.GetDateString(), &mTextFontInfo, 2, inLocalRect, teFlushLeft, true, truncEnd); - break; - case kPriorityMessageColumn: - DrawMessagePriority(message, inLocalRect); - break; - case kSizeMessageColumn: - DrawMessageSize(message, inLocalRect); - break; - case kStatusMessageColumn: - DrawMessageStatus(message, inLocalRect); - break; - case kAddresseeMessageColumn: - { - const char* raw = message.GetAddresseeString(); - char* conv = IntlDecodeMimePartIIStr(raw, mContext->GetWinCSID(), FALSE); - if(mContext->GetWinCSID() == CS_UTF8) - DrawUTF8TextString((conv ? conv : raw), &mTextFontInfo, 2, inLocalRect); - else - DrawTextString((conv ? conv : raw), &mTextFontInfo, 2, inLocalRect); - DrawTextString((conv ? conv : raw), &mTextFontInfo, 2, inLocalRect); - if(conv) - XP_FREE(conv); - } - break; - case kTotalMessageColumn: - if (GetSortedColumn() == kThreadMessageColumn && message.IsThread()) - DrawCountCell(message.GetNumChildren(), inLocalRect); - break; - case kUnreadMessageColumn: - if (GetSortedColumn() == kThreadMessageColumn && message.IsThread()) - DrawCountCell(message.GetNumNewChildren(), inLocalRect); - break; - default: - Assert_(false); - break; - } - // The selection of a new message after one is removed is handled by a timer, and is keyed - // off mRowToSelect. This data member is set when we are notified that a row has been removed. - // We used to start this timer immediately on initiating the delete operation (in DeleteSelection) - // but this ended up firing before the refresh occurred, resulting in two rows selected, which - // was ugly. So we turn on the idler here, now, to make sure that the row isn't selected until - // after the refresh is done. 98/01/14 - if (mRowToSelect) - { - CDeferredTaskManager::Post1(new CDeferredSelectRowTask(this, mRowToSelect), this); - mRowToSelect = LArray::index_Bad; - } - if (mScrollToShowNew) - { - CDeferredTaskManager::Post1(new CScrollToNewMailTask(this), this); - mScrollToShowNew = false; - } -} // CThreadView::DrawCellContents - -//---------------------------------------------------------------------------------------- -void CThreadView::DrawIconsSelf( - const STableCell& inCell, - IconTransformType inTransformType, - const Rect& inIconRect) const -//---------------------------------------------------------------------------------------- -{ - const ResIDT kPaperClipBackLayer = 15555; - const ResIDT kPaperClipFrontLayer = 15556; - CMessage message(inCell.row, GetMessagePane()); - Boolean hasAttachments = message.HasAttachments(); - if (hasAttachments) - DrawIconFamily(kPaperClipBackLayer, 16, 16, inTransformType, inIconRect); - Inherited::DrawIconsSelf(inCell, inTransformType, inIconRect); - if (hasAttachments) - DrawIconFamily(kPaperClipFrontLayer, 16, 16, inTransformType, inIconRect); -} // CThreadView::DrawIconsSelf - -//---------------------------------------------------------------------------------------- -Boolean CThreadView::GetDragCopyStatus( - DragReference inDragRef -, const CMailSelection& inSelection -, Boolean& outCopy) -//---------------------------------------------------------------------------------------- -{ - SInt16 modifiers; - ::GetDragModifiers(inDragRef, NULL, &modifiers, NULL); - outCopy = ((modifiers & optionKey) != 0); // user wants copy if possible. - MSG_DragEffect effect = outCopy ? MSG_Require_Copy : MSG_Default_Drag; - MSG_FolderInfo* destFolder = GetOwningFolder(); - if (!destFolder) - return false; // eg, when the pane is blank because a server is selected. - // Ask the back end for guidance on what is possible: - effect = ::MSG_DragMessagesIntoFolderStatus( - inSelection.xpPane, - inSelection.GetSelectionList(), - inSelection.selectionSize, - destFolder, - effect); - if (effect == MSG_Drag_Not_Allowed && outCopy) - { - // Well, maybe a move is ok - effect = ::MSG_DragMessagesIntoFolderStatus( - inSelection.xpPane, - inSelection.GetSelectionList(), - inSelection.selectionSize, - destFolder, - MSG_Default_Drag); - } - outCopy = (effect & MSG_Require_Copy) != 0; - return (effect != MSG_Drag_Not_Allowed); // this looks ok as a drop operation. -} // CThreadView::GetSelectionAndCopyStatusFromDrag - -//---------------------------------------------------------------------------------------- -void CThreadView::EnterDropArea( - DragReference inDragRef, - Boolean inDragHasLeftSender) -// CStandardFlexTable overrides the LDropArea base method, because it assumes a drop-on-row -// scenario -//---------------------------------------------------------------------------------------- -{ - LDragAndDrop::EnterDropArea(inDragRef, inDragHasLeftSender); -} - -//---------------------------------------------------------------------------------------- -void CThreadView::LeaveDropArea(DragReference inDragRef) -// CStandardFlexTable overrides the LDropArea base method, because it assumes a drop-on-row -// scenario -//---------------------------------------------------------------------------------------- -{ - LDragAndDrop::LeaveDropArea(inDragRef); - mDropRow = 0; - mIsDropBetweenRows = false; - mIsInternalDrop = false; -} - -//---------------------------------------------------------------------------------------- -Boolean CThreadView::ItemIsAcceptable( - DragReference inDragRef, - ItemReference /*inItemRef*/ ) -//---------------------------------------------------------------------------------------- -{ - Boolean dropOK = false; - Boolean doCopy = false; - - CMailSelection selection; - if (GetSelectionFromDrag(inDragRef, selection) - && selection.xpPane != GetMessagePane() - && GetDragCopyStatus(inDragRef, selection, doCopy)) - dropOK = true; - if (dropOK && doCopy) - { - CursHandle copyDragCursor = ::GetCursor(curs_CopyDrag); - if (copyDragCursor != nil) - ::SetCursor(*copyDragCursor); - } - else - ::SetCursor(&qd.arrow); - return dropOK; -} // CThreadView::ItemIsAcceptable - -//---------------------------------------------------------------------------------------- -void CThreadView::ReceiveDragItem( - DragReference inDragRef, - DragAttributes /*inDragAttrs*/, - ItemReference inItemRef, - Rect& /*inItemBounds*/) -//---------------------------------------------------------------------------------------- -{ - Assert_(inItemRef == CMailFlexTable::eMailNewsSelectionDragItemRefNum); - - // What are the items being dragged? - CMailSelection selection; - if (!GetSelectionFromDrag(inDragRef, selection)) - return; - - // Don't do anything if the user aborted by dragging back into the same view. - if (selection.xpPane == GetMessagePane()) - return; - - Boolean copyMessages; - if (!GetDragCopyStatus(inDragRef, selection, copyMessages)) - return; - - // display modal dialog - short stringID = (copyMessages ? 19 : 15); // Copying / Moving Messages - CStr255 commandString; - ::GetIndString(commandString, 7099, stringID); - CMailProgressWindow* progressWindow = CMailProgressWindow::CreateModalParasite( - CMailProgressWindow::res_ID_modal, - selection.xpPane, - commandString); - if (progressWindow) - progressWindow->SetDelay(0); - - // copy / move messages - if (! copyMessages) - ::MSG_MoveMessagesIntoFolder( - selection.xpPane, - selection.GetSelectionList(), - selection.selectionSize, - mXPFolder.GetFolderInfo() - ); - else - ::MSG_CopyMessagesIntoFolder( - selection.xpPane, - selection.GetSelectionList(), - selection.selectionSize, - mXPFolder.GetFolderInfo() - ); - // Close any windows associated with these messages, if the preferences - // say we should. - CMessageWindow::NoteSelectionFiledOrDeleted(selection); - mUndoCommand = cmd_Undo; -} // CThreadView::ReceiveDragItem - -//---------------------------------------------------------------------------------------- -void CThreadView::DrawMessageSize( - const CMessage& inMessage, - const Rect& inLocalRect ) -//---------------------------------------------------------------------------------------- -{ - DrawTextString(inMessage.GetSizeStr(), - &mTextFontInfo, 2, inLocalRect, teFlushLeft, true, truncEnd); -} // CThreadView::DrawMessageSize - -//---------------------------------------------------------------------------------------- -void CThreadView::DrawMessagePriority( - const CMessage& inMessage, - const Rect& inLocalRect) -//---------------------------------------------------------------------------------------- -{ - DrawTextString(inMessage.GetPriorityStr(), - &mTextFontInfo, 0, inLocalRect); -} // CThreadView::DrawMessagePriority - -//---------------------------------------------------------------------------------------- -void CThreadView::DrawMessageStatus( - const CMessage& inMessage, - const Rect& inLocalRect) -//---------------------------------------------------------------------------------------- -{ - DrawTextString(inMessage.GetStatusStr(), - &mTextFontInfo, 0, inLocalRect); -} //CThreadView::DrawMessageStatus - -//---------------------------------------------------------------------------------------- -ResIDT CThreadView::GetIconID(TableIndexT inRow) const -//---------------------------------------------------------------------------------------- -{ - CMessage message(inRow, GetMessagePane()); - return message.GetIconID(mXPFolder.GetFolderFlags()); -} // CMessageFolderView::GetIconID - -//---------------------------------------------------------------------------------------- -UInt16 CThreadView::GetNestedLevel(TableIndexT inRow) const -//---------------------------------------------------------------------------------------- -{ - CMessage message(inRow, GetMessagePane()); - return message.GetThreadLevel(); -} // CThreadView::GetNestedLevel - -//---------------------------------------------------------------------------------------- -Boolean CThreadView::GetHiliteTextRect( - const TableIndexT inRow, - Rect& outRect) const -//---------------------------------------------------------------------------------------- -{ - STableCell cell(inRow, GetHiliteColumn()); - if (!GetLocalCellRect(cell, outRect)) - return false; - Rect iconRect; - GetIconRect(cell, outRect, iconRect); - outRect.left = iconRect.right; - char subject[kMaxSubjectLength]; - GetHiliteText(inRow, subject, sizeof(subject), &outRect); - return true; -} // CThreadView::GetHiliteRect - -//---------------------------------------------------------------------------------------- -void CThreadView::GetDropFlagRect( - const Rect& inLocalCellRect, - Rect& outFlagRect ) const -//---------------------------------------------------------------------------------------- -{ - Inherited::GetDropFlagRect(inLocalCellRect, outFlagRect); - if (GetSortedColumn() != kThreadMessageColumn) - { - // Return a rectangle of zero width. - outFlagRect.left = inLocalCellRect.left; - outFlagRect.right = outFlagRect.left; - } -} // CThreadView::GetDropFlagRect - -//---------------------------------------------------------------------------------------- -void CThreadView::GetMainRowText( - TableIndexT inRow, - char* outText, - UInt16 inMaxBufferLength) const -// Calculate the text and (if ioRect is not passed in as null) a rectangle that fits it. -// Return result indicates if any of the text is visible in the cell -//---------------------------------------------------------------------------------------- -{ - if (!outText || inMaxBufferLength < 2) - return; - CMessage message(inRow, GetMessagePane()); - const char* raw = message.GetSubject(outText, inMaxBufferLength - 1); - char* conv = IntlDecodeMimePartIIStr(raw, mContext->GetWinCSID(), FALSE); - if (conv) - { - XP_STRNCPY_SAFE(outText, conv, inMaxBufferLength); - XP_FREE(conv); - } -} // CThreadView::GetMainRowText - -//---------------------------------------------------------------------------------------- -void CThreadView::DrawMessageSubject( - TableIndexT inRow, - const Rect& inLocalRect) -// Draw the message drop flag, icon and subject -//---------------------------------------------------------------------------------------- -{ - // draw a drop flag if we're sorted by thread and this - // message is a thread header... - char subject[kMaxSubjectLength]; - Rect textRect = inLocalRect; - if (GetHiliteText(inRow, subject, sizeof(subject), &textRect)) - { - if (mContext->GetWinCSID() == CS_UTF8) - { - textRect.right = inLocalRect.right; // calculation will have been wrong. - DrawUTF8TextString(subject, &mTextFontInfo, 0, textRect); - } - else - DrawTextString(subject, &mTextFontInfo, 0, textRect); -// if (inRow == mDropRow) -// ::InvertRect(&textRect); - } -} // CThreadView::DrawMessageSubject - -//---------------------------------------------------------------------------------------- -Boolean CThreadView::CellSelects(const STableCell& inCell) const -//---------------------------------------------------------------------------------------- -{ - PaneIDT cellType = GetCellDataType(inCell); - switch (cellType) - { - case kThreadMessageColumn: - { - CMessage message(inCell.row, GetMessagePane()); - return (message.IsThread()); - } - case kMarkedReadMessageColumn: - case kFlagMessageColumn: - return false; - default: - return true; - } -} // CThreadView::CellSelects - -//----------------------------------- -void CThreadView::SetRowCount() -// Queries the back end pane and sets the number of rows. -// Overridden to call MSG_GetThreadLineByIndex, which forces -// authentication if the preference specifies it. A result of false -// means that the folder is password protected. -//----------------------------------- -{ - MSG_MessageLine ignored; - MSG_Pane* pane = GetMessagePane(); - if (!pane || !::MSG_GetThreadLineByIndex(pane, 0, 1, &ignored)) - { - // Access denied! - TableIndexT rows, cols; - GetTableSize(rows, cols); - if (rows > 0) - RemoveRows(rows, 1, false); - return; - } - Inherited::SetRowCount(); -} // CThreadView::SetRowCount() - - -//---------------------------------------------------------------------------------------- -Boolean CThreadView::CellWantsClick ( const STableCell& inCell ) const -// Overloaded to ensure that certain columns get the mouse click -//---------------------------------------------------------------------------------------- -{ - PaneIDT cellType = GetCellDataType(inCell); - switch (cellType) - { -// case kThreadMessageColumn: - case kMarkedReadMessageColumn: - case kFlagMessageColumn: - case kPriorityMessageColumn: - return true; - - default: - return false; - } - -} // CThreadView::CellWantsClick - - -//---------------------------------------------------------------------------------------- -void CThreadView::ClickCell( - const STableCell &inCell, - const SMouseDownEvent &inMouseDown) -// Handles marking message read/unread -//---------------------------------------------------------------------------------------- -{ - CMailProgressWindow::RemoveModalParasite(); - PaneIDT cellType = GetCellDataType(inCell); - switch (cellType) - { - case kThreadMessageColumn: - { - if (GetSortedColumn() == kThreadMessageColumn) - { - CMessage message(inCell.row, GetMessagePane()); - if (message.IsThread()) - { - if (! message.IsOpenThread()) - ToggleExpandAction(inCell.row); - DoSelectThread(inCell.row); - CMessage::InvalidateCache(); // Because BE has changed the message state - } - } - break; - } - // toggle the message's read/unread state - case kMarkedReadMessageColumn: - { - MSG_ViewIndex index = inCell.row - 1; - MSG_Command(GetMessagePane(), MSG_ToggleMessageRead, &index, 1); - CMessage::InvalidateCache(); // Because BE has changed the message state - RefreshCell(inCell); - break; - } - case kFlagMessageColumn: - { - CMessage message(inCell.row, GetMessagePane()); - MSG_CommandType cmd = message.IsFlagged() ? MSG_UnmarkMessages : MSG_MarkMessages; - MSG_ViewIndex index = inCell.row - 1; - MSG_Command(GetMessagePane(), cmd, &index, 1); - CMessage::InvalidateCache(); // Because BE has changed the message state - RefreshCell(inCell); - break; - } - case kPriorityMessageColumn: - { - if ((mXPFolder.GetFolderFlags() & MSG_FOLDER_FLAG_NEWSGROUP) != 0) - break; // no priority for news. - - // calculate popup location - FocusDraw(); - Point where = inMouseDown.wherePort; - PortToGlobalPoint(where); - Rect cellRect; - if (GetLocalCellRect(inCell, cellRect)) - { - where = topLeft(cellRect); - ::LocalToGlobal(&where); - } - - // get popup default value - CMessage message(inCell.row, GetMessagePane()); - MSG_PRIORITY oldPriority = message.GetPriority(); - Int16 defaultChoice = CMessage::PriorityToMenuItem(oldPriority); - - // display popup - Int16 menuItem = 0; - LMenu * thePopup = new LMenu(kPriorityMenuID); - - { // copied from HandlePopupMenuSelect() - - MenuHandle menuH = thePopup->GetMacMenuH(); - -// we decided that all the context menus should look the same and -// this meant drawing them in the system font (at least for 4.0) -// to re-enable drawing in another font just take out my #ifdef's -// and #endif's -#ifdef USE_SOME_OTHER_FONT_FOR_THE_PRIORITY_MENU - Int16 saveFont = ::LMGetSysFontFam(); - Int16 saveSize = ::LMGetSysFontSize(); - - StMercutioMDEFTextState theMercutioMDEFTextState; -#endif - try { -#ifdef USE_SOME_OTHER_FONT_FOR_THE_PRIORITY_MENU - - // Reconfigure the system font so that the menu will be drawn in our desired - // font and size - if ( mTextTraitsID ) { - FocusDraw(); - TextTraitsH traitsH = UTextTraits::LoadTextTraits(mTextTraitsID); - if ( traitsH ) { - // Bug #64133 - // If setting to application font, get the application font for current script - if((**traitsH).fontNumber == 1) - ::LMSetSysFontFam ( ::GetScriptVariable(::FontToScript(1), smScriptAppFond) ); - else - ::LMSetSysFontFam ( (**traitsH).fontNumber ); - ::LMSetSysFontSize((**traitsH).size); - ::LMSetLastSPExtra(-1L); - } - } -#endif - // Handle the actual insertion into the hierarchical menubar - ::InsertMenu(menuH, hierMenu); - - // Call PopupMenuSelect and wait for it to return - Int32 result = ::PopUpMenuSelect(menuH, where.v, where.h, defaultChoice); - - // Extract the values from the returned result. - menuItem = LoWord(result); - } - catch(...) { - // Ignore errors - } - -// this is the last one of these that you'd want to take out in order -// to re-enable the ability to use some font (other than the system font) -// to draw the priority context menu -#ifdef USE_SOME_OTHER_FONT_FOR_THE_PRIORITY_MENU - // Restore the system font - ::LMSetSysFontFam(saveFont); - ::LMSetSysFontSize(saveSize); - ::LMSetLastSPExtra(-1L); -#endif - // Finally get the menu removed - ::DeleteMenu(kPriorityMenuID); - } - - if (menuItem) - { - MSG_PRIORITY newPriority = CMessage::MenuItemToPriority(menuItem); - if (newPriority != oldPriority) - { - // BE bug? We're not getting told that a change happened. So - // do it ourselves. If this gets fixed later, we can remove these - // change calls. - ChangeStarting(GetMessagePane(), MSG_NotifyChanged, inCell.row, 1); - MSG_SetPriority(GetMessagePane(), message.GetMessageKey(), newPriority); - ChangeFinished(GetMessagePane(), MSG_NotifyChanged, inCell.row, 1); - CMessage::InvalidateCache(); // Because BE has changed the message state - } - } - break; - } - default: - break; - } -} // CThreadView::ClickCell - -//---------------------------------------------------------------------------------------- -TableIndexT CThreadView::GetHiliteColumn() const -//---------------------------------------------------------------------------------------- -{ - return mTableHeader->ColumnFromID(kSubjectMessageColumn); -} // CThreadView::GetHiliteColumn - -//---------------------------------------------------------------------------------------- -void CThreadView::SetCellExpansion( - const STableCell& inCell, - Boolean inExpanded) -//---------------------------------------------------------------------------------------- -{ - Boolean currentlyExpanded; - if (!CellHasDropFlag(inCell, currentlyExpanded) || (inExpanded == currentlyExpanded)) - return; - ToggleExpandAction(inCell.row); - CMessage::InvalidateCache(); // Because BE has changed the message state -} // CThreadView::SetCellExpansion - -//---------------------------------------------------------------------------------------- -Boolean CThreadView::CellInitiatesDrag(const STableCell& inCell) const -//---------------------------------------------------------------------------------------- -{ - PaneIDT cellType = GetCellDataType(inCell); - return (cellType == kSubjectMessageColumn - || (cellType == kThreadMessageColumn && GetSortedColumn() == kThreadMessageColumn)); -} // CThreadView::CellInitiatesDrag - -//---------------------------------------------------------------------------------------- -Boolean CThreadView::CellHasDropFlag( - const STableCell& inCell, - Boolean& outExpanded) const -//---------------------------------------------------------------------------------------- -{ - PaneIDT cellType = GetCellDataType(inCell); - - // Only show drop flags when we're sorted by thread - if (cellType == kSubjectMessageColumn && GetSortedColumn() == kThreadMessageColumn) - { - CMessage message(inCell.row, GetMessagePane()); - if (message.IsThread()) - { - outExpanded = message.IsOpenThread(); - return true; - } - } - return false; -} // CThreadView::CellHasDropFlag - -//---------------------------------------------------------------------------------------- -TableIndexT CThreadView::CountExtraRowsControlledByCell(const STableCell& inCell) const -//---------------------------------------------------------------------------------------- -{ - PaneIDT cellType = GetCellDataType(inCell); - // Only show drop flags when we're sorted by thread - if (cellType != kThreadMessageColumn || GetSortedColumn() != kThreadMessageColumn) - return 0; - int32 msgExpansionDelta = MSG_ExpansionDelta(GetMessagePane(), inCell.row - 1); - if (msgExpansionDelta >= 0) - return 0; - return -msgExpansionDelta; -} // CThreadView::CountExtraRowsControlledByCell - -//---------------------------------------------------------------------------------------- -void CThreadView::OpenRow(TableIndexT inRow) -// Open the message into its own window. -//---------------------------------------------------------------------------------------- -{ - Assert_(mContext); - - // Check the application heap. - if (Memory_MemoryIsLow() || ::MaxBlock() < 100*1024) - throw memFullErr; - // Check the Mozilla allocator - void* temp = XP_ALLOC(20*1024); - if (!temp) - throw memFullErr; - XP_FREE(temp); - - ::SetCursor(*::GetCursor(watchCursor)); - Boolean multipleSelection = GetSelectedRowCount() > 1; - CMessage message(inRow, GetMessagePane()); - // if a Draft, template, or Queue message open the compose window - if ( - (mXPFolder.GetFolderFlags() - & (MSG_FOLDER_FLAG_DRAFTS | MSG_FOLDER_FLAG_QUEUE | MSG_FOLDER_FLAG_TEMPLATES)) - || message.IsTemplate() - ) - { - ::MSG_OpenDraft(GetMessagePane() , mXPFolder.GetFolderInfo(), message.GetMessageKey()); - return; - } - // First see if there's an open window open to this message. If there is, - // bring it to the front. - CMessageWindow* messageWindow = CMessageWindow::FindAndShow(message.GetMessageKey()); - if (messageWindow) - { - messageWindow->GetMessageView()->SetDefaultCSID(mContext->GetDefaultCSID()); - // Found it. Bring it to the front. - messageWindow->Select(); - return; - } - // First, if recycling a window is indicated, ask for any existing one. - if (mContext->GetCurrentCommand() != cmd_OpenSelectionNewWindow) - { - // With a multiple selection, we never recycle! - XP_Bool prefReuseWindow = 0; // recycle any message window - PREF_GetBoolPref("mailnews.reuse_message_window", &prefReuseWindow); - if (!multipleSelection && - (CApplicationEventAttachment::CurrentEventHasModifiers(optionKey) ^ prefReuseWindow)) - { - messageWindow = CMessageWindow::FindAndShow(0); - } - } - // If we couldn't (or shouldn't) recycle one, make a new one. - if (!messageWindow) - { - try - { - messageWindow = - (CMessageWindow*)URobustCreateWindow::CreateWindow( - CMessageWindow::res_ID, - LCommander::GetTopCommander()); - CBrowserContext* theContext = new CBrowserContext(MWContextMailMsg); - StSharer theShareLock(theContext); // if we throw, theContext will have no users & die - messageWindow->SetWindowContext(theContext); - } - catch(...) - { - delete messageWindow; - messageWindow = NULL; - throw; - } - } - // Whether it's a new one or an old one, load the message now. - if (messageWindow) - { - try - { - messageWindow->GetMessageView()->ShowMessage( - CMailNewsContext::GetMailMaster(), - mXPFolder.GetFolderInfo(), - message.GetMessageKey()); // pass flags to tell what sort of message it is - messageWindow->GetMessageView()->SetDefaultCSID(mContext->GetDefaultCSID()); - messageWindow->Select(); -// messageWindow->Show(); - // The window will now show itself when a successful load occurs - } - catch(...) - { - delete messageWindow; - messageWindow = NULL; - throw; - } - } - CMessage::InvalidateCache(); // So that the "read" flag gets changed. -} // CThreadView::OpenRow - -#define THREE_PANE 1 - -//---------------------------------------------------------------------------------------- -void CThreadView::SaveSelectedMessage() -//---------------------------------------------------------------------------------------- -{ - MSG_Pane* curPane = GetMessagePane(); - if (curPane) - { - MSG_FolderInfo* curFolder = ::MSG_GetThreadFolder(curPane); - if (curFolder) - { - if (GetSelectedRowCount() == 1) - { - TableIndexT curRow = mTableSelector->GetFirstSelectedRow(); - CMessage message(curRow, curPane); - MessageKey curMessage = message.GetMessageKey(); - ::MSG_SetLastMessageLoaded(curFolder, curMessage); - } - else - ::MSG_SetLastMessageLoaded(curFolder, MSG_MESSAGEKEYNONE); - } - } -} // CThreadView::SaveSelectedMessage - -//---------------------------------------------------------------------------------------- -Boolean CThreadView::RestoreSelectedMessage() -// Called on FolderLoaded pane notification. We probably should check the preference. -//---------------------------------------------------------------------------------------- -{ - XP_Bool remember = true; - if (PREF_NOERROR != PREF_GetBoolPref("mailnews.remember_selected_message", &remember)) - return false; - if (!remember) - return false; - MSG_Pane* curPane = GetMessagePane(); - if (curPane) - { - MSG_FolderInfo* curFolder = ::MSG_GetThreadFolder(curPane); - if (curFolder) - { - MessageKey savedMessage = ::MSG_GetLastMessageLoaded(curFolder); - if (savedMessage != MSG_MESSAGEKEYNONE) - { - MSG_ViewIndex index = ::MSG_GetMessageIndexForKey(curPane, savedMessage, true); - if (index != MSG_VIEWINDEXNONE) - { - mRowToSelect = index + 1; - return true; - } - } - } - } - return false; -} // CThreadView::RestoreSelectedMessage - -//---------------------------------------------------------------------------------------- -void CThreadView::LoadMessageFolder( - CNSContext* inContext, // My window's context - const CMessageFolder& inFolder, - Boolean inLoadNow) -// Load a given message folder into the message table view. -//---------------------------------------------------------------------------------------- -{ - Assert_(inContext); - // Load the folder into the message list. We'll get a PaneChanged message - // when loading is complete, and another one to say that the folder info - // has changed. When these callbacks occur, we'll call SetFolder(). However, - // the first time the window is initialized, the title needs to look nice - // even during the load process. Hence this call, which will be made twice: - SetFolder(inFolder); - if (!inLoadNow) - { - CDeferredLoadFolderTask* task - = new CDeferredLoadFolderTask(this, inContext, inFolder); - CDeferredTaskManager::Post1(task, this); - return; - } - try - { - ::SetCursor(*::GetCursor(watchCursor)); - SaveSelectedMessage(); - UnselectAllCells(); - // Else it crashes, because the messageview (if displaying a message), doesn't - // get cleaned up properly. #81060 - mContext = inContext; -#if !ONECONTEXTPERWINDOW - SetMessagePane(nil); // release the memory first. -#endif - // A null inFolder is possible, and the result should be to clear the thread area. - // This behavior is new in 5.0 with the 3-pane window - 97/10/06 - if (!inFolder.GetFolderInfo()) - { - RemoveAllRows( true ); - SetMessagePane(nil); - return; - } -#if ONECONTEXTPERWINDOW - if (!GetMessagePane()) -#endif - { - SetMessagePane(::MSG_CreateThreadPane(*inContext, CMailNewsContext::GetMailMaster())); - ThrowIfNULL_(GetMessagePane()); - // plug into the view so we get notified when the data changes - ::MSG_SetFEData(GetMessagePane(), CMailCallbackManager::Get()); - } - if (inFolder.GetFolderInfo() == MSG_GetThreadFolder(GetMessagePane())) - return; - -#if USING_MODAL_FOLDER_LOAD - CStr255 commandString; - ::GetIndString(commandString, 7099, 16); // "Loading Folder" - CMailProgressWindow::CreateModalParasite( - CMailProgressWindow::res_ID_modal, - GetMessagePane(), - commandString); -#endif - // Close any other windows showing this folder - CWindowIterator iter(WindowType_MailThread); - CThreadWindow* thisWindow - = dynamic_cast(LWindow::FetchWindowObject(GetMacPort())); - - CThreadWindow* window; - for (iter.Next(window); window; iter.Next(window)) - { - window = dynamic_cast(window); - if (window && window != thisWindow) - { - CMessageView* messageView = window->GetMessageView(); - if (inFolder.GetFolderInfo() == messageView->GetFolderInfo()) - window->AttemptClose(); - } - } -#if 1 - // IMAP mailboxes do "get new mail" automatically. So set up the flags to expect new - // mail. - if ((inFolder.GetFolderFlags() & MSG_FOLDER_FLAG_IMAPBOX) == MSG_FOLDER_FLAG_IMAPBOX) - ExpectNewMail(); -#else - // IMAP inbox does "get new mail" automatically. So set up the flags to expect new - // mail. - #define IMAP_INBOX (MSG_FOLDER_FLAG_INBOX | MSG_FOLDER_FLAG_IMAPBOX) - if ((inFolder.GetFolderFlags() & IMAP_INBOX) == IMAP_INBOX) - ExpectNewMail(); -#endif - // Now finally, load the folder - ThrowIfError_(::MSG_LoadFolder(GetMessagePane(), inFolder.GetFolderInfo())); - - #ifndef THREE_PANE - SwitchTarget(this); - #endif - - // Change the i18n encoding and font to match the new folder: - int foldercsid = ::MSG_GetFolderCSID(inFolder.GetFolderInfo()); - if ((CS_UNKNOWN == foldercsid) || (CS_DEFAULT == foldercsid)) - { - foldercsid = INTL_DefaultDocCharSetID(0); - ::MSG_SetFolderCSID(inFolder.GetFolderInfo(), foldercsid); - } - SetDefaultCSID(foldercsid); - ResetTextTraits(); // May need to change the font when we change folder - } - catch(...) - { - } -} // CThreadView::LoadMessageFolder - -//---------------------------------------------------------------------------------------- -Boolean CThreadView::RelocateViewToFolder(const CMessageFolder& inFolder) -// Retarget the view to the specified BE folder. -//---------------------------------------------------------------------------------------- -{ - if (!inFolder.GetFolderInfo() || inFolder == mXPFolder) - return false; - - if (CThreadWindow::FindAndShow(inFolder.GetFolderInfo()) == nil) - { - MSG_Master* master = CMailNewsContext::GetMailMaster(); - LoadMessageFolder(mContext, inFolder); - return true; - } - return false; -} // CThreadWindow::RelocateViewToFolder - - -//---------------------------------------------------------------------------------------- -void CThreadView::FileMessagesToSelectedPopupFolder(const char *inFolderName, - Boolean inMoveMessages) -// File selected messages to the specified BE folder. If inMoveMessages is true, move -// the messages, otherwise copy them. -//---------------------------------------------------------------------------------------- -{ - if (!inFolderName || !*inFolderName) - return; - CMailSelection selection; - if ( !GetSelection(selection) ) { - Assert_(false); // Method should not be called in this case! - return; // Nothing selected! - } - -#ifdef Debug_Signal - const char *curName = ::MSG_GetFolderNameFromID(GetOwningFolder()); - Assert_(strcasecomp(curName, inFolderName) != 0); // Specified folder should not be the same as this folder -#endif // Debug_Signal - - CStr255 commandString; - ::GetIndString(commandString, 7099, (inMoveMessages ? 15 : 19)); // "Moving/Copying Messages" - CMailProgressWindow* progressWindow = CMailProgressWindow::CreateModalParasite( - CMailProgressWindow::res_ID_modal, - GetMessagePane(), - commandString); - if (progressWindow) - progressWindow->SetDelay(0); - if ( inMoveMessages ) - ::MSG_MoveMessagesInto(selection.xpPane, selection.GetSelectionList(), selection.selectionSize, - inFolderName); - else - ::MSG_CopyMessagesInto(selection.xpPane, selection.GetSelectionList(), selection.selectionSize, - inFolderName); - mUndoCommand = cmd_Undo; -} // CThreadWindow::FileMessagesToSelectedPopupFolder - -//---------------------------------------------------------------------------------------- -Boolean CThreadView::ScrollToGoodPlace() -//---------------------------------------------------------------------------------------- -{ - if (mRows == 0) - return false; - MessageKey id; - MSG_ViewIndex index; - MSG_ViewIndex threadIndex; - MSG_ViewNavigate(GetMessagePane(), MSG_FirstNew, 0, &id, &index, &threadIndex, NULL); - if (index != MSG_VIEWINDEXNONE) - { - ScrollRowIntoFrame(mRows); // show bottom cell... - ScrollRowIntoFrame(index + 1); // ... then show first unread. - return true; - } - return false; -} // CThreadView::ScrollToGoodPlace - -//---------------------------------------------------------------------------------------- -void CThreadView::NoteSortByThreadColumn(Boolean isThreaded) const -//---------------------------------------------------------------------------------------- -{ - if (isThreaded) - GetTableHeader()->ChangeIconOfColumn(kThreadMessageColumn, kThreadedIcon); - else - GetTableHeader()->ChangeIconOfColumn(kThreadMessageColumn, kUnthreadedIcon); -} - -//---------------------------------------------------------------------------------------- -void CThreadView::ChangeSort(const LTableHeader::SortChange* inSortChange) -//---------------------------------------------------------------------------------------- -{ - CStandardFlexTable::ChangeSort(inSortChange); - if (GetMessagePane() != NULL) - { - MSG_CommandType sortCommand; - switch (inSortChange->sortColumnID) - { - case kDateMessageColumn: sortCommand = MSG_SortByDate; break; - case kSubjectMessageColumn: sortCommand = MSG_SortBySubject; break; - case kThreadMessageColumn: sortCommand = MSG_SortByThread; break; - case kSenderMessageColumn: - case kAddresseeMessageColumn: sortCommand = MSG_SortBySender; break; - - case kMarkedReadMessageColumn: sortCommand = MSG_SortByUnread; break; - case kPriorityMessageColumn: sortCommand = MSG_SortByPriority; break; - case kSizeMessageColumn: sortCommand = MSG_SortBySize; break; - case kStatusMessageColumn: sortCommand = MSG_SortByStatus; break; - case kFlagMessageColumn: sortCommand = MSG_SortByFlagged; break; - case kHiddenOrderReceivedColumn: sortCommand = MSG_SortByMessageNumber; break; - //case kUnreadMessageColumn: sortCommand = - //case kTotalMessageColumn: sortCommand = - - default: sortCommand = (MSG_CommandType) 0; - } - if (sortCommand != 0) - { - CMailProgressWindow::RemoveModalParasite(); - ::MSG_Command(GetMessagePane(), sortCommand, NULL, 0); - // Make sure the menus and headers reflect the new state of affairs - SyncSortToBackend(); - } - } -} // CThreadView::ChangeSort - -//---------------------------------------------------------------------------------------- -void CThreadView::DeleteSelection() -// Delete all selected messages -//---------------------------------------------------------------------------------------- -{ - try - { - CMailSelection selection; - if (GetSelection(selection)) - { -#if 0 - // Don't do this any more! Interrupting IMAP will cause a crash if the timing - // is just right. 98/03/31 - CThreadWindow* threadWindow - = dynamic_cast(LWindow::FetchWindowObject(GetMacPort())); - XP_ASSERT(threadWindow); - CMessageView* messageView - = dynamic_cast(threadWindow-> - FindPaneByID(CMessageView::class_ID)); - XP_ASSERT(messageView); - messageView->ObeyCommand(cmd_Stop, NULL); -#endif - // Try to close any open windows on these messages - const MSG_ViewIndex* index = selection.GetSelectionList(); - for (int i = 0; i < selection.selectionSize; i++,index++) - { - CMessage message((*index + 1), GetMessagePane()); - // (Add one to convert to TableIndexT) - CMessageWindow::CloseAll(message.GetMessageKey()); - } - MSG_CommandType cmd = - ((mXPFolder.GetFolderFlags() & MSG_FOLDER_FLAG_NEWSGROUP) == 0) - ? UMessageLibrary::GetMSGCommand(cmd_Clear) - : MSG_CancelMessage; // cancel my posting, if possible. - CMailProgressWindow::RemoveModalParasite(); - MSG_Command( - GetMessagePane(), - cmd, - (MSG_ViewIndex*)selection.GetSelectionList(), - selection.selectionSize); - UnselectAllCells(); - } - // The selection of a new message after one is removed is handled by a deferred task. - // We used to start this timer immediately on initiating the delete operation (here) - // but this ended up firing before the refresh occurred, resulting in two rows - // selected, which was ugly. So we moved the posting call to DrawCellContents, - // to make sure that the row isn't selected until after the refresh is done. 98/01/14 - } - catch(...) {} -} // CThreadView::DeleteSelection() - -//---------------------------------------------------------------------------------------- -void CThreadView::ChangeStarting( - MSG_Pane* inPane, - MSG_NOTIFY_CODE inChangeCode, - TableIndexT inStartRow, - SInt32 inRowCount) -//---------------------------------------------------------------------------------------- -{ - if (mMysticPlane <= kMysticUpdateThreshHold - && (inChangeCode == MSG_NotifyScramble || inChangeCode == MSG_NotifyAll)) - { - try - { - // Get the selection, convert it to non-volatile MSG_FolderInfo... - CMailSelection selection; - if (GetSelection(selection)) - { - delete mSavedSelection; - mSavedSelection = new CPersistentMessageSelection(selection); - } - } - catch (...) {} - } - Inherited::ChangeStarting(inPane, inChangeCode, inStartRow, inRowCount); -} // CThreadView::ChangeStarting - -//---------------------------------------------------------------------------------------- -void CThreadView::ChangeFinished( - MSG_Pane* inPane, - MSG_NOTIFY_CODE inChangeCode, - TableIndexT inStartRow, - SInt32 inRowCount) -//---------------------------------------------------------------------------------------- -{ - Inherited::ChangeFinished(inPane, inChangeCode, inStartRow, inRowCount); - if (mMysticPlane <= kMysticUpdateThreshHold) - { - switch (inChangeCode) - { - case MSG_NotifyScramble: - case MSG_NotifyAll: - { - SetNotifyOnSelectionChange(false); - try - { - UnselectAllCells(); - if (mSavedSelection) - { - const MSG_ViewIndex* index = mSavedSelection->GetSelectionList(); - MSG_ViewIndex count = mSavedSelection->selectionSize; - for (MSG_ViewIndex i = 0; i < count; i++, index++) - { - if (*index != MSG_VIEWINDEXNONE) - SelectRow(1 + *index); - } - } - } - catch (...) {} - SetNotifyOnSelectionChange(true); - SelectionChanged(); - delete mSavedSelection; - mSavedSelection = NULL; - } - break; - case MSG_NotifyInsertOrDelete: - if (CMailProgressWindow::GettingMail()) // could happen from the folder pane etc. - mExpectingNewMail = true; - if (mExpectingNewMail || inRowCount > 0) - mGotNewMail = true; - // If we're deleting the only selected row, we may need to select - // something later. Don't do this as a result of "get new mail", though. - // The intention here is that this behavior is only to happen as a result - // of an explicit user delete, on the current machine (Note that you may - // log on to another machine and delete the message that is currently - // selected. Note also that, during folder load, filters can cause a - // "row-deleted" message here.) - if (inRowCount == -1 // one row was deleted - && mSelectAfterDelete // the preference to do this is on - && GetSelectedRowCount() == 0 // there is nothing selected now - && inStartRow <= mRows + 1 // range check (+1 if deleting last row) - && !mExpectingNewMail) // this is not a folder load, or get mail - mRowToSelect = inStartRow; - break; - } - CMessage::InvalidateCache(); // most changes will make the index invalid. - } -} // CThreadView::ChangeFinished - -//---------------------------------------------------------------------------------------- -void CThreadView::SetFolder(const CMessageFolder& inFolder) -// Set the window title to the folder name. -//---------------------------------------------------------------------------------------- -{ - mXPFolder = inFolder; - - Boolean isNewsgroup = ((mXPFolder.GetFolderFlags() & MSG_FOLDER_FLAG_NEWSGROUP) != 0); - - char newName[255]; - const char* nameToUse = (inFolder.GetPrettyName() ? - inFolder.GetPrettyName() : inFolder.GetName()); - if (nameToUse) - { - strcpy(newName, nameToUse); - NET_UnEscape(newName); - } - else - *newName = '\0'; - - CThreadWindow* threadWindow - = dynamic_cast(LWindow::FetchWindowObject(GetMacPort())); - if (threadWindow) - threadWindow->SetFolderName(newName, isNewsgroup); -} // CThreadView::SetFolderName - -// ------------------------- -void CThreadView::SyncSortToBackend() -//--------------------------- -{ - // This is ugly it would be better if we did this in FindCommandStatus. - // since the BE could provide us the needed info. The difficutly would be in keeping - // the headers in sync. If done properly would help simplify FindCommandStatus - // and eliminate all this extra stuff - // Something to think about for 5.0 - MSG_Pane* inPane = GetMessagePane(); - XP_Bool selectable; - MSG_COMMAND_CHECK_STATE checkedState; - const char* display_string = nil; - MSG_CommandType cmd; - XP_Bool plural; - for (cmd = MSG_SortByDate; - cmd <= MSG_SortByUnread; - cmd = MSG_CommandType( int(cmd) + 1)) - { - ::MSG_CommandStatus( - inPane, cmd, nil, 0, &selectable, &checkedState, &display_string, &plural ); - if (checkedState == MSG_Checked) - break; - } - PaneIDT pane = 0; - switch ( cmd ) - { - case MSG_SortByDate: pane = kDateMessageColumn; break; - case MSG_SortBySubject: pane = kSubjectMessageColumn; break; - case MSG_SortBySender: pane = kSenderMessageColumn; break; - case MSG_SortByUnread: pane = kMarkedReadMessageColumn;break; - case MSG_SortByPriority: pane = kPriorityMessageColumn; break; - case MSG_SortBySize: pane = kSizeMessageColumn; break; - case MSG_SortByStatus: pane = kStatusMessageColumn; break; - case MSG_SortByFlagged: pane = kFlagMessageColumn; break; - case MSG_SortByMessageNumber: pane = kHiddenOrderReceivedColumn; break; - default: - case MSG_SortByThread: pane = kThreadMessageColumn; break; - } - NoteSortByThreadColumn(cmd == MSG_SortByThread); - UInt16 col = mTableHeader->ColumnFromID( pane ); - ::MSG_CommandStatus( - inPane, MSG_SortBackward, nil, 0, &selectable, &checkedState, - &display_string, &plural); - Boolean backwards = checkedState == MSG_Checked; - mTableHeader->SetWithoutSort( col, backwards, true ); - // Make sure the sort submenus on the menu bar are showing the correct state. - UpdateSortMenuCommands(); -} // CThreadView::SyncSortToBackend() - -//---------------------------------------------------------------------------------------- -void CThreadView::PaneChanged( - MSG_Pane* inPane, - MSG_PANE_CHANGED_NOTIFY_CODE inNotifyCode, - int32 value) -//---------------------------------------------------------------------------------------- -{ - switch (inNotifyCode) - { - case MSG_PaneNotifyFolderLoaded: - if (value > 0) - { - LWindow* win = LWindow::FetchWindowObject(GetMacPort()); - if (win) - win->Show(); - SetFolder(CMessageFolder((MSG_FolderInfo*)value)); - CMessage::InvalidateCache(); - SetRowCount(); - Refresh(); - } - // This is the first opportunity to do stuff that needs the folder etc. - // Update history entry and load an empty message into the message view. - // Calling SelectionChanged will do these things. - - SelectionChanged(); - - EnableStopButton(false); - if (mMotionPendingCommand != (MSG_MotionType)-1) - { - ObeyMotionCommand( mMotionPendingCommand ); - mMotionPendingCommand = (MSG_MotionType)-1; - } -#ifdef PREFERENCE_IMPLEMENTED - if (!RestoreSelectedMessage()) - ScrollToGoodPlace(); -#else - RestoreSelectedMessage(); // select the last selected message AND - mScrollToShowNew = true; - //ScrollToGoodPlace(); // scroll to show anything new. -#endif - DontExpectNewMail(); - // break; NO! Fall through, because we need to update the rowcount and sort order. - case MSG_PaneNotifyFolderInfoChanged: - if (mXPFolder == (MSG_FolderInfo*)value) - { - SyncSortToBackend(); - CMessage::InvalidateCache(); - } - mXPFolder.FolderInfoChanged(); - break; - case MSG_PaneProgressDone: // comes from progress window - if ((MessageT)value == msg_NSCAllConnectionsComplete) - { - if (GotNewMail()) // ie in THIS folder in THIS operation - { - CMessage::InvalidateCache(); - SetRowCount(); - Refresh(); - ScrollToGoodPlace(); - } - if (CMailProgressWindow::GettingMail()) - DontExpectNewMail(); - } - break; - case MSG_PaneNotifyFolderDeleted: - if ((MSG_FolderInfo*)value == mXPFolder.GetFolderInfo()) - { - RemoveAllRows( false ); - ::MSG_LoadFolder(GetMessagePane(), nil); - mXPFolder.SetFolderInfo(nil); // prevent crashes - } - break; - default: - Inherited::PaneChanged(inPane, inNotifyCode, value); - } -} // CThreadView::PaneChanged - -//---------------------------------------------------------------------------------------- -void CThreadView::ResizeFrameBy( - Int16 inWidthDelta, - Int16 inHeightDelta, - Boolean inRefresh) -//---------------------------------------------------------------------------------------- -{ - Inherited::ResizeFrameBy(inWidthDelta, inHeightDelta, inRefresh); - ScrollSelectionIntoFrame(); -} // CThreadView::ResizeFrameBy - -//---------------------------------------------------------------------------------------- -void CThreadView::FindSortCommandStatus(CommandT inCommand, Int16& outMark) -//---------------------------------------------------------------------------------------- -{ - PaneIDT paneID = GetSortedColumn(); - outMark = 0; - switch (inCommand) - { - case cmd_SortByDate: - if (paneID == kDateMessageColumn) - outMark = checkMark; - break; - case cmd_SortBySubject: - if (paneID == kSubjectMessageColumn) - outMark = checkMark; - break; - case cmd_SortBySender: - if (paneID == kSenderMessageColumn || paneID == kAddresseeMessageColumn) - outMark = checkMark; - break; - case cmd_SortByThread: - if (paneID == kThreadMessageColumn) - outMark = checkMark; - break; - case cmd_SortByPriority: - if (paneID == kPriorityMessageColumn) - outMark = checkMark; - break; - case cmd_SortBySize: - if (paneID == kSizeMessageColumn) - outMark = checkMark; - break; - case cmd_SortByReadness: - if (paneID == kMarkedReadMessageColumn) - outMark = checkMark; - break; - case cmd_SortByStatus: - if (paneID == kStatusMessageColumn) - outMark = checkMark; - break; - case cmd_SortByFlagged: - if (paneID == kFlagMessageColumn) - outMark = checkMark; - break; - case cmd_SortByOrderReceived: - if (paneID == kHiddenOrderReceivedColumn) - outMark = checkMark; - break; - case cmd_SortAscending: - case cmd_SortDescending: - outMark = - ((inCommand == cmd_SortDescending) == IsSortedBackwards()) ? - checkMark : 0; - break; - } -} // CThreadView::FindSortCommandStatus - -// ------------------------- -void CThreadView::UpdateSortMenuCommands() const -//--------------------------- -{ - list commandsToUpdate; - commandsToUpdate.push_front(cmd_SortByDate); - commandsToUpdate.push_front(cmd_SortBySubject); - commandsToUpdate.push_front(cmd_SortBySender); - commandsToUpdate.push_front(cmd_SortByThread); - commandsToUpdate.push_front(cmd_SortByPriority); - commandsToUpdate.push_front(cmd_SortBySize); - commandsToUpdate.push_front(cmd_SortByReadness); - commandsToUpdate.push_front(cmd_SortByStatus); - commandsToUpdate.push_front(cmd_SortByFlagged); - commandsToUpdate.push_front(cmd_SortByOrderReceived); - commandsToUpdate.push_front(cmd_SortAscending); - commandsToUpdate.push_front(cmd_SortDescending); - CTargetedUpdateMenuRegistry::SetCommands(commandsToUpdate); - CTargetedUpdateMenuRegistry::UpdateMenus(); -} // CThreadView::UpdateSortMenuCommands - -//---------------------------------------------------------------------------------------- -Boolean CThreadView::ObeySortCommand(CommandT inCommand) -//---------------------------------------------------------------------------------------- -{ - PaneIDT oldColumnID = GetSortedColumn(); - Boolean oldReverse = IsSortedBackwards(); - PaneIDT newColumnID; - Boolean newReverse = oldReverse; - switch (inCommand) - { - case cmd_SortByDate: - newColumnID = kDateMessageColumn; - break; - case cmd_SortBySubject: - newColumnID = kSubjectMessageColumn; - break; - case cmd_SortBySender: - newColumnID = kSenderMessageColumn; - break; - case cmd_SortByThread: - newColumnID = kThreadMessageColumn; - break; - case cmd_SortByPriority: - newColumnID = kPriorityMessageColumn; - break; - case cmd_SortBySize: - newColumnID = kSizeMessageColumn; - break; - case cmd_SortByReadness: - newColumnID = kMarkedReadMessageColumn; - break; - case cmd_SortByStatus: - newColumnID = kStatusMessageColumn; - break; - case cmd_SortByFlagged: - newColumnID = kFlagMessageColumn; - break; - case cmd_SortByOrderReceived: - newColumnID = kHiddenOrderReceivedColumn; - break; - case cmd_SortAscending: - case cmd_SortDescending: - newColumnID = GetSortedColumn(); - newReverse = (cmd_SortDescending == inCommand); - break; - default: - return false; - } - if (oldColumnID != newColumnID || oldReverse != newReverse) - { - mTableHeader->SetSortedColumn(mTableHeader->ColumnFromID(newColumnID), newReverse, true); - } - return true; -} // CThreadView::ObeySortCommand - -//---------------------------------------------------------------------------------------- -void CThreadView::FindCommandStatus( - CommandT inCommand, - Boolean &outEnabled, - Boolean &outUsesMark, - Char16 &outMark, - Str255 outName) -//---------------------------------------------------------------------------------------- -{ - outEnabled =false; // This is probably unnecessary, I think PP does it before calling. - if (::StillDown()) - { - // Assume this is a call from the context menu attachment. - Point whereLocal; - ::GetMouse(&whereLocal); - SPoint32 imagePoint; - LocalToImagePoint(whereLocal, imagePoint); - STableCell hitCell; - if (GetCellHitBy(imagePoint, hitCell)) - { - PaneIDT cellType = GetCellDataType(hitCell); - if (cellType == kPriorityMessageColumn) - return; // disable all commands, because we do it ourselves. - // Fix me: there's no reason why the priority popup can't be done - // using the context menu mechanism now. - } - } - if (inCommand == cmd_Stop && mStillLoading) - { - outEnabled = true; // stop button on, nothing else. - return; - // ... otherwise, fall through and pass it up to the window - } - // Note: for cmd_Stop, the window may also be able to handle the command, if - // a message pane exists. - CMailSelection selection; - GetSelection(selection); - switch (inCommand) - { - // Single-selection items - case cmd_SelectThread: - outEnabled = selection.selectionSize == 1; - return; - // Items always available - case cmd_SubscribeNewsgroups: - outEnabled = true; - return; - case cmd_AddToBookmarks: - outEnabled = (mXPFolder.GetFolderFlags() & MSG_FOLDER_FLAG_IMAPBOX) == 0; - return; - case cmd_SelectMarkedMessages: - case cmd_MarkReadByDate: - case cmd_NewFolder: - outEnabled = true; - outUsesMark = false; - return; - case cmd_GetMoreMessages: - CStr255 cmdStr; - CStr255 numStr; - ::GetIndString(cmdStr, kMailNewsMenuStrings, kNextChunkMessagesStrID); - ::NumToString(CPrefs::GetLong(CPrefs::NewsArticlesMax), numStr); - cmdStr += numStr; - memcpy(outName, (StringPtr)cmdStr, cmdStr.Length() + 1); - break; - } - // Now check for message library commands. Remember (###), some of these are - // handled by CMessageView(), and that might be our super commander, so - // return here only if msglib enables the item for the thread pane. - // Also don't want the message pane to only deal with cases where 1 message is selected - if (FindMessageLibraryCommandStatus(inCommand, outEnabled, outUsesMark, outMark, outName) - && ( outEnabled || selection.selectionSize != 1) ) - return; - MSG_MotionType cmd = UMessageLibrary::GetMotionType(inCommand); - if (UMessageLibrary::IsValidMotion(cmd)) - { - XP_Bool selectable; - outEnabled = ( - GetMessagePane() - && MSG_NavigateStatus( - GetMessagePane(), - cmd, - selection.GetSelectionList() ? *selection.GetSelectionList() : MSG_VIEWINDEXNONE, - &selectable, - NULL) == 0 - && selectable - ); - outUsesMark = false; - if (outEnabled) // ONLY in this case. See the previous comment (###). - return; - } - if ( (inCommand == cmd_MoveMailMessages) || (inCommand == cmd_CopyMailMessages) || - CMailFolderSubmenu::IsMailFolderCommand(&inCommand) ) { - // Mail folder commands - outEnabled = (GetSelectedRowCount() > 0); - return; - } - // Default for if and switch: fall through into second switch - switch (inCommand) - { - case cmd_GetInfo: - outEnabled = false; // FIXME: implement it. - break; - case cmd_SortByDate: - case cmd_SortBySubject: - case cmd_SortBySender: - case cmd_SortByThread: - case cmd_SortByPriority: - case cmd_SortBySize: -// case cmd_SortByTotal: - case cmd_SortByReadness: - case cmd_SortByStatus: - case cmd_SortByFlagged: - case cmd_SortByOrderReceived: - case cmd_SortAscending: - case cmd_SortDescending: - if (!mStillLoading) - { - outUsesMark = true; - outEnabled = true; - FindSortCommandStatus(inCommand, outMark); - } - break; - default: - if (inCommand >= ENCODING_BASE && inCommand < ENCODING_CEILING) - { - if (mContext) - { - outUsesMark = true; - outEnabled = true; - - int16 csid = CPrefs::CmdNumToDocCsid( inCommand ); - outMark = (csid == mContext->GetDefaultCSID()) ? 0x12 : ' '; - } - } - else - { - // if (inCommand == cmd_OpenSelection) - // outEnabled = false; - // else - Inherited::FindCommandStatus(inCommand, outEnabled, outUsesMark, outMark, outName); - } - } -} // CThreadView::FindCommandStatus - -//---------------------------------------------------------------------------------------- -void CThreadView::SelectAfterDelete(TableIndexT row) -// Called from ObeyCommand after command completion. -// In "expanded mode", the user probably wants a new message to -// be loaded into the message pane after a deletion. -// So detect the case when a message was showing and the message has -// been moved from the folder. We want to display a new message. -//---------------------------------------------------------------------------------------- -{ - SetUpdateCommandStatus(true); // Always do this. - if (row > 0) - SelectRow(row > mRows ? mRows : row); -} // CThreadView::SelectAfterDelete - -//---------------------------------------------------------------------------------------- -Boolean CThreadView::ObeyMotionCommand(MSG_MotionType cmd) -//---------------------------------------------------------------------------------------- -{ - if (!GetMessagePane()) return false; - Assert_(UMessageLibrary::IsValidMotion(cmd)); - try - { - CMailSelection selection; - GetSelection(selection); - MSG_ViewIndex resultIndex; - MessageKey resultKey = MSG_MESSAGEKEYNONE; - MSG_FolderInfo* finfo; - if (MSG_ViewNavigate( - GetMessagePane(), - cmd, - selection.GetSelectionList() ? *selection.GetSelectionList() : MSG_VIEWINDEXNONE, - &resultKey, - &resultIndex, - NULL, - &finfo) == 0) - { - if (resultKey != MSG_MESSAGEKEYNONE) - { - SetNotifyOnSelectionChange(false); - UnselectAllCells(); - SetNotifyOnSelectionChange(true); - if (finfo && finfo != GetOwningFolder()) - RelocateViewToFolder(finfo); - SelectMessageWhenReady(resultKey); - } - else if (finfo) - { - switch( cmd ) - { - case MSG_NextFolder: - case MSG_NextMessage: - mMotionPendingCommand = MSG_FirstMessage; - break; - case MSG_NextUnreadMessage: - case MSG_NextUnreadThread: - case MSG_NextUnreadGroup: - case MSG_LaterMessage: - case (MSG_MotionType)MSG_ToggleThreadKilled: - mMotionPendingCommand = MSG_NextUnreadMessage; - break; - default: - break; - } - RelocateViewToFolder( finfo ); - } - return true; - } - mUndoCommand = cmd_Undo; - } - catch (...) - { - SysBeep(1); - } - return false; -} // CThreadView::ObeyMotionCommand - -//---------------------------------------------------------------------------------------- -void CThreadView::SelectionChanged() -//---------------------------------------------------------------------------------------- -{ - Inherited::SelectionChanged(); -} // CThreadView::SelectionChanged - -//---------------------------------------------------------------------------------------- -void CThreadView::SelectMessageWhenReady(MessageKey inKey) -//---------------------------------------------------------------------------------------- -{ - if (mStillLoading || (!GetMessagePane())) - CDeferredTaskManager::Post1(new CDeferredSelectKeyTask(this, inKey), this); - else - SelectMessage(inKey); -} // CThreadView::SelectMessageWhenReady - -//---------------------------------------------------------------------------------------- -void CThreadView::SelectMessage(MessageKey inKey) -//---------------------------------------------------------------------------------------- -{ - Assert_(GetMessagePane()); - if (GetMessagePane()) - { - MSG_ViewIndex index = ::MSG_GetMessageIndexForKey(GetMessagePane(), inKey, true); - if (index != MSG_VIEWINDEXNONE) - SelectRow(index + 1); - } -} // CThreadView::SelectMessage - -//---------------------------------------------------------------------------------------- -void CThreadView::UpdateHistoryEntry() -//---------------------------------------------------------------------------------------- -{ - TableIndexT rowCount = GetSelectedRowCount(); - MSG_Pane* pane = GetMessagePane(); - if (!pane) - return; // e.g., during window creation - URL_Struct* url = nil; - char entryName[64]; - entryName[0] = '\0'; - if (rowCount == 1) - { -#if 0 // Auto-scroll should not be done here (+ it was redundant) - if (!CApplicationEventAttachment::CurrentEventHasModifiers(cmdKey) && - !CApplicationEventAttachment::CurrentEventHasModifiers(shiftKey)) - { - STableCell cell = GetFirstSelectedCell(); - if (IsValidCell(cell)) - ScrollCellIntoFrame(cell); - } -#endif - CMailSelection selection; - GetSelection( selection ); - CMessage message(*selection.GetSelectionList() + 1, selection.xpPane); - MessageKey id = message.GetMessageKey(); - url = ::MSG_ConstructUrlForMessage(pane, id); - message.GetSubject(entryName, sizeof(entryName)); - } - else - { - // zero selection or multiple selection - use folder for history entry - url = CreateURLForProxyDrag(entryName); - } - if (url && *entryName) - { - LO_DiscardDocument(*mContext); - History_entry* theNewEntry = ::SHIST_CreateHistoryEntry( - url, - entryName); - ::SHIST_AddDocument(*mContext, theNewEntry); - } - XP_FREEIF(url); -} // CThreadView::UpdateHistoryEntry - -//---------------------------------------------------------------------------------------- -Boolean CThreadView::ObeyMarkReadByDateCommand() -//---------------------------------------------------------------------------------------- -{ - StDialogHandler handler(10525, NULL); - LWindow* dlog = handler.GetDialog(); - if (! dlog) - return true; - - CSearchDateField* dateField = dynamic_cast - (dlog->FindPaneByID(CSearchDateField::class_ID)); - if (dateField) - { - dateField->SetToToday(); - MessageT message; - do - { - message = handler.DoDialog(); - } while (message != msg_OK && message != msg_Cancel); - if (message == msg_OK) - { - Int16 outYear; UInt8 outMonth, outDay; - dateField->GetDate(&outYear, &outMonth, &outDay); - - tm time; - time.tm_sec = 1; - time.tm_min = 1; - time.tm_hour = 1; - time.tm_mday = outDay; - time.tm_mon = outMonth - 1; - time.tm_year = outYear - 1900; - time.tm_wday = -1; - time.tm_yday = -1; - time.tm_isdst = -1; - - time_t endDate = ::mktime(&time); - MSG_MarkReadByDate(GetMessagePane(), 0, endDate); - } - } - return true; -} // CThreadView::ObeyMarkReadByDateCommand - -//---------------------------------------------------------------------------------------- -void CThreadView::DoSelectThread(TableIndexT inSelectedRow) -// Select all messages belonging to the same thread as this row. -//---------------------------------------------------------------------------------------- -{ - CMessage message(inSelectedRow, GetMessagePane()); - MSG_ViewIndex threadIndex = MSG_ThreadIndexOfMsg(GetMessagePane(), message.GetMessageKey()); - if (threadIndex == MSG_VIEWINDEXNONE) - return; - TableIndexT first = 1 + threadIndex; - STableCell firstCell(first, 1); - TableIndexT last = first + CountExtraRowsControlledByCell(firstCell); - Assert_(first < last || first == inSelectedRow); - if (LTableRowSelector * selector = dynamic_cast(mTableSelector)) - { - // Powerplant's ClickSelect has already been called, so use the sense of the - // clicked cell and turn all other cells in the thread on or off to match. - STableCell clickedCell(inSelectedRow, 1); - Boolean doSelect = selector->CellIsSelected(clickedCell); - SetNotifyOnSelectionChange(false); - try - { - if (!CApplicationEventAttachment::CurrentEventHasModifiers(shiftKey|cmdKey)) - UnselectAllCells(); - for (TableIndexT i = first; i <= last; i++) - selector->DoSelect(i, doSelect, true, false); - } - catch (...) {} - SetNotifyOnSelectionChange(true); - SelectionChanged(); - } -} // CThreadView::DoSelectThread - -//---------------------------------------------------------------------------------------- -void CThreadView::DoSelectFlaggedMessages() -//---------------------------------------------------------------------------------------- -{ - SetNotifyOnSelectionChange(false); - try - { - if (!CApplicationEventAttachment::CurrentEventHasModifiers(shiftKey|cmdKey)) - UnselectAllCells(); - for (TableIndexT i = 1; i <= mRows; i++) - { - CMessage message(i, GetMessagePane()); - if (message.IsFlagged()) - SelectCell(STableCell(i, 1)); - } - } - catch (...) {} - SetNotifyOnSelectionChange(true); - SelectionChanged(); -} // CThreadView::DoSelectFlaggedMessages - -//---------------------------------------------------------------------------------------- -Boolean CThreadView::ObeyCommand( - CommandT inCommand, - void *ioParam) -//---------------------------------------------------------------------------------------- -{ - if (!mContext) - return false; - - if (inCommand == cmd_UnselectAllCells) - { - UnselectAllCells(); - return true; - } - - if (inCommand != cmd_Stop && XP_IsContextBusy((MWContext*)(*mContext))) - return LCommander::GetTopCommander()->ObeyCommand(inCommand, ioParam); // global commands OK. - if (inCommand == msg_TabSelect) - return (GetOwningFolder() != nil); // Allow selection only if a folder is loaded. - - Boolean commandHandled = false; - CommandT originalCommand = mContext->GetCurrentCommand(); - CNSContext* originalContext = mContext; // in case we close the window & delete it! - mContext->SetCurrentCommand(inCommand); - if (inCommand == cmd_GetNewMail || inCommand == cmd_GetMoreMessages) - { - ExpectNewMail(); - - // getting new messages: slow down the status bar - // to reduce flickers and improve performance - CThreadWindow* threadWindow - = dynamic_cast(LWindow::FetchWindowObject(GetMacPort())); - if (threadWindow) - threadWindow->GetProgressListener()->SetLaziness( - CProgressListener::lazy_VeryButForThisCommandOnly); - } - // Don't let msgLib do the deletion since we want(?) to close open mail windows - if ( inCommand == cmd_Clear ) - { - DeleteSelection(); - return true; - } - if ( inCommand == cmd_NewFolder ) - { - UFolderDialogs::ConductNewFolderDialog(GetOwningFolder()); - return true; - } - - // If you're reading a news group, and you want to compose a new message, the new message - // is, by default, addressed to that news group... this test and reassignment are necessary - // to make this happen - if ( (inCommand == cmd_NewMailMessage) && (GetFolderFlags() & MSG_FOLDER_FLAG_NEWSGROUP) ) { - inCommand = cmd_PostNew; - } - - // For msglib commands, we have to be careful to check whether the command - // can be handled for THIS pane, because the message pane might have - // enabled the menu item. Failing to check again here leads to a nasty - // crash. - Boolean enabled; Boolean usesMark; Char16 mark; Str255 name; - if (FindMessageLibraryCommandStatus(inCommand, enabled, usesMark, mark, name) - && enabled) - { - commandHandled = ObeyMessageLibraryCommand(inCommand, ioParam); - if (inCommand == cmd_Undo || inCommand == cmd_Redo) - { - UnselectAllCells(); - mUndoTask = new CDeferredUndoTask(this); - CDeferredTaskManager::Post1(mUndoTask, this); - } - else if (mUndoTask) - CDeferredTaskManager::Remove(mUndoTask, this); - } - if (!commandHandled) - { - MSG_MotionType mcmd = UMessageLibrary::GetMotionType(inCommand); - if (UMessageLibrary::IsValidMotion(mcmd)) - commandHandled = ObeyMotionCommand(mcmd); - if (!commandHandled) - { - // Mail folder commands. We come here either from a button (broadcast) or - // from a menu command (synthetic). - const char* folderPath = nil; - if (inCommand == cmd_MoveMailMessages || inCommand == cmd_CopyMailMessages) - { - // Button case - if ( ioParam ) // The BE dereferences this ASAP - folderPath = ::MSG_GetFolderNameFromID((MSG_FolderInfo*)ioParam); - } - else if (!CMailFolderSubmenu::IsMailFolderCommand(&inCommand, &folderPath)) // menu case - { - folderPath = nil; // any other case. - } - if (folderPath && *folderPath) - { - FileMessagesToSelectedPopupFolder( - folderPath, - inCommand == cmd_MoveMailMessages); - commandHandled = true; - } - } - } - if (!commandHandled) switch(inCommand) - { - case cmd_SubscribeNewsgroups: - MSG_Host* selectedHost = MSG_GetHostForFolder(GetOwningFolder()); - CNewsSubscriber::DoSubscribeNewsGroup(selectedHost); - break; - case cmd_MarkReadByDate: - ObeyMarkReadByDateCommand(); - commandHandled = true; - break; -#if 0 - case cmd_RelocateViewToFolder: - // Don't handle this in the three-pane view. The folder pane has to change, too, - // so pass it up to CThreadWindow and let it delegate. - commandHandled = RelocateViewToFolder((MSG_FolderInfo*)ioParam); - break; -#endif // 0 - case cmd_SortByDate: - case cmd_SortBySubject: - case cmd_SortBySender: - case cmd_SortByThread: - case cmd_SortByPriority: - case cmd_SortBySize: - case cmd_SortByStatus: - case cmd_SortByFlagged: - case cmd_SortByOrderReceived: - case cmd_SortByReadness: - case cmd_SortAscending: - case cmd_SortDescending: - if (ObeySortCommand(inCommand)) - commandHandled = true; - break; - case cmd_SelectThread: - CMailSelection selection; - GetSelection( selection ); - TableIndexT selectedRow = *selection.GetSelectionList() + 1; - DoSelectThread(selectedRow); - break; - case cmd_SelectMarkedMessages: - DoSelectFlaggedMessages(); - break; - } // switch - if (!commandHandled && inCommand > ENCODING_BASE && inCommand < ENCODING_CEILING) - { - Int16 default_csid = CPrefs::CmdNumToDocCsid(inCommand); - SetDefaultCSID(default_csid); - LCommander::SetUpdateCommandStatus(true); // bug #80474 - commandHandled = true; - } - if (!commandHandled) - commandHandled = Inherited::ObeyCommand(inCommand, ioParam); - //----------------------------------- - // Cleanup - //----------------------------------- - // The following test against originalContext protects against the cases (quit, close) - // when the object has been deleted. The test against cmdHandled protects against - // re-entrant calls to ListenToMessage. - if (mContext == originalContext) - if (commandHandled) - mContext->SetCurrentCommand(cmd_Nothing); // watch out for re-entrant broadcast msgs. - else - { - // It wasn't a command, so restore damage done if we're processing a broadcast. - mContext->SetCurrentCommand(originalCommand); - } - return commandHandled; -} // CThreadView::ObeyCommand - -//---------------------------------------------------------------------------------------- -void CThreadView::ResetTextTraits() -//---------------------------------------------------------------------------------------- -{ - Int16 wincsid = mContext->GetWinCSID(); - ResIDT newTextTraitsID; - // ## Begin Hacky Code copy from Akbar (v3.0) mnews.cp - // This will make everyone happy. - // If the window is MAC_ROMAN, it will use the default mnews font. - // Otherwise, get it from the Font preference - if ( wincsid == INTL_CharSetNameToID(INTL_ResourceCharSet()) ) - newTextTraitsID = 130; - else - newTextTraitsID = CPrefs::GetTextFieldTextResIDs(wincsid); - // ## End of Hacky Code copy from Akbar (v3.0) mnews.cp - - if (newTextTraitsID != mTextTraitsID ) - { - SetTextTraits(newTextTraitsID); - Refresh(); - } -} // CThreadView::ResetTextTraits - -//---------------------------------------------------------------------------------------- -Int16 CThreadView::DefaultCSIDForNewWindow(void) -//---------------------------------------------------------------------------------------- -{ - if (mContext) - return mContext->GetDefaultCSID(); - return 0; -} // CThreadView::DefaultCSIDForNewWindow - -//---------------------------------------------------------------------------------------- -void CThreadView::SetDefaultCSID(Int16 default_csid) -//---------------------------------------------------------------------------------------- -{ - // Set the csid in the context - mContext->SetDefaultCSID(default_csid); - mContext->SetWinCSID(INTL_DocToWinCharSetID(default_csid)); - - // Set the csid for the folder - MSG_SetFolderCSID(GetOwningFolder(), default_csid); - - // We need to set the csid for the view with the window - // Ask the CThreadWindow to do it. - CThreadWindow* threadWindow - = dynamic_cast(LWindow::FetchWindowObject(GetMacPort())); - if (threadWindow) - threadWindow->SetDefaultCSID(default_csid); - - // We need to change the text info and redraw all the header - ResetTextTraits(); - - // If we have Message Window appear, we need to set the csid for it. - try { - // Find the all the MessageWindow which view the some folder - // and set the default csid for its view. - - CWindowIterator iter(WindowType_Message); - CMessageWindow* window; - for (iter.Next(window); window; iter.Next(window)) - { - window = dynamic_cast(window); - if (window) - { - CMessageView* messageView = window->GetMessageView(); - if (GetOwningFolder() == messageView->GetFolderInfo()) - { - messageView->SetDefaultCSID(default_csid); - } - } - } - } - catch( ... ) - { - } - -} // CThreadView::SetDefaultCSID - -// ¥¥ÊFix me, this should go into some utility classes -//---------------------------------------------------------------------------------------- -void CThreadView::DrawUTF8TextString( - const char* inText, - const FontInfo* inFontInfo, - SInt16 inMargin, - const Rect& inBounds, - SInt16 inJustification, - Boolean inDoTruncate, - TruncCode inTruncWhere) -//---------------------------------------------------------------------------------------- -{ - Rect r = inBounds; - - r.left += inMargin; - r.right -= inMargin; - - PlaceUTF8TextInRect(inText, - strlen(inText), - r, - inJustification, - teCenter, - inFontInfo, - inDoTruncate, - inTruncWhere ); -} - -// ¥¥ÊFix me, this should go into some utility classes -//---------------------------------------------------------------------------------------- -void CThreadView::PlaceUTF8TextInRect( - const char* inText, - Uint32 inTextLength, - const Rect &inRect, - Int16 inHorizJustType, - Int16 inVertJustType, - const FontInfo* /*inFontInfo*/, - Boolean inDoTruncate, - TruncCode /*inTruncWhere*/) -//---------------------------------------------------------------------------------------- -{ - FontInfo utf8FontInfo; - UFontSwitcher *fs; - UMultiFontTextHandler *th; - th = UUTF8TextHandler::Instance(); - fs = UPropFontSwitcher::Instance(); - th->GetFontInfo(fs, &utf8FontInfo); - - const char* text = inText; - short length = inTextLength; - if (inDoTruncate) - { - // ¥¥ Fix ME: Don't know how to do text truncation for UTF8 now. - } - Point thePoint = UGraphicGizmos::CalcStringPosition( - inRect, - th->TextWidth(fs, (char*)text, length), - inHorizJustType, - inVertJustType, - &utf8FontInfo); - ::MoveTo(thePoint.h, thePoint.v); - th->DrawText(fs, (char*)text ,length); -} // CThreadView::PlaceUTF8TextInRect - -//---------------------------------------------------------------------------------------- -void CThreadView::ListenToMessage( - MessageT inCommand, - void *ioParam) -//---------------------------------------------------------------------------------------- -{ - // Check ObeyCommand first, for a button message, but ONLY IF WE'RE ON DUTY. - if (!IsOnDuty() || !ObeyCommand((CommandT)inCommand, ioParam)) // button message? - { - Inherited::ListenToMessage(inCommand, ioParam); - switch (inCommand) - { - case msg_NSCAllConnectionsComplete: - { -// if (mPendingCommand) -// { -// CommandT cmd = mPendingCommand; -// mPendingCommand = 0; -// ObeyCommand(cmd, nil); -// -// } -// else -#ifdef REMOVED_870427 - if (GotNewMail()) - { - ScrollToGoodPlace(); - DontExpectNewMail(); - } - break; -#endif - if (GetContext()->GetCurrentCommand() == cmd_GetNewMail) - DontExpectNewMail(); - } - } // switch - } -} // CThreadView::ListenToMessage - -//---------------------------------------------------------------------------------------- -void CThreadView::ActivateSelf() -//---------------------------------------------------------------------------------------- -{ - Inherited::ActivateSelf(); -} // CThreadView::ActivateSelf - -//---------------------------------------------------------------------------------------- -void CThreadView::ObeyCommandWhenReady(CommandT inCommand) -//---------------------------------------------------------------------------------------- -{ - if (inCommand != cmd_Nothing) - CDeferredTaskManager::Post(new CDeferredThreadViewCommand(this, inCommand, nil), this); -} - -//---------------------------------------------------------------------------------------- -URL_Struct* CThreadView::CreateURLForProxyDrag(char* outTitle) -//---------------------------------------------------------------------------------------- -{ - MSG_Pane* pane = GetMessagePane(); - if (!pane) - return nil; - MSG_FolderInfo* folderInfo = GetOwningFolder(); - if (!folderInfo) - return nil; - CMessageFolder folder(folderInfo); - if (outTitle) - { - strcpy(outTitle, folder.GetName()); - NET_UnEscape(outTitle); - } - return ::MSG_ConstructUrlForFolder(pane, folderInfo); -} // CThreadView::CreateURLForProxyDrag - -#if defined(QAP_BUILD) -//---------------------------------------------------------------------------------------- -void CThreadView::GetQapRowText( - TableIndexT inRow, - char* outText, - UInt16 inMaxBufferLength) const -// Calculate the text and (if ioRect is not passed in as null) a rectangle that fits it. -// Return result indicates if any of the text is visible in the cell -//---------------------------------------------------------------------------------------- -{ - if (!outText || inMaxBufferLength == 0) - return; - - cstring rowText(""); - short colCount = mTableHeader->CountVisibleColumns(); - CMessage message(inRow, GetMessagePane()); - - CMailNewsWindow * myWindow = dynamic_cast(LWindow::FetchWindowObject(GetMacPort())); - if (!myWindow) return; - - for (short col = 1; col <= colCount; col ++) - { - STableCell aCell(inRow, col); - LTableHeader::SColumnData * colData = mTableHeader->GetColumnData(col); - if (!colData) break; - LPane * colPane = myWindow->FindPaneByID(colData->paneID); - if (!colPane) break; - - // get column name - CStr255 descriptor; - switch (GetCellDataType(aCell)) - { - case kThreadMessageColumn: descriptor = "Thread"; break; - case kMarkedReadMessageColumn: descriptor = "MarkRead"; break; - case kFlagMessageColumn: descriptor = "Flag"; break; - default: - colPane->GetDescriptor(descriptor); - break; - } - rowText += descriptor; - rowText += "=\042"; - - // add cell text - switch (PaneIDT dataType = GetCellDataType(aCell)) - { - case kThreadMessageColumn: - if (message.IsThread()) - { - if (message.IsOpenThread()) - rowText += "-"; - else - rowText += "+"; - } - else - rowText += " "; - break; - - // note: no intl conversions (yet?) for subject, sender and addressee - case kMarkedReadMessageColumn: rowText += (message.HasBeenRead() ? "+" : " "); break; - case kFlagMessageColumn: rowText += (message.IsFlagged() ? "+" : " "); break; - case kSubjectMessageColumn: rowText += message.GetSubject(); break; - case kSenderMessageColumn: rowText += message.GetSender(); break; - case kDateMessageColumn: rowText += message.GetDateString(); break; - case kPriorityMessageColumn: rowText += message.GetPriorityStr(); break; - case kSizeMessageColumn: rowText += message.GetSizeStr(); break; - case kStatusMessageColumn: rowText += message.GetStatusStr(); break; - case kAddresseeMessageColumn: rowText += message.GetAddresseeString(); break; - - case kTotalMessageColumn: - case kUnreadMessageColumn: - if (GetSortedColumn() == kThreadMessageColumn && message.IsThread()) - { - int theNum = (dataType == kTotalMessageColumn - ? message.GetNumChildren() - : message.GetNumNewChildren()); - char tempStr[32]; - sprintf(tempStr, "%d", theNum); - rowText += tempStr; - } - break; - } - if (col < colCount) - rowText += "\042 | "; - else - rowText += "\042\r"; - } - strncpy(outText, (char*)rowText, inMaxBufferLength); - outText[inMaxBufferLength - 1] = '\0'; -} // CThreadView::GetQapRowText -#endif //QAP_BUILD diff --git a/cmd/macfe/central/CBrowserContext.cp b/cmd/macfe/central/CBrowserContext.cp index c54b18b9439..f68e1c4825d 100644 --- a/cmd/macfe/central/CBrowserContext.cp +++ b/cmd/macfe/central/CBrowserContext.cp @@ -1142,6 +1142,9 @@ void CBrowserContext::LayoutNewDocument( theCurrentView->LayoutNewDocument(inURL, inWidth, inHeight, inMarginWidth, inMarginHeight); CStr31 theTitle = CFileMgr::FileNameFromURL(inURL->address); + // i18n problem- we may need to convert theTitle to UTF8 before call SHIST_CreateHistryEntry + // However, currently theTitle is only URL encoded file name which have no 8bit data. Should double check again later. + History_entry* theNewEntry = SHIST_CreateHistoryEntry(inURL, theTitle); SHIST_AddDocument(*this, theNewEntry); diff --git a/lib/libmocha/lm_hist.c b/lib/libmocha/lm_hist.c index 66843a73702..85d6b6f9978 100644 --- a/lib/libmocha/lm_hist.c +++ b/lib/libmocha/lm_hist.c @@ -188,6 +188,8 @@ hist_go(JSContext *cx, JSObject *obj, he = SHIST_GetObjectNum(&context->hist, index); } else if (JSVAL_IS_STRING(argv[0])) { + /* i18n problem */ + /* I believe this part is broken for I18N. Particular after we change the he->title to UTF8 */ char * argv_str = JS_GetStringBytes(JSVAL_TO_STRING(argv[0])); histlist = SHIST_GetList(context); if (histlist) @@ -260,6 +262,9 @@ hist_toString(JSContext *cx, JSObject *obj, ""); while ((he = XP_ListNextObject(histlist)) != 0) { StrAllocCat(bytes, "" "
"); + /* i18n problem */ + /* I believe this part is broken for I18N. Particular after we change the he->title to UTF8 */ + /* force the output HTML to display as in UTF8 will fix it. */ StrAllocCat(bytes, he->title); StrAllocCat(bytes, "