You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
1038 lines
30 KiB
1038 lines
30 KiB
/////////////////////////////////////////////////////////////////////////////
|
|
// Copyright (C) 1993-1996 Microsoft Corporation. All Rights Reserved.
|
|
//
|
|
// MODULE: Order.cpp
|
|
//
|
|
// PURPOSE: Implements the order articles dialog. Allows the user to
|
|
// sequence multipart articles for decoding.
|
|
//
|
|
|
|
#include "pch.hxx"
|
|
#include "storutil.h"
|
|
#include "mimeole.h"
|
|
#include "mimeutil.h"
|
|
#include "resource.h"
|
|
#include "shlwapip.h"
|
|
#include "thormsgs.h"
|
|
#include "order.h"
|
|
#include "error.h"
|
|
#include "demand.h"
|
|
#include "imsgsite.h"
|
|
#include "note.h"
|
|
#include "xputil.h"
|
|
|
|
// NOTE - The drag list control requires us to register a message and use that
|
|
// for notifications sent from the list to the dialog. This message
|
|
// is defined only for this dialog. -- SteveSer.
|
|
|
|
static UINT g_mDragList = 0;
|
|
|
|
#define CND_GETNEXTARTICLE (WM_USER + 101)
|
|
#define CND_OPENNOTE (WM_USER + 102)
|
|
#define CND_MESSAGEAVAIL (WM_USER + 103)
|
|
|
|
CCombineAndDecode::CCombineAndDecode()
|
|
{
|
|
m_cRef = 1;
|
|
|
|
m_hwndParent = NULL;
|
|
|
|
m_pTable = NULL;
|
|
m_rgRows = NULL;
|
|
m_cRows = 0;
|
|
|
|
m_pszBuffer = NULL;
|
|
m_iItemToMove = -1;
|
|
|
|
m_cLinesTotal = 0;
|
|
m_cCurrentLine = 0;
|
|
m_cPrevLine = 0;
|
|
m_dwCurrentArt = 0;
|
|
m_pMsgParts = NULL;
|
|
m_pCancel = 0;
|
|
m_hTimeout = 0;
|
|
m_hwndDlg = 0;
|
|
}
|
|
|
|
|
|
CCombineAndDecode::~CCombineAndDecode()
|
|
{
|
|
SafeRelease(m_pTable);
|
|
SafeRelease(m_pMsgParts);
|
|
SafeRelease(m_pCancel);
|
|
CallbackCloseTimeout(&m_hTimeout);
|
|
}
|
|
|
|
|
|
HRESULT STDMETHODCALLTYPE CCombineAndDecode::QueryInterface(REFIID riid, void **ppvObj)
|
|
{
|
|
if (IsEqualIID(riid, IID_IUnknown))
|
|
*ppvObj = (void*) (IUnknown *)(IStoreCallback *)this;
|
|
else if (IsEqualIID(riid, IID_IStoreCallback))
|
|
*ppvObj = (void*) (IStoreCallback *) this;
|
|
else
|
|
{
|
|
*ppvObj = NULL;
|
|
return E_NOINTERFACE;
|
|
}
|
|
|
|
AddRef();
|
|
return S_OK;
|
|
}
|
|
|
|
ULONG STDMETHODCALLTYPE CCombineAndDecode::AddRef()
|
|
{
|
|
return ++m_cRef;
|
|
}
|
|
|
|
ULONG STDMETHODCALLTYPE CCombineAndDecode::Release()
|
|
{
|
|
if (--m_cRef == 0)
|
|
{
|
|
delete this;
|
|
return 0;
|
|
}
|
|
return m_cRef;
|
|
}
|
|
|
|
//
|
|
// FUNCTION: CCombineAndDecode::Start()
|
|
//
|
|
// PURPOSE:
|
|
//
|
|
// PARAMETERS:
|
|
// [in] hwndParent
|
|
// [in] pTable
|
|
// [in] rgRows
|
|
// [in] cRows
|
|
//
|
|
// RETURN VALUE:
|
|
// HRESULT
|
|
//
|
|
HRESULT CCombineAndDecode::Start(HWND hwndParent, IMessageTable *pTable,
|
|
ROWINDEX *rgRows, DWORD cRows, FOLDERID idFolder)
|
|
{
|
|
int nResult = -1;
|
|
|
|
TraceCall("CCombineAndDecode::Start");
|
|
|
|
// Verify we got everything we needed
|
|
if (!IsWindow(hwndParent) || !pTable || !rgRows || 0 == cRows)
|
|
return (E_INVALIDARG);
|
|
|
|
// Keep these for later
|
|
m_hwndParent = hwndParent;
|
|
m_pTable = pTable;
|
|
m_pTable->AddRef();
|
|
|
|
m_rgRows = rgRows;
|
|
m_cRows = cRows;
|
|
|
|
m_idFolder = idFolder;
|
|
// Create the order dialog and get to work
|
|
nResult = (int) DialogBoxParam(g_hLocRes, MAKEINTRESOURCE(iddOrderMessages),
|
|
m_hwndParent, OrderDlgProc, (LPARAM) this);
|
|
|
|
// If the user pressed OK, then we go ahead and decode
|
|
if (nResult == IDOK)
|
|
{
|
|
DialogBoxParam(g_hLocRes, MAKEINTRESOURCE(iddCombineAndDecode), m_hwndParent,
|
|
CombineDlgProc, (LPARAM) this);
|
|
}
|
|
|
|
return (S_OK);
|
|
}
|
|
|
|
|
|
//
|
|
// FUNCTION: CCombineAndDecode::OrderDlgProc()
|
|
//
|
|
// PURPOSE: Public callback function for the message ordering dialog proc
|
|
//
|
|
INT_PTR CALLBACK CCombineAndDecode::OrderDlgProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
|
|
{
|
|
CCombineAndDecode *pThis;
|
|
|
|
if (uMsg == WM_INITDIALOG)
|
|
{
|
|
SetWindowLongPtr(hwnd, DWLP_USER, lParam);
|
|
pThis = (CCombineAndDecode *) lParam;
|
|
}
|
|
else
|
|
pThis = (CCombineAndDecode *) GetWindowLongPtr(hwnd, DWLP_USER);
|
|
|
|
if (pThis)
|
|
return (pThis->_OrderDlgProc(hwnd, uMsg, wParam, lParam));
|
|
|
|
return (FALSE);
|
|
|
|
}
|
|
|
|
|
|
//
|
|
// FUNCTION: CCombineAndDecode::_OrderDlgProc()
|
|
//
|
|
// PURPOSE: Private callback function for the message ordering dialog proc
|
|
//
|
|
INT_PTR CALLBACK CCombineAndDecode::_OrderDlgProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
|
|
{
|
|
switch (uMsg)
|
|
{
|
|
case WM_INITDIALOG:
|
|
return (BOOL) HANDLE_WM_INITDIALOG(hwnd, wParam, lParam, _Order_OnInitDialog);
|
|
|
|
case WM_COMMAND:
|
|
HANDLE_WM_COMMAND(hwnd, wParam, lParam, _Order_OnCommand);
|
|
return (TRUE);
|
|
|
|
case WM_CLOSE:
|
|
HANDLE_WM_CLOSE(hwnd, wParam, lParam, _Order_OnClose);
|
|
return (TRUE);
|
|
|
|
default:
|
|
if (uMsg == g_mDragList)
|
|
return (_Order_OnDragList(hwnd, (int) wParam, (DRAGLISTINFO*) lParam));
|
|
}
|
|
|
|
return (FALSE);
|
|
}
|
|
|
|
|
|
//
|
|
// FUNCTION: CCombineAndDecode::_Order_OnInitDialog()
|
|
//
|
|
// PURPOSE: Initializes the order dialog by filling in the message headers.
|
|
//
|
|
BOOL CCombineAndDecode::_Order_OnInitDialog(HWND hwnd, HWND hwndFocus, LPARAM lParam)
|
|
{
|
|
HWND hwndList;
|
|
HDC hdc;
|
|
SIZE size;
|
|
int cx = 0;
|
|
HFONT hfontOld;
|
|
HFONT hfont;
|
|
int cxScrollBar;
|
|
LPMESSAGEINFO pInfo;
|
|
int iItem;
|
|
LPSTR pszSubject = NULL;
|
|
CHAR szNoSubject[CCHMAX_STRINGRES] = "";
|
|
|
|
CenterDialog(hwnd);
|
|
|
|
// Get some drawing information about the ListBox so we can set the scroll
|
|
// bar width correctly later.
|
|
hwndList = GetDlgItem(hwnd, IDC_MESSAGE_LIST);
|
|
hdc = GetDC(hwndList);
|
|
hfont = (HFONT) SendMessage(hwndList, WM_GETFONT, 0, 0L);
|
|
hfontOld = (HFONT) SelectObject(hdc, hfont);
|
|
cxScrollBar = GetSystemMetrics(SM_CXHTHUMB);
|
|
|
|
// Fill the listbox with the article subjects
|
|
for (DWORD i = 0; i < m_cRows; i++)
|
|
{
|
|
// Get the message header from the table
|
|
if (SUCCEEDED(m_pTable->GetRow(m_rgRows[i], &pInfo)))
|
|
{
|
|
if(pInfo->pszSubject)
|
|
pszSubject = pInfo->pszSubject;
|
|
else
|
|
{
|
|
LoadString(g_hLocRes, idsEmptySubjectRO, szNoSubject, sizeof(szNoSubject));
|
|
pszSubject = szNoSubject;
|
|
}
|
|
|
|
Assert(pszSubject);
|
|
|
|
// Figure out which string is widest before inserting
|
|
GetTextExtentPoint32(hdc, pszSubject, lstrlen(pszSubject), &size);
|
|
if (cx < size.cx)
|
|
cx = size.cx;
|
|
|
|
// Add the string
|
|
iItem = (int) SendMessage(hwndList, LB_ADDSTRING, 0, (LPARAM) pszSubject);
|
|
if (LB_ERR != iItem)
|
|
SendMessage(hwndList, LB_SETITEMDATA, iItem, (LPARAM) m_rgRows[i]);
|
|
|
|
// Free the memory
|
|
m_pTable->ReleaseRow(pInfo);
|
|
}
|
|
}
|
|
|
|
// Clean up the GDI objects
|
|
SelectObject(hdc, hfontOld);
|
|
ReleaseDC(hwndList, hdc);
|
|
|
|
// Make sure there are scroll bars if needed.
|
|
SendMessage(hwndList, LB_SETHORIZONTALEXTENT, cx + cxScrollBar, 0L);
|
|
|
|
// Make the list box a drag list box
|
|
if (MakeDragList(hwndList))
|
|
g_mDragList = RegisterWindowMessage(DRAGLISTMSGSTRING);
|
|
|
|
SendMessage(hwndList, LB_SETCURSEL, 0, 0);
|
|
|
|
return (FALSE);
|
|
}
|
|
|
|
|
|
//
|
|
// FUNCTION: CCombineAndDecode::_Order_OnCommand()
|
|
//
|
|
// PURPOSE: Handle the commands generated by the buttons on the dialog.
|
|
//
|
|
void CCombineAndDecode::_Order_OnCommand(HWND hwnd, int id, HWND hwndCtl,
|
|
UINT codeNotify)
|
|
{
|
|
HWND hwndList = GetDlgItem(hwnd, IDC_MESSAGE_LIST);
|
|
|
|
switch (id)
|
|
{
|
|
case IDOK:
|
|
{
|
|
// Get the info we need out of the ListBox
|
|
for (DWORD i = 0; i < m_cRows; i++)
|
|
{
|
|
m_rgRows[i] = (ROWINDEX) ListBox_GetItemData(hwndList, i);
|
|
}
|
|
|
|
EndDialog(hwnd, 1);
|
|
break;
|
|
}
|
|
|
|
case IDCANCEL:
|
|
EndDialog(hwnd, 0);
|
|
break;
|
|
|
|
case IDC_MOVE_UP:
|
|
case IDC_MOVE_DOWN:
|
|
{
|
|
LPTSTR pszBuffer;
|
|
DWORD cch;
|
|
UINT index;
|
|
LPARAM lpData;
|
|
|
|
// Get the currently selected item
|
|
index = (DWORD) SendMessage(hwndList, LB_GETCURSEL, 0, 0);
|
|
|
|
// If nothing is selected the listbox returns LB_ERR
|
|
if (index == LB_ERR)
|
|
return;
|
|
|
|
// Check the bounds
|
|
if ((id == IDC_MOVE_UP && index == 0) ||
|
|
(id == IDC_MOVE_DOWN && (int) index == (ListBox_GetCount(hwndList) - 1)))
|
|
return;
|
|
|
|
// Move the item in the listbox
|
|
cch = (DWORD) SendMessage(hwndList, LB_GETTEXTLEN, index, 0L);
|
|
if (!MemAlloc((LPVOID*) &pszBuffer, sizeof(TCHAR) * (cch + 1)))
|
|
return;
|
|
|
|
// Get the source string and data
|
|
SendMessage(hwndList, LB_GETTEXT, index, (LPARAM) pszBuffer);
|
|
lpData = SendMessage(hwndList, LB_GETITEMDATA, index, 0);
|
|
|
|
// Delete the source
|
|
SendMessage(hwndList, LB_DELETESTRING, index, 0L);
|
|
|
|
// Insert the new one
|
|
if (id == IDC_MOVE_UP)
|
|
index--;
|
|
else
|
|
index++;
|
|
|
|
SendMessage(hwndList, LB_INSERTSTRING, index, (LPARAM) pszBuffer);
|
|
SendMessage(hwndList, LB_SETITEMDATA, index, lpData);
|
|
SendMessage(hwndList, LB_SETCURSEL, index, 0L);
|
|
|
|
MemFree(pszBuffer);
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
//
|
|
// FUNCTION: Order_OnDragList()
|
|
//
|
|
// PURPOSE: Handles the drag list notifications which reorder the messages.
|
|
//
|
|
// PARAMETERS:
|
|
// hwnd - handle of the parent of the drag list
|
|
// idCtl - identifer of the drag list sending the notification
|
|
// lpdli - pointer to a DRAGLISTINFO struct with info about the
|
|
// notification.
|
|
//
|
|
// RETURN VALUE:
|
|
// Dependant on the notification.
|
|
//
|
|
// COMMENTS:
|
|
// This function uses the SetDlgMsgResult() macro defined in WINDOWSX.H to
|
|
// set the return value for each message since the parent window is a
|
|
// dialog.
|
|
//
|
|
LRESULT CCombineAndDecode::_Order_OnDragList(HWND hwnd, int idCtl, LPDRAGLISTINFO lpdli)
|
|
{
|
|
UINT iItem;
|
|
UINT cch;
|
|
|
|
Assert(((int) m_iItemToMove) >= 0);
|
|
|
|
switch (lpdli->uNotification)
|
|
{
|
|
// The user has started dragging one of the list control's items
|
|
case DL_BEGINDRAG:
|
|
{
|
|
// Find out which item is being dragged
|
|
m_iItemToMove = LBItemFromPt(lpdli->hWnd, lpdli->ptCursor, TRUE);
|
|
|
|
// Allocate a buffer for the string
|
|
Assert(m_pszBuffer == NULL);
|
|
cch = ListBox_GetTextLen(lpdli->hWnd, m_iItemToMove) + 1;
|
|
MemAlloc((LPVOID *) &m_pszBuffer, cch);
|
|
SendMessage(lpdli->hWnd, LB_GETTEXT, m_iItemToMove, (LPARAM) m_pszBuffer);
|
|
m_lpData = SendMessage(lpdli->hWnd, LB_GETITEMDATA, m_iItemToMove, 0);
|
|
|
|
DOUT("DL_BEGINDRAG: iItem = %d, text = %100s\r\n", m_iItemToMove, m_pszBuffer);
|
|
|
|
// Draw the insert icon
|
|
DrawInsert(hwnd, lpdli->hWnd, m_iItemToMove);
|
|
|
|
// Set the return value to allow the drag to contine
|
|
SetDlgMsgResult(hwnd, g_mDragList, TRUE);
|
|
return TRUE;
|
|
}
|
|
|
|
case DL_CANCELDRAG:
|
|
{
|
|
DOUT("DL_CANCELDRAG\r\n");
|
|
DrawInsert(hwnd, lpdli->hWnd, -1);
|
|
SafeMemFree(m_pszBuffer);
|
|
return 0; // Return value is ignored
|
|
}
|
|
|
|
// The user is in the process of dragging, update the position
|
|
// and move the insert icon
|
|
case DL_DRAGGING:
|
|
{
|
|
// Find out where the cursor is now
|
|
iItem = LBItemFromPt(lpdli->hWnd, lpdli->ptCursor, TRUE);
|
|
|
|
// Dump some debug info
|
|
DOUT("DL_DRAGGING: iItem = %d\r\n", iItem);
|
|
|
|
// Update the insert icon position
|
|
DrawInsert(hwnd, lpdli->hWnd, iItem);
|
|
|
|
// If the cursor is over a valid position set the cursor to
|
|
// DL_MOVECURSOR, otherwise use the DL_STOPCURSOR
|
|
if (-1 != iItem)
|
|
SetDlgMsgResult(hwnd, g_mDragList, DL_MOVECURSOR);
|
|
else
|
|
SetDlgMsgResult(hwnd, g_mDragList, DL_STOPCURSOR);
|
|
|
|
return (LRESULT) TRUE;
|
|
}
|
|
|
|
// The user has dropped the item somewhere, if valid update it's
|
|
// position
|
|
case DL_DROPPED:
|
|
{
|
|
// Where are we now.
|
|
iItem = LBItemFromPt(lpdli->hWnd, lpdli->ptCursor, TRUE);
|
|
DOUT("DL_DROPPED: iItem = %d\r\n", iItem);
|
|
|
|
// If the drop was somewhere valid
|
|
if (iItem != -1)
|
|
{
|
|
// Remove the insert icon
|
|
DrawInsert(hwnd, lpdli->hWnd, -1);
|
|
|
|
// Move the item in the listbox
|
|
if (m_iItemToMove != iItem)
|
|
{
|
|
SendMessage(lpdli->hWnd, LB_DELETESTRING, m_iItemToMove, 0L);
|
|
SendMessage(lpdli->hWnd, LB_INSERTSTRING, iItem, (LPARAM) m_pszBuffer);
|
|
SendMessage(lpdli->hWnd, LB_SETITEMDATA, iItem, m_lpData);
|
|
SendMessage(lpdli->hWnd, LB_SETCURSEL, iItem, 0L);
|
|
}
|
|
}
|
|
|
|
m_iItemToMove = (UINT) -1;
|
|
SafeMemFree(m_pszBuffer);
|
|
m_lpData = -1;
|
|
|
|
// Set the return value to reset the cursor
|
|
SetDlgMsgResult(hwnd, g_mDragList, DL_CURSORSET);
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
|
|
//
|
|
// FUNCTION: CCombineAndDecode::_Order_OnClose()
|
|
//
|
|
// PURPOSE: This get's called when the user clicks on the "x" button in the
|
|
// title bar.
|
|
//
|
|
void CCombineAndDecode::_Order_OnClose(HWND hwnd)
|
|
{
|
|
SendMessage(hwnd, WM_COMMAND, IDCANCEL, 0L);
|
|
}
|
|
|
|
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// Combine and Decode Progress dialog
|
|
//
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
|
|
|
|
INT_PTR CALLBACK CCombineAndDecode::CombineDlgProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
|
|
{
|
|
CCombineAndDecode *pThis;
|
|
|
|
if (uMsg == WM_INITDIALOG)
|
|
{
|
|
SetWindowLongPtr(hwnd, DWLP_USER, lParam);
|
|
pThis = (CCombineAndDecode *) lParam;
|
|
}
|
|
else
|
|
pThis = (CCombineAndDecode *) GetWindowLongPtr(hwnd, DWLP_USER);
|
|
|
|
if (pThis)
|
|
return (pThis->_CombineDlgProc(hwnd, uMsg, wParam, lParam));
|
|
|
|
return (FALSE);
|
|
}
|
|
|
|
INT_PTR CALLBACK CCombineAndDecode::_CombineDlgProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
|
|
{
|
|
switch (uMsg)
|
|
{
|
|
case WM_INITDIALOG:
|
|
return (BOOL) HANDLE_WM_INITDIALOG(hwnd, wParam, lParam, _Combine_OnInitDialog);
|
|
|
|
case WM_COMMAND:
|
|
HANDLE_WM_COMMAND(hwnd, wParam, lParam, _Combine_OnCommand);
|
|
return (TRUE);
|
|
|
|
case WM_DESTROY:
|
|
HANDLE_WM_CLOSE(hwnd, wParam, lParam, _Combine_OnDestroy);
|
|
return (TRUE);
|
|
|
|
case CND_GETNEXTARTICLE:
|
|
_Combine_GetNextArticle(hwnd);
|
|
return (TRUE);
|
|
|
|
case CND_OPENNOTE:
|
|
_Combine_OpenNote(hwnd);
|
|
return (TRUE);
|
|
|
|
case CND_MESSAGEAVAIL:
|
|
_Combine_OnMsgAvail(m_hwndDlg);
|
|
return (TRUE);
|
|
|
|
}
|
|
|
|
return (FALSE);
|
|
}
|
|
|
|
|
|
|
|
//
|
|
// FUNCTION: CCombineAndDecode::_Combine_OnInitDialog()
|
|
//
|
|
// PURPOSE: Initializes the progress dialog by figuring out how many lines
|
|
// will be downloaded, etc. To finish, we post a message to start
|
|
// the first message downloading.
|
|
//
|
|
BOOL CCombineAndDecode::_Combine_OnInitDialog(HWND hwnd, HWND hwndFocus, LPARAM lParam)
|
|
{
|
|
HRESULT hr = S_OK;
|
|
LPMESSAGEINFO pInfo;
|
|
|
|
m_hwndDlg = hwnd;
|
|
|
|
// Create the CNewsMsgList for Opie's groovy combiner
|
|
hr = MimeOleCreateMessageParts(&m_pMsgParts);
|
|
if (FAILED(hr))
|
|
{
|
|
EndDialog(hwnd, 0);
|
|
return (FALSE);
|
|
}
|
|
|
|
// Get a sum of the lines we need to download for the total messages
|
|
m_cLinesTotal = 0;
|
|
for (DWORD i = 0; i < m_cRows; i++)
|
|
{
|
|
// Get the message header from the table
|
|
if (SUCCEEDED(m_pTable->GetRow(m_rgRows[i], &pInfo)))
|
|
{
|
|
m_cLinesTotal += pInfo->cbMessage;
|
|
m_pTable->ReleaseRow(pInfo);
|
|
}
|
|
}
|
|
|
|
// Set the initial state of the progress bar
|
|
SendDlgItemMessage(hwnd, IDC_DOWNLOAD_PROG, PBM_SETRANGE, 0, MAKELONG(0, 100));
|
|
SendDlgItemMessage(hwnd, IDC_DOWNLOAD_PROG, PBM_SETPOS, 0, 0);
|
|
|
|
// Set up the animation
|
|
if (Animate_Open(GetDlgItem(hwnd, IDC_DOWNLOAD_AVI), MAKEINTRESOURCE(idanDecode)))
|
|
{
|
|
Animate_Play(GetDlgItem(hwnd, IDC_DOWNLOAD_AVI), 0, -1, -1);
|
|
}
|
|
|
|
// Start the download
|
|
m_dwCurrentArt = 0;
|
|
m_cCurrentLine = 0;
|
|
|
|
PostMessage(hwnd, CND_GETNEXTARTICLE, 0, 0L);
|
|
|
|
CenterDialog(hwnd);
|
|
ShowWindow(hwnd, SW_SHOW);
|
|
|
|
return (TRUE);
|
|
}
|
|
|
|
|
|
//
|
|
// FUNCTION: CCombineAndDecode::_Combine_OnCommand()
|
|
//
|
|
// PURPOSE: When the user hit's the Cancel button, we in turn tell the store
|
|
// to stop downloading.
|
|
//
|
|
void CCombineAndDecode::_Combine_OnCommand(HWND hwnd, int id, HWND hwndCtl, UINT codeNotify)
|
|
{
|
|
if (id == IDCANCEL && m_pCancel)
|
|
m_pCancel->Cancel(CT_CANCEL);
|
|
}
|
|
|
|
|
|
void CCombineAndDecode::_Combine_OnDestroy(HWND hwnd)
|
|
{
|
|
|
|
}
|
|
|
|
|
|
//
|
|
// FUNCTION: CCombineAndDecode::_Combine_GetNextArticle()
|
|
//
|
|
// PURPOSE: Called when we can start downloading another message.
|
|
//
|
|
void CCombineAndDecode::_Combine_GetNextArticle(HWND hwnd)
|
|
{
|
|
LPMIMEMESSAGE pMsg = NULL;
|
|
LPMESSAGEINFO pInfo;
|
|
TCHAR szProg[CCHMAX_STRINGRES];
|
|
TCHAR szBuf[CCHMAX_STRINGRES];
|
|
HRESULT hr;
|
|
|
|
if (SUCCEEDED(m_pTable->GetRow(m_rgRows[m_dwCurrentArt], &pInfo)))
|
|
{
|
|
// Set the progress for the current article
|
|
AthLoadString(idsProgDLMessage, szProg, ARRAYSIZE(szProg));
|
|
wnsprintf(szBuf, ARRAYSIZE(szBuf), szProg, pInfo->pszSubject);
|
|
SetDlgItemText(hwnd, IDC_GENERAL_TEXT, szBuf);
|
|
|
|
// Reset the line count
|
|
m_cPrevLine = 0;
|
|
|
|
// Check to see if the message is cached
|
|
if (!(pInfo->dwFlags & ARF_HASBODY))
|
|
{
|
|
// Request the message
|
|
hr = m_pTable->OpenMessage(m_rgRows[m_dwCurrentArt], 0, &pMsg, (IStoreCallback *) this);
|
|
if (FAILED(hr) && hr != E_PENDING)
|
|
{
|
|
AthMessageBoxW(m_hwndDlg, MAKEINTRESOURCEW(idsAthena), MAKEINTRESOURCEW(idsErrCantCombineNotConnected),
|
|
0, MB_OK | MB_ICONSTOP);
|
|
EndDialog(m_hwndDlg, 0);
|
|
}
|
|
}
|
|
else
|
|
_Combine_OnMsgAvail(hwnd);
|
|
|
|
if (pMsg)
|
|
pMsg->Release();
|
|
|
|
m_pTable->ReleaseRow(pInfo);
|
|
}
|
|
}
|
|
|
|
|
|
//
|
|
// FUNCTION: CCombineAndDecode::_Combine_OnMsgAvail()
|
|
//
|
|
// PURPOSE: Called once we've finished downloading an article.
|
|
//
|
|
void CCombineAndDecode::_Combine_OnMsgAvail(HWND hwnd)
|
|
{
|
|
LPMIMEMESSAGE pMsg = NULL;
|
|
DWORD increment;
|
|
TCHAR szProg[CCHMAX_STRINGRES];
|
|
HRESULT hr;
|
|
|
|
// Mark it read
|
|
m_pTable->Mark(&(m_rgRows[m_dwCurrentArt]), 1, APPLY_CHILDREN, MARK_MESSAGE_READ, (IStoreCallback *) this);
|
|
|
|
// Get the message now that it's available and add it to the combine list
|
|
if (SUCCEEDED(hr = m_pTable->OpenMessage(m_rgRows[m_dwCurrentArt], 0, &pMsg, (IStoreCallback *) this)))
|
|
{
|
|
// Add this to the pMsgList
|
|
m_pMsgParts->AddPart(pMsg);
|
|
pMsg->Release();
|
|
}
|
|
|
|
// Update the progress
|
|
LPMESSAGEINFO pInfo;
|
|
if (SUCCEEDED(m_pTable->GetRow(m_rgRows[m_dwCurrentArt], &pInfo)))
|
|
{
|
|
increment = pInfo->cbMessage - m_cPrevLine;
|
|
m_cCurrentLine += increment;
|
|
m_pTable->ReleaseRow(pInfo);
|
|
}
|
|
|
|
if (m_cLinesTotal)
|
|
{
|
|
increment = m_cCurrentLine * 100 / m_cLinesTotal;
|
|
SendDlgItemMessage(hwnd, IDC_DOWNLOAD_PROG, PBM_SETPOS, increment, 0);
|
|
}
|
|
|
|
// Increment the number of messages we've retrieved
|
|
m_dwCurrentArt++;
|
|
|
|
// If there are more to get, go get 'em
|
|
if (m_dwCurrentArt < m_cRows)
|
|
{
|
|
PostMessage(hwnd, CND_GETNEXTARTICLE, 0, 0L);
|
|
}
|
|
else
|
|
{
|
|
PostMessage(hwnd, CND_OPENNOTE, 0, 0);
|
|
}
|
|
}
|
|
|
|
void CCombineAndDecode::_Combine_OpenNote(HWND hwnd)
|
|
{
|
|
LPMIMEMESSAGE pMsgComb;
|
|
LPMIMEMESSAGE pMsg = NULL;
|
|
DWORD increment;
|
|
TCHAR szProg[CCHMAX_STRINGRES];
|
|
HRESULT hr;
|
|
|
|
// Update the progress
|
|
AthLoadString(idsProgCombiningMsgs, szProg, ARRAYSIZE(szProg));
|
|
SetDlgItemText(hwnd, IDC_GENERAL_TEXT, szProg);
|
|
SetDlgItemText(hwnd, IDC_SPECIFIC_TEXT, TEXT(""));
|
|
|
|
// All the articles are downloaded. Merge the message list
|
|
// and open the note.
|
|
hr = m_pMsgParts->CombineParts(&pMsgComb);
|
|
if (FAILED(hr))
|
|
{
|
|
AthMessageBoxW(hwnd, MAKEINTRESOURCEW(idsAthenaNews),
|
|
MAKEINTRESOURCEW(idsGenericError), 0, MB_OK | MB_ICONSTOP);
|
|
}
|
|
else
|
|
{
|
|
FOLDERINFO info;
|
|
INIT_MSGSITE_STRUCT initStruct;
|
|
DWORD dwCreateFlags = 0;
|
|
|
|
if (SUCCEEDED(g_pStore->GetFolderInfo(m_idFolder, &info)))
|
|
{
|
|
// If this is a find folder, we need to put the account on the message
|
|
if (!!(info.dwFlags & FOLDER_FINDRESULTS))
|
|
{
|
|
FOLDERID id;
|
|
if (SUCCEEDED(m_pTable->GetRowFolderId(*m_rgRows, &id)))
|
|
{
|
|
FOLDERINFO fiServer = {0};
|
|
|
|
if (SUCCEEDED(GetFolderServer(id, &fiServer)))
|
|
{
|
|
HrSetAccount(pMsgComb, fiServer.pszName);
|
|
g_pStore->FreeRecord(&fiServer);
|
|
}
|
|
}
|
|
}
|
|
|
|
g_pStore->FreeRecord(&info);
|
|
}
|
|
|
|
// Initialize note struct
|
|
initStruct.dwInitType = OEMSIT_MSG;
|
|
initStruct.folderID = m_idFolder;
|
|
initStruct.pMsg = pMsgComb;
|
|
|
|
// Decide whether it is news or mail
|
|
if (GetFolderType(m_idFolder) == FOLDER_NEWS)
|
|
{
|
|
FOLDERINFO rServer;
|
|
if (SUCCEEDED(GetFolderServer(m_idFolder, &rServer)))
|
|
{
|
|
HrSetAccount(pMsgComb, rServer.pszAccountId);
|
|
g_pStore->FreeRecord(&rServer);
|
|
}
|
|
|
|
dwCreateFlags = OENCF_NEWSFIRST;
|
|
}
|
|
|
|
// Create and Open Note
|
|
hr = CreateAndShowNote(OENA_READ, dwCreateFlags, &initStruct, m_hwndParent);
|
|
pMsgComb->Release();
|
|
}
|
|
|
|
EndDialog(m_hwndDlg, 0);
|
|
}
|
|
|
|
//
|
|
// FUNCTION: CCombineAndDecode::OnBegin()
|
|
//
|
|
// PURPOSE: Called when the store starts downloading an article.
|
|
//
|
|
HRESULT CCombineAndDecode::OnBegin(STOREOPERATIONTYPE tyOperation, STOREOPERATIONINFO *pOpInfo, IOperationCancel *pCancel)
|
|
{
|
|
Assert(tyOperation != SOT_INVALID);
|
|
Assert(m_pCancel == NULL);
|
|
|
|
m_type = tyOperation;
|
|
|
|
if (pCancel != NULL)
|
|
{
|
|
m_pCancel = pCancel;
|
|
m_pCancel->AddRef();
|
|
}
|
|
|
|
return(S_OK);
|
|
}
|
|
|
|
|
|
//
|
|
// FUNCTION: CCombineAndDecode::OnProgress()
|
|
//
|
|
// PURPOSE: Called while the messages are downloading to give us some
|
|
// progress.
|
|
//
|
|
HRESULT STDMETHODCALLTYPE CCombineAndDecode::OnProgress(STOREOPERATIONTYPE tyOperation, DWORD dwCurrent, DWORD dwMax, LPCSTR pszStatus)
|
|
{
|
|
int increment;
|
|
TCHAR szProg[CCHMAX_STRINGRES];
|
|
TCHAR szBuf[CCHMAX_STRINGRES];
|
|
|
|
Assert(m_hwndDlg != NULL);
|
|
|
|
// Close any timeout dialog, if present
|
|
CallbackCloseTimeout(&m_hTimeout);
|
|
|
|
// Connection progress
|
|
if (tyOperation == SOT_CONNECTION_STATUS)
|
|
{
|
|
Assert(dwCurrent < IXP_LAST);
|
|
|
|
// Create some lovely status text
|
|
int ids = XPUtil_StatusToString((IXPSTATUS) dwCurrent);
|
|
AthLoadString(ids, szBuf, ARRAYSIZE(szBuf));
|
|
SetDlgItemText(m_hwndDlg, IDC_GENERAL_TEXT, szBuf);
|
|
}
|
|
|
|
AthLoadString(idsProgDLGetLines, szProg, ARRAYSIZE(szProg));
|
|
wnsprintf(szBuf, ARRAYSIZE(szBuf), szProg, dwCurrent, dwMax);
|
|
SetDlgItemText(m_hwndDlg, IDC_SPECIFIC_TEXT, szBuf);
|
|
|
|
increment = dwCurrent - m_cPrevLine;
|
|
m_cCurrentLine += increment;
|
|
m_cPrevLine = dwCurrent;
|
|
|
|
if (m_cLinesTotal)
|
|
{
|
|
increment = m_cCurrentLine * 100 / m_cLinesTotal;
|
|
SendDlgItemMessage(m_hwndDlg, IDC_DOWNLOAD_PROG, PBM_SETPOS, increment, 0);
|
|
}
|
|
|
|
return(S_OK);
|
|
}
|
|
|
|
|
|
//
|
|
// FUNCTION: CCombineAndDecode::OnTimeout()
|
|
//
|
|
// PURPOSE: If a timeout occurs, we call through to the default timeout handler.
|
|
//
|
|
HRESULT STDMETHODCALLTYPE CCombineAndDecode::OnTimeout(LPINETSERVER pServer, LPDWORD pdwTimeout, IXPTYPE ixpServerType)
|
|
{
|
|
// Display a timeout dialog
|
|
return CallbackOnTimeout(pServer, ixpServerType, *pdwTimeout, (ITimeoutCallback *)this, &m_hTimeout);
|
|
}
|
|
|
|
|
|
//
|
|
// FUNCTION: CCombineAndDecode::OnTimeoutResponse()
|
|
//
|
|
// PURPOSE: Called when the user responds to a timeout dialog.
|
|
//
|
|
HRESULT STDMETHODCALLTYPE CCombineAndDecode::OnTimeoutResponse(TIMEOUTRESPONSE eResponse)
|
|
{
|
|
// Call into general timeout response utility
|
|
return CallbackOnTimeoutResponse(eResponse, m_pCancel, &m_hTimeout);
|
|
}
|
|
|
|
|
|
//
|
|
// FUNCTION: CCombineAndDecode::CanConnect()
|
|
//
|
|
// PURPOSE: Called if the store needs to connect to download the requested
|
|
// messages. We just call through to the default handlers.
|
|
//
|
|
HRESULT STDMETHODCALLTYPE CCombineAndDecode::CanConnect(LPCSTR pszAccountId, DWORD dwFlags)
|
|
{
|
|
HWND hwndParent;
|
|
DWORD dwReserved = 0;
|
|
|
|
GetParentWindow(dwReserved, &hwndParent);
|
|
|
|
return CallbackCanConnect(pszAccountId, hwndParent, TRUE);
|
|
}
|
|
|
|
|
|
|
|
//
|
|
// FUNCTION: CCombineAndDecode::OnLogonPrompt()
|
|
//
|
|
// PURPOSE: If the user needs to logon, we present them with the default
|
|
// logon UI.
|
|
//
|
|
HRESULT STDMETHODCALLTYPE CCombineAndDecode::OnLogonPrompt(LPINETSERVER pServer, IXPTYPE ixpServerType)
|
|
{
|
|
// Close any timeout dialog, if present
|
|
CallbackCloseTimeout(&m_hTimeout);
|
|
|
|
// Call into general OnLogonPrompt Utility
|
|
return CallbackOnLogonPrompt(m_hwndDlg, pServer, ixpServerType);
|
|
}
|
|
|
|
|
|
//
|
|
// FUNCTION: CCombineAndDecode::OnComplete()
|
|
//
|
|
// PURPOSE: When we finish downloading a message, this get's hit. We add
|
|
// this message to the list for the combiner and then request the
|
|
// next message.
|
|
//
|
|
HRESULT STDMETHODCALLTYPE CCombineAndDecode::OnComplete(STOREOPERATIONTYPE tyOperation, HRESULT hrComplete, LPSTOREOPERATIONINFO pOpInfo, LPSTOREERROR pErrorInfo)
|
|
{
|
|
Assert(m_hwndDlg != NULL);
|
|
AssertSz(m_type != SOT_INVALID, "somebody isn't calling OnBegin");
|
|
|
|
// Close any timeout dialog, if present
|
|
CallbackCloseTimeout(&m_hTimeout);
|
|
|
|
if (m_type != tyOperation)
|
|
return(S_OK);
|
|
|
|
if (m_pCancel != NULL)
|
|
{
|
|
m_pCancel->Release();
|
|
m_pCancel = NULL;
|
|
}
|
|
|
|
// If error occurred, display the error
|
|
if (FAILED(hrComplete))
|
|
{
|
|
// Call into my swanky utility
|
|
CallbackDisplayError(m_hwndDlg, hrComplete, pErrorInfo);
|
|
EndDialog(m_hwndDlg, 0);
|
|
}
|
|
else
|
|
{
|
|
if (tyOperation == SOT_GET_MESSAGE)
|
|
PostMessage(m_hwndDlg, CND_MESSAGEAVAIL, 0, 0);
|
|
}
|
|
return(S_OK);
|
|
}
|
|
|
|
|
|
//
|
|
// FUNCTION: CCombineAndDecode::OnPrompt()
|
|
//
|
|
// PURPOSE: Last time I checked, this was SSL related goo.
|
|
//
|
|
HRESULT STDMETHODCALLTYPE CCombineAndDecode::OnPrompt(HRESULT hrError, LPCTSTR pszText, LPCTSTR pszCaption, UINT uType, INT *piUserResponse)
|
|
{
|
|
// Close any timeout dialog, if present
|
|
CallbackCloseTimeout(&m_hTimeout);
|
|
|
|
// Call into my swanky utility
|
|
return CallbackOnPrompt(m_hwndDlg, hrError, pszText, pszCaption, uType, piUserResponse);
|
|
}
|
|
|
|
|
|
//
|
|
// FUNCTION: CCombineAndDecode::GetParentWindow()
|
|
//
|
|
// PURPOSE: Called if the store needs to show UI. We return our dialog
|
|
// window handle.
|
|
//
|
|
HRESULT STDMETHODCALLTYPE CCombineAndDecode::GetParentWindow(DWORD dwReserved, HWND *phwndParent)
|
|
{
|
|
Assert(m_hwndDlg != NULL);
|
|
|
|
*phwndParent = m_hwndDlg;
|
|
|
|
return(S_OK);
|
|
}
|
|
|
|
|
|
|
|
#if 0
|
|
BOOL CALLBACK CombineAndDecodeProg(HWND hwnd, UINT uMsg, WPARAM wParam,
|
|
LPARAM lParam)
|
|
{
|
|
PORDERPARAMS pop = (PORDERPARAMS) GetWindowLongPtr(hwnd, DWLP_USER);
|
|
TCHAR szProg[CCHMAX_STRINGRES];
|
|
TCHAR szBuf[CCHMAX_STRINGRES];
|
|
LPMIMEMESSAGE pMsg=0;
|
|
DWORD increment;
|
|
HRESULT hr;
|
|
|
|
switch (uMsg)
|
|
{
|
|
case IMC_BODYAVAIL:
|
|
{
|
|
LPMIMEMESSAGE pMsg = NULL;
|
|
BOOL fCached = FALSE;
|
|
|
|
Assert(pop->pGroup);
|
|
if (SUCCEEDED(wParam) && SUCCEEDED(pop->pGroup->GetArticle(pop->rgpMsgs[pop->dwCurrentArt], &pMsg, hwnd, &fCached, FALSE, GETMSG_INSECURE)) && fCached)
|
|
{
|
|
Assert(pMsg);
|
|
Order_OnMsgAvail(hwnd, pop, pMsg);
|
|
}
|
|
else
|
|
{
|
|
if ((HRESULT)wParam != hrUserCancel)
|
|
AthMessageBoxW(hwnd, MAKEINTRESOURCEW(idsAthenaNews),
|
|
MAKEINTRESOURCEW(idsErrNewsCantOpen), 0, MB_OK | MB_ICONSTOP);
|
|
PostMessage(hwnd, WM_CLOSE, 0, 0);
|
|
}
|
|
|
|
if (pMsg)
|
|
pMsg->Release();
|
|
return (TRUE);
|
|
}
|
|
|
|
|
|
}
|
|
|
|
return (FALSE);
|
|
}
|
|
|
|
#endif
|
|
|
|
|