/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- * * The contents of this file are subject to the Netscape Public License * Version 1.0 (the "NPL"); you may not use this file except in * compliance with the NPL. You may obtain a copy of the NPL at * http://www.mozilla.org/NPL/ * * Software distributed under the NPL is distributed on an "AS IS" basis, * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL * for the specific language governing rights and limitations under the * NPL. * * The Initial Developer of this code under the NPL is Netscape * Communications Corporation. Portions created by Netscape are * Copyright (C) 1998 Netscape Communications Corporation. All Rights * Reserved. */ /* COMPFRM.CPP - Compose Window Frame. This module contains code for the * compose window frame class. Handles all menu and tool commands. * */ #include "stdafx.h" #include "rosetta.h" #include "edt.h" #include "compbar.h" #include "compfrm.h" #include "prefapi.h" #include "addrdlg.h" #include "intl_csi.h" #include "apiaddr.h" #include "namcomp.h" #include "addrfrm.h" //for MOZ_NEWADDR #include "nscpmapi.h" // rhp: for MAPI check extern "C" { #include "xpgetstr.h" extern int MK_MSG_SAVE_AS; extern int MK_MSG_CANT_OPEN; extern int MK_MSG_MISSING_SUBJECT; }; #ifdef XP_WIN32 #include "postal.h" #endif #define COMPOSE_WINDOW_WIDTH 73 // default to 73 characters wide ///////////////////////////////////////////////////////////////////////////// // CComposeFrame // This is for mail that is sent immediately static UINT ComposeCodes[] = { IDM_SENDNOW, IDM_QUOTEORIGINAL, IDM_ADDRESSPICKER, ID_CHECK_SPELLING, IDM_SAVEASDRAFT, HG26722 ID_NAVIGATE_INTERRUPT }; static BOOL bSendDeferred = FALSE; const UINT NEAR MAPI_CUST_MSG = RegisterWindowMessage(MAPI_CUSTOM_COMPOSE_MSG); // rhp - for MAPI BEGIN_MESSAGE_MAP(CComposeFrame, CGenericFrame) ON_WM_CREATE() ON_WM_CLOSE() ON_WM_SETFOCUS() ON_MESSAGE(WM_SETMESSAGESTRING, OnSetMessageString) ON_MESSAGE(NSBUTTONMENUOPEN, OnButtonMenuOpen) ON_MESSAGE(WM_TOOLCONTROLLER,OnToolController) ON_COMMAND(ID_CHECK_SPELLING, OnCheckSpelling) ON_COMMAND(IDM_PASTEASQUOTE, OnPasteQuote) ON_UPDATE_COMMAND_UI(IDM_PASTEASQUOTE, OnUpdatePasteQuote) ON_COMMAND(ID_EDIT_SELECTALLMESSAGES, OnSelectAll) ON_UPDATE_COMMAND_UI(ID_EDIT_SELECTALLMESSAGES,OnUpdateSelectAll) ON_COMMAND(IDM_SEND, OnSend) ON_UPDATE_COMMAND_UI(IDM_SEND, OnUpdateSend) ON_COMMAND(IDM_SENDNOW, OnSendNow) ON_UPDATE_COMMAND_UI(IDM_SENDNOW, OnUpdateSendNow) ON_COMMAND(IDM_SENDLATER, OnSendLater) ON_UPDATE_COMMAND_UI(IDM_SENDLATER,OnUpdateSendLater) ON_COMMAND(IDM_QUOTEORIGINAL, OnQuoteOriginal) ON_UPDATE_COMMAND_UI(IDM_QUOTEORIGINAL,OnUpdateButtonGeneral) ON_COMMAND(IDM_SAVEAS, OnSaveAs) ON_UPDATE_COMMAND_UI(IDM_SAVEAS, OnUpdateButtonGeneral) ON_COMMAND(IDM_SAVEASDRAFT, OnSaveDraft) ON_UPDATE_COMMAND_UI(IDM_SAVEASDRAFT, OnUpdateSaveDraft) ON_COMMAND(IDM_SAVEASTEMPLATE, OnSaveTemplate) ON_UPDATE_COMMAND_UI(IDM_SAVEASTEMPLATE, OnUpdateSaveTemplate) ON_COMMAND(IDM_CONVERT,OnConvert) ON_UPDATE_COMMAND_UI(IDM_CONVERT, OnUpdateConvert) ON_COMMAND(IDM_ATTACHFILE,OnAttachFile) ON_COMMAND(ID_SECURITY,OnSecurity) ON_UPDATE_COMMAND_UI(ID_SECURITY,OnUpdateSecurity) ON_COMMAND(ID_DONEGOINGOFFLINE, OnDoneGoingOffline) ON_WM_DESTROY() ON_BN_CLICKED(IDM_ATTACHFILE, OnAttachFile) ON_BN_CLICKED(IDM_ATTACHWEBPAGE, OnAttachUrl) ON_COMMAND(IDM_ADDRESSPICKER,OnSelectAddresses) ON_COMMAND(ID_MAIL_WRAPLONGLINES,OnWrapLongLines) ON_UPDATE_COMMAND_UI(ID_MAIL_WRAPLONGLINES,OnUpdateWrapLongLines) ON_COMMAND(IDM_ATTACHMYCARD,OnAttachMyCard) ON_UPDATE_COMMAND_UI(IDM_ATTACHMYCARD,OnUpdateAttachMyCard) ON_COMMAND(ID_FILE_NEWMESSAGE, OnNew) ON_COMMAND(IDM_ADDRESSES,OnViewAddresses) ON_COMMAND(IDM_ATTACHMENTS,OnViewAttachments) ON_COMMAND(IDM_OPTIONS,OnViewOptions) ON_COMMAND(IDC_ADDRESSTAB,OnAddressTab) ON_COMMAND(IDC_ATTACHTAB,OnAttachTab) ON_COMMAND(IDC_OPTIONSTAB,OnOptionsTab) ON_COMMAND(IDC_COLLAPSE,OnCollapse) ON_UPDATE_COMMAND_UI(ID_CHECK_SPELLING, OnUpdateButtonGeneral) ON_UPDATE_COMMAND_UI(IDM_ADDRESSES,OnUpdateViewAddresses) ON_UPDATE_COMMAND_UI(IDM_ATTACHMENTS,OnUpdateViewAttachments) ON_UPDATE_COMMAND_UI(IDM_OPTIONS,OnUpdateViewOptions) ON_REGISTERED_MESSAGE(WM_FINDREPLACE, OnFindReplace) // general button enabler, these should be enabled as long as the // compose window is visible ON_UPDATE_COMMAND_UI(ID_VIEW_ADDRESSES, OnUpdateButtonGeneral) ON_UPDATE_COMMAND_UI(IDC_ADDRESS,OnUpdateButtonGeneral) ON_UPDATE_COMMAND_UI(IDC_DIRECTORY,OnUpdateButtonGeneral) ON_UPDATE_COMMAND_UI(IDM_ATTACHFILE,OnUpdateButtonGeneral) ON_UPDATE_COMMAND_UI(IDM_ATTACHWEBPAGE,OnUpdateButtonGeneral) ON_UPDATE_COMMAND_UI(IDM_ADDRESSPICKER,OnUpdateButtonGeneral) ON_COMMAND(IDM_MESSAGEBODYONLY,OnToggleAddressArea) ON_UPDATE_COMMAND_UI(IDM_MESSAGEBODYONLY,OnUpdateToggleAddressArea) ON_COMMAND(IDM_OPT_MESSAGEBAR_TOGGLE, OnToggleMessageToolbar) ON_UPDATE_COMMAND_UI(IDM_OPT_MESSAGEBAR_TOGGLE, OnUpdateToggleMessageToolbar) // Security Stuff ON_UPDATE_COMMAND_UI(IDS_SECURITY_STATUS, OnUpdateSecureStatus) ON_UPDATE_COMMAND_UI(IDS_SIGNED_STATUS, OnUpdateSecureStatus) // Name completion ON_UPDATE_COMMAND_UI(ID_TOGGLENAMECOMPLETION, OnUpdateToggleNameCompletion) ON_COMMAND(ID_TOGGLENAMECOMPLETION, OnToggleNameCompletion) ON_UPDATE_COMMAND_UI(ID_SHOW_NAME_PICKER, OnUpdateShowNamePicker) ON_COMMAND(ID_SHOW_NAME_PICKER, OnShowNamePicker) // rhp - for custom message #ifndef MOZ_LITE ON_REGISTERED_MESSAGE(MAPI_CUST_MSG, OnProcessMAPIMessage) // rhp - for MAPI #endif END_MESSAGE_MAP() #ifndef _AFXDLL #undef new #endif IMPLEMENT_DYNCREATE(CComposeFrame,CGenericFrame) #ifndef _AFXDLL #define new DEBUG_NEW #endif #ifdef XP_WIN32 char *ToolBarProfileName = "MailComposeToolBar"; #endif // Constructor for CCompFrame. Creates the toolbar controller object. // This object is used by the Gold editor to display/control the // HTML toolbar commands. Initialize local variables, set the deferred // flag to the last known state CComposeFrame::CComposeFrame() { PREF_GetBoolPref("network.online", &bSendDeferred); bSendDeferred = !bSendDeferred; m_bUseHtml = FALSE; m_pToolBarController = NULL; m_pComposeBar = NULL; // dialog bar m_pComposePane = NULL; // message pane (for backend) m_pFocus = NULL; // current field with focus m_bInitialized = FALSE; m_pInitialText = NULL; m_bWrapLongLines = TRUE; m_cxChar = 0; m_quoteSel = -1; // no quoting selection yet m_bMAPISendMode = MAPI_IGNORE; // rhp - For MAPI UI-less send/save operations } // The menu gets cleaned up on window destruction but we need // to delete our accelerator table ourselves CComposeFrame::~CComposeFrame() { // free the accelerator table if(m_hAccelTable != NULL) { ::FreeResource((HGLOBAL)m_hAccelTable); m_hAccelTable = NULL; } if (m_pToolBarController) delete m_pToolBarController; // free up the dialog bar (address & attachment controls) if (m_pComposeBar) delete m_pComposeBar; } // GetAddressWidget() returns the current address control widget. LPADDRESSCONTROL CComposeFrame::GetAddressWidgetInterface() { ASSERT(m_pComposeBar); return m_pComposeBar->GetAddressWidgetInterface(); } // AppendAddress() adds a header/value to the current address block. It // accepts a MSG_HEADER_SET value which is translated to the appropriate // corresponding string and appended to the end of the address list with // the supplied value. // Returns TRUE on success, FALSE otherwise. BOOL CComposeFrame::AppendAddress( MSG_HEADER_SET header, // header to add const char * value // header value (or NULL for empty) ) { // check for a valid widget if (::IsWindow(m_pComposeBar->m_hWnd)) { // get a pointer to the addressing block widget LPADDRESSCONTROL pIAddress = GetAddressWidgetInterface(); if (pIAddress) { CListBox * pListBox = pIAddress->GetListBox(); // check to make sure we got a valid list and the list // has a valid window if (::IsWindow(pListBox->m_hWnd)) { const char * szType = MSG_HeaderMaskToString(header); if (!szType) return FALSE; // add the entry to the list pIAddress->AppendEntry(TRUE, szType,value ? value : "", 0, 0); } } } return TRUE; } // destroy message compose pane void CComposeFrame::OnDestroy() { MSG_DestroyPane(m_pComposePane); m_pComposePane = NULL; CGenericFrame::OnDestroy(); } int CComposeFrame::CreateHtmlToolbars() { // Create the HTML edit toolbars. There are currently two separate // toolbars.. one for formats and another for character operations. m_pToolBarController = new CEditToolBarController(this); ASSERT(m_pToolBarController); if (!m_pToolBarController->CreateEditBars(GetMainContext()->GetContext(), FALSE, DISPLAY_CHARACTER_TOOLBAR)) return -1; // fail to create return 0; } void CComposeFrame::DestroyHtmlToolbars() { XP_Bool prefBool; PREF_GetBoolPref("editor.show_character_toolbar",&prefBool); if ( prefBool ) { CWnd * pWnd = m_pToolBarController->GetCharacterBar(); if (pWnd && ::IsWindow(pWnd->m_hWnd)) pWnd->DestroyWindow(); } } void CComposeFrame::ShowHtmlToolbars() { // display the appropriate toolbars for HTML editing based on // configuration. XP_Bool prefBool; PREF_GetBoolPref("editor.show_character_toolbar",&prefBool); if ( prefBool ) m_pToolBarController->GetCharacterBar()->ShowWindow(SW_SHOW); } void CComposeFrame::SetMsgPane(MSG_Pane * pPane) { m_pComposePane = pPane; } void CComposeFrame::CreatePlainTextEditor() { CWnd *pView = GetDescendantWindow(AFX_IDW_PANE_FIRST, TRUE); ASSERT(pView); // create the editor parent. This is a window whose sole purpose is to // resize the edit control... this will go away when the Gold editor // is fully integrated. CRect rect(0,0,0,0); if (::IsWindow(pView->m_hWnd) && pView->IsWindowVisible()) pView->GetClientRect(rect); m_EditorParent.Create ( NULL, NULL, WS_VISIBLE | WS_CHILD, rect, pView, 0 ); SetEditorParent((CWnd*)&m_EditorParent); // create the editor which is currently a standard windows edit // control. This will be replaced by the Gold editor. if (rect.Width()) rect.left = EDIT_MARGIN_OFFSET; m_Editor.Create ( WS_VSCROLL | ES_MULTILINE | WS_CHILD | WS_VISIBLE | ES_AUTOVSCROLL | ES_WANTRETURN | ES_NOHIDESEL, rect, &m_EditorParent, IDC_COMPOSEEDITOR); m_Editor.SetComposeFrame(this); m_Editor.SetTabStops(); m_cxChar = m_Editor.GetCharWidth(); #ifdef XP_WIN16 m_Editor.SendMessage(EM_LIMITTEXT,0,0); #endif } // Perform initial setup for the compose window. // status bar format static const UINT BASED_CODE indicators[] = { HG27811 IDS_TRANSFER_STATUS, ID_SEPARATOR, IDS_ONLINE_STATUS, IDS_TASKBAR }; int CComposeFrame::OnCreate( LPCREATESTRUCT lpCreateStruct ) { int retval = CGenericFrame::OnCreate ( lpCreateStruct ); //I'm hardcoding string since I don't want it translated. m_pChrome->CreateCustomizableToolbar("Compose_Message", 3, TRUE); CButtonToolbarWindow *pWindow; BOOL bOpen, bShowing; int32 nPos; m_pChrome->LoadToolbarConfiguration(ID_COMPOSE_MESSAGE_TOOLBAR, CString("Message_Toolbar"),nPos, bOpen, bShowing); // Set up toolbar LPNSTOOLBAR pIToolBar = NULL; m_pChrome->QueryInterface(IID_INSToolBar,(LPVOID*)&pIToolBar); if ( pIToolBar ) { pIToolBar->Create( this ); pIToolBar->SetButtons( ComposeCodes, sizeof(ComposeCodes) / sizeof(UINT) ); pIToolBar->SetSizes( CSize( 23+7, 21+6), CSize( 23, 21 ) ); // this is currently loading one bitmap.. this needs to be fixed to add // the deferred bitmaps as well. pIToolBar->LoadBitmap(MAKEINTRESOURCE(IDB_COMPOSETOOLBAR)); pIToolBar->SetToolbarStyle( theApp.m_pToolbarStyle ); pWindow = new CButtonToolbarWindow(CWnd::FromHandlePermanent(pIToolBar->GetHWnd()), theApp.m_pToolbarStyle, 43, 27, eLARGE_HTAB); m_pChrome->GetCustomizableToolbar()->AddNewWindow(ID_COMPOSE_MESSAGE_TOOLBAR, pWindow,nPos, 50, 37, 0, CString(szLoadString(ID_COMPOSE_MESSAGE_TOOLBAR)),theApp.m_pToolbarStyle, bOpen, FALSE); m_pChrome->ShowToolbar(ID_COMPOSE_MESSAGE_TOOLBAR, bShowing); m_pChrome->GetCustomizableToolbar()->SetBottomBorder(TRUE); CWnd *pToolWnd = CWnd::FromHandlePermanent( pIToolBar->GetHWnd() ); if ( pToolWnd ) { CStationaryToolbarButton * pStationaryToolbarButton = new CStationaryToolbarButton; pStationaryToolbarButton->Create(pToolWnd, theApp.m_pToolbarStyle, CSize(50, 40), CSize(30, 27), szLoadString(IDS_TOOLATTACH), szLoadString(IDS_TOOLATTACHFILES), szLoadString(IDS_TOOLATTACHALL), IDB_ATTACHBUTTON, 0, CSize(23, 21), TRUE, IDM_ATTACHFILE, 10, TB_HAS_IMMEDIATE_MENU); pIToolBar->AddButton( pStationaryToolbarButton, 3 ); } if (bSendDeferred) { pIToolBar->RemoveButton(0); CCommandToolbarButton *pCommandButton = new CCommandToolbarButton; CString statusStr, toolTipStr, textStr; WFE_ParseButtonString(IDM_SENDLATER, statusStr, toolTipStr, textStr); DWORD dwButtonStyle = 0; pCommandButton->Create(pToolWnd, theApp.m_pToolbarStyle, CSize(44, 37), CSize(25, 25), (const char*) textStr,(const char*) toolTipStr, (const char*) statusStr, IDB_COMPOSETOOLBAR, 7, CSize(23,21), IDM_SENDLATER, -1, dwButtonStyle); pIToolBar->AddButton(pCommandButton, 0); CCommandToolbar *pToolBar = (CCommandToolbar *) CWnd::FromHandlePermanent( pIToolBar->GetHWnd() ); pToolBar->ReplaceButtonBitmapIndex(IDM_SENDNOW,7); } m_pChrome->Release(); } // create the address/attachment widget dialog bar m_pComposeBar = new CComposeBar(GetMainContext()->GetContext()); ASSERT(m_pComposeBar); m_pComposeBar->Create ( this, (UINT) IDD_COMPOSEBAR, (UINT) WS_CLIPCHILDREN|CBRS_TOP, (UINT) IDD_COMPOSEBAR ); if (m_bUseHtml) { if (CreateHtmlToolbars() == -1) return -1; RecalcLayout(); // Check if format toolbar needs more room and // increase window width to fit it, but observe 600 pixel maximum width int iWidth = min(600, m_pToolBarController->GetCharacterBar()->GetToolbarWidth() + GetSystemMetrics(SM_CXFRAME) + 8); // Kludge - 8 more needed to work right! if( iWidth > lpCreateStruct->cx ){ SetWindowPos(NULL, 0, 0, iWidth, lpCreateStruct->cy, SWP_NOMOVE|SWP_NOZORDER|SWP_NOACTIVATE); } } else { CreatePlainTextEditor(); } // create a unique title for the composition window CString cs; cs = szLoadString(IDS_COMPOSITION); GetChrome()->SetWindowTitle(cs); // Instead of using ANSI_VAR_FONT for i18n SetCSID(INTL_DefaultWinCharSetID(0)); // create the status bar m_barStatus.Create( this ); m_barStatus.SetIndicators(indicators, sizeof(indicators)/sizeof(UINT)); LPNSSTATUSBAR pIStatusBar = NULL; m_pChrome->QueryInterface( IID_INSStatusBar, (LPVOID *) &pIStatusBar ); if ( pIStatusBar ) { pIStatusBar->Attach( &m_barStatus ); pIStatusBar->Release(); } if (m_bUseHtml) ShowHtmlToolbars(); // Attach the submenus shared by Composer, Message Composer, and right-button popups HMENU hMenu = ::GetMenu(m_hWnd); if( hMenu ) { HMENU hTableMenu = ::GetSubMenu(hMenu, ED_MENU_TABLE); if( hTableMenu ) { ::ModifyMenu( hTableMenu, ID_SELECT_TABLE, MF_BYCOMMAND | MF_POPUP | MF_STRING, (UINT)::LoadMenu(AfxGetResourceHandle(), MAKEINTRESOURCE(IDM_COMPOSER_TABLE_SELECTMENU)), szLoadString(IDS_SUBMENU_SELECT_TABLE) ); ::ModifyMenu( hTableMenu, ID_INSERT_TABLE, MF_BYCOMMAND | MF_POPUP | MF_STRING, (UINT)::LoadMenu(AfxGetResourceHandle(), MAKEINTRESOURCE(IDM_COMPOSER_TABLE_INSERTMENU)), szLoadString(IDS_SUBMENU_INSERT_TABLE) ); ::ModifyMenu( hTableMenu, ID_DELETE_TABLE, MF_BYCOMMAND | MF_POPUP | MF_STRING, (UINT)::LoadMenu(AfxGetResourceHandle(), MAKEINTRESOURCE(IDM_COMPOSER_TABLE_DELETEMENU)), szLoadString(IDS_SUBMENU_DELETE_TABLE) ); } } return retval; } // OnCreateClient() sets up the context information and create the // contained CView derived class. BOOL CComposeFrame::OnCreateClient(LPCREATESTRUCT lpcs, CCreateContext *pContext) { BOOL bRetval = CGenericFrame::OnCreateClient(lpcs, pContext); // Get the current view CWnd *pView = GetDescendantWindow(AFX_IDW_PANE_FIRST, TRUE); ASSERT(pView); CWinCX * pWinCX = new CWinCX( (CGenericDoc*)pContext->m_pCurrentDoc, this, (CGenericView *)pView ); // This is the main and active context. SetMainContext(pWinCX); SetActiveContext(pWinCX); RECT rect; GetClientRect(&rect); pWinCX->Initialize(FALSE, &rect); pWinCX->GetContext()->fancyFTP = TRUE; pWinCX->GetContext()->fancyNews = TRUE; pWinCX->GetContext()->intrupt = FALSE; if (m_bUseHtml) pWinCX->GetContext()->is_editor = TRUE; pWinCX->GetContext()->reSize = FALSE; return bRetval; } // PreCreateWindow() sets the initial compose window size based on // values that were saved in the registry during OnClose(). The width // is currently hard-coded to open up to 73 (COMPOSE_WINDOW_WIDTH) // characters wide. BOOL CComposeFrame::PreCreateWindow ( CREATESTRUCT &cs ) { cs.style |= WS_CLIPCHILDREN; BOOL rv = CGenericFrame::PreCreateWindow ( cs ); int16 iLeft,iRight,iTop,iBottom; PREF_GetRectPref("mail.compose_window_rect", &iLeft, &iTop, &iRight, &iBottom); // Restore X,Y and height, but recalculate width if ( iLeft != -1) { cs.x = iLeft; cs.y = iTop; cs.cy = iBottom-iTop; //if (m_bUseHtml) //{ cs.cx = iRight - iLeft; return rv; //} } CWnd *pCwnd = AfxGetMainWnd(); ASSERT(pCwnd); // get the current character width from the font size, first // we have to create the font. CClientDC dc(pCwnd); HFONT font; CFont *pOldFont; LOGFONT lf; XP_MEMSET(&lf,0,sizeof(LOGFONT)); TEXTMETRIC tm; lf.lfPitchAndFamily = FF_MODERN | FIXED_PITCH; strcpy(lf.lfFaceName, IntlGetUIFixFaceName(0)); lf.lfHeight = -MulDiv(9,dc.GetDeviceCaps(LOGPIXELSY), 72); lf.lfQuality = PROOF_QUALITY; font = theApp.CreateAppFont( lf ); pOldFont = dc.SelectObject(CFont::FromHandle(font)); dc.GetTextMetrics(&tm); dc.SelectObject(pOldFont); cs.cx = (GetSystemMetrics(SM_CXFRAME)*2) + (tm.tmAveCharWidth*(COMPOSE_WINDOW_WIDTH+(m_bUseHtml?2:0))); cs.cx += GetSystemMetrics(SM_CXVSCROLL); cs.cx += EDIT_MARGIN_OFFSET; // use 2/3 of the screen as the standard default height cs.cy = (GetSystemMetrics(SM_CYSCREEN)/3)*2; theApp.ReleaseAppFont(font); return rv; } void CComposeFrame::DisplayHeaders ( MSG_HEADER_SET headers ) { ASSERT(m_pComposeBar); m_pComposeBar->DisplayHeaders ( headers ); m_pComposeBar->UpdateFixedSize ( ); RecalcLayout ( ); #ifdef XP_WIN16 m_pComposeBar->Invalidate(); #endif m_SavedHeaders = headers; } LONG CComposeFrame::OnToolController(UINT,LONG) { if (m_bUseHtml) return (LONG)m_pToolBarController; return 0; } void CComposeFrame::SetModified(BOOL bValue) { if (m_bUseHtml) EDT_SetDirtyFlag(GetMainContext()->GetContext(), bValue); else m_EditorParent.SetModified(bValue); } void CComposeFrame::OnSetFocus(CWnd * pOldWnd) { CGenericFrame::OnSetFocus(pOldWnd); if (GetFocusField()) GetFocusField()->SetFocus(); } BOOL CComposeFrame::CanCloseFrame(void) { BOOL bModified = FALSE; if (m_bUseHtml){ bModified = EDT_DirtyFlag(GetMainContext()->GetContext()); MWContext *pMWContext; if( GetMainContext() == NULL || (pMWContext = GetMainContext()->GetContext()) == NULL ) return(FALSE); // Ignore close if in the process of doing something if( pMWContext->edit_saving_url || pMWContext->waitingMode || EDT_IsBlocked(pMWContext) ) return(FALSE); } else bModified = m_EditorParent.m_bModified; if (bModified) { CString csText, csTitle; csText.LoadString(IDS_MESSAGENOTSENT); csTitle.LoadString(IDS_MESSAGECOMPOSITION); if(MessageBox( csText, csTitle, MB_YESNO | MB_ICONEXCLAMATION)==IDNO) return(FALSE); } return(TRUE); } void CComposeFrame::OnClose ( void ) { // See if the document will allow closing. if (!CanCloseFrame()) return; m_pComposeBar->Cleanup(); if (m_bUseHtml){ MWContext *pMWContext; if( GetMainContext() == NULL || (pMWContext = GetMainContext()->GetContext()) == NULL ) return; // Stop any active plugin if (!CheckAndCloseEditorPlugin(pMWContext)) return; EDT_DestroyEditBuffer(pMWContext); } // Save the window position... as long as it is not iconified or // maximized... if ( !IsIconic() && !IsZoomed() ) { CRect rect; GetWindowRect ( &rect ); PREF_SetRectPref("mail.compose_window_rect", (int16)rect.left, (int16)rect.top, (int16)rect.right, (int16)rect.bottom); } CWinCX * pWinCX = (CWinCX*)GetMainContext(); if ( pWinCX ) { // close the context and stuff CGenericView * pView = pWinCX->GetView(); if ( pView ) pView->FrameClosing ( ); } m_pChrome->SaveToolbarConfiguration(ID_COMPOSE_MESSAGE_TOOLBAR, CString("Message_Toolbar")); #ifdef XP_WIN32 // Save toolbar state CFrameWnd::SaveBarState(ToolBarProfileName); #endif CGenericFrame::OnClose(); } // Used by the template to set the context type. void CComposeFrame::SetType(MWContextType type) { MWContext * xpContext = GetMainContext()->GetContext(); ASSERT(xpContext); xpContext->type = type; } #ifdef XP_WIN32 int16 CComposeFrame::GetTitleWinCSID() // jliu - used by genframe.cpp { return INTL_DocToWinCharSetID( m_iCSID ); } #endif void CComposeFrame::SetCSID(int16 iCSID) { if(iCSID != m_iCSID) { m_iCSID = iCSID; m_pComposeBar->SetCSID(iCSID); if (m_cfTextFont) { theApp.ReleaseAppFont(m_cfTextFont); } CClientDC dc(this); LOGFONT lf; XP_MEMSET(&lf,0,sizeof(LOGFONT)); lf.lfPitchAndFamily = FF_MODERN | FIXED_PITCH; strcpy(lf.lfFaceName, IntlGetUIFixFaceName(m_iCSID)); lf.lfCharSet = IntlGetLfCharset(m_iCSID); lf.lfHeight = -MulDiv(9,dc.GetDeviceCaps(LOGPIXELSY), 72); lf.lfQuality = PROOF_QUALITY; m_cfTextFont = theApp.CreateAppFont( lf ); TEXTMETRIC tm; CFont * pOld = dc.SelectObject(CFont::FromHandle(m_cfTextFont)); dc.GetTextMetrics(&tm); dc.SelectObject(pOld); m_cxChar = tm.tmAveCharWidth; if (!m_bUseHtml) ::SendMessage(m_Editor.GetSafeHwnd(), WM_SETFONT, (WPARAM)m_cfTextFont, FALSE); else EDT_SetEncoding(GetMainContext()->GetContext(), m_iCSID); #ifdef XP_WIN32 // jliu added the following to support CJK caption print SendMessage( WM_SETTINGCHANGE ); #endif RecalcLayout(); } } // OnUpdateThis() enables/disables UI menus/tools based on the state // which the backend is reporting. If the menu is a check-item, that // will be reflected into the appropriate item as well. void CComposeFrame::OnUpdateThis ( CCmdUI* pCmdUI, MSG_CommandType tMenuType ) { if (!m_pComposePane || !pCmdUI) return; if (GetMsgPane() && MSG_DeliveryInProgress(GetMsgPane())) { pCmdUI->Enable(FALSE); return; } XP_Bool bSelectable = FALSE; // is this a selectable command? XP_Bool bPlural = FALSE; // indicates whether to append "s" (which we never do) MSG_COMMAND_CHECK_STATE sState = MSG_Unchecked; // checked or unchecked // call the backend requesting various state information MSG_CommandStatus( m_pComposePane, // message pane tMenuType, // MSG_CommandType value NULL, 0, &bSelectable, // enable/disable &sState, // checked/unchecked NULL, &bPlural); // plural command? pCmdUI->Enable(bSelectable); // enable or disable item pCmdUI->SetCheck(sState == MSG_Checked); // set the check state } void CComposeFrame::MessageCommand(MSG_CommandType msgCmd) { ASSERT(m_pComposePane); MSG_Command(m_pComposePane, msgCmd, NULL, 0); } void CComposeFrame::OnWrapLongLines ( ) { if (!m_bUseHtml) { int bHasFocus = 0; m_bWrapLongLines ^= 1; CRect rect; CString cs; if (GetFocus() == (CWnd *)&m_Editor) bHasFocus = 1; m_Editor.GetWindowRect(rect); m_EditorParent.ScreenToClient(rect); m_Editor.GetWindowText(cs); CFont *pFont = m_Editor.GetFont(); m_Editor.DestroyWindow(); m_Editor.Create ( WS_VSCROLL | ES_MULTILINE | WS_CHILD | WS_VISIBLE | ES_AUTOVSCROLL | ES_WANTRETURN | (m_bWrapLongLines ? 0 : ES_AUTOHSCROLL|WS_HSCROLL), rect, &m_EditorParent, IDC_COMPOSEEDITOR); m_Editor.SetFont(pFont); m_Editor.SetWindowText(cs); if (bHasFocus) m_Editor.SetFocus(); } } void CComposeFrame::OnUpdateWrapLongLines ( CCmdUI * pCmdUI ) { OnUpdateButtonGeneral(pCmdUI); pCmdUI->SetCheck(m_bWrapLongLines == 1); } void CComposeFrame::OnNew ( ) { MSG_Command(GetMsgPane(), MSG_MailNew, NULL, 0); } void CComposeFrame::OnSelectAll() { if (m_bUseHtml) EDT_SelectAll(GetMainContext()->GetContext()); else { m_Editor.SetSel(0,-1); m_Editor.SetFocus(); } } void CComposeFrame::OnUpdateSelectAll(CCmdUI *pCmdUI) { pCmdUI->Enable(TRUE); } void CComposeFrame::OnUpdatePasteQuote(CCmdUI *pCmdUI) { pCmdUI->Enable( IsClipboardFormatAvailable(CF_TEXT) #ifdef XP_WIN32 || IsClipboardFormatAvailable(CF_UNICODETEXT) #endif ); } void CComposeFrame::OnPasteQuote( ) { char *lpszText; HANDLE hszText; char *lpszQuotedText = NULL; OpenClipboard(); #ifdef XP_WIN32 // ftang BOOL bDoneByUnicode = FALSE; // Try to use CF_UNICODETEXT first if ((CS_USER_DEFINED_ENCODING != (m_iCSID & ~CS_AUTO)) && IsClipboardFormatAvailable(CF_UNICODETEXT) && (hszText = (HANDLE) GetClipboardData(CF_UNICODETEXT)) ) { char* lpszConvertedText = NULL; lpszText = (char *) GlobalLock(hszText); // Now, let's convert the Unicode text into the datacsid encoding int ucs2len = CASTINT(INTL_UnicodeLen((INTL_Unicode*)lpszText)); int mbbufneeded = CASTINT(INTL_UnicodeToStrLen((m_iCSID & ~CS_AUTO), (INTL_Unicode*)lpszText, ucs2len)); if(NULL != (lpszConvertedText = (char*)XP_ALLOC(mbbufneeded + 1))) { INTL_UnicodeToStr(m_iCSID, (INTL_Unicode*)lpszText, ucs2len, (unsigned char*) lpszConvertedText, mbbufneeded + 1); if (m_bUseHtml) { MSG_PastePlaintextQuotation(GetMsgPane(), lpszConvertedText); } else { lpszQuotedText = MSG_ConvertToQuotation(lpszConvertedText); FE_InsertMessageCompositionText(GetMainContext()->GetContext(), lpszQuotedText, FALSE); } XP_FREEIF(lpszConvertedText); bDoneByUnicode = TRUE; } GlobalUnlock(hszText); } if(bDoneByUnicode) { // Already done. Do nothing } else // not done by unicode try CF_TEXT now #endif if (hszText = (HANDLE) GetClipboardData(CF_TEXT)) { lpszText = (char *) GlobalLock(hszText); if (m_bUseHtml) { MSG_PastePlaintextQuotation(GetMsgPane(), lpszText); } else { lpszQuotedText = MSG_ConvertToQuotation(lpszText); FE_InsertMessageCompositionText(GetMainContext()->GetContext(), lpszQuotedText, FALSE); } GlobalUnlock(hszText); } if (lpszQuotedText) XP_FREE(lpszQuotedText); CloseClipboard(); } // UpdateToolbar() changes the command IDs as well as the assigned bitmap // to reflect the current state.. deferred send or immediate delivery. void CComposeFrame::UpdateToolBar(void) { ApiToolBar(pIToolBar,m_pChrome); if ( pIToolBar ) { pIToolBar->SetButtons(ComposeCodes, sizeof(ComposeCodes) / sizeof(UINT)); // this is currently loading one bitmap.. this needs to be fixed to add // the deferred bitmaps as well. pIToolBar->LoadBitmap(MAKEINTRESOURCE(IDB_COMPOSETOOLBAR)); } } void CComposeFrame::OnDoneGoingOffline() { BOOL bGlobalDeferred = FALSE; PREF_GetBoolPref("network.online", &bGlobalDeferred); bSendDeferred = !bGlobalDeferred; LPNSTOOLBAR pIToolBar; m_pChrome->QueryInterface( IID_INSToolBar, (LPVOID *) &pIToolBar ); if ( pIToolBar ) { CString statusStr, toolTipStr, textStr; if (bSendDeferred) { WFE_ParseButtonString(IDM_SENDLATER, statusStr, toolTipStr, textStr); CCommandToolbar *pToolBar = (CCommandToolbar *) CWnd::FromHandlePermanent( pIToolBar->GetHWnd() ); if ( pToolBar) { CToolbarButton *pBarButton = pToolBar->GetNthButton(0); if (pBarButton) { pToolBar->ReplaceButtonBitmapIndex(IDM_SENDNOW, 7); pBarButton->SetToolTipText(toolTipStr); pBarButton->SetStatusText(statusStr); pBarButton->SetText(textStr); pBarButton->SetButtonCommand(IDM_SENDLATER); } pIToolBar->Release(); } } else { WFE_ParseButtonString(IDM_SENDNOW, statusStr, toolTipStr, textStr); CCommandToolbar *pToolBar = (CCommandToolbar *) CWnd::FromHandlePermanent( pIToolBar->GetHWnd() ); if (pToolBar) { CToolbarButton *pBarButton = pToolBar->GetNthButton(0); pToolBar->ReplaceButtonBitmapIndex(IDM_SENDLATER, 0); if (pBarButton) { pBarButton->SetToolTipText(toolTipStr); pBarButton->SetStatusText(statusStr); pBarButton->SetText(textStr); pBarButton->SetButtonCommand(IDM_SENDNOW); } pIToolBar->Release(); } } } } void CComposeFrame::OnUpdateButtonGeneral(CCmdUI *pCmdUI) { OnUpdateThis(pCmdUI, MSG_SendMessage ); } void CComposeFrame::OnUpdateSend(CCmdUI *pCmdUI) { OnUpdateThis(pCmdUI, bSendDeferred ? MSG_SendMessageLater : MSG_SendMessage); pCmdUI->SetText(bSendDeferred ? szLoadString(IDS_DEFAULTSENDNOW) : szLoadString(IDS_DEFAULTSENDLATER)); } void CComposeFrame::OnUpdateSendNow(CCmdUI *pCmdUI) { OnUpdateThis(pCmdUI, MSG_SendMessage); pCmdUI->SetText(bSendDeferred ? szLoadString(IDS_SENDNOW) : szLoadString(IDS_DEFAULTSENDNOW)); } void CComposeFrame::OnUpdateSendLater(CCmdUI *pCmdUI) { OnUpdateThis(pCmdUI, MSG_SendMessageLater); pCmdUI->SetText(bSendDeferred ? szLoadString(IDS_DEFAULTSENDLATER) : szLoadString(IDS_SENDLATER)); } // This function is send to the backend for a callback when quoting // text. Currently, it simply calls the pre-existing insert code. int WFE_InsertMessage(void *closure, const char * data) { if (data) { FE_InsertMessageCompositionText((MWContext*)closure,data,FALSE); } else { MSG_Pane *pPane = MSG_FindPane((MWContext *)closure, MSG_COMPOSITIONPANE); if (pPane) { CComposeFrame * pCompose = (CComposeFrame *) MSG_GetFEData(pPane); if (pCompose->GetQuoteSel() != -1) { if (! pCompose->UseHtml()) { int32 eReplyOnTop = 0; int start = ((int) pCompose->GetQuoteSel()), end = start; int tmpStart = 0; if (PREF_NOERROR == PREF_GetIntPref("mailnews.reply_on_top", &eReplyOnTop)) { switch(eReplyOnTop) { case 1: default: pCompose->GetEditor()->SetSel(start, end); break; case 2: pCompose->GetEditor()->GetSel(tmpStart, end); pCompose->GetEditor()->SetSel(start, end); break; case 3: pCompose->GetEditor()->GetSel(tmpStart, end); pCompose->GetEditor()->SetSel(end, start); break; } } } pCompose->SetQuoteSel(-1); } } } return 0; } void CComposeFrame::OnQuoteOriginal( void ) { SetQuoteSelection(); MSG_QuoteMessage(GetMsgPane(),WFE_InsertMessage,(void*)GetMainContext()->GetContext()); } void CComposeFrame::OnAddressTab(void) { m_pComposeBar->OnAddressTab(); } void CComposeFrame::OnAttachTab(void) { m_pComposeBar->OnAttachTab(); } void CComposeFrame::OnOptionsTab(void) { m_pComposeBar->OnOptionsTab(); } void CComposeFrame::OnCollapse(void) { m_pComposeBar->OnCollapse(); } // OnSaveAs().. This should probably have better backend support. This function // gets the current message body text and saves it to a user specified location. void CComposeFrame::OnSaveAs(void) { // Call the file-picker to get a filename/location. char * pPath = wfe_GetSaveFileName(m_hWnd, XP_GetString(MK_MSG_SAVE_AS), szLoadString(IDS_DEFAULTSAVEAS), 0); // if a valid path was specified, continue with save if (pPath && strlen(pPath)) { uint32 ulBodySize; char *pBody; // open the file for writing FILE *pFile = fopen(pPath, "w"); // if the file was opened successfully, continue with save if (pFile) { FE_GetMessageBody(m_pComposePane, &pBody, &ulBodySize, NULL); if (!fwrite(pBody, sizeof(char), CASTSIZE_T(ulBodySize), pFile)) { // couldn't write file char szOpenError[512]; sprintf(szOpenError, szLoadString(IDS_CANTWRITETOFILE), pPath); FE_Alert(GetMainContext()->GetContext(), szOpenError); } if (UseHtml()) XP_HUGE_FREE(pBody); else XP_FREE(pBody); fclose(pFile); } else { // can't open file char szOpenError[512]; sprintf(szOpenError, szLoadString(IDS_CANTWRITETOFILE), pPath); FE_Alert(GetMainContext()->GetContext(), szOpenError); } XP_FREE(pPath); } } void CComposeFrame::OnCheckSpelling() { CWnd * pWnd = GetEditorWnd(); if (pWnd) pWnd->SendMessage(WM_COMMAND,ID_CHECK_SPELLING); } // OnSaveAsDraft() sends based on the current delivery state. void CComposeFrame::OnSaveDraft ( void ) { ASSERT(m_pComposeBar); m_pComposeBar->UpdateHeaderInfo ( ); // first we must get the text from the front end and then // tell the backend what text to send. uint32 ulBodySize; char *pBody; FE_GetMessageBody(GetMsgPane(), &pBody, &ulBodySize, NULL); // if we could get text, tell the backend if (ulBodySize) MSG_SetCompBody(GetMsgPane(),pBody); // start the meteors tumbling GetChrome()->StartAnimation(); MWContext *context; context = GetMainContext()->GetContext(); // Pass current csid to backend, so it can do right conversion for // 8bit header. INTL_SetCSIDocCSID(LO_GetDocumentCharacterSetInfo(context), m_iCSID); MSG_Command(GetMsgPane(), MSG_SaveDraft, 0, 0); GetChrome()->StopAnimation(); if (!m_bUseHtml) m_EditorParent.m_bModified = FALSE; } void CComposeFrame::OnUpdateSaveDraft(CCmdUI *pCmdUI) { // Change the string based on the deferred sending status OnUpdateThis(pCmdUI, MSG_SaveDraft ); } void CComposeFrame::OnSaveTemplate ( void ) { ASSERT(m_pComposeBar); m_pComposeBar->UpdateHeaderInfo ( ); // first we must get the text from the front end and then // tell the backend what text to send. uint32 ulBodySize; char *pBody; FE_GetMessageBody(GetMsgPane(), &pBody, &ulBodySize, NULL); // if we could get text, tell the backend if (ulBodySize) MSG_SetCompBody(GetMsgPane(),pBody); // start the meteors tumbling GetChrome()->StartAnimation(); MWContext *context; context = GetMainContext()->GetContext(); // Pass current csid to backend, so it can do right conversion for // 8bit header. INTL_SetCSIDocCSID(LO_GetDocumentCharacterSetInfo(context), m_iCSID); MSG_Command(GetMsgPane(), MSG_SaveTemplate, 0, 0); GetChrome()->StopAnimation(); if (!m_bUseHtml) m_EditorParent.m_bModified = FALSE; } void CComposeFrame::OnUpdateSaveTemplate(CCmdUI *pCmdUI) { // Change the string based on the deferred sending status OnUpdateThis(pCmdUI, MSG_SaveTemplate ); } LRESULT CComposeFrame::OnButtonMenuOpen(WPARAM wParam, LPARAM lParam) { HMENU hMenu = (HMENU) lParam; UINT nCommand = (UINT) LOWORD(wParam); if (nCommand == IDM_ATTACHFILE){ ::AppendMenu(hMenu,MF_STRING|MF_ENABLED, IDM_ATTACHFILE, szLoadString(IDS_TOOLATTACHFILE)); ::AppendMenu(hMenu,MF_STRING|MF_ENABLED, IDM_ATTACHWEBPAGE, szLoadString(IDS_ATTACHWEBPAGE)); ::AppendMenu(hMenu,MF_SEPARATOR, 0, NULL); ::AppendMenu(hMenu,MF_STRING|MF_ENABLED, IDM_ATTACHMYCARD, szLoadString(IDS_ATTACHMYCARD)); return 1; } else if (GetMainWinContext()){ // Route other messages to Edit View, which handles messages common to all Composer frames return ::SendMessage( GetMainWinContext()->GetPane(), NSBUTTONMENUOPEN, wParam, lParam); } return 0; } // DoSend() sends based on the current delivery state. void CComposeFrame::DoSend ( BOOL bNow ) { ASSERT(m_pComposeBar); LPADDRESSCONTROL pIAddress = GetAddressWidgetInterface(); if (pIAddress) { CListBox * pListBox = pIAddress->GetListBox(); if (::IsWindow(pListBox->m_hWnd)) pListBox->SendMessage(WM_NOTIFYSELECTIONCHANGE); } MSG_ClearComposeHeaders(GetMsgPane()); m_pComposeBar->UpdateHeaderInfo ( ); // first we must get the text from the front end and then // tell the backend what text to send. uint32 ulBodySize; char *pBody = NULL; FE_GetMessageBody(GetMsgPane(), &pBody, &ulBodySize, NULL); #ifndef _WIN32 if (ulBodySize > 32767) { MessageBox(szLoadString(IDS_MSGTOBIG), szLoadString(IDS_TITLE_ERROR), MB_ICONSTOP|MB_OK); return; } #endif // if we could get text, tell the backend if (pBody) MSG_SetCompBody(GetMsgPane(),pBody); int errcode = 0; MWContext * context = GetMainContext()->GetContext(); while ((errcode = MSG_SanityCheck(GetMsgPane(),errcode))!=0) { GetChrome()->StopAnimation(); if (errcode == MK_MSG_MISSING_SUBJECT) { char * ptr = PromptMessageSubject(); if (ptr != NULL) { MSG_SetCompHeader(GetMsgPane(),MSG_SUBJECT_HEADER_MASK,ptr); XP_FREE(ptr); } else return; } else if (!FE_Confirm(context,XP_GetString(errcode))) return; } // Pass current csid to backend, so it can do right conversion for // 8bit header. INTL_SetCSIWinCSID(LO_GetDocumentCharacterSetInfo(context), m_iCSID); MSG_Command(GetMsgPane(), bNow ? MSG_SendMessage : MSG_SendMessageLater, 0, 0); if (GetMsgPane() && MSG_DeliveryInProgress(GetMsgPane())) { // start the meteors tumbling GetChrome()->StartAnimation(); LPNSSTATUSBAR pIStatusBar = NULL; GetChrome()->QueryInterface( IID_INSStatusBar, (LPVOID *) &pIStatusBar ); if ( pIStatusBar ) { pIStatusBar->ModalStatus( TRUE, 0, szLoadString(IDS_SENDINGMESSAGE)); pIStatusBar->Release(); } } // rhp - this condition is for MAPI UI-less send operations... else { if (!IsWindowVisible()) // First, check if the window is not already visible ShowWindow(SW_SHOW); // and if not, get it on the screen for the user to deal with... } // rhp } void CComposeFrame::OnAttachMyCard() { ASSERT(m_pComposeBar); m_pComposeBar->SetAttachMyCard(!m_pComposeBar->GetAttachMyCard()); } void CComposeFrame::OnUpdateAttachMyCard(CCmdUI * pCmdUI) { pCmdUI->Enable(TRUE); pCmdUI->SetCheck(m_pComposeBar->GetAttachMyCard()); } void CComposeFrame::OnAttachFile() { ASSERT(m_pComposeBar); m_pComposeBar->OnAttachTab(); m_pComposeBar->UpdateWindow(); m_pComposeBar->AttachFile(); } void CComposeFrame::OnAttachUrl() { ASSERT(m_pComposeBar); m_pComposeBar->OnAttachTab(); m_pComposeBar->UpdateWindow(); m_pComposeBar->AttachUrl(); } void CComposeFrame::ConvertToPlainText() { if (MessageBox(szLoadString(IDS_CONVERTWARN), szLoadString(IDS_CONVERTTITLE), MB_ICONEXCLAMATION | MB_YESNO) == IDYES) { MWContext *pMWContext; if( GetMainContext() == NULL || (pMWContext = GetMainContext()->GetContext()) == NULL ) return; // Stop any active plugin if (!CheckAndCloseEditorPlugin(pMWContext)) return; EDT_DestroyEditBuffer(pMWContext); pMWContext->is_editor = FALSE; m_pChrome->SetMenu(IDR_COMPOSEPLAIN); DestroyHtmlToolbars(); RecalcLayout(); CreatePlainTextEditor(); ::SendMessage(m_Editor.GetSafeHwnd(), WM_SETFONT, (WPARAM)m_cfTextFont, FALSE); m_bUseHtml = FALSE; } } void CComposeFrame::ConvertToHtml() { m_pChrome->SetMenu(IDR_COMPOSEFRAME); CreateHtmlToolbars(); ShowHtmlToolbars(); RecalcLayout(); SetEditorParent(NULL); m_Editor.DestroyWindow(); m_EditorParent.DestroyWindow(); m_bUseHtml = TRUE; if (GetMainContext() != NULL) { CWinCX * pWinCX = GetMainContext()->IsFrameContext() ? VOID2CX(GetMainContext(),CWinCX) : NULL; if (pWinCX != NULL) { MWContext * pContext = pWinCX->GetContext(); if (!pContext->is_editor) { pContext->is_editor = TRUE; URL_Struct * pUrl = NET_CreateURLStruct(EDT_NEW_DOC_URL,NET_DONT_RELOAD); if (pUrl != NULL) { pWinCX->GetUrl(pUrl, FO_CACHE_AND_PRESENT); pWinCX->GetContext()->bIsComposeWindow = TRUE; } } } } } void CComposeFrame::OnConvert() { if (m_bUseHtml) ConvertToPlainText(); else ConvertToHtml(); } void CComposeFrame::OnUpdateConvert(CCmdUI * pCmdUI) { pCmdUI->Enable(FALSE); // wait for it } void CComposeFrame::OnSend() { DoSend(!bSendDeferred); } void CComposeFrame::OnSendNow() { DoSend(TRUE ); } void CComposeFrame::OnSendLater() { DoSend(FALSE); } void CComposeFrame::MakeComposeBarVisible() { if (!GetComposeBar()->IsVisible()) GetComposeBar()->OnToggleShow(); else if (GetComposeBar()->IsCollapsed()) { GetComposeBar()->OnCollapse(); CCustToolbar * pToolbar = GetChrome()->GetCustomizableToolbar(); if( pToolbar ) pToolbar->RemoveExternalTab(1); RecalcLayout(); } } void CComposeFrame::OnViewAddresses() { MakeComposeBarVisible(); GetComposeBar()->SendMessage(WM_COMMAND,IDC_ADDRESSTAB); } void CComposeFrame::OnViewAttachments() { MakeComposeBarVisible(); m_pComposeBar->m_pSubjectEdit->SetFocus(); UpdateWindow(); GetComposeBar()->SendMessage(WM_COMMAND,IDC_ATTACHTAB); } void CComposeFrame::OnViewOptions() { MakeComposeBarVisible(); m_pComposeBar->m_pSubjectEdit->SetFocus(); UpdateWindow(); GetComposeBar()->PostMessage(WM_COMMAND,IDC_OPTIONSTAB); } void CComposeFrame::OnUpdateViewAddresses(CCmdUI * pCmdUI) { pCmdUI->SetRadio(GetComposeBar()->GetTab() == IDX_COMPOSEADDRESS); pCmdUI->Enable(TRUE); } void CComposeFrame::OnUpdateViewAttachments(CCmdUI * pCmdUI) { pCmdUI->SetRadio(GetComposeBar()->GetTab() == IDX_COMPOSEATTACH); pCmdUI->Enable(TRUE); } void CComposeFrame::OnUpdateViewOptions(CCmdUI * pCmdUI) { pCmdUI->SetRadio(GetComposeBar()->GetTab() == IDX_COMPOSEOPTIONS); pCmdUI->Enable(TRUE); } // OnSetInitialFocus - Invoked after the frame window, toolbar and view are created. // It sets the initial keyboard focus. LONG CComposeFrame::OnSetInitialFocus(WPARAM wParam, LPARAM lParam) { return 0; } void CComposeFrame::SetInitialText( const char *pText ) { if (m_pInitialText) XP_FREE (m_pInitialText); m_pInitialText = NULL; if (pText) m_pInitialText = XP_STRDUP(pText); } BOOL CComposeFrame::BccOnly(void) { LPADDRESSCONTROL pIAddress = GetAddressWidgetInterface(); CListBox * pListBox = pIAddress->GetListBox(); int count = pListBox->GetCount(); int total = 0; for (int i=0; iGetEntry(i,&szType, &szName)) if(strcmp(szType,szLoadString(IDS_ADDRESSBCC))) total++; } return !total; } void CComposeFrame::InsertInitialText(void) { const char *pBody = MSG_GetCompBody(GetMsgPane()); LPADDRESSCONTROL pIAddress = GetAddressWidgetInterface(); if (pIAddress) { CListBox * pListBox = pIAddress->GetListBox(); if (::IsWindow(pListBox->m_hWnd)) pListBox->ResetContent(); } if (m_pInitialText && strlen(m_pInitialText)) { EDT_ReadFromBuffer(GetMainContext()->GetContext(), m_pInitialText); XP_FREEIF(m_pInitialText); } else if (pBody && strlen(pBody)) { FE_InsertMessageCompositionText( GetMainContext()->GetContext(), pBody, TRUE); FE_InsertMessageCompositionText( GetMainContext()->GetContext(), "\n", TRUE); MSG_SetCompBody(GetMsgPane(), ""); } CompleteComposeInitialization(); if (m_bUseHtml) EDT_SetDirtyFlag(GetMainContext()->GetContext(), FALSE); if (MSG_ShouldAutoQuote(GetMsgPane())) { SetQuoteSelection(); MSG_QuoteMessage(GetMsgPane(),WFE_InsertMessage,(void*)GetMainContext()->GetContext()); } } void CComposeFrame::CompleteComposeInitialization(void) { MSG_HeaderEntry * entry; int nCount; nCount = MSG_RetrieveStandardHeaders(GetMsgPane(),&entry); LPADDRESSCONTROL pIAddress = m_pComposeBar->GetAddressWidgetInterface(); CListBox * pListBox = pIAddress->GetListBox(); if (nCount > 0) { int i; pListBox->LockWindowUpdate(); for (i=0; iAppendEntry(FALSE, MSG_HeaderMaskToString(entry[i].header_type), entry[i].header_value, 0, 0); XP_FREE(entry[i].header_value); } pIAddress->AppendEntry(); ::LockWindowUpdate(NULL); } if (entry) XP_FREE(entry); const char * subject = MSG_GetCompHeader(GetMsgPane(),MSG_SUBJECT_HEADER_MASK); if (!nCount) pIAddress->AppendEntry(NULL); // in case of the existance hidden headers, get new count nCount = pListBox->GetCount(); if (subject && strlen(subject)) { m_pComposeBar->m_pSubjectEdit->SetWindowText(subject); GetChrome()->SetDocumentTitle(subject); } if (nCount<=1 || BccOnly()) { if (BccOnly()) { pIAddress->DeleteEntry(pListBox->GetCount()-1); pIAddress->AppendEntry(TRUE, szLoadString(IDS_ADDRESSTO),"",0,0); } pListBox->UpdateWindow(); pListBox->SetFocus(); SetFocusField(pListBox); } else if (subject && strlen(subject)) { if (!UseHtml()) { GetEditor()->SetFocus(); SetFocusField(GetEditor()); } } else { m_pComposeBar->m_pSubjectEdit->SetSel(-1,0); m_pComposeBar->m_pSubjectEdit->SetFocus(); SetFocusField(m_pComposeBar->m_pSubjectEdit); } // Set the message priority based on the fileds const char * priorityString = MSG_GetCompHeader(GetMsgPane(), MSG_PRIORITY_HEADER_MASK); if (priorityString) { // Backend deals only untranslated priority; we have to do some mapping here if (strstr(priorityString, "Highest")) m_pComposeBar->m_iPriorityIdx = MSG_HighestPriority - 2; else if (strstr(priorityString, "High")) m_pComposeBar->m_iPriorityIdx = MSG_HighPriority - 2; else if (strstr(priorityString, "Lowest")) m_pComposeBar->m_iPriorityIdx = MSG_LowestPriority - 2; else if (strstr(priorityString, "Low")) m_pComposeBar->m_iPriorityIdx = MSG_LowPriority - 2; else m_pComposeBar->m_iPriorityIdx = MSG_NormalPriority - 2; } switch (MSG_GetHTMLAction(GetMsgPane())) { default: case MSG_HTMLAskUser: m_pComposeBar->m_pszMessageFormat = strdup(szLoadString(IDS_FORMAT_ASKME)); break; case MSG_HTMLUseMultipartAlternative: m_pComposeBar->m_pszMessageFormat = strdup(szLoadString(IDS_FORMAT_BOTH)); break; case MSG_HTMLConvertToPlaintext: m_pComposeBar->m_pszMessageFormat = strdup(szLoadString(IDS_FORMAT_PLAIN)); break; case MSG_HTMLSendAsHTML: m_pComposeBar->m_pszMessageFormat = strdup(szLoadString(IDS_FORMAT_HTML)); break; } m_pComposeBar->SetAttachMyCard(MSG_GetCompBoolHeader(GetMsgPane(),MSG_ATTACH_VCARD_BOOL_HEADER_MASK)); m_pComposeBar->SetReturnReceipt(MSG_GetCompBoolHeader(GetMsgPane(),MSG_RETURN_RECEIPT_BOOL_HEADER_MASK)); m_pComposeBar->SetUseUUENCODE(MSG_GetCompBoolHeader(GetMsgPane(),MSG_UUENCODE_BINARY_BOOL_HEADER_MASK)); UpdateSecurityOptions(); m_bInitialized = TRUE; } void CComposeFrame::UpdateSecurityOptions(void) { HG27625 } void CComposeFrame::GoldDoneLoading () { MSG_InitializeCompositionPane(GetMsgPane(),m_pOldContext,m_pFields); PostMessage(WM_COMP_SET_INITIAL_FOCUS); UpdateAttachmentInfo(); } //////////////////////////////////////////////////////////////////////////////////// // Begin the pseudo-backend code here. const char * MSG_HeaderMaskToString(MSG_HEADER_SET header) { const char * retval = NULL; switch (header) { case MSG_TO_HEADER_MASK: retval = szLoadString(IDS_ADDRESSTO); break; case MSG_CC_HEADER_MASK: retval = szLoadString(IDS_ADDRESSCC); break; case MSG_BCC_HEADER_MASK: retval = szLoadString(IDS_ADDRESSBCC); break; case MSG_REPLY_TO_HEADER_MASK: retval = szLoadString(IDS_ADDRESSREPLYTO); break; case MSG_NEWSGROUPS_HEADER_MASK: retval = szLoadString(IDS_ADDRESSNEWSGROUP); break; case MSG_FOLLOWUP_TO_HEADER_MASK: retval = szLoadString(IDS_ADDRESSFOLLOWUPTO); break; default: XP_ASSERT(0); } return retval; } MSG_HEADER_SET MSG_StringToHeaderMask(char * string) { MSG_HEADER_SET retval = 0; if (!stricmp(szLoadString(IDS_ADDRESSTO),string)) retval = MSG_TO_HEADER_MASK; else if (!stricmp(szLoadString(IDS_ADDRESSCC),string)) retval = MSG_CC_HEADER_MASK; else if (!stricmp(szLoadString(IDS_ADDRESSBCC),string)) retval = MSG_BCC_HEADER_MASK; else if (!stricmp(szLoadString(IDS_ADDRESSREPLYTO),string)) retval = MSG_REPLY_TO_HEADER_MASK; else if (!stricmp(szLoadString(IDS_ADDRESSNEWSGROUP),string)) retval = MSG_NEWSGROUPS_HEADER_MASK; else if (!stricmp(szLoadString(IDS_ADDRESSFOLLOWUPTO),string)) retval = MSG_FOLLOWUP_TO_HEADER_MASK; else XP_ASSERT(0); return retval; } BOOL CComposeFrame::OnCmdMsg(UINT nID, int nCode, void* pExtra, AFX_CMDHANDLERINFO* pHandlerInfo) { BOOL bRetVal = CGenericFrame::OnCmdMsg(nID,nCode,pExtra,pHandlerInfo); if (nCode == CN_UPDATE_COMMAND_UI) if (!bRetVal && !m_bUseHtml) bRetVal = m_Editor.OnCmdMsg(nID,nCode,pExtra,pHandlerInfo); return bRetVal; } void CComposeFrame::OnToggleMessageToolbar() { GetChrome()->ShowToolbar(ID_COMPOSE_MESSAGE_TOOLBAR, !GetChrome()->GetToolbarVisible(ID_COMPOSE_MESSAGE_TOOLBAR)); } void CComposeFrame::OnUpdateToggleMessageToolbar(CCmdUI* pCmdUI) { pCmdUI->SetCheck(GetChrome()->GetToolbarVisible(ID_COMPOSE_MESSAGE_TOOLBAR)); pCmdUI->Enable(TRUE); } void CComposeFrame::OnToggleAddressArea() { m_pComposeBar->OnToggleShow(); } void CComposeFrame::OnUpdateToggleAddressArea(CCmdUI * pCmdUI) { pCmdUI->SetCheck(m_pComposeBar->IsVisible()); pCmdUI->Enable(TRUE); } #define UNSECURE_INDEX 9 #define SECURE_INDEX 11 #define UNSEC_SIGNED_INDEX 8 #define SEC_SIGNED_INDEX 10 void CComposeFrame::OnUpdateSecurity(CCmdUI * pCmdUI) { HG72521 OnUpdateButtonGeneral(pCmdUI); } void CComposeFrame::OnUpdateSecureStatus(CCmdUI *pCmdUI) { HG87282 } void CComposeFrame::OnUpdateShowNamePicker(CCmdUI *pCmdUI) { #ifdef MOZ_NEWADDR pCmdUI->Enable(FALSE); LPADDRESSCONTROL pIAddress = GetAddressWidgetInterface(); if (pIAddress) { CEdit *pEdit = pIAddress->GetAddressNameField(); if(GetFocus() == pEdit) { pCmdUI->Enable(TRUE); } } #else pCmdUI->Enable(FALSE); #endif } void CComposeFrame::OnShowNamePicker() { #ifdef MOZ_NEWADDR //need to get text of current selection LPADDRESSCONTROL pIAddress = GetAddressWidgetInterface(); if (pIAddress) { pIAddress->ShowNameCompletionPicker(this); } #endif } void CComposeFrame::OnUpdateToggleNameCompletion(CCmdUI *pCmdUI) { pCmdUI->Enable(FALSE); #ifdef MOZ_NEWADDR LPADDRESSCONTROL pIAddress = GetAddressWidgetInterface(); if(pIAddress) { pCmdUI->Enable(TRUE); BOOL bHasNameCompletion = pIAddress->GetEntryHasNameCompletion(); if(bHasNameCompletion) { pCmdUI->SetText(::szLoadString(IDS_NAMECOMPLETIONOFF)); } else { pCmdUI->SetText(::szLoadString(IDS_NAMECOMPLETIONON)); } } #endif } void CComposeFrame::OnToggleNameCompletion() { #ifdef MOZ_NEWADDR LPADDRESSCONTROL pIAddress = GetAddressWidgetInterface(); if(pIAddress) { BOOL bHasNameCompletion = pIAddress->GetEntryHasNameCompletion(); pIAddress->SetEntryHasNameCompletion(!bHasNameCompletion); } #endif } char * CComposeFrame::PromptMessageSubject() { CWnd * pWnd = GetFocus(); CString csText; CString csDefault; csText.LoadString(IDS_COMPOSE_NOSUBJECT); csDefault.LoadString(IDS_COMPOSE_DEFAULTNOSUBJECT); MWContext * pContext = GetMainContext()->GetContext(); char * ptr = ABSTRACTCX(pContext)->Prompt(pContext, csText, csDefault); pWnd->SetFocus(); return ptr; } void CComposeFrame::OnSecurity() { m_pComposeBar->UpdateHeaderInfo ( ); CGenericFrame::OnSecurity(); } void CComposeFrame::RefreshNewEncoding(int16 doc_csid, BOOL bSave ) { int16 win_csid = INTL_DocToWinCharSetID(doc_csid); INTL_CharSetInfo c = LO_GetDocumentCharacterSetInfo( GetMainContext()->GetContext() ); INTL_SetCSIDocCSID( c, doc_csid ); INTL_SetCSIWinCSID( c, win_csid ); SetCSID( doc_csid ); } LRESULT CComposeFrame::OnFindReplace(WPARAM wParam, LPARAM lParam) { if (!m_bUseHtml) { return m_Editor.OnFindReplace(wParam,lParam); } return CGenericFrame::OnFindReplace(wParam,lParam); } void CComposeFrame::GetMessageString(UINT MenuID, CString& Message) const { #ifdef EDITOR // static function for both CEditFrame and CComposeFrame // to get runtime-determined statusline strings for menus if( edt_GetMessageString(GetActiveView(), MenuID, Message) ) return; #endif CGenericFrame::GetMessageString(MenuID, Message); } // OnSetMessageString - Override of CGenericFrame's WM_SETMESSAGESTRING message handler. We need this // because the base class is supressing the dynamically-created menu help strings for Composer LRESULT CComposeFrame::OnSetMessageString(WPARAM wParam, LPARAM lParam) { if( edt_IsEditorDynamicMenu(wParam) ) return CFrameWnd::OnSetMessageString(wParam, lParam); else return CGenericFrame::OnSetMessageString(wParam, lParam); } // rhp - Added for sending the message when the window is not shown // This is to wait until attachments are loaded for MAPI Operations void CComposeFrame::UpdateComposeWindowForMAPI(void) { TRACE("UPDATE WINDOW FOR MAPI\n"); if (GetMAPISendMode() == MAPI_SEND) { TRACE("SEND WINDOW FOR MAPI\n"); PostMessage(WM_COMMAND, IDM_SEND); SetMAPISendMode(MAPI_IGNORE); } else if (GetMAPISendMode() == MAPI_SAVE) { TRACE("SAVE WINDOW FOR MAPI\n"); PostMessage(WM_COMMAND, IDM_SAVEASDRAFT); SetMAPISendMode(MAPI_QUITWHENDONE); } else if (GetMAPISendMode() == MAPI_QUITWHENDONE) { PostMessage(WM_CLOSE); SetMAPISendMode(MAPI_IGNORE); } } // rhp - This is to respond to a custom message to identify compose windows LONG CComposeFrame::OnProcessMAPIMessage(WPARAM wParam, LPARAM lParam) { return(MAPI_CUSTOM_RET_CODE); }