8537 lines
248 KiB
C++
8537 lines
248 KiB
C++
//*************************************************
|
|
// h e a d e r . c p p
|
|
//
|
|
// Purpose:
|
|
// implements Header UI for Read|SendNote
|
|
//
|
|
// Owner:
|
|
// brettm.
|
|
//
|
|
// History:
|
|
// July '95: Created
|
|
//
|
|
// Copyright (C) Microsoft Corp. 1993, 1994.
|
|
//*************************************************
|
|
|
|
#include <pch.hxx>
|
|
#include <richedit.h>
|
|
#include <resource.h>
|
|
#include <thormsgs.h>
|
|
#include "oleutil.h"
|
|
#include "fonts.h"
|
|
#include "error.h"
|
|
#include "header.h"
|
|
#include "options.h"
|
|
#include "note.h"
|
|
#include "ipab.h"
|
|
#include "addrobj.h"
|
|
#include "hotlinks.h"
|
|
#include <mimeole.h>
|
|
#include <secutil.h>
|
|
#include <xpcomm.h>
|
|
#include "menuutil.h"
|
|
#include "shlwapi.h"
|
|
#include "envcid.h"
|
|
#include "ourguid.h"
|
|
#include "mimeutil.h"
|
|
#include "strconst.h"
|
|
#include "mailutil.h"
|
|
#include "regutil.h"
|
|
#include "spoolapi.h"
|
|
#include "init.h"
|
|
#include "instance.h"
|
|
#include "attman.h"
|
|
#include "envguid.h"
|
|
#include <inetcfg.h> //ICW
|
|
#include <pickgrp.h>
|
|
#include "menures.h"
|
|
#include "storecb.h"
|
|
#include "mimeolep.h"
|
|
#include "multlang.h"
|
|
#include "mirror.h"
|
|
#include "seclabel.h"
|
|
#include "shlwapip.h"
|
|
#include "reutil.h"
|
|
#include <iert.h>
|
|
#include "msgprop.h"
|
|
#include "demand.h"
|
|
|
|
ASSERTDATA
|
|
|
|
extern UINT GetCurColorRes(void);
|
|
|
|
class CFieldSizeMgr : public CPrivateUnknown,
|
|
public IFontCacheNotify,
|
|
public IConnectionPoint
|
|
{
|
|
public:
|
|
// IUnknown
|
|
virtual STDMETHODIMP QueryInterface(REFIID riid, LPVOID * ppvObj) {
|
|
return CPrivateUnknown::QueryInterface(riid, ppvObj); };
|
|
virtual STDMETHODIMP_(ULONG) AddRef(void) {
|
|
return CPrivateUnknown::AddRef();};
|
|
virtual STDMETHODIMP_(ULONG) Release(void) {
|
|
return CPrivateUnknown::Release(); };
|
|
|
|
// IFontCacheNotify
|
|
HRESULT STDMETHODCALLTYPE OnPreFontChange(void);
|
|
HRESULT STDMETHODCALLTYPE OnPostFontChange(void);
|
|
|
|
// IConnectionPoint
|
|
HRESULT STDMETHODCALLTYPE GetConnectionInterface(IID *pIID);
|
|
HRESULT STDMETHODCALLTYPE GetConnectionPointContainer(IConnectionPointContainer **ppCPC);
|
|
HRESULT STDMETHODCALLTYPE Advise(IUnknown *pUnkSink, DWORD *pdwCookie);
|
|
HRESULT STDMETHODCALLTYPE Unadvise(DWORD dwCookie);
|
|
HRESULT STDMETHODCALLTYPE EnumConnections(IEnumConnections **ppEnum);
|
|
|
|
// CPrivateUnknown
|
|
HRESULT PrivateQueryInterface(REFIID riid, LPVOID * ppvObj);
|
|
|
|
int GetScalingFactor(void);
|
|
void ResetGlobalSizes(void);
|
|
HRESULT Init(void);
|
|
|
|
// This one should only be called from headers' OnPostFontChange calls
|
|
BOOL FontsChanged(void) {return m_fFontsChanged;}
|
|
|
|
CFieldSizeMgr(IUnknown *pUnkOuter=NULL);
|
|
~CFieldSizeMgr();
|
|
|
|
private:
|
|
IUnknownList *m_pAdviseRegistry;
|
|
CRITICAL_SECTION m_rAdviseCritSect;
|
|
BOOL m_fFontsChanged;
|
|
DWORD m_dwFontNotify;
|
|
};
|
|
|
|
// **********************************************************
|
|
// ***** Debug stuff for handling painting and resizing *****
|
|
// **********************************************************
|
|
const int PAINTING_DEBUG_LEVEL = 4;
|
|
const int RESIZING_DEBUG_LEVEL = 8;
|
|
const int GEN_HEADER_DEBUG_LEVEL = 16;
|
|
|
|
#ifdef DEBUG
|
|
|
|
class StackRegistry {
|
|
public:
|
|
StackRegistry(LPSTR pszTitle, INT_PTR p1 = 0, INT_PTR p2 = 0, INT_PTR p3 = 0, INT_PTR p4 = 0, INT_PTR p5 = 0);
|
|
~StackRegistry();
|
|
|
|
private:
|
|
int m_StackLevel;
|
|
CHAR m_szTitle[256+1];
|
|
|
|
static int gm_cStackLevel;
|
|
static int gm_strLen;
|
|
static LPSTR gm_Indent;
|
|
};
|
|
|
|
int StackRegistry::gm_cStackLevel = 0;
|
|
LPSTR StackRegistry::gm_Indent = "------------------------------";
|
|
int StackRegistry::gm_strLen = lstrlen(gm_Indent);
|
|
|
|
StackRegistry::StackRegistry(LPSTR pszTitle, INT_PTR p1, INT_PTR p2, INT_PTR p3, INT_PTR p4, INT_PTR p5)
|
|
{
|
|
gm_cStackLevel++;
|
|
m_StackLevel = (gm_cStackLevel > gm_strLen) ? gm_strLen : gm_cStackLevel;
|
|
StrCpyN(m_szTitle, pszTitle, ARRAYSIZE(m_szTitle));
|
|
m_szTitle[256] = 0;
|
|
|
|
if (1 == gm_cStackLevel)
|
|
DOUTL(RESIZING_DEBUG_LEVEL, "\n*********** BEGIN TRACE ***********");
|
|
|
|
DOUTL(RESIZING_DEBUG_LEVEL, "IN*** %s%s - %x, %x, %x, %x, %x", gm_Indent+gm_strLen-m_StackLevel, m_szTitle, p1, p2, p3, p4, p5);
|
|
}
|
|
|
|
StackRegistry::~StackRegistry()
|
|
{
|
|
DOUTL(RESIZING_DEBUG_LEVEL, "OUT** %s%s", gm_Indent+gm_strLen-m_StackLevel, m_szTitle);
|
|
|
|
if (1 == gm_cStackLevel)
|
|
DOUTL(RESIZING_DEBUG_LEVEL, "************ END TRACE ************\n");
|
|
|
|
gm_cStackLevel--;
|
|
Assert(gm_cStackLevel >= 0);
|
|
}
|
|
|
|
|
|
#define STACK StackRegistry stack
|
|
|
|
#else
|
|
|
|
// BUGBUG (neilbren) WIN64
|
|
// Figure out when __noop was introduced (MSC_VER ?) so we don't have to key off of WIN64
|
|
#define STACK __noop
|
|
|
|
#endif
|
|
|
|
// ******************************
|
|
// ***** End of debug stuff *****
|
|
// ******************************
|
|
|
|
|
|
// c o n s t a n t s
|
|
const DWORD SETWINPOS_DEF_FLAGS = SWP_NOZORDER|SWP_NOACTIVATE;
|
|
|
|
#define GET_WM_COMMAND_ID(wp, lp) LOWORD(wp)
|
|
#define GET_WM_COMMAND_HWND(wp, lp) (HWND)(lp)
|
|
#define GET_WM_COMMAND_CMD(wp, lp) HIWORD(wp)
|
|
#define WC_ATHHEADER wszHeaderWndClass
|
|
#define RGB_TRANSPARENT RGB(255,0,255)
|
|
#define HDM_TESTQUERYPRI (WM_USER + 1)
|
|
#define cxBorder (GetSystemMetrics(SM_CXBORDER))
|
|
#define cyBorder (GetSystemMetrics(SM_CYBORDER))
|
|
|
|
// HDRCB_VCARD must remain -1 and all others must be negative
|
|
enum {
|
|
HDRCB_VCARD = -1,
|
|
HDRCB_SIGNED = -2,
|
|
HDRCB_ENCRYPT = -3,
|
|
HDRCB_NO_BUTTON = -4
|
|
};
|
|
|
|
// WARNING:: This next macro is only to be used with g_rgBtnInd inside the CNoteHdr class.
|
|
// Make sure that they match the entries in g_rgBtnInd
|
|
#define BUTTON_STATES m_fDigSigned, m_fEncrypted, m_fVCard
|
|
#define BUTTON_USE_IN_COMPOSE FALSE, FALSE, TRUE
|
|
|
|
static const DWORD g_rgBtnInd[] = {HDRCB_SIGNED, HDRCB_ENCRYPT, HDRCB_VCARD};
|
|
|
|
static const int cchMaxWab = 512;
|
|
static const int cxTBButton = 16;
|
|
static const int BUTTON_BUFFER = 2;
|
|
static const int cxBtn = 16;
|
|
static const int cyBtn = cxBtn;
|
|
static const int cxFlags = 12;
|
|
static const int cyFlags = cxFlags;
|
|
static const int cxFlagsDelta = cxFlags + 4;
|
|
static const int MAX_ATTACH_PIXEL_HEIGHT = 50;
|
|
static const int ACCT_ENTRY_SIZE = CCHMAX_ACCOUNT_NAME + CCHMAX_EMAIL_ADDRESS + 10;
|
|
static const int INVALID_PHCI_Y = -1;
|
|
static const int cMaxRecipMenu = (ID_ADD_RECIPIENT_LAST-ID_ADD_RECIPIENT_FIRST);
|
|
static const int NUM_COMBO_LINES = 9;
|
|
static const int MAX_RICHEDIT_LINES = 4;
|
|
static const int DEFER_WINDOW_SIZE = MAX_HEADER_COMP + 1 + 1 + 1 + 5; // +1=header window, +1=field resize, +1 toolbar
|
|
static const LPTSTR GRP_DELIMITERS = " ,\t;\n\r";
|
|
|
|
#define c_wszEmpty L""
|
|
#define c_aszEmpty ""
|
|
|
|
|
|
// t y p e d e f s
|
|
|
|
typedef struct TIPLOOKUP_tag
|
|
{
|
|
int idm;
|
|
int ids;
|
|
} TIPLOOKUP;
|
|
|
|
typedef struct CMDMAPING_tag
|
|
{
|
|
DWORD cmdIdOffice,
|
|
cmdIdOE;
|
|
} CMDMAPING;
|
|
|
|
typedef struct PERSISTHEADER_tag
|
|
{
|
|
DWORD cbSize; // size so we can version the stuct
|
|
DWORD dwRes1, // padding just in case...
|
|
dwRes2;
|
|
} PERSISTHEADER;
|
|
|
|
#define cchMaxSubject 256
|
|
|
|
typedef struct WELLINIT_tag
|
|
{
|
|
INT idField;
|
|
ULONG uMAPI;
|
|
} WELLINIT, *PWELLINIT;
|
|
|
|
|
|
// s t a t i c d a t a
|
|
static HIMAGELIST g_himlStatus = 0,
|
|
g_himlBtns = 0,
|
|
g_himlSecurity = 0;
|
|
|
|
static TCHAR g_szStatFlagged[cchHeaderMax+1] = c_aszEmpty,
|
|
g_szStatLowPri[cchHeaderMax+1] = c_aszEmpty,
|
|
g_szStatHighPri[cchHeaderMax+1] = c_aszEmpty,
|
|
g_szStatWatched[cchHeaderMax+1] = c_aszEmpty,
|
|
g_szStatIgnored[cchHeaderMax+1] = c_aszEmpty,
|
|
g_szStatFormat1[cchHeaderMax+1] = c_aszEmpty,
|
|
g_szStatFormat2[cchHeaderMax+1] = c_aszEmpty,
|
|
g_szStatFormat3[cchHeaderMax+1] = c_aszEmpty,
|
|
g_szStatUnsafeAtt[cchHeaderMax+1] = c_aszEmpty;
|
|
|
|
static CFieldSizeMgr *g_pFieldSizeMgr = NULL;
|
|
static WNDPROC g_lpfnREWndProc = NULL;
|
|
static CHARFORMAT g_cfHeader = {0};
|
|
static int g_cyFont = 0,
|
|
g_cyLabelHeight = 0;
|
|
|
|
static char const szButton[]="BUTTON";
|
|
static WCHAR const wszHeaderWndClass[]=L"OE_Envelope";
|
|
|
|
|
|
|
|
// KEEP in ssync with c_rgTipLookup
|
|
const TBBUTTON c_btnsOfficeEnvelope[]=
|
|
{
|
|
{TBIMAGE_SEND_MAIL, ID_SEND_NOW, TBSTATE_ENABLED, TBSTYLE_BUTTON, {0,0}, 0, -1},
|
|
__TOOLBAR_SEP__,
|
|
{ TBIMAGE_CHECK_NAMES, ID_CHECK_NAMES, TBSTATE_ENABLED, TBSTYLE_BUTTON, {0, 0}, 0, -1},
|
|
{ TBIMAGE_ADDRESS_BOOK, ID_ADDRESS_BOOK, TBSTATE_ENABLED, TBSTYLE_BUTTON, {0, 0}, 0, -1},
|
|
__TOOLBAR_SEP__,
|
|
{TBIMAGE_SET_PRIORITY, ID_SET_PRIORITY, TBSTATE_ENABLED, TBSTYLE_DROPDOWN, {0,0}, 0, -1},
|
|
{TBIMAGE_INSERT_ATTACHMENT, ID_INSERT_ATTACHMENT, TBSTATE_ENABLED, TBSTYLE_BUTTON, {0,0}, 0, -1},
|
|
__TOOLBAR_SEP__,
|
|
{ TBIMAGE_ENVELOPE_BCC, ID_ENV_BCC, TBSTATE_ENABLED, TBSTYLE_BUTTON, {0,0}, 0, -1}
|
|
};
|
|
|
|
// KEEP in ssync with c_btnsOfficeEnvelope
|
|
const TIPLOOKUP c_rgTipLookup[] =
|
|
{
|
|
{ID_SEND_NOW, idsSendMsgTT},
|
|
{ID_CHECK_NAMES, idsCheckNamesTT},
|
|
{ID_ADDRESS_BOOK, idsAddressBookTT},
|
|
{ID_SET_PRIORITY, idsSetPriorityTT},
|
|
{ID_INSERT_ATTACHMENT, idsInsertFileTT},
|
|
{ID_ENV_BCC, idsEnvBccTT}
|
|
};
|
|
|
|
// Prototypes
|
|
HRESULT ParseFollowup(LPMIMEMESSAGE pMsg, LPTSTR* ppszGroups, BOOL* pfPoster);
|
|
DWORD HdrGetRichEditText(HWND hwnd, LPWSTR pwchBuff, DWORD dwNumChars, BOOL fSelection);
|
|
void HdrSetRichEditText(HWND hwnd, LPWSTR pwchBuff, BOOL fReplace);
|
|
|
|
// i n l i n e s
|
|
|
|
void HdrSetRichEditText(HWND hwnd, LPWSTR pwchBuff, BOOL fReplace)
|
|
{
|
|
if (!hwnd)
|
|
return;
|
|
|
|
PHCI phci = (HCI*)GetWindowLongPtr(hwnd, GWLP_USERDATA);
|
|
AssertSz(phci, "We are calling HdrSetRichEditText on a non-richedit control");
|
|
|
|
SetRichEditText(hwnd, pwchBuff, fReplace, phci->pDoc, (phci->dwFlags & HCF_READONLY));
|
|
}
|
|
|
|
DWORD HdrGetRichEditText(HWND hwnd, LPWSTR pwchBuff, DWORD dwNumChars, BOOL fSelection)
|
|
{
|
|
if (!hwnd)
|
|
return 0;
|
|
|
|
PHCI phci = (HCI*)GetWindowLongPtr(hwnd, GWLP_USERDATA);
|
|
AssertSz(phci, "We are calling HdrSetRichEditText on a non-richedit control");
|
|
|
|
return GetRichEditText(hwnd, pwchBuff, dwNumChars, fSelection, phci->pDoc);
|
|
}
|
|
|
|
inline void GetRealClientRect(HWND hwnd, RECT *prc)
|
|
{
|
|
GetClientRect(hwnd, prc);
|
|
AdjustWindowRectEx(prc, GetWindowLong(hwnd, GWL_STYLE), FALSE, GetWindowLong(hwnd, GWL_EXSTYLE));
|
|
}
|
|
|
|
inline int GetCtrlWidth(HWND hwnd)
|
|
{
|
|
RECT rc;
|
|
GetWindowRect(hwnd, &rc);
|
|
return rc.right - rc.left;
|
|
}
|
|
|
|
inline int GetControlSize(BOOL fIncludeBorder, int cLines)
|
|
{
|
|
int size = cLines * g_cyFont;
|
|
|
|
// If borders, include the metrics
|
|
if (fIncludeBorder)
|
|
size += 7;
|
|
|
|
return size;
|
|
}
|
|
|
|
inline int GetCtrlHeight(HWND hwnd)
|
|
{
|
|
DWORD id = GetWindowLong(hwnd, GWL_ID);
|
|
if (idFromCombo == id)
|
|
{
|
|
return GetControlSize(TRUE, 1);
|
|
}
|
|
else
|
|
{
|
|
RECT rc;
|
|
GetWindowRect(hwnd, &rc);
|
|
return rc.bottom - rc.top;
|
|
}
|
|
}
|
|
|
|
inline int GetStatusHeight(int cLines) {return ((cyBtn<g_cyFont)?GetControlSize(TRUE, cLines):((cyBtn-4)*cLines + 2*cyBorder + 6)); }
|
|
inline int CYOfStatusLine() { return ((cyBtn<g_cyFont)?g_cyFont:(cyBtn - 4)); }
|
|
inline int ControlXBufferSize() { return 10 * cxBorder; }
|
|
inline int ControlYBufferSize() { return 4 * cyBorder; }
|
|
inline int PaddingOfLabels() { return 2 * ControlXBufferSize(); }
|
|
inline int CXOfButtonToLabel() { return 4*cxBorder + cxBtn; }
|
|
|
|
inline BOOL ButtonInLabels(int iBtn) { return (iBtn > HDRCB_VCARD); }
|
|
inline HFONT GetFont(BOOL fBold) { return HGetSystemFont(fBold?FNT_SYS_ICON_BOLD:FNT_SYS_ICON); }
|
|
|
|
|
|
static IMSGPRIORITY priLookup[3]=
|
|
{ IMSG_PRI_LOW,
|
|
IMSG_PRI_NORMAL,
|
|
IMSG_PRI_HIGH
|
|
};
|
|
|
|
#define HCI_ENTRY(flg,opt,ide,idb,idsl,idse,idst) \
|
|
{ \
|
|
flg, opt, \
|
|
ide, idb, \
|
|
idsl, idse, idst, \
|
|
NOFLAGS, TRUE, \
|
|
NULL, NULL, \
|
|
0, 0, 0, 0, \
|
|
c_wszEmpty, c_wszEmpty \
|
|
}
|
|
|
|
static int rgIDTabOrderMailSend[] =
|
|
{
|
|
idFromCombo, idADTo,
|
|
idADCc, idADBCc,
|
|
idTXTSubject, idwAttachWell
|
|
};
|
|
|
|
static HCI rgMailHeaderSend[]=
|
|
{
|
|
|
|
HCI_ENTRY(HCF_COMBO|HCF_ADVANCED|HCF_BORDER,
|
|
0,
|
|
idFromCombo, 0,
|
|
idsFromField, NULL,
|
|
NULL),
|
|
|
|
HCI_ENTRY(HCF_MULTILINE|HCF_HASBUTTON|HCF_ADDRBOOK|HCF_ADDRWELL|HCF_BORDER,
|
|
0,
|
|
idADTo, idbtnTo,
|
|
idsToField, idsEmptyTo,
|
|
idsTTRecipients),
|
|
|
|
HCI_ENTRY(HCF_MULTILINE|HCF_HASBUTTON|HCF_ADDRBOOK|HCF_ADDRWELL|HCF_BORDER,
|
|
0,
|
|
idADCc, idbtnCc,
|
|
idsCcField, idsEmptyCc,
|
|
idsTTRecipients),
|
|
|
|
HCI_ENTRY(HCF_MULTILINE|HCF_HASBUTTON|HCF_ADDRBOOK|HCF_ADDRWELL|HCF_ADVANCED|HCF_BORDER,
|
|
0,
|
|
idADBCc, idbtnBCc,
|
|
idsBCcField, idsEmptyBCc,
|
|
idsTTRecipients),
|
|
|
|
HCI_ENTRY(HCF_USECHARSET|HCF_BORDER,
|
|
0,
|
|
idTXTSubject, 0,
|
|
idsSubjectField, idsEmptySubject,
|
|
idsTTSubject),
|
|
|
|
HCI_ENTRY(HCF_BORDER|HCF_ATTACH,
|
|
0,
|
|
idwAttachWell, 0,
|
|
idsAttachment, 0,
|
|
idsTTAttachment),
|
|
};
|
|
|
|
static int rgIDTabOrderMailRead[] =
|
|
{
|
|
idADFrom, idTXTDate,
|
|
idADTo, idADCc,
|
|
idTXTSubject, idwAttachWell,
|
|
idSecurity
|
|
};
|
|
|
|
static HCI rgMailHeaderRead[]=
|
|
{
|
|
HCI_ENTRY(HCF_MULTILINE|HCF_READONLY|HCF_ADDRWELL,
|
|
0,
|
|
idADFrom, 0,
|
|
idsFromField, idsNoFromField,
|
|
NULL),
|
|
|
|
HCI_ENTRY(HCF_READONLY,
|
|
0,
|
|
idTXTDate, 0,
|
|
idsDateField, NULL,
|
|
NULL),
|
|
|
|
HCI_ENTRY(HCF_MULTILINE|HCF_READONLY|HCF_ADDRWELL,
|
|
0,
|
|
idADTo, 0,
|
|
idsToField, idsNoCcOrTo,
|
|
NULL),
|
|
|
|
HCI_ENTRY(HCF_MULTILINE|HCF_READONLY|HCF_ADVANCED|HCF_ADDRWELL,
|
|
0,
|
|
idADCc, 0,
|
|
idsCcField, idsNoCcOrTo,
|
|
NULL),
|
|
|
|
HCI_ENTRY(HCF_READONLY|HCF_USECHARSET,
|
|
0,
|
|
idTXTSubject, 0,
|
|
idsSubjectField, idsEmptySubjectRO,
|
|
NULL),
|
|
|
|
HCI_ENTRY(HCF_READONLY|HCF_BORDER|HCF_ATTACH,
|
|
0,
|
|
idwAttachWell, 0,
|
|
idsAttachment, 0,
|
|
NULL),
|
|
|
|
HCI_ENTRY(HCF_READONLY|HCF_ADVANCED, // HCF_ADVANCED will hide it when empty
|
|
0,
|
|
idSecurity, 0,
|
|
idsSecurityField, NULL,
|
|
NULL),
|
|
};
|
|
|
|
static int rgIDTabOrderNewsSend[] =
|
|
{
|
|
idFromCombo, idADNewsgroups,
|
|
idTXTFollowupTo, idADCc,
|
|
idADReplyTo, idTXTDistribution,
|
|
idTXTKeywords, idTXTSubject,
|
|
idwAttachWell, idADApproved,
|
|
idTxtControl
|
|
};
|
|
|
|
static HCI rgNewsHeaderSend[]=
|
|
{
|
|
HCI_ENTRY(HCF_COMBO|HCF_ADVANCED|HCF_BORDER,
|
|
0,
|
|
idFromCombo, 0,
|
|
idsNewsServer, NULL,
|
|
NULL),
|
|
|
|
HCI_ENTRY(HCF_MULTILINE|HCF_HASBUTTON|HCF_NEWSPICK|HCF_BORDER,
|
|
0,
|
|
idADNewsgroups, idbtnTo,
|
|
idsNewsgroupsField, idsEmptyNewsgroups,
|
|
idsTTNewsgroups),
|
|
|
|
HCI_ENTRY(HCF_ADVANCED|HCF_HASBUTTON|HCF_NEWSPICK|HCF_MULTILINE|HCF_USECHARSET|HCF_BORDER,
|
|
0,
|
|
idTXTFollowupTo, idbtnFollowup,
|
|
idsFollowupToField, idsEmptyFollowupTo,
|
|
idsTTFollowup),
|
|
|
|
HCI_ENTRY(HCF_MULTILINE|HCF_ADDRWELL|HCF_HASBUTTON|HCF_ADDRBOOK|HCF_BORDER,
|
|
0,
|
|
idADCc, idbtnCc,
|
|
idsCcField, idsEmptyCc,
|
|
idsTTRecipients),
|
|
|
|
HCI_ENTRY(HCF_ADVANCED|HCF_ADDRWELL|HCF_HASBUTTON|HCF_ADDRBOOK|HCF_BORDER,
|
|
0,
|
|
idADReplyTo, idbtnReplyTo,
|
|
idsReplyToField, idsEmptyReplyTo,
|
|
idsTTReplyTo),
|
|
|
|
HCI_ENTRY(HCF_MULTILINE|HCF_ADVANCED|HCF_BORDER,
|
|
0,
|
|
idTXTDistribution, 0,
|
|
idsDistributionField, idsEmptyDistribution,
|
|
idsTTDistribution),
|
|
|
|
HCI_ENTRY(HCF_MULTILINE|HCF_ADVANCED|HCF_USECHARSET|HCF_BORDER,
|
|
0,
|
|
idTXTKeywords, 0,
|
|
idsKeywordsField, idsEmptyKeywords,
|
|
idsTTKeywords),
|
|
|
|
HCI_ENTRY(HCF_USECHARSET|HCF_BORDER,
|
|
0,
|
|
idTXTSubject, 0,
|
|
idsSubjectField, idsEmptySubject,
|
|
idsTTSubject),
|
|
|
|
HCI_ENTRY(HCF_BORDER|HCF_ATTACH,
|
|
0,
|
|
idwAttachWell, 0,
|
|
idsAttachment, 0,
|
|
idsTTAttachment),
|
|
|
|
HCI_ENTRY(HCF_ADVANCED|HCF_OPTIONAL,
|
|
OPT_NEWSMODERATOR,
|
|
idADApproved, 0,
|
|
idsApprovedField, idsEmptyApproved,
|
|
idsTTApproved),
|
|
|
|
HCI_ENTRY(HCF_ADVANCED|HCF_OPTIONAL,
|
|
OPT_NEWSCONTROLHEADER,
|
|
idTxtControl, 0,
|
|
idsControlField, idsEmptyControl,
|
|
idsTTControl),
|
|
|
|
};
|
|
|
|
static int rgIDTabOrderNewsRead[] =
|
|
{
|
|
idADFrom, idADReplyTo,
|
|
idTXTOrg, idTXTDate,
|
|
idADNewsgroups, idTXTFollowupTo,
|
|
idTXTDistribution, idTXTKeywords,
|
|
idTXTSubject, idwAttachWell,
|
|
idSecurity
|
|
};
|
|
|
|
static HCI rgNewsHeaderRead[]=
|
|
{
|
|
HCI_ENTRY(HCF_MULTILINE|HCF_READONLY|HCF_ADDRWELL,
|
|
0,
|
|
idADFrom, 0,
|
|
idsFromField, idsNoFromField,
|
|
NULL),
|
|
|
|
HCI_ENTRY(HCF_READONLY|HCF_ADVANCED|HCF_ADDRWELL,
|
|
0,
|
|
idADReplyTo, 0,
|
|
idsReplyToField, idsNotSpecified,
|
|
NULL),
|
|
|
|
HCI_ENTRY(HCF_READONLY|HCF_ADVANCED|HCF_USECHARSET,
|
|
0,
|
|
idTXTOrg, 0,
|
|
idsOrgField, idsNotSpecified,
|
|
NULL),
|
|
|
|
HCI_ENTRY(HCF_READONLY,
|
|
0,
|
|
idTXTDate, 0,
|
|
idsDateField, idsNotSpecified,
|
|
NULL),
|
|
|
|
HCI_ENTRY(HCF_MULTILINE|HCF_READONLY,
|
|
0,
|
|
idADNewsgroups, 0,
|
|
idsNewsgroupsField, idsNotSpecified,
|
|
NULL),
|
|
|
|
HCI_ENTRY(HCF_READONLY|HCF_ADVANCED,
|
|
0,
|
|
idTXTFollowupTo, 0,
|
|
idsFollowupToField, idsNotSpecified,
|
|
NULL),
|
|
|
|
HCI_ENTRY(HCF_MULTILINE|HCF_READONLY|HCF_ADVANCED,
|
|
0,
|
|
idTXTDistribution, 0,
|
|
idsDistributionField, idsNotSpecified,
|
|
NULL),
|
|
|
|
HCI_ENTRY(HCF_MULTILINE|HCF_READONLY|HCF_ADVANCED|HCF_USECHARSET,
|
|
0,
|
|
idTXTKeywords, 0,
|
|
idsKeywordsField, idsNotSpecified,
|
|
NULL),
|
|
|
|
HCI_ENTRY(HCF_READONLY|HCF_USECHARSET,
|
|
0,
|
|
idTXTSubject, 0,
|
|
idsSubjectField, idsEmptySubjectRO,
|
|
NULL),
|
|
|
|
HCI_ENTRY(HCF_READONLY|HCF_BORDER|HCF_ATTACH,
|
|
0,
|
|
idwAttachWell, 0,
|
|
idsAttachment, 0,
|
|
NULL),
|
|
|
|
HCI_ENTRY(HCF_READONLY|HCF_ADVANCED,
|
|
0,
|
|
idSecurity, 0,
|
|
idsSecurityField, NULL,
|
|
NULL),
|
|
};
|
|
|
|
|
|
// p r o t o t y p e s
|
|
void _ValidateNewsgroups(LPWSTR pszGroups);
|
|
INT_PTR CALLBACK _PlainWarnDlgProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam);
|
|
|
|
#ifdef DEBUG
|
|
void DEBUGHdrName(HWND hwnd);
|
|
|
|
void DEBUGDumpHdr(HWND hwnd, int cHdr, PHCI rgHCI)
|
|
{
|
|
PHCI phci;
|
|
char sz[cchHeaderMax+1];
|
|
RECT rc;
|
|
HWND hwndEdit;
|
|
|
|
#ifndef DEBUG_SIZINGCODE
|
|
return;
|
|
#endif
|
|
|
|
DOUTL(GEN_HEADER_DEBUG_LEVEL, "-----");
|
|
|
|
for (int i=0; i<(int)cHdr; i++)
|
|
{
|
|
phci=&rgHCI[i];
|
|
|
|
hwndEdit=GetDlgItem(hwnd, phci->idEdit);
|
|
|
|
GetChildRect(hwnd, hwndEdit, &rc);
|
|
DEBUGHdrName(hwndEdit);
|
|
wnsprintf(sz, ARRAYSIZE(sz), "\tat:(%d,%d) \tsize:(%d,%d)\r\n", rc.left, rc.top, rc.right-rc.left, rc.bottom-rc.top);
|
|
OutputDebugString(sz);
|
|
}
|
|
GetWindowRect(hwnd, &rc);
|
|
DOUTL(GEN_HEADER_DEBUG_LEVEL, "HeaderSize: (%d,%d)\r\n-----", rc.right-rc.left, rc.bottom-rc.top);
|
|
}
|
|
|
|
void DEBUGHdrName(HWND hwnd)
|
|
{
|
|
char sz[cchHeaderMax+1];
|
|
char *psz=0;
|
|
|
|
switch (GetDlgCtrlID(hwnd))
|
|
{
|
|
case idTXTSubject:
|
|
psz="Subject";
|
|
break;
|
|
|
|
case idTXTOrg:
|
|
psz="Org";
|
|
break;
|
|
|
|
case idADTo:
|
|
psz="To";
|
|
break;
|
|
|
|
case idADCc:
|
|
psz="Cc";
|
|
break;
|
|
|
|
case idADFrom:
|
|
psz="From";
|
|
break;
|
|
|
|
case idTXTDate:
|
|
psz="Date";
|
|
break;
|
|
|
|
case idTXTDistribution:
|
|
psz="Distribution";
|
|
break;
|
|
|
|
case idADApproved:
|
|
psz="Approved";
|
|
break;
|
|
|
|
case idADReplyTo:
|
|
psz="ReplyTo";
|
|
break;
|
|
|
|
case idTXTKeywords:
|
|
psz="Keywords";
|
|
break;
|
|
|
|
case idADNewsgroups:
|
|
psz="NewsGroup";
|
|
break;
|
|
|
|
case idTXTFollowupTo:
|
|
psz="FollowUp";
|
|
break;
|
|
|
|
default:
|
|
psz="<Unknown>";
|
|
break;
|
|
}
|
|
|
|
wnsprintf(sz, ARRAYSIZE(sz), "%s: ", psz);
|
|
OutputDebugString(sz);
|
|
}
|
|
#endif
|
|
|
|
// FHeader_Init
|
|
//
|
|
// Purpose: called to init and de-init global header stuff, eg.
|
|
// wndclasses, static data etc.
|
|
//
|
|
// Comments:
|
|
// TODO: defer this initialisation
|
|
//
|
|
BOOL FHeader_Init(BOOL fInit)
|
|
{
|
|
WNDCLASSW wc={0};
|
|
static BOOL s_fInited=FALSE;
|
|
BOOL fSucceeded = TRUE;
|
|
|
|
if (fInit)
|
|
{
|
|
if (s_fInited)
|
|
goto exit;
|
|
|
|
Assert(!g_pFieldSizeMgr);
|
|
|
|
g_pFieldSizeMgr = new CFieldSizeMgr;
|
|
if (!g_pFieldSizeMgr || FAILED(g_pFieldSizeMgr->Init()))
|
|
{
|
|
fSucceeded = FALSE;
|
|
goto exit;
|
|
}
|
|
|
|
wc.style = 0;
|
|
wc.lpfnWndProc = CNoteHdr::ExtCNoteHdrWndProc;
|
|
wc.hInstance = g_hInst;
|
|
wc.hCursor = LoadCursor(NULL, IDC_ARROW);
|
|
wc.hbrBackground = (HBRUSH)(COLOR_BTNFACE+1);
|
|
wc.lpszClassName = WC_ATHHEADER;
|
|
|
|
if (!RegisterClassWrapW(&wc))
|
|
{
|
|
fSucceeded = FALSE;
|
|
goto exit;
|
|
}
|
|
|
|
g_himlStatus=ImageList_LoadBitmap(g_hLocRes, MAKEINTRESOURCE(idbHeaderStatus), cxFlags, 0, RGB_TRANSPARENT);
|
|
if (!g_himlStatus)
|
|
{
|
|
fSucceeded = FALSE;
|
|
goto exit;
|
|
}
|
|
|
|
g_himlBtns=ImageList_LoadBitmap(g_hLocRes, MAKEINTRESOURCE(idbBtns), cxBtn, 0, RGB_TRANSPARENT);
|
|
if (!g_himlBtns)
|
|
{
|
|
fSucceeded = FALSE;
|
|
goto exit;
|
|
}
|
|
|
|
g_himlSecurity=ImageList_LoadBitmap(g_hLocRes, MAKEINTRESOURCE(idbSecurity), cxBtn, 0, RGB_TRANSPARENT);
|
|
if (!g_himlSecurity)
|
|
{
|
|
fSucceeded = FALSE;
|
|
goto exit;
|
|
}
|
|
|
|
ImageList_SetBkColor(g_himlStatus, CLR_NONE);
|
|
ImageList_SetBkColor(g_himlBtns, CLR_NONE);
|
|
ImageList_SetBkColor(g_himlSecurity, CLR_NONE);
|
|
|
|
AthLoadString(idsStatusFlagged, g_szStatFlagged, cchHeaderMax);
|
|
AthLoadString(idsStatusLowPri, g_szStatLowPri, cchHeaderMax);
|
|
AthLoadString(idsStatusHighPri, g_szStatHighPri, cchHeaderMax);
|
|
AthLoadString(idsStatusWatched, g_szStatWatched, cchHeaderMax);
|
|
AthLoadString(idsStatusIgnored, g_szStatIgnored, cchHeaderMax);
|
|
AthLoadString(idsStatusFormat1, g_szStatFormat1, cchHeaderMax);
|
|
AthLoadString(idsStatusFormat2, g_szStatFormat2, cchHeaderMax);
|
|
AthLoadString(idsStatusFormat3, g_szStatFormat3, cchHeaderMax);
|
|
AthLoadString(idsStatusUnsafeAttach, g_szStatUnsafeAtt, cchHeaderMax);
|
|
|
|
s_fInited=TRUE;
|
|
|
|
|
|
}
|
|
// De-Init ******
|
|
else
|
|
{
|
|
UnregisterClassWrapW(WC_ATHHEADER, g_hInst);
|
|
if (g_himlStatus)
|
|
{
|
|
ImageList_Destroy(g_himlStatus);
|
|
g_himlStatus = 0;
|
|
}
|
|
if (g_himlBtns)
|
|
{
|
|
ImageList_Destroy(g_himlBtns);
|
|
g_himlBtns = 0;
|
|
}
|
|
if (g_himlSecurity)
|
|
{
|
|
ImageList_Destroy(g_himlSecurity);
|
|
g_himlSecurity = 0;
|
|
}
|
|
s_fInited=FALSE;
|
|
|
|
SafeRelease(g_pFieldSizeMgr);
|
|
}
|
|
|
|
exit:
|
|
if (!fSucceeded)
|
|
SafeRelease(g_pFieldSizeMgr);
|
|
|
|
return fSucceeded;
|
|
}
|
|
|
|
|
|
HRESULT CreateInstance_Envelope(IUnknown *pUnkOuter, IUnknown **ppUnknown)
|
|
{
|
|
// Locals
|
|
HRESULT hr=S_OK;
|
|
CNoteHdr *pNew=NULL;
|
|
|
|
// Trace
|
|
TraceCall("CreateInstance_Envelope");
|
|
|
|
if (NULL != pUnkOuter)
|
|
return CLASS_E_NOAGGREGATION;
|
|
|
|
// Invalid Arg
|
|
Assert(NULL != ppUnknown && NULL == pUnkOuter);
|
|
|
|
// Create
|
|
IF_NULLEXIT(pNew = new CNoteHdr);
|
|
|
|
// Return the Innter
|
|
*ppUnknown = (IMsoEnvelope*) pNew;
|
|
|
|
exit:
|
|
// Done
|
|
return hr;
|
|
}
|
|
|
|
|
|
CNoteHdr::CNoteHdr()
|
|
{
|
|
// Not initialised
|
|
// Member: Initialised In:
|
|
// --------------------+---------------------------
|
|
// m_wNoteType Finit
|
|
|
|
m_cRef = 1;
|
|
m_cHCI = 0;
|
|
m_cAccountIDs = 0;
|
|
m_iCurrComboIndex = 0;
|
|
|
|
m_hwnd = 0;
|
|
m_hwndLastFocus = 0;
|
|
m_hwndRebar = 0;
|
|
|
|
m_pri = priNorm; // default to Normal Pri
|
|
m_cfAccept = CF_NULL;
|
|
m_ntNote = OENA_COMPOSE;
|
|
|
|
m_fMail = TRUE;
|
|
m_fVCard = FALSE;
|
|
m_fDirty = FALSE;
|
|
m_fInSize = FALSE;
|
|
m_fFlagged = FALSE;
|
|
m_fAdvanced = FALSE;
|
|
m_fResizing = FALSE;
|
|
m_fUIActive = FALSE;
|
|
m_fDigSigned = FALSE;
|
|
m_fEncrypted = FALSE;
|
|
m_fSkipLayout = TRUE; // Skip layout until after load
|
|
m_fSignTrusted = TRUE;
|
|
m_fOfficeInit = FALSE;
|
|
m_fStillLoading = TRUE;
|
|
m_fEncryptionOK = TRUE;
|
|
m_fHandleChange = TRUE;
|
|
m_fAutoComplete = FALSE;
|
|
m_fSendImmediate = FALSE;
|
|
m_fVCardSave = !m_fVCard;
|
|
m_fSecurityInited = FALSE;
|
|
m_fAddressesChanged = FALSE;
|
|
m_fForceEncryption = FALSE;
|
|
m_fThisHeadDigSigned = FALSE;
|
|
m_fThisHeadEncrypted = FALSE;
|
|
m_fDropTargetRegister = FALSE;
|
|
|
|
m_pMsg = NULL;
|
|
m_lpWab = NULL;
|
|
m_rgHCI = NULL;
|
|
m_hwndTT = NULL;
|
|
m_pTable = NULL;
|
|
m_lpWabal = NULL;
|
|
m_pszRefs = NULL;
|
|
m_pMsgSend = NULL;
|
|
m_hCharset = NULL;
|
|
m_pAccount = NULL;
|
|
m_hInitRef = NULL;
|
|
m_lpAttMan = NULL;
|
|
m_hwndParent = NULL;
|
|
m_pAddrWells = NULL;
|
|
m_hwndToolbar = NULL;
|
|
m_pHeaderSite = NULL;
|
|
m_pEnvelopeSite = NULL;
|
|
m_pMsoComponentMgr = NULL;
|
|
m_lpszSecurityField = NULL;
|
|
m_ppAccountIDs = NULL;
|
|
*m_szLastLang = 0;
|
|
|
|
m_MarkType = MARK_MESSAGE_NORMALTHREAD;
|
|
m_hwndOldCapture = NULL;
|
|
m_dwCurrentBtn = HDRCB_NO_BUTTON;
|
|
m_dwClickedBtn = HDRCB_NO_BUTTON;
|
|
m_dwEffect = 0;
|
|
m_cCapture = 0;
|
|
m_dwDragType = 0;
|
|
m_dwComponentMgrID = 0;
|
|
m_dwIMEStartCount = 0;
|
|
m_dwFontNotify = 0;
|
|
|
|
m_dxTBOffset = 0;
|
|
m_grfKeyState = 0;
|
|
m_cxLeftMargin = 0;
|
|
m_himl = NULL;
|
|
m_fPoster = FALSE;
|
|
|
|
ZeroMemory(&m_SecState, sizeof(m_SecState));
|
|
}
|
|
|
|
CNoteHdr::~CNoteHdr()
|
|
{
|
|
Assert (m_pMsgSend==NULL);
|
|
|
|
if (m_hwnd)
|
|
DestroyWindow(m_hwnd);
|
|
|
|
ReleaseObj(m_pTable);
|
|
ReleaseObj(m_lpWabal);
|
|
ReleaseObj(m_lpWab);
|
|
SafeMemFree(m_pszRefs);
|
|
ReleaseObj(m_pAccount);
|
|
CleanupSECSTATE(&m_SecState);
|
|
ReleaseObj(m_lpAttMan);
|
|
ReleaseObj(m_pMsg);
|
|
SafeMemFree(m_lpszSecurityField);
|
|
|
|
if (m_pAddrWells)
|
|
delete m_pAddrWells;
|
|
|
|
if (m_himl)
|
|
ImageList_Destroy(m_himl);
|
|
|
|
if (m_fOfficeInit)
|
|
HrOfficeInitialize(FALSE);
|
|
|
|
if (m_cAccountIDs)
|
|
{
|
|
while (m_cAccountIDs--)
|
|
SafeMemFree(m_ppAccountIDs[m_cAccountIDs]);
|
|
}
|
|
SafeMemFree(m_ppAccountIDs);
|
|
}
|
|
|
|
|
|
ULONG CNoteHdr::AddRef()
|
|
{
|
|
return ++m_cRef;
|
|
}
|
|
|
|
ULONG CNoteHdr::Release()
|
|
{
|
|
if (--m_cRef==0)
|
|
{
|
|
delete this;
|
|
return 0;
|
|
}
|
|
return m_cRef;
|
|
}
|
|
|
|
|
|
HRESULT CNoteHdr::QueryInterface(REFIID riid, LPVOID *lplpObj)
|
|
{
|
|
if (!lplpObj)
|
|
return E_INVALIDARG;
|
|
|
|
*lplpObj = NULL;
|
|
|
|
if (IsEqualIID(riid, IID_IUnknown))
|
|
*lplpObj = (LPVOID)this;
|
|
|
|
else if (IsEqualIID(riid, IID_IHeader))
|
|
*lplpObj = (LPVOID)(LPHEADER)this;
|
|
|
|
else if (IsEqualIID(riid, IID_IMsoEnvelope))
|
|
*lplpObj = (LPVOID)(IMsoEnvelope*)this;
|
|
|
|
else if (IsEqualIID(riid, IID_IMsoComponent))
|
|
*lplpObj = (LPVOID)(IMsoComponent*)this;
|
|
|
|
else if (IsEqualIID(riid, IID_IPersistMime))
|
|
*lplpObj = (LPVOID)(LPPERSISTMIME)this;
|
|
|
|
else if (IsEqualIID(riid, IID_IOleCommandTarget))
|
|
*lplpObj = (LPVOID)(LPOLECOMMANDTARGET)this;
|
|
|
|
else if (IsEqualIID(riid, IID_IDropTarget))
|
|
*lplpObj = (LPVOID)(IDropTarget*)this;
|
|
|
|
else if (IsEqualIID(riid, IID_IFontCacheNotify))
|
|
*lplpObj = (LPVOID)(IFontCacheNotify*)this;
|
|
|
|
else
|
|
return E_NOINTERFACE;
|
|
|
|
AddRef();
|
|
return NOERROR;
|
|
}
|
|
|
|
// IOleCommandTarget
|
|
HRESULT CNoteHdr::QueryStatus(const GUID *pguidCmdGroup, ULONG cCmds, OLECMD rgCmds[], OLECMDTEXT *pCmdText)
|
|
{
|
|
ULONG ul;
|
|
HWND hwndFocus = GetFocus();
|
|
DWORD dwFlags = 0;
|
|
BOOL fFound = FALSE;
|
|
|
|
if (!rgCmds)
|
|
return E_INVALIDARG;
|
|
|
|
for (int i=0; i<(int)m_cHCI; i++)
|
|
{
|
|
// if it's in our control-list and not a combobox
|
|
if (hwndFocus == GetDlgItem(m_hwnd, m_rgHCI[i].idEdit) &&
|
|
!(m_rgHCI[i].dwFlags & HCF_COMBO))
|
|
{
|
|
GetEditDisableFlags(hwndFocus, &dwFlags);
|
|
fFound = TRUE;
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (pguidCmdGroup == NULL)
|
|
{
|
|
for (ul=0;ul<cCmds; ul++)
|
|
{
|
|
switch (rgCmds[ul].cmdID)
|
|
{
|
|
|
|
case cmdidSend:
|
|
case cmdidCheckNames:
|
|
case cmdidAttach:
|
|
case cmdidOptions:
|
|
case cmdidSelectNames:
|
|
case cmdidFocusTo:
|
|
case cmdidFocusCc:
|
|
case cmdidFocusSubject:
|
|
// office commands enabled if we have an env-site
|
|
rgCmds[ul].cmdf = m_pEnvelopeSite ? OLECMDF_ENABLED|OLECMDF_SUPPORTED : 0;
|
|
break;
|
|
|
|
case OLECMDID_CUT:
|
|
case OLECMDID_PASTE:
|
|
case OLECMDID_COPY:
|
|
case OLECMDID_UNDO:
|
|
case OLECMDID_SELECTALL:
|
|
if (fFound)
|
|
HrQueryToolbarButtons(dwFlags, pguidCmdGroup, &rgCmds[ul]);
|
|
break;
|
|
|
|
default:
|
|
rgCmds[ul].cmdf = 0;
|
|
break;
|
|
}
|
|
}
|
|
|
|
return NOERROR;
|
|
}
|
|
else if (IsEqualGUID(CMDSETID_OutlookExpress, *pguidCmdGroup))
|
|
{
|
|
BOOL fReadOnly = IsReadOnly(),
|
|
fMailAndNotReadOnly = m_fMail && !fReadOnly;
|
|
UINT pri;
|
|
|
|
GetPriority(&pri);
|
|
|
|
for (ULONG ul = 0; ul < cCmds; ul++)
|
|
{
|
|
ULONG cmdID = rgCmds[ul].cmdID;
|
|
if (0 != rgCmds[ul].cmdf)
|
|
continue;
|
|
|
|
switch (cmdID)
|
|
{
|
|
case ID_SELECT_RECIPIENTS:
|
|
case ID_SELECT_NEWSGROUPS:
|
|
case ID_INSERT_ATTACHMENT:
|
|
rgCmds[ul].cmdf = QS_ENABLED(!fReadOnly);
|
|
break;
|
|
|
|
case ID_INSERT_CONTACT_INFO:
|
|
HrGetVCardState(&rgCmds[ul].cmdf);
|
|
break;
|
|
|
|
case ID_ENCRYPT:
|
|
if(m_fForceEncryption)
|
|
{
|
|
if(!m_fDigSigned)
|
|
rgCmds[ul].cmdf = QS_ENABLECHECK(fMailAndNotReadOnly, m_fEncrypted);
|
|
else
|
|
break;
|
|
}
|
|
else
|
|
rgCmds[ul].cmdf = QS_ENABLECHECK(fMailAndNotReadOnly, m_fEncrypted);
|
|
break;
|
|
|
|
case ID_DIGITALLY_SIGN:
|
|
rgCmds[ul].cmdf = QS_ENABLECHECK(!fReadOnly && 0 == (g_dwAthenaMode & MODE_NEWSONLY), m_fDigSigned);
|
|
break;
|
|
|
|
case ID_SET_PRIORITY:
|
|
case ID_POPUP_PRIORITY:
|
|
rgCmds[ul].cmdf = QS_ENABLED(fMailAndNotReadOnly);
|
|
break;
|
|
|
|
case ID_PRIORITY_HIGH:
|
|
case ID_PRIORITY_NORMAL:
|
|
case ID_PRIORITY_LOW:
|
|
rgCmds[ul].cmdf = QS_ENABLERADIO(fMailAndNotReadOnly, (pri == UINT(ID_PRIORITY_LOW - cmdID)));
|
|
break;
|
|
|
|
case ID_CHECK_NAMES:
|
|
rgCmds[ul].cmdf = QS_ENABLED(TRUE);
|
|
break;
|
|
|
|
case ID_FULL_HEADERS:
|
|
rgCmds[ul].cmdf = QS_ENABLECHECK(TRUE, m_fAdvanced);
|
|
break;
|
|
|
|
case ID_CUT:
|
|
case ID_COPY:
|
|
case ID_NOTE_COPY:
|
|
case ID_PASTE:
|
|
case ID_UNDO:
|
|
case ID_SELECT_ALL:
|
|
if (fFound)
|
|
HrQueryToolbarButtons(dwFlags, pguidCmdGroup, &rgCmds[ul]);
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
else if (IsEqualGUID(*pguidCmdGroup, CGID_Envelope))
|
|
{
|
|
for (ul=0;ul<cCmds; ul++)
|
|
{
|
|
switch (rgCmds[ul].cmdID)
|
|
{
|
|
case MSOEENVCMDID_VCARD:
|
|
HrGetVCardState(&rgCmds[ul].cmdf);
|
|
break;
|
|
|
|
case MSOEENVCMDID_DIGSIGN:
|
|
rgCmds[ul].cmdf = QS_ENABLECHECK(!IsReadOnly(), m_fDigSigned);
|
|
break;
|
|
|
|
case MSOEENVCMDID_ENCRYPT:
|
|
if(m_fForceEncryption)
|
|
{
|
|
if(!m_fDigSigned)
|
|
rgCmds[ul].cmdf = QS_ENABLECHECK(m_fMail && !IsReadOnly(), m_fEncrypted);
|
|
else
|
|
break;
|
|
}
|
|
else
|
|
rgCmds[ul].cmdf = QS_ENABLECHECK(m_fMail && !IsReadOnly(), m_fEncrypted);
|
|
break;
|
|
|
|
case MSOEENVCMDID_DIRTY:
|
|
{
|
|
BOOL fDirty;
|
|
fDirty = m_fDirty || (m_lpAttMan && m_lpAttMan->HrIsDirty()==S_OK);
|
|
|
|
if (fDirty)
|
|
rgCmds[ul].cmdf = MSOCMDF_ENABLED;
|
|
else
|
|
rgCmds[ul].cmdf = 0;
|
|
}
|
|
break;
|
|
|
|
case MSOEENVCMDID_SEND:
|
|
case MSOEENVCMDID_CHECKNAMES:
|
|
case MSOEENVCMDID_AUTOCOMPLETE:
|
|
case MSOEENVCMDID_SETACTION:
|
|
case MSOEENVCMDID_PRIORITY:
|
|
rgCmds[ul].cmdf = MSOCMDF_ENABLED;
|
|
break;
|
|
|
|
default:
|
|
rgCmds[ul].cmdf = 0;
|
|
break;
|
|
}
|
|
}
|
|
|
|
return NOERROR;
|
|
}
|
|
|
|
return OLECMDERR_E_UNKNOWNGROUP;
|
|
}
|
|
|
|
|
|
// IOleCommandTarget
|
|
HRESULT CNoteHdr::Exec(const GUID *pguidCmdGroup, DWORD nCmdID, DWORD nCmdExecOpt, VARIANTARG *pvaIn, VARIANTARG *pvaOut)
|
|
{
|
|
HRESULT hr = NOERROR;
|
|
HWND hwndFocus;
|
|
UINT msg = 0;
|
|
WPARAM wParam = 0;
|
|
LPARAM lParam = 0;
|
|
BOOL fOfficeCmd=FALSE;
|
|
|
|
if (pguidCmdGroup == NULL)
|
|
{
|
|
switch (nCmdID)
|
|
{
|
|
case OLECMDID_CUT:
|
|
msg = WM_CUT;
|
|
break;
|
|
|
|
case OLECMDID_PASTE:
|
|
msg = WM_PASTE;
|
|
break;
|
|
|
|
case OLECMDID_COPY:
|
|
msg = WM_COPY;
|
|
break;
|
|
|
|
case OLECMDID_UNDO:
|
|
msg = WM_UNDO;
|
|
break;
|
|
|
|
case OLECMDID_SELECTALL:
|
|
msg = EM_SETSEL;
|
|
lParam = (LPARAM)(INT)-1;
|
|
break;
|
|
|
|
case OLECMDID_CLEARSELECTION:
|
|
msg = WM_CLEAR;
|
|
break;
|
|
|
|
default:
|
|
hr = _ConvertOfficeCmdIDToOE(&nCmdID);
|
|
if (hr==S_OK)
|
|
{ //if sucess, nCmdId now points to an OE command
|
|
fOfficeCmd = TRUE;
|
|
goto oe_cmd;
|
|
}
|
|
else
|
|
hr = OLECMDERR_E_NOTSUPPORTED;
|
|
}
|
|
|
|
if (0 != msg)
|
|
{
|
|
hwndFocus = GetFocus();
|
|
if (IsChild(m_hwnd, hwndFocus))
|
|
SendMessage(hwndFocus, msg, wParam, lParam);
|
|
}
|
|
return hr;
|
|
}
|
|
else if (IsEqualGUID(*pguidCmdGroup, CGID_Envelope))
|
|
{
|
|
oe_cmd:
|
|
switch (nCmdID)
|
|
{
|
|
case MSOEENVCMDID_ATTACHFILE:
|
|
if (m_lpAttMan)
|
|
m_lpAttMan->WMCommand(0, ID_INSERT_ATTACHMENT, NULL);
|
|
break;
|
|
|
|
case MSOEENVCMDID_FOCUSTO:
|
|
::SetFocus(GetDlgItem(m_hwnd, idADTo));
|
|
break;
|
|
|
|
case MSOEENVCMDID_FOCUSCC:
|
|
::SetFocus(GetDlgItem(m_hwnd, idADCc));
|
|
break;
|
|
|
|
case MSOEENVCMDID_FOCUSSUBJ:
|
|
::SetFocus(GetDlgItem(m_hwnd, idTXTSubject));
|
|
break;
|
|
|
|
case MSOEENVCMDID_SEND:
|
|
if (MSOCMDEXECOPT_DONTPROMPTUSER == nCmdExecOpt)
|
|
m_fSendImmediate = TRUE;
|
|
else
|
|
m_fSendImmediate = FALSE;
|
|
|
|
hr = HrSend();
|
|
break;
|
|
|
|
case MSOEENVCMDID_NEWS:
|
|
m_fMail = FALSE;
|
|
break;
|
|
|
|
case MSOEENVCMDID_CHECKNAMES:
|
|
hr = HrCheckNames((MSOCMDEXECOPT_PROMPTUSER == nCmdExecOpt)? FALSE: TRUE, TRUE);
|
|
if (!m_fMail)
|
|
{
|
|
hr = HrCheckGroups(FALSE);
|
|
if (hrNoRecipients == hr)
|
|
hr = S_OK;
|
|
}
|
|
break;
|
|
|
|
case MSOEENVCMDID_AUTOCOMPLETE:
|
|
m_fAutoComplete = TRUE;
|
|
break;
|
|
|
|
case MSOEENVCMDID_VIEWCONTACTS:
|
|
hr = HrViewContacts();
|
|
break;
|
|
|
|
case MSOEENVCMDID_DIGSIGN:
|
|
hr = HrHandleSecurityIDMs(TRUE);
|
|
break;
|
|
case MSOEENVCMDID_ENCRYPT:
|
|
hr = HrHandleSecurityIDMs(FALSE);
|
|
break;
|
|
|
|
case MSOEENVCMDID_SETACTION:
|
|
if (pvaIn->vt == VT_I4)
|
|
m_ntNote = pvaIn->lVal;
|
|
break;
|
|
|
|
case MSOEENVCMDID_SELECTRECIPIENTS:
|
|
hr = HrPickNames(0);
|
|
break;
|
|
|
|
case MSOEENVCMDID_ADDSENDER:
|
|
hr = HrAddSender();
|
|
break;
|
|
|
|
case MSOEENVCMDID_ADDALLONTO:
|
|
hr = HrAddAllOnToList();
|
|
break;
|
|
|
|
case MSOEENVCMDID_PICKNEWSGROUPS:
|
|
if (!m_fMail)
|
|
{
|
|
if (idTXTFollowupTo == GetWindowLong(GetFocus(), GWL_ID))
|
|
OnButtonClick(idbtnFollowup);
|
|
else
|
|
OnButtonClick(idbtnTo);
|
|
}
|
|
break;
|
|
|
|
case MSOEENVCMDID_VCARD:
|
|
m_fVCard = !m_fVCard;
|
|
hr = HrOnOffVCard();
|
|
break;
|
|
|
|
case MSOEENVCMDID_DIRTY:
|
|
_ClearDirtyFlag();
|
|
break;
|
|
|
|
default:
|
|
hr = OLECMDERR_E_NOTSUPPORTED;
|
|
}
|
|
|
|
// suppress OE errors when running under office-envelope
|
|
if (fOfficeCmd && hr != OLECMDERR_E_NOTSUPPORTED)
|
|
hr = S_OK;
|
|
|
|
return hr;
|
|
}
|
|
|
|
return OLECMDERR_E_UNKNOWNGROUP;
|
|
}
|
|
|
|
|
|
BOOL CNoteHdr::IsReplyNote()
|
|
{
|
|
return (m_ntNote==OENA_REPLYTOAUTHOR || m_ntNote==OENA_REPLYTONEWSGROUP || m_ntNote==OENA_REPLYALL);
|
|
}
|
|
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
// IPersistMime::Load
|
|
// before calling this function, need to set m_ntNote by MSOEENVCMDID_SETACTION.
|
|
HRESULT CNoteHdr::Load(LPMIMEMESSAGE pMsg)
|
|
{
|
|
HRESULT hr=S_OK;
|
|
HCHARSET hCharset = NULL;
|
|
PROPVARIANT var;
|
|
|
|
Assert(pMsg);
|
|
if (!pMsg)
|
|
return E_INVALIDARG;
|
|
|
|
m_fStillLoading = TRUE;
|
|
|
|
m_fSkipLayout = TRUE;
|
|
|
|
m_fHandleChange = TRUE;
|
|
|
|
ReplaceInterface(m_pMsg, pMsg);
|
|
|
|
pMsg->GetCharset(&hCharset);
|
|
|
|
// bug #43295
|
|
// If we are in same codepages, we can pass FALSE to UpdateCharSetFont().
|
|
// But if we are in the differnet codepages, we need to update font to
|
|
// display the header (decoded) in the correct codepage.
|
|
// UpdateCharSetFonts(hCharset, FALSE);
|
|
if (hCharset)
|
|
HrUpdateCharSetFonts(hCharset, hCharset != m_hCharset);
|
|
|
|
// If there is an account set in the message, make sure that we use it.
|
|
var.vt = VT_LPSTR;
|
|
if (SUCCEEDED(pMsg->GetProp(PIDTOSTR(PID_ATT_ACCOUNTID), NOFLAGS, &var)))
|
|
{
|
|
IImnAccount *pAcct = NULL;
|
|
if (SUCCEEDED(g_pAcctMan->FindAccount(AP_ACCOUNT_ID, var.pszVal, &pAcct)))
|
|
{
|
|
HWND hwndCombo = GetDlgItem(m_hwnd, idFromCombo);
|
|
if (hwndCombo)
|
|
{
|
|
int cEntries = ComboBox_GetCount(hwndCombo);
|
|
for (int i = 0; i < cEntries; i++)
|
|
{
|
|
LPSTR idStr = (LPSTR)ComboBox_GetItemData(hwndCombo, i);
|
|
if (0 == lstrcmp(idStr, var.pszVal))
|
|
{
|
|
ComboBox_SetCurSel(hwndCombo, i);
|
|
m_iCurrComboIndex = i;
|
|
ReplaceInterface(m_pAccount, pAcct);
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
else
|
|
ReplaceInterface(m_pAccount, pAcct);
|
|
|
|
pAcct->Release();
|
|
}
|
|
SafeMemFree(var.pszVal);
|
|
}
|
|
|
|
HrInitSecurity();
|
|
HrUpdateSecurity(pMsg);
|
|
|
|
// Modify subject if need to add a Fw: or a Re:
|
|
if (m_ntNote==OENA_FORWARD || IsReplyNote())
|
|
HrSetReplySubject(pMsg, OENA_FORWARD != m_ntNote);
|
|
else
|
|
HrSetupNote(pMsg);
|
|
|
|
SetReferences(pMsg);
|
|
|
|
if (m_fMail)
|
|
hr = HrSetMailRecipients(pMsg);
|
|
else
|
|
hr = HrSetNewsRecipients(pMsg);
|
|
|
|
if (OENA_READ == m_ntNote)
|
|
_SetEmptyFieldStrings();
|
|
|
|
// Update fiels, which depends from language
|
|
_UpdateTextFields(FALSE);
|
|
|
|
// setup priority, default to normal if a reply
|
|
if (!IsReplyNote())
|
|
HrSetPri(pMsg);
|
|
// on reply's auto add to the wab
|
|
else
|
|
HrAutoAddToWAB();
|
|
|
|
HrClearUndoStack();
|
|
|
|
m_fSkipLayout = FALSE;
|
|
ReLayout();
|
|
|
|
m_fDirty=FALSE;
|
|
if (m_pHeaderSite)
|
|
m_pHeaderSite->Update();
|
|
|
|
return hr;
|
|
}
|
|
|
|
void CNoteHdr::_SetEmptyFieldStrings(void)
|
|
{
|
|
PHCI phci = m_rgHCI;
|
|
|
|
AssertSz((OENA_READ == m_ntNote), "Should only get here in a read note.");
|
|
|
|
// No longer want EN_CHANGE messages to be handled in the richedits. At this
|
|
// point we will be setting text in the edits but don't want the phci->fEmpty
|
|
// to be set. That message causes the phci->fEmpty to be set.
|
|
m_fHandleChange = FALSE;
|
|
for (int i = 0; (ULONG)i < m_cHCI; i++, phci++)
|
|
if (phci->fEmpty)
|
|
{
|
|
if (0 == (phci->dwFlags & (HCF_COMBO|HCF_ATTACH)))
|
|
HdrSetRichEditText(GetDlgItem(m_hwnd, phci->idEdit), phci->szEmpty, FALSE);
|
|
else
|
|
SetWindowTextWrapW(GetDlgItem(m_hwnd, phci->idEdit), phci->szEmpty);
|
|
}
|
|
}
|
|
|
|
HRESULT CNoteHdr::_AttachVCard(IMimeMessage *pMsg)
|
|
{
|
|
HRESULT hr = 0;
|
|
LPWAB lpWab = 0;
|
|
TCHAR szVCardName[MAX_PATH],
|
|
szTempDir[MAX_PATH],
|
|
szVCardTempFile[MAX_PATH],
|
|
szVCFName[MAX_PATH];
|
|
UINT uFile=0;
|
|
INT iLen=0;
|
|
LPTSTR lptstr = NULL;
|
|
LPSTREAM pstmFile=NULL,
|
|
pstmCopy=NULL;
|
|
|
|
*szVCardName = 0;
|
|
*szTempDir = 0;
|
|
*szVCardTempFile = 0;
|
|
*szVCFName = 0;
|
|
|
|
if (m_lpAttMan && (S_OK == m_lpAttMan->HrCheckVCardExists(m_fMail)))
|
|
goto error;
|
|
|
|
hr = HrCreateWabObject(&lpWab);
|
|
if(FAILED(hr))
|
|
goto error;
|
|
|
|
GetOption(m_fMail?OPT_MAIL_VCARDNAME:OPT_NEWS_VCARDNAME, szVCardName, MAX_PATH);
|
|
|
|
if(*szVCardName == '\0')
|
|
{
|
|
hr = E_FAIL;
|
|
goto error;
|
|
}
|
|
|
|
GetTempPath(sizeof(szTempDir), szTempDir);
|
|
|
|
uFile = GetTempFileName(szTempDir, "VCF", 0, szVCardTempFile);
|
|
if (uFile == 0)
|
|
{
|
|
hr = E_FAIL;
|
|
goto error;
|
|
}
|
|
|
|
hr = lpWab->HrCreateVCardFile(szVCardName, szVCardTempFile);
|
|
if(FAILED(hr))
|
|
goto error;
|
|
|
|
hr = OpenFileStream((LPSTR)szVCardTempFile, OPEN_EXISTING, GENERIC_READ, &pstmFile);
|
|
if(FAILED(hr))
|
|
goto error;
|
|
|
|
hr = MimeOleCreateVirtualStream(&pstmCopy);
|
|
if(FAILED(hr))
|
|
goto error;
|
|
|
|
hr = HrCopyStream(pstmFile, pstmCopy, NULL);
|
|
if(FAILED(hr))
|
|
goto error;
|
|
|
|
wnsprintf(szVCFName, ARRAYSIZE(szVCFName), "%s%s", szVCardName, ".vcf");
|
|
|
|
hr = pMsg->AttachFile(szVCFName, pstmCopy, FALSE);
|
|
if(FAILED(hr))
|
|
goto error;
|
|
|
|
error:
|
|
ReleaseObj(pstmFile);
|
|
ReleaseObj(pstmCopy);
|
|
ReleaseObj(lpWab);
|
|
|
|
DeleteFile(szVCardTempFile);
|
|
return hr;
|
|
}
|
|
|
|
// IPersistMime::Save
|
|
HRESULT CNoteHdr::Save(LPMIMEMESSAGE pMsg, DWORD dwFlags)
|
|
{
|
|
HRESULT hr = NOERROR;
|
|
BOOL fSkipCheck = FALSE;
|
|
|
|
Assert(m_lpWabal);
|
|
|
|
// If sending, then previously did a CheckNames passing FALSE. If get here,
|
|
// then either all the names are resolved, or we are not sending so don't care
|
|
// what error codes are returned.
|
|
HrCheckNames(TRUE, FALSE);
|
|
|
|
// RAID 41350. If the save fails after leaving the header, the header
|
|
// recipients might be in a bad state. Make sure that they are resolved again
|
|
// after the save.
|
|
m_fAddressesChanged = TRUE;
|
|
|
|
// Is the security inited???
|
|
if(dwFlags != 0)
|
|
m_fSecurityInited = FALSE;
|
|
|
|
// This call will check if the dialog has been shown or if we are not mime and
|
|
// therefore should not show the dialog either.
|
|
if (m_pHeaderSite)
|
|
fSkipCheck = (S_OK != m_pHeaderSite->CheckCharsetConflict());
|
|
|
|
if (fSkipCheck)
|
|
{
|
|
IF_FAILEXIT(hr = _UnicodeSafeSave(pMsg, FALSE));
|
|
|
|
// Ignore any charset conflict errors.
|
|
hr = S_OK;
|
|
}
|
|
else
|
|
{
|
|
IF_FAILEXIT(hr = _UnicodeSafeSave(pMsg, TRUE));
|
|
|
|
if (MIME_S_CHARSET_CONFLICT == hr)
|
|
{
|
|
int ret;
|
|
PROPVARIANT Variant;
|
|
HCHARSET hCharset;
|
|
|
|
// Setup the Variant
|
|
Variant.vt = VT_UI4;
|
|
|
|
if (m_pEnvelopeSite && m_fShowedUnicodeDialog)
|
|
ret = m_iUnicodeDialogResult;
|
|
else
|
|
{
|
|
ret = IntlCharsetConflictDialogBox();
|
|
|
|
if (m_pEnvelopeSite)
|
|
{
|
|
m_fShowedUnicodeDialog = TRUE;
|
|
m_iUnicodeDialogResult = ret;
|
|
}
|
|
}
|
|
|
|
// Save As Is...
|
|
if (ret == IDOK)
|
|
{
|
|
IF_FAILEXIT(hr = _UnicodeSafeSave(pMsg, FALSE));
|
|
|
|
// User choose to send as is. Bail out and pretend no charset conflict
|
|
hr = S_OK;
|
|
}
|
|
// Save as Unicode
|
|
else if (ret == idcSendAsUnicode)
|
|
{
|
|
// User choose to send as Unicode (UTF8). set new charset and resnd
|
|
hCharset = GetMimeCharsetFromCodePage(CP_UTF8);
|
|
if (m_pHeaderSite)
|
|
m_pHeaderSite->ChangeCharset(hCharset);
|
|
else
|
|
{
|
|
pMsg->SetCharset(hCharset, CSET_APPLY_ALL);
|
|
ChangeLanguage(m_pMsg);
|
|
|
|
// bobn [6/23/99] Raid 77019
|
|
// If we switch to unicode and we're a word note, we
|
|
// need to remember that we're unicode so that we
|
|
// will not have the body encoding out of sync with
|
|
// the header encoding
|
|
if (m_pEnvelopeSite)
|
|
m_hCharset = hCharset;
|
|
}
|
|
IF_FAILEXIT(hr = _UnicodeSafeSave(pMsg, FALSE));
|
|
|
|
Assert(MIME_S_CHARSET_CONFLICT != hr);
|
|
}
|
|
else
|
|
{
|
|
// return to edit mode and bail out
|
|
hr = MAPI_E_USER_CANCEL;
|
|
goto exit;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
IF_FAILEXIT(hr = _UnicodeSafeSave(pMsg, FALSE));
|
|
Assert(MIME_S_CHARSET_CONFLICT != hr);
|
|
}
|
|
}
|
|
|
|
exit:
|
|
|
|
return hr;
|
|
}
|
|
|
|
HRESULT CNoteHdr::_UnicodeSafeSave(IMimeMessage *pMsg, BOOL fCheckConflictOnly)
|
|
{
|
|
HRESULT hr = S_OK;
|
|
UINT cpID = 0;
|
|
WCHAR wsz[cchMaxSubject+1];
|
|
PROPVARIANT rVariant;
|
|
SYSTEMTIME st;
|
|
|
|
HdrGetRichEditText(GetDlgItem(m_hwnd, idTXTSubject), wsz, ARRAYSIZE(wsz), FALSE);
|
|
|
|
// All checks in here had better exit if get a MIME_S_CHARSET_CONFLICT
|
|
if (fCheckConflictOnly)
|
|
{
|
|
HCHARSET hCharSet;
|
|
BOOL fGetDefault = TRUE;
|
|
|
|
// Get charset for header
|
|
if (m_pHeaderSite)
|
|
{
|
|
if (SUCCEEDED(m_pHeaderSite->GetCharset(&hCharSet)))
|
|
{
|
|
cpID = CustomGetCPFromCharset(hCharSet, FALSE);
|
|
fGetDefault = FALSE;
|
|
}
|
|
}
|
|
|
|
// Get default charset if didn't get one from header
|
|
if (fGetDefault)
|
|
{
|
|
pMsg->GetCharset(&hCharSet);
|
|
cpID = CustomGetCPFromCharset(hCharSet, FALSE);
|
|
}
|
|
|
|
// If we are unicode, then there is no need to check because
|
|
// we will always work, so exit.
|
|
if (CP_UTF7 == cpID || CP_UTF8 == cpID || CP_UNICODE == cpID)
|
|
goto exit;
|
|
|
|
IF_FAILEXIT(hr = HrSetSenderInfoUtil(pMsg, m_pAccount, m_lpWabal, m_fMail, cpID, TRUE));
|
|
if (MIME_S_CHARSET_CONFLICT == hr)
|
|
goto exit;
|
|
|
|
IF_FAILEXIT(hr = HrSafeToEncodeToCP(wsz, cpID));
|
|
if (MIME_S_CHARSET_CONFLICT == hr)
|
|
goto exit;
|
|
|
|
if (m_pszRefs)
|
|
{
|
|
IF_FAILEXIT(hr = HrSafeToEncodeToCP(m_pszRefs, cpID));
|
|
if (MIME_S_CHARSET_CONFLICT == hr)
|
|
goto exit;
|
|
}
|
|
|
|
IF_FAILEXIT(hr = HrCheckDisplayNames(m_lpWabal, cpID));
|
|
if (MIME_S_CHARSET_CONFLICT == hr)
|
|
goto exit;
|
|
|
|
if (m_lpAttMan)
|
|
{
|
|
IF_FAILEXIT(hr = m_lpAttMan->CheckAttachNameSafeWithCP(cpID));
|
|
if (MIME_S_CHARSET_CONFLICT == hr)
|
|
goto exit;
|
|
}
|
|
|
|
if (!m_fMail)
|
|
{
|
|
IF_FAILEXIT(hr = HrNewsSave(pMsg, cpID, TRUE));
|
|
if (MIME_S_CHARSET_CONFLICT == hr)
|
|
goto exit;
|
|
}
|
|
|
|
// this checking produced a 4 bugs in OE 5.01 and 5.5 and I disaable it (YST)
|
|
#ifdef YST
|
|
if (m_pEnvelopeSite)
|
|
{
|
|
IF_FAILEXIT(hr = _CheckMsoBodyCharsetConflict(cpID));
|
|
if (MIME_S_CHARSET_CONFLICT == hr)
|
|
goto exit;
|
|
}
|
|
#endif
|
|
}
|
|
else
|
|
{
|
|
// ************************
|
|
// This portion only happens on save, so don't try to do for fCheckConflictOnly
|
|
// Anything not in this section had better be mirrored in the fCheckConflictOnly block above
|
|
|
|
IF_FAILEXIT(hr = HrSetAccountByAccount(pMsg, m_pAccount));
|
|
|
|
if (m_fVCard)
|
|
{
|
|
HWND hwndFocus=GetFocus();
|
|
|
|
hr = _AttachVCard(pMsg);
|
|
if (FAILED(hr))
|
|
{
|
|
if (AthMessageBoxW(m_hwnd, MAKEINTRESOURCEW(m_fMail?idsAthenaMail:idsAthenaNews),
|
|
MAKEINTRESOURCEW(idsErrAttachVCard), NULL, MB_YESNO | MB_ICONEXCLAMATION ) != IDYES)
|
|
{
|
|
::SetFocus(hwndFocus);
|
|
IF_FAILEXIT(hr);
|
|
}
|
|
}
|
|
}
|
|
|
|
// set the time
|
|
rVariant.vt = VT_FILETIME;
|
|
GetSystemTime(&st);
|
|
SystemTimeToFileTime(&st, &rVariant.filetime);
|
|
pMsg->SetProp(PIDTOSTR(PID_ATT_SENTTIME), 0, &rVariant);
|
|
|
|
// Priority
|
|
if (m_pri!=priNone)
|
|
{
|
|
rVariant.vt = VT_UI4;
|
|
rVariant.ulVal = priLookup[m_pri];
|
|
pMsg->SetProp(PIDTOSTR(PID_ATT_PRIORITY), 0, &rVariant);
|
|
}
|
|
|
|
IF_FAILEXIT(hr = HrSaveSecurity(pMsg));
|
|
// end of save only portion.
|
|
// *************************
|
|
|
|
m_lpWabal->DeleteRecipType(MAPI_ORIG);
|
|
IF_FAILEXIT(hr = HrSetSenderInfoUtil(pMsg, m_pAccount, m_lpWabal, m_fMail, 0, FALSE));
|
|
IF_FAILEXIT(hr = MimeOleSetBodyPropW(pMsg, HBODY_ROOT, PIDTOSTR(PID_HDR_SUBJECT), NOFLAGS, wsz));
|
|
|
|
if (m_pszRefs)
|
|
IF_FAILEXIT(hr = MimeOleSetBodyPropW(pMsg, HBODY_ROOT, PIDTOSTR(PID_HDR_REFS), NOFLAGS, m_pszRefs));
|
|
|
|
// This must be called after HrSaveSecurity
|
|
IF_FAILEXIT(hr = HrSetWabalOnMsg(pMsg, m_lpWabal));
|
|
|
|
if (m_lpAttMan)
|
|
IF_FAILEXIT(hr = m_lpAttMan->Save(pMsg, 0));
|
|
|
|
if (!m_fMail)
|
|
IF_FAILEXIT(hr = HrNewsSave(pMsg, cpID, FALSE));
|
|
}
|
|
|
|
exit:
|
|
return hr;
|
|
}
|
|
|
|
// IPersist::GetClassID
|
|
HRESULT CNoteHdr::GetClassID(CLSID *pClsID)
|
|
{
|
|
//TODO:
|
|
*pClsID = CLSID_OEEnvelope;
|
|
return NOERROR;
|
|
}
|
|
|
|
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
// IHeader::SetRect
|
|
HRESULT CNoteHdr::SetRect(LPRECT prc)
|
|
{
|
|
MoveWindow(m_hwnd, prc->left, prc->top, prc->right-prc->left, prc->bottom - prc->top, TRUE);
|
|
return NOERROR;
|
|
}
|
|
|
|
|
|
// IHeader::GetRect
|
|
HRESULT CNoteHdr::GetRect(LPRECT prcView)
|
|
{
|
|
GetRealClientRect(m_hwnd, prcView);
|
|
return NOERROR;
|
|
}
|
|
|
|
|
|
|
|
// IHeader::Init
|
|
HRESULT CNoteHdr::Init(IHeaderSite* pHeaderSite, HWND hwndParent)
|
|
{
|
|
if (pHeaderSite==NULL || hwndParent==NULL)
|
|
return E_INVALIDARG;
|
|
|
|
m_pHeaderSite = pHeaderSite;
|
|
m_pHeaderSite->AddRef();
|
|
m_hwndParent = hwndParent;
|
|
|
|
return HrInit(NULL);
|
|
}
|
|
|
|
|
|
// IHeader::SetPriority
|
|
HRESULT CNoteHdr::SetPriority(UINT pri)
|
|
{
|
|
RECT rc;
|
|
|
|
if ((UINT)m_pri != pri)
|
|
{
|
|
m_pri = pri;
|
|
|
|
InvalidateStatus();
|
|
ReLayout();
|
|
|
|
SetDirtyFlag();
|
|
}
|
|
|
|
return NOERROR;
|
|
}
|
|
|
|
|
|
// IHeader::GetPriority
|
|
HRESULT CNoteHdr::GetPriority(UINT* ppri)
|
|
{
|
|
*ppri = m_pri;
|
|
return NOERROR;
|
|
}
|
|
|
|
// Update fiels, which depends from language
|
|
void CNoteHdr::_UpdateTextFields(BOOL fSetWabal)
|
|
{
|
|
LPWSTR lpszOrg = NULL,
|
|
lpszSubj = NULL,
|
|
lpszKeywords = NULL;
|
|
|
|
if (IsReadOnly())
|
|
{
|
|
// if it's a readnote, reload the header that depend on a charset
|
|
MimeOleGetBodyPropW(m_pMsg, HBODY_ROOT, PIDTOSTR(PID_HDR_SUBJECT), NOFLAGS, &lpszSubj);
|
|
MimeOleGetBodyPropW(m_pMsg, HBODY_ROOT, PIDTOSTR(PID_HDR_KEYWORDS), NOFLAGS, &lpszKeywords);
|
|
MimeOleGetBodyPropW(m_pMsg, HBODY_ROOT, PIDTOSTR(PID_HDR_ORG), NOFLAGS, &lpszOrg);
|
|
|
|
if(lpszOrg)
|
|
{
|
|
HdrSetRichEditText(GetDlgItem(m_hwnd, idTXTOrg), lpszOrg, FALSE);
|
|
MemFree(lpszOrg);
|
|
}
|
|
|
|
if(lpszKeywords)
|
|
{
|
|
HdrSetRichEditText(GetDlgItem(m_hwnd, idTXTKeywords), lpszKeywords, FALSE);
|
|
MemFree(lpszKeywords);
|
|
}
|
|
|
|
if(lpszSubj)
|
|
{
|
|
HdrSetRichEditText(GetDlgItem(m_hwnd, idTXTSubject), lpszSubj, FALSE);
|
|
MemFree(lpszSubj);
|
|
}
|
|
|
|
if (fSetWabal)
|
|
{
|
|
LPWABAL lpWabal = NULL;
|
|
|
|
Assert(m_hwnd);
|
|
Assert(m_pMsg);
|
|
Assert(m_lpWabal);
|
|
|
|
if (SUCCEEDED(HrGetWabalFromMsg(m_pMsg, &lpWabal)))
|
|
{
|
|
ReplaceInterface(m_lpWabal, lpWabal);
|
|
|
|
if (SUCCEEDED(m_pAddrWells->HrSetWabal(m_lpWabal)))
|
|
{
|
|
m_lpWabal->HrResolveNames(NULL, FALSE);
|
|
m_pAddrWells->HrDisplayWells(m_hwnd);
|
|
}
|
|
}
|
|
ReleaseObj(lpWabal);
|
|
}
|
|
|
|
m_fDirty = FALSE; // don't make dirty if a readnote
|
|
}
|
|
}
|
|
|
|
// IHeader::ChangeLanguage
|
|
HRESULT CNoteHdr::ChangeLanguage(LPMIMEMESSAGE pMsg)
|
|
{
|
|
HCHARSET hCharset=NULL;
|
|
|
|
if (!pMsg)
|
|
return E_INVALIDARG;
|
|
|
|
pMsg->GetCharset(&hCharset);
|
|
|
|
// Update fields, which depends from language
|
|
_UpdateTextFields(TRUE);
|
|
|
|
// update the fonts scripts etc
|
|
HrUpdateCharSetFonts(hCharset, TRUE);
|
|
|
|
// notify the addr wells that the font need to change
|
|
m_pAddrWells->OnFontChange();
|
|
return S_OK;
|
|
}
|
|
|
|
|
|
|
|
|
|
HRESULT CNoteHdr::OnPreFontChange()
|
|
{
|
|
HWND hwndFrom=GetDlgItem(m_hwnd, idFromCombo);
|
|
|
|
if (hwndFrom)
|
|
SendMessage(hwndFrom, WM_SETFONT, 0, 0);
|
|
return S_OK;
|
|
}
|
|
|
|
HRESULT CNoteHdr::OnPostFontChange()
|
|
{
|
|
ULONG cxNewLeftMargin = _GetLeftMargin();
|
|
HWND hwndFrom=GetDlgItem(m_hwnd, idFromCombo);
|
|
HFONT hFont;
|
|
HWND hwndBlock = HwndStartBlockingPaints(m_hwnd);
|
|
BOOL fLayout=FALSE;
|
|
|
|
if (g_pFieldSizeMgr->FontsChanged() || (m_cxLeftMargin != cxNewLeftMargin))
|
|
{
|
|
m_cxLeftMargin = cxNewLeftMargin;
|
|
fLayout=TRUE;
|
|
}
|
|
|
|
// update the fonts
|
|
ChangeLanguage(m_pMsg);
|
|
|
|
// update the account combo
|
|
if (hwndFrom &&
|
|
g_lpIFontCache &&
|
|
g_lpIFontCache->GetFont(FNT_SYS_ICON, NULL, &hFont)==S_OK)
|
|
SendMessage(hwndFrom, WM_SETFONT, (WPARAM)hFont, 0);
|
|
|
|
if (fLayout)
|
|
ReLayout();
|
|
|
|
if (hwndBlock)
|
|
StopBlockingPaints(hwndBlock);
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
|
|
// IHeader::GetTitle
|
|
HRESULT CNoteHdr::GetTitle(LPWSTR pwszTitle, ULONG cch)
|
|
{
|
|
// Locals
|
|
static WCHAR s_wszNoteTitle[cchHeaderMax+1] = L"";
|
|
static DWORD s_cLenTitle = 0;
|
|
INETCSETINFO CsetInfo;
|
|
UINT uiCodePage = 0;
|
|
HRESULT hr = S_OK;
|
|
LPWSTR pwszLang = NULL;
|
|
BOOL fWinNT = g_OSInfo.dwPlatformId == VER_PLATFORM_WIN32_NT;
|
|
|
|
if (pwszTitle==NULL || cch==0)
|
|
return E_INVALIDARG;
|
|
|
|
if (*s_wszNoteTitle == L'\0')
|
|
{
|
|
if (fWinNT)
|
|
{
|
|
AthLoadStringW(idsNoteLangTitle, s_wszNoteTitle, ARRAYSIZE(s_wszNoteTitle));
|
|
|
|
// -4 for the %1 and %2 that will be replaced
|
|
s_cLenTitle = lstrlenW(s_wszNoteTitle) - 4;
|
|
}
|
|
else
|
|
{
|
|
AthLoadStringW(idsNoteLangTitle9x, s_wszNoteTitle, ARRAYSIZE(s_wszNoteTitle));
|
|
|
|
// -2 for the %s that will be replaced
|
|
s_cLenTitle = lstrlenW(s_wszNoteTitle) - 2;
|
|
}
|
|
}
|
|
|
|
if (m_hCharset)
|
|
{
|
|
MimeOleGetCharsetInfo(m_hCharset,&CsetInfo);
|
|
uiCodePage = CsetInfo.cpiWindows;
|
|
}
|
|
|
|
if (uiCodePage == 0 || uiCodePage == GetACP())
|
|
{
|
|
HdrGetRichEditText(GetDlgItem(m_hwnd, idTXTSubject), pwszTitle, cch-1, FALSE);
|
|
if (0 == *pwszTitle)
|
|
AthLoadStringW((OENA_READ == m_ntNote) ? idsNoSubject : idsNewNote, pwszTitle, cch-1);
|
|
|
|
ConvertTabsToSpacesW(pwszTitle);
|
|
}
|
|
else
|
|
{
|
|
AssertSz(cch > (ARRAYSIZE(CsetInfo.szName) + s_cLenTitle), "Won't fit language. Get bigger cch!!!");
|
|
|
|
// if no lang pack then s_szLastLang is empty and we need to try to restore message header
|
|
IF_NULLEXIT(pwszLang = PszToUnicode(CP_ACP, *m_szLastLang ? m_szLastLang : CsetInfo.szName));
|
|
|
|
if (fWinNT)
|
|
{
|
|
WCHAR wszSubj[cchHeaderMax+1];
|
|
DWORD cchLang,
|
|
cchTotal,
|
|
cchSubj;
|
|
LPSTR pArgs[2];
|
|
|
|
*wszSubj = 0;
|
|
|
|
HdrGetRichEditText(GetDlgItem(m_hwnd, idTXTSubject), wszSubj, ARRAYSIZE(wszSubj), FALSE);
|
|
if (0 == *wszSubj)
|
|
AthLoadStringW((OENA_READ == m_ntNote) ? idsNoSubject : idsNewNote, wszSubj, ARRAYSIZE(wszSubj));
|
|
|
|
ConvertTabsToSpacesW(wszSubj);
|
|
|
|
cchSubj = lstrlenW(wszSubj);
|
|
cchLang = lstrlenW(pwszLang);
|
|
cchTotal = s_cLenTitle + cchLang + cchSubj + 1;
|
|
|
|
// If too big, truncate the subject, not language since
|
|
// asserting that we have enough for language.
|
|
if (cchTotal > cch)
|
|
{
|
|
cchSubj -= (cchTotal - cch);
|
|
wszSubj[cchSubj] = L'\0';
|
|
}
|
|
|
|
pArgs[0] = (LPSTR)wszSubj;
|
|
pArgs[1] = (LPSTR)pwszLang;
|
|
*pwszTitle = L'\0';
|
|
FormatMessageW(FORMAT_MESSAGE_FROM_STRING|FORMAT_MESSAGE_ARGUMENT_ARRAY,
|
|
s_wszNoteTitle,
|
|
0, 0,
|
|
pwszTitle,
|
|
cch,
|
|
(va_list*)pArgs);
|
|
}
|
|
else
|
|
{
|
|
wnsprintfW(pwszTitle, cch, s_wszNoteTitle, pwszLang);
|
|
}
|
|
}
|
|
|
|
exit:
|
|
MemFree(pwszLang);
|
|
return hr;
|
|
}
|
|
|
|
|
|
void CNoteHdr::_AddRecipTypeToMenu(HMENU hmenu)
|
|
{
|
|
ADRINFO adrInfo;
|
|
WCHAR wszDisp[256];
|
|
ULONG uPos=0;
|
|
|
|
BOOL fFound = m_lpWabal->FGetFirst(&adrInfo);
|
|
while (fFound && (uPos < cMaxRecipMenu))
|
|
{
|
|
if (adrInfo.lRecipType==MAPI_TO || adrInfo.lRecipType==MAPI_CC)
|
|
{
|
|
if(lstrlenW(adrInfo.lpwszDisplay) > 255)
|
|
{
|
|
StrCpyNW(wszDisp, adrInfo.lpwszDisplay, 255);
|
|
wszDisp[255] = '\0';
|
|
}
|
|
else
|
|
{
|
|
StrCpyNW(wszDisp, adrInfo.lpwszDisplay, ARRAYSIZE(wszDisp));
|
|
}
|
|
|
|
AppendMenuWrapW(hmenu, MF_STRING , ID_ADD_RECIPIENT_FIRST+uPos, wszDisp);
|
|
uPos++;
|
|
}
|
|
fFound = m_lpWabal->FGetNext(&adrInfo);
|
|
}
|
|
}
|
|
|
|
// IHeader::UpdateRecipientMenu
|
|
HRESULT CNoteHdr::UpdateRecipientMenu(HMENU hmenu)
|
|
{
|
|
HRESULT hr = E_FAIL;
|
|
BOOL fSucceeded = TRUE;
|
|
|
|
// destory current recipients
|
|
while (fSucceeded)
|
|
fSucceeded = DeleteMenu(hmenu, 2, MF_BYPOSITION);
|
|
|
|
if (!m_lpWabal)
|
|
return E_FAIL;
|
|
|
|
// Add To: and Cc: people
|
|
_AddRecipTypeToMenu(hmenu);
|
|
|
|
return NOERROR;
|
|
}
|
|
|
|
|
|
// IHeader::SetInitFocus
|
|
HRESULT CNoteHdr::SetInitFocus(BOOL fSubject)
|
|
{
|
|
if (m_rgHCI)
|
|
{
|
|
if (fSubject)
|
|
::SetFocus(GetDlgItem(m_hwnd, idTXTSubject));
|
|
else
|
|
{
|
|
if (0 == (m_rgHCI[0].dwFlags & HCF_COMBO))
|
|
::SetFocus(GetDlgItem(m_hwnd, m_rgHCI[0].idEdit));
|
|
else
|
|
::SetFocus(GetDlgItem(m_hwnd, m_rgHCI[1].idEdit));
|
|
}
|
|
}
|
|
return NOERROR;
|
|
}
|
|
|
|
|
|
// IHeader::SetVCard
|
|
HRESULT CNoteHdr::SetVCard(BOOL fFresh)
|
|
{
|
|
HRESULT hr = NOERROR;
|
|
TCHAR szBuf[MAX_PATH];
|
|
LPWAB lpWab = NULL;
|
|
ULONG cbEID=0;
|
|
LPENTRYID lpEID = NULL;
|
|
WORD wVCard;
|
|
|
|
if (m_ntNote == OENA_READ)
|
|
wVCard = (m_lpAttMan->HrFVCard() == S_OK) ? VCardTRUE : VCardFALSE;
|
|
else if (!fFresh) //not a fresh note.
|
|
wVCard = VCardFALSE;
|
|
else if (m_ntNote == OENA_FORWARD)
|
|
wVCard = (m_lpAttMan->HrCheckVCardExists(m_fMail) == S_OK) ? VCardFALSE : VCardDONTKNOW;
|
|
else
|
|
wVCard = VCardDONTKNOW;
|
|
|
|
if (wVCard != VCardDONTKNOW)
|
|
m_fVCard = wVCard;
|
|
else
|
|
{
|
|
hr = HrGetVCardName(szBuf, sizeof(szBuf));
|
|
if (FAILED(hr)) // no vcard name selected
|
|
{
|
|
if (m_fMail)
|
|
SetDwOption(OPT_MAIL_ATTACHVCARD, FALSE, NULL, 0);
|
|
else
|
|
SetDwOption(OPT_NEWS_ATTACHVCARD, FALSE, NULL, 0);
|
|
}
|
|
|
|
if (m_fMail)
|
|
m_fVCard = (BOOL)DwGetOption(OPT_MAIL_ATTACHVCARD);
|
|
else
|
|
m_fVCard = (BOOL)DwGetOption(OPT_NEWS_ATTACHVCARD);
|
|
}
|
|
|
|
hr = HrOnOffVCard();
|
|
if (FAILED(hr))
|
|
goto error;
|
|
|
|
error:
|
|
ReleaseObj(lpWab);
|
|
return hr;
|
|
}
|
|
|
|
|
|
// IHeader::IsSecured
|
|
HRESULT CNoteHdr::IsSecured()
|
|
{
|
|
if (m_fDigSigned || m_fEncrypted)
|
|
return S_OK;
|
|
else
|
|
return S_FALSE;
|
|
}
|
|
|
|
HRESULT CNoteHdr::IsHeadSigned()
|
|
{
|
|
if (m_fDigSigned)
|
|
return S_OK;
|
|
else
|
|
return S_FALSE;
|
|
}
|
|
|
|
// set ForvrEncryption form policy module if fSet is TRUE
|
|
// if fSet is not set then returns S_FALSE if ForceEncryption was not set
|
|
|
|
HRESULT CNoteHdr::ForceEncryption(BOOL *fEncrypt, BOOL fSet)
|
|
{
|
|
HRESULT hr = S_FALSE;
|
|
if(fSet)
|
|
{
|
|
Assert(fEncrypt);
|
|
if(m_fDigSigned)
|
|
{
|
|
if(*fEncrypt)
|
|
m_fEncrypted = TRUE;
|
|
|
|
}
|
|
m_fForceEncryption = *fEncrypt;
|
|
if(m_ntNote != OENA_READ)
|
|
HrUpdateSecurity();
|
|
hr = S_OK;
|
|
}
|
|
else if(m_fForceEncryption && m_fDigSigned)
|
|
{
|
|
m_fEncrypted = TRUE;
|
|
hr = S_OK;
|
|
}
|
|
|
|
return(hr);
|
|
}
|
|
|
|
// IHeader::AddRecipient
|
|
HRESULT CNoteHdr::AddRecipient(int idOffset)
|
|
{
|
|
BOOL fFound;
|
|
ULONG uPos=0;
|
|
ADRINFO adrInfo;
|
|
LPADRINFO lpAdrInfo=0;
|
|
LPWAB lpWab;
|
|
HRESULT hr=E_FAIL;
|
|
|
|
Assert(m_lpWabal);
|
|
|
|
fFound = m_lpWabal->FGetFirst(&adrInfo);
|
|
while (fFound &&
|
|
(uPos < cMaxRecipMenu))
|
|
{
|
|
if (idOffset==-1 &&
|
|
adrInfo.lRecipType==MAPI_ORIG)
|
|
{
|
|
lpAdrInfo=&adrInfo;
|
|
break;
|
|
}
|
|
|
|
if (adrInfo.lRecipType==MAPI_TO || adrInfo.lRecipType==MAPI_CC)
|
|
{
|
|
if (idOffset==(int)uPos)
|
|
{
|
|
lpAdrInfo=&adrInfo;
|
|
break;
|
|
}
|
|
uPos++;
|
|
}
|
|
fFound=m_lpWabal->FGetNext(&adrInfo);
|
|
}
|
|
|
|
if (lpAdrInfo &&
|
|
!FAILED (HrCreateWabObject (&lpWab)))
|
|
{
|
|
hr=lpWab->HrAddToWAB(m_hwnd, lpAdrInfo);
|
|
lpWab->Release ();
|
|
}
|
|
|
|
if (FAILED(hr) && hr!=MAPI_E_USER_CANCEL)
|
|
{
|
|
if (hr==MAPI_E_COLLISION)
|
|
AthMessageBoxW(m_hwnd, MAKEINTRESOURCEW(idsAthenaMail), MAKEINTRESOURCEW(idsErrAddrDupe), NULL, MB_OK);
|
|
else
|
|
AthMessageBoxW(m_hwnd, MAKEINTRESOURCEW(idsAthenaMail), MAKEINTRESOURCEW(idsErrAddToWAB), NULL, MB_OK);
|
|
}
|
|
|
|
return NOERROR;
|
|
}
|
|
|
|
|
|
// IHeader::OnDocumentReady
|
|
HRESULT CNoteHdr::OnDocumentReady(LPMIMEMESSAGE pMsg)
|
|
{
|
|
HRESULT hr = S_OK;
|
|
|
|
m_fStillLoading = FALSE;
|
|
if (m_lpAttMan)
|
|
hr = m_lpAttMan->Load(pMsg);
|
|
|
|
return hr;
|
|
}
|
|
|
|
|
|
// IHeader::DropFiles
|
|
HRESULT CNoteHdr::DropFiles(HDROP hDrop, BOOL fMakeLinks)
|
|
{
|
|
HRESULT hr = S_OK;
|
|
if (m_lpAttMan)
|
|
hr = m_lpAttMan->HrDropFiles(hDrop, fMakeLinks);
|
|
|
|
return hr;
|
|
}
|
|
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
// IMsoEnvelope:Init
|
|
HRESULT CNoteHdr::Init(IUnknown* punk, IMsoEnvelopeSite* pesit, DWORD grfInit)
|
|
{
|
|
HRESULT hr = S_OK;
|
|
|
|
if (punk == NULL && pesit == NULL && grfInit == 0)
|
|
{
|
|
SafeRelease(m_pEnvelopeSite);
|
|
hr = E_FAIL;
|
|
goto Exit;
|
|
}
|
|
|
|
if (pesit==NULL)
|
|
{
|
|
hr = E_INVALIDARG;
|
|
goto Exit;
|
|
}
|
|
|
|
ReplaceInterface(m_pEnvelopeSite, pesit);
|
|
|
|
hr = HrInit(NULL);
|
|
if (FAILED(hr))
|
|
goto Exit;
|
|
|
|
if (grfInit & ENV_INIT_FROMSTREAM)
|
|
{
|
|
IStream *pstm = NULL;
|
|
|
|
// no IStream to work with?
|
|
if (!punk)
|
|
return E_INVALIDARG;
|
|
|
|
hr = punk->QueryInterface(IID_IStream, (LPVOID*)&pstm);
|
|
if (!FAILED(hr))
|
|
{
|
|
hr = _LoadFromStream(pstm);
|
|
pstm->Release();
|
|
}
|
|
}
|
|
|
|
_SetButtonText(ID_SEND_NOW, MAKEINTRESOURCE((grfInit & ENV_INIT_DOCBEHAVIOR)?idsEnvSendCopy:idsEnvSend));
|
|
|
|
Exit:
|
|
return hr;
|
|
}
|
|
|
|
|
|
// IMsoEnvelope::SetParent
|
|
// we create the envelope window here
|
|
HRESULT CNoteHdr::SetParent(HWND hwndParent)
|
|
{
|
|
Assert (IsWindow(m_hwnd));
|
|
|
|
ShowWindow(m_hwnd, hwndParent ? SW_SHOW : SW_HIDE);
|
|
|
|
if (hwndParent)
|
|
{
|
|
_RegisterWithComponentMgr(TRUE);
|
|
_RegisterAsDropTarget(TRUE);
|
|
_RegisterWithFontCache(TRUE);
|
|
}
|
|
else
|
|
{
|
|
_RegisterWithComponentMgr(FALSE);
|
|
_RegisterAsDropTarget(FALSE);
|
|
_RegisterWithFontCache(FALSE);
|
|
}
|
|
|
|
m_hwndParent = hwndParent?hwndParent:g_hwndInit;
|
|
::SetParent(m_hwnd, m_hwndParent);
|
|
|
|
if (hwndParent)
|
|
ReLayout();
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
// IMsoEnvelope::Resize
|
|
HRESULT CNoteHdr::Resize(LPCRECT prc)
|
|
{
|
|
MoveWindow(m_hwnd, prc->left, prc->top, prc->right - prc->left, prc->bottom - prc->top, TRUE);
|
|
return NOERROR;
|
|
}
|
|
|
|
// IMsoEnvelope::Show
|
|
HRESULT CNoteHdr::Show(BOOL fShow)
|
|
{
|
|
ShowWindow(m_hwnd, fShow ? SW_SHOW : SW_HIDE);
|
|
return NOERROR;
|
|
}
|
|
|
|
// IMsoEnvelope::SetHelpMode
|
|
HRESULT CNoteHdr::SetHelpMode(BOOL fEnter)
|
|
{
|
|
return NOERROR;
|
|
}
|
|
|
|
// IMsoEnvelope::Save
|
|
HRESULT CNoteHdr::Save(IStream* pstm, DWORD grfSave)
|
|
{
|
|
HRESULT hr = S_OK;
|
|
IMimeMessage *pMsg = NULL;
|
|
PERSISTHEADER rPersistHdr;
|
|
|
|
if (pstm == NULL)
|
|
return E_INVALIDARG;
|
|
|
|
hr = WriteClassStm(pstm, CLSID_OEEnvelope);
|
|
if (!FAILED(hr))
|
|
{
|
|
ZeroMemory(&rPersistHdr, sizeof(PERSISTHEADER));
|
|
rPersistHdr.cbSize = sizeof(PERSISTHEADER);
|
|
hr = pstm->Write(&rPersistHdr, sizeof(PERSISTHEADER), NULL);
|
|
if (!FAILED(hr))
|
|
{
|
|
hr = HrCreateMessage(&pMsg);
|
|
if (!FAILED(hr))
|
|
{
|
|
hr = Save(pMsg, 0);
|
|
if (!FAILED(hr))
|
|
hr = pMsg->Save(pstm, FALSE);
|
|
|
|
pMsg->Release();
|
|
}
|
|
}
|
|
}
|
|
|
|
_ClearDirtyFlag();
|
|
return hr;
|
|
}
|
|
|
|
// IMsoEnvelope::GetAttach
|
|
HRESULT CNoteHdr::GetAttach(const WCHAR* wszName,IStream** ppstm)
|
|
{
|
|
return NOERROR;
|
|
}
|
|
|
|
HRESULT CNoteHdr::SetAttach(const WCHAR* wszName, const WCHAR *wszCID, IStream **ppstm, DWORD *pgrfAttach)
|
|
{
|
|
IStream *pstm=0;
|
|
HBODY hBody;
|
|
LPWSTR pszCntTypeW=NULL;
|
|
HRESULT hr;
|
|
PROPVARIANT pv;
|
|
|
|
if (!m_pMsgSend)
|
|
return E_FAIL;
|
|
|
|
IF_FAILEXIT(hr = MimeOleCreateVirtualStream(&pstm));
|
|
|
|
IF_FAILEXIT(hr = m_pMsgSend->AttachURL(NULL, NULL, 0, pstm, NULL, &hBody));
|
|
|
|
// strip off cid: header
|
|
if (StrCmpNIW(wszCID, L"CID:", 4)==0)
|
|
wszCID += 4;
|
|
|
|
IF_FAILEXIT(hr = MimeOleSetBodyPropW(m_pMsgSend, hBody, PIDTOSTR(PID_HDR_CNTID), 0, wszCID));
|
|
|
|
IF_FAILEXIT(hr = MimeOleSetBodyPropW(m_pMsgSend, hBody, PIDTOSTR(STR_ATT_FILENAME), 0, wszName));
|
|
|
|
FindMimeFromData(NULL, wszName, NULL, NULL, NULL, 0, &pszCntTypeW, 0);
|
|
pv.vt = pszCntTypeW ? VT_LPWSTR : VT_LPSTR;
|
|
if (pszCntTypeW)
|
|
pv.pwszVal = pszCntTypeW;
|
|
else
|
|
pv.pszVal = (LPSTR)STR_MIME_APPL_STREAM; // if FindMimeFromData fails use application/octect-stream
|
|
|
|
IF_FAILEXIT(hr = m_pMsgSend->SetBodyProp(hBody, PIDTOSTR(PID_HDR_CNTTYPE), 0, &pv));
|
|
|
|
*ppstm = pstm;
|
|
pstm->AddRef();
|
|
|
|
exit:
|
|
ReleaseObj(pstm);
|
|
return hr;
|
|
}
|
|
|
|
// IMsoEnvelope::NewAttach
|
|
HRESULT CNoteHdr::NewAttach(const WCHAR* pwzName,DWORD grfAttach)
|
|
{
|
|
return NOERROR;
|
|
}
|
|
|
|
// IMsoEnvelope::SetFocus
|
|
HRESULT CNoteHdr::SetFocus(DWORD grfFocus)
|
|
{
|
|
if (!m_rgHCI)
|
|
return S_OK;
|
|
|
|
if (grfFocus & ENV_FOCUS_TAB)
|
|
{
|
|
// reverse tab in from word, focus on well if visible or subject
|
|
if (IsWindowVisible(GetDlgItem(m_hwnd, idwAttachWell)))
|
|
::SetFocus(GetDlgItem(m_hwnd, idwAttachWell));
|
|
else
|
|
::SetFocus(GetDlgItem(m_hwnd, idTXTSubject));
|
|
}
|
|
else if (grfFocus & ENV_FOCUS_INITIAL)
|
|
SetInitFocus(FALSE);
|
|
else if (grfFocus & ENV_FOCUS_RESTORE && m_hwndLastFocus)
|
|
::SetFocus(m_hwndLastFocus);
|
|
|
|
return NOERROR;
|
|
}
|
|
|
|
// IMsoEnvelope::GetHeaderInfo
|
|
HRESULT CNoteHdr::GetHeaderInfo(ULONG dispid, DWORD grfHeader, void** pszData)
|
|
{
|
|
HRESULT hr = E_FAIL;
|
|
|
|
if (!pszData)
|
|
return E_INVALIDARG;
|
|
|
|
*pszData = NULL;
|
|
if (dispid == dispidSubject)
|
|
hr = HrGetFieldText((LPWSTR*)pszData, idTXTSubject);
|
|
|
|
return hr;
|
|
}
|
|
|
|
// IMsoEnvelope::SetHeaderInfo
|
|
HRESULT CNoteHdr::SetHeaderInfo(ULONG dispid, const void *pv)
|
|
{
|
|
HRESULT hr = S_OK;
|
|
LPSTR psz = NULL;
|
|
|
|
switch (dispid)
|
|
{
|
|
case dispidSubject:
|
|
HdrSetRichEditText(GetDlgItem(m_hwnd, idTXTSubject), (LPWSTR)pv, FALSE);
|
|
break;
|
|
|
|
case dispidSendBtnText:
|
|
{
|
|
IF_NULLEXIT(psz = PszToANSI(GetACP(), (LPWSTR)pv));
|
|
|
|
_SetButtonText(ID_SEND_NOW, psz);
|
|
break;
|
|
}
|
|
}
|
|
|
|
exit:
|
|
MemFree(psz);
|
|
return NOERROR;
|
|
}
|
|
|
|
// IMsoEnvelope::IsDirty
|
|
HRESULT CNoteHdr::IsDirty()
|
|
{
|
|
if (m_fDirty || (m_lpAttMan && (m_lpAttMan->HrIsDirty()==S_OK)))
|
|
return S_OK;
|
|
else
|
|
return S_FALSE;
|
|
}
|
|
|
|
// IMsoEnvelope::GetLastError
|
|
HRESULT CNoteHdr::GetLastError(HRESULT hr, WCHAR __RPC_FAR *wszBuf, ULONG cchBuf)
|
|
{
|
|
DWORD ids;
|
|
|
|
switch (hr)
|
|
{
|
|
case E_NOTIMPL:
|
|
ids = idsNYIGeneral;
|
|
break;
|
|
|
|
default:
|
|
ids = idsGenericError;
|
|
}
|
|
|
|
AthLoadStringW(ids, wszBuf, cchBuf);
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
// IMsoEnvelope::DoDebug
|
|
HRESULT CNoteHdr::DoDebug(DWORD grfDebug)
|
|
{
|
|
return S_OK;
|
|
}
|
|
|
|
|
|
////////////////////////////////////////////////////////////////////////////////////////
|
|
// IMsoComponent::FDebugMessage
|
|
BOOL CNoteHdr::FDebugMessage(HMSOINST hinst, UINT message, WPARAM wParam, LPARAM lParam)
|
|
{
|
|
return TRUE;
|
|
}
|
|
|
|
|
|
// IMsoComponent::FPreTranslateMessage
|
|
BOOL CNoteHdr::FPreTranslateMessage(MSG *pMsg)
|
|
{
|
|
HWND hwnd;
|
|
BOOL fShift;
|
|
|
|
// Invalid ARgs
|
|
if (NULL == pMsg)
|
|
return FALSE;
|
|
|
|
// check if it's US, or one of our children
|
|
if (pMsg->hwnd != m_hwnd && !IsChild(m_hwnd, pMsg->hwnd))
|
|
return FALSE;
|
|
|
|
if (pMsg->message == WM_KEYDOWN &&
|
|
pMsg->wParam == VK_ESCAPE &&
|
|
GetFocus() == m_hwndToolbar &&
|
|
m_hwndLastFocus)
|
|
{
|
|
// when focus is inthe toolbar, we're not UIActive (cheaper than subclassing to catch WM_SETFOCUS\WM_KILLFOCUS
|
|
// as toolbar doesn't send NM_SETFOCUS). So we special case ESCAPE to drop the focus from the toolbar
|
|
::SetFocus(m_hwndLastFocus);
|
|
return TRUE;
|
|
}
|
|
|
|
// check to see if we are UIActive
|
|
if (!m_fUIActive)
|
|
return FALSE;
|
|
|
|
// check and see if it's one of our accelerators
|
|
if (::TranslateAcceleratorWrapW(m_hwnd, GetAcceleratorTable(), pMsg))
|
|
return TRUE;
|
|
|
|
// handle tab-key here
|
|
if (pMsg->message == WM_KEYDOWN &&
|
|
pMsg->wParam == VK_TAB)
|
|
{
|
|
fShift = ( GetKeyState(VK_SHIFT ) & 0x8000) != 0;
|
|
|
|
if (!fShift &&
|
|
(GetKeyState(VK_CONTROL) & 0x8000))
|
|
{
|
|
// ctrl-TAB means focus to the toolbar
|
|
::SetFocus(m_hwndToolbar);
|
|
return TRUE;
|
|
}
|
|
|
|
hwnd = _GetNextDlgTabItem(m_hwnd, pMsg->hwnd, fShift);
|
|
if (hwnd != NULL)
|
|
::SetFocus(hwnd);
|
|
else
|
|
if (m_pEnvelopeSite)
|
|
m_pEnvelopeSite->SetFocus(TRUE);
|
|
return TRUE;
|
|
}
|
|
|
|
// pass the accelerators to the envelopesite
|
|
if (m_pEnvelopeSite &&
|
|
(pMsg->message >= WM_KEYFIRST && pMsg->message <= WM_KEYLAST) &&
|
|
m_pEnvelopeSite->TranslateAccelerators(pMsg)==S_OK)
|
|
return TRUE;
|
|
|
|
// see if it's a message for our child controls
|
|
if (pMsg->message != WM_SYSCHAR &&
|
|
IsDialogMessageWrapW(m_hwnd, pMsg))
|
|
return TRUE;
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
|
|
// IMsoComponent::OnEnterState
|
|
void CNoteHdr::OnEnterState(ULONG uStateID, BOOL fEnter)
|
|
{
|
|
return;
|
|
}
|
|
|
|
|
|
// IMsoComponent::OnAppActivate
|
|
void CNoteHdr::OnAppActivate(BOOL fActive, DWORD dwOtherThreadID)
|
|
{
|
|
return;
|
|
}
|
|
|
|
|
|
// IMsoComponent::OnLoseActivation
|
|
void CNoteHdr::OnLoseActivation()
|
|
{
|
|
return;
|
|
}
|
|
|
|
|
|
// IMsoComponent::OnActivationChange
|
|
void CNoteHdr::OnActivationChange(IMsoComponent *pic, BOOL fSameComponent, const MSOCRINFO *pcrinfo, BOOL fHostIsActivating, const MSOCHOSTINFO *pchostinfo, DWORD dwReserved)
|
|
{
|
|
return;
|
|
}
|
|
|
|
|
|
// IMsoComponent::FDoIdle
|
|
BOOL CNoteHdr::FDoIdle(DWORD grfidlef)
|
|
{
|
|
return FALSE;
|
|
}
|
|
|
|
|
|
// IMsoComponent::FContinueMessageLoop
|
|
BOOL CNoteHdr::FContinueMessageLoop(ULONG uReason, void *pvLoopData, MSG *pMsgPeeked)
|
|
{
|
|
return FALSE;
|
|
}
|
|
|
|
|
|
// IMsoComponent::FQueryTerminate
|
|
BOOL CNoteHdr::FQueryTerminate(BOOL fPromptUser)
|
|
{
|
|
return TRUE;
|
|
}
|
|
|
|
|
|
// IMsoComponent::Terminate
|
|
void CNoteHdr::Terminate()
|
|
{
|
|
_RegisterWithComponentMgr(FALSE);
|
|
if (m_hwnd)
|
|
DestroyWindow(m_hwnd);
|
|
}
|
|
|
|
// IMsoComponent::HwndGetWindow
|
|
HWND CNoteHdr::HwndGetWindow(DWORD dwWhich, DWORD dwReserved)
|
|
{
|
|
HWND hwnd = NULL;
|
|
|
|
switch (dwWhich)
|
|
{
|
|
case msocWindowComponent:
|
|
case msocWindowDlgOwner:
|
|
hwnd = m_hwnd;
|
|
break;
|
|
|
|
case msocWindowFrameOwner:
|
|
hwnd = GetParent(m_hwnd);
|
|
break;
|
|
|
|
case msocWindowFrameToplevel:
|
|
{
|
|
if (m_pEnvelopeSite)
|
|
m_pEnvelopeSite->GetFrameWnd(&hwnd);
|
|
return hwnd;
|
|
}
|
|
}
|
|
return hwnd;
|
|
}
|
|
|
|
|
|
// HrUpdateCharSetFonts
|
|
//
|
|
// Purpose: Creates the controls on the header dialog
|
|
// calculates and sets up all initial coordinates
|
|
//
|
|
//
|
|
// Comments:
|
|
//
|
|
HRESULT CNoteHdr::HrUpdateCharSetFonts(HCHARSET hCharset, BOOL fUpdateFields)
|
|
{
|
|
PHCI phci;
|
|
HWND hwnd;
|
|
INT iHC;
|
|
TCHAR sz[cchHeaderMax+1];
|
|
BOOL fDirty=m_fDirty;
|
|
INETCSETINFO rCharset;
|
|
HRESULT hr = E_FAIL;
|
|
|
|
// Check Params
|
|
Assert(hCharset);
|
|
|
|
// No font cache, bummer
|
|
if (!g_lpIFontCache)
|
|
return E_FAIL;
|
|
|
|
// Get Charset Information
|
|
if (SUCCEEDED(MimeOleGetCharsetInfo(hCharset, &rCharset)))
|
|
{
|
|
HFONT hHeaderFont, hSystemFont;
|
|
|
|
if ((m_hCharset != hCharset) || (0 == *m_szLastLang))
|
|
{
|
|
*m_szLastLang = 0;
|
|
GetMimeCharsetForTitle(hCharset, NULL, m_szLastLang, ARRAYSIZE(m_szLastLang) - 1, IsReadOnly());
|
|
// Save Charset
|
|
m_hCharset = hCharset;
|
|
}
|
|
|
|
// If don't update fields, then just return
|
|
if (!fUpdateFields)
|
|
return S_OK;
|
|
|
|
// Get charset charformat
|
|
hHeaderFont = HGetCharSetFont(FNT_SYS_ICON, hCharset);
|
|
|
|
hSystemFont = GetFont(FALSE);
|
|
|
|
// Loop through header fields
|
|
for (iHC=0; iHC<(int)m_cHCI; iHC++)
|
|
{
|
|
// Get info
|
|
phci = &m_rgHCI[iHC];
|
|
hwnd = GetDlgItem(m_hwnd, phci->idEdit);
|
|
//Assert(hwndRE);
|
|
if (!hwnd)
|
|
continue;
|
|
|
|
switch (phci->dwFlags & (HCF_COMBO|HCF_ATTACH))
|
|
{
|
|
case HCF_COMBO:
|
|
case HCF_ATTACH:
|
|
SendMessage(hwnd, WM_SETFONT, (WPARAM)hSystemFont, MAKELPARAM(TRUE, 0));
|
|
break;
|
|
|
|
// richedit
|
|
// REVIEW: Why are we only doing a request resize when we have the USECHARSET flag set???
|
|
case 0:
|
|
if (phci->dwFlags & HCF_USECHARSET)
|
|
{
|
|
SetFontOnRichEdit(hwnd, hHeaderFont);
|
|
SendMessage(hwnd, EM_REQUESTRESIZE, 0, 0);
|
|
}
|
|
else
|
|
{
|
|
SetFontOnRichEdit(hwnd, hSystemFont);
|
|
}
|
|
break;
|
|
|
|
default:
|
|
AssertSz(FALSE, "How did we get something that is combo and attach???");
|
|
break;
|
|
}
|
|
}
|
|
// Don't let this make the note dirty
|
|
if (fDirty)
|
|
SetDirtyFlag();
|
|
else
|
|
m_fDirty=FALSE;
|
|
|
|
hr = S_OK;
|
|
}
|
|
|
|
return hr;
|
|
}
|
|
|
|
//
|
|
// WMCreate
|
|
//
|
|
// Purpose: Creates the controls on the header dialog
|
|
// calculates and sets up all initial coordinates
|
|
//
|
|
//
|
|
// Comments:
|
|
//
|
|
BOOL CNoteHdr::WMCreate()
|
|
{
|
|
HWND hwnd;
|
|
LONG lStyleFlags,
|
|
lExStyleFlags,
|
|
lMask;
|
|
int cy,
|
|
cx,
|
|
cxButtons = ControlXBufferSize();
|
|
HFONT hFont;
|
|
TOOLINFO ti;
|
|
PHCI phci;
|
|
RECT rc;
|
|
CAddrWellCB *pawcb;
|
|
CHARFORMAT cfHeaderCset;
|
|
HRESULT hr;
|
|
LPCWSTR pwszTitle = NULL;
|
|
BOOL fSubjectField;
|
|
|
|
Assert(g_cyFont); // should have been setup already
|
|
|
|
if (m_pEnvelopeSite)
|
|
{
|
|
// if we are the office-envelope, create a toolbar
|
|
if (_CreateEnvToolbar())
|
|
return FALSE;
|
|
}
|
|
|
|
cy = ControlYBufferSize() + m_dxTBOffset;
|
|
cx = 0;
|
|
|
|
if (S_OK != HrInitFieldList())
|
|
return FALSE;
|
|
|
|
//BROKEN: using system charformat here as not CSET info with MIMEOLE
|
|
// Get charset for cset
|
|
{
|
|
hFont = GetFont(FALSE);
|
|
if (hFont != 0)
|
|
{
|
|
hr = FontToCharformat(hFont, &g_cfHeader);
|
|
}
|
|
|
|
hFont = HGetCharSetFont(FNT_SYS_ICON, m_hCharset);
|
|
if (hFont != 0)
|
|
{
|
|
hr = FontToCharformat(hFont, &cfHeaderCset);
|
|
if (FAILED(hr))
|
|
CopyMemory (&cfHeaderCset, &g_cfHeader, sizeof (CHARFORMAT));
|
|
}
|
|
else
|
|
CopyMemory (&cfHeaderCset, &g_cfHeader, sizeof (CHARFORMAT));
|
|
hFont = GetFont(FALSE);
|
|
|
|
}
|
|
|
|
// ~~~~ Do we need to be calling this with WrapW???
|
|
// Create a tooltip, if it doesn't already exist:
|
|
m_hwndTT=CreateWindowEx(WS_EX_TOPMOST, TOOLTIPS_CLASS, NULL, 0,
|
|
CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT,CW_USEDEFAULT,
|
|
m_hwnd, (HMENU) NULL, g_hInst, NULL);
|
|
if (!m_hwndTT)
|
|
return FALSE;
|
|
|
|
ti.cbSize=sizeof(TOOLINFO);
|
|
ti.hwnd=m_hwnd;
|
|
ti.hinst=g_hLocRes;
|
|
ti.uFlags=TTF_IDISHWND|TTF_SUBCLASS;
|
|
|
|
m_lpAttMan = new CAttMan();
|
|
if (!m_lpAttMan)
|
|
return FALSE;
|
|
|
|
if (m_lpAttMan->HrInit(m_hwnd, m_ntNote==OENA_READ, m_ntNote==OENA_FORWARD, !DwGetOption(OPT_SECURITY_ATTACHMENT)))
|
|
return FALSE;
|
|
|
|
for (int iHC=0; iHC<(int)m_cHCI; iHC++)
|
|
{
|
|
phci=&m_rgHCI[iHC];
|
|
BOOL fIsCombo = (HCF_COMBO & phci->dwFlags);
|
|
BOOL fNeedsBorder = (phci->dwFlags & HCF_BORDER);
|
|
int cyCtrlSize;
|
|
|
|
|
|
// if header is optional, check setting
|
|
if ((phci->dwFlags & HCF_OPTIONAL) &&
|
|
!DwGetOption(phci->dwOpt))
|
|
continue;
|
|
|
|
if (phci->dwFlags & HCF_ATTACH)
|
|
{
|
|
// if we're not readonly, register ourselves as a drop target...
|
|
if (!(phci->dwFlags & HCF_READONLY))
|
|
{
|
|
hr = _RegisterAsDropTarget(TRUE);
|
|
if (FAILED(hr))
|
|
return FALSE;
|
|
}
|
|
continue;
|
|
}
|
|
|
|
phci->height = GetControlSize(fNeedsBorder, 1);
|
|
|
|
// Richedit
|
|
if (!fIsCombo)
|
|
{
|
|
pwszTitle = GetREClassStringW();
|
|
cyCtrlSize = phci->height;
|
|
lStyleFlags = WS_CHILD|WS_TABSTOP|WS_VISIBLE|ES_SAVESEL;
|
|
|
|
lMask=ENM_KEYEVENTS|ENM_CHANGE|ENM_SELCHANGE|ENM_REQUESTRESIZE;
|
|
|
|
if (phci->dwFlags & HCF_MULTILINE)
|
|
{
|
|
//lStyleFlags |= ES_MULTILINE|ES_WANTRETURN|WS_VSCROLL|ES_AUTOVSCROLL;
|
|
lStyleFlags |= ES_MULTILINE|WS_VSCROLL|ES_AUTOVSCROLL;
|
|
}
|
|
else
|
|
lStyleFlags |= ES_AUTOHSCROLL;
|
|
}
|
|
// Combo Box
|
|
else
|
|
{
|
|
pwszTitle = L"ComboBox";
|
|
cyCtrlSize = GetControlSize(fNeedsBorder, NUM_COMBO_LINES);
|
|
lStyleFlags = WS_CHILD|WS_TABSTOP|WS_VISIBLE|WS_VSCROLL|
|
|
CBS_DROPDOWNLIST|CBS_HASSTRINGS|CBS_SORT;
|
|
}
|
|
|
|
if (phci->dwFlags & HCF_READONLY)
|
|
lStyleFlags|=ES_READONLY;
|
|
|
|
GetClientRect(m_hwnd, &rc);
|
|
|
|
lExStyleFlags = fNeedsBorder ? WS_EX_NOPARENTNOTIFY|WS_EX_CLIENTEDGE : WS_EX_NOPARENTNOTIFY;
|
|
|
|
// @hack [dhaws] {55073} Do RTL mirroring only in special richedit versions.
|
|
fSubjectField = (idsSubjectField == phci->idsLabel);
|
|
RichEditRTLMirroring(m_hwnd, fSubjectField, &lExStyleFlags, TRUE);
|
|
|
|
// Regardless of mirroring, BiDi-Dates should be displayed RTL
|
|
if(((phci->idsLabel == idsDateField) && IsBiDiCalendar()))
|
|
lExStyleFlags |= WS_EX_RTLREADING;
|
|
hwnd = CreateWindowExWrapW(lExStyleFlags,
|
|
pwszTitle,
|
|
NULL,
|
|
lStyleFlags,
|
|
cx, cy, rc.right, cyCtrlSize,
|
|
m_hwnd,
|
|
(HMENU)IntToPtr(phci->idEdit),
|
|
g_hInst, 0 );
|
|
if (!hwnd)
|
|
return FALSE;
|
|
|
|
RichEditRTLMirroring(m_hwnd, fSubjectField, &lExStyleFlags, FALSE);
|
|
|
|
if (0 == (phci->dwFlags & HCF_BORDER))
|
|
{
|
|
SendMessage(hwnd, EM_SETBKGNDCOLOR, WPARAM(FALSE), LPARAM(GetSysColor(COLOR_BTNFACE)));
|
|
}
|
|
|
|
ti.uId = (UINT_PTR)hwnd;
|
|
ti.lpszText = (LPTSTR)IntToPtr(phci->idsTT);
|
|
SendMessage(m_hwndTT, TTM_ADDTOOL, 0, (LPARAM) &ti);
|
|
|
|
// hang a pointer into the phci off each control
|
|
SetWindowLongPtr(hwnd, GWLP_USERDATA, (LPARAM)phci);
|
|
|
|
if (!fIsCombo)
|
|
{
|
|
LPRICHEDITOLE preole = NULL;
|
|
ITextDocument *pDoc = NULL;
|
|
|
|
SideAssert(SendMessage(hwnd, EM_GETOLEINTERFACE, NULL, (LPARAM)&preole));
|
|
phci->preole = preole;
|
|
Assert(preole);
|
|
|
|
if (SUCCEEDED(preole->QueryInterface(IID_ITextDocument, (LPVOID*)&pDoc)))
|
|
phci->pDoc = pDoc;
|
|
// This only happens with richedit 1.0
|
|
else
|
|
phci->pDoc = NULL;
|
|
|
|
// Set edit charformat
|
|
if (phci->dwFlags & HCF_USECHARSET)
|
|
SendMessage(hwnd, EM_SETCHARFORMAT, 0, (LPARAM)&cfHeaderCset);
|
|
else
|
|
SendMessage(hwnd, EM_SETCHARFORMAT, 0, (LPARAM)&g_cfHeader);
|
|
|
|
if ((pawcb = new CAddrWellCB(!(phci->dwFlags&HCF_READONLY), phci->dwFlags&HCF_ADDRWELL)))
|
|
{
|
|
if (pawcb->FInit(hwnd))
|
|
SendMessage(hwnd, EM_SETOLECALLBACK, 0, (LPARAM)(IRichEditOleCallback *)pawcb);
|
|
ReleaseObj(pawcb);
|
|
}
|
|
|
|
SendMessage(hwnd, EM_SETEVENTMASK, 0, lMask);
|
|
g_lpfnREWndProc=(WNDPROC)SetWindowLongPtrAthW(hwnd, GWLP_WNDPROC, (LPARAM)EditSubClassProc);
|
|
}
|
|
else
|
|
{
|
|
CHAR szAccount[CCHMAX_ACCOUNT_NAME];
|
|
CHAR szAcctID[CCHMAX_ACCOUNT_NAME];
|
|
CHAR szDefault[CCHMAX_ACCOUNT_NAME];
|
|
CHAR szEmailAddress[CCHMAX_EMAIL_ADDRESS];
|
|
CHAR szEntry[ACCT_ENTRY_SIZE];
|
|
CHAR szDefaultEntry[ACCT_ENTRY_SIZE];
|
|
IImnEnumAccounts *pEnum=NULL;
|
|
IImnAccount *pAccount=NULL;
|
|
int i = 0;
|
|
DWORD cAccounts = 0;
|
|
LPSTR *ppszAcctIDs;
|
|
|
|
*szDefault = 0;
|
|
*szDefaultEntry = 0;
|
|
|
|
// If default account isn't setup, this might fail, but doesn't matter.
|
|
g_pAcctMan->GetDefaultAccountName(m_fMail?ACCT_MAIL:ACCT_NEWS, szDefault, ARRAYSIZE(szDefault));
|
|
|
|
hr = g_pAcctMan->Enumerate(m_fMail?SRV_MAIL:SRV_NNTP, &pEnum);
|
|
|
|
if (SUCCEEDED(hr))
|
|
hr = pEnum->GetCount(&cAccounts);
|
|
|
|
if (SUCCEEDED(hr) && cAccounts)
|
|
{
|
|
if (!MemAlloc((void**)&m_ppAccountIDs, cAccounts*sizeof(LPSTR)))
|
|
hr = E_OUTOFMEMORY;
|
|
}
|
|
|
|
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
*szDefaultEntry = 0;
|
|
ppszAcctIDs = m_ppAccountIDs;
|
|
while(SUCCEEDED(pEnum->GetNext(&pAccount)))
|
|
{
|
|
*szAccount = 0;
|
|
*szEmailAddress = 0;
|
|
|
|
pAccount->GetPropSz(AP_ACCOUNT_NAME, szAccount, ARRAYSIZE(szAccount));
|
|
if (m_fMail)
|
|
{
|
|
pAccount->GetPropSz(AP_SMTP_EMAIL_ADDRESS, szEmailAddress, ARRAYSIZE(szEmailAddress));
|
|
wnsprintf(szEntry, ARRAYSIZE(szEntry), "%s (%s)", szEmailAddress, szAccount);
|
|
}
|
|
else
|
|
{
|
|
StrCpyN(szEntry, szAccount, ARRAYSIZE(szEntry));
|
|
}
|
|
|
|
i = ComboBox_InsertString(hwnd, -1, szEntry);
|
|
if (i != CB_ERR)
|
|
{
|
|
if (0 == lstrcmpi(szDefault, szAccount))
|
|
{
|
|
StrCpyN(szDefaultEntry, szEntry, ARRAYSIZE(szDefaultEntry));
|
|
}
|
|
|
|
if (SUCCEEDED(pAccount->GetPropSz(AP_ACCOUNT_ID, szAcctID, ARRAYSIZE(szAcctID))))
|
|
{
|
|
DWORD cchSize = (lstrlen(szAcctID) + 1);
|
|
if (MemAlloc((void**)ppszAcctIDs, cchSize * sizeof(CHAR)))
|
|
{
|
|
StrCpyN(*ppszAcctIDs, szAcctID, cchSize);
|
|
}
|
|
else
|
|
{
|
|
*ppszAcctIDs = NULL;
|
|
}
|
|
}
|
|
else
|
|
*ppszAcctIDs = NULL;
|
|
|
|
SendMessage(hwnd, CB_SETITEMDATA, WPARAM(i), LPARAM(*ppszAcctIDs));
|
|
ppszAcctIDs++;
|
|
m_cAccountIDs++;
|
|
}
|
|
// Release Account
|
|
SafeRelease(pAccount);
|
|
}
|
|
AssertSz(m_cAccountIDs == cAccounts, "Why isn't num Ds = num accts?");
|
|
|
|
SafeRelease(pEnum);
|
|
AssertSz(!pAccount, "The last account didn't get freed.");
|
|
|
|
if (0 != *szDefaultEntry)
|
|
{
|
|
ComboBox_SelectString(hwnd, -1, szDefaultEntry);
|
|
m_iCurrComboIndex = ComboBox_GetCurSel(hwnd);
|
|
}
|
|
else
|
|
{
|
|
ComboBox_SetCurSel(hwnd, 0);
|
|
m_iCurrComboIndex = 0;
|
|
}
|
|
|
|
if (SUCCEEDED(HrGetAccountInHeader(&pAccount)))
|
|
{
|
|
ReplaceInterface(m_pAccount, pAccount);
|
|
ReleaseObj(pAccount);
|
|
}
|
|
|
|
SendMessage(hwnd, WM_SETFONT, WPARAM(hFont), MAKELONG(TRUE,0));
|
|
}
|
|
}
|
|
}
|
|
|
|
_RegisterWithFontCache(TRUE);
|
|
|
|
HrOnOffVCard();
|
|
ReLayout();
|
|
return PostWMCreate(); // allow subclass to setup the controls once created...
|
|
}
|
|
|
|
|
|
//
|
|
// HeaderWndProc
|
|
//
|
|
// Purpose: Main WNDPROC for header dialog
|
|
//
|
|
// Comments:
|
|
//
|
|
|
|
LRESULT CALLBACK CNoteHdr::ExtCNoteHdrWndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
|
|
{
|
|
CNoteHdr *pnh = NULL;
|
|
|
|
if (msg==WM_NCCREATE)
|
|
{
|
|
SetWndThisPtrOnCreate(hwnd, lParam);
|
|
pnh=(CNoteHdr *)GetWndThisPtr(hwnd);
|
|
if (!pnh)
|
|
return -1;
|
|
|
|
pnh->m_hwnd=hwnd;
|
|
return pnh->WMCreate();
|
|
}
|
|
|
|
pnh = (CNoteHdr *)GetWndThisPtr(hwnd);
|
|
if (pnh)
|
|
return pnh->CNoteHdrWndProc(hwnd, msg, wParam, lParam);
|
|
else
|
|
return DefWindowProcWrapW(hwnd, msg, wParam, lParam);
|
|
}
|
|
|
|
void CNoteHdr::RelayToolTip(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
|
|
{
|
|
MSG Msg;
|
|
|
|
if (m_hwndTT != NULL)
|
|
{
|
|
Msg.lParam=lParam;
|
|
Msg.wParam=wParam;
|
|
Msg.message=msg;
|
|
Msg.hwnd=hwnd;
|
|
SendMessage(m_hwndTT, TTM_RELAYEVENT, 0, (LPARAM) (LPMSG) &Msg);
|
|
}
|
|
}
|
|
|
|
LRESULT CALLBACK CNoteHdr::CNoteHdrWndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
|
|
{
|
|
POINT pt;
|
|
int newWidth;
|
|
RECT rc;
|
|
HFONT hFont=NULL;
|
|
|
|
switch (msg)
|
|
{
|
|
case WM_HEADER_GETFONT:
|
|
// update cached fornt for addrobj's
|
|
if (g_lpIFontCache)
|
|
g_lpIFontCache->GetFont(wParam ? FNT_SYS_ICON_BOLD:FNT_SYS_ICON, m_hCharset, &hFont);
|
|
return (LRESULT)hFont;
|
|
|
|
case HDM_TESTQUERYPRI:
|
|
// hack for test team to query header's priority...
|
|
return m_pri;
|
|
|
|
case WM_DESTROY:
|
|
OnDestroy();
|
|
break;
|
|
|
|
case WM_NCDESTROY:
|
|
OnNCDestroy();
|
|
break;
|
|
|
|
case WM_CTLCOLORBTN:
|
|
// make sure the buttons backgrounds are window-color so the ownerdraw
|
|
// imagelists paint transparent OK
|
|
return (LPARAM)GetSysColorBrush(COLOR_WINDOWFRAME);
|
|
|
|
case WM_CONTEXTMENU:
|
|
if (m_lpAttMan && m_lpAttMan->WMContextMenu(hwnd, msg, wParam, lParam))
|
|
return 0;
|
|
break;
|
|
|
|
case WM_MOUSEMOVE:
|
|
{
|
|
DWORD newButton = GetButtonUnderMouse(LOWORD(lParam), HIWORD(lParam));
|
|
if ((HDRCB_NO_BUTTON == m_dwClickedBtn) ||
|
|
(HDRCB_NO_BUTTON == newButton) ||
|
|
(m_dwClickedBtn == newButton))
|
|
if (newButton != m_dwCurrentBtn)
|
|
{
|
|
DOUTL(PAINTING_DEBUG_LEVEL, "Old button: %d, New Button: %d", m_dwCurrentBtn, newButton);
|
|
|
|
if (HDRCB_NO_BUTTON == newButton)
|
|
{
|
|
DOUTL(PAINTING_DEBUG_LEVEL, "Leaving right button framing.");
|
|
// Need to clear old button.
|
|
InvalidateRect(m_hwnd, &m_rcCurrentBtn, FALSE);
|
|
|
|
HeaderRelease(FALSE);
|
|
}
|
|
else
|
|
{
|
|
DOUTL(PAINTING_DEBUG_LEVEL, "Framing button.");
|
|
if (HDRCB_NO_BUTTON == m_dwCurrentBtn)
|
|
HeaderCapture();
|
|
else
|
|
InvalidateRect(m_hwnd, &m_rcCurrentBtn, FALSE);
|
|
|
|
GetButtonRect(newButton, &m_rcCurrentBtn);
|
|
InvalidateRect(m_hwnd, &m_rcCurrentBtn, FALSE);
|
|
}
|
|
|
|
m_dwCurrentBtn = newButton;
|
|
}
|
|
RelayToolTip(hwnd, msg, wParam, lParam);
|
|
break;
|
|
}
|
|
|
|
case WM_LBUTTONDOWN:
|
|
case WM_RBUTTONDOWN:
|
|
{
|
|
RECT rc;
|
|
int x = LOWORD(lParam),
|
|
y = HIWORD(lParam);
|
|
|
|
HeaderCapture();
|
|
|
|
m_dwClickedBtn = GetButtonUnderMouse(x, y);
|
|
if (m_dwClickedBtn != HDRCB_NO_BUTTON)
|
|
{
|
|
GetButtonRect(m_dwClickedBtn, &rc);
|
|
InvalidateRect(m_hwnd, &rc, FALSE);
|
|
}
|
|
|
|
RelayToolTip(hwnd, msg, wParam, lParam);
|
|
|
|
break;
|
|
}
|
|
case WM_LBUTTONUP:
|
|
case WM_RBUTTONUP:
|
|
{
|
|
int x = LOWORD(lParam),
|
|
y = HIWORD(lParam);
|
|
DWORD iBtn = GetButtonUnderMouse(x, y);
|
|
|
|
RelayToolTip(hwnd, msg, wParam, lParam);
|
|
|
|
if (m_dwClickedBtn == iBtn)
|
|
HandleButtonClicks(x, y, iBtn);
|
|
m_dwClickedBtn = HDRCB_NO_BUTTON;
|
|
HeaderRelease(FALSE);
|
|
break;
|
|
}
|
|
|
|
case WM_PAINT:
|
|
WMPaint();
|
|
break;
|
|
|
|
case WM_SYSCOLORCHANGE:
|
|
if (m_himl)
|
|
{
|
|
// remap the toolbar bitmap into the new color scheme
|
|
ImageList_Destroy(m_himl);
|
|
SendMessage(m_hwndToolbar, TB_SETIMAGELIST, 0, NULL);
|
|
m_himl = LoadMappedToolbarBitmap(g_hLocRes, (fIsWhistler() ? ((GetCurColorRes() > 24) ? idb32SmBrowserHot : idbSmBrowserHot): idbNWSmBrowserHot), cxTBButton);
|
|
|
|
SendMessage(m_hwndToolbar, TB_SETIMAGELIST, 0, (LPARAM)m_himl);
|
|
}
|
|
|
|
UpdateRebarBandColors(m_hwndRebar);
|
|
// fall thro'
|
|
|
|
case WM_WININICHANGE:
|
|
case WM_DISPLAYCHANGE:
|
|
case WM_QUERYNEWPALETTE:
|
|
case WM_PALETTECHANGED:
|
|
SendMessage(m_hwndRebar, msg, wParam, lParam);
|
|
break;
|
|
|
|
case WM_ERASEBKGND:
|
|
return 1;
|
|
|
|
case WM_SIZE:
|
|
{
|
|
STACK("WM_SIZE (width, heigth)", LOWORD(lParam), HIWORD(lParam));
|
|
|
|
if (m_fResizing)
|
|
break;
|
|
|
|
m_fResizing = TRUE;
|
|
|
|
newWidth = LOWORD(lParam);
|
|
|
|
SetPosOfControls(newWidth, FALSE);
|
|
|
|
if (m_hwndRebar)
|
|
{
|
|
GetClientRect(m_hwndRebar, &rc);
|
|
|
|
// resize the width of the toolbar
|
|
if(rc.right != newWidth)
|
|
SetWindowPos(m_hwndRebar, NULL, 0, 0, newWidth, 30, SETWINPOS_DEF_FLAGS|SWP_NOMOVE);
|
|
}
|
|
|
|
AssertSz(m_fResizing, "Someone re-entered me!!! Why is m_fResizing already false??");
|
|
m_fResizing = FALSE;
|
|
break;
|
|
}
|
|
|
|
case WM_CLOSE:
|
|
//prevent alt-f4
|
|
return 0;
|
|
|
|
case WM_COMMAND:
|
|
WMCommand(GET_WM_COMMAND_HWND(wParam, lParam),
|
|
GET_WM_COMMAND_ID(wParam, lParam),
|
|
GET_WM_COMMAND_CMD(wParam, lParam));
|
|
break;
|
|
|
|
case WM_NOTIFY:
|
|
return WMNotify(wParam, lParam);
|
|
}
|
|
return DefWindowProcWrapW(hwnd, msg, wParam, lParam);
|
|
}
|
|
|
|
|
|
void CNoteHdr::HeaderCapture()
|
|
{
|
|
if (0 == m_cCapture)
|
|
m_hwndOldCapture = SetCapture(m_hwnd);
|
|
m_cCapture++;
|
|
}
|
|
|
|
void CNoteHdr::HeaderRelease(BOOL fForce)
|
|
{
|
|
if (0 == m_cCapture)
|
|
return;
|
|
|
|
if (fForce)
|
|
m_cCapture = 0;
|
|
else
|
|
m_cCapture--;
|
|
|
|
if (0 == m_cCapture)
|
|
{
|
|
ReleaseCapture();
|
|
if (NULL != m_hwndOldCapture)
|
|
{
|
|
DOUTL(PAINTING_DEBUG_LEVEL, "Restoring old mouse events capture.");
|
|
SetCapture(m_hwndOldCapture);
|
|
m_hwndOldCapture = NULL;
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
BOOL CNoteHdr::WMNotify(WPARAM wParam, LPARAM lParam)
|
|
{
|
|
HWND hwnd=m_hwnd;
|
|
int idCtl=(int)wParam;
|
|
LPNMHDR pnmh=(LPNMHDR)lParam;
|
|
TBNOTIFY *ptbn;
|
|
LPTOOLTIPTEXT lpttt;
|
|
int i;
|
|
|
|
if (m_lpAttMan->WMNotify((int) wParam, pnmh))
|
|
return TRUE;
|
|
|
|
switch (pnmh->code)
|
|
{
|
|
case RBN_CHEVRONPUSHED:
|
|
{
|
|
ITrackShellMenu* ptsm;
|
|
CoCreateInstance(CLSID_TrackShellMenu, NULL, CLSCTX_INPROC_SERVER, IID_ITrackShellMenu,
|
|
(LPVOID*)&ptsm);
|
|
if (!ptsm)
|
|
break;
|
|
|
|
ptsm->Initialize(0, 0, 0, SMINIT_TOPLEVEL|SMINIT_VERTICAL);
|
|
|
|
LPNMREBARCHEVRON pnmch = (LPNMREBARCHEVRON) pnmh;
|
|
ptsm->SetObscured(m_hwndToolbar, NULL, SMSET_TOP);
|
|
|
|
MapWindowPoints(m_hwndRebar, HWND_DESKTOP, (LPPOINT)&pnmch->rc, 2);
|
|
POINTL pt = {pnmch->rc.left, pnmch->rc.right};
|
|
ptsm->Popup(m_hwndRebar, &pt, (RECTL*)&pnmch->rc, MPPF_BOTTOM);
|
|
ptsm->Release();
|
|
break;
|
|
}
|
|
|
|
case EN_MSGFILTER:
|
|
{
|
|
// if we get a control-tab, then richedit snags this and inserts a
|
|
// tab char, we hook the wm_keydown and never pass to richedit
|
|
if (((MSGFILTER *)pnmh)->msg == WM_KEYDOWN &&
|
|
((MSGFILTER *)pnmh)->wParam == VK_TAB &&
|
|
(GetKeyState(VK_CONTROL) & 0x8000))
|
|
return TRUE;
|
|
break;
|
|
}
|
|
|
|
case ATTN_RESIZEPARENT:
|
|
{
|
|
RECT rc;
|
|
|
|
GetClientRect(m_hwnd, &rc);
|
|
SetPosOfControls(rc.right, TRUE);
|
|
return TRUE;
|
|
}
|
|
|
|
case EN_REQUESTRESIZE:
|
|
{
|
|
REQRESIZE *presize=(REQRESIZE *)lParam;
|
|
HWND hwndEdit = presize->nmhdr.hwndFrom;
|
|
|
|
STACK("EN_REQUESTRESIZE (hwnd, width, heigth)", (DWORD_PTR)(presize->nmhdr.hwndFrom), presize->rc.right - presize->rc.left, presize->rc.bottom - presize->rc.top);
|
|
|
|
if (S_FALSE != HrUpdateCachedHeight(hwndEdit, &presize->rc) && !m_fResizing)
|
|
{
|
|
RECT rc;
|
|
DWORD dwMask = (DWORD) SendMessage(hwndEdit, EM_GETEVENTMASK, 0, 0);
|
|
|
|
SendMessage(hwndEdit, EM_SETEVENTMASK, 0, dwMask & (~ENM_REQUESTRESIZE));
|
|
|
|
STACK("EN_REQUESTRESIZE after GrowControls");
|
|
|
|
GetClientRect(m_hwnd, &rc);
|
|
SetPosOfControls(rc.right, FALSE);
|
|
|
|
SendMessage(hwndEdit, EM_SETEVENTMASK, 0, dwMask);
|
|
}
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
case NM_SETFOCUS:
|
|
case NM_KILLFOCUS:
|
|
// UIActivate/Deactivate for attachment manager
|
|
if (m_lpAttMan && pnmh->hwndFrom == m_lpAttMan->Hwnd())
|
|
_UIActivate(pnmh->code == NM_SETFOCUS, pnmh->hwndFrom);
|
|
break;
|
|
|
|
case EN_SELCHANGE:
|
|
{
|
|
PHCI phci=(PHCI)GetWndThisPtr(pnmh->hwndFrom);
|
|
if (phci)
|
|
phci->dwACFlags &= ~AC_SELECTION;
|
|
|
|
// update office toolbars if running as envelope
|
|
if(m_pEnvelopeSite)
|
|
m_pEnvelopeSite->DirtyToolbars();
|
|
|
|
// on a sel change, forward a note updatetoolbar to update the
|
|
// cut|copy|paste buttons
|
|
if (m_pHeaderSite)
|
|
m_pHeaderSite->Update();
|
|
return TRUE;
|
|
}
|
|
|
|
case TTN_NEEDTEXT:
|
|
// we use TTN_NEEDTEXT to show toolbar tips as we have different tips than toolbar-labels
|
|
// because on the office-envelope toolbar only 2 buttons (send and bcc) have text next to the
|
|
// buttons
|
|
lpttt = (LPTOOLTIPTEXT) pnmh;
|
|
lpttt->hinst = NULL;
|
|
lpttt->lpszText = 0;
|
|
|
|
for (i=0; i< ARRAYSIZE(c_rgTipLookup); i++)
|
|
{
|
|
if (c_rgTipLookup[i].idm == (int)lpttt->hdr.idFrom)
|
|
{
|
|
lpttt->hinst = g_hLocRes;
|
|
lpttt->lpszText = MAKEINTRESOURCE(c_rgTipLookup[i].ids);
|
|
break;
|
|
}
|
|
}
|
|
break;
|
|
|
|
case TBN_DROPDOWN:
|
|
{
|
|
ptbn = (TBNOTIFY *)lParam;
|
|
|
|
if (ptbn->iItem == ID_SET_PRIORITY)
|
|
{
|
|
HMENU hMenuPopup;
|
|
UINT i;
|
|
hMenuPopup = LoadPopupMenu(IDR_PRIORITY_POPUP);
|
|
|
|
if (hMenuPopup != NULL)
|
|
{
|
|
for (i = 0; i < 3; i++)
|
|
CheckMenuItem(hMenuPopup, i, MF_UNCHECKED | MF_BYPOSITION);
|
|
GetPriority(&i);
|
|
Assert(i != priNone);
|
|
CheckMenuItem(hMenuPopup, 2 - i, MF_CHECKED | MF_BYPOSITION);
|
|
|
|
DoToolbarDropdown(hwnd, (LPNMHDR) lParam, hMenuPopup);
|
|
|
|
DestroyMenu(hMenuPopup);
|
|
}
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
return FALSE;
|
|
}
|
|
|
|
HRESULT CNoteHdr::WMCommand(HWND hwndCmd, int id, WORD wCmd)
|
|
{
|
|
HWND hwnd=m_hwnd;
|
|
int i;
|
|
UINT pri;
|
|
|
|
if (m_lpAttMan && m_lpAttMan->WMCommand(hwndCmd, id, wCmd))
|
|
return S_OK;
|
|
|
|
for (i=0; i<(int)m_cHCI; i++)
|
|
if (m_rgHCI[i].idEdit==id)
|
|
{
|
|
switch (wCmd)
|
|
{
|
|
case EN_CHANGE:
|
|
{
|
|
if (m_fHandleChange)
|
|
{
|
|
BOOL fEmpty;
|
|
PHCI phci = (PHCI)GetWndThisPtr(hwndCmd);
|
|
char sz[cchHeaderMax+1];
|
|
DWORD dwMask = 0;
|
|
|
|
RichEditProtectENChange(hwndCmd, &dwMask, TRUE);
|
|
|
|
Assert(phci);
|
|
fEmpty = (0 == GetRichEditTextLen(hwndCmd));
|
|
|
|
// if it has no text, see if it has object...
|
|
if (fEmpty && phci->preole)
|
|
fEmpty = (fEmpty && (0 == phci->preole->GetObjectCount()));
|
|
|
|
if (phci->dwFlags & HCF_ADDRWELL)
|
|
m_fAddressesChanged = TRUE;
|
|
|
|
phci->fEmpty = fEmpty;
|
|
SetDirtyFlag();
|
|
|
|
if (m_fAutoComplete && (m_rgHCI[i].dwFlags & HCF_ADDRWELL) && !IsReadOnly())
|
|
{
|
|
if (NULL == m_pTable)
|
|
{
|
|
if (NULL == m_lpWab)
|
|
HrCreateWabObject(&m_lpWab);
|
|
if (m_lpWab)
|
|
m_lpWab->HrGetPABTable(&m_pTable);
|
|
}
|
|
if (m_pTable)
|
|
HrAutoComplete(hwndCmd, &m_rgHCI[i]);
|
|
}
|
|
RichEditProtectENChange(hwndCmd, &dwMask, FALSE);
|
|
}
|
|
}
|
|
return S_OK;
|
|
|
|
case CBN_SELCHANGE:
|
|
{
|
|
IImnAccount *pAcct = NULL;
|
|
|
|
if (!m_fMail)
|
|
{
|
|
int newIndex = ComboBox_GetCurSel(hwndCmd);
|
|
HWND hwndNews = GetDlgItem(m_hwnd, idADNewsgroups);
|
|
|
|
// Don't need to warn if going to same account, or if there are no newgroups listed.
|
|
if ((newIndex != m_iCurrComboIndex) && (0 < GetWindowTextLength(hwndNews)))
|
|
{
|
|
if (IDCANCEL == DoDontShowMeAgainDlg(m_hwnd, c_szDSChangeNewsServer, MAKEINTRESOURCE(idsAthena),
|
|
MAKEINTRESOURCE(idsChangeNewsServer), MB_OKCANCEL))
|
|
{
|
|
ComboBox_SetCurSel(hwndCmd, m_iCurrComboIndex);
|
|
return S_OK;
|
|
}
|
|
else
|
|
HdrSetRichEditText(hwndNews, c_wszEmpty, FALSE);
|
|
}
|
|
m_iCurrComboIndex = newIndex;
|
|
}
|
|
if (SUCCEEDED(HrGetAccountInHeader(&pAcct)))
|
|
ReplaceInterface(m_pAccount, pAcct);
|
|
ReleaseObj(pAcct);
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
case CBN_SETFOCUS:
|
|
case EN_SETFOCUS:
|
|
_UIActivate(TRUE, hwndCmd);
|
|
return S_OK;
|
|
|
|
case CBN_KILLFOCUS:
|
|
case EN_KILLFOCUS:
|
|
_UIActivate(FALSE, hwndCmd);
|
|
return S_OK;
|
|
}
|
|
return S_FALSE;
|
|
}
|
|
|
|
switch (id)
|
|
{
|
|
case ID_PRIORITY_LOW:
|
|
SetPriority(priLow);
|
|
return S_OK;
|
|
|
|
case ID_PRIORITY_NORMAL:
|
|
SetPriority(priNorm);
|
|
return S_OK;
|
|
|
|
case ID_PRIORITY_HIGH:
|
|
SetPriority(priHigh);
|
|
return S_OK;
|
|
|
|
case ID_SET_PRIORITY:
|
|
GetPriority(&pri);
|
|
pri++;
|
|
if (pri > priHigh)
|
|
pri = priLow;
|
|
SetPriority(pri);
|
|
return S_OK;
|
|
|
|
case ID_SELECT_ALL:
|
|
{
|
|
HWND hwndFocus=GetFocus();
|
|
|
|
if (GetParent(hwndFocus)==m_hwnd)
|
|
{
|
|
// only if it's one of our kids..
|
|
Edit_SetSel(hwndFocus, 0, -1);
|
|
return S_OK;
|
|
}
|
|
}
|
|
break;
|
|
|
|
case ID_CUT:
|
|
if (FDoCutCopyPaste(WM_CUT))
|
|
return S_OK;
|
|
break;
|
|
|
|
case ID_NOTE_COPY:
|
|
case ID_COPY:
|
|
if (FDoCutCopyPaste(WM_COPY))
|
|
return S_OK;
|
|
break;
|
|
|
|
case ID_PASTE:
|
|
if (FDoCutCopyPaste(WM_PASTE))
|
|
return S_OK;
|
|
break;
|
|
|
|
case ID_DELETE_VCARD:
|
|
m_fVCard = FALSE;
|
|
SetDirtyFlag();
|
|
HrOnOffVCard();
|
|
return S_OK;
|
|
|
|
case ID_OPEN_VCARD:
|
|
HrShowVCardProperties(m_hwnd);
|
|
return S_OK;
|
|
|
|
case ID_DIGITALLY_SIGN:
|
|
case ID_ENCRYPT:
|
|
HrHandleSecurityIDMs(ID_DIGITALLY_SIGN == id);
|
|
return S_OK;
|
|
|
|
case ID_ADDRESS_BOOK:
|
|
HrViewContacts();
|
|
return S_OK;
|
|
|
|
//this is for office use only
|
|
case ID_CHECK_NAMES:
|
|
HrCheckNames(FALSE, TRUE);
|
|
return S_OK;
|
|
|
|
//this is for office use only
|
|
case ID_ENV_BCC:
|
|
if (m_pEnvelopeSite)
|
|
{
|
|
ShowAdvancedHeaders(!m_fAdvanced);
|
|
|
|
SetDwOption(OPT_MAILNOTEADVSEND, !!m_fAdvanced, NULL, NULL);
|
|
|
|
// ~~~~ m_pHeaderSite is mutually exclusive to m_pEnvelopeSite
|
|
//if (m_pHeaderSite)
|
|
// m_pHeaderSite->Update();
|
|
|
|
return S_OK;
|
|
}
|
|
break;
|
|
|
|
case ID_MESSAGE_OPTS:
|
|
ShowEnvOptions();
|
|
return S_OK;
|
|
|
|
case ID_SAVE_ATTACHMENTS:
|
|
case ID_NOTE_SAVE_ATTACHMENTS:
|
|
if (m_pHeaderSite)
|
|
m_pHeaderSite->SaveAttachment();
|
|
|
|
return S_OK;
|
|
|
|
// These next two should only be handled by the header if in the envelope
|
|
case ID_SEND_MESSAGE:
|
|
case ID_SEND_NOW:
|
|
if (m_pEnvelopeSite)
|
|
{
|
|
m_fShowedUnicodeDialog = FALSE;
|
|
m_iUnicodeDialogResult = 0;
|
|
|
|
HrSend();
|
|
return S_OK;
|
|
}
|
|
|
|
default:
|
|
if (id>=ID_ADDROBJ_OLE_FIRST && id <=ID_ADDROBJ_OLE_LAST)
|
|
{
|
|
DoNoteOleVerb(id-ID_ADDROBJ_OLE_FIRST);
|
|
return S_OK;
|
|
}
|
|
}
|
|
|
|
return S_FALSE;
|
|
}
|
|
|
|
HRESULT CNoteHdr::HrAutoComplete(HWND hwnd, PHCI pHCI)
|
|
{
|
|
CHARRANGE chrg, chrgCaret;
|
|
LPWSTR pszPartial, pszSemiColon, pszComma;
|
|
INT i, j, len, iTextLen;
|
|
LPWSTR pszBuf=0;
|
|
WCHAR szFound[cchMaxWab+1];
|
|
WCHAR sz;
|
|
HRESULT hr = NOERROR;
|
|
|
|
STACK("HrAutoComplete");
|
|
|
|
*szFound = 0;
|
|
|
|
// If the IME is open, bail out
|
|
if (0 < m_dwIMEStartCount)
|
|
return hr;
|
|
|
|
if (NULL==hwnd || NULL==m_pTable || NULL==pHCI)
|
|
return hr;
|
|
|
|
if (pHCI->dwACFlags&AC_IGNORE)
|
|
return hr;
|
|
|
|
SendMessage(hwnd, EM_EXGETSEL, 0, (LPARAM)&chrgCaret);
|
|
if (chrgCaret.cpMin != chrgCaret.cpMax)
|
|
return hr;
|
|
|
|
if (S_OK != HrGetFieldText(&pszBuf, hwnd))
|
|
return hr;
|
|
|
|
sz = pszBuf[chrgCaret.cpMin];
|
|
if (!(sz==0x0000 || sz==L' ' || sz==L';'|| sz==L',' || sz==L'\r'))
|
|
goto cleanup;
|
|
|
|
DOUTL(64, "HrAutoComplete- Didn't exit early");
|
|
|
|
pszBuf[chrgCaret.cpMin] = 0x0000;
|
|
pszSemiColon = StrRChrIW(pszBuf, &pszBuf[lstrlenW(pszBuf)], L';');
|
|
pszComma = StrRChrIW(pszBuf, &pszBuf[lstrlenW(pszBuf)], L',');
|
|
if (pszComma >= pszSemiColon)
|
|
pszPartial = pszComma;
|
|
else
|
|
pszPartial = pszSemiColon;
|
|
|
|
if (!pszPartial)
|
|
pszPartial = pszBuf;
|
|
else
|
|
pszPartial++;
|
|
|
|
//skip spaces and returns...
|
|
while (*pszPartial==L' ' || *pszPartial==L'\r' || *pszPartial==L'\n')
|
|
pszPartial++;
|
|
|
|
if (NULL == *pszPartial)
|
|
goto cleanup;
|
|
|
|
//Certain richedits put in 0xfffc for an object, if our text is only that, it's no good
|
|
if (*pszPartial==0xfffc && pszPartial[1]==0x0000)
|
|
goto cleanup;
|
|
|
|
len = lstrlenW(pszPartial);
|
|
m_lpWab->SearchPABTable(m_pTable, pszPartial, szFound, ARRAYSIZE(szFound));
|
|
|
|
if (*szFound != 0)
|
|
{
|
|
chrg.cpMin = chrgCaret.cpMin;
|
|
chrg.cpMax = chrg.cpMin + lstrlenW(szFound) - len;
|
|
if (chrg.cpMin < chrg.cpMax)
|
|
{
|
|
RichEditExSetSel(hwnd, &chrgCaret);
|
|
HdrSetRichEditText(hwnd, szFound + len, TRUE);
|
|
SendMessage(hwnd, EM_SETMODIFY, (WPARAM)(UINT)TRUE, 0);
|
|
RichEditExSetSel(hwnd, &chrg);
|
|
pHCI->dwACFlags |= AC_SELECTION;
|
|
}
|
|
}
|
|
|
|
cleanup:
|
|
MemFree(pszBuf);
|
|
return hr;
|
|
}
|
|
|
|
|
|
|
|
void CNoteHdr::WMPaint()
|
|
{
|
|
PAINTSTRUCT ps;
|
|
HDC hdc,
|
|
hdcMem;
|
|
RECT rc;
|
|
PHCI phci = m_rgHCI;
|
|
HBITMAP hbmMem;
|
|
|
|
int idc,
|
|
cxHeader,
|
|
cyHeader,
|
|
cxLabel = ControlXBufferSize(),
|
|
cyStatus,
|
|
cyLeftButtonOffset = BUTTON_BUFFER,
|
|
cxLabelWithBtn = cxLabel + CXOfButtonToLabel();
|
|
char sz[cchHeaderMax+1];
|
|
int cStatusBarLines = 0;
|
|
BOOL fBold;
|
|
HWND hwnd;
|
|
|
|
if (!m_hwnd)
|
|
return;
|
|
|
|
STACK("WMPaint");
|
|
|
|
if (m_fFlagged || (priLow == m_pri) || (priHigh == m_pri) || (MARK_MESSAGE_NORMALTHREAD != m_MarkType))
|
|
cStatusBarLines++;
|
|
|
|
if (m_lpAttMan->GetUnsafeAttachCount())
|
|
cStatusBarLines++;
|
|
|
|
hdc = BeginPaint(m_hwnd, &ps);
|
|
|
|
// **************** Init the background bitmap ****************
|
|
hdcMem = CreateCompatibleDC(hdc);
|
|
idc = SaveDC(hdcMem);
|
|
|
|
GetClientRect(m_hwnd, &rc);
|
|
cxHeader = rc.right;
|
|
cyHeader = rc.bottom;
|
|
|
|
hbmMem = CreateCompatibleBitmap(hdc, rc.right, rc.bottom);
|
|
SelectObject(hdcMem, (HGDIOBJ)hbmMem);
|
|
|
|
// **************** Clear the rect *****************
|
|
FillRect(hdcMem, &rc, GetSysColorBrush(COLOR_BTNFACE));
|
|
|
|
// **************** Setup the HDC ******************
|
|
fBold = IsReadOnly();
|
|
SetBkColor(hdcMem, GetSysColor(COLOR_BTNFACE)); // colour of header window
|
|
SetBkMode(hdcMem, TRANSPARENT);
|
|
SetTextColor(hdcMem, GetSysColor(COLOR_BTNTEXT));
|
|
SelectObject(hdcMem, GetFont(fBold));
|
|
|
|
// **************** Paint the left labels and buttons **************
|
|
// Center the buttons images
|
|
if (g_cyFont > cyBtn)
|
|
cyLeftButtonOffset += ((g_cyFont - cyBtn) / 2);
|
|
|
|
for (int i = 0; (ULONG)i < m_cHCI; i++, phci++)
|
|
{
|
|
if (S_OK == HrFShowHeader(phci))
|
|
{
|
|
if (HCF_HASBUTTON & phci->dwFlags)
|
|
{
|
|
TextOutW(hdcMem, cxLabelWithBtn, phci->cy + BUTTON_BUFFER, phci->sz, phci->strlen);
|
|
ImageList_Draw(g_himlBtns, (HCF_ADDRBOOK & phci->dwFlags)?0:1, hdcMem, cxLabel, phci->cy + cyLeftButtonOffset, ILD_NORMAL);
|
|
}
|
|
else
|
|
TextOutW(hdcMem, cxLabel, (HCF_BORDER & phci->dwFlags)? phci->cy + BUTTON_BUFFER: phci->cy, phci->sz, phci->strlen);
|
|
}
|
|
}
|
|
|
|
// **************** Paint the status bar as needed *******************
|
|
if (cStatusBarLines > 0)
|
|
{
|
|
int cxStatusBtn = ControlXBufferSize() + 1, // 1 added for the border
|
|
cyStatusBtn = m_dxTBOffset + cyBorder + 1, // 1 added for the border
|
|
cyStatusBmp = cyStatusBtn,
|
|
cNumButtons = 0;
|
|
LPTSTR pszTitles[3]={0};
|
|
|
|
// Center the buttons images
|
|
if (g_cyFont > cyBtn)
|
|
cyStatusBmp += ((g_cyFont - cyBtn) / 2);
|
|
|
|
// Fill the dark rect
|
|
rc.top = m_dxTBOffset;
|
|
rc.bottom = m_dxTBOffset + GetStatusHeight(cStatusBarLines);
|
|
FillRect(hdcMem, &rc, GetSysColorBrush(COLOR_BTNSHADOW));
|
|
InflateRect(&rc, -1, -1);
|
|
FillRect(hdcMem, &rc, GetSysColorBrush(COLOR_INFOBK));
|
|
|
|
// Set up the DC for the rest of the status bar
|
|
SetBkColor(hdcMem, GetSysColor(COLOR_INFOBK)); // colour of header window
|
|
SetTextColor(hdcMem, GetSysColor(COLOR_INFOTEXT));
|
|
SelectObject(hdcMem, GetFont(FALSE));
|
|
|
|
// Draw icons in status bar
|
|
if (priLow == m_pri)
|
|
{
|
|
ImageList_Draw(g_himlStatus, 1, hdcMem, cxStatusBtn, cyStatusBmp+2, ILD_NORMAL);
|
|
cxStatusBtn += cxFlagsDelta;
|
|
pszTitles[cNumButtons++] = g_szStatLowPri;
|
|
}
|
|
else if (priHigh == m_pri)
|
|
{
|
|
ImageList_Draw(g_himlStatus, 0, hdcMem, cxStatusBtn, cyStatusBmp+2, ILD_NORMAL);
|
|
cxStatusBtn += cxFlagsDelta;
|
|
pszTitles[cNumButtons++] = g_szStatHighPri;
|
|
}
|
|
|
|
if (MARK_MESSAGE_WATCH == m_MarkType)
|
|
{
|
|
ImageList_Draw(g_himlStatus, 4, hdcMem, cxStatusBtn, cyStatusBmp+2, ILD_NORMAL);
|
|
cxStatusBtn += cxFlagsDelta;
|
|
pszTitles[cNumButtons++] = g_szStatWatched;
|
|
}
|
|
else if (MARK_MESSAGE_IGNORE == m_MarkType)
|
|
{
|
|
ImageList_Draw(g_himlStatus, 5, hdcMem, cxStatusBtn, cyStatusBmp+2, ILD_NORMAL);
|
|
cxStatusBtn += cxFlagsDelta;
|
|
pszTitles[cNumButtons++] = g_szStatIgnored;
|
|
}
|
|
|
|
if (m_fFlagged)
|
|
{
|
|
ImageList_Draw(g_himlStatus, 2, hdcMem, cxStatusBtn, cyStatusBmp+2, ILD_NORMAL);
|
|
cxStatusBtn += cxFlagsDelta;
|
|
pszTitles[cNumButtons++] = g_szStatFlagged;
|
|
}
|
|
|
|
if (m_lpAttMan->GetUnsafeAttachCount())
|
|
{
|
|
ImageList_Draw(g_himlStatus, 6, hdcMem, cxStatusBtn, cyStatusBmp+2, ILD_NORMAL);
|
|
cxStatusBtn += cxFlagsDelta;
|
|
}
|
|
|
|
if (cNumButtons > 0)
|
|
{
|
|
char szHeaderString[cchHeaderMax*4+1];
|
|
|
|
// Add an additional pixel for the text.
|
|
cyStatusBtn++;
|
|
switch (cNumButtons)
|
|
{
|
|
case 1:
|
|
{
|
|
wnsprintf(szHeaderString, ARRAYSIZE(szHeaderString), g_szStatFormat1, pszTitles[0]);
|
|
TextOut(hdcMem, cxStatusBtn, cyStatusBtn, szHeaderString, lstrlen(szHeaderString));
|
|
break;
|
|
}
|
|
case 2:
|
|
{
|
|
wnsprintf(szHeaderString, ARRAYSIZE(szHeaderString), g_szStatFormat2, pszTitles[0], pszTitles[1]);
|
|
TextOut(hdcMem, cxStatusBtn, cyStatusBtn, szHeaderString, lstrlen(szHeaderString));
|
|
break;
|
|
}
|
|
case 3:
|
|
{
|
|
wnsprintf(szHeaderString, ARRAYSIZE(szHeaderString), g_szStatFormat3, pszTitles[0], pszTitles[1], pszTitles[2]);
|
|
TextOut(hdcMem, cxStatusBtn, cyStatusBtn, szHeaderString, lstrlen(szHeaderString));
|
|
break;
|
|
}
|
|
}
|
|
cyStatusBtn += CYOfStatusLine() - 1;
|
|
}
|
|
|
|
if (m_lpAttMan->GetUnsafeAttachCount())
|
|
{
|
|
char szHeaderString[cchHeaderMax*4+1];
|
|
|
|
// Add an additional pixel for the text.
|
|
cyStatusBtn++;
|
|
wnsprintf(szHeaderString, ARRAYSIZE(szHeaderString), g_szStatUnsafeAtt, m_lpAttMan->GetUnsafeAttachList());
|
|
TextOut(hdcMem, cxStatusBtn, cyStatusBtn, szHeaderString, lstrlen(szHeaderString));
|
|
}
|
|
}
|
|
|
|
// ************ Draw the right side buttons **************
|
|
if (m_fDigSigned || m_fEncrypted || m_fVCard)
|
|
{
|
|
int width = GetRightMargin(TRUE),
|
|
cx = cxHeader - (ControlXBufferSize() + cxBtn),
|
|
cy = BeginYPos() + BUTTON_BUFFER,
|
|
yDiff = cyBtn + ControlYBufferSize() + 2*BUTTON_BUFFER;
|
|
|
|
if (m_fDigSigned)
|
|
{
|
|
ImageList_Draw(g_himlSecurity, m_fSignTrusted?0:2, hdcMem, cx, cy, ILD_NORMAL);
|
|
cy += yDiff;
|
|
}
|
|
|
|
if (m_fEncrypted)
|
|
{
|
|
ImageList_Draw(g_himlSecurity, m_fEncryptionOK?1:3, hdcMem, cx, cy, ILD_NORMAL);
|
|
cy += yDiff;
|
|
}
|
|
|
|
if (m_fVCard)
|
|
{
|
|
ImageList_Draw(g_himlBtns, 2, hdcMem, cx, cy, ILD_NORMAL);
|
|
}
|
|
}
|
|
|
|
// Draw active button edge
|
|
if (HDRCB_NO_BUTTON != m_dwCurrentBtn)
|
|
{
|
|
DOUTL(PAINTING_DEBUG_LEVEL, "Framing button %d: (%d, %d) to (%d, %d)",
|
|
m_dwCurrentBtn, m_rcCurrentBtn.left, m_rcCurrentBtn.top, m_rcCurrentBtn.right, m_rcCurrentBtn.bottom);
|
|
if (HDRCB_NO_BUTTON == m_dwClickedBtn)
|
|
DrawEdge(hdcMem, &m_rcCurrentBtn, BDR_RAISEDINNER, BF_TOPRIGHT | BF_BOTTOMLEFT);
|
|
else
|
|
DrawEdge(hdcMem, &m_rcCurrentBtn, BDR_SUNKENINNER, BF_TOPRIGHT | BF_BOTTOMLEFT);
|
|
}
|
|
|
|
BitBlt(hdc, 0, 0, cxHeader, cyHeader, hdcMem, 0, 0, SRCCOPY);
|
|
|
|
RestoreDC(hdcMem, idc);
|
|
|
|
DeleteObject(hbmMem);
|
|
DeleteDC(hdcMem);
|
|
|
|
EndPaint(m_hwnd, &ps);
|
|
}
|
|
|
|
|
|
HRESULT CNoteHdr::HrFillToolbarColor(HDC hdc)
|
|
{
|
|
HRESULT hr = NOERROR;
|
|
RECT rc;
|
|
|
|
if (!m_hwndToolbar)
|
|
return hr;
|
|
|
|
GetRealClientRect(m_hwndToolbar, &rc);
|
|
FillRect(hdc, &rc, GetSysColorBrush(COLOR_3DFACE));
|
|
|
|
return hr;
|
|
}
|
|
|
|
|
|
HRESULT CNoteHdr::HrGetVCardName(LPTSTR pszName, DWORD cch)
|
|
{
|
|
HRESULT hr = E_FAIL;
|
|
|
|
if (pszName == NULL || cch==0)
|
|
goto error;
|
|
|
|
*pszName = 0;
|
|
if (m_fMail)
|
|
GetOption(OPT_MAIL_VCARDNAME, pszName, cch);
|
|
else
|
|
GetOption(OPT_NEWS_VCARDNAME, pszName, cch);
|
|
|
|
if (*pszName != 0)
|
|
hr = NOERROR;
|
|
|
|
error:
|
|
return hr;
|
|
}
|
|
|
|
// turn on or off the vcard stamp.
|
|
HRESULT CNoteHdr::HrOnOffVCard()
|
|
{
|
|
HRESULT hr = NOERROR;
|
|
RECT rc;
|
|
TOOLINFO ti = {0};
|
|
|
|
ti.cbSize = sizeof(TOOLINFO);
|
|
ti.uFlags = 0;
|
|
ti.uId = idVCardStamp;
|
|
ti.hinst=g_hLocRes;
|
|
ti.hwnd = m_hwnd;
|
|
|
|
if (m_fVCardSave == m_fVCard)
|
|
return hr;
|
|
else
|
|
m_fVCardSave = m_fVCard;
|
|
|
|
if (m_fVCard)
|
|
{
|
|
ti.lpszText = (LPTSTR)idsTTVCardStamp;
|
|
|
|
SendMessage(m_hwndTT, TTM_ADDTOOL, 0, (LPARAM) &ti);
|
|
}
|
|
else
|
|
SendMessage(m_hwndTT, TTM_DELTOOL, 0, (LPARAM) &ti);
|
|
|
|
InvalidateRightMargin(0);
|
|
ReLayout();
|
|
|
|
return hr;
|
|
}
|
|
|
|
HRESULT CNoteHdr::HrGetVCardState(ULONG* pCmdf)
|
|
{
|
|
TCHAR szBuf[MAX_PATH];
|
|
HRESULT hr;
|
|
|
|
// if OLECMDF_LATCHED is on, insert vcard menu should be checked.
|
|
if (m_fVCard)
|
|
*pCmdf |= OLECMDF_LATCHED;
|
|
|
|
hr = HrGetVCardName(szBuf, sizeof(szBuf));
|
|
if (FAILED(hr)) // no vcard name selected
|
|
{
|
|
*pCmdf &= ~OLECMDF_ENABLED;
|
|
*pCmdf &= ~OLECMDF_LATCHED;
|
|
}
|
|
else
|
|
*pCmdf |= OLECMDF_ENABLED;
|
|
|
|
return NOERROR;
|
|
}
|
|
|
|
|
|
HRESULT CNoteHdr::HrShowVCardCtxtMenu(int x, int y)
|
|
{
|
|
HMENU hPopup=0;
|
|
HRESULT hr = E_FAIL;
|
|
POINT pt;
|
|
|
|
if (!m_fVCard)
|
|
goto exit;
|
|
|
|
// Pop up the context menu.
|
|
hPopup = LoadPopupMenu(IDR_VCARD_POPUP);
|
|
if (!hPopup)
|
|
goto exit;
|
|
|
|
if (IsReadOnly())
|
|
EnableMenuItem(hPopup, ID_DELETE_VCARD, MF_BYCOMMAND|MF_DISABLED|MF_GRAYED);
|
|
|
|
pt.x = x;
|
|
pt.y = y;
|
|
ClientToScreen(m_hwnd, &pt);
|
|
TrackPopupMenuEx( hPopup, TPM_LEFTALIGN|TPM_LEFTBUTTON|TPM_RIGHTBUTTON,
|
|
pt.x, pt.y, m_hwnd, NULL);
|
|
|
|
hr = NOERROR;
|
|
|
|
exit:
|
|
if (hPopup)
|
|
DestroyMenu(hPopup);
|
|
|
|
return hr;
|
|
}
|
|
|
|
HRESULT CNoteHdr::HrShowVCardProperties(HWND hwnd)
|
|
{
|
|
HRESULT hr = NOERROR;
|
|
LPWAB lpWab = NULL;
|
|
TCHAR szName[MAX_PATH] = {0};
|
|
UINT cb = 0;
|
|
|
|
if (IsReadOnly() && m_lpAttMan)
|
|
return m_lpAttMan->HrShowVCardProp();
|
|
|
|
//else
|
|
// return E_FAIL;
|
|
|
|
hr = HrGetVCardName(szName, sizeof(szName));
|
|
if (FAILED(hr))
|
|
goto error;
|
|
|
|
hr = HrCreateWabObject(&lpWab);
|
|
if (FAILED(hr))
|
|
goto error;
|
|
|
|
//load names into the combobox from personal address book
|
|
hr = lpWab->HrEditEntry(hwnd, szName, ARRAYSIZE(szName));
|
|
if (FAILED(hr))
|
|
goto error;
|
|
|
|
error:
|
|
if (FAILED(hr) && hr!=MAPI_E_USER_CANCEL)
|
|
AthMessageBoxW(hwnd, MAKEINTRESOURCEW(idsAthena), MAKEINTRESOURCEW(idsErrVCardProperties),
|
|
NULL, MB_OK | MB_ICONEXCLAMATION);
|
|
|
|
ReleaseObj(lpWab);
|
|
return hr;
|
|
}
|
|
|
|
|
|
LRESULT CALLBACK CNoteHdr::IMESubClassProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam, PHCI phci)
|
|
{
|
|
CNoteHdr *pnh = NULL;
|
|
HWND hwndParent = GetParent(hwnd);
|
|
|
|
STACK("IMESubClassProc");
|
|
|
|
if (IsWindow(hwndParent))
|
|
{
|
|
// Get the header class of the header window
|
|
pnh = (CNoteHdr *)GetWndThisPtr(hwndParent);
|
|
|
|
switch (msg)
|
|
{
|
|
case WM_IME_STARTCOMPOSITION:
|
|
DOUTL(64, "WM_IME_STARTCOMPOSITION");
|
|
pnh->m_dwIMEStartCount++;
|
|
break;
|
|
|
|
case WM_IME_ENDCOMPOSITION:
|
|
DOUTL(64, "WM_IME_ENDCOMPOSITION");
|
|
|
|
// Make sure we don't go negative.
|
|
if (0 < pnh->m_dwIMEStartCount)
|
|
{
|
|
pnh->m_dwIMEStartCount--;
|
|
}
|
|
else
|
|
{
|
|
AssertSz(FALSE, "We just received an extra WM_IME_ENDCOMPOSITION");
|
|
DOUTL(64, "WM_IME_ENDCOMPOSITION, not expected");
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
|
|
// Defer to the default window proc
|
|
return CallWindowProcWrapW(g_lpfnREWndProc, hwnd, msg, wParam, lParam);
|
|
}
|
|
|
|
// bug #28379
|
|
// this is a hack to work around RichEd32 4.0 above bug in which
|
|
// it did not syncronize the keyboard change in the child windows.
|
|
// we use these global variable to keep track which keyboard
|
|
// is using now.
|
|
static HKL g_hCurrentKeyboardHandle = NULL ;
|
|
static BOOL g_fBiDiSystem = (BOOL) GetSystemMetrics(SM_MIDEASTENABLED);
|
|
static TCHAR g_chLastPressed = 0;
|
|
LRESULT CALLBACK CNoteHdr::EditSubClassProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
|
|
{
|
|
HDC hdc;
|
|
PAINTSTRUCT ps;
|
|
int idcKeep;
|
|
PHCI phci;
|
|
LRESULT lRet;
|
|
CHARRANGE chrg;
|
|
|
|
phci=(PHCI)GetWndThisPtr(hwnd);
|
|
Assert(phci);
|
|
Assert(g_lpfnREWndProc);
|
|
|
|
|
|
if (phci && (phci->dwFlags&HCF_ADDRWELL))
|
|
{
|
|
switch (msg)
|
|
{
|
|
case WM_IME_STARTCOMPOSITION:
|
|
case WM_IME_ENDCOMPOSITION:
|
|
return IMESubClassProc(hwnd, msg, wParam, lParam, phci);
|
|
|
|
case WM_CUT:
|
|
// if cutting a selection, make sure we don't autocomplete when we get the en_change
|
|
goto cut;
|
|
|
|
case WM_KEYDOWN:
|
|
if (VK_BACK==wParam ||
|
|
VK_DELETE==wParam ||
|
|
((GetKeyState(VK_CONTROL)&0x8000) && ('x'==wParam || 'X'==wParam)))
|
|
{
|
|
// if deleting a selection, make sure we don't autocomplete when we get the en_change
|
|
cut:
|
|
phci->dwACFlags |= AC_IGNORE;
|
|
lRet = CallWindowProcWrapW(g_lpfnREWndProc, hwnd, msg, wParam, lParam);
|
|
phci->dwACFlags &= ~AC_IGNORE;
|
|
return lRet;
|
|
}
|
|
else if (phci->dwACFlags&AC_SELECTION && (VK_RETURN==wParam))
|
|
{
|
|
SendMessage(hwnd, EM_EXGETSEL, 0, (LPARAM)&chrg);
|
|
if (chrg.cpMin < chrg.cpMax)
|
|
{
|
|
chrg.cpMin = chrg.cpMax;
|
|
SendMessage(hwnd, EM_EXSETSEL, 0, (LPARAM)&chrg);
|
|
HdrSetRichEditText(hwnd, (',' == wParam) ? L", ": L"; ", TRUE);
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
// bobn: brianv says we have to take this out...
|
|
/*if ((g_dwBrowserFlags == 3) && (GetKeyState(VK_CONTROL)&0x8000) && (GetKeyState(VK_SHIFT)&0x8000))
|
|
{
|
|
switch(wParam) {
|
|
case 'R':
|
|
g_chLastPressed = (g_chLastPressed == 0) ? 'R' : 0;
|
|
break;
|
|
case 'O':
|
|
g_chLastPressed = (g_chLastPressed == 'R') ? 'O' : 0;
|
|
break;
|
|
case 'C':
|
|
g_chLastPressed = (g_chLastPressed == 'O') ? 'C' : 0;
|
|
break;
|
|
case 'K':
|
|
if (g_chLastPressed == 'C')
|
|
g_dwBrowserFlags |= 4;
|
|
g_chLastPressed = 0;
|
|
break;
|
|
}
|
|
}*/
|
|
break;
|
|
|
|
case WM_CHAR:
|
|
// VK_RETURN is no longer sent as a WM_CHAR so we place it in the
|
|
// WM_KEYDOWN. RAID 75444
|
|
if (phci->dwACFlags&AC_SELECTION && (wParam==',' || wParam==';'))
|
|
{
|
|
SendMessage(hwnd, EM_EXGETSEL, 0, (LPARAM)&chrg);
|
|
if (chrg.cpMin < chrg.cpMax)
|
|
{
|
|
chrg.cpMin = chrg.cpMax;
|
|
SendMessage(hwnd, EM_EXSETSEL, 0, (LPARAM)&chrg);
|
|
HdrSetRichEditText(hwnd, (wParam==',') ? L", ": L"; ", TRUE);
|
|
return 0;
|
|
}
|
|
}
|
|
break;
|
|
|
|
case WM_SETFOCUS:
|
|
if(g_fBiDiSystem)
|
|
{
|
|
HKL hklUS = NULL;
|
|
GetUSKeyboardLayout(&hklUS);
|
|
ActivateKeyboardLayout(hklUS, 0);
|
|
}
|
|
break;
|
|
|
|
}
|
|
}
|
|
|
|
// bug #28379
|
|
// this is a hack to work around RichEd32 4.0 above bug in which
|
|
// it did not syncronize the keyboard change in the child windows.
|
|
// we use these global variable to keep track which keyboard
|
|
// is using now.
|
|
|
|
//a-msadek; bug# 45709
|
|
// BiDi richedit uses WM_INPUTLANGCHANGE to determine reading order
|
|
// This will make it confused causing Latin text displayed flipped
|
|
if(!g_fBiDiSystem)
|
|
{
|
|
if (msg == WM_INPUTLANGCHANGE )
|
|
{
|
|
if ( g_hCurrentKeyboardHandle &&
|
|
g_hCurrentKeyboardHandle != (HKL) lParam )
|
|
ActivateKeyboardLayout(g_hCurrentKeyboardHandle, 0 );
|
|
}
|
|
if (msg == WM_INPUTLANGCHANGEREQUEST )
|
|
g_hCurrentKeyboardHandle = (HKL) lParam ;
|
|
}
|
|
|
|
// dispatch subject off to regular edit wndproc, and to & cc off to the RE wnd proc.
|
|
return CallWindowProcWrapW(g_lpfnREWndProc, hwnd, msg, wParam, lParam);
|
|
}
|
|
|
|
void GetUSKeyboardLayout(HKL *phkl)
|
|
{
|
|
UINT cNumkeyboards = 0, i;
|
|
HKL* phKeyboadList = NULL;
|
|
HKL hKeyboardUS = NULL;
|
|
// Let's check how many keyboard the system has
|
|
cNumkeyboards = GetKeyboardLayoutList(0, phKeyboadList);
|
|
|
|
phKeyboadList = (HKL*)LocalAlloc(LPTR, cNumkeyboards * sizeof(HKL));
|
|
cNumkeyboards = GetKeyboardLayoutList(cNumkeyboards, phKeyboadList);
|
|
|
|
for (i = 0; i < cNumkeyboards; i++)
|
|
{
|
|
LANGID LangID = PRIMARYLANGID(LANGIDFROMLCID(LOWORD(phKeyboadList[i])));
|
|
if(LangID == LANG_ENGLISH)
|
|
{
|
|
*phkl = phKeyboadList[i];
|
|
break;
|
|
}
|
|
}
|
|
if(phKeyboadList)
|
|
{
|
|
LocalFree((HLOCAL)phKeyboadList);
|
|
}
|
|
}
|
|
|
|
HRESULT CNoteHdr::HrUpdateTooltipPos()
|
|
{
|
|
TOOLINFO ti;
|
|
|
|
if (m_hwndTT)
|
|
{
|
|
/* ti.cbSize = sizeof(TOOLINFO);
|
|
ti.hwnd = m_hwnd;
|
|
ti.uId = idStamp;
|
|
::SetRect(&ti.rect, m_ptStamp.x, m_ptStamp.y, m_ptStamp.x + cxStamp, m_ptStamp.y + cyStamp);
|
|
SendMessage(m_hwndTT, TTM_NEWTOOLRECT, 0, (LPARAM) &ti);
|
|
|
|
if (m_fVCard)
|
|
{
|
|
ti.uFlags = 0;
|
|
ti.uId = idVCardStamp;
|
|
ti.lpszText = (LPTSTR) idsTTVCardStamp;
|
|
if (m_pri!=priNone) //mail
|
|
::SetRect(&ti.rect, m_ptStamp.x, m_ptStamp.y*2+cyStamp, m_ptStamp.x + cxStamp, 2*(m_ptStamp.y+cyStamp));
|
|
else // news
|
|
::SetRect(&ti.rect, m_ptStamp.x, m_ptStamp.y, m_ptStamp.x + cxStamp, m_ptStamp.y + cyStamp);
|
|
|
|
SendMessage(m_hwndTT, TTM_NEWTOOLRECT, 0, (LPARAM) &ti);
|
|
}*/
|
|
|
|
}
|
|
return NOERROR;
|
|
}
|
|
|
|
HRESULT CNoteHdr::HrInit(IMimeMessage *pMsg)
|
|
{
|
|
HWND hwnd;
|
|
HRESULT hr=S_OK;
|
|
|
|
if (m_hwnd) // already running
|
|
return S_OK;
|
|
|
|
if (!FInitRichEdit(TRUE))
|
|
return E_FAIL;
|
|
|
|
if (!m_pEnvelopeSite)
|
|
{
|
|
Assert(m_hwndParent);
|
|
hwnd=CreateWindowExWrapW( WS_EX_CONTROLPARENT|WS_EX_NOPARENTNOTIFY,
|
|
WC_ATHHEADER,
|
|
NULL,
|
|
WS_VISIBLE|WS_CLIPSIBLINGS|WS_CLIPCHILDREN|WS_CHILD,
|
|
0,0,0,0,
|
|
m_hwndParent,
|
|
(HMENU)idcNoteHdr,
|
|
g_hInst, (LPVOID)this );
|
|
}
|
|
else
|
|
{
|
|
Assert(!m_hwnd);
|
|
|
|
hr = HrOfficeInitialize(TRUE);
|
|
if (FAILED(hr))
|
|
goto error;
|
|
|
|
m_hwndParent = g_hwndInit;
|
|
|
|
hwnd=CreateWindowExWrapW(WS_EX_CONTROLPARENT|WS_EX_NOPARENTNOTIFY,
|
|
WC_ATHHEADER,
|
|
NULL,
|
|
WS_CLIPSIBLINGS|WS_CLIPCHILDREN|WS_CHILD,
|
|
0,0,0,0,
|
|
m_hwndParent,
|
|
(HMENU)idcNoteHdr,
|
|
g_hInst, (LPVOID)this);
|
|
|
|
if (!hwnd)
|
|
{
|
|
hr = E_FAIL;
|
|
goto error;
|
|
}
|
|
|
|
m_ntNote = OENA_COMPOSE;
|
|
m_fMail = TRUE;
|
|
|
|
if (pMsg)
|
|
hr = Load(pMsg);
|
|
else
|
|
hr = HrOfficeLoad();
|
|
if (FAILED(hr))
|
|
goto error;
|
|
}
|
|
|
|
|
|
if (!hwnd)
|
|
{
|
|
hr=E_OUTOFMEMORY;
|
|
goto error;
|
|
}
|
|
|
|
m_hwnd = hwnd;
|
|
m_fDirty=FALSE;
|
|
|
|
error:
|
|
return hr;
|
|
}
|
|
|
|
|
|
HRESULT CNoteHdr::HrOfficeInitialize(BOOL fInit)
|
|
{
|
|
HRESULT hr = E_FAIL;
|
|
|
|
if (fInit)
|
|
{
|
|
hr = CoIncrementInit("CNoteHdr::HrOfficeInitialize", MSOEAPI_START_COMOBJECT, NULL, &m_hInitRef);
|
|
if (FAILED(hr))
|
|
return hr;
|
|
|
|
if (!FHeader_Init(TRUE))
|
|
return E_FAIL;
|
|
|
|
m_fAutoComplete = TRUE;
|
|
m_fDirty=FALSE;
|
|
|
|
hr = _RegisterWithComponentMgr(TRUE);
|
|
if (FAILED(hr))
|
|
return E_FAIL;
|
|
|
|
m_fOfficeInit = TRUE;
|
|
}
|
|
else
|
|
{
|
|
if (m_hInitRef)
|
|
CoDecrementInit("CNoteHdr::HrOfficeInitialize", &m_hInitRef);
|
|
|
|
}
|
|
|
|
return NOERROR;
|
|
}
|
|
|
|
|
|
void CNoteHdr::OnNCDestroy()
|
|
{
|
|
if (m_rgHCI)
|
|
{
|
|
MemFree(m_rgHCI);
|
|
m_rgHCI = NULL;
|
|
m_cHCI = 0;
|
|
}
|
|
|
|
_RegisterAsDropTarget(FALSE);
|
|
_RegisterWithFontCache(FALSE);
|
|
|
|
SafeRelease(m_pHeaderSite);
|
|
SafeRelease(m_pEnvelopeSite);
|
|
|
|
m_hwnd = NULL;
|
|
}
|
|
|
|
void CNoteHdr::OnDestroy()
|
|
{
|
|
HrFreeFieldList();
|
|
|
|
if (m_lpAttMan)
|
|
m_lpAttMan->HrClose();
|
|
|
|
// release office interfaces if we get torn down
|
|
_RegisterWithComponentMgr(FALSE);
|
|
}
|
|
|
|
|
|
HRESULT CNoteHdr::ShowAdvancedHeaders(BOOL fShow)
|
|
{
|
|
if (!!m_fAdvanced != fShow)
|
|
{
|
|
m_fAdvanced=fShow;
|
|
|
|
ReLayout();
|
|
|
|
if (m_hwndToolbar)
|
|
SendMessage(m_hwndToolbar, TB_CHECKBUTTON, ID_ENV_BCC, MAKELONG(!!m_fAdvanced, 0));
|
|
}
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
|
|
HRESULT CNoteHdr::HrFShowHeader(PHCI phci)
|
|
{
|
|
Assert(phci);
|
|
|
|
if (phci->dwFlags & HCF_COMBO)
|
|
{
|
|
if (m_cAccountIDs < 2)
|
|
return S_FALSE;
|
|
else
|
|
return S_OK;
|
|
}
|
|
|
|
if (phci->dwFlags & HCF_ATTACH)
|
|
{
|
|
if (!m_fStillLoading)
|
|
{
|
|
ULONG cAttMan = 0;
|
|
HrGetAttachCount(&cAttMan);
|
|
|
|
if (cAttMan)
|
|
return S_OK;
|
|
}
|
|
return S_FALSE;
|
|
}
|
|
|
|
if (phci->dwFlags & HCF_ADVANCED)
|
|
{
|
|
if (IsReadOnly())
|
|
{
|
|
// If it is a read note and CC is empty, don't show
|
|
if (phci->fEmpty)
|
|
return S_FALSE;
|
|
}
|
|
else
|
|
// If is a send note and not suppose to show adv headers, don't show
|
|
if (!m_fAdvanced)
|
|
return S_FALSE;
|
|
}
|
|
|
|
if ((phci->dwFlags & HCF_OPTIONAL) && !DwGetOption(phci->dwOpt))
|
|
return S_FALSE;
|
|
|
|
if (phci->dwFlags & HCF_HIDDEN)
|
|
return S_FALSE;
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
// =================================================================================
|
|
// SzGetDisplaySec
|
|
// returns the security enhancements and state of such for this message
|
|
// Params:
|
|
// OUT pidsLabel - if non-NULL, will contain the ids for the field name
|
|
// Returns:
|
|
// a built string giving information about the signature and/or encryption
|
|
// =================================================================================
|
|
LPWSTR CNoteHdr::SzGetDisplaySec(LPMIMEMESSAGE pMsg, int *pidsLabel)
|
|
{
|
|
WCHAR szResource[CCHMAX_STRINGRES];
|
|
LPWSTR lpszLabel = NULL;
|
|
DWORD cchSecurityField = 0;
|
|
|
|
if (m_lpszSecurityField)
|
|
{
|
|
MemFree(m_lpszSecurityField);
|
|
m_lpszSecurityField = NULL;
|
|
}
|
|
|
|
// check label first.
|
|
if ((m_ntNote == OENA_READ) && pMsg)
|
|
{
|
|
HrGetLabelString(pMsg, &lpszLabel);
|
|
}
|
|
|
|
|
|
if (pidsLabel)
|
|
*pidsLabel=idsSecurityField;
|
|
|
|
UINT labelLen = 1;
|
|
if(lpszLabel)
|
|
{
|
|
//Bug #101350 - lstrlenW will AV (and handle it) if passed a NULL
|
|
labelLen += lstrlenW(lpszLabel);
|
|
}
|
|
|
|
// need to build string
|
|
cchSecurityField = (2 * CCHMAX_STRINGRES + labelLen);
|
|
if (!MemAlloc((LPVOID *)&m_lpszSecurityField, (cchSecurityField *sizeof(WCHAR))))
|
|
return NULL;
|
|
|
|
*m_lpszSecurityField = L'\0';
|
|
|
|
// Example: "Digitally signed - signature unverifiable; Encrypted - Certificate is trusted"
|
|
|
|
if (MST_SIGN_MASK & m_SecState.type)
|
|
{
|
|
AthLoadStringW(idsSecurityLineDigSign, szResource, ARRAYSIZE(szResource));
|
|
StrCpyNW(m_lpszSecurityField, szResource, cchSecurityField);
|
|
|
|
if (IsSignTrusted(&m_SecState))
|
|
AthLoadStringW(idsSecurityLineSignGood, szResource, ARRAYSIZE(szResource));
|
|
else if (MSV_BADSIGNATURE & m_SecState.ro_msg_validity)
|
|
AthLoadStringW(idsSecurityLineSignBad, szResource, ARRAYSIZE(szResource));
|
|
else if ((MSV_UNVERIFIABLE & m_SecState.ro_msg_validity) ||
|
|
(MSV_MALFORMEDSIG & m_SecState.ro_msg_validity))
|
|
AthLoadStringW(idsSecurityLineSignUnsure, szResource, ARRAYSIZE(szResource));
|
|
|
|
else if ((ATHSEC_NOTRUSTWRONGADDR & m_SecState.user_validity) &&
|
|
((m_SecState.user_validity & ~ATHSEC_NOTRUSTWRONGADDR) == ATHSEC_TRUSTED) &&
|
|
(! m_SecState.ro_msg_validity))
|
|
{
|
|
AthLoadStringW(idsSecurityLineSignPreProblem, szResource, ARRAYSIZE(szResource));
|
|
StrCatBuffW(m_lpszSecurityField, szResource, cchSecurityField);
|
|
AthLoadStringW(idsSecurityLineSignMismatch, szResource, ARRAYSIZE(szResource));
|
|
}
|
|
|
|
else if (((ATHSEC_TRUSTED != m_SecState.user_validity) && m_SecState.fHaveCert) ||
|
|
(MSV_EXPIRED_SIGNINGCERT & m_SecState.ro_msg_validity))
|
|
{
|
|
AthLoadStringW(idsSecurityLineSignPreProblem, szResource, ARRAYSIZE(szResource));
|
|
|
|
if (ATHSEC_TRUSTED != m_SecState.user_validity)
|
|
{
|
|
int nNotTrust = 0;
|
|
|
|
StrCatBuffW(m_lpszSecurityField, szResource, cchSecurityField);
|
|
|
|
// ignore revokedness for now
|
|
if (ATHSEC_NOTRUSTUNKNOWN & m_SecState.user_validity)
|
|
{
|
|
AthLoadStringW(idsSecurityLineSignUntrusted, szResource, ARRAYSIZE(szResource));
|
|
}
|
|
else if(ATHSEC_NOTRUSTREVOKED & m_SecState.user_validity)
|
|
{
|
|
AthLoadStringW(idsSecurityLineSignRevoked, szResource, ARRAYSIZE(szResource));
|
|
nNotTrust = 1;
|
|
}
|
|
else if(ATHSEC_NOTRUSTOTHER & m_SecState.user_validity)
|
|
{
|
|
AthLoadStringW(idsSecurityLineSignOthers, szResource, ARRAYSIZE(szResource));
|
|
nNotTrust = 1;
|
|
}
|
|
else if(m_SecState.user_validity & ATHSEC_NOTRUSTWRONGADDR)
|
|
{
|
|
AthLoadStringW(idsSecurityLineSignMismatch, szResource, ARRAYSIZE(szResource));
|
|
nNotTrust = 1;
|
|
}
|
|
else // if(!(m_SecState.user_validity & ATHSEC_NOTRUSTNOTTRUSTED))
|
|
AthLoadStringW(idsSecurityLineSignDistrusted, szResource, ARRAYSIZE(szResource));
|
|
|
|
if((m_SecState.user_validity & ATHSEC_NOTRUSTNOTTRUSTED) && nNotTrust)
|
|
{
|
|
StrCatBuffW(m_lpszSecurityField, szResource, cchSecurityField);
|
|
AthLoadStringW(idsSecurityLineListStr, szResource, ARRAYSIZE(szResource));
|
|
StrCatBuffW(m_lpszSecurityField, szResource, cchSecurityField);
|
|
AthLoadStringW(idsSecurityLineSignDistrusted, szResource, ARRAYSIZE(szResource));
|
|
}
|
|
|
|
if (MSV_EXPIRED_SIGNINGCERT & m_SecState.ro_msg_validity)
|
|
{
|
|
StrCatBuffW(m_lpszSecurityField, szResource, cchSecurityField);
|
|
AthLoadStringW(idsSecurityLineListStr, szResource, ARRAYSIZE(szResource));
|
|
}
|
|
}
|
|
if (MSV_EXPIRED_SIGNINGCERT & m_SecState.ro_msg_validity)
|
|
{
|
|
StrCatBuffW(m_lpszSecurityField, szResource, cchSecurityField);
|
|
AthLoadStringW(idsSecurityLineSignExpired, szResource, ARRAYSIZE(szResource));
|
|
}
|
|
}
|
|
else
|
|
{
|
|
AthLoadStringW(idsSecurityLineSignUnsure, szResource, ARRAYSIZE(szResource));
|
|
}
|
|
StrCatBuffW(m_lpszSecurityField, szResource, cchSecurityField);
|
|
|
|
if (MST_ENCRYPT_MASK & m_SecState.type)
|
|
{
|
|
AthLoadStringW(idsSecurityLineBreakStr, szResource, ARRAYSIZE(szResource));
|
|
StrCatBuffW(m_lpszSecurityField, szResource, cchSecurityField);
|
|
}
|
|
}
|
|
|
|
if (MST_ENCRYPT_MASK & m_SecState.type)
|
|
{
|
|
AthLoadStringW(idsSecurityLineEncryption, szResource, ARRAYSIZE(szResource));
|
|
StrCatBuffW(m_lpszSecurityField, szResource, cchSecurityField);
|
|
|
|
if (MSV_OK == (m_SecState.ro_msg_validity & MSV_ENCRYPT_MASK))
|
|
AthLoadStringW(idsSecurityLineEncGood, szResource, ARRAYSIZE(szResource));
|
|
else if (MSV_CANTDECRYPT & m_SecState.ro_msg_validity)
|
|
AthLoadStringW(idsSecurityLineEncBad, szResource, ARRAYSIZE(szResource));
|
|
else if (MSV_ENC_FOR_EXPIREDCERT & m_SecState.ro_msg_validity)
|
|
AthLoadStringW(idsSecurityLineEncExpired, szResource, ARRAYSIZE(szResource));
|
|
else
|
|
{
|
|
DOUTL(DOUTL_CRYPT, "CRYPT: bad encrypt state in SzGetDisplaySec");
|
|
szResource[0] = _T('\000');
|
|
}
|
|
StrCatBuffW(m_lpszSecurityField, szResource, cchSecurityField);
|
|
}
|
|
|
|
if(lpszLabel != NULL)
|
|
{
|
|
AthLoadStringW(idsSecurityLineBreakStr, szResource, ARRAYSIZE(szResource));
|
|
StrCatBuffW(m_lpszSecurityField, szResource, cchSecurityField);
|
|
StrCatBuffW(m_lpszSecurityField, lpszLabel, cchSecurityField);
|
|
MemFree(lpszLabel);
|
|
}
|
|
return m_lpszSecurityField;
|
|
}
|
|
|
|
|
|
HRESULT CNoteHdr::HrClearUndoStack()
|
|
{
|
|
int iHC;
|
|
HWND hwndRE;
|
|
|
|
for (iHC=0; iHC<(int)m_cHCI; iHC++)
|
|
{
|
|
if (hwndRE = GetDlgItem(m_hwnd, m_rgHCI[iHC].idEdit))
|
|
SendMessage(hwndRE, EM_EMPTYUNDOBUFFER, 0, 0);
|
|
}
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
// There are some cases where we don't wan't the resolve name to
|
|
// be skipped. For example, a resolve name during a save will set
|
|
// m_fAddressesChanged to be false. That is fine, except it doesn't
|
|
// underline the addresses. So when the user tries to resolve the name
|
|
// by doing the resolve name command, the name will appear not to
|
|
// be resolved. In this case, we don't want the next call to HrCheckNames
|
|
// to be skipped.
|
|
HRESULT CNoteHdr::HrCheckNames(BOOL fSilent, BOOL fSetCheckedFlag)
|
|
{
|
|
HRESULT hr;
|
|
|
|
if (!m_fAddressesChanged)
|
|
return S_OK;
|
|
|
|
if (m_fPoster && (OENA_READ != m_ntNote))
|
|
{
|
|
//We need to setmodify the cc field.
|
|
//We need to do this because this field is not typed in by the user.
|
|
Edit_SetModify(GetDlgItem(m_hwnd, idADCc), TRUE);
|
|
}
|
|
|
|
hr = m_pAddrWells->HrCheckNames(m_hwnd, fSilent ? CNF_DONTRESOLVE : 0);
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
if (m_lpWabal == NULL)
|
|
hr = hrNoRecipients;
|
|
else
|
|
{
|
|
ADRINFO AdrInfo;
|
|
if (!m_lpWabal->FGetFirst(&AdrInfo))
|
|
hr = hrNoRecipients;
|
|
}
|
|
|
|
if (SUCCEEDED(hr) && fSetCheckedFlag)
|
|
m_fAddressesChanged = FALSE;
|
|
}
|
|
return hr;
|
|
}
|
|
|
|
HRESULT CNoteHdr::HrCheckGroups(BOOL fPosting)
|
|
{
|
|
HRESULT hr = S_OK;
|
|
BOOL fFailed = FALSE;
|
|
ULONG cReplyTo=0;
|
|
ADRINFO adrInfo;
|
|
BOOL fOneOrMoreNames = FALSE;
|
|
BOOL fMoreNames = FALSE;
|
|
TCHAR szAcctID[CCHMAX_ACCOUNT_NAME];
|
|
FOLDERID idServer = FOLDERID_INVALID;
|
|
|
|
if (!m_pAccount)
|
|
return E_FAIL;
|
|
|
|
m_pAccount->GetPropSz(AP_ACCOUNT_ID, szAcctID, sizeof(szAcctID));
|
|
// find the parent folder id of the account
|
|
hr = g_pStore->FindServerId(szAcctID, &idServer);
|
|
if (FAILED(hr))
|
|
return hr;
|
|
|
|
// check the group names...
|
|
hr = ResolveGroupNames(m_hwnd, idADNewsgroups, idServer, FALSE, &fMoreNames);
|
|
fOneOrMoreNames = fMoreNames;
|
|
fFailed = FAILED(hr);
|
|
|
|
// Check followup names
|
|
hr = ResolveGroupNames(m_hwnd, idTXTFollowupTo, idServer, TRUE, &fMoreNames);
|
|
fOneOrMoreNames = (fOneOrMoreNames || fMoreNames);
|
|
fFailed = fFailed || FAILED(hr);
|
|
|
|
if (!fOneOrMoreNames)
|
|
return hrNoRecipients;
|
|
|
|
if (fPosting)
|
|
{
|
|
// make sure there is only one reply-to person, in the wabal
|
|
if (m_lpWabal->FGetFirst(&adrInfo))
|
|
do
|
|
if (adrInfo.lRecipType == MAPI_REPLYTO)
|
|
cReplyTo++;
|
|
while (m_lpWabal->FGetNext(&adrInfo));
|
|
|
|
if (cReplyTo>1)
|
|
{
|
|
// this is not cool. Don't allow then to post...
|
|
AthMessageBoxW(m_hwnd, MAKEINTRESOURCEW(idsAthenaNews), MAKEINTRESOURCEW(idsErrOnlyOneReplyTo), NULL, MB_OK);
|
|
return hrTooManyReplyTo;
|
|
}
|
|
}
|
|
|
|
if (fPosting && fFailed)
|
|
{
|
|
if (IDYES == AthMessageBoxW(m_hwnd, MAKEINTRESOURCEW(idsAthenaNews), MAKEINTRESOURCEW(idsIgnoreResolveError), 0, MB_ICONEXCLAMATION |MB_YESNO))
|
|
hr = S_OK;
|
|
else
|
|
hr = MAPI_E_USER_CANCEL;
|
|
}
|
|
|
|
return hr;
|
|
}
|
|
|
|
|
|
HRESULT CNoteHdr::ResolveGroupNames(HWND hwnd, int idField, FOLDERID idServer, BOOL fPosterAllowed, BOOL *fOneOrMoreNames)
|
|
{
|
|
HRESULT hr = S_OK;
|
|
FOLDERINFO Folder;
|
|
int nResolvedNames = 0;
|
|
|
|
AssertSz((idServer != FOLDERID_INVALID), TEXT("ResolveGroupNames: [ARGS] No account folder"));
|
|
|
|
// Now loop through the group names and see if they all exist. First make
|
|
// a copy of the string since strtok is destructive.
|
|
LPWSTR pwszBuffer = NULL;
|
|
LPSTR pszBuffer = NULL;
|
|
DWORD dwType;
|
|
LONG lIndex,
|
|
cchBufLen,
|
|
lIter = 0;
|
|
TCHAR szPrompt[CCHMAX_STRINGRES];
|
|
LPTSTR psz = NULL,
|
|
pszTok = NULL,
|
|
pszToken = NULL;
|
|
|
|
// HrGetFieldText will return S_FALSE if no text
|
|
hr = HrGetFieldText(&pwszBuffer, idField);
|
|
if (S_OK != hr)
|
|
return hr;
|
|
|
|
IF_NULLEXIT(pszBuffer = PszToANSI(GetACP(), pwszBuffer));
|
|
|
|
psz = pszBuffer;
|
|
// Check group name
|
|
while (*psz && IsSpace(psz))
|
|
psz = CharNext(psz);
|
|
|
|
if(!(*psz))
|
|
{
|
|
hr = S_FALSE;
|
|
goto exit;
|
|
}
|
|
else
|
|
psz = NULL;
|
|
|
|
pszTok = pszBuffer;
|
|
pszToken = StrTokEx(&pszTok, GRP_DELIMITERS);
|
|
while (NULL != pszToken)
|
|
{
|
|
if (!fPosterAllowed ||
|
|
(fPosterAllowed && 0 != lstrcmpi(pszToken, c_szPosterKeyword)))
|
|
{
|
|
ZeroMemory(&Folder, sizeof(Folder));
|
|
|
|
// See if the Folder Already Exists
|
|
Folder.idParent = idServer;
|
|
Folder.pszName = (LPSTR)pszToken;
|
|
|
|
// Try to find in the index
|
|
if (DB_S_FOUND == g_pStore->FindRecord(IINDEX_ALL, COLUMNS_ALL, &Folder, NULL))
|
|
{
|
|
// Check to see if this newsgroup allows posting.
|
|
if (Folder.dwFlags & FOLDER_NOPOSTING)
|
|
{
|
|
psz = AthLoadString(idsErrNewsgroupNoPosting, 0, 0);
|
|
wnsprintf(szPrompt, ARRAYSIZE(szPrompt), psz, pszToken, pszToken);
|
|
AthFreeString(psz);
|
|
|
|
AthMessageBox(hwnd, MAKEINTRESOURCE(idsAthenaNews), szPrompt,
|
|
0, MB_ICONSTOP | MB_OK);
|
|
hr = E_FAIL;
|
|
}
|
|
|
|
if (Folder.dwFlags & FOLDER_BLOCKED)
|
|
{
|
|
psz = AthLoadString(idsErrNewsgroupBlocked, 0, 0);
|
|
wnsprintf(szPrompt, ARRAYSIZE(szPrompt), psz, pszToken, pszToken);
|
|
AthFreeString(psz);
|
|
|
|
AthMessageBox(hwnd, MAKEINTRESOURCE(idsAthenaNews), szPrompt,
|
|
0, MB_ICONSTOP | MB_OK);
|
|
hr = E_FAIL;
|
|
}
|
|
else
|
|
nResolvedNames++;
|
|
|
|
|
|
// Free
|
|
g_pStore->FreeRecord(&Folder);
|
|
}
|
|
else
|
|
{
|
|
psz = AthLoadString(idsErrCantResolveGroup, 0, 0);
|
|
wnsprintf(szPrompt, ARRAYSIZE(szPrompt), psz, pszToken);
|
|
AthFreeString(psz);
|
|
AthMessageBox(hwnd, MAKEINTRESOURCE(idsAthenaNews), szPrompt, 0,
|
|
MB_ICONSTOP | MB_OK);
|
|
hr = E_FAIL;
|
|
}
|
|
|
|
}
|
|
|
|
pszToken = StrTokEx(&pszTok, GRP_DELIMITERS);
|
|
}
|
|
|
|
exit:
|
|
MemFree(pszBuffer);
|
|
MemFree(pwszBuffer);
|
|
|
|
*fOneOrMoreNames = ((nResolvedNames > 0) ? TRUE : FALSE);
|
|
return (hr);
|
|
}
|
|
|
|
|
|
HRESULT CNoteHdr::HrGetFieldText(LPWSTR* ppszText, int idHdrCtrl)
|
|
{
|
|
HWND hwnd = GetDlgItem(m_hwnd, idHdrCtrl);
|
|
|
|
return HrGetFieldText(ppszText, hwnd);
|
|
}
|
|
|
|
HRESULT CNoteHdr::HrGetFieldText(LPWSTR* ppszText, HWND hwnd)
|
|
{
|
|
DWORD cch;
|
|
|
|
cch = GetRichEditTextLen(hwnd) + 1;
|
|
if (1 == cch)
|
|
return (S_FALSE);
|
|
|
|
if (!MemAlloc((LPVOID*) ppszText, cch * sizeof(WCHAR)))
|
|
return (E_OUTOFMEMORY);
|
|
|
|
HdrGetRichEditText(hwnd, *ppszText, cch, FALSE);
|
|
|
|
return (S_OK);
|
|
}
|
|
|
|
HRESULT CNoteHdr::HrAddSender()
|
|
{
|
|
ULONG uPos=0;
|
|
ADRINFO adrInfo;
|
|
LPADRINFO lpAdrInfo=0;
|
|
LPWAB lpWab;
|
|
HRESULT hr=E_FAIL;
|
|
|
|
if (m_lpWabal->FGetFirst(&adrInfo))
|
|
do
|
|
if (adrInfo.lRecipType==MAPI_ORIG)
|
|
{
|
|
lpAdrInfo=&adrInfo;
|
|
break;
|
|
}
|
|
while (m_lpWabal->FGetNext(&adrInfo));
|
|
|
|
if (lpAdrInfo &&
|
|
!FAILED (HrCreateWabObject (&lpWab)))
|
|
{
|
|
hr=lpWab->HrAddToWAB(m_hwnd, lpAdrInfo);
|
|
lpWab->Release ();
|
|
}
|
|
|
|
if (FAILED(hr) && hr!=MAPI_E_USER_CANCEL)
|
|
{
|
|
if (hr==MAPI_E_COLLISION)
|
|
AthMessageBoxW (m_hwnd, MAKEINTRESOURCEW(idsAthenaMail), MAKEINTRESOURCEW(idsErrAddrDupe), NULL, MB_OK);
|
|
else
|
|
AthMessageBoxW (m_hwnd, MAKEINTRESOURCEW(idsAthenaMail), MAKEINTRESOURCEW(idsErrAddToWAB), NULL, MB_OK);
|
|
}
|
|
return NOERROR;
|
|
}
|
|
|
|
HRESULT CNoteHdr::HrAddAllOnToList()
|
|
{
|
|
ADRINFO adrInfo;
|
|
LPWAB lpWab;
|
|
HRESULT hr = S_OK;
|
|
|
|
if (m_lpWabal->FGetFirst(&adrInfo))
|
|
{
|
|
hr = HrCreateWabObject(&lpWab);
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
do
|
|
{
|
|
if (MAPI_TO == adrInfo.lRecipType)
|
|
{
|
|
hr = lpWab->HrAddToWAB(m_hwnd, &adrInfo);
|
|
if (MAPI_E_COLLISION == hr)
|
|
{
|
|
hr = S_OK;
|
|
AthMessageBoxW (m_hwnd, MAKEINTRESOURCEW(idsAthenaMail), MAKEINTRESOURCEW(idsErrAddrDupe), NULL, MB_OK);
|
|
}
|
|
}
|
|
} while (SUCCEEDED(hr) && m_lpWabal->FGetNext(&adrInfo));
|
|
}
|
|
lpWab->Release();
|
|
}
|
|
|
|
if (FAILED(hr) && (MAPI_E_USER_CANCEL != hr))
|
|
AthMessageBoxW (m_hwnd, MAKEINTRESOURCEW(idsAthenaMail), MAKEINTRESOURCEW(idsErrAddToWAB), NULL, MB_OK);
|
|
|
|
return hr;
|
|
}
|
|
|
|
|
|
HRESULT CNoteHdr::HrInitFieldList()
|
|
{
|
|
PHCI pHCI, pLoopHCI;
|
|
INT size;
|
|
BOOL fReadOnly = IsReadOnly();
|
|
|
|
if (m_fMail)
|
|
{
|
|
if (fReadOnly)
|
|
{
|
|
pHCI = rgMailHeaderRead;
|
|
size = sizeof(rgMailHeaderRead);
|
|
}
|
|
else
|
|
{
|
|
pHCI = rgMailHeaderSend;
|
|
size = sizeof(rgMailHeaderSend);
|
|
}
|
|
|
|
}
|
|
else
|
|
{
|
|
if (fReadOnly)
|
|
{
|
|
pHCI = rgNewsHeaderRead;
|
|
size = sizeof(rgNewsHeaderRead);
|
|
}
|
|
else
|
|
{
|
|
pHCI = rgNewsHeaderSend;
|
|
size = sizeof(rgNewsHeaderSend);
|
|
}
|
|
}
|
|
|
|
// Setup the labels
|
|
pLoopHCI = pHCI;
|
|
m_cHCI = size/sizeof(HCI);
|
|
|
|
for (ULONG i = 0; i < m_cHCI; i++, pLoopHCI++)
|
|
{
|
|
if (0 == pLoopHCI->strlen)
|
|
{
|
|
AthLoadStringW(pLoopHCI->idsLabel, pLoopHCI->sz, cchHeaderMax+1);
|
|
pLoopHCI->strlen = lstrlenW(pLoopHCI->sz);
|
|
}
|
|
if ((0 == pLoopHCI->strlenEmpty) && (0 != pLoopHCI->idsEmpty))
|
|
{
|
|
AthLoadStringW(pLoopHCI->idsEmpty, pLoopHCI->szEmpty, cchHeaderMax+1);
|
|
pLoopHCI->strlenEmpty = lstrlenW(pLoopHCI->szEmpty);
|
|
}
|
|
}
|
|
|
|
if (NULL != MemAlloc((LPVOID *)&m_rgHCI, size))
|
|
CopyMemory(m_rgHCI, pHCI, size);
|
|
else
|
|
return E_OUTOFMEMORY;
|
|
|
|
m_cxLeftMargin = _GetLeftMargin();
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
int CNoteHdr::_GetLeftMargin()
|
|
{
|
|
PHCI pLoopHCI = m_rgHCI;
|
|
INT size;
|
|
int cxButtons = ControlXBufferSize();
|
|
HDC hdc = GetDC(m_hwnd);
|
|
HFONT hfontOld;
|
|
ULONG cxEditMarginCur = 0,
|
|
cxEditMaxMargin = 0;
|
|
SIZE rSize;
|
|
BOOL fReadOnly = IsReadOnly();
|
|
|
|
// Setup the labels
|
|
hfontOld=(HFONT)SelectObject(hdc, GetFont(fReadOnly));
|
|
|
|
for (ULONG i = 0; i < m_cHCI; i++, pLoopHCI++)
|
|
{
|
|
AssertSz(pLoopHCI->strlen, "Haven't set the strings yet.");
|
|
|
|
GetTextExtentPoint32AthW(hdc, pLoopHCI->sz, pLoopHCI->strlen, &rSize, NOFLAGS);
|
|
cxEditMarginCur = rSize.cx + PaddingOfLabels();
|
|
if (pLoopHCI->dwFlags & HCF_HASBUTTON)
|
|
cxEditMarginCur += CXOfButtonToLabel();
|
|
|
|
if (cxEditMarginCur > cxEditMaxMargin)
|
|
cxEditMaxMargin = cxEditMarginCur;
|
|
}
|
|
SelectObject(hdc, hfontOld);
|
|
ReleaseDC(m_hwnd, hdc);
|
|
|
|
return cxEditMaxMargin;
|
|
}
|
|
|
|
HRESULT CNoteHdr::HrFreeFieldList()
|
|
{
|
|
if (m_rgHCI)
|
|
{
|
|
for (int i=0; i<(int)m_cHCI; i++)
|
|
{
|
|
// You must free the pDoc before the preole or fault! (RICHED 2.0)
|
|
SafeRelease(m_rgHCI[i].pDoc);
|
|
SafeRelease(m_rgHCI[i].preole);
|
|
}
|
|
}
|
|
return NOERROR;
|
|
}
|
|
|
|
static WELLINIT rgWellInitMail[]=
|
|
{
|
|
{idADTo, MAPI_TO},
|
|
{idADCc, MAPI_CC},
|
|
{idADFrom, MAPI_ORIG},
|
|
{idADBCc, MAPI_BCC}
|
|
};
|
|
|
|
static WELLINIT rgWellInitNews[]=
|
|
{
|
|
{idADFrom, MAPI_ORIG},
|
|
{idADCc, MAPI_TO},
|
|
{idADReplyTo, MAPI_REPLYTO}
|
|
};
|
|
|
|
BOOL CNoteHdr::PostWMCreate()
|
|
{
|
|
HWND hwnd;
|
|
HWND hwndWells[4];
|
|
ULONG ulRecipType[4];
|
|
ULONG cWells=0;
|
|
PWELLINIT pWI;
|
|
INT size;
|
|
INT i;
|
|
|
|
if (hwnd=GetDlgItem(m_hwnd, idTXTSubject))
|
|
SendMessage(hwnd, EM_LIMITTEXT,cchMaxSubject,0);
|
|
|
|
if (m_fMail)
|
|
{
|
|
pWI = rgWellInitMail;
|
|
size = ARRAYSIZE(rgWellInitMail);
|
|
}
|
|
else
|
|
{
|
|
pWI = rgWellInitNews;
|
|
size = ARRAYSIZE(rgWellInitNews);
|
|
}
|
|
|
|
for (i=0; i<size; i++)
|
|
{
|
|
hwnd = GetDlgItem(m_hwnd, pWI[i].idField);
|
|
if (hwnd)
|
|
{
|
|
hwndWells[cWells] = hwnd;
|
|
ulRecipType[cWells++] = pWI[i].uMAPI;
|
|
}
|
|
}
|
|
|
|
AssertSz(!m_pAddrWells, "Who called PostWMCreate??????");
|
|
m_pAddrWells = new CAddrWells;
|
|
|
|
if (!m_pAddrWells || FAILED(m_pAddrWells->HrInit(cWells, hwndWells, ulRecipType)))
|
|
return FALSE;
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
|
|
HRESULT CNoteHdr::HrSetMailRecipients(LPMIMEMESSAGE pMsg)
|
|
{
|
|
ADRINFO rAdrInfo;
|
|
HRESULT hr = NOERROR;
|
|
IImnEnumAccounts *pEnumAccounts = NULL;
|
|
LPWABAL lpWabal = NULL;
|
|
BOOL fAdvanced = FALSE;
|
|
|
|
AssertSz(OENA_REPLYTONEWSGROUP != m_ntNote, "Shouldn't get a REPLYTONEWSGROUP in a mail note.");
|
|
|
|
SafeRelease(m_lpWabal);
|
|
|
|
// Set initial state of wabals to use
|
|
switch (m_ntNote)
|
|
{
|
|
case OENA_READ:
|
|
case OENA_WEBPAGE:
|
|
case OENA_STATIONERY:
|
|
IF_FAILEXIT(hr = HrGetWabalFromMsg(pMsg, &m_lpWabal));
|
|
break;
|
|
|
|
case OENA_COMPOSE:
|
|
case OENA_REPLYTOAUTHOR:
|
|
case OENA_REPLYALL:
|
|
IF_FAILEXIT(hr = HrGetWabalFromMsg(pMsg, &lpWabal));
|
|
IF_FAILEXIT(hr = HrCreateWabalObject(&m_lpWabal));
|
|
break;
|
|
|
|
case OENA_FORWARD:
|
|
case OENA_FORWARDBYATTACH:
|
|
IF_FAILEXIT(hr = HrCreateWabalObject(&m_lpWabal));
|
|
break;
|
|
}
|
|
|
|
// Actually set recipients now.
|
|
switch (m_ntNote)
|
|
{
|
|
case OENA_COMPOSE:
|
|
{
|
|
#pragma prefast(suppress:11, "noise")
|
|
BOOL fMoreIterations = lpWabal->FGetFirst(&rAdrInfo);
|
|
while (fMoreIterations)
|
|
{
|
|
if (rAdrInfo.lRecipType != MAPI_ORIG)
|
|
{
|
|
hr = m_lpWabal->HrAddEntry(&rAdrInfo);
|
|
if (FAILED(hr))
|
|
break;
|
|
}
|
|
fMoreIterations = lpWabal->FGetNext(&rAdrInfo);
|
|
}
|
|
break;
|
|
}
|
|
|
|
case OENA_REPLYTOAUTHOR:
|
|
case OENA_REPLYALL:
|
|
{
|
|
BOOL fNeedOriginatorItems = TRUE;
|
|
BOOL fMoreIterations;
|
|
|
|
// Add items to To: line from the ReplyTo Field
|
|
fMoreIterations = lpWabal->FGetFirst (&rAdrInfo);
|
|
while (fMoreIterations)
|
|
{
|
|
if (rAdrInfo.lRecipType==MAPI_REPLYTO)
|
|
{
|
|
Assert (rAdrInfo.lpwszAddress);
|
|
|
|
fNeedOriginatorItems = FALSE;
|
|
rAdrInfo.lRecipType=MAPI_TO;
|
|
IF_FAILEXIT(hr = m_lpWabal->HrAddEntry(&rAdrInfo));
|
|
}
|
|
|
|
fMoreIterations = lpWabal->FGetNext (&rAdrInfo);
|
|
}
|
|
|
|
// If we don't need to add the MAPI_ORIG and we are not trying to reply to all, then we are done
|
|
if (!fNeedOriginatorItems && (OENA_REPLYALL != m_ntNote))
|
|
break;
|
|
|
|
// Raid-35976: Unable to open message window with no accounts configured
|
|
// Get an SMTP account enumerator
|
|
Assert(g_pAcctMan);
|
|
if (g_pAcctMan && (OENA_REPLYALL == m_ntNote))
|
|
g_pAcctMan->Enumerate(SRV_SMTP|SRV_HTTPMAIL, &pEnumAccounts);
|
|
|
|
// Add the following items to the To line
|
|
// 1) If there were no ReplyTo items, then fill from the Orig field
|
|
// 2) If is ReplyToAll, then fill from the To and CC line
|
|
fMoreIterations = lpWabal->FGetFirst (&rAdrInfo);
|
|
while (fMoreIterations)
|
|
{
|
|
// No replyto people were added, and this is a MAPI_ORIG
|
|
if (fNeedOriginatorItems && rAdrInfo.lRecipType == MAPI_ORIG)
|
|
{
|
|
rAdrInfo.lRecipType=MAPI_TO;
|
|
IF_FAILEXIT(hr = m_lpWabal->HrAddEntry(&rAdrInfo));
|
|
}
|
|
|
|
// pEnumAccounts will only be set if ReplyToAll
|
|
// If ReplyToAll, then add the CC and To line entries to the To field
|
|
else if (pEnumAccounts && (rAdrInfo.lRecipType == MAPI_TO || rAdrInfo.lRecipType == MAPI_CC))
|
|
{
|
|
BOOL fIsSendersAccount = FALSE;
|
|
TCHAR szEmailAddress[CCHMAX_EMAIL_ADDRESS];
|
|
|
|
Assert (rAdrInfo.lpwszAddress);
|
|
|
|
pEnumAccounts->Reset();
|
|
|
|
// See if rAdrInfo.lpszAddress exist as one of the user's Send Email Addresses
|
|
while (!fIsSendersAccount)
|
|
{
|
|
IImnAccount *pAccount = NULL;
|
|
hr = pEnumAccounts->GetNext(&pAccount);
|
|
if (hr == E_EnumFinished || FAILED(hr))
|
|
break;
|
|
|
|
if (SUCCEEDED(pAccount->GetPropSz(AP_SMTP_EMAIL_ADDRESS, szEmailAddress, ARRAYSIZE(szEmailAddress))))
|
|
{
|
|
LPWSTR pwszAddress = NULL;
|
|
IF_NULLEXIT(pwszAddress = PszToUnicode(CP_ACP, szEmailAddress));
|
|
if (0 == StrCmpIW(rAdrInfo.lpwszAddress, pwszAddress))
|
|
fIsSendersAccount = TRUE;
|
|
MemFree(pwszAddress);
|
|
}
|
|
pAccount->Release();
|
|
}
|
|
|
|
// Reset hr
|
|
hr = S_OK;
|
|
|
|
// Add the account if it isn't from the sender
|
|
if (!fIsSendersAccount)
|
|
{
|
|
if (0 != StrCmpW(rAdrInfo.lpwszAddress, L"Undisclosed Recipients"))
|
|
{
|
|
// only include recipient on ReplyAll if it's not the sender...
|
|
IF_FAILEXIT(hr = m_lpWabal->HrAddEntry(&rAdrInfo));
|
|
}
|
|
}
|
|
}
|
|
fMoreIterations = lpWabal->FGetNext(&rAdrInfo);
|
|
}
|
|
}
|
|
}
|
|
|
|
Assert (m_lpWabal);
|
|
|
|
// For the send note case, make sure that resolved addresses are valid.
|
|
// If display name and email address are the same, UnresolveOneOffs() will clear
|
|
// the email address to force a real resolve.
|
|
if (OENA_COMPOSE == m_ntNote || OENA_WEBPAGE == m_ntNote || OENA_STATIONERY == m_ntNote)
|
|
m_lpWabal->UnresolveOneOffs();
|
|
|
|
m_lpWabal->HrResolveNames(NULL, FALSE);
|
|
|
|
Assert(m_pAddrWells);
|
|
m_pAddrWells->HrSetWabal(m_lpWabal);
|
|
m_pAddrWells->HrDisplayWells(m_hwnd);
|
|
|
|
if (OENA_READ == m_ntNote)
|
|
fAdvanced = DwGetOption(OPT_MAILNOTEADVREAD);
|
|
else
|
|
{
|
|
fAdvanced = DwGetOption(OPT_MAILNOTEADVSEND);
|
|
|
|
// Need to make sure that if we are in a compose note, that we check to see
|
|
// if we added a bcc without setting the advanced headers. If this is the case,
|
|
// then show the advanced headers for this note.
|
|
if (!fAdvanced && (0 < GetRichEditTextLen(GetDlgItem(m_hwnd, idADBCc))))
|
|
fAdvanced = TRUE;
|
|
}
|
|
// BUG: 31217: showadvanced has to be the last thing we call after modifying the
|
|
// well contents
|
|
ShowAdvancedHeaders(fAdvanced);
|
|
|
|
exit:
|
|
// Cleanup
|
|
ReleaseObj(lpWabal);
|
|
ReleaseObj(pEnumAccounts);
|
|
return hr;
|
|
}
|
|
|
|
|
|
HRESULT CNoteHdr::HrSetupNote(LPMIMEMESSAGE pMsg)
|
|
{
|
|
HWND hwnd;
|
|
WCHAR wsz[cchMaxSubject+1];
|
|
LPWSTR psz = NULL;
|
|
PROPVARIANT rVariant;
|
|
HRESULT hr = NOERROR;
|
|
|
|
if (!pMsg)
|
|
return E_INVALIDARG;
|
|
|
|
MimeOleGetBodyPropW(pMsg, HBODY_ROOT, PIDTOSTR(PID_HDR_SUBJECT), NOFLAGS, &psz);
|
|
HdrSetRichEditText(GetDlgItem(m_hwnd, idTXTSubject), psz, FALSE);
|
|
|
|
*wsz=0;
|
|
rVariant.vt = VT_FILETIME;
|
|
pMsg->GetProp(PIDTOSTR(PID_ATT_SENTTIME), 0, &rVariant);
|
|
AthFileTimeToDateTimeW(&rVariant.filetime, wsz, ARRAYSIZE(wsz), DTM_LONGDATE|DTM_NOSECONDS);
|
|
|
|
HdrSetRichEditText(GetDlgItem(m_hwnd, idTXTDate), wsz, FALSE);
|
|
|
|
MemFree(psz);
|
|
return hr;
|
|
}
|
|
|
|
|
|
HRESULT CNoteHdr::HrSetPri(LPMIMEMESSAGE pMsg)
|
|
{
|
|
UINT pri=priNorm;
|
|
PROPVARIANT rVariant;
|
|
|
|
Assert(pMsg);
|
|
|
|
rVariant.vt = VT_UI4;
|
|
if (SUCCEEDED(pMsg->GetProp(PIDTOSTR(PID_ATT_PRIORITY), 0, &rVariant)))
|
|
{
|
|
if (rVariant.ulVal == IMSG_PRI_HIGH)
|
|
pri=priHigh;
|
|
else if (rVariant.ulVal == IMSG_PRI_LOW)
|
|
pri=priLow;
|
|
}
|
|
|
|
return SetPriority(pri);
|
|
}
|
|
|
|
|
|
HRESULT CNoteHdr::HrAutoAddToWAB()
|
|
{
|
|
LPWAB lpWab=0;
|
|
LPWABAL lpWabal=0;
|
|
HRESULT hr;
|
|
ADRINFO adrInfo;
|
|
|
|
if (!m_lpWabal)
|
|
return S_OK;
|
|
|
|
if (!DwGetOption(OPT_MAIL_AUTOADDTOWABONREPLY))
|
|
return S_OK;
|
|
|
|
IF_FAILEXIT(hr=HrCreateWabObject(&lpWab));
|
|
|
|
// when this is called, m_lpWabal contains everyone on the to: and cc: line
|
|
// for a reply/reply all. We will add all these people to the WAB, ignoring any
|
|
// clashes or failures
|
|
// Add Sender if email and displayname are not the same.
|
|
// if so then there's no username so little point in adding.
|
|
|
|
if (m_lpWabal->FGetFirst(&adrInfo))
|
|
do
|
|
{
|
|
// IE5.#2568: we now just add to the WAB regardless of
|
|
// email and dispname being the same.
|
|
// if (lstrcmp(adrInfo.lpszDisplay, adrInfo.lpszAddress)!=0)
|
|
lpWab->HrAddNewEntry(adrInfo.lpwszDisplay, adrInfo.lpwszAddress);
|
|
}
|
|
while (m_lpWabal->FGetNext(&adrInfo));
|
|
|
|
exit:
|
|
ReleaseObj(lpWab);
|
|
return hr;
|
|
}
|
|
|
|
|
|
HRESULT CNoteHdr::HrOfficeLoad()
|
|
{
|
|
HRESULT hr = NOERROR;
|
|
|
|
m_fSkipLayout = FALSE;
|
|
|
|
if (!m_hCharset)
|
|
{
|
|
if (g_hDefaultCharsetForMail==NULL)
|
|
ReadSendMailDefaultCharset();
|
|
|
|
m_hCharset = g_hDefaultCharsetForMail;
|
|
}
|
|
|
|
if (m_hCharset)
|
|
HrUpdateCharSetFonts(m_hCharset, FALSE);
|
|
|
|
SafeRelease(m_lpWabal);
|
|
|
|
hr = HrCreateWabalObject(&m_lpWabal);
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
Assert(m_pAddrWells);
|
|
m_pAddrWells->HrSetWabal(m_lpWabal);
|
|
|
|
ShowAdvancedHeaders(DwGetOption(OPT_MAILNOTEADVSEND));
|
|
|
|
m_fStillLoading = FALSE;
|
|
}
|
|
|
|
return hr;
|
|
}
|
|
|
|
|
|
void CNoteHdr::SetReferences(LPMIMEMESSAGE pMsg)
|
|
{
|
|
LPWSTR lpszRefs = 0;
|
|
|
|
SafeMemFree(m_pszRefs);
|
|
MimeOleGetBodyPropW(pMsg, HBODY_ROOT, PIDTOSTR(PID_HDR_REFS), NOFLAGS, &lpszRefs);
|
|
|
|
switch (m_ntNote)
|
|
{
|
|
case OENA_REPLYALL:
|
|
case OENA_REPLYTOAUTHOR:
|
|
case OENA_REPLYTONEWSGROUP:
|
|
{
|
|
LPWSTR lpszMsgId = 0;
|
|
|
|
MimeOleGetBodyPropW(pMsg, HBODY_ROOT, PIDTOSTR(PID_HDR_MESSAGEID), NOFLAGS, &lpszMsgId);
|
|
|
|
if (lpszMsgId)
|
|
HrCreateReferences(lpszRefs, lpszMsgId, &m_pszRefs);
|
|
|
|
SafeMimeOleFree(lpszMsgId);
|
|
break;
|
|
}
|
|
|
|
case OENA_READ:
|
|
case OENA_WEBPAGE:
|
|
case OENA_STATIONERY:
|
|
case OENA_COMPOSE:
|
|
// hold on to the reference line for a send-note, so we can repersist if saving in drafts
|
|
if (lpszRefs)
|
|
m_pszRefs = PszDupW(lpszRefs);
|
|
break;
|
|
|
|
default:
|
|
break;
|
|
}
|
|
|
|
SafeMimeOleFree(lpszRefs);
|
|
}
|
|
|
|
HRESULT CNoteHdr::HrSetNewsRecipients(LPMIMEMESSAGE pMsg)
|
|
{
|
|
HRESULT hr = S_OK;
|
|
LPWSTR pwszNewsgroups = 0,
|
|
pwszCC = 0,
|
|
pwszSetNewsgroups = 0;
|
|
TCHAR szApproved[CCHMAX_EMAIL_ADDRESS];
|
|
HWND hwnd;
|
|
|
|
AssertSz(OENA_REPLYTOAUTHOR != m_ntNote, "Shouldn't get a REPLYTOAUTHOR in a news note.");
|
|
AssertSz(OENA_FORWARD != m_ntNote, "Shouldn't get a FORWARD in a news note.");
|
|
AssertSz(OENA_FORWARDBYATTACH != m_ntNote, "Shouldn't get a FORWARDBYATTACH in a news note.");
|
|
|
|
*szApproved = 0;
|
|
if (m_pAccount && DwGetOption(OPT_NEWSMODERATOR))
|
|
{
|
|
if (FAILED(m_pAccount->GetPropSz(AP_NNTP_REPLY_EMAIL_ADDRESS, szApproved, ARRAYSIZE(szApproved))) || (0 == *szApproved))
|
|
m_pAccount->GetPropSz(AP_NNTP_EMAIL_ADDRESS, szApproved, ARRAYSIZE(szApproved));
|
|
}
|
|
|
|
MimeOleGetBodyPropW(pMsg, HBODY_ROOT, PIDTOSTR(PID_HDR_NEWSGROUPS), NOFLAGS, &pwszNewsgroups);
|
|
|
|
switch (m_ntNote)
|
|
{
|
|
case OENA_READ:
|
|
{
|
|
LPWSTR lpszOrg = 0;
|
|
MimeOleGetBodyPropW(pMsg, HBODY_ROOT, PIDTOSTR(PID_HDR_ORG), NOFLAGS, &lpszOrg);
|
|
HdrSetRichEditText(GetDlgItem(m_hwnd, idTXTOrg), lpszOrg, FALSE);
|
|
SafeMimeOleFree(lpszOrg);
|
|
}
|
|
// Fall through
|
|
|
|
|
|
case OENA_WEBPAGE:
|
|
case OENA_STATIONERY:
|
|
case OENA_COMPOSE:
|
|
{
|
|
LPWSTR lpszFollowup = 0,
|
|
lpszDist = 0,
|
|
lpszKeywords = 0;
|
|
|
|
MimeOleGetBodyPropW(pMsg, HBODY_ROOT, PIDTOSTR(PID_HDR_FOLLOWUPTO), NOFLAGS, &lpszFollowup);
|
|
MimeOleGetBodyPropW(pMsg, HBODY_ROOT, PIDTOSTR(PID_HDR_DISTRIB), NOFLAGS, &lpszDist);
|
|
MimeOleGetBodyPropW(pMsg, HBODY_ROOT, PIDTOSTR(PID_HDR_KEYWORDS), NOFLAGS, &lpszKeywords);
|
|
|
|
pwszSetNewsgroups = pwszNewsgroups;
|
|
|
|
HdrSetRichEditText(GetDlgItem(m_hwnd, idTXTFollowupTo), lpszFollowup, FALSE);
|
|
HdrSetRichEditText(GetDlgItem(m_hwnd, idTXTDistribution), lpszDist, FALSE);
|
|
HdrSetRichEditText(GetDlgItem(m_hwnd, idTXTKeywords), lpszKeywords, FALSE);
|
|
|
|
MemFree(lpszFollowup);
|
|
MemFree(lpszDist);
|
|
MemFree(lpszKeywords);
|
|
break;
|
|
}
|
|
|
|
case OENA_REPLYALL:
|
|
case OENA_REPLYTONEWSGROUP:
|
|
{
|
|
LPSTR pszGroupsFree = 0;
|
|
|
|
if (SUCCEEDED(ParseFollowup(pMsg, &pszGroupsFree, &m_fPoster)))
|
|
{
|
|
if (pszGroupsFree)
|
|
{
|
|
SafeMemFree(pwszNewsgroups);
|
|
|
|
IF_NULLEXIT(pwszNewsgroups = PszToUnicode(CP_ACP, pszGroupsFree));
|
|
}
|
|
|
|
pwszSetNewsgroups = pwszNewsgroups;
|
|
}
|
|
else
|
|
pwszSetNewsgroups = pwszNewsgroups;
|
|
Assert(pwszSetNewsgroups);
|
|
|
|
if ((OENA_REPLYALL == m_ntNote) || m_fPoster)
|
|
{
|
|
MimeOleGetBodyPropW(pMsg, HBODY_ROOT, PIDTOSTR(PID_HDR_REPLYTO), NOFLAGS, &pwszCC);
|
|
if (!pwszCC)
|
|
MimeOleGetBodyPropW(pMsg, HBODY_ROOT, PIDTOSTR(PID_HDR_FROM), NOFLAGS, &pwszCC);
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
|
|
// set common fields
|
|
HdrSetRichEditText(GetDlgItem(m_hwnd, idADNewsgroups), pwszSetNewsgroups, FALSE);
|
|
|
|
// set read note / send note specific fields
|
|
if (OENA_READ != m_ntNote)
|
|
SetDlgItemText(m_hwnd, idADApproved, szApproved);
|
|
|
|
// set up the recipients
|
|
hr = HrSetNewsWabal(pMsg, pwszCC);
|
|
|
|
// BUG: 31217: showadvanced has to be the last thing we call after modifying the
|
|
// well contents
|
|
ShowAdvancedHeaders(DwGetOption(m_ntNote == OENA_READ ? OPT_NEWSNOTEADVREAD : OPT_NEWSNOTEADVSEND));
|
|
|
|
exit:
|
|
MemFree(pwszNewsgroups);
|
|
MemFree(pwszCC);
|
|
return hr;
|
|
}
|
|
|
|
|
|
HRESULT CNoteHdr::FullHeadersShowing(void)
|
|
{
|
|
return m_fAdvanced ? S_OK : S_FALSE;
|
|
}
|
|
|
|
|
|
HRESULT CNoteHdr::HrNewsSave(LPMIMEMESSAGE pMsg, CODEPAGEID cpID, BOOL fCheckConflictOnly)
|
|
{
|
|
HRESULT hr = S_OK;
|
|
WCHAR wsz[256];
|
|
WCHAR *pwszTrim;
|
|
BOOL fSenderOk = FALSE,
|
|
fSetMessageAcct = TRUE;
|
|
PROPVARIANT rVariant;
|
|
SYSTEMTIME st;
|
|
HWND hwnd;
|
|
PROPVARIANT rUserData;
|
|
BOOL fConflict = FALSE;
|
|
|
|
if (fCheckConflictOnly)
|
|
{
|
|
HdrGetRichEditText(GetDlgItem(m_hwnd, idADNewsgroups), wsz, ARRAYSIZE(wsz), FALSE);
|
|
pwszTrim = strtrimW(wsz);
|
|
if (*pwszTrim)
|
|
{
|
|
IF_FAILEXIT(hr = HrSafeToEncodeToCP(pwszTrim, cpID));
|
|
if (MIME_S_CHARSET_CONFLICT == hr)
|
|
goto exit;
|
|
}
|
|
|
|
HdrGetRichEditText(GetDlgItem(m_hwnd, idTXTFollowupTo), wsz, ARRAYSIZE(wsz), FALSE);
|
|
pwszTrim = strtrimW(wsz);
|
|
if (*pwszTrim)
|
|
{
|
|
IF_FAILEXIT(hr = HrSafeToEncodeToCP(pwszTrim, cpID));
|
|
if (MIME_S_CHARSET_CONFLICT == hr)
|
|
goto exit;
|
|
}
|
|
|
|
HdrGetRichEditText(GetDlgItem(m_hwnd, idTXTDistribution), wsz, ARRAYSIZE(wsz), FALSE);
|
|
pwszTrim = strtrimW(wsz);
|
|
if (*pwszTrim)
|
|
{
|
|
IF_FAILEXIT(hr = HrSafeToEncodeToCP(pwszTrim, cpID));
|
|
if (MIME_S_CHARSET_CONFLICT == hr)
|
|
goto exit;
|
|
}
|
|
|
|
HdrGetRichEditText(GetDlgItem(m_hwnd, idTXTKeywords), wsz, ARRAYSIZE(wsz), FALSE);
|
|
pwszTrim = strtrimW(wsz);
|
|
if (*pwszTrim)
|
|
{
|
|
IF_FAILEXIT(hr = HrSafeToEncodeToCP(pwszTrim, cpID));
|
|
if (MIME_S_CHARSET_CONFLICT == hr)
|
|
goto exit;
|
|
}
|
|
|
|
if (hwnd = GetDlgItem(m_hwnd, idADApproved))
|
|
{
|
|
HdrGetRichEditText(hwnd, wsz, ARRAYSIZE(wsz), FALSE);
|
|
pwszTrim = strtrimW(wsz);
|
|
if (*pwszTrim)
|
|
{
|
|
IF_FAILEXIT(hr = HrSafeToEncodeToCP(pwszTrim, cpID));
|
|
if (MIME_S_CHARSET_CONFLICT == hr)
|
|
goto exit;
|
|
}
|
|
}
|
|
|
|
if (hwnd = GetDlgItem(m_hwnd, idTxtControl))
|
|
{
|
|
HdrGetRichEditText(hwnd, wsz, ARRAYSIZE(wsz), FALSE);
|
|
pwszTrim = strtrimW(wsz);
|
|
if (*pwszTrim)
|
|
{
|
|
IF_FAILEXIT(hr = HrSafeToEncodeToCP(pwszTrim, cpID));
|
|
if (MIME_S_CHARSET_CONFLICT == hr)
|
|
goto exit;
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
// ************************
|
|
// This portion only happens on save, so don't try to do for fCheckConflictOnly
|
|
// Anything not in this section had better be mirrored in the fCheckConflictOnly block above
|
|
|
|
// Place any ascii only stuff here.
|
|
|
|
// end of save only portion.
|
|
// *************************
|
|
HdrGetRichEditText(GetDlgItem(m_hwnd, idADNewsgroups), wsz, ARRAYSIZE(wsz), FALSE);
|
|
pwszTrim = strtrimW(wsz);
|
|
if (*pwszTrim)
|
|
{
|
|
// Bug #22455 - Make sure we strip spaces etc from between newsgroups
|
|
_ValidateNewsgroups(pwszTrim);
|
|
IF_FAILEXIT(hr = MimeOleSetBodyPropW(pMsg, HBODY_ROOT, PIDTOSTR(PID_HDR_NEWSGROUPS), NOFLAGS, pwszTrim));
|
|
}
|
|
|
|
HdrGetRichEditText(GetDlgItem(m_hwnd, idTXTFollowupTo), wsz, ARRAYSIZE(wsz), FALSE);
|
|
pwszTrim = strtrimW(wsz);
|
|
if (*pwszTrim)
|
|
{
|
|
IF_FAILEXIT(hr = MimeOleSetBodyPropW(pMsg, HBODY_ROOT, PIDTOSTR(PID_HDR_FOLLOWUPTO), NOFLAGS, pwszTrim));
|
|
}
|
|
|
|
HdrGetRichEditText(GetDlgItem(m_hwnd, idTXTDistribution), wsz, ARRAYSIZE(wsz), FALSE);
|
|
pwszTrim = strtrimW(wsz);
|
|
if (*pwszTrim)
|
|
{
|
|
IF_FAILEXIT(hr = MimeOleSetBodyPropW(pMsg, HBODY_ROOT, PIDTOSTR(PID_HDR_DISTRIB), NOFLAGS, pwszTrim));
|
|
}
|
|
|
|
HdrGetRichEditText(GetDlgItem(m_hwnd, idTXTKeywords), wsz, ARRAYSIZE(wsz), FALSE);
|
|
pwszTrim = strtrimW(wsz);
|
|
if (*pwszTrim)
|
|
{
|
|
IF_FAILEXIT(hr = MimeOleSetBodyPropW(pMsg, HBODY_ROOT, PIDTOSTR(PID_HDR_KEYWORDS), NOFLAGS, pwszTrim));
|
|
}
|
|
|
|
if (hwnd = GetDlgItem(m_hwnd, idADApproved))
|
|
{
|
|
HdrGetRichEditText(hwnd, wsz, ARRAYSIZE(wsz), FALSE);
|
|
pwszTrim = strtrimW(wsz);
|
|
if (*pwszTrim)
|
|
{
|
|
IF_FAILEXIT(hr = MimeOleSetBodyPropW(pMsg, HBODY_ROOT, PIDTOSTR(PID_HDR_APPROVED), NOFLAGS, pwszTrim));
|
|
}
|
|
}
|
|
|
|
if (hwnd = GetDlgItem(m_hwnd, idTxtControl))
|
|
{
|
|
HdrGetRichEditText(hwnd, wsz, ARRAYSIZE(wsz), FALSE);
|
|
pwszTrim = strtrimW(wsz);
|
|
if (*pwszTrim)
|
|
{
|
|
IF_FAILEXIT(hr = MimeOleSetBodyPropW(pMsg, HBODY_ROOT, PIDTOSTR(PID_HDR_CONTROL), NOFLAGS, pwszTrim));
|
|
}
|
|
}
|
|
}
|
|
|
|
exit:
|
|
return hr;
|
|
}
|
|
|
|
|
|
HRESULT CNoteHdr::HrSetNewsWabal(LPMIMEMESSAGE pMsg, LPWSTR pwszCC)
|
|
{
|
|
HRESULT hr = S_OK;
|
|
LPWABAL lpWabal = NULL;
|
|
ADDRESSLIST addrList = { 0 };
|
|
LPWSTR pwszEmail = NULL;
|
|
IMimeMessageW *pMsgW = NULL;
|
|
|
|
SafeRelease(m_lpWabal);
|
|
|
|
if (OENA_READ == m_ntNote)
|
|
{
|
|
// for a read note, just take the wabal from the message
|
|
IF_FAILEXIT(hr = HrGetWabalFromMsg(pMsg, &m_lpWabal));
|
|
}
|
|
else
|
|
{
|
|
TCHAR szReplyAddr[CCHMAX_EMAIL_ADDRESS];
|
|
TCHAR szEmailAddr[CCHMAX_EMAIL_ADDRESS];
|
|
|
|
// for a compose note, or a reply note we need to do some munging, so create a new wabal
|
|
IF_FAILEXIT(hr = HrCreateWabalObject(&m_lpWabal));
|
|
|
|
if (OENA_COMPOSE == m_ntNote)
|
|
{
|
|
ADRINFO rAdrInfo;
|
|
|
|
IF_FAILEXIT(hr = HrGetWabalFromMsg(pMsg, &lpWabal));
|
|
|
|
// just copy everything except From: and ReplyTo: because we'll add those later
|
|
if (lpWabal->FGetFirst(&rAdrInfo))
|
|
{
|
|
do
|
|
{
|
|
if (rAdrInfo.lRecipType != MAPI_ORIG && rAdrInfo.lRecipType != MAPI_REPLYTO)
|
|
IF_FAILEXIT(hr = m_lpWabal->HrAddEntry(&rAdrInfo));
|
|
}
|
|
while (lpWabal->FGetNext(&rAdrInfo));
|
|
}
|
|
}
|
|
|
|
// add replyto if necessary
|
|
if (m_pAccount)
|
|
{
|
|
if (SUCCEEDED(m_pAccount->GetPropSz(AP_NNTP_REPLY_EMAIL_ADDRESS, szReplyAddr, ARRAYSIZE(szReplyAddr))) &&
|
|
*szReplyAddr &&
|
|
SUCCEEDED(m_pAccount->GetPropSz(AP_NNTP_EMAIL_ADDRESS, szEmailAddr, ARRAYSIZE(szEmailAddr))) &&
|
|
lstrcmpi(szReplyAddr, szEmailAddr))
|
|
{
|
|
TCHAR szName[CCHMAX_DISPLAY_NAME];
|
|
if (SUCCEEDED(m_pAccount->GetPropSz(AP_NNTP_DISPLAY_NAME, szName, ARRAYSIZE(szName))))
|
|
IF_FAILEXIT(hr = m_lpWabal->HrAddEntryA(szName, szReplyAddr, MAPI_REPLYTO));
|
|
else
|
|
IF_FAILEXIT(hr = m_lpWabal->HrAddEntryA(szReplyAddr, szReplyAddr, MAPI_REPLYTO));
|
|
}
|
|
}
|
|
|
|
//Bug# 79066
|
|
if ((OENA_REPLYALL == m_ntNote) || m_fPoster)
|
|
{
|
|
if (FAILED(MimeOleParseRfc822AddressW(IAT_REPLYTO, pwszCC, &addrList)))
|
|
{
|
|
IF_FAILEXIT(hr = MimeOleParseRfc822AddressW(IAT_FROM, pwszCC, &addrList));
|
|
}
|
|
|
|
IF_NULLEXIT(pwszEmail = PszToUnicode(CP_ACP, addrList.prgAdr->pszEmail));
|
|
IF_FAILEXIT(hr = m_lpWabal->HrAddEntry(addrList.prgAdr->pszFriendlyW, pwszEmail, MAPI_TO));
|
|
|
|
}
|
|
}
|
|
|
|
// For the send note case, make sure that resolved addresses are valid.
|
|
// If display name and email address are the same, UnresolveOneOffs() will clear
|
|
// the email address to force a real resolve.
|
|
if ((OENA_COMPOSE == m_ntNote) || (OENA_WEBPAGE == m_ntNote) || OENA_STATIONERY == m_ntNote)
|
|
m_lpWabal->UnresolveOneOffs();
|
|
|
|
m_lpWabal->HrResolveNames(NULL, FALSE);
|
|
|
|
Assert(m_pAddrWells);
|
|
if (SUCCEEDED(hr = m_pAddrWells->HrSetWabal(m_lpWabal)))
|
|
hr = m_pAddrWells->HrDisplayWells(m_hwnd);
|
|
|
|
exit:
|
|
if (g_pMoleAlloc)
|
|
{
|
|
if (addrList.cAdrs)
|
|
g_pMoleAlloc->FreeAddressList(&addrList);
|
|
}
|
|
|
|
ReleaseObj(lpWabal);
|
|
MemFree(pwszEmail);
|
|
ReleaseObj(pMsgW);
|
|
return hr;
|
|
}
|
|
|
|
|
|
HRESULT CNoteHdr::HrSetReplySubject(LPMIMEMESSAGE pMsg, BOOL fReply)
|
|
{
|
|
WCHAR szNewSubject[cchMaxSubject+1];
|
|
LPWSTR pszNorm = NULL;
|
|
int cchPrefix;
|
|
LPCWSTR lpwReFwd = NULL;
|
|
|
|
MimeOleGetBodyPropW(pMsg, HBODY_ROOT, STR_ATT_NORMSUBJ, NOFLAGS, &pszNorm);
|
|
|
|
if (!!DwGetOption(OPT_HARDCODEDHDRS))
|
|
{
|
|
//Use english strings and not from resources
|
|
lpwReFwd = fReply ? c_wszRe : c_wszFwd;
|
|
|
|
StrCpyNW(szNewSubject, lpwReFwd, cchMaxSubject);
|
|
}
|
|
else
|
|
{
|
|
// pull in the new prefix from resource...
|
|
AthLoadStringW(fReply?idsPrefixReply:idsPrefixForward, szNewSubject, cchMaxSubject);
|
|
}
|
|
|
|
cchPrefix = lstrlenW(szNewSubject);
|
|
Assert(cchPrefix);
|
|
if (pszNorm)
|
|
{
|
|
StrCpyNW(szNewSubject+cchPrefix, pszNorm, min(lstrlenW(pszNorm), cchMaxSubject-cchPrefix)+1);
|
|
SafeMimeOleFree(pszNorm);
|
|
}
|
|
HdrSetRichEditText(GetDlgItem(m_hwnd, idTXTSubject), szNewSubject, FALSE);
|
|
|
|
return NOERROR;
|
|
}
|
|
|
|
#define FIsDelimiter(_ch) (_ch==L';' || _ch==L',' || _ch==L' ' || _ch==L'\r' || _ch==L'\n' || _ch == L'\t')
|
|
|
|
void _ValidateNewsgroups(LPWSTR pszGroups)
|
|
{
|
|
LPWSTR pszDst = pszGroups;
|
|
BOOL fInGroup = FALSE;
|
|
WCHAR ch;
|
|
|
|
Assert(pszGroups);
|
|
|
|
while (ch = *pszGroups++)
|
|
{
|
|
if (FIsDelimiter(ch))
|
|
{
|
|
if (fInGroup)
|
|
{
|
|
while ((ch = *pszGroups) && FIsDelimiter(ch))
|
|
pszGroups++;
|
|
if (ch)
|
|
*pszDst++ = L',';
|
|
fInGroup = FALSE;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
*pszDst++ = ch;
|
|
fInGroup = TRUE;
|
|
}
|
|
}
|
|
*pszDst = 0;
|
|
}
|
|
|
|
|
|
HRESULT CNoteHdr::HrQueryToolbarButtons(DWORD dwFlags, const GUID *pguidCmdGroup, OLECMD* pOleCmd)
|
|
{
|
|
pOleCmd->cmdf = 0;
|
|
|
|
if (NULL == pguidCmdGroup)
|
|
{
|
|
switch (pOleCmd->cmdID)
|
|
{
|
|
case OLECMDID_CUT:
|
|
pOleCmd->cmdf = QS_ENABLED(dwFlags&edfEditHasSelAndIsRW);
|
|
break;
|
|
|
|
case OLECMDID_PASTE:
|
|
pOleCmd->cmdf = QS_ENABLED(dwFlags&edfPaste);
|
|
break;
|
|
|
|
case OLECMDID_SELECTALL:
|
|
pOleCmd->cmdf = QS_ENABLED(TRUE);
|
|
break;
|
|
|
|
case OLECMDID_COPY:
|
|
pOleCmd->cmdf = QS_ENABLED(dwFlags&edfEditHasSel);
|
|
break;
|
|
|
|
case OLECMDID_UNDO:
|
|
pOleCmd->cmdf = QS_ENABLED(dwFlags&edfUndo);
|
|
break;
|
|
}
|
|
}
|
|
else if (IsEqualGUID(CMDSETID_OutlookExpress, *pguidCmdGroup))
|
|
{
|
|
switch (pOleCmd->cmdID)
|
|
{
|
|
case ID_CUT:
|
|
pOleCmd->cmdf = QS_ENABLED(dwFlags&edfEditHasSelAndIsRW);
|
|
break;
|
|
|
|
case ID_PASTE:
|
|
pOleCmd->cmdf = QS_ENABLED(dwFlags&edfPaste);
|
|
break;
|
|
|
|
case ID_SELECT_ALL:
|
|
pOleCmd->cmdf = QS_ENABLED(TRUE);
|
|
break;
|
|
|
|
case ID_NOTE_COPY:
|
|
case ID_COPY:
|
|
pOleCmd->cmdf = QS_ENABLED(dwFlags&edfEditHasSel);
|
|
break;
|
|
|
|
case ID_UNDO:
|
|
pOleCmd->cmdf = QS_ENABLED(dwFlags&edfUndo);
|
|
break;
|
|
}
|
|
}
|
|
|
|
return NOERROR;
|
|
}
|
|
|
|
|
|
void CNoteHdr::OnButtonClick(int idBtn)
|
|
{
|
|
UINT cch;
|
|
LPTSTR pszGroups;
|
|
//CPickGroupDlg* ppgd;
|
|
|
|
switch (idBtn)
|
|
{
|
|
case idbtnTo:
|
|
if (m_fMail)
|
|
HrPickNames(0);
|
|
else
|
|
HrPickGroups(idADNewsgroups, FALSE);
|
|
break;
|
|
|
|
case idbtnFollowup:
|
|
HrPickGroups(idTXTFollowupTo, TRUE);
|
|
break;
|
|
|
|
case idbtnCc:
|
|
if (m_fMail)
|
|
HrPickNames(1);
|
|
else
|
|
HrPickNames(0);
|
|
break;
|
|
|
|
case idbtnBCc:
|
|
HrPickNames(2);
|
|
break;
|
|
|
|
case idbtnReplyTo:
|
|
HrPickNames(1);
|
|
break;
|
|
}
|
|
}
|
|
|
|
void CNoteHdr::HrPickGroups(int idWell, BOOL fFollowUpTo)
|
|
{
|
|
UINT cch;
|
|
DWORD cServer = 0;
|
|
HWND hwnd;
|
|
LPSTR pszGroups=NULL;
|
|
LPWSTR pwszGroups=NULL;
|
|
CPickGroupDlg *ppgd;
|
|
CHAR szAccount[CCHMAX_ACCOUNT_NAME];
|
|
|
|
g_pAcctMan->GetAccountCount(ACCT_NEWS, &cServer);
|
|
|
|
// BUGBUG Sometimes m_pAccount is an IMAP server, so we want to also
|
|
// test that we have at least one news server. This is a known problem
|
|
// that was punted a long time ago.
|
|
if (!m_pAccount || !cServer)
|
|
{
|
|
AthMessageBoxW (m_hwnd, MAKEINTRESOURCEW(idsAthenaMail), MAKEINTRESOURCEW(idsErrConfigureServer), NULL, MB_OK);
|
|
return;
|
|
}
|
|
|
|
hwnd = GetDlgItem(m_hwnd, idWell);
|
|
if (S_OK == HrGetFieldText(&pwszGroups, hwnd))
|
|
{
|
|
// Since this function doesn't fail, just make sure that we
|
|
// don't do anything funky when PszToANSI and PszToUnicode fails.
|
|
pszGroups = PszToANSI(GetACP(), pwszGroups);
|
|
}
|
|
|
|
ppgd = new CPickGroupDlg;
|
|
if (ppgd)
|
|
{
|
|
FOLDERID idServer = FOLDERID_INVALID;
|
|
m_pAccount->GetPropSz(AP_ACCOUNT_ID, szAccount, sizeof(szAccount));
|
|
|
|
// find the parent folder id of the account
|
|
if (SUCCEEDED(g_pStore->FindServerId(szAccount, &idServer)) &&
|
|
ppgd->FCreate(m_hwnd, idServer, &pszGroups, fFollowUpTo) &&
|
|
pszGroups)
|
|
{
|
|
SafeMemFree(pwszGroups);
|
|
pwszGroups = PszToUnicode(CP_ACP, pszGroups);
|
|
HdrSetRichEditText(hwnd, pwszGroups != NULL ? pwszGroups : c_wszEmpty, FALSE);
|
|
}
|
|
|
|
ppgd->Release();
|
|
}
|
|
|
|
MemFree(pwszGroups);
|
|
MemFree(pszGroups);
|
|
}
|
|
|
|
HRESULT CNoteHdr::HrPickNames(int iwell)
|
|
{
|
|
HRESULT hr = NOERROR;
|
|
|
|
if (IsReadOnly())
|
|
return hr;
|
|
|
|
Assert(m_lpWabal);
|
|
Assert(m_pAddrWells);
|
|
|
|
//We need to setmodify so that it is marked as dirty. In a normal case,
|
|
//the user would have typed in and hence set modify would have happenned automatically
|
|
if (m_fPoster)
|
|
{
|
|
Edit_SetModify(GetDlgItem(m_hwnd, idADCc), TRUE);
|
|
}
|
|
|
|
hr=m_pAddrWells->HrSelectNames(m_hwnd, iwell, m_fMail?FALSE:TRUE);
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
// Check to see if need to show advanced headers.
|
|
if (0 < GetRichEditTextLen(GetDlgItem(m_hwnd, idADBCc)))
|
|
ShowAdvancedHeaders(TRUE);
|
|
}
|
|
else if (hr!=MAPI_E_USER_CANCEL)
|
|
AthMessageBoxW (m_hwnd, MAKEINTRESOURCEW(idsAthenaMail), MAKEINTRESOURCEW(idsErrPickNames), NULL, MB_OK);
|
|
|
|
return hr;
|
|
}
|
|
|
|
HRESULT CNoteHdr::HrGetAccountInHeader(IImnAccount **ppAcct)
|
|
{
|
|
HRESULT hr = E_FAIL;
|
|
IImnAccount *pAcct = NULL;
|
|
ULONG cAccount = 0;
|
|
HWND hwndCombo = GetDlgItem(m_hwnd, idFromCombo);
|
|
|
|
// If the combo box is being used then get the account info from it.
|
|
if (SUCCEEDED(g_pAcctMan->GetAccountCount(m_fMail?ACCT_MAIL:ACCT_NEWS, &cAccount)) &&
|
|
(cAccount > 1) && hwndCombo)
|
|
{
|
|
LPSTR szAcctID = NULL;
|
|
ULONG i = ComboBox_GetCurSel(hwndCombo);
|
|
|
|
szAcctID = (LPSTR)SendMessage(hwndCombo, CB_GETITEMDATA, WPARAM(i), 0);
|
|
hr = g_pAcctMan->FindAccount(AP_ACCOUNT_ID, szAcctID, &pAcct);
|
|
}
|
|
|
|
// Get default account from MsgSite
|
|
if (FAILED(hr) && m_pHeaderSite)
|
|
{
|
|
IOEMsgSite *pMsgSite = NULL;
|
|
IServiceProvider *pServ = NULL;
|
|
|
|
hr = m_pHeaderSite->QueryInterface(IID_IServiceProvider, (LPVOID*)&pServ);
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
hr = pServ->QueryService(IID_IOEMsgSite, IID_IOEMsgSite, (LPVOID*)&pMsgSite);
|
|
pServ->Release();
|
|
}
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
hr = pMsgSite->GetDefaultAccount(m_fMail?ACCT_MAIL:ACCT_NEWS, &pAcct);
|
|
pMsgSite->Release();
|
|
}
|
|
}
|
|
|
|
// Get global default. Used in failure case and in Envelope (WordMail, etc) case
|
|
if (FAILED(hr))
|
|
hr = g_pAcctMan->GetDefaultAccount(m_fMail?ACCT_MAIL:ACCT_NEWS, &pAcct);
|
|
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
AssertSz(pAcct, "How is it that we succeeded, yet we don't have an account???");
|
|
ReplaceInterface((*ppAcct), pAcct);
|
|
}
|
|
else if (E_FAIL == hr)
|
|
hr = HR_E_COULDNOTFINDACCOUNT;
|
|
|
|
ReleaseObj(pAcct);
|
|
|
|
return hr;
|
|
}
|
|
|
|
HRESULT CNoteHdr::HrFillMessage(IMimeMessage *pMsg)
|
|
{
|
|
IUnknown *punk;
|
|
IPersistMime *pPM = NULL;
|
|
HRESULT hr;
|
|
|
|
if (m_pEnvelopeSite)
|
|
punk = m_pEnvelopeSite;
|
|
else
|
|
punk = m_pHeaderSite;
|
|
|
|
AssertSz(punk, "You need either a HeaderSite or an EnvelopeSite");
|
|
|
|
hr = punk->QueryInterface(IID_IPersistMime, (LPVOID*)&pPM);
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
hr = pPM->Save(pMsg, 0);
|
|
ReleaseObj(pPM);
|
|
|
|
if (hr == MAPI_E_USER_CANCEL)
|
|
goto Exit;
|
|
}
|
|
else
|
|
// If can't get a IPersistMime, need to fake the save through the m_pEnvelopeSite
|
|
// The only time the QI for IPersistMime doesn't work is if you have an m_pEnvelopeSite
|
|
// that doesn't support IPersistMime. If you have a m_pHeaderSite, QI should always work.
|
|
{
|
|
LPSTREAM pstm;
|
|
HBODY hBodyHtml = 0;
|
|
|
|
AssertSz(m_pEnvelopeSite, "If the QI didn't work, then must be an envelope site.");
|
|
|
|
// We need to select the charset before we save the message
|
|
pMsg->SetCharset(m_hCharset, CSET_APPLY_ALL);
|
|
|
|
hr = Save(pMsg, 0);
|
|
if (FAILED(hr))
|
|
goto Exit;
|
|
|
|
// Word will call our GetAttach function during this call to GetBody so save m_pMsgSend
|
|
// so that we can inline attaches that Word sends to us.
|
|
m_pMsgSend = pMsg;
|
|
|
|
if (SUCCEEDED(_GetMsoBody(ENV_BODY_HTML, &pstm)))
|
|
{
|
|
pMsg->SetTextBody(TXT_HTML, IET_INETCSET, NULL, pstm, &hBodyHtml);
|
|
pstm->Release();
|
|
}
|
|
|
|
if (SUCCEEDED(_GetMsoBody(ENV_BODY_TEXT, &pstm)))
|
|
{
|
|
pMsg->SetTextBody(TXT_PLAIN, IET_INETCSET, hBodyHtml, pstm, NULL);
|
|
pstm->Release();
|
|
}
|
|
|
|
m_pMsgSend = NULL;
|
|
}
|
|
|
|
Exit:
|
|
return hr;
|
|
}
|
|
|
|
HRESULT CNoteHdr::_GetMsoBody(ULONG uBody, LPSTREAM *ppstm)
|
|
{
|
|
LPSTREAM pstm=NULL;
|
|
HRESULT hr;
|
|
|
|
*ppstm = NULL;
|
|
|
|
IF_FAILEXIT(hr = MimeOleCreateVirtualStream(&pstm));
|
|
IF_FAILEXIT(hr = m_pEnvelopeSite->GetBody(pstm, uCodePageFromCharset(m_hCharset), uBody));
|
|
|
|
*ppstm = pstm;
|
|
pstm = NULL;
|
|
|
|
exit:
|
|
ReleaseObj(pstm);
|
|
return hr;
|
|
}
|
|
|
|
#ifdef YST
|
|
// this check produced a 4 bugs in OE 5.01 and 5.5 and I disaable it (YST)
|
|
HRESULT CNoteHdr::_CheckMsoBodyCharsetConflict(CODEPAGEID cpID)
|
|
{
|
|
HRESULT hr = S_OK;
|
|
LPSTREAM pstm = NULL;
|
|
BSTR bstrText = NULL;
|
|
ULONG cbToRead = 0,
|
|
cbRead = 0;
|
|
|
|
IF_FAILEXIT(hr = MimeOleCreateVirtualStream(&pstm));
|
|
|
|
hr = m_pEnvelopeSite->GetBody(pstm, CP_UNICODE, ENV_BODY_TEXT);
|
|
|
|
// bobn; Raid 81900; 6/30/99
|
|
// Excel (and powerpoint?) don't have a text body.
|
|
// Check that there is an HTML body and we can have
|
|
// it in unicode.
|
|
if(FAILED(hr))
|
|
IF_FAILEXIT(hr = m_pEnvelopeSite->GetBody(pstm, CP_UNICODE, ENV_BODY_HTML));
|
|
|
|
IF_FAILEXIT(hr = HrIStreamToBSTR(CP_UNICODE, pstm, &bstrText));
|
|
|
|
hr = HrSafeToEncodeToCP((LPWSTR)bstrText, cpID);
|
|
|
|
exit:
|
|
SysFreeString(bstrText);
|
|
ReleaseObj(pstm);
|
|
return hr;
|
|
}
|
|
#endif //YST
|
|
|
|
HRESULT CNoteHdr::HrCheckSendInfo()
|
|
{
|
|
HRESULT hr;
|
|
BOOL fOneOrMoreGroups = FALSE,
|
|
fOneOrMoreNames = FALSE;
|
|
|
|
hr = HrCheckNames(FALSE, TRUE);
|
|
if (FAILED(hr))
|
|
{
|
|
if ((MAPI_E_USER_CANCEL != hr) && (hrNoRecipients != hr))
|
|
hr = hrBadRecipients;
|
|
|
|
if (hrNoRecipients != hr)
|
|
goto Exit;
|
|
}
|
|
else
|
|
fOneOrMoreNames = TRUE;
|
|
|
|
// If we didn't find any email recipients, don't need to check if valid.
|
|
if (SUCCEEDED(hr) && m_lpWabal)
|
|
hr = m_lpWabal->IsValidForSending();
|
|
|
|
// Only check groups if:
|
|
// 1- Have succeeded to this point or didn't have any email recipients
|
|
// 2- In a news header
|
|
if ((SUCCEEDED(hr) || (hrNoRecipients == hr)) && !m_fMail)
|
|
{
|
|
hr = HrCheckGroups(TRUE);
|
|
if (SUCCEEDED(hr))
|
|
fOneOrMoreGroups = TRUE;
|
|
}
|
|
|
|
if (FAILED(hr))
|
|
goto Exit;
|
|
|
|
hr = HrCheckSubject(!fOneOrMoreGroups);
|
|
if (FAILED(hr))
|
|
goto Exit;
|
|
|
|
// TODO:
|
|
if (m_pHeaderSite && m_pHeaderSite->IsHTML() == S_OK)
|
|
{
|
|
// if a HTML message, then let's make sure there's no plain-text recipients
|
|
if (fOneOrMoreNames)
|
|
{
|
|
hr = HrIsCoolToSendHTML();
|
|
if (hr == S_FALSE && m_pHeaderSite)
|
|
// send plain-text only...
|
|
m_pHeaderSite->SetHTML(FALSE);
|
|
}
|
|
|
|
if (fOneOrMoreGroups &&
|
|
(IDCANCEL == DoDontShowMeAgainDlg(m_hwnd, c_szDSHTMLNewsWarning, MAKEINTRESOURCE(idsAthena),
|
|
MAKEINTRESOURCE(idsErrHTMLInNewsIsBad), MB_OKCANCEL)))
|
|
hr = MAPI_E_USER_CANCEL;
|
|
}
|
|
|
|
Exit:
|
|
return hr;
|
|
}
|
|
|
|
HRESULT CNoteHdr::HrSend(void)
|
|
{
|
|
HRESULT hr;
|
|
IMimeMessage *pMsg = NULL;
|
|
IOEMsgSite *pMsgSite = NULL;
|
|
|
|
if (m_pEnvelopeSite)
|
|
{
|
|
// With the envelope site, must check to see if things set up at this point to use mail
|
|
hr = ProcessICW(m_hwnd, FOLDER_LOCAL, TRUE);
|
|
if (hr == S_FALSE)
|
|
// user cancelled out of config wizard so we can't continue
|
|
hr = MAPI_E_USER_CANCEL;
|
|
if (FAILED(hr))
|
|
goto error;
|
|
m_fSendImmediate = TRUE;
|
|
}
|
|
|
|
hr = HrCreateMessage(&pMsg);
|
|
if (FAILED(hr))
|
|
goto error;
|
|
|
|
// The only case where this will happen is if no accounts are configured. Just to make
|
|
// sure, call the ICW and then try to get the default account.
|
|
if (!m_pAccount)
|
|
{
|
|
hr = ProcessICW(m_hwnd, m_fMail ? FOLDER_LOCAL : FOLDER_NEWS, TRUE);
|
|
if (FAILED(hr))
|
|
goto error;
|
|
|
|
if (FAILED(g_pAcctMan->GetDefaultAccount(m_fMail?ACCT_MAIL:ACCT_NEWS, &m_pAccount)))
|
|
{
|
|
hr = HR_E_COULDNOTFINDACCOUNT;
|
|
goto error;
|
|
}
|
|
}
|
|
|
|
hr = HrCheckSendInfo();
|
|
if (FAILED(hr))
|
|
goto error;
|
|
|
|
// Does IPersistMime save stuff
|
|
hr = HrFillMessage(pMsg);
|
|
if (FAILED(hr))
|
|
goto error;
|
|
|
|
if (m_pHeaderSite)
|
|
{
|
|
IOEMsgSite *pMsgSite = NULL;
|
|
IServiceProvider *pServ = NULL;
|
|
|
|
hr = m_pHeaderSite->QueryInterface(IID_IServiceProvider, (LPVOID*)&pServ);
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
hr = pServ->QueryService(IID_IOEMsgSite, IID_IOEMsgSite, (LPVOID*)&pMsgSite);
|
|
pServ->Release();
|
|
}
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
if (!m_fMail && IsReplyNote() && !DwGetDontShowAgain(c_szDSReplyNews))
|
|
{
|
|
LRESULT id = DoDontShowMeAgainDlg(m_hwnd, c_szDSReplyNews,
|
|
MAKEINTRESOURCE(idsPostNews),
|
|
MAKEINTRESOURCE(idsReplyToNewsGroup),
|
|
MB_YESNO);
|
|
if (IDNO == id || IDCANCEL == id)
|
|
hr = hrUserCancel;
|
|
else
|
|
hr = pMsgSite->SendToOutbox(pMsg, m_fSendImmediate, m_pHeaderSite);
|
|
}
|
|
else
|
|
{
|
|
hr = pMsgSite->SendToOutbox(pMsg, m_fSendImmediate, m_pHeaderSite);
|
|
}
|
|
pMsgSite->Release();
|
|
}
|
|
}
|
|
// We are in office Envelope
|
|
else
|
|
{
|
|
COEMsgSite *pMsgSite = NULL;
|
|
CStoreCB *pCB = NULL;
|
|
|
|
pMsgSite = new COEMsgSite();
|
|
if (!pMsgSite)
|
|
hr = E_OUTOFMEMORY;
|
|
|
|
pCB = new CStoreCB;
|
|
if (!pCB)
|
|
hr = E_OUTOFMEMORY;
|
|
|
|
if (SUCCEEDED(hr))
|
|
hr = pCB->Initialize(m_hwndParent, MAKEINTRESOURCE(idsSendingToOutbox), TRUE);
|
|
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
INIT_MSGSITE_STRUCT rInitStruct;
|
|
|
|
rInitStruct.dwInitType = OEMSIT_MSG;
|
|
rInitStruct.folderID = FOLDERID_INVALID;
|
|
rInitStruct.pMsg = pMsg;
|
|
|
|
hr = pMsgSite->Init(&rInitStruct);
|
|
}
|
|
|
|
if (SUCCEEDED(hr))
|
|
hr = pMsgSite->SetStoreCallback(pCB);
|
|
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
hr = pMsgSite->SendToOutbox(pMsg, m_fSendImmediate, m_pHeaderSite);
|
|
if (E_PENDING == hr)
|
|
hr = pCB->Block();
|
|
|
|
pCB->Close();
|
|
}
|
|
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
m_pEnvelopeSite->CloseNote(ENV_CLOSE_SEND);
|
|
ShowWindow(m_hwnd, SW_HIDE);
|
|
}
|
|
|
|
if (pMsgSite)
|
|
{
|
|
pMsgSite->Close();
|
|
pMsgSite->Release();
|
|
}
|
|
|
|
ReleaseObj(pCB);
|
|
}
|
|
|
|
error:
|
|
if (FAILED(hr))
|
|
{
|
|
int idsErr = -1;
|
|
m_fSecurityInited = FALSE;
|
|
|
|
switch (hr)
|
|
{
|
|
case hrNoRecipients:
|
|
if(!m_fMail)
|
|
hr = HR_E_POST_WITHOUT_NEWS; // idsErr = idsErrPostWithoutNewsgroup;
|
|
break;
|
|
|
|
case HR_E_COULDNOTFINDACCOUNT:
|
|
if(!m_fMail)
|
|
hr = HR_E_CONFIGURE_SERVER; //idsErr = idsErrConfigureServer;
|
|
break;
|
|
|
|
case HR_E_ATHSEC_FAILED:
|
|
case hrUserCancel:
|
|
case MAPI_E_USER_CANCEL:
|
|
idsErr = 0;
|
|
break;
|
|
|
|
case HR_E_ATHSEC_NOCERTTOSIGN:
|
|
case MIME_E_SECURITY_NOSIGNINGCERT:
|
|
idsErr = 0;
|
|
if(DialogBoxParam(g_hLocRes,
|
|
MAKEINTRESOURCE(iddErrSecurityNoSigningCert), m_hwnd,
|
|
ErrSecurityNoSigningCertDlgProc, NULL) == idGetDigitalIDs)
|
|
GetDigitalIDs(m_pAccount);
|
|
break;
|
|
|
|
default:
|
|
// idsErr = m_fMail?idsErrSendMail:NULL; // ~~~ Should we have a default for news?
|
|
break;
|
|
}
|
|
|
|
if (idsErr != 0)
|
|
{
|
|
AthErrorMessageW(m_hwnd, MAKEINTRESOURCEW(idsAthena), MAKEINTRESOURCEW(idsErrSendMail), hr);
|
|
if ((hr == hrNoRecipients) || (hr == HR_E_POST_WITHOUT_NEWS))
|
|
SetInitFocus(FALSE);
|
|
}
|
|
}
|
|
|
|
|
|
ReleaseObj(pMsg);
|
|
return hr;
|
|
}
|
|
|
|
HRESULT CNoteHdr::HrCheckSubject(BOOL fMail)
|
|
{
|
|
HWND hwnd;
|
|
|
|
if ((hwnd=GetDlgItem(m_hwnd, idTXTSubject)) && GetRichEditTextLen(hwnd)==0)
|
|
{
|
|
if (IDCANCEL == DoDontShowMeAgainDlg(m_hwnd, fMail?c_szRegMailEmptySubj:c_szRegNewsEmptySubj,
|
|
MAKEINTRESOURCE(idsAthena),
|
|
MAKEINTRESOURCE(fMail?idsWarnMailEmptySubj:idsWarnNewsEmptySubj),
|
|
MB_OKCANCEL))
|
|
{
|
|
::SetFocus(hwnd);
|
|
return MAPI_E_USER_CANCEL;
|
|
}
|
|
}
|
|
return NOERROR;
|
|
}
|
|
|
|
HRESULT CNoteHdr::HrIsCoolToSendHTML()
|
|
{
|
|
HRESULT hr=S_OK;
|
|
ADRINFO adrInfo;
|
|
BOOL fPlainText=FALSE;
|
|
int id;
|
|
|
|
// check for plaintext people
|
|
if (m_lpWabal->FGetFirst(&adrInfo))
|
|
{
|
|
do
|
|
{
|
|
if (adrInfo.fPlainText)
|
|
{
|
|
fPlainText=TRUE;
|
|
break;
|
|
}
|
|
}
|
|
while (m_lpWabal->FGetNext(&adrInfo));
|
|
}
|
|
|
|
if (fPlainText)
|
|
{
|
|
id = (int) DialogBox(g_hLocRes, MAKEINTRESOURCE(iddPlainRecipWarning), m_hwnd, _PlainWarnDlgProc);
|
|
if (id == IDNO)
|
|
return S_FALSE;
|
|
else
|
|
if (id == IDCANCEL)
|
|
return MAPI_E_USER_CANCEL;
|
|
else
|
|
return S_OK;
|
|
}
|
|
return hr;
|
|
}
|
|
|
|
|
|
|
|
INT_PTR CALLBACK _PlainWarnDlgProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
|
|
{
|
|
int id;
|
|
|
|
switch (msg)
|
|
{
|
|
case WM_INITDIALOG:
|
|
CenterDialog(hwnd);
|
|
return TRUE;
|
|
|
|
case WM_COMMAND:
|
|
id = GET_WM_COMMAND_ID(wParam, lParam);
|
|
if (id == IDYES || id == IDNO || id == IDCANCEL)
|
|
{
|
|
EndDialog(hwnd, id);
|
|
break;
|
|
}
|
|
}
|
|
return FALSE;
|
|
}
|
|
|
|
|
|
static HACCEL g_hAccelMailSend=0;
|
|
|
|
// This should only get called from the envelope as a send note
|
|
HACCEL CNoteHdr::GetAcceleratorTable()
|
|
{
|
|
Assert(!IsReadOnly());
|
|
Assert(m_pEnvelopeSite);
|
|
|
|
if (!g_hAccelMailSend)
|
|
g_hAccelMailSend = LoadAccelerators(g_hLocRes, MAKEINTRESOURCE(IDA_SEND_HDR_ACCEL));
|
|
|
|
return g_hAccelMailSend;
|
|
}
|
|
|
|
HRESULT CNoteHdr::HrInitSecurityOptions(LPMIMEMESSAGE pMsg, ULONG ulSecurityType)
|
|
{
|
|
HRESULT hr;
|
|
|
|
if (!m_fSecurityInited)
|
|
{
|
|
if (SUCCEEDED(hr = ::HrInitSecurityOptions(pMsg, ulSecurityType)))
|
|
m_fSecurityInited = TRUE;
|
|
}
|
|
else
|
|
hr = S_OK;
|
|
|
|
return hr;
|
|
}
|
|
|
|
HRESULT CNoteHdr::HrHandleSecurityIDMs(BOOL fDigSign)
|
|
{
|
|
IMimeBody *pBody;
|
|
PROPVARIANT var;
|
|
HRESULT hr;
|
|
|
|
if (fDigSign)
|
|
m_fDigSigned = !m_fDigSigned;
|
|
else
|
|
m_fEncrypted = !m_fEncrypted;
|
|
|
|
if(m_fForceEncryption && m_fDigSigned)
|
|
m_fEncrypted = TRUE;
|
|
|
|
hr = HrUpdateSecurity();
|
|
|
|
return hr;
|
|
}
|
|
|
|
|
|
HRESULT CNoteHdr::HrInitSecurity()
|
|
{
|
|
HRESULT hr = S_OK;
|
|
|
|
// Constructor set these flags to false so don't need to handle else case
|
|
if (OENA_READ != m_ntNote && m_fMail)
|
|
{
|
|
m_fDigSigned = DwGetOption(OPT_MAIL_DIGSIGNMESSAGES);
|
|
m_fEncrypted = DwGetOption(OPT_MAIL_ENCRYPTMESSAGES);
|
|
}
|
|
|
|
return hr;
|
|
}
|
|
|
|
|
|
HRESULT CNoteHdr::HrUpdateSecurity(LPMIMEMESSAGE pMsg)
|
|
{
|
|
RECT rc;
|
|
HRESULT hr = NOERROR;
|
|
LPWSTR psz = NULL;
|
|
HWND hEdit;
|
|
|
|
switch (m_ntNote)
|
|
{
|
|
case OENA_READ:
|
|
case OENA_REPLYTOAUTHOR:
|
|
case OENA_REPLYTONEWSGROUP:
|
|
case OENA_REPLYALL:
|
|
case OENA_FORWARD:
|
|
case OENA_FORWARDBYATTACH:
|
|
|
|
if (pMsg)
|
|
{
|
|
CleanupSECSTATE(&m_SecState);
|
|
HrGetSecurityState(pMsg, &m_SecState, NULL);
|
|
|
|
m_fDigSigned = IsSigned(m_SecState.type);
|
|
m_fEncrypted = IsEncrypted(m_SecState.type);
|
|
|
|
// RAID 12243. Added these two flags for broken and untrusted messages
|
|
if(m_ntNote == OENA_READ)
|
|
{
|
|
m_fSignTrusted = IsSignTrusted(&m_SecState);
|
|
m_fEncryptionOK = IsEncryptionOK(&m_SecState);
|
|
}
|
|
}
|
|
break;
|
|
|
|
case OENA_COMPOSE:
|
|
if (pMsg)
|
|
{
|
|
// Make certain that the highest security of (current message, option defaults) is applied.
|
|
//
|
|
CleanupSECSTATE(&m_SecState);
|
|
HrGetSecurityState(pMsg, &m_SecState, NULL);
|
|
|
|
if (! m_fDigSigned)
|
|
{
|
|
m_fDigSigned = IsSigned(m_SecState.type);
|
|
}
|
|
if (! m_fEncrypted)
|
|
{
|
|
m_fEncrypted = IsEncrypted(m_SecState.type);
|
|
}
|
|
}
|
|
break;
|
|
|
|
default: // do nothing
|
|
break;
|
|
}
|
|
hEdit = GetDlgItem(m_hwnd, idSecurity);
|
|
if (hEdit)
|
|
{
|
|
PHCI phci = (HCI*)GetWindowLongPtr(hEdit, GWLP_USERDATA);
|
|
// BUG 17788: need to set the text even if it is null
|
|
// since that will delete old security line text.
|
|
psz = SzGetDisplaySec(pMsg, NULL);
|
|
|
|
HdrSetRichEditText(hEdit, psz, FALSE);
|
|
|
|
phci->fEmpty = (0 == *psz);
|
|
}
|
|
|
|
m_fThisHeadDigSigned = m_fDigSigned;
|
|
m_fThisHeadEncrypted = m_fEncrypted;
|
|
|
|
// if(!m_fDigSigned)
|
|
// m_fForceEncryption = FALSE;
|
|
|
|
InvalidateRightMargin(0);
|
|
ReLayout();
|
|
|
|
if (m_pHeaderSite)
|
|
m_pHeaderSite->Update();
|
|
|
|
if (m_hwndToolbar)
|
|
{
|
|
Assert(m_pEnvelopeSite);
|
|
if (m_fDigSigned)
|
|
SendMessage(m_hwndToolbar, TB_SETSTATE, ID_DIGITALLY_SIGN, MAKELONG(TBSTATE_ENABLED | TBSTATE_PRESSED, 0));
|
|
else
|
|
SendMessage(m_hwndToolbar, TB_SETSTATE, ID_DIGITALLY_SIGN, MAKELONG(TBSTATE_ENABLED, 0));
|
|
|
|
if(m_fForceEncryption && m_fDigSigned)
|
|
SendMessage(m_hwndToolbar, TB_SETSTATE, ID_ENCRYPT, MAKELONG(TBSTATE_PRESSED, 0));
|
|
else if (m_fEncrypted)
|
|
SendMessage(m_hwndToolbar, TB_SETSTATE, ID_ENCRYPT, MAKELONG(TBSTATE_ENABLED | TBSTATE_PRESSED, 0));
|
|
else
|
|
SendMessage(m_hwndToolbar, TB_SETSTATE, ID_ENCRYPT, MAKELONG(TBSTATE_ENABLED, 0));
|
|
}
|
|
|
|
return hr;
|
|
}
|
|
|
|
|
|
HRESULT CNoteHdr::HrSaveSecurity(LPMIMEMESSAGE pMsg)
|
|
{
|
|
HRESULT hr;
|
|
ULONG ulSecurityType = MST_CLASS_SMIME_V1;
|
|
|
|
if (m_fDigSigned)
|
|
ulSecurityType |= ((DwGetOption(OPT_OPAQUE_SIGN)) ? MST_THIS_BLOBSIGN : MST_THIS_SIGN);
|
|
else
|
|
ulSecurityType &= ~((DwGetOption(OPT_OPAQUE_SIGN)) ? MST_THIS_BLOBSIGN : MST_THIS_SIGN);
|
|
|
|
|
|
if (m_fEncrypted)
|
|
ulSecurityType |= MST_THIS_ENCRYPT;
|
|
else
|
|
ulSecurityType &= ~MST_THIS_ENCRYPT;
|
|
|
|
hr = HrInitSecurityOptions(pMsg, ulSecurityType);
|
|
|
|
return hr;
|
|
}
|
|
|
|
|
|
BOOL CNoteHdr::IsReadOnly()
|
|
{
|
|
if (m_ntNote==OENA_READ)
|
|
return TRUE;
|
|
else
|
|
return FALSE;
|
|
}
|
|
|
|
|
|
HRESULT CNoteHdr::HrViewContacts()
|
|
{
|
|
LPWAB lpWab;
|
|
|
|
if (!FAILED (HrCreateWabObject (&lpWab)))
|
|
{
|
|
// launch wab in modal-mode if a) container is modal or b) running as office envelope
|
|
lpWab->HrBrowse (m_hwnd, m_fOfficeInit ? TRUE : (m_pHeaderSite ? (m_pHeaderSite->IsModal() == S_OK) : FALSE));
|
|
lpWab->Release ();
|
|
}
|
|
else
|
|
AthMessageBoxW(m_hwnd, MAKEINTRESOURCEW(idsAthenaMail), MAKEINTRESOURCEW(idsGeneralWabError), NULL, MB_OK);
|
|
|
|
return NOERROR;
|
|
}
|
|
|
|
BOOL CNoteHdr::FDoCutCopyPaste(int wmCmd)
|
|
{
|
|
HWND hwndFocus=GetFocus();
|
|
|
|
// only if it's one of our kids..
|
|
if (GetParent(hwndFocus)==m_hwnd)
|
|
{
|
|
SendMessage(hwndFocus, wmCmd, 0, 0);
|
|
return TRUE;
|
|
}
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
HRESULT CNoteHdr::GetTabStopArray(HWND *rgTSArray, int *pcArrayCount)
|
|
{
|
|
Assert(rgTSArray);
|
|
Assert(pcArrayCount);
|
|
|
|
int *array;
|
|
int cCount;
|
|
if (m_fMail)
|
|
{
|
|
if (IsReadOnly())
|
|
{
|
|
array = rgIDTabOrderMailRead;
|
|
cCount = sizeof(rgIDTabOrderMailRead)/sizeof(int);
|
|
}
|
|
else
|
|
{
|
|
array = rgIDTabOrderMailSend;
|
|
cCount = sizeof(rgIDTabOrderMailSend)/sizeof(int);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if (IsReadOnly())
|
|
{
|
|
array = rgIDTabOrderNewsRead;
|
|
cCount = sizeof(rgIDTabOrderNewsRead)/sizeof(int);
|
|
}
|
|
else
|
|
{
|
|
array = rgIDTabOrderNewsSend;
|
|
cCount = sizeof(rgIDTabOrderNewsSend)/sizeof(int);
|
|
}
|
|
}
|
|
|
|
AssertSz(cCount <= *pcArrayCount, "Do you need to change MAX_HEADER_COMP in note.h?");
|
|
for (int i = 0; i < cCount; i++)
|
|
*rgTSArray++ = GetDlgItem(m_hwnd, *array++);
|
|
|
|
*pcArrayCount = cCount;
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
|
|
HRESULT CNoteHdr::SetFlagState(MARK_TYPE markType)
|
|
{
|
|
BOOL fDoRelayout = FALSE;
|
|
switch (markType)
|
|
{
|
|
case MARK_MESSAGE_FLAGGED:
|
|
case MARK_MESSAGE_UNFLAGGED:
|
|
{
|
|
BOOL fFlagged = (MARK_MESSAGE_FLAGGED == markType);
|
|
if (m_fFlagged != fFlagged)
|
|
{
|
|
fDoRelayout = TRUE;
|
|
m_fFlagged = fFlagged;
|
|
}
|
|
break;
|
|
}
|
|
|
|
case MARK_MESSAGE_WATCH:
|
|
case MARK_MESSAGE_IGNORE:
|
|
case MARK_MESSAGE_NORMALTHREAD:
|
|
if (m_MarkType != markType)
|
|
{
|
|
fDoRelayout = TRUE;
|
|
m_MarkType = markType;
|
|
}
|
|
break;
|
|
}
|
|
|
|
if (fDoRelayout)
|
|
{
|
|
InvalidateStatus();
|
|
ReLayout();
|
|
|
|
if (m_pHeaderSite)
|
|
m_pHeaderSite->Update();
|
|
}
|
|
return S_OK;
|
|
}
|
|
|
|
|
|
HRESULT CNoteHdr::ShowEnvOptions()
|
|
{
|
|
nyi("Header options are not implemented yet.");
|
|
return S_OK;
|
|
}
|
|
|
|
void CNoteHdr::ReLayout()
|
|
{
|
|
RECT rc;
|
|
|
|
if (m_fSkipLayout)
|
|
return;
|
|
|
|
GetClientRect(m_hwnd, &rc);
|
|
SetPosOfControls(rc.right, TRUE);
|
|
|
|
InvalidateRect(m_hwnd, &rc, TRUE);
|
|
DOUTL(PAINTING_DEBUG_LEVEL, "STATE Invalidating:(%d,%d) for (%d,%d)", rc.left, rc.top, rc.right, rc.bottom);
|
|
}
|
|
|
|
//IDropTarget
|
|
HRESULT CNoteHdr::DragEnter(LPDATAOBJECT pDataObj, DWORD grfKeyState, POINTL pt, DWORD *pdwEffect)
|
|
{
|
|
LPENUMFORMATETC penum = NULL;
|
|
HRESULT hr;
|
|
FORMATETC fmt;
|
|
ULONG ulCount = 0;
|
|
|
|
if (m_lpAttMan->HrIsDragSource() == S_OK)
|
|
{
|
|
*pdwEffect=DROPEFFECT_NONE;
|
|
return S_OK;
|
|
}
|
|
|
|
if (!pdwEffect || !pDataObj)
|
|
return E_INVALIDARG;
|
|
|
|
m_dwEffect = DROPEFFECT_NONE;
|
|
|
|
// lets get the enumerator from the IDataObject, and see if the format we take is
|
|
// available
|
|
hr = pDataObj->EnumFormatEtc(DATADIR_GET, &penum);
|
|
|
|
if (SUCCEEDED(hr) && penum)
|
|
{
|
|
hr = penum->Reset();
|
|
while (SUCCEEDED(hr=penum->Next(1, &fmt, &ulCount)) && ulCount)
|
|
{
|
|
if ( fmt.cfFormat==CF_HDROP ||
|
|
fmt.cfFormat==CF_FILEDESCRIPTORA ||
|
|
fmt.cfFormat==CF_FILEDESCRIPTORW)
|
|
{
|
|
// we take either a CF_FILEDESCRIPTOR from the shell, or a CF_HDROP...
|
|
|
|
//by default, or a move if the shift key is down
|
|
if ( (*pdwEffect) & DROPEFFECT_COPY )
|
|
m_dwEffect = DROPEFFECT_COPY;
|
|
|
|
if ( ((*pdwEffect) & DROPEFFECT_MOVE) &&
|
|
(grfKeyState & MK_SHIFT))
|
|
m_dwEffect=DROPEFFECT_MOVE;
|
|
|
|
// IE3 gives us a link
|
|
// if ONLY link is specified, default to a copy
|
|
if (*pdwEffect == DROPEFFECT_LINK)
|
|
m_dwEffect=DROPEFFECT_LINK;
|
|
|
|
m_cfAccept=fmt.cfFormat;
|
|
if (m_cfAccept==CF_FILEDESCRIPTORW) // this is the richest format we take, if we find one of these, no point looking any
|
|
break; // further...
|
|
}
|
|
}
|
|
}
|
|
|
|
ReleaseObj(penum);
|
|
*pdwEffect = m_dwEffect;
|
|
m_grfKeyState = grfKeyState;
|
|
return S_OK;
|
|
}
|
|
|
|
|
|
HRESULT CNoteHdr::DragOver(DWORD grfKeyState,POINTL pt, DWORD *pdwEffect)
|
|
{
|
|
if (m_lpAttMan->HrIsDragSource() == S_OK)
|
|
{
|
|
*pdwEffect=DROPEFFECT_NONE;
|
|
return S_OK;
|
|
}
|
|
|
|
if ( m_dwEffect == DROPEFFECT_NONE) // we're not taking drops at all...
|
|
{
|
|
*pdwEffect = m_dwEffect;
|
|
return NOERROR;
|
|
}
|
|
|
|
// Cool, we've accepted the drag this far... now we
|
|
// have to watch to see if it turns into a copy or move...
|
|
// as before, take the copy as default or move if the
|
|
// shft key is down
|
|
if ((*pdwEffect)&DROPEFFECT_COPY)
|
|
m_dwEffect=DROPEFFECT_COPY;
|
|
|
|
if (((*pdwEffect)&DROPEFFECT_MOVE)&&
|
|
(grfKeyState&MK_SHIFT))
|
|
m_dwEffect=DROPEFFECT_MOVE;
|
|
|
|
if (*pdwEffect==DROPEFFECT_LINK) // if it's link ONLY, like IE3 gives, then fine...
|
|
m_dwEffect=DROPEFFECT_LINK;
|
|
|
|
*pdwEffect &= m_dwEffect;
|
|
m_grfKeyState=grfKeyState;
|
|
|
|
return NOERROR;
|
|
}
|
|
|
|
|
|
HRESULT CNoteHdr::DragLeave()
|
|
{
|
|
return NOERROR;
|
|
}
|
|
|
|
|
|
HRESULT CNoteHdr::Drop(LPDATAOBJECT pDataObj, DWORD grfKeyState, POINTL pt, DWORD *pdwEffect)
|
|
{
|
|
HRESULT hr = E_FAIL;
|
|
FORMATETC fmte = {m_cfAccept, NULL, DVASPECT_CONTENT, -1, TYMED_HGLOBAL};
|
|
STGMEDIUM medium;
|
|
|
|
*pdwEffect = m_dwEffect;
|
|
|
|
if ( m_dwEffect != DROPEFFECT_NONE )
|
|
{
|
|
// If this is us sourcing the drag, just bail. We may want to save the
|
|
// points of the icons.
|
|
//
|
|
if (m_lpAttMan->HrIsDragSource() == S_OK)
|
|
{
|
|
*pdwEffect=DROPEFFECT_NONE;
|
|
return S_OK;
|
|
}
|
|
|
|
if ( (m_grfKeyState & MK_RBUTTON) &&
|
|
m_lpAttMan->HrGetRequiredAction(pdwEffect, pt))
|
|
return E_FAIL;
|
|
|
|
|
|
if (pDataObj &&
|
|
SUCCEEDED(pDataObj->GetData(&fmte, &medium)))
|
|
{
|
|
|
|
if (m_cfAccept==CF_HDROP)
|
|
{
|
|
HDROP hdrop=(HDROP)GlobalLock(medium.hGlobal);
|
|
|
|
hr=m_lpAttMan->HrDropFiles(hdrop, (*pdwEffect)&DROPEFFECT_LINK);
|
|
|
|
GlobalUnlock(medium.hGlobal);
|
|
}
|
|
else
|
|
if (m_cfAccept==CF_FILEDESCRIPTORA || m_cfAccept==CF_FILEDESCRIPTORW)
|
|
{
|
|
// all file descriptors are copy|more, link makes no sense, as they are are
|
|
// memory object, ie. non-existent in fat.
|
|
hr=m_lpAttMan->HrDropFileDescriptor(pDataObj, FALSE);
|
|
}
|
|
#ifdef DEBUG
|
|
else
|
|
AssertSz(0, "how did this clipformat get accepted??");
|
|
#endif
|
|
|
|
if (medium.pUnkForRelease)
|
|
medium.pUnkForRelease->Release();
|
|
else
|
|
GlobalFree(medium.hGlobal);
|
|
}
|
|
}
|
|
return hr;
|
|
}
|
|
|
|
HRESULT CNoteHdr::HrGetAttachCount(ULONG *pcAttach)
|
|
{
|
|
return m_lpAttMan->HrGetAttachCount(pcAttach);
|
|
}
|
|
|
|
HRESULT CNoteHdr::HrIsDragSource()
|
|
{
|
|
return m_lpAttMan->HrIsDragSource();
|
|
}
|
|
|
|
|
|
HRESULT CNoteHdr::UnloadAll()
|
|
{
|
|
if (m_lpAttMan)
|
|
{
|
|
m_lpAttMan->HrUnload();
|
|
m_lpAttMan->HrClearDirtyFlag();
|
|
}
|
|
|
|
for (int i=0; i<(int)m_cHCI; i++)
|
|
{
|
|
if (0 == (m_rgHCI[i].dwFlags & HCF_ATTACH))
|
|
{
|
|
if (0 == (m_rgHCI[i].dwFlags & HCF_COMBO))
|
|
HdrSetRichEditText(GetDlgItem(m_hwnd, m_rgHCI[i].idEdit), c_wszEmpty, FALSE);
|
|
else
|
|
SetWindowText(GetDlgItem(m_hwnd, m_rgHCI[i].idEdit), "");
|
|
}
|
|
}
|
|
|
|
m_fDirty = FALSE;
|
|
m_pri = priNorm;
|
|
return S_OK;
|
|
}
|
|
|
|
void CNoteHdr::SetDirtyFlag()
|
|
{
|
|
if (!m_fStillLoading)
|
|
{
|
|
m_fDirty = TRUE;
|
|
if (m_pEnvelopeSite)
|
|
m_pEnvelopeSite->OnPropChange(dispidSomething);
|
|
}
|
|
}
|
|
|
|
void CNoteHdr::SetPosOfControls(int headerWidth, BOOL fChangeVisibleStates)
|
|
{
|
|
int cx,
|
|
cy,
|
|
cyDirty,
|
|
cyLabelDirty,
|
|
oldWidth = 0,
|
|
windowPosFlags = SETWINPOS_DEF_FLAGS,
|
|
editWidth = headerWidth - m_cxLeftMargin - GetRightMargin(FALSE);
|
|
RECT rc;
|
|
HWND hwnd;
|
|
PHCI phci = m_rgHCI;
|
|
BOOL fRePosition = FALSE;
|
|
|
|
if ((headerWidth < 5) || (m_fSkipLayout))
|
|
return;
|
|
|
|
STACK("SetPosOfControls (header width, edit width)", headerWidth, editWidth);
|
|
|
|
// size the dialog
|
|
GetClientRect(m_hwnd, &rc);
|
|
cyDirty = rc.bottom;
|
|
cyLabelDirty = rc.bottom;
|
|
|
|
if (fChangeVisibleStates)
|
|
windowPosFlags |= SWP_SHOWWINDOW;
|
|
|
|
cy = BeginYPos();
|
|
|
|
for (int i=0; i<(int)m_cHCI; i++, phci++)
|
|
{
|
|
hwnd = GetDlgItem(m_hwnd, phci->idEdit);
|
|
if (hwnd)
|
|
{
|
|
if (S_OK == HrFShowHeader(phci))
|
|
{
|
|
int newLabelCY = (phci->dwFlags & HCF_BORDER) ? cy + 2*cyBorder : cy;
|
|
BOOL fLabelMoved = FALSE;
|
|
if (phci->cy != cy)
|
|
{
|
|
int smcy = ((INVALID_PHCI_Y != phci->cy) && (phci->cy < cy)) ? phci->cy : cy;
|
|
if (cyLabelDirty > smcy)
|
|
cyLabelDirty = smcy;
|
|
phci->cy = cy;
|
|
fLabelMoved = TRUE;
|
|
}
|
|
|
|
// Is an attachment
|
|
if (HCF_ATTACH & phci->dwFlags)
|
|
{
|
|
DWORD cyAttMan = 0;
|
|
RECT rc;
|
|
|
|
m_lpAttMan->HrGetHeight(editWidth, &cyAttMan);
|
|
if (cyAttMan > MAX_ATTACH_PIXEL_HEIGHT)
|
|
cyAttMan = MAX_ATTACH_PIXEL_HEIGHT;
|
|
|
|
cyAttMan += 4*cyBorder;
|
|
|
|
cyDirty = cy;
|
|
|
|
rc.left = m_cxLeftMargin;
|
|
rc.right = m_cxLeftMargin + editWidth;
|
|
rc.top = cy;
|
|
rc.bottom = cy + cyAttMan;
|
|
|
|
m_lpAttMan->HrSetSize(&rc);
|
|
|
|
if ((cyAttMan != (DWORD)phci->height) && (cyDirty > cy))
|
|
cyDirty = cy;
|
|
|
|
AssertSz(cyAttMan != 0, "Setting this to zero would be a bummer...");
|
|
phci->height = cyAttMan;
|
|
|
|
cy += cyAttMan + ControlYBufferSize();
|
|
}
|
|
// Is either an edit or combo
|
|
else
|
|
{
|
|
int newHeight = phci->height,
|
|
ctrlHeight = GetCtrlHeight(hwnd);
|
|
|
|
oldWidth = GetCtrlWidth(hwnd);
|
|
|
|
if (HCF_COMBO & phci->dwFlags)
|
|
{
|
|
if (ctrlHeight != newHeight)
|
|
{
|
|
fRePosition = TRUE;
|
|
phci->height = ctrlHeight;
|
|
newHeight = GetControlSize(TRUE, NUM_COMBO_LINES);
|
|
}
|
|
else
|
|
{
|
|
fRePosition = fRePosition || fLabelMoved || (oldWidth != editWidth);
|
|
if (fRePosition)
|
|
newHeight = GetControlSize(TRUE, NUM_COMBO_LINES);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
fRePosition = fRePosition || fLabelMoved || (oldWidth != editWidth) || (ctrlHeight != newHeight);
|
|
}
|
|
|
|
if (fRePosition)
|
|
{
|
|
SetWindowPos(hwnd, NULL, m_cxLeftMargin, cy, editWidth, newHeight, windowPosFlags);
|
|
|
|
// RAID 81136: The above SetWindowPos might change the width in such a way
|
|
// that the height now needs to change. We detect this condition below and
|
|
// cause another resize to handle the needed height change. This, of course,
|
|
// is only valid with the richedits.
|
|
if ((newHeight != phci->height) && (0 == (HCF_COMBO & phci->dwFlags)))
|
|
{
|
|
SetWindowPos(hwnd, NULL, m_cxLeftMargin, cy, editWidth, phci->height, windowPosFlags);
|
|
}
|
|
if (cyDirty > cy)
|
|
cyDirty = cy;
|
|
if (fLabelMoved)
|
|
InvalidateRect(hwnd, NULL, FALSE);
|
|
}
|
|
cy += phci->height + ControlYBufferSize();
|
|
}
|
|
}
|
|
else
|
|
{
|
|
phci->cy = INVALID_PHCI_Y;
|
|
if (fChangeVisibleStates)
|
|
SetWindowPos(hwnd, NULL, 0, 0, 0, 0, SWP_NOSIZE|SWP_NOMOVE|SWP_HIDEWINDOW);
|
|
}
|
|
}
|
|
}
|
|
|
|
DOUTL(RESIZING_DEBUG_LEVEL, "STATE resizing header (headerwidth=%d, cy=%d)", headerWidth, cy);
|
|
|
|
// don't send a poschanging, as we did all the work here, plus invalidation...
|
|
SetWindowPos(m_hwnd, NULL, NULL, NULL, headerWidth, cy,
|
|
SETWINPOS_DEF_FLAGS|SWP_NOMOVE|SWP_DRAWFRAME|SWP_FRAMECHANGED);
|
|
|
|
// notify the parent to resize the note...
|
|
if (m_pHeaderSite)
|
|
m_pHeaderSite->Resize();
|
|
|
|
if (m_pEnvelopeSite)
|
|
{
|
|
m_pEnvelopeSite->RequestResize(&cy);
|
|
}
|
|
|
|
GetRealClientRect(m_hwnd, &rc);
|
|
|
|
// Dirty the labels region
|
|
if (rc.bottom != cyLabelDirty)
|
|
{
|
|
rc.top = cyLabelDirty;
|
|
rc.right = m_cxLeftMargin;
|
|
rc.left = 0;
|
|
InvalidateRect(m_hwnd, &rc, TRUE);
|
|
DOUTL(PAINTING_DEBUG_LEVEL, "STATE Invalidating:(%d,%d) for (%d,%d)", rc.left, rc.top, rc.right, rc.bottom);
|
|
}
|
|
|
|
// Dirty the right margin if needed.
|
|
if (editWidth != oldWidth)
|
|
{
|
|
int rightMargin = (editWidth > oldWidth) ? editWidth - oldWidth : 0;
|
|
|
|
InvalidateRightMargin(rightMargin);
|
|
}
|
|
|
|
|
|
#ifdef DEBUG
|
|
DEBUGDumpHdr(m_hwnd, m_cHCI, m_rgHCI);
|
|
#endif
|
|
|
|
}
|
|
|
|
void CNoteHdr::InvalidateRightMargin(int additionalWidth)
|
|
{
|
|
RECT rc;
|
|
GetClientRect(m_hwnd, &rc);
|
|
|
|
rc.left = rc.right - GetRightMargin(TRUE) - additionalWidth;
|
|
|
|
InvalidateRect(m_hwnd, &rc, TRUE);
|
|
DOUTL(PAINTING_DEBUG_LEVEL, "STATE Invalidating:(%d,%d) for (%d,%d)", rc.left, rc.top, rc.right, rc.bottom);
|
|
}
|
|
|
|
|
|
HRESULT CNoteHdr::HrUpdateCachedHeight(HWND hwndEdit, RECT *prc)
|
|
{
|
|
int cyGrow,
|
|
cLines = (int) SendMessage(hwndEdit, EM_GETLINECOUNT, 0, 0);
|
|
BOOL fIncludeEdges = WS_EX_CLIENTEDGE & GetWindowLong(hwndEdit, GWL_EXSTYLE);
|
|
PHCI phci = (HCI*)GetWindowLongPtr(hwndEdit, GWLP_USERDATA);
|
|
|
|
if (prc->bottom < 0 || prc->top < 0)
|
|
return S_FALSE;
|
|
|
|
STACK("HrUpdateCachedHeight. Desired lines", cLines);
|
|
|
|
// Only allow between 1 and MAX_RICHEDIT_LINES lines
|
|
if (cLines < 1)
|
|
cLines = 1;
|
|
else if (cLines > MAX_RICHEDIT_LINES)
|
|
cLines = MAX_RICHEDIT_LINES;
|
|
|
|
DOUTL(RESIZING_DEBUG_LEVEL, "STATE Actual lines=%d", cLines);
|
|
|
|
// Figure out how many pixels cLines lines is
|
|
cyGrow = GetControlSize(fIncludeEdges, cLines);
|
|
|
|
// If these are different, then change is needed
|
|
if (cyGrow != GetCtrlHeight(hwndEdit))
|
|
phci->height = cyGrow;
|
|
else
|
|
return S_FALSE;
|
|
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
|
|
void CNoteHdr::ShowControls()
|
|
{
|
|
PHCI phci = m_rgHCI;
|
|
|
|
STACK("ShowControls");
|
|
|
|
for (int i=0; i<(int)m_cHCI; i++, phci++)
|
|
{
|
|
HWND hwnd;
|
|
BOOL fHide;
|
|
|
|
fHide = (S_FALSE == HrFShowHeader(phci));
|
|
|
|
hwnd = GetDlgItem(m_hwnd, phci->idEdit);
|
|
if (hwnd)
|
|
ShowWindow(hwnd, fHide?SW_HIDE:SW_SHOW);
|
|
}
|
|
}
|
|
|
|
int CNoteHdr::GetRightMargin(BOOL fMax)
|
|
{
|
|
int margin = ControlXBufferSize();
|
|
|
|
if (fMax || m_fDigSigned || m_fEncrypted || m_fVCard)
|
|
margin += margin + cxBtn;
|
|
|
|
return margin;
|
|
}
|
|
|
|
// prc is in and out
|
|
DWORD CNoteHdr::GetButtonUnderMouse(int x, int y)
|
|
{
|
|
int resultButton = HDRCB_NO_BUTTON;
|
|
PHCI phci = m_rgHCI;
|
|
|
|
// Is it in the labels?
|
|
if ((x > int(ControlXBufferSize() - BUTTON_BUFFER)) && (x < int(m_cxLeftMargin - ControlXBufferSize() + BUTTON_BUFFER)))
|
|
{
|
|
for (int i=0; i<(int)m_cHCI; i++, phci++)
|
|
{
|
|
// Only check labels that have buttons that are showing
|
|
if ((0 != (phci->dwFlags & HCF_HASBUTTON)) && (INVALID_PHCI_Y != phci->cy))
|
|
{
|
|
if (y < (phci->cy))
|
|
break;
|
|
|
|
if (y < (phci->cy + 2*BUTTON_BUFFER + g_cyLabelHeight))
|
|
{
|
|
resultButton = i;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
else
|
|
// Is one of the right side buttons?
|
|
{
|
|
int width = GetCtrlWidth(m_hwnd),
|
|
xBuffSize = ControlXBufferSize(),
|
|
yBuffSize = ControlYBufferSize();
|
|
|
|
// Are we in the correct x range?
|
|
if ((x > (width - (xBuffSize + cxBtn + BUTTON_BUFFER))) && (x < width - xBuffSize + BUTTON_BUFFER))
|
|
{
|
|
BOOL rgBtnStates[] = {BUTTON_STATES};
|
|
BOOL rgUseButton[] = {BUTTON_USE_IN_COMPOSE};
|
|
BOOL fReadOnly = IsReadOnly();
|
|
int cy = BeginYPos();
|
|
|
|
for (int i = 0; i < ARRAYSIZE(rgBtnStates); i++)
|
|
{
|
|
if (rgBtnStates[i])
|
|
{
|
|
if (y < cy)
|
|
break;
|
|
|
|
if (y < (cy + cyBtn + 2*BUTTON_BUFFER))
|
|
{
|
|
if (fReadOnly || rgUseButton[i])
|
|
resultButton = g_rgBtnInd[i];
|
|
break;
|
|
}
|
|
|
|
cy += cyBtn + 2*BUTTON_BUFFER + yBuffSize;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
return resultButton;
|
|
}
|
|
|
|
void CNoteHdr::GetButtonRect(DWORD iBtn, RECT *prc)
|
|
{
|
|
// Do we already have the rect?
|
|
if (iBtn == m_dwCurrentBtn)
|
|
{
|
|
CopyRect(prc, &m_rcCurrentBtn);
|
|
return;
|
|
}
|
|
|
|
// Buttons on the left hand side of the header
|
|
if (ButtonInLabels(iBtn))
|
|
{
|
|
AssertSz(iBtn < m_cHCI, "We are about to access an invalid element...");
|
|
int cyBegin = BeginYPos();
|
|
|
|
prc->top = m_rgHCI[iBtn].cy;
|
|
prc->bottom = m_rgHCI[iBtn].cy + g_cyLabelHeight + 2*BUTTON_BUFFER;
|
|
prc->left = ControlXBufferSize() - BUTTON_BUFFER;
|
|
prc->right = (m_cxLeftMargin - ControlXBufferSize()) + BUTTON_BUFFER;
|
|
|
|
DOUTL(PAINTING_DEBUG_LEVEL, "STATE Set New Button Frame for button (btn:%d):(%d,%d) to (%d,%d)",
|
|
iBtn, prc->left, prc->top, prc->right, prc->bottom);
|
|
}
|
|
// Buttons on the right hand side.
|
|
else
|
|
{
|
|
RECT rc;
|
|
int cx = GetCtrlWidth(m_hwnd) - (ControlXBufferSize() + cxBtn),
|
|
cy = BeginYPos(),
|
|
yBuffSize = cyBtn + ControlYBufferSize() + 2*BUTTON_BUFFER;
|
|
|
|
BOOL rgBtnStates[] = {BUTTON_STATES};
|
|
|
|
prc->left = cx - BUTTON_BUFFER;
|
|
prc->right = cx + cxBtn + BUTTON_BUFFER;
|
|
for (int i = 0; i < ARRAYSIZE(rgBtnStates); i++)
|
|
{
|
|
if (g_rgBtnInd[i] == iBtn)
|
|
{
|
|
prc->top = cy;
|
|
prc->bottom = cy + cyBtn + 2*BUTTON_BUFFER;
|
|
DOUTL(PAINTING_DEBUG_LEVEL, "STATE Set New Button Frame for button (btn:%d):(%d,%d) to (%d,%d)",
|
|
iBtn, prc->left, prc->top, prc->right, prc->bottom);
|
|
return;
|
|
}
|
|
else if (rgBtnStates[i])
|
|
cy += yBuffSize;
|
|
}
|
|
}
|
|
}
|
|
|
|
int CNoteHdr::BeginYPos()
|
|
{
|
|
int beginBuffer = m_dxTBOffset;
|
|
int cLines = 0;
|
|
|
|
if (m_fFlagged || (priLow == m_pri) || (priHigh == m_pri) || (MARK_MESSAGE_NORMALTHREAD != m_MarkType))
|
|
cLines++;
|
|
|
|
if (m_lpAttMan->GetUnsafeAttachCount())
|
|
cLines++;
|
|
|
|
if (cLines)
|
|
beginBuffer += GetStatusHeight(cLines) + g_cyFont/2;
|
|
|
|
return beginBuffer;
|
|
}
|
|
|
|
void CNoteHdr::HandleButtonClicks(int x, int y, int iBtn)
|
|
{
|
|
m_dwCurrentBtn = HDRCB_NO_BUTTON;
|
|
m_dwClickedBtn = HDRCB_NO_BUTTON;
|
|
HeaderRelease(TRUE);
|
|
InvalidateRect(m_hwnd, &m_rcCurrentBtn, FALSE);
|
|
|
|
if (HDRCB_NO_BUTTON == iBtn)
|
|
return;
|
|
|
|
switch (iBtn)
|
|
{
|
|
case HDRCB_VCARD:
|
|
HrShowVCardCtxtMenu(x, y);
|
|
break;
|
|
|
|
case HDRCB_SIGNED:
|
|
case HDRCB_ENCRYPT:
|
|
{
|
|
HrShowSecurityProperty(m_hwnd, m_pMsg);
|
|
break;
|
|
}
|
|
|
|
// This is an index into the labels
|
|
default:
|
|
OnButtonClick(m_rgHCI[iBtn].idBtn);
|
|
break;
|
|
}
|
|
}
|
|
|
|
void CNoteHdr::InvalidateStatus()
|
|
{
|
|
RECT rc;
|
|
GetClientRect(m_hwnd, &rc);
|
|
|
|
rc.bottom = BeginYPos();
|
|
|
|
InvalidateRect(m_hwnd, &rc, TRUE);
|
|
DOUTL(PAINTING_DEBUG_LEVEL, "STATE Invalidating:(%d,%d) for (%d,%d)", rc.left, rc.top, rc.right, rc.bottom);
|
|
}
|
|
|
|
|
|
|
|
|
|
HRESULT CNoteHdr::_CreateEnvToolbar()
|
|
{
|
|
UINT i;
|
|
RECT rc;
|
|
TCHAR szRes[CCHMAX_STRINGRES];
|
|
REBARBANDINFO rbbi;
|
|
POINT ptIdeal = {0};
|
|
|
|
// ~~~~ Do we need to do a WrapW here????
|
|
// create REBAR so we can show toolbar chevrons
|
|
m_hwndRebar = CreateWindowEx(0, REBARCLASSNAME, NULL,
|
|
WS_VISIBLE | WS_CHILD | WS_CLIPCHILDREN |
|
|
WS_CLIPSIBLINGS | CCS_NODIVIDER | CCS_NOPARENTALIGN,
|
|
0, 0, 100, 136, m_hwnd, NULL, g_hInst, NULL);
|
|
|
|
if (!m_hwndRebar)
|
|
return E_OUTOFMEMORY;
|
|
|
|
SendMessage(m_hwndRebar, RB_SETTEXTCOLOR, 0, (LPARAM)GetSysColor(COLOR_BTNTEXT));
|
|
SendMessage(m_hwndRebar, RB_SETBKCOLOR, 0, (LPARAM)GetSysColor(COLOR_BTNFACE));
|
|
//SendMessage(m_hwndRebar, RB_SETEXTENDEDSTYLE, RBS_EX_OFFICE9, RBS_EX_OFFICE9);
|
|
SendMessage(m_hwndRebar, CCM_SETVERSION, COMCTL32_VERSION, 0);
|
|
|
|
// ~~~~ Do we need to do a WrapW here????
|
|
m_hwndToolbar = CreateWindowEx(WS_EX_TOOLWINDOW, TOOLBARCLASSNAME, NULL,
|
|
WS_CHILD|WS_CLIPCHILDREN|WS_VISIBLE|CCS_NOPARENTALIGN|CCS_NODIVIDER|
|
|
TBSTYLE_TOOLTIPS|TBSTYLE_FLAT|TBSTYLE_LIST,
|
|
0, 0, 0, 0, m_hwndRebar, NULL,
|
|
g_hInst, NULL);
|
|
|
|
if (!m_hwndToolbar)
|
|
return E_OUTOFMEMORY;
|
|
|
|
// set style on toolbar
|
|
SendMessage(m_hwndToolbar, TB_SETEXTENDEDSTYLE, 0, TBSTYLE_EX_DRAWDDARROWS);
|
|
|
|
SendMessage(m_hwndToolbar, TB_BUTTONSTRUCTSIZE, sizeof(TBBUTTON), 0);
|
|
SendMessage(m_hwndToolbar, TB_ADDBUTTONS, (WPARAM)ARRAYSIZE(c_btnsOfficeEnvelope), (LPARAM)c_btnsOfficeEnvelope);
|
|
|
|
// set the normal imagelist, office toolbar has ONE only as it's always in Color
|
|
m_himl = LoadMappedToolbarBitmap(g_hLocRes, (fIsWhistler() ? ((GetCurColorRes() > 24) ? idb32SmBrowserHot : idbSmBrowserHot): idbNWSmBrowserHot), cxTBButton);
|
|
if (!m_himl)
|
|
return E_OUTOFMEMORY;
|
|
|
|
SendMessage(m_hwndToolbar, TB_SETIMAGELIST, 0, (LPARAM)m_himl);
|
|
SendMessage(m_hwndToolbar, TB_SETBUTTONSIZE, 0, MAKELONG(cxTBButton, cxTBButton));
|
|
|
|
// Add text to the Bcc btn. The Send btn is taken care of in the Init
|
|
_SetButtonText(ID_ENV_BCC, MAKEINTRESOURCE(idsEnvBcc));
|
|
|
|
GetClientRect(m_hwndToolbar, &rc);
|
|
|
|
// get the IDEALSIZE of the toolbar
|
|
SendMessage(m_hwndToolbar, TB_GETIDEALSIZE, FALSE, (LPARAM)&ptIdeal);
|
|
|
|
// insert a band
|
|
ZeroMemory(&rbbi, sizeof(rbbi));
|
|
rbbi.cbSize = sizeof(REBARBANDINFO);
|
|
rbbi.fMask = RBBIM_SIZE | RBBIM_CHILD | RBBIM_CHILDSIZE | RBBIM_IDEALSIZE | RBBIM_STYLE;
|
|
rbbi.fStyle = RBBS_USECHEVRON;
|
|
rbbi.cx = 0;
|
|
rbbi.hwndChild = m_hwndToolbar;
|
|
rbbi.cxMinChild = 0;
|
|
rbbi.cyMinChild = rc.bottom;
|
|
rbbi.cxIdeal = ptIdeal.x;
|
|
|
|
SendMessage(m_hwndRebar, RB_INSERTBAND, (UINT)-1, (LPARAM)(LPREBARBANDINFO)&rbbi);
|
|
|
|
// set the toolbar offset
|
|
m_dxTBOffset = rc.bottom;
|
|
return S_OK;
|
|
}
|
|
|
|
|
|
|
|
HRESULT CNoteHdr::_LoadFromStream(IStream *pstm)
|
|
{
|
|
HRESULT hr;
|
|
IMimeMessage *pMsg;
|
|
IStream *pstmTmp,
|
|
*pstmMsg;
|
|
PERSISTHEADER rPersist;
|
|
ULONG cbRead;
|
|
CLSID clsid;
|
|
|
|
if (pstm == NULL)
|
|
return E_INVALIDARG;
|
|
|
|
HrRewindStream(pstm);
|
|
|
|
// make sure it's our GUID
|
|
if (ReadClassStm(pstm, &clsid)!=S_OK ||
|
|
!IsEqualCLSID(clsid, CLSID_OEEnvelope))
|
|
return E_FAIL;
|
|
|
|
// make sure the persistent header is the correct version
|
|
hr = pstm->Read(&rPersist, sizeof(PERSISTHEADER), &cbRead);
|
|
if (hr != S_OK || cbRead != sizeof(PERSISTHEADER) || rPersist.cbSize != sizeof(PERSISTHEADER))
|
|
return E_FAIL;
|
|
|
|
// read the message
|
|
hr = HrCreateMessage(&pMsg);
|
|
if (!FAILED(hr))
|
|
{
|
|
hr = MimeOleCreateVirtualStream(&pstmMsg);
|
|
if (!FAILED(hr))
|
|
{
|
|
// MimeOle always rewinds the stream we give it, so we have to copy the
|
|
// message from our persistent stream into another stream
|
|
hr = HrCopyStream(pstm, pstmMsg, NULL);
|
|
if (!FAILED(hr))
|
|
{
|
|
hr = pMsg->Load(pstmMsg);
|
|
if (!FAILED(hr))
|
|
{
|
|
hr = Load(pMsg);
|
|
if (!FAILED(hr))
|
|
{
|
|
// BUG: as we use an empty message to persist data for office envelope and empty mime-body can be
|
|
// considers a text/plain body part. We need to make sure we mark this as RENDERED before loading
|
|
// any attachments
|
|
if (pMsg->GetTextBody(TXT_PLAIN, IET_DECODED, &pstmTmp, NULL)==S_OK)
|
|
pstmTmp->Release();
|
|
|
|
hr = OnDocumentReady(pMsg);
|
|
}
|
|
}
|
|
}
|
|
pstmMsg->Release();
|
|
}
|
|
pMsg->Release();
|
|
}
|
|
return hr;
|
|
}
|
|
|
|
HRESULT CNoteHdr::_SetButtonText(int idmCmd, LPSTR pszText)
|
|
{
|
|
TBBUTTONINFO tbi;
|
|
TCHAR szRes[CCHMAX_STRINGRES];
|
|
|
|
ZeroMemory(&tbi, sizeof(TBBUTTONINFO));
|
|
tbi.cbSize = sizeof(TBBUTTONINFO);
|
|
tbi.dwMask = TBIF_TEXT | TBIF_STYLE;
|
|
tbi.fsStyle = TBSTYLE_BUTTON | TBSTYLE_AUTOSIZE;
|
|
|
|
if (IS_INTRESOURCE(pszText))
|
|
{
|
|
// its a string resource id
|
|
LoadString(g_hLocRes, PtrToUlong(pszText), szRes, sizeof(szRes));
|
|
pszText = szRes;
|
|
}
|
|
|
|
tbi.pszText = pszText;
|
|
tbi.cchText = lstrlen(pszText);
|
|
SendMessage(m_hwndToolbar, TB_SETBUTTONINFO, idmCmd, (LPARAM) &tbi);
|
|
return S_OK;
|
|
}
|
|
|
|
HRESULT CNoteHdr::_ConvertOfficeCmdIDToOE(LPDWORD pdwCmdId)
|
|
{
|
|
static const CMDMAPING rgCmdMap[] =
|
|
{ {cmdidSend, MSOEENVCMDID_SEND},
|
|
{cmdidCheckNames, MSOEENVCMDID_CHECKNAMES},
|
|
{cmdidAttach, MSOEENVCMDID_ATTACHFILE},
|
|
{cmdidSelectNames, MSOEENVCMDID_SELECTRECIPIENTS},
|
|
{cmdidFocusTo, MSOEENVCMDID_FOCUSTO},
|
|
{cmdidFocusCc, MSOEENVCMDID_FOCUSCC},
|
|
{cmdidFocusSubject, MSOEENVCMDID_FOCUSSUBJ}
|
|
};
|
|
|
|
for (int i=0; i<ARRAYSIZE(rgCmdMap); i++)
|
|
if (rgCmdMap[i].cmdIdOffice == *pdwCmdId)
|
|
{
|
|
*pdwCmdId = rgCmdMap[i].cmdIdOE;
|
|
return S_OK;
|
|
}
|
|
|
|
return E_FAIL;
|
|
}
|
|
|
|
|
|
HRESULT CNoteHdr::_UIActivate(BOOL fActive, HWND hwndFocus)
|
|
{
|
|
m_fUIActive = fActive;
|
|
if (fActive)
|
|
{
|
|
if (m_pHeaderSite)
|
|
m_pHeaderSite->OnUIActivate();
|
|
|
|
if (m_pMsoComponentMgr)
|
|
m_pMsoComponentMgr->FOnComponentActivate(m_dwComponentMgrID);
|
|
|
|
if (m_pEnvelopeSite)
|
|
{
|
|
m_pEnvelopeSite->OnEnvSetFocus();
|
|
m_pEnvelopeSite->DirtyToolbars();
|
|
}
|
|
|
|
}
|
|
else
|
|
{
|
|
// store focus if decativating
|
|
m_hwndLastFocus = hwndFocus;
|
|
if (m_pHeaderSite)
|
|
m_pHeaderSite->OnUIDeactivate(FALSE);
|
|
}
|
|
return S_OK;
|
|
}
|
|
|
|
|
|
|
|
HWND CNoteHdr::_GetNextDlgTabItem(HWND hwndDlg, HWND hwndFocus, BOOL fShift)
|
|
{
|
|
int i,
|
|
j,
|
|
idFocus = GetDlgCtrlID(hwndFocus),
|
|
iFocus;
|
|
LONG lStyle;
|
|
HWND hwnd;
|
|
|
|
// find current pos
|
|
for (i=0; i<ARRAYSIZE(rgIDTabOrderMailSend); i++)
|
|
{
|
|
if (rgIDTabOrderMailSend[i] == idFocus)
|
|
break;
|
|
}
|
|
|
|
// i now points to the current control's index
|
|
if (fShift)
|
|
{
|
|
// backwards
|
|
for (j=i-1; j>=0; j--)
|
|
{
|
|
hwnd = GetDlgItem(hwndDlg, rgIDTabOrderMailSend[j]);
|
|
AssertSz(hwnd, "something broke");
|
|
if (hwnd)
|
|
{
|
|
lStyle = GetWindowLong(hwnd, GWL_STYLE);
|
|
if ((lStyle & WS_VISIBLE) &&
|
|
(lStyle & WS_TABSTOP) &&
|
|
!(lStyle & WS_DISABLED))
|
|
return GetDlgItem(hwndDlg, rgIDTabOrderMailSend[j]);
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
// forwards tab
|
|
for (j=i+1; j<ARRAYSIZE(rgIDTabOrderMailSend); j++)
|
|
{
|
|
hwnd = GetDlgItem(hwndDlg, rgIDTabOrderMailSend[j]);
|
|
AssertSz(hwnd, "something broke");
|
|
if (hwnd)
|
|
{
|
|
lStyle = GetWindowLong(hwnd, GWL_STYLE);
|
|
if ((lStyle & WS_VISIBLE) &&
|
|
(lStyle & WS_TABSTOP) &&
|
|
!(lStyle & WS_DISABLED))
|
|
return GetDlgItem(hwndDlg, rgIDTabOrderMailSend[j]);
|
|
}
|
|
}
|
|
}
|
|
// not found
|
|
return NULL;
|
|
}
|
|
|
|
|
|
|
|
HRESULT CNoteHdr::_ClearDirtyFlag()
|
|
{
|
|
m_fDirty = FALSE;
|
|
if (m_lpAttMan)
|
|
m_lpAttMan->HrClearDirtyFlag();
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
HRESULT CNoteHdr::_RegisterAsDropTarget(BOOL fOn)
|
|
{
|
|
HRESULT hr=S_OK;
|
|
|
|
if (fOn)
|
|
{
|
|
// already registered
|
|
if (!m_fDropTargetRegister)
|
|
{
|
|
hr = CoLockObjectExternal((LPDROPTARGET)this, TRUE, FALSE);
|
|
if (FAILED(hr))
|
|
goto error;
|
|
|
|
hr = RegisterDragDrop(m_hwnd, (LPDROPTARGET)this);
|
|
if (FAILED(hr))
|
|
goto error;
|
|
|
|
m_fDropTargetRegister=TRUE;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
// nothing to do
|
|
if (m_fDropTargetRegister)
|
|
{
|
|
RevokeDragDrop(m_hwnd);
|
|
CoLockObjectExternal((LPUNKNOWN)(LPDROPTARGET)this, FALSE, TRUE);
|
|
m_fDropTargetRegister = FALSE;
|
|
}
|
|
}
|
|
|
|
error:
|
|
return hr;
|
|
}
|
|
|
|
|
|
HRESULT CNoteHdr::_RegisterWithFontCache(BOOL fOn)
|
|
{
|
|
Assert(g_pFieldSizeMgr);
|
|
|
|
if (fOn)
|
|
{
|
|
if (0 == m_dwFontNotify)
|
|
g_pFieldSizeMgr->Advise((IUnknown*)(IFontCacheNotify*)this, &m_dwFontNotify);
|
|
}
|
|
else
|
|
{
|
|
if (m_dwFontNotify)
|
|
{
|
|
g_pFieldSizeMgr->Unadvise(m_dwFontNotify);
|
|
m_dwFontNotify = NULL;
|
|
}
|
|
}
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
|
|
HRESULT CNoteHdr::_RegisterWithComponentMgr(BOOL fOn)
|
|
{
|
|
MSOCRINFO crinfo;
|
|
IServiceProvider *pSP;
|
|
|
|
if (fOn)
|
|
{
|
|
// not registered, so get a component msgr interface and register ourselves
|
|
if (m_pMsoComponentMgr == NULL)
|
|
{
|
|
// negotiate an component msgr from the host
|
|
if (m_pEnvelopeSite &&
|
|
m_pEnvelopeSite->QueryInterface(IID_IServiceProvider, (LPVOID *)&pSP)==S_OK)
|
|
{
|
|
pSP->QueryService(IID_IMsoComponentManager, IID_IMsoComponentManager, (LPVOID *)&m_pMsoComponentMgr);
|
|
pSP->Release();
|
|
}
|
|
|
|
// if not host-provided, try and obtain from LoadLibrary on office dll
|
|
if (!m_pMsoComponentMgr &&
|
|
FAILED(MsoFGetComponentManager(&m_pMsoComponentMgr)))
|
|
return E_FAIL;
|
|
|
|
Assert (m_pMsoComponentMgr);
|
|
crinfo.cbSize = sizeof(MSOCRINFO);
|
|
crinfo.uIdleTimeInterval = 3000;
|
|
crinfo.grfcrf = msocrfPreTranslateAll;
|
|
crinfo.grfcadvf = msocadvfRedrawOff;
|
|
|
|
if (!m_pMsoComponentMgr->FRegisterComponent((IMsoComponent*) this, &crinfo, &m_dwComponentMgrID))
|
|
return E_FAIL;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if (m_pMsoComponentMgr)
|
|
{
|
|
m_pMsoComponentMgr->FRevokeComponent(m_dwComponentMgrID);
|
|
m_pMsoComponentMgr->Release();
|
|
m_pMsoComponentMgr = NULL;
|
|
m_dwComponentMgrID = 0;
|
|
}
|
|
}
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
HRESULT ParseFollowup(LPMIMEMESSAGE pMsg, LPTSTR* ppszGroups, BOOL* pfPoster)
|
|
{
|
|
LPTSTR pszToken, pszTok;
|
|
BOOL fFirst = TRUE,
|
|
fPoster = FALSE;
|
|
int cchFollowup;
|
|
LPSTR lpszFollowup=0;
|
|
ADDRESSLIST addrList={0};
|
|
HRESULT hr = S_OK;
|
|
|
|
*ppszGroups = NULL;
|
|
|
|
if (!pMsg)
|
|
return E_INVALIDARG;
|
|
|
|
if (FAILED(MimeOleGetBodyPropA(pMsg, HBODY_ROOT, PIDTOSTR(PID_HDR_FOLLOWUPTO), NOFLAGS, &lpszFollowup)))
|
|
return E_FAIL;
|
|
|
|
cchFollowup = lstrlen(lpszFollowup) + 1;
|
|
if (!MemAlloc((LPVOID*) ppszGroups, sizeof(TCHAR) * cchFollowup))
|
|
{
|
|
hr = E_OUTOFMEMORY;
|
|
goto exit;
|
|
}
|
|
|
|
**ppszGroups = 0;
|
|
|
|
// WARNING: we about to trash lpszFollowup with strtok...
|
|
|
|
// Walk through the string parsing out the tokens
|
|
pszTok = lpszFollowup;
|
|
pszToken = StrTokEx(&pszTok, GRP_DELIMITERS);
|
|
while (NULL != pszToken)
|
|
{
|
|
// Want to add all items except Poster (c_szPosterKeyword)
|
|
if (0 == lstrcmpi(pszToken, c_szPosterKeyword))
|
|
fPoster = TRUE;
|
|
else
|
|
{
|
|
if (!fFirst)
|
|
{
|
|
StrCatBuff(*ppszGroups, g_szComma, cchFollowup);
|
|
}
|
|
else
|
|
fFirst = FALSE;
|
|
StrCatBuff(*ppszGroups, pszToken, cchFollowup);
|
|
}
|
|
pszToken = StrTokEx(&pszTok, GRP_DELIMITERS);
|
|
}
|
|
|
|
*pfPoster = fPoster;
|
|
|
|
exit:
|
|
SafeMimeOleFree(lpszFollowup);
|
|
|
|
if (**ppszGroups == 0)
|
|
{
|
|
MemFree(*ppszGroups);
|
|
*ppszGroups = NULL;
|
|
}
|
|
|
|
return hr;
|
|
}
|
|
|
|
//***************************************************
|
|
CFieldSizeMgr::CFieldSizeMgr(IUnknown *pUnkOuter) : CPrivateUnknown(pUnkOuter)
|
|
{
|
|
TraceCall("CFieldSizeMgr::CFieldSizeMgr");
|
|
|
|
m_pAdviseRegistry = NULL;
|
|
m_fFontsChanged = FALSE;
|
|
m_dwFontNotify = 0;
|
|
InitializeCriticalSection(&m_rAdviseCritSect);
|
|
}
|
|
|
|
//***************************************************
|
|
CFieldSizeMgr::~CFieldSizeMgr()
|
|
{
|
|
IConnectionPoint *pCP = NULL;
|
|
|
|
TraceCall("CFieldSizeMgr::~CFieldSizeMgr");
|
|
|
|
EnterCriticalSection(&m_rAdviseCritSect);
|
|
|
|
if (m_pAdviseRegistry)
|
|
m_pAdviseRegistry->Release();
|
|
|
|
LeaveCriticalSection(&m_rAdviseCritSect);
|
|
|
|
if (g_lpIFontCache)
|
|
{
|
|
if (SUCCEEDED(g_lpIFontCache->QueryInterface(IID_IConnectionPoint, (LPVOID*)&pCP)))
|
|
{
|
|
pCP->Unadvise(m_dwFontNotify);
|
|
pCP->Release();
|
|
}
|
|
}
|
|
|
|
DeleteCriticalSection(&m_rAdviseCritSect);
|
|
}
|
|
|
|
|
|
//***************************************************
|
|
HRESULT CFieldSizeMgr::OnPreFontChange(void)
|
|
{
|
|
DWORD cookie = 0;
|
|
IFontCacheNotify* pCurr;
|
|
IUnknown* pTempCurr;
|
|
|
|
TraceCall("CFieldSizeMgr::OnPreFontChange");
|
|
|
|
EnterCriticalSection(&m_rAdviseCritSect);
|
|
while(SUCCEEDED(m_pAdviseRegistry->GetNext(LD_FORWARD, &pTempCurr, &cookie)))
|
|
{
|
|
if (SUCCEEDED(pTempCurr->QueryInterface(IID_IFontCacheNotify, (LPVOID *)&pCurr)))
|
|
{
|
|
pCurr->OnPreFontChange();
|
|
pCurr->Release();
|
|
}
|
|
|
|
pTempCurr->Release();
|
|
}
|
|
LeaveCriticalSection(&m_rAdviseCritSect);
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
//***************************************************
|
|
HRESULT CFieldSizeMgr::OnPostFontChange(void)
|
|
{
|
|
DWORD cookie = 0;
|
|
IFontCacheNotify* pCurr;
|
|
IUnknown* pTempCurr;
|
|
|
|
TraceCall("CFieldSizeMgr::OnPostFontChange");
|
|
|
|
ResetGlobalSizes();
|
|
|
|
EnterCriticalSection(&m_rAdviseCritSect);
|
|
while(SUCCEEDED(m_pAdviseRegistry->GetNext(LD_FORWARD, &pTempCurr, &cookie)))
|
|
{
|
|
if (SUCCEEDED(pTempCurr->QueryInterface(IID_IFontCacheNotify, (LPVOID *)&pCurr)))
|
|
{
|
|
pCurr->OnPostFontChange();
|
|
pCurr->Release();
|
|
}
|
|
|
|
pTempCurr->Release();
|
|
}
|
|
LeaveCriticalSection(&m_rAdviseCritSect);
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
//***************************************************
|
|
HRESULT CFieldSizeMgr::GetConnectionInterface(IID *pIID)
|
|
{
|
|
return E_NOTIMPL;
|
|
}
|
|
|
|
//***************************************************
|
|
HRESULT CFieldSizeMgr::GetConnectionPointContainer(IConnectionPointContainer **ppCPC)
|
|
{
|
|
*ppCPC = NULL;
|
|
return E_NOTIMPL;
|
|
}
|
|
|
|
//***************************************************
|
|
HRESULT CFieldSizeMgr::EnumConnections(IEnumConnections **ppEnum)
|
|
{
|
|
*ppEnum = NULL;
|
|
return E_NOTIMPL;
|
|
}
|
|
|
|
//***************************************************
|
|
HRESULT CFieldSizeMgr::Advise(IUnknown *pUnkSink, DWORD *pdwCookie)
|
|
{
|
|
TraceCall("CFieldSizeMgr::Advise");
|
|
|
|
EnterCriticalSection(&m_rAdviseCritSect);
|
|
HRESULT hr = m_pAdviseRegistry->AddItem(pUnkSink, pdwCookie);
|
|
LeaveCriticalSection(&m_rAdviseCritSect);
|
|
return hr;
|
|
}
|
|
|
|
//***************************************************
|
|
HRESULT CFieldSizeMgr::Unadvise(DWORD dwCookie)
|
|
{
|
|
TraceCall("CFieldSizeMgr::Unadvise");
|
|
|
|
EnterCriticalSection(&m_rAdviseCritSect);
|
|
HRESULT hr = m_pAdviseRegistry->RemoveItem(dwCookie);
|
|
LeaveCriticalSection(&m_rAdviseCritSect);
|
|
return hr;
|
|
}
|
|
|
|
//***************************************************
|
|
int CFieldSizeMgr::GetScalingFactor(void)
|
|
{
|
|
int iScaling = 100;
|
|
UINT cp;
|
|
|
|
cp = GetACP();
|
|
if((932 == cp) || (936 == cp) || (950 == cp) || (949 == cp) || (((1255 == cp) || (1256 == cp)) && (VER_PLATFORM_WIN32_NT != g_OSInfo.dwPlatformId)))
|
|
iScaling = 115;
|
|
|
|
return iScaling;
|
|
}
|
|
|
|
//***************************************************
|
|
void CFieldSizeMgr::ResetGlobalSizes(void)
|
|
{
|
|
HDC hdc;
|
|
HFONT hfontOld,
|
|
hfont;
|
|
TEXTMETRIC tm;
|
|
|
|
int oldcyFont = g_cyFont,
|
|
oldLabelHeight = g_cyLabelHeight,
|
|
cyScaledFont;
|
|
|
|
TraceCall("CFieldSizeMgr::ResetGlobalSizes");
|
|
|
|
// calc height of edit, based on font we're going to put in it...
|
|
hdc=GetDC(NULL);
|
|
hfont = GetFont(FALSE);
|
|
hfontOld=(HFONT)SelectObject(hdc, hfont); // Hopefully charset fonts are about the same size ???!!!
|
|
|
|
g_cfHeader.cbSize = sizeof(CHARFORMAT);
|
|
FontToCharformat(hfont, &g_cfHeader);
|
|
|
|
GetTextMetrics(hdc, &tm);
|
|
|
|
DOUTL(16, "tmHeight=%d tmAscent=%d tmDescent=%d tmInternalLeading=%d tmExternalLeading=%d\n",
|
|
tm.tmHeight, tm.tmAscent, tm.tmDescent, tm.tmInternalLeading, tm.tmExternalLeading);
|
|
|
|
SelectObject(hdc, hfontOld);
|
|
|
|
cyScaledFont = (tm.tmHeight + tm.tmExternalLeading) * GetScalingFactor();
|
|
if((cyScaledFont%100) >= 50)
|
|
cyScaledFont += 100;
|
|
g_cyFont = (cyScaledFont / 100);
|
|
g_cyLabelHeight = (g_cyFont < cyBtn) ? cyBtn : g_cyFont;
|
|
|
|
DOUTL(GEN_HEADER_DEBUG_LEVEL,"cyFont=%d", g_cyFont);
|
|
ReleaseDC(NULL, hdc);
|
|
|
|
m_fFontsChanged = ((oldcyFont != g_cyFont) || (oldLabelHeight != g_cyLabelHeight));
|
|
}
|
|
|
|
//***************************************************
|
|
HRESULT CFieldSizeMgr::Init(void)
|
|
{
|
|
HRESULT hr = S_OK;
|
|
IConnectionPoint *pCP = NULL;
|
|
|
|
TraceCall("CFieldSizeMgr::Init");
|
|
|
|
ResetGlobalSizes();
|
|
|
|
EnterCriticalSection(&m_rAdviseCritSect);
|
|
|
|
IF_FAILEXIT(hr = IUnknownList_CreateInstance(&m_pAdviseRegistry));
|
|
IF_FAILEXIT(hr = m_pAdviseRegistry->Init(NULL, 0, 0));
|
|
|
|
// We don't want to fail if the font cache is not created. That just means
|
|
// that the fonts won't be changed.
|
|
if (g_lpIFontCache)
|
|
{
|
|
IF_FAILEXIT(hr = g_lpIFontCache->QueryInterface(IID_IConnectionPoint, (LPVOID*)&pCP));
|
|
IF_FAILEXIT(hr = pCP->Advise((IUnknown*)(IFontCacheNotify*)this, &m_dwFontNotify));
|
|
}
|
|
|
|
exit:
|
|
ReleaseObj(pCP);
|
|
LeaveCriticalSection(&m_rAdviseCritSect);
|
|
|
|
return hr;
|
|
}
|
|
|
|
//***************************************************
|
|
HRESULT CFieldSizeMgr::PrivateQueryInterface(REFIID riid, LPVOID *lplpObj)
|
|
{
|
|
TraceCall("CFieldSizeMgr::PrivateQueryInterface");
|
|
|
|
if(!lplpObj)
|
|
return E_INVALIDARG;
|
|
|
|
*lplpObj = NULL;
|
|
|
|
if (IsEqualIID(riid, IID_IFontCacheNotify))
|
|
*lplpObj = (LPVOID)(IFontCacheNotify *)this;
|
|
else if (IsEqualIID(riid, IID_IConnectionPoint))
|
|
*lplpObj = (LPVOID)(IConnectionPoint *)this;
|
|
else
|
|
{
|
|
return E_NOINTERFACE;
|
|
}
|
|
AddRef();
|
|
return S_OK;
|
|
}
|
|
|