/* -*- 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. */ // edframe.cpp : implementation file // #include "stdafx.h" #ifdef EDITOR #include "edt.h" #include "netsvw.h" #include "edview.h" #include "edprops.h" #include "mainfrm.h" #include "edframe.h" #include "edres2.h" #include "compfrm.h" #include "resource.h" #include "prefapi.h" #include "prefapi.h" #include "eddialog.h" #include "template.h" #include "edtplug.h" // For XP Strings extern "C" { #include "xpgetstr.h" #define WANT_ENUM_STRING_IDS #include "allxpstr.h" #undef WANT_ENUM_STRING_IDS } #ifdef _DEBUG #undef THIS_FILE static char BASED_CODE THIS_FILE[] = __FILE__; #endif // Globals in TEMPLATE.CPP - // saves last frame location for new window postioning // and flag to overlay current window (default = cascaded windows) extern BOOL wfe_bUseLastFrameLocation; extern CGenericFrame *wfe_pLastFrame; char *EDT_NEW_DOC_URL = NULL; char *EDT_NEW_DOC_NAME = NULL; extern TagType FEED_nParagraphTags[]; void FED_SetupStrings(void) { // Get strings from XP_MSG.I for new document stuff // These are the same strings used in \LIB\LIBNET\MKGETURL.C // to do most of the new doc stuff at cross-platform level if (EDT_NEW_DOC_URL == NULL) { StrAllocCopy(EDT_NEW_DOC_URL, XP_GetString(XP_EDIT_NEW_DOC_URL) ); } if (EDT_NEW_DOC_NAME == NULL) { StrAllocCopy(EDT_NEW_DOC_NAME, XP_GetString(XP_EDIT_NEW_DOC_NAME) ); } } static UINT nTraceCount = 0; // toolbar buttons - IDs are command buttons except for ID_SEPARATOR and // ID_COMBOBOX, the placeholder for comboboxes.built with CComboToolBar _WIN32 // Main edit toolbar: static UINT BASED_CODE nIDEditBarArray[] = { // same order as in the bitmap for toolbar ID_EDT_NEW_DOC_BLANK, ID_FILE_OPENURL, ID_EDT_FILE_SAVE, ID_FILE_PUBLISH, ID_OPEN_NAV_WINDOW, ID_FILE_PRINT, ID_CHECK_SPELLING, ID_MAKE_LINK, ID_INSERT_TARGET, ID_INSERT_IMAGE, ID_INSERT_HRULE, ID_INSERT_TABLE_OR_PROPS, }; #define EDITBAR_ID_COUNT ((sizeof(nIDEditBarArray))/sizeof(UINT)) // Character Format Toolbar: // NOTE: We now use a NSToolbar2 for the button array static UINT BASED_CODE nIDCharacterBarArray[] = { // same order as in the bitmap for toolbar ID_COMBOBOX, // Paragraph style ID_COMBOBOX, // Font Face ID_COMBOBOX, // Font Size ID_COMBOBOX // Font Color combobox in Win4+ versions - define COLOR_COMBO_INDEX as this location }; #define CHARBAR_ID_COUNT ((sizeof(nIDCharacterBarArray))/sizeof(UINT)) static UINT BASED_CODE nIDCharButtonBarArray[] = { // same order as in the bitmap for toolbar ID_FORMAT_CHAR_BOLD, ID_FORMAT_CHAR_ITALIC, ID_FORMAT_CHAR_UNDERLINE, ID_FORMAT_CHAR_NONE, ID_FORMAT_UNUM_LIST, ID_FORMAT_NUM_LIST, ID_FORMAT_OUTDENT, ID_FORMAT_INDENT, ID_ALIGN_POPUP, ID_INSERT_POPUP }; #define CHARBUTTONBAR_ID_COUNT ((sizeof(nIDCharButtonBarArray))/sizeof(UINT)) static UINT BASED_CODE nIDCharFloatButtonBarArray[] = { // same order as in the bitmap for toolbar ID_SEPARATOR, ID_FORMAT_CHAR_BOLD, ID_FORMAT_CHAR_ITALIC, ID_FORMAT_CHAR_UNDERLINE, ID_CHECK_SPELLING, ID_SEPARATOR, ID_FORMAT_UNUM_LIST, ID_FORMAT_NUM_LIST, ID_FORMAT_OUTDENT, ID_FORMAT_INDENT, ID_SEPARATOR, ID_ALIGN_POPUP, ID_INSERT_POPUP }; #define CHARBUTTONBARFLOAT_ID_COUNT ((sizeof(nIDCharFloatButtonBarArray))/sizeof(UINT)) #define COLOR_COMBO_INDEX 3 // Location of color combo we hide in Win16/NT3.51 // Global strings for dropdown property combos // Filled in once in InitComposer() char * ed_pOther = NULL; char * ed_pMixedFonts = NULL; char * ed_pDontChange = NULL; CBitmap ed_DragCaretBitmap; ////////////////////////////////////////////////////////////////////////// // The height of an item in the dropdown listbox part of a comobbox extern int wfe_iListItemHeight; extern void SetCurrentDefaultFontColor(); // Callback notification when preferences are changed int PR_CALLBACK ed_prefWatcher(const char *pPrefName, void *pData) { switch ((int)pData) { case 1: { int32 iDelay; PREF_GetIntPref("editor.auto_save_delay", &iDelay); CGenericFrame * f; // We must set the autosave values for ALL edit contexts for(f = theApp.m_pFrameList; f; f = f->m_pNext) { MWContext *pMWContext = f->GetMainContext()->GetContext(); if ( pMWContext && EDT_IS_EDITOR(pMWContext) && !pMWContext->bIsComposeWindow ){ EDT_SetAutoSavePeriod(pMWContext, iDelay); } } break; } case 2: { PREF_GetIntPref("editor.fontsize_mode", &wfe_iFontSizeMode); CGenericFrame * f; // We update font size combobox for ALL edit contexts for(f = theApp.m_pFrameList; f; f = f->m_pNext) { MWContext *pMWContext = f->GetMainContext()->GetContext(); if ( pMWContext && EDT_IS_EDITOR(pMWContext) ){ CNetscapeEditView * pView = (CNetscapeEditView*)f->GetActiveView(); if( pView ){ pView->UpdateFontSizeCombo(); } } } break; } case 3: { // Find all composer windows and change Author name only if it // isn't already set in the page CGenericFrame * f; for(f = theApp.m_pFrameList; f; f = f->m_pNext) { MWContext *pMWContext = f->GetMainContext()->GetContext(); if ( pMWContext && EDT_IS_EDITOR(pMWContext) && !pMWContext->bIsComposeWindow ){ int count = EDT_MetaDataCount(pMWContext); BOOL bFound = FALSE; EDT_MetaData* pData = NULL; for ( int i = 0; i < count; i++ ) { pData = EDT_GetMetaData(pMWContext, i); if( pData ){ if( 0 != _stricmp(pData->pName, "Author") ){ bFound = TRUE; EDT_FreeMetaData(pData); break; } EDT_FreeMetaData(pData); } } // Use preference only if Author tag not already found if(!bFound){ pData->pName = XP_STRDUP("Author"); PREF_CopyCharPref("editor.author", &pData->pContent); EDT_SetMetaData(pMWContext, pData); EDT_FreeMetaData(pData); } } } break; } } return PREF_NOERROR; } static void wfe_EditURLCallback(const char* urlToOpen){ FE_LoadUrl((char*) urlToOpen, LOAD_URL_COMPOSER); } // Initialize global data (Note: we don't have a MWContext/Frame/View yet) void WFE_InitComposer() { // Check to make sure range of IDs in EDRES1.H (which start at 36000) // don't collide with those in RESOURCE.H ASSERT(ID_EDIT_LAST_ID < 42000); int i; UINT n = ID_FORMAT_FONTFACE_BASE; char pPref[32]; char * pLocation = NULL; // Count the number of most-recently-used template locations theApp.m_iTemplateLocationCount = 0; for ( i = 0; i < MAX_TEMPLATE_LOCATIONS; i++ ){ sprintf( pPref, "editor.template_history_%d", i); PREF_CopyCharPref(pPref, &pLocation); if( pLocation && *pLocation ){ // We have a non-empty string - count it theApp.m_iTemplateLocationCount++; XP_FREEIF(pLocation); } else { break; } } XP_FREEIF(pLocation); // Initialize the static string "Other" we use in comboboxes if( !ed_pOther ){ ed_pOther = XP_STRDUP(szLoadString(IDS_OTHER)); } if( !ed_pMixedFonts ){ ed_pMixedFonts = XP_STRDUP(szLoadString(IDS_MIXED_FONTS)); } if( !ed_pDontChange ){ ed_pDontChange = XP_STRDUP(szLoadString(IDS_DONT_CHANGE)); } // This will be updated in CGenericFrame::OnDisplayPreferences() PREF_GetIntPref("editor.fontsize_mode", &wfe_iFontSizeMode); // Register callbacks for items we need to know immediately when changed PREF_RegisterCallback("editor.auto_save_delay", ed_prefWatcher, (void*)1); PREF_RegisterCallback("editor.fontsize_mode", ed_prefWatcher, (void*)2); PREF_RegisterCallback("editor.author", ed_prefWatcher, (void*)3); wfe_pFont = new CFont(); wfe_pBoldFont = new CFont(); if( wfe_pFont && wfe_pBoldFont ){ if( GetSystemMetrics(SM_DBCSENABLED) ){ HFONT hFont = NULL; #ifdef _WIN32 hFont = (HFONT)GetStockObject(DEFAULT_GUI_FONT); #endif if (!hFont){ hFont = (HFONT)GetStockObject(SYSTEM_FONT); } wfe_pFont->Attach(hFont); wfe_pBoldFont->Attach(hFont); } else { // Get a 1-pixel font LOGFONT logFont; memset(&logFont, 0, sizeof(logFont)); //logFont.lfHeight = -MulDiv(9, ::GetDeviceCaps(hDC, LOGPIXELSY), 72); logFont.lfHeight = -10; // This maps to "8 pts" logFont.lfWeight = FW_NORMAL; logFont.lfCharSet = IntlGetLfCharset(CIntlWin::GetSystemLocaleCsid()); logFont.lfPitchAndFamily = VARIABLE_PITCH | FF_SWISS; if (CIntlWin::GetSystemLocaleCsid() == CS_LATIN1) _tcscpy(logFont.lfFaceName, "MS Sans Serif"); else _tcscpy(logFont.lfFaceName, IntlGetUIPropFaceName(CIntlWin::GetSystemLocaleCsid())); if( !wfe_pFont->CreateFontIndirect(&logFont) ){ delete wfe_pFont; wfe_pFont = NULL; } logFont.lfWeight = FW_BOLD; if( !wfe_pBoldFont->CreateFontIndirect(&logFont) ){ delete wfe_pBoldFont; wfe_pBoldFont = NULL; } } } // Set default Author name to the same as mail username if not already set char * pAuthor = NULL; if( PREF_CopyCharPref("editor.author", &pAuthor) != PREF_NOERROR || !pAuthor || !*pAuthor ){ // No Author field - copy the mail username char * pUserName = NULL; if( PREF_CopyCharPref("mail.identity.username", &pUserName) == PREF_NOERROR && pUserName && *pUserName ){ PREF_SetCharPref("editor.author", pUserName); } XP_FREEIF(pUserName); } XP_FREEIF(pAuthor); // Register edtplug java-to-C++ Open-the-editor callback. EDTPLUG_RegisterEditURLCallback(&wfe_EditURLCallback); if( !ed_DragCaretBitmap.LoadBitmap(IDB_ED_DRAG) ) XP_ASSERT(FALSE); // Get global last-color-picked from prefs char * pCustomColor = NULL; LO_Color LoColor; PREF_CopyCharPref("editor.last_color_picked", &pCustomColor); if( pCustomColor ) { EDT_ParseColorString(&LoColor, pCustomColor); wfe_crLastColorPicked = RGB(LoColor.red, LoColor.green, LoColor.blue); XP_FREEIF(pCustomColor); } else { wfe_crLastColorPicked = 0; } PREF_CopyCharPref("editor.last_background_color_picked", &pCustomColor); if( pCustomColor ) { EDT_ParseColorString(&LoColor, pCustomColor); wfe_crLastBkgrndColorPicked = RGB(LoColor.red, LoColor.green, LoColor.blue); XP_FREEIF(pCustomColor); } else { wfe_crLastBkgrndColorPicked = RGB(255, 255, 255); } // Fill color table with 0s memset((void*)wfe_CustomPalette, 0, 16*sizeof(COLORREF)); // We should make this an expandable list so we can // append document colors to the list for( i = 1; i <= MAX_CUSTOM_COLORS; i++ ) { wsprintf(pPref, "editor.custom_color_%d", (i < MAX_CUSTOM_COLORS) ? i : 0); PREF_CopyCharPref(pPref, &pCustomColor); if (pCustomColor) EDT_ParseColorString(&LoColor, pCustomColor); XP_FREEIF(pCustomColor); // Save color to test if it changed wfe_CustomPalette[i] = RGB(LoColor.red, LoColor.green, LoColor.blue); } } void WFE_ExitComposer() { if( wfe_pFont ){ delete wfe_pFont; } if( wfe_pBoldFont ){ delete wfe_pBoldFont; } XP_FREEIF(ed_pOther); XP_FREEIF(ed_pMixedFonts); XP_FREEIF(ed_pDontChange); ed_DragCaretBitmap.DeleteObject(); } ///////////////////////////////////////////////////////////////////////////// // Toolbar controller class used by Edit and Mail compose frames // CEditToolBarController::CEditToolBarController(CWnd * pParent) : m_pWnd(pParent), m_iFontColorOtherIndex(0), m_pCharacterToolbar(0), m_pCommandView(NULL) { } CEditToolBarController::~CEditToolBarController() { if( m_pCharacterToolbar ) delete m_pCharacterToolbar; } void CEditToolBarController::setEmbeddedView(CView *pView) { m_pCommandView = pView; } BOOL CEditToolBarController::CreateEditBars(MWContext *pMWContext, CView *pCommandView, unsigned ett) { // Initialize things needed by both CNetscapeEditFrame and CComposeFrame CGenericFrame *pParent = (CGenericFrame*)GetParent(); if (ett & DISPLAY_EDIT_TOOLBAR) { CButtonToolbarWindow *pWindow; BOOL bOpen, bShowing; int32 nPos; //I'm hardcoding because I don't want this translated pParent->GetChrome()->LoadToolbarConfiguration(IDS_EDIT_TOOLBAR_CAPTION, CString("Composition_Toolbar"),nPos, bOpen, bShowing); // Add a customizable toolbar LPNSTOOLBAR pIToolBar; pParent->GetChrome()->QueryInterface( IID_INSToolBar, (LPVOID *) &pIToolBar ); if ( pIToolBar ) { pIToolBar->Create( pParent, WS_CHILD|WS_CLIPCHILDREN|WS_VISIBLE|CBRS_TOP ); pIToolBar->SetButtons( nIDEditBarArray, EDITBAR_ID_COUNT ); // Set menu/toolbar popup styles for specific buttons: pIToolBar->SetButtonStyle(ID_EDT_NEW_DOC_BLANK, TB_HAS_TIMED_MENU); pIToolBar->SetButtonStyle(ID_FILE_OPENURL, TB_HAS_TIMED_MENU); pIToolBar->SetButtonStyle(ID_FILE_PRINT, TB_HAS_TIMED_MENU); // First pair are actually ignored! Second is bitmap size pIToolBar->SetSizes( CSize( 29, 27 ), CSize( 23, 21 ) ); pIToolBar->LoadBitmap( MAKEINTRESOURCE( IDB_FILE_PICT_TOOLBAR ) ); pIToolBar->SetToolbarStyle( theApp.m_pToolbarStyle ); pWindow = new CButtonToolbarWindow(CWnd::FromHandlePermanent(pIToolBar->GetHWnd()), theApp.m_pToolbarStyle, 43, 27, eLARGE_HTAB); pParent->GetChrome()->GetCustomizableToolbar()->AddNewWindow(IDS_EDIT_TOOLBAR_CAPTION, pWindow,nPos, 50, 37, 0, CString(szLoadString(IDS_EDIT_TOOLBAR_CAPTION)),theApp.m_pToolbarStyle, bOpen, FALSE); pParent->GetChrome()->ShowToolbar(IDS_EDIT_TOOLBAR_CAPTION, bShowing); pIToolBar->Release(); } } // Character Format toolbar if( ett & DISPLAY_CHARACTER_TOOLBAR ){ // We don't use the "Insert Object" last item if we are displaying the edit toolbar, // which has these items if (!pCommandView) { if (!m_wndCharacterBar.Create(ett & DISPLAY_EDIT_TOOLBAR, GetParent(), IDW_PARA_TOOLBAR, IDS_CHAR_TOOLBAR_CAPTION, nIDCharacterBarArray, CHARBAR_ID_COUNT, IDB_NEW_FORMAT_TOOLBAR, CSize(8, ED_TB_BUTTON_HEIGHT), CSize(1,ED_TB_BITMAP_HEIGHT) ) ) return FALSE; m_pCharacterToolbar = CreateCharacterToolbar((ett & DISPLAY_EDIT_TOOLBAR) ? CHARBUTTONBAR_ID_COUNT-1 : CHARBUTTONBAR_ID_COUNT); m_wndCharacterBar.SetCNSToolbar(m_pCharacterToolbar); } else { if (!m_wndCharacterBar.CreateFloater(GetParent(), IDW_PARA_TOOLBAR, IDS_CHAR_TOOLBAR_CAPTION, nIDCharacterBarArray, CHARBAR_ID_COUNT, nIDCharFloatButtonBarArray,CHARBUTTONBARFLOAT_ID_COUNT , IDB_EDIT_FLOAT_TOOLBAR, CSize(27, 22), CSize(20, 16), pCommandView) ) return FALSE; } // Paragraph styles Combo CRect rect; rect.SetRectEmpty(); //Don't need size to create it if (!m_ParagraphCombo.Create(CBS_DROPDOWNLIST|WS_VISIBLE|WS_TABSTOP|WS_VSCROLL, rect, &m_wndCharacterBar, ID_COMBO_PARA)) { TRACE0("Failed to create paragraph format combo-box\n"); return FALSE; } // Font Face Combo if (!m_FontFaceCombo.Create(rect, &m_wndCharacterBar, ID_COMBO_FONTFACE)) { return FALSE; } // Font Size Combo if (!m_FontSizeCombo.Create(rect, &m_wndCharacterBar, ID_COMBO_FONTSIZE)) { TRACE0("Failed to create Font Size combo-box\n"); return FALSE; } if ( wfe_pFont ){ m_ParagraphCombo.SetFont(wfe_pFont); //Other combos are CNSComboBox and have font set in Create or Subclass calls } if( !m_FontColorCombo.CreateAndFill(rect, &m_wndCharacterBar, ID_COMBO_FONTCOLOR, DEFAULT_COLORREF) ){ return FALSE; } // Fill the other combo boxes CString csTemp; // Paragraph - Get maximum width while loading strings int iMaxParaWidth = 0; CDC *pDC = m_ParagraphCombo.GetDC(); CSize cSize; int wincsid = INTL_CharSetNameToID(INTL_ResourceCharSet()); for ( int i = 0; FEED_nParagraphTags[i] != P_UNKNOWN; i++ ){ if (csTemp.LoadString(CASTUINT(ID_LIST_TEXT_PARAGRAPH_BASE+FEED_nParagraphTags[i]))){ m_ParagraphCombo.AddString((LPCTSTR)csTemp); if ( pDC ){ cSize = CIntlWin::GetTextExtent(wincsid, pDC->GetSafeHdc(), csTemp, csTemp.GetLength()); pDC->LPtoDP(&cSize); if ( cSize.cx > iMaxParaWidth ){ iMaxParaWidth = cSize.cx; } } } } // String used to get width of FontSize combobox csTemp = "55"; cSize = CIntlWin::GetTextExtent(wincsid, pDC->GetSafeHdc(), csTemp, csTemp.GetLength()); pDC->LPtoDP(&cSize); // Save the full height of this font wfe_iFontHeight = cSize.cy; // Calculate list item height from font size and store in global variable // Trim 1 pixel off height to fit more items in the list wfe_iListItemHeight = wfe_iFontHeight - 1; int iFontSizeWidth = cSize.cx + sysInfo.m_iScrollWidth + 6; // This is longest string when combobox is dropped down: csTemp = "8 pts"; cSize = CIntlWin::GetTextExtent(wincsid, pDC->GetSafeHdc(), csTemp, csTemp.GetLength()); pDC->LPtoDP(&cSize); int iMaxSizeWidth = cSize.cx; // + sysInfo.m_iScrollWidth; m_ParagraphCombo.ReleaseDC(pDC); // Initialize app-global list of TrueType fonts // and fill the toolbar combo with all font strings // WARNING: This is a user-draw listbox and pointers to font-name strings // must be STATIC pDC = m_FontFaceCombo.GetDC(); wfe_InitTrueTypeArray(pDC); int iMaxFontWidth = 0; wfe_iFontFaceOtherIndex = wfe_FillFontComboBox(&m_FontFaceCombo, &iMaxFontWidth); // ??? "NEEDED ONLY IF NOT A WINDOW" m_FontFaceCombo.ReleaseDC(pDC); // Font Size // This gets filled on every call to open the combobox wfe_FillFontSizeCombo(pMWContext, &m_FontSizeCombo); m_FontFaceCombo.SetCurSel(0); // show the first entry // Now that we have a font, we can set the full size of comboboxes // The order of these calls determine order of appearence in toolbar // Use 0 for height (param 5) to let class figure out optimal height // Note that we use Scroll Width to get size of combobox since users // can change that in Win95 and NT4.0 and that size determines width // of combobox dropdown button if (m_wndCharacterBar) m_wndCharacterBar.SetComboBox( ID_COMBO_PARA, &m_ParagraphCombo, sysInfo.m_iScrollWidth+61, iMaxParaWidth + 4, 0 ); m_ParagraphCombo.SetCurSel(0); int iWidth = sysInfo.m_iScrollWidth; // Allow wider closed-combo-size when screen width is > 640 // (We can't test pMWContext->bIsComposeWindow, it is not set at this stage) if( sysInfo.m_iScreenWidth <= 640 || !(ett & DISPLAY_EDIT_TOOLBAR) ){ // We are in Message Composer - use fixed width iWidth += 80; } else { // Add width of 1st string so it displays fully in closed combobox pDC = m_FontFaceCombo.GetDC(); if ( pDC ){ csTemp = XP_GetString(XP_NSFONT_DEFAULT); cSize = CIntlWin::GetTextExtent(wincsid, pDC->GetSafeHdc(), csTemp, csTemp.GetLength()); pDC->LPtoDP(&cSize); // but never smaller than 90 so other long names show better // in Win16/NT3.51, which can't expand width of dropdown iWidth += max(90, cSize.cy); m_FontFaceCombo.ReleaseDC(pDC); } else { iWidth += 90; } } m_wndCharacterBar.SetComboBox( ID_COMBO_FONTFACE, &m_FontFaceCombo, iWidth, iMaxFontWidth, 0 ); m_wndCharacterBar.SetComboBox( ID_COMBO_FONTSIZE, &m_FontSizeCombo, iFontSizeWidth, iMaxSizeWidth, 0 ); m_FontSizeCombo.SetCurSel(2); // Initialize with the "default" size - 3rd in list // Set the color combobox data m_wndCharacterBar.SetComboBox( ID_COMBO_FONTCOLOR, &m_FontColorCombo, sysInfo.m_iScrollWidth+16, 0, 0); m_FontColorCombo.SetCurSel(0); // Initialize with default color // Make the Alignment and "Insert Object" buttons do their actions on button down // Used to popup a CDropDownToolbar m_wndCharacterBar.SetDoOnButtonDown(ID_ALIGN_POPUP, TRUE); m_wndCharacterBar.SetDoOnButtonDown(ID_INSERT_POPUP, TRUE); #ifdef XP_WIN16 // This will add tooltips for Win16 m_wndCharacterBar.RecalcLayout(); #endif } int nLastID = ID_EDIT_LAST_ID; ASSERT(nLastID < 42000); return TRUE; } CCommandToolbar* CEditToolBarController::CreateCharacterToolbar(int nCount) { CCommandToolbar *pCharToolbar =new CCommandToolbar(15, theApp.m_pToolbarStyle, 43, 25 /*27*/, 25 /*27*/); if (!pCharToolbar->Create(GetParent())) { return FALSE; } pCharToolbar->SetBitmap(IDB_CHAR_FORMAT_TOOLBAR); CString statusStr, toolTipStr, textStr; int nBitmapIndex = 0; for(int i = 0; i < nCount; i++) { CCommandToolbarButton *pCommandButton = new CCommandToolbarButton; WFE_ParseButtonString(nIDCharButtonBarArray[i], statusStr, toolTipStr, textStr); pCommandButton->Create(pCharToolbar, TB_PICTURES, CSize(44, 37)/*novice size*/, CSize(25, 25) /*advanced size*/, "",(const char*) toolTipStr, (const char*) statusStr, IDB_CHAR_FORMAT_TOOLBAR, i, CSize(20,18)/*Bitmap size*/, nIDCharButtonBarArray[i], -1, (DWORD)0/*button style*/); pCommandButton->SetPicturesOnly(TRUE); pCommandButton->SetBitmap(pCharToolbar->GetBitmap(), TRUE); pCharToolbar->AddButton(pCommandButton, i); } return pCharToolbar; } int CEditToolBarController::GetSelectedFontFaceIndex() { int iSel = m_FontFaceCombo.GetCurSel(); if( wfe_iFontFaceOtherIndex && iSel == wfe_iFontFaceOtherIndex ){ return INDEX_OTHER; } return iSel; } int CEditToolBarController::GetSelectedFontColorIndex() { int iSel = m_FontColorCombo.GetCurSel(); if( m_iFontColorOtherIndex && iSel == m_iFontColorOtherIndex ){ return INDEX_OTHER; } return iSel; } void CEditToolBarController::ShowToolBar( BOOL bShow, CComboToolBar * pToolBar) { ASSERT(m_pWnd); ASSERT(pToolBar); CFrameWnd * pFrame = pToolBar->GetParentFrame(); if ( pFrame != m_pWnd ) { // Parent frame isn't toolbar Controller - must be a floating "MiniFrame" pFrame->ShowWindow(bShow ? SW_SHOW : SW_HIDE); } // Do this even if we have mini-frame because we use // the toolbar's show state to tell us current visibility pToolBar->ShowWindow(bShow ? SW_SHOW : SW_HIDE); pFrame->RecalcLayout(); } ///////////////////////////////////////////////////////////////////////////// // CEditFrame #undef new IMPLEMENT_DYNCREATE(CEditFrame, CMainFrame) #define new DEBUG_NEW BEGIN_MESSAGE_MAP(CEditFrame, CMainFrame) //{{AFX_MSG_MAP(CEditFrame) ON_MESSAGE(WM_TOOLCONTROLLER,OnToolController) ON_WM_CREATE() ON_WM_INITMENUPOPUP() ON_WM_CLOSE() ON_COMMAND(ID_FILE_CLOSE, OnFileClose) ON_WM_QUERYENDSESSION() ON_COMMAND(ID_EDIT_WINDOW_BOOKMARKS, OnShowBookmarkWindow) // Override CMainFrame //}}AFX_MSG_MAP ON_MESSAGE(WM_SETMESSAGESTRING, OnSetMessageString) ON_MESSAGE(NSBUTTONMENUOPEN, OnButtonMenuOpen) END_MESSAGE_MAP() ///////////////////////////////////////////////////////////////////////////// CEditFrame::CEditFrame() { m_pToolBarController = new CEditToolBarController( this ); m_hPal = NULL; m_pTemplateContext = NULL; } CEditFrame::~CEditFrame() { delete m_pToolBarController; } ///////////////////////////////////////////////////////////////////////////// // CEditFrame diagnostics #ifdef _DEBUG void CEditFrame::AssertValid() const { CMainFrame::AssertValid(); } void CEditFrame::Dump(CDumpContext& dc) const { CMainFrame::Dump(dc); } #endif //_DEBUG ///////////////////////////////////////////////////////////////////////////// // CEditFrame member functions BOOL CEditFrame::OnCreateClient(LPCREATESTRUCT lpcs, CCreateContext *pContext) { // Call the base - it creates our CWinCX context return CMainFrame::OnCreateClient(lpcs, pContext); // We don't need to set the context flag since it is now // set in CMainFrame::OnCreateClient() [framinit.cpp] // because of a SetFocus() call done there, which needs to have // is_editor already set to avoid JavaScript message problems #if 0 if(bRetval == TRUE) { CWinCX * pContext = GetMainWinContext(); ASSERT( pContext ); // Tell net and stream processors that we are an editor MWContext * pMWContext = pContext->GetContext(); ASSERT( pMWContext ); pMWContext->is_editor = TRUE; } return bRetval; #endif } void CEditFrame::DockControlBarLeftOf(CToolBar* Bar,CToolBar* LeftOf) { #ifdef XP_WIN32 CRect rect; DWORD dw; UINT n; // get MFC to adjust the dimensions of all docked ToolBars // so that GetWindowRect will be accurate RecalcLayout(); LeftOf->GetWindowRect(&rect); rect.OffsetRect(10,10); dw=LeftOf->GetBarStyle(); n = 0; n = (dw&CBRS_ALIGN_TOP) ? AFX_IDW_DOCKBAR_TOP : n; n = (dw&CBRS_ALIGN_BOTTOM && n==0) ? AFX_IDW_DOCKBAR_BOTTOM : n; n = (dw&CBRS_ALIGN_LEFT && n==0) ? AFX_IDW_DOCKBAR_LEFT : n; n = (dw&CBRS_ALIGN_RIGHT && n==0) ? AFX_IDW_DOCKBAR_RIGHT : n; // When we take the default parameters on rect, DockControlBar will dock // each Toolbar on a seperate line. By calculating a rectangle, we in effect // are simulating a Toolbar being dragged to that location and docked. DockControlBar(Bar,n,&rect); #endif } ///////////////////////////////////////////////////////////////////////////// // CEditFrame message handlers int CEditFrame::OnCreate(LPCREATESTRUCT lpCreateStruct) { // Most of the work is done in base class if (CMainFrame::OnCreate(lpCreateStruct) == -1) return -1; ASSERT(m_pToolBarController); GetChrome()->CreateCustomizableToolbar("Composer"/*ID_COMPOSER*/, 2, FALSE); if ( !m_pToolBarController->CreateEditBars(GetMainContext()->GetContext(), FALSE) ) return -1; // fail to create // Need to do this to get accurate toolbar size info RecalcLayout(); CControlBarToolbarWindow *pWindow; BOOL bOpen, bShowing; int32 nPos; //putterman: I'm hardcoding because I don't want this translated GetChrome()->LoadToolbarConfiguration(IDS_CHAR_TOOLBAR_CAPTION, CString("Formatting_Toolbar"), nPos, bOpen, bShowing); pWindow = new CControlBarToolbarWindow(m_pToolBarController->GetCharacterBar(), theApp.m_pToolbarStyle, 43, 27, eLARGE_HTAB); GetChrome()->GetCustomizableToolbar()->AddNewWindow(IDS_CHAR_TOOLBAR_CAPTION, pWindow,nPos, 50, 37, 0, CString(szLoadString(IDS_CHAR_TOOLBAR_CAPTION)),theApp.m_pToolbarStyle, bOpen, FALSE); GetChrome()->ShowToolbar(IDS_CHAR_TOOLBAR_CAPTION, bShowing); GetChrome()->SetWindowTitle(szLoadString(IDS_NETSCAPE_COMPOSER)); SetCursor(theApp.LoadStandardCursor(IDC_WAIT)); // 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_INSERT_TABLE, MF_BYCOMMAND | MF_POPUP | MF_STRING, (UINT)::LoadMenu(AfxGetResourceHandle(), MAKEINTRESOURCE(IDM_COMPOSER_TABLE_INSERTMENU)), szLoadString(IDS_SUBMENU_INSERT_TABLE) ); ::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_DELETE_TABLE, MF_BYCOMMAND | MF_POPUP | MF_STRING, (UINT)::LoadMenu(AfxGetResourceHandle(), MAKEINTRESOURCE(IDM_COMPOSER_TABLE_DELETEMENU)), szLoadString(IDS_SUBMENU_DELETE_TABLE) ); ::ModifyMenu( hTableMenu, ID_PASTE_TABLE, MF_BYCOMMAND | MF_POPUP | MF_STRING, (UINT)::LoadMenu(AfxGetResourceHandle(), MAKEINTRESOURCE(IDM_COMPOSER_TABLE_PASTEMENU)), szLoadString(IDS_SUBMENU_PASTE_TABLE) ); } } return 0; } // Global function so we can use it in CComposeFrame as well // Returns TRUE only if message was supplied BOOL edt_GetMessageString(CView * pView, UINT MenuID, CString& Message) { if (MenuID >= ID_EDITOR_PLUGINS_BASE && MenuID < (ID_EDITOR_PLUGINS_BASE + MAX_EDITOR_PLUGINS)) { uint32 CategoryId, PluginId; CNetscapeEditView *pEditView = (CNetscapeEditView *)pView; ASSERT(pView != NULL && pView->IsKindOf(RUNTIME_CLASS(CNetscapeEditView))); if (pEditView->GetPluginInfo(MenuID, &CategoryId, &PluginId)) Message = EDT_GetPluginMenuHelp(CategoryId, PluginId); return TRUE; } else if (MenuID >= ID_EDIT_HISTORY_BASE && MenuID < (ID_EDIT_HISTORY_BASE + MAX_EDIT_HISTORY_LOCATIONS) ) { char * pStatusTitle = NULL; // Get the string for Page Title associated with menu item (which shows the URL) // (NULL means we don't need to get the URL string) if( EDT_GetEditHistory( ((CGenericView*)pView)->GetContext()->GetContext(), MenuID-ID_EDIT_HISTORY_BASE, NULL, &pStatusTitle) ) { Message = pStatusTitle; return TRUE; } } return FALSE; } // Helper to test for dynamic menus shared by Page and Message Composer frame windows BOOL edt_IsEditorDynamicMenu(WPARAM wParam) { return( (wParam >= ID_EDITOR_PLUGINS_BASE && wParam < (ID_EDITOR_PLUGINS_BASE + MAX_EDITOR_PLUGINS)) || (wParam >= ID_EDIT_HISTORY_BASE && wParam < (ID_EDIT_HISTORY_BASE + MAX_EDIT_HISTORY_LOCATIONS)) ); } // GetMessageString - Override of CFrameWnd virtual. It sets the menu help strings for the // dynamically loaded editor plugins. void CEditFrame::GetMessageString(UINT MenuID, CString& Message) const { if( edt_GetMessageString(GetActiveView(), MenuID, Message) ) return; CMainFrame::GetMessageString(MenuID, Message); } // OnSetMessageString - Override of CMainFrame's WM_SETMESSAGESTRING message handler. We need this // because the base class (actually CGenericFrame) is supressing the dynamically created menu help // strings for Composer LRESULT CEditFrame::OnSetMessageString(WPARAM wParam, LPARAM lParam) { if( edt_IsEditorDynamicMenu(wParam) ) return CFrameWnd::OnSetMessageString(wParam, lParam); else return CMainFrame::OnSetMessageString(wParam, lParam); } LONG CEditFrame::OnToolController(UINT,LONG) { return (LONG)m_pToolBarController; } void CEditFrame::OnShowBookmarkWindow() { XP_Bool prefBool; PREF_GetBoolPref("editor.hints.bookmark",&prefBool); if ( prefBool ){ // Show a "Hint" dialog about drag and drop until // user checks "Don't show this" in dialog CEditHintDlg dlg(this, IDS_DRAG_BOOKMARK_HINT); dlg.DoModal(); if ( dlg.m_bDontShowAgain ) { PREF_SetBoolPref("editor.hints.bookmark",FALSE); } } CGenericFrame::OnShowBookmarkWindow(); } // Handy dandy routine to get a preference and prompt // user to set it in Editor Preferences if it does // not already exist char* CEditFrame::GetLocationFromPreferences(const char *pPrefName, UINT nID_Msg, UINT nID_Caption, UINT nID_FileCaption) { if( pPrefName == NULL ){ return NULL; } char *pLocation = NULL; PREF_CopyCharPref(pPrefName, &pLocation); if( pLocation == NULL || pLocation[0] == '\0' ){ // Popup dialog to allow user to set location now CGetLocationDlg dlg(this, nID_Msg, nID_Caption, nID_FileCaption); if(dlg.DoModal() == IDOK){ if( !dlg.m_csLocation.IsEmpty() ){ pLocation = XP_STRDUP((char*)LPCSTR(dlg.m_csLocation)); PREF_SetCharPref(pPrefName, pLocation); } } } if( pLocation && pLocation[0] == '\0' ){ XP_FREE(pLocation); return NULL; } return pLocation; } void CEditFrame::OnClose() { MWContext *pMWContext; if( GetMainContext() == NULL || (pMWContext = GetMainContext()->GetContext()) == NULL ) return; // Stop any active plugin if (!CheckAndCloseEditorPlugin(pMWContext)) return; // Ignore close if we are doing something if(pMWContext->edit_saving_url || pMWContext->waitingMode || (EDT_IsBlocked(pMWContext) &&LO_GetEDBuffer(pMWContext))//if we dont have an edit buffer, we should not be blocked from closing! ) { return; } // The CGenericFrame flag should be respected only for // one attempt to close, so clear it here BOOL bPromptForSaving = !m_bSkipSaveEditChanges; m_bSkipSaveEditChanges = FALSE; // Check for changes to doc and prompt to save: // except if we are a new document AND nothing was ever edited, // don't prompt to save it // Don't close if user cancels when prompted to save if( LO_GetEDBuffer( ABSTRACTCX(pMWContext)->GetDocumentContext() ) ){ if( bPromptForSaving && !FE_CheckAndSaveDocument(pMWContext) ){ return; } History_entry * hist_entry = SHIST_GetCurrent(&(pMWContext ->hist)); EDT_PreClose(pMWContext,hist_entry ? hist_entry->address: NULL, RealCloseS,(void *)this); return; } RealClose(); } void CEditFrame::RealCloseS(void* hook) { CEditFrame *pEdFrame = (CEditFrame *)hook; if (!pEdFrame) { ASSERT(0); return; } pEdFrame->RealClose(); } void CEditFrame::RealClose() { MWContext *pMWContext; if( GetMainContext() == NULL || (pMWContext = GetMainContext()->GetContext()) == NULL ) return; if( LO_GetEDBuffer( ABSTRACTCX(pMWContext)->GetDocumentContext() ) ){ EDT_DestroyEditBuffer(pMWContext); } //I'm hardcoding because I don't want this translated GetChrome()->SaveToolbarConfiguration(IDS_EDIT_TOOLBAR_CAPTION, CString("Composition_Toolbar")); GetChrome()->SaveToolbarConfiguration(IDS_CHAR_TOOLBAR_CAPTION, CString("Formatting_Toolbar")); CMainFrame::OnClose(); } void CEditFrame::OnFileClose() { MWContext *pMWContext; if( GetMainContext() == NULL || (pMWContext = GetMainContext()->GetContext()) == NULL ) return; // Stop any active plugin if (!CheckAndCloseEditorPlugin(pMWContext)) return; if ( FE_CheckAndSaveDocument(pMWContext) ) { m_bSkipSaveEditChanges = TRUE; CMainFrame::OnFrameExit(); } } BOOL CEditFrame::OnQueryEndSession() { if (!CMainFrame::OnQueryEndSession()) return FALSE; MWContext *pMWContext; if( GetMainContext() == NULL || (pMWContext = GetMainContext()->GetContext()) == NULL ) return TRUE; // Returns FALSE if user cancels from dialog - stops shutdown return FE_CheckAndSaveDocument(pMWContext); } // These are Frame load/creation routines for editor, formerly in GENFRAME.CPP // Get pointer to URL passed from 2nd instance char* GetGlobalUrlPointer(HANDLE handle) { char * pUrl = NULL; #ifdef WIN32 // Read URL from memory-mapped file and load it handle = OpenFileMapping(FILE_MAP_READ | FILE_MAP_WRITE, TRUE, szNGMemoryMapFilename); if (NULL != handle) { char * szFile = (char*)MapViewOfFile(handle, FILE_MAP_READ | FILE_MAP_WRITE, 0, 0, 0); if (szFile ) { pUrl = XP_STRDUP(szFile); } else { TRACE1( "OpenFileMapping error: %u\n", GetLastError() ); } CloseHandle(handle); } #else pUrl = (char*)GlobalLock(handle); #endif return pUrl; } // Save the last-use template URL // to our list of recently-accessed templates // Call from FE_EditorGetUrlExitRoutine after template successfully loaded void CEditFrame::SaveTemplateLocation(char *pLastLoc) { int iToBeMoved = -1; char szLocName[32]; char szLocation[256]; int iLen = 256; char * pLastLocation = NULL; int i; if( pLastLoc ){ pLastLocation = XP_STRDUP(pLastLoc); } else { PREF_CopyCharPref("editor.template_last_loc",&pLastLocation); } if( !pLastLocation ){ return; } // First scan the list to find pref that matches new item for( i = 0; i < theApp.m_iTemplateLocationCount; i++ ){ wsprintf(szLocName,"editor.template_history_%d",i); PREF_GetCharPref(szLocName,szLocation,&iLen); if( 0 == strcmp(szLocation,pLastLocation) ){ // URL is already in the list if (i ==0) // It is already at the start of list, // so there's nothing more to do! return; iToBeMoved = i; break; } } // If our list was already at the limit, we will delete the oldest item if( theApp.m_iTemplateLocationCount >= MAX_TEMPLATE_LOCATIONS ){ theApp.m_iTemplateLocationCount = MAX_TEMPLATE_LOCATIONS; } else if( iToBeMoved == -1 ){ // We will be adding 1 new item theApp.m_iTemplateLocationCount++; } // Start at 1 less than new count or item to-be-deleted // that is, start at the number to be replaced after // adjusting for the zero index int iStart; if (iToBeMoved > 0){ iStart = iToBeMoved; } else { iStart = theApp.m_iTemplateLocationCount-1; } for( i = iStart; i > 0; i-- ){ // iterate backwards and move everything up 1 position wsprintf(szLocName, "editor.template_history_%d", i-1); PREF_GetCharPref(szLocName, szLocation, &iLen); wsprintf(szLocName, "editor.template_history_%d", i); PREF_SetCharPref(szLocName,szLocation); } // Add the new item to list wsprintf(szLocName, "editor.template_history_%d", 0); PREF_SetCharPref(szLocName, pLastLocation); if (pLastLocation) XP_FREE(pLastLocation); } // Route toolbar menu messages to edit view LRESULT CEditFrame::OnButtonMenuOpen(WPARAM wParam, LPARAM lParam) { if( GetMainWinContext()){ return ::SendMessage( GetMainWinContext()->GetPane(), NSBUTTONMENUOPEN, wParam, lParam); } return 0; } ////////////////////////////////////////////////////////////////////// // Frame load/creation methods // Prototypes of CGenericFrame functions are in GENFRAME.H // int FindCurrentUrlInHistory(MWContext * pMWcontext, char * szAddress) { if(!pMWcontext) return 0; XP_List * list_ptr; History_entry *pEntry; int nIndex = 0; list_ptr = pMWcontext->hist.list_ptr; while((pEntry = (History_entry *) XP_ListNextObject(list_ptr))!=0) { nIndex++; if (0 == XP_STRCMP(pEntry->address, szAddress )) { return nIndex; } } // If no match found: return 0; } // Use this to activate a Navigator or Editor frame instead // of creating a new one. MWContext * FE_ActivateFrameWithURL(char * pUrl, BOOL bFindEditor) { if ( pUrl == NULL ) { return NULL; } for(CGenericFrame * f = theApp.m_pFrameList; f; f = f->m_pNext) { MWContext *pMWContext = f->GetMainContext()->GetContext(); if ( pMWContext && (bFindEditor && EDT_IS_EDITOR(pMWContext)) || (!bFindEditor && !EDT_IS_EDITOR(pMWContext)) ) { History_entry * pEntry = SHIST_GetCurrent(&pMWContext->hist); if( pEntry && pEntry->address && EDT_IsSameURL(pEntry->address, pUrl,0,0) ) { if ( f->IsIconic() ){ f->ShowWindow(SW_RESTORE); } f->SetActiveWindow(); // Don't close the frame f->m_bCloseFrame = FALSE; return pMWContext; } } } return NULL; } // Use this to activate a Navigator frame with supplied URL, // or the frame that is previous in app's frame list, // or create a new frame if no other frames exist // Use when we can't edit a file -- not found or not editable type void FE_RevertToPreviousFrame(char * pUrl, MWContext *pMWContext) { CGenericFrame *pFrame = (CGenericFrame*)GetFrame(pMWContext); if( !pFrame ){ return; } // If we were loading into an untouched new doc, // the only case when we DON'T create a new frame first, // then stay in that doc -- don't close it if( EDT_IS_EDITOR(pMWContext) && EDT_IS_NEW_DOCUMENT(pMWContext) && !EDT_DirtyFlag(pMWContext) ){ // If ESC key is used to cancel load URL, focus needs to be set pFrame->GetActiveView()->SetFocus(); return; } // Find the browser with the same URL if( FE_ActivateFrameWithURL(pUrl, FALSE) ){ // Close caller's frame pFrame->PostMessage(WM_CLOSE); return; } if( wfe_pLastFrame ){ if ( wfe_pLastFrame->IsIconic() ){ // Bloody unlikely! wfe_pLastFrame->ShowWindow(SW_RESTORE); } wfe_pLastFrame->m_bCloseFrame = FALSE; wfe_pLastFrame->SetActiveWindow(); } else { // No existing frame, // create a new browser at same location // and load home page wfe_bUseLastFrameLocation = TRUE; MWContext *pNavContext = CFE_CreateNewDocWindow(NULL, NULL); if( pNavContext ){ ((CMainFrame*)GetFrame(pNavContext))->OnLoadHomePage(); } } // Be sure this is clear so we don't get prompted to save bogus empty document EDT_SetDirtyFlag(pMWContext, FALSE); // Close caller's frame pFrame->PostMessage(WM_CLOSE); } void FE_EditorGetUrlExitRoutine(URL_Struct *pUrlStruct, int iStatus, MWContext *pMWContext) { // Error status is negative, but don't close // if error is from publishing upload if( EDT_IS_EDITOR(pMWContext) && !pMWContext->bIsComposeWindow ) { CEditFrame * pFrame = (CEditFrame*)GetFrame(pMWContext); if(iStatus < 0 ){ //Enable window if we have an error -- it is disabled in CEditFrame::OnCreate() // WE DON'T DISABLE WINDOW ANY MORE //pFrame->GetActiveView()->EnableWindow(TRUE); // Be sure this is cleared, else next load will think // we want a template. This is used by FE_EditorDocumentLoaded // to convert a template doc into a new doc pFrame->m_pTemplateContext = NULL; // Default is to try to load the failed address char *pAddress = pUrlStruct->address; if( pUrlStruct->files_to_post == NULL ){ // we failed to to load a document into an editor context // Try to find frame with our URL, // or the previous frame in list, // or create a new browser frame // (also closes current edit frame) // // But first check if we failed to load the URL // Save preference int iTemp = theApp.m_nChangeHomePage; // These are (dynamically?) defined. See allxpstr.h // TODO: We should probably check a whole range of values if( iStatus == MK_UNABLE_TO_LOCATE_FILE || iStatus == MK_MALFORMED_URL_ERROR ){ // This will prevent trying to load // a bad startup URL on the command line theApp.m_nChangeHomePage = FALSE; // If we didn't find URL at startup, // then don't try to load it in Browser either if( iStatus == -209 ){ pAddress = NULL; } } // Close current window and go back to last active window FE_RevertToPreviousFrame(pAddress, pMWContext); theApp.m_nChangeHomePage = iTemp; } } } #ifdef XP_WIN32 // Do this even if not an edit context if ( iStatus == MK_DATA_LOADED && pMWContext->type == MWContextSaveToDisk && pMWContext->save_as_name ){ // Notify site manager that a file was saved // CString csUrlFileName; // Convert local file to URL format // WFE_ConvertFile2Url(csUrlFileName, (const char*)pMWContext->save_as_name); // For now, give local name to SiteManager: if ( bSiteMgrIsActive ) { pITalkSMClient->SavedURL(pMWContext->save_as_name); } } #endif // XP_WIN32 } // Editor calls us when we are finished loading void FE_EditorDocumentLoaded(MWContext* pMWContext) { if ( ! pMWContext ) { return; } CEditFrame* pFrame; CGenericFrame *pWnd = (CGenericFrame*)GetFrame(pMWContext); #ifdef ENDER if (!pWnd->IsKindOf(RUNTIME_CLASS(CEditFrame))) return; else #endif //ENDER pFrame = (CEditFrame*)pWnd; // Clear cached pointers to old elements CWinCX * pContext = WINCX(pMWContext); if(pContext){ pContext->ClearLastElement(); } History_entry * hist_ent = SHIST_GetCurrent(&pMWContext->hist); ASSERT(hist_ent); ASSERT(hist_ent->address); if( !hist_ent || !hist_ent->address ){ return; } // Tell edit core the file Auto Save preference int32 iSave; PREF_GetIntPref("editor.auto_save_delay",&iSave); EDT_SetAutoSavePeriod(pMWContext, iSave ); // Close the caller's window if marked to do so if( wfe_pLastFrame && wfe_pLastFrame->m_bCloseFrame){ wfe_pLastFrame->PostMessage(WM_CLOSE); } if( pMWContext == pFrame->m_pTemplateContext ) { // We loaded a URL (template or text file) // that we want to convert to a new doc // Save in history pFrame->SaveTemplateLocation(hist_ent->address); EDT_ConvertCurrentDocToNewDoc(pMWContext); pFrame->m_pTemplateContext = NULL; } // This is really needed only for Win16 -- to set initial focus, // but it shouldn't hurt to do this all the time if( pFrame->IsKindOf(RUNTIME_CLASS(CEditFrame)) ) { pFrame->PostMessage(WM_SETFOCUS, 0, 0); } #ifdef MOZ_MAIL_NEWS if (pMWContext->type == MWContextMessageComposition) { CGenericFrame * pFrame = wfe_FrameFromXPContext(pMWContext); if (pFrame) { CComposeFrame * pCompose = (CComposeFrame*)pFrame; if (pCompose->UseHtml()) { if (!pCompose->Initialized()) pCompose->InsertInitialText(); else { int32 startOffset = pCompose->GetQuoteSel(); if (startOffset != -1) { int32 endOffset = startOffset; int32 eReplyOnTop = 0; if (PREF_NOERROR == PREF_GetIntPref("mailnews.reply_on_top", &eReplyOnTop)) { switch (eReplyOnTop) { case 1: default: EDT_SetInsertPointToOffset(pMWContext, startOffset, 0); break; case 2: case 3: endOffset = EDT_GetInsertPointOffset(pMWContext); EDT_SetInsertPointToOffset( pMWContext, startOffset, endOffset - startOffset); break; } } pCompose->SetQuoteSel(-1); } } } // UseHtml() } // pFrame } // MWContextMessageComposition #endif // MOZ_MAIL_NEWS } void FE_FinishedRelayout(MWContext * pMWContext) { // Clear cached pointers to old elements if( pMWContext ){ CWinCX * pContext = WINCX(pMWContext); if(pContext){ pContext->ClearLastElement(); } } } ////////////////////////////////////////////////////////////////////////// enum { ED_LOAD_CURRENT_PAGE, ED_LOAD_CURRENT_FRAME, ED_LOAD_NEW_PAGE, ED_LOAD_TEMPLATE }; typedef struct _EDT_LoadUrlData { int iStyle; BOOL bNewWindow; CGenericFrame * pFrame; MWContext * pCopyHistoryContext; } EDT_LoadUrlData; // Access function for calling from outside to Edit or Navigate // Used by LiveWire SiteManager, DDE, OLE, and JAVA interfaces void FE_LoadUrl( char *pUrl, BOOL bEdit ) { if ( *pUrl == '\0' ){ // An empty string is same as none // Will load new blank page if bEdit is TRUE, // else load HomePage into browser pUrl = NULL; } CString csUrlFileName; if ( pUrl && NET_URL_Type(pUrl) == 0 ) { // Assume "file:///" if no URL type supplied WFE_ConvertFile2Url(csUrlFileName, (const char*)pUrl); pUrl = (char*)LPCSTR(csUrlFileName); } // Get the last active browser or editor frame // It doesn't matter which frame's function we call // since we are assured of having a URL and don't need history or other data. CGenericFrame* pFrame = (CGenericFrame*)FEU_GetLastActiveFrame(MWContextBrowser, FEU_FINDBROWSERANDEDITOR); // Default is to start a new editor frame BOOL bNewEditor = TRUE; MWContext * pMWContext = NULL; if( pFrame ){ if( pFrame->GetMainContext() ){ pMWContext = pFrame->GetMainContext()->GetContext(); } // If any frame already exists, then create a new editor in LoadUrlEditor // but if we are loading from an empty/untouched new document, then use that frame instead if( pMWContext && EDT_IS_NEW_DOCUMENT(pMWContext) && !EDT_DirtyFlag(pMWContext) ){ bNewEditor = FALSE; } } else { // We end up here if launched from OLE automation, e.g., Sitemanager if( bEdit ){ theApp.m_EditTmplate->OpenDocumentFile(NULL); pFrame = (CGenericFrame*)FEU_GetLastActiveFrame(MWContextBrowser, FEU_FINDEDITORONLY); // We don't need a new frame -- load the URL into the frame just created bNewEditor = FALSE; } else { theApp.m_ViewTmplate->OpenDocumentFile(NULL); pFrame = (CGenericFrame*)FEU_GetLastActiveFrame(MWContextBrowser, FEU_FINDBROWSERONLY); } } if( pFrame ){ if( !pMWContext && pFrame->GetMainContext() ){ pMWContext = pFrame->GetMainContext()->GetContext(); } if ( bEdit ) { // This will look for exisiting window AFTER // passing through EDT_PreOpen() plugin hook pFrame->LoadUrlEditor( pUrl, bNewEditor, pUrl ? ED_LOAD_CURRENT_PAGE : ED_LOAD_NEW_PAGE ); } else if( !FE_ActivateFrameWithURL(pUrl, FALSE) ) { // We didn't find a Browser with that URL - find or create a Browser if( !pFrame->GetMainContext() || EDT_IS_EDITOR(pMWContext) ){ // The last active frame was an editor - we need a Browser pFrame = (CGenericFrame*)FEU_GetLastActiveFrame(MWContextBrowser, FEU_FINDBROWSERONLY); } if( pFrame ){ // Bring this page to the foreground if ( pFrame->IsIconic() ){ pFrame->ShowWindow(SW_RESTORE); } pFrame->SetActiveWindow(); // Load into existing Browser pFrame->GetMainContext()->NormalGetUrl(pUrl); } else { // Start a new Browser frame with supplied URL wfe_CreateNavigator(pUrl); } } } else { //VERY BAD TO BE HERE - EXIT APP! ::MessageBox(0, "Failed to create new window\nfrom OLE Automation launch", 0, 0); // We know there are no visible windows to ask user about, // so just exit theApp.CommonAppExit(); } } void FE_SetNewDocumentProperties(MWContext * pMWContext) { EDT_PageData *pPageData = EDT_GetPageData(pMWContext); if ( pPageData == NULL ){ return; } // Copy background image if not in same directory as document int bKeepImages; PREF_GetBoolPref("editor.publish_keep_images",&bKeepImages); pPageData->bKeepImagesWithDoc = bKeepImages; // Get editor colors if using custom colors XP_Bool prefBool; PREF_GetBoolPref("editor.use_custom_colors",&prefBool); if( prefBool ) { COLORREF clr; PREF_GetColorPrefDWord("editor.text_color",&clr); WFE_SetLO_ColorPtr(clr,&pPageData->pColorText); PREF_GetColorPrefDWord("editor.link_color",&clr); WFE_SetLO_ColorPtr(clr,&pPageData->pColorLink); PREF_GetColorPrefDWord("editor.active_link_color",&clr); WFE_SetLO_ColorPtr(clr,&pPageData->pColorActiveLink); PREF_GetColorPrefDWord("editor.followed_link_color",&clr); WFE_SetLO_ColorPtr(clr,&pPageData->pColorFollowedLink); // Set the background color even if we use an image TODO: CHECK IF THIS IS SOURCE OF BUG PREF_GetColorPrefDWord("editor.background_color",&clr); WFE_SetLO_ColorPtr(clr, &pPageData->pColorBackground); } char * szBack = NULL; PREF_CopyCharPref("editor.background_image",&szBack); XP_Bool bBack; PREF_GetBoolPref("editor.use_background_image",&bBack); // Background image preference is independent from color preferences if( bBack && szBack ){ pPageData->pBackgroundImage = XP_STRDUP(szBack); XP_FREE(szBack); } EDT_SetPageData(pMWContext, pPageData); EDT_FreePageData(pPageData); // Add fixed MetaData items: EDT_MetaData *pMetaData = EDT_NewMetaData(); if ( pMetaData == NULL ){ return; } //What generated this document: pMetaData->bHttpEquiv = FALSE; pMetaData->pName = XP_STRDUP("Author"); PREF_CopyCharPref("editor.author",&(pMetaData->pContent)); EDT_SetMetaData(pMWContext, pMetaData); EDT_FreeMetaData(pMetaData); // Force entire view to be painted // (if not, a browser background image leaks through at top, // above caret on first line) ::InvalidateRect( (PANECX(pMWContext))->GetPane(), NULL, TRUE); } // From the Composer button on the Taskbar: void CGenericFrame::OnOpenComposerWindow() { CAbstractCX *pCX = GetMainContext(); if(pCX != NULL) { int nCount = FEU_GetNumActiveFrames(MWContextBrowser, FEU_FINDEDITORONLY); if((nCount == 1 && (pCX->GetContext()->type == MWContextBrowser && EDT_IS_EDITOR(pCX->GetContext()))) || nCount == 0){ // If we didn't find an editor, start a new one OnEditNewBlankDocument(); } else if(nCount > 1 || !(pCX->GetContext()->type == MWContextBrowser && EDT_IS_EDITOR(pCX->GetContext()))) { CFrameWnd *pFrame; //if we are an editor then get the bottom most editor if(pCX->GetContext()->type == MWContextBrowser && EDT_IS_EDITOR(pCX->GetContext())) { pFrame = FEU_GetBottomFrame(MWContextBrowser, FEU_FINDEDITORONLY); } else // if we are not an editor, then get the last active editor pFrame = FEU_GetLastActiveFrame(MWContextBrowser, FEU_FINDEDITORONLY); if(pFrame){ if(pFrame->IsIconic()) pFrame->ShowWindow(SW_RESTORE); #ifdef _WIN32 pFrame->SetForegroundWindow(); #else pFrame->SetActiveWindow(); #endif } } } } static void FinishLoadUrlEditor(XP_Bool bUserCanceled, char* pUrl, void* user_data) { ASSERT(user_data); if( !user_data){ return; } EDT_LoadUrlData * pData = (EDT_LoadUrlData*)user_data; if( bUserCanceled ){ // Note: We usually create a new Compose window below, // except when we need to create one in FE_LoadUrl // because no Browser or Composer windows existed // before trying to start Composer. // If this window was already created, // create a Navigator with the URL instead // and close the Composer window if( !pData->bNewWindow && pData->pFrame ){ wfe_CreateNavigator(pUrl); pData->pFrame->PostMessage(WM_CLOSE,0,0); } return; } // Use the MAIN context for frameset URL or if active context is not found CWinCX *pWinContext = NULL; if( pData->iStyle == ED_LOAD_CURRENT_FRAME || !(pWinContext = pData->pFrame->GetActiveWinContext()) ){ pWinContext = pData->pFrame->GetMainWinContext(); } URL_Struct *pUrlStruct = NULL; History_entry * pEntry = NULL; if( pWinContext ){ pEntry = SHIST_GetCurrent(&(pWinContext->GetContext()->hist)); } // An empty string is same as blank if( pUrl && *pUrl == '\0' ){ pUrl = NULL; } BOOL bNewDocument = (pData->iStyle == ED_LOAD_NEW_PAGE) || (pUrl == NULL); if( !bNewDocument ){ // Try to activate an existing window EXCEPT if loading a template if( pUrl && pData->iStyle != ED_LOAD_TEMPLATE && FE_ActivateFrameWithURL( pUrl, TRUE ) ){ // We found existing window - we're done delete pData; return; } // Important! We need to detect when URL to load is same as current history's URL // so we create the URL Struct from the appropriate context if ( pUrl == NULL || (pEntry && pEntry->address && !strcmp(pEntry->address, pUrl)) ) { // Create a new URL struct using the data in current page's context if(pEntry){ pUrlStruct = SHIST_CreateURLStructFromHistoryEntry(pWinContext->GetContext(), pEntry); // Above defaults to NET_DONT_RELOAD. // We need NET_NORMAL_RELOAD to be sure we do normal server checks // to see if doc changed at original source (fix for bug 80606) pUrlStruct->force_reload = NET_NORMAL_RELOAD; } else { // Unlikely event - no current history entry bNewDocument = TRUE; } } else { // Create a new URL structures and copy URL string to it pUrlStruct = NET_CreateURLStruct(pUrl, NET_NORMAL_RELOAD); } } if ( pUrlStruct ) { // Must clear this to correctly load URL pUrlStruct->fe_data = NULL; // If this structure changes in the future to hold data which can be carried // across contexts, then we lose. memset((void *)&(pUrlStruct->savedData), 0, sizeof(SHIST_SavedData)); } MWContext * pEditContext = NULL; if( pData->bNewWindow ){ // Most uses create a new context, frame, view set and load the URL if supplied pEditContext = FE_CreateNewEditWindow(NULL, pUrlStruct ); } else { // Or load URL into an existing window only if its already an editor if( EDT_IS_EDITOR(pWinContext->GetContext()) ){ pEditContext = pWinContext->GetContext(); } if( !bNewDocument ){ // If Composer frame was created at startup, // we end up here to load URL from the command line // Suppress the "-embedding" string we get from OLE launch if( 0 == strcmpi(pUrl, "-embedding") ){ bNewDocument = TRUE; } else { pWinContext->NormalGetUrl(pUrl); } } } if( pEditContext ){ if ( bNewDocument ) { // Start a new document - Get the view from the newly-created edit context // Start new doc with URL = "about:editfilenew" WINCX(pEditContext)->NormalGetUrl(EDT_NEW_DOC_URL); } else { if( pData->iStyle == ED_LOAD_TEMPLATE ){ // This will trigger changing to new doc name and URL // in Edit FE_EditorGetUrlExitRoutine. ((CEditFrame*)GetFrame(pEditContext))->m_pTemplateContext = pEditContext; } // Copy the history of the "caller" browser window if it was set // Note, after LoadUrlEditor, if user closes the Navigator window // before canceling out of a "Can't Edit URL" prompt, // pNavContext will be BAD, so check if context is in the list if ( pData->pCopyHistoryContext && XP_IsContextInList(pData->pCopyHistoryContext) && pData->pCopyHistoryContext != pEditContext ) { // Copy History from current window to Edit context // (This sets current history index to 1) SHIST_CopySession(pEditContext, pData->pCopyHistoryContext); // Set the current session history index for the new context // by finding same location of old address in new context // If there is not pCurrentEntry, then browser had no history // and we got a new doc when editor was created: index = 1 int nIndex = 1; if ( pEntry && pEntry->address != NULL ) { nIndex = FindCurrentUrlInHistory(pEditContext, pEntry->address ); } SHIST_SetCurrent(&(pEditContext->hist), nIndex ); } } } delete pData; } void CGenericFrame::LoadUrlEditor(char * pUrl, BOOL bNewWindow, int iLoadStyle, MWContext * pCopyHistoryContext) { EDT_LoadUrlData * pData = new EDT_LoadUrlData; if( pData ){ pData->pFrame = this; pData->iStyle = iLoadStyle; // We MUST create a new window if current window is not an editor pData->bNewWindow = EDT_IS_EDITOR(GetMainContext()->GetContext()) ? bNewWindow : TRUE; // We will copy history from a source browser context ONLY if creating a new window pData->pCopyHistoryContext = pData->bNewWindow ? pCopyHistoryContext : NULL; if( pUrl && *pUrl){ // Be sure we have URL format by now CString csURL; WFE_ConvertFile2Url(csURL, pUrl); // Call Editor Plugin to possibly replace the supplied URL // or do source file locking EDT_PreOpen(GetMainContext()->GetContext(), (char*)(LPCSTR(csURL)), &FinishLoadUrlEditor, pData); //TODO: REMOVE THIS - TEMP - SKIP PLUGIN TO AVOID NSPR20 PROBLEMS???? //FinishLoadUrlEditor(FALSE, (char*)(LPCSTR(csURL)), pData); } else { // No URL address given - Don't go through plugin FinishLoadUrlEditor(FALSE, NULL, pData); } } } // Start New document in a new window // This is used by both Browser and Editor void CGenericFrame::OnEditNewBlankDocument() { if ( GetMainContext() == NULL || GetMainContext()->GetContext() == NULL ) { return; } // Create a new window with a new blank page LoadUrlEditor(NULL, TRUE, ED_LOAD_NEW_PAGE); } // Open a Editor window with current URL from a browser window void CGenericFrame::OnNavigateToEdit() { CWinCX *pContext = GetMainWinContext(); if( !pContext || !pContext->GetContext()) return; OpenEditorWindow(ED_LOAD_CURRENT_PAGE); } void CGenericFrame::OnEditFrame() { CWinCX *pContext = GetActiveWinContext(); if( !pContext || !pContext->GetContext()) return; // This style really doesn't do anything -- // we will look for active frame no matter // what style is if not ED_LOAD_CURRENT_PAGE OpenEditorWindow(ED_LOAD_CURRENT_FRAME); } void CGenericFrame::OpenEditorWindow(int iLoadStyle) { CWinCX *pWinContext = NULL; // If editing a frameset, or no active window, use top-level (frameset) URL if( iLoadStyle == ED_LOAD_CURRENT_PAGE || !(pWinContext = GetActiveWinContext()) ){ pWinContext = GetMainWinContext(); } if( !pWinContext ){ return; } MWContext * pCurrentContext = pWinContext->GetContext(); if(!pCurrentContext){ return; } History_entry * pEntry = SHIST_GetCurrent(&(pWinContext->GetContext()->hist)); // Get current address from history and load that into editor // Pass pCurrentContext to signal FinishLoadUrlEditor to copy history from this context LoadUrlEditor((pEntry && pEntry->address) ? pEntry->address : NULL, TRUE, iLoadStyle, pCurrentContext); } // Called by other apps via registered message // TODO: TEST IF THESE ARE USED ANY MORE -- LIVEWIRE??? LRESULT CGenericFrame::OnOpenEditor(WPARAM wParam, LPARAM lParam ) { HANDLE handle = NULL; #ifndef WIN32 // We get data passed to us if Win16 handle = (HANDLE)wParam; #endif char *pUrl = GetGlobalUrlPointer(handle); // In Win32, handle wil be obtained from memory-mapped file // This will load an empty editor window if no data is found // This will try to locate an existing window AFTER passing // through EDT_PreOpen() plugin hook function LoadUrlEditor(pUrl); #ifndef WIN32 if ( NULL != handle) { GlobalUnlock(handle); } #else // Win16 if ( pUrl ) { XP_FREE(pUrl ); } #endif return 0; } // Called by other apps via registered message LRESULT CGenericFrame::OnOpenNavigator(WPARAM wParam, LPARAM lParam ) { HANDLE handle = NULL; #ifndef WIN32 // We get data passed to us if Win16 handle = (HANDLE)wParam; #endif char *pUrl = GetGlobalUrlPointer(handle); // First try to find existing frame if ( ! FE_ActivateFrameWithURL( pUrl, FALSE ) ) { wfe_CreateNavigator( pUrl ); } #ifndef WIN32 if ( NULL != handle) { GlobalUnlock(handle); } #else // Win16 if ( pUrl ) { XP_FREE(pUrl ); } #endif return 0; } // Should be called only from Edit view // or from EditToNavigate (which is called from view) // after FE_CheckAndSaveDocument is called void CGenericFrame::OpenNavigatorWindow(MWContext * pMWContext) { if ( !pMWContext ){ return; } BOOL bNewDocument = FALSE; MWContext * pNavContext = NULL; BOOL bNewWindow = TRUE; URL_Struct *pUrlStruct = NULL; History_entry * pCurrentEntry = SHIST_GetCurrent(&(pMWContext->hist)); if ( pCurrentEntry != NULL && pCurrentEntry->address ) { if ( 0 == XP_STRCMP(pCurrentEntry->address, EDT_NEW_DOC_NAME) ) { // Suppress trying to load "Untitled" document, load home page instead bNewDocument = TRUE; pCurrentEntry = NULL; } else { // First try to find existing frame pNavContext = FE_ActivateFrameWithURL( pCurrentEntry->address, FALSE ); if ( pNavContext ) { bNewWindow = FALSE; // Do reload in case the contents of the found browser window // are older than the editor we are switching from // (Note: Must get new CWinCX from MWcontext since // this will get sent before view is activated, // i.e., Main and Active contexts not set yet) WINCX(pNavContext)->Reload(NET_SUPER_RELOAD); } else { pUrlStruct = SHIST_CreateURLStructFromHistoryEntry(GetMainContext()->GetContext(), pCurrentEntry); if ( pUrlStruct ) { // Must clear this to correctly load URL into new context pUrlStruct->fe_data = NULL; // Always check the server to get most up-to-date version pUrlStruct->force_reload = NET_NORMAL_RELOAD; // This prevents URL from being added twice // to history list -- we copy from old to new context // and reposition "current" to that history item pUrlStruct->history_num = 0; // If this structure changes in the future to hold data which can be carried // across contexts, then we lose. memset((void *)&(pUrlStruct->savedData), 0, sizeof(SHIST_SavedData)); } } } } else { // If no current history, this will cause loading the Home Page bNewDocument = TRUE; } if ( !pNavContext ) { // Create new Frame+View+Context pNavContext = CFE_CreateNewDocWindow(NULL, pUrlStruct ); } if ( pNavContext ) { if ( bNewWindow ) { // Copy History from Editor to Navigator context // Note: This function was modified to not copy any "Untitled" new doc entries SHIST_CopySession(pNavContext, pMWContext); // Set the current session history index for the new context // by finding same location of old address in new context // (Note: pCurrentEntry = NULL in browser when changing to browser // from an empty document. Set default Index to 0 to handle this) int nIndex = 0; if ( pCurrentEntry && pCurrentEntry->address != NULL ) { nIndex = FindCurrentUrlInHistory(pNavContext, pCurrentEntry->address ); } SHIST_SetCurrent(&(pNavContext->hist), nIndex ); } // Do this AFTER copying history so homepage appears in new history list if ( bNewDocument ) { // Load home page if no URL or "Untitled" was supplied // TODO: Find existing instance of current home page? (very tricky!) ((CMainFrame*)GetFrame(pNavContext))->OnLoadHomePage(); } } } // Replace Editor with a Navigator window with current Editor URL // This and OpenEditorWindow should be called // only after FE_CheckAndSaveDocument void CGenericFrame::EditToNavigate(MWContext * pEditContext, BOOL bNewDocument ) { if ( pEditContext == NULL ) { return; } // Place Browser at same place wfe_bUseLastFrameLocation = TRUE; OpenNavigatorWindow(pEditContext); // Close the underlying editor ((CMainFrame*)GetFrame(pEditContext))->PostMessage(WM_CLOSE); } LRESULT CGenericFrame::OnNetscapeGoldIsActive(WPARAM wParam, LPARAM lParam) { // Return handle to Frame window as response to // our special message - another instance or app // is asking if we are here return (LRESULT)(this->m_hWnd); } void CGenericFrame::OnEditNewDocFromTemplate() { if ( GetMainContext() == NULL || GetMainContext()->GetContext() == NULL ) { return; } // Popup dialog to allow user to set location, choose from 20 most recent, or choose new file COpenTemplateDlg dlg(this); if(dlg.DoModal() == IDOK){ char *pTemplate = NULL; if( !dlg.m_csLocation.IsEmpty() ){ pTemplate = XP_STRDUP((char*)LPCSTR(dlg.m_csLocation)); if( pTemplate ) { // Save the location chosen; if it is loaded successfully, // it will be added to template history list PREF_SetCharPref("editor.template_last_loc", pTemplate); // Load a browser with this template URL char * pDefault = NULL; PREF_CopyCharPref("editor.default_template_location", &pDefault); if( pDefault && 0 == strcmp(pDefault, pTemplate) ){ // Current location is Netscape's Template page, // Load into Browser wfe_CreateNavigator(pTemplate); } else { // Check if user is already editing this template MWContext *pEditContext = FE_ActivateFrameWithURL(pTemplate, TRUE); if( pEditContext && EDT_DirtyFlag(pEditContext) ){ CGenericFrame *pFrame = (CGenericFrame*)GetFrame(pEditContext); // Warn the user that template is being edited // and new page wont have unsaved changes pFrame->MessageBox(szLoadString(IDS_EDITING_TEMPLATE), szLoadString(IDS_NEW_PAGE_TEMPLATE), MB_ICONEXCLAMATION | MB_OK); } // Load template page into a new edit window LoadUrlEditor(pTemplate, TRUE, ED_LOAD_TEMPLATE); } XP_FREEIF(pDefault); XP_FREE(pTemplate); } } } } ////////////////////////////////////////////////////////////////////// // SiteManager communications methods // #ifdef XP_WIN32 // Site Manager tells us it is being activated or destroyed LRESULT CGenericFrame::OnSiteMgrMessage(WPARAM wParam, LPARAM lParam) { if( wParam == SM_IS_ALIVE ){ if( pITalkSMClient && !pITalkSMClient->IsRegistered() ){ // This should occur only if SiteManager was run the very first time // after our instance started (it wasn't registered) // Recreating our class will reset registration flag delete pITalkSMClient; pITalkSMClient = new (ITalkSMClient); } if( pITalkSMClient && pITalkSMClient->IsRegistered() ){ bSiteMgrIsActive = TRUE; pITalkSMClient->SetKnownSMState(TRUE); } return 1; } else if( wParam == SM_IS_DEAD ){ bSiteMgrIsActive = FALSE; if( pITalkSMClient ){ pITalkSMClient->SetKnownSMState(FALSE); } return 1; } return 0; } #endif void CGenericFrame::OnActivateSiteManager() { #ifdef XP_WIN32 XP_Bool prefBool; PREF_GetBoolPref("editor.hints.sitemanager",&prefBool); if( bSiteMgrIsRegistered ) { if ( prefBool ) { // Show a "Hint" dialog about drag and drop until // user checks "Don't show this" in dialog CEditHintDlg dlg(this, IDS_DRAG_SITEMAN_HINT); dlg.DoModal(); if ( dlg.m_bDontShowAgain ) { PREF_SetBoolPref("editor.hints.sitemanager",FALSE); } } // This will invoke SiteManager if it is not already running if( pITalkSMClient->BecomeActive() ){ bSiteMgrIsActive = TRUE; } } #endif } void CGenericFrame::OnUpdateActivateSiteManager(CCmdUI* pCmdUI) { #ifdef XP_WIN32 pCmdUI->Enable( bSiteMgrIsRegistered ); #endif } static BOOL bInFileMenu = FALSE; static BOOL bInFontMenu = FALSE; static BOOL bInSizeMenu = FALSE; static BOOL bInHistoryMenu = FALSE; static BOOL bInTableMenu = FALSE; static BOOL bInEditMenu = FALSE; // Not totally cool to use fixed menu indexes, but much more efficient #define ed_RECENTFILE_INDEX 2 // In File menu #define ed_PASTE_INDEX 4 // In Edit menu #define ed_FONT_FACE_INDEX 0 // In Format Menu #define ed_FONT_SIZE_INDEX 1 // In Format Menu #define ed_SELECT_MENU_INDEX 1 // These are in Table menu #define ed_DELETE_MENU_INDEX 2 #define ed_PASTE_MENU_INDEX 3 #define ed_ALIGN_MENU_INDEX 5 // Put all Composer-only code here - called only from CGenericFrame::OnMenuSelect() void CGenericFrame::OnMenuSelectComposer(UINT nItemID, UINT nFlags, HMENU hSysMenu) { if ( nFlags == 0xFFFF && hSysMenu == 0 ) { // Menu is being destroyed - clear rebuild flags bInFileMenu = FALSE; bInFontMenu = FALSE; bInSizeMenu = FALSE; bInHistoryMenu = FALSE; bInTableMenu = FALSE; bInEditMenu = FALSE; return; } if ( nFlags & MF_POPUP ) { MWContext * pMWContext = GetMainContext()->GetContext(); HMENU hMenu = ::GetMenu(m_hWnd); if( !hMenu || !pMWContext ){ return; } int nCount = GetMenuItemCount(hMenu); HMENU hEditHistoryMenu = NULL; HMENU hFontMenu = NULL; HMENU hSizeMenu = NULL; HMENU hSubMenu = NULL; int i; for( i = 0; i < nCount; i++) { hSubMenu = GetSubMenu(hMenu, i); if( hSubMenu ) { // Build recent files submenu when menu is opened so we can disable if empty if( i == ED_MENU_FILE && nItemID == ED_MENU_FILE ) { if( bInFileMenu ) return; bInFileMenu = TRUE; // Build a menu of recently-edited URL titles int iCount = ((CNetscapeEditView*)GetActiveView())->BuildEditHistoryMenu(::GetSubMenu(hSubMenu, ed_RECENTFILE_INDEX), 0); if( iCount == 0 ) EnableMenuItem(hSubMenu, ed_RECENTFILE_INDEX, MF_BYPOSITION | MF_GRAYED); } // Checking nItemID assures we do stuff only when the popup opens first time else if( i == ED_MENU_EDIT && nItemID == ED_MENU_EDIT ) { if( bInEditMenu ) return; bInEditMenu = TRUE; BOOL bInTable = EDT_IsInsertPointInTable(pMWContext); // Get what types are available on the clipboard BOOL bHaveText, bHaveLink, bHaveImage, bHaveTable; BOOL bCanPaste = wfe_GetClipboardTypes(pMWContext, bHaveText, bHaveImage, bHaveLink, bHaveTable ); HMENU hPasteMenu = ::GetSubMenu(hSubMenu, ed_PASTE_INDEX); if( bHaveText && bHaveImage ) { if( hPasteMenu && bHaveTable && ::GetMenuItemCount(hPasteMenu) == 2 ) { // We already had a submenu with 2 items, but we need 3, // just reload the menu ::DestroyMenu(hPasteMenu); hPasteMenu = 0; } if( !hPasteMenu ) { hPasteMenu = ::LoadMenu(AfxGetResourceHandle(), MAKEINTRESOURCE(IDM_COMPOSER_PASTEMENU)); ::ModifyMenu(hSubMenu, ed_PASTE_INDEX, MF_BYPOSITION | MF_POPUP | MF_STRING, (UINT)hPasteMenu, szLoadString(IDS_EDIT_PASTE)); } if( !bHaveTable && ::GetMenuItemCount(hPasteMenu) == 3 ) { ::DeleteMenu(hPasteMenu, 0, MF_BYPOSITION); } } else if( hPasteMenu ) { // Replace the existing submenu with the single "Paste" command ::DestroyMenu(hPasteMenu); ::ModifyMenu(hSubMenu, ed_PASTE_INDEX, MF_BYPOSITION | MF_STRING, ID_EDIT_PASTE, szLoadString(IDS_EDIT_PASTE) ); } } // Do things in Format menu only when specific submenu is selected else if( i == ED_MENU_FORMAT && hSubMenu == hSysMenu) { if( nItemID == ed_FONT_FACE_INDEX ) { hFontMenu = ::GetSubMenu(hSubMenu, ed_FONT_FACE_INDEX); // Prevent rebuilding menu when mouse moves away if( bInFontMenu ) return; bInFontMenu = TRUE; // Delete any existing items for( int i = ::GetMenuItemCount(hFontMenu) - 1; i >= 0; i--){ DeleteMenu(hFontMenu, i, MF_BYPOSITION); } // Get list of FontFace fonts defined in XP_Strings char * pFontFaces = EDT_GetFontFaces(); // Build the FontFace menu if( pFontFaces ) { char * pFont = pFontFaces; ::AppendMenu(hFontMenu, MF_STRING, ID_FORMAT_FONTFACE_BASE, pFont); pFont += XP_STRLEN(pFont) + 1; if( *pFont ) { ::AppendMenu(hFontMenu, MF_STRING, ID_FORMAT_FONTFACE_BASE+1, pFont); } int nCount = 0; if( wfe_iTrueTypeFontCount && wfe_ppTrueTypeFonts ) { // Add separator ::AppendMenu(hFontMenu, MF_SEPARATOR,0,0); // Add TrueType fonts but don't overflow the screen height // Number of items that will fit, minus some for items already // added, separators, and a bit extra nCount = (sysInfo.m_iScreenHeight / GetSystemMetrics(SM_CYMENU)) - 6; for( int i = 0; i < min(wfe_iTrueTypeFontCount, nCount); i++ ){ ::AppendMenu(hFontMenu, MF_STRING, ID_FORMAT_FONTFACE_BASE+i+2, wfe_ppTrueTypeFonts[i]); } } if( nCount < wfe_iTrueTypeFontCount ) { ::AppendMenu(hFontMenu, MF_SEPARATOR,0,0); // Last item is "Other..." to launch Window's Font Face dialog ::AppendMenu(hFontMenu, MF_STRING, ID_OTHER_FONTFACE, ed_pOther); } } } else if( nItemID == ed_FONT_SIZE_INDEX ) { hSizeMenu = ::GetSubMenu(hSubMenu, ed_FONT_SIZE_INDEX); if( bInSizeMenu ) return; bInSizeMenu = TRUE; int iCount = ::GetMenuItemCount(hSizeMenu); if( iCount == 1 ) { // Initial menu has 1 placeholder - modify that // and append the rest // First 2 menu items are relative size change ::ModifyMenu( hSizeMenu, 0, MF_BYPOSITION | MF_STRING, ID_FORMAT_INCREASE_FONTSIZE, szLoadString(IDS_INCREASE_FONTSIZE) ); ::AppendMenu( hSizeMenu, MF_STRING, ID_FORMAT_DECREASE_FONTSIZE, szLoadString(IDS_DECREASE_FONTSIZE) ); ::AppendMenu( hSizeMenu, MF_SEPARATOR, 0, 0); } // Delete any existing items except for 1st three for( i = iCount - 1; i > 2; i--) { DeleteMenu(hSizeMenu, i, MF_BYPOSITION); } // Check if current base font is fixed width BOOL bFixedWidth = (EDT_GetFontFaceIndex(pMWContext) == 1); // Change font size strings based on current font base for ( i = 0; i < MAX_FONT_SIZE; i++ ){ ::AppendMenu( hSizeMenu, MF_STRING, ID_FORMAT_FONTSIZE_BASE + i, wfe_GetFontSizeString(pMWContext, i+1, bFixedWidth, TRUE) ); // Format for menu } if( wfe_iFontSizeMode == ED_FONTSIZE_ADVANCED ) { // The "Advanced" absolute point size strings ::AppendMenu( hSizeMenu, MF_SEPARATOR, 0, 0); // This string is "8 pts" so it must be translated ::AppendMenu( hSizeMenu, MF_STRING, ID_FORMAT_POINTSIZE_BASE, szLoadString(IDS_8_PTS)); // Others assume pure numbers don't have to be translated ::AppendMenu( hSizeMenu, MF_STRING, ID_FORMAT_POINTSIZE_BASE+1, "9"); ::AppendMenu( hSizeMenu, MF_STRING, ID_FORMAT_POINTSIZE_BASE+2, "10"); ::AppendMenu( hSizeMenu, MF_STRING, ID_FORMAT_POINTSIZE_BASE+3, "11"); ::AppendMenu( hSizeMenu, MF_STRING, ID_FORMAT_POINTSIZE_BASE+4, "12"); ::AppendMenu( hSizeMenu, MF_STRING, ID_FORMAT_POINTSIZE_BASE+5, "14"); ::AppendMenu( hSizeMenu, MF_STRING, ID_FORMAT_POINTSIZE_BASE+6, "16"); ::AppendMenu( hSizeMenu, MF_STRING, ID_FORMAT_POINTSIZE_BASE+7, "18"); ::AppendMenu( hSizeMenu, MF_STRING, ID_FORMAT_POINTSIZE_BASE+8, "20"); ::AppendMenu( hSizeMenu, MF_STRING, ID_FORMAT_POINTSIZE_BASE+9, "22"); ::AppendMenu( hSizeMenu, MF_STRING, ID_FORMAT_POINTSIZE_BASE+10, "24"); ::AppendMenu( hSizeMenu, MF_STRING, ID_FORMAT_POINTSIZE_BASE+11, "26"); ::AppendMenu( hSizeMenu, MF_STRING, ID_FORMAT_POINTSIZE_BASE+12, "28"); ::AppendMenu( hSizeMenu, MF_STRING, ID_FORMAT_POINTSIZE_BASE+13, "36"); ::AppendMenu( hSizeMenu, MF_STRING, ID_FORMAT_POINTSIZE_BASE+14, "48"); ::AppendMenu( hSizeMenu, MF_STRING, ID_FORMAT_POINTSIZE_BASE+15, "72"); } } } else if( i == ED_MENU_TABLE && nItemID == ED_MENU_TABLE ) { if( bInTableMenu ) return; bInTableMenu = TRUE; BOOL bInTable = EDT_IsInsertPointInTable(pMWContext); ::EnableMenuItem(hSubMenu, ed_DELETE_MENU_INDEX, MF_BYPOSITION | (bInTable ? MF_ENABLED : MF_GRAYED)) ; ::EnableMenuItem(hSubMenu, ed_SELECT_MENU_INDEX, MF_BYPOSITION | (bInTable ? MF_ENABLED : MF_GRAYED)); ::EnableMenuItem(hSubMenu, ed_PASTE_MENU_INDEX, MF_BYPOSITION | (bInTable ? MF_ENABLED : MF_GRAYED)); ::EnableMenuItem(hSubMenu, ed_ALIGN_MENU_INDEX, MF_BYPOSITION | (bInTable ? MF_ENABLED : MF_GRAYED)); // Show "Convert table to text" when table is selected or // caret is inside table with nothing selected BOOL bConvertToText = EDT_IsTableSelected(pMWContext) || (bInTable && !EDT_IsSelected(pMWContext) && EDT_GetSelectedCellCount(pMWContext) == 0); ::ModifyMenu(hSubMenu, ID_TABLE_TEXT_CONVERT, MF_BYCOMMAND | MF_STRING, ID_TABLE_TEXT_CONVERT, szLoadString(bConvertToText ? IDS_CONVERT_TABLE_TO_TEXT : IDS_CONVERT_TEXT_TO_TABLE) ); } } } } } ///////////////////////////////////////////////////////////////////////////// // Checks if there is any active editor plugin and lets the user stop it. // Return: TRUE - no plugin was running or user stopped the active plugin // FALSE - user didn't want to stop the plugin BOOL CheckAndCloseEditorPlugin(MWContext *pMWContext) { if (EDT_IsPluginActive(pMWContext)) { CGenericView* pView = WINCX(pMWContext)->GetView(); CWnd *pParentWnd = pView->GetFrame()->GetFrameWnd()->GetLastActivePopup(); if (pParentWnd->MessageBox(szLoadString(IDS_CONFIRM_STOP_PLUGIN), NULL, MB_YESNO | MB_ICONQUESTION) == IDYES) EDT_StopPlugin(pMWContext); else return FALSE; } return TRUE; } #endif // EDITOR