|
|
//*************************************************
// 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; }
|