/* -*- 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. */ // mainfrm.cpp : implementation of the CMainFrame class // #include "stdafx.h" #include "dialog.h" #include "winclose.h" #include "cntritem.h" #include "timer.h" #include "cxsave.h" #include "edt.h" #include "mainfrm.h" #include "edframe.h" #include "netsvw.h" #include "hiddenfr.h" #include "intlwin.h" #include "msgcom.h" #include "custom.h" #include "statbar.h" #include "histbld.h" #include "nethelp.h" #include "mnwizard.h" #include "ssl.h" #include "prefapi.h" #include "prefInfo.h" #include "medit.h" #include "np.h" #include "npapi.h" // for NPWindow #ifdef JAVA #include "java.h" #endif #ifdef _DEBUG #undef THIS_FILE static char BASED_CODE THIS_FILE[] = __FILE__; #endif #ifndef _AFXDLL #define new DEBUG_NEW // MSVC Debugging new...goes to regular new in release mode #endif #define SECURE_BITMAP_INDEX 10 #define MIDSECURE_BITMAP_INDEX 9 #define UNSECURE_BITMAP_INDEX 8 // // If we are already calling NET_ProcessNet() cuz of a socket ready message // do not call it again via a timer interrupt // MODULE_PRIVATE int winfeInProcessNet = FALSE; static int calledProcessNet = FALSE; // remember a socket which got a network event while we were thinking static long m_nSocketToDealWith = 0; extern CMapStringToOb DNSCacheMap; static CHistoryMenuBuilder histBuilder; #include "toolbar.cpp" ///////////////////////////////////////////////////////////////////////////// // CMainFrame diagnostics #ifdef _DEBUG void CMainFrame::AssertValid() const { CGenericFrame::AssertValid(); } void CMainFrame::Dump(CDumpContext& dc) const { CGenericFrame::Dump(dc); } #endif //_DEBUG // // Pop up an alert box for the user // void CMainFrame::Alert(char * Msg) { MessageBox(Msg, szLoadString(AFX_IDS_APP_TITLE), MB_ICONEXCLAMATION | MB_OK); } // // Pop up a message to the user. // Return TRUE if the user clicks on the "OK" button else FALSE // int CMainFrame::Confirm(char * Msg) { int res = GetActiveWindow()->MessageBox(Msg, szLoadString(AFX_IDS_APP_TITLE), MB_ICONQUESTION | MB_OKCANCEL); return(res == IDOK); } char * CMainFrame::Prompt(const char * Msg, const char * Dflt) { // CDialogPRMT foo(this->GetActiveWindow()); // Must always use ActiveWindow so preference dialogs are the parent, // else user can move focus to preference dialog and loose prompt dialog CDialogPRMT foo(this->GetActiveWindow()); return(foo.DoModal(Msg, Dflt)); } char * CMainFrame::PromptPassword(char * Msg) { // CDialogPASS foo(this); CDialogPASS foo(this->GetActiveWindow()); return(foo.DoModal(Msg)); } #define IS_IN_WINDOW(hParent,hChild)\ (((hParent) == (hChild)) || ::IsChild(hParent, hChild)) BOOL CMainFrame::setNextTabFocus( int forward ) { CWinCX *pWinCX = GetMainWinContext(); if( pWinCX ) { // setTabFocusNext will search siblings BOOL ret = pWinCX->setTabFocusNext( forward ); if( ret ) return( TRUE ); } return( FALSE ); } BOOL CMainFrame::PreTranslateMessage(MSG* pMsg) { BOOL bTranslated = CGenericFrame::PreTranslateMessage(pMsg); if (bTranslated) return TRUE; // msg handled if (pMsg->message != WM_KEYDOWN) return FALSE; // we're not interested in translating this message // Do not continue with tab processing if in an editor if( (pMsg->wParam != VK_TAB && pMsg->wParam != VK_SPACE && pMsg->wParam != VK_RETURN) || EDT_IS_EDITOR(GetMainContext()->GetContext()) ) return( FALSE ); // if a plugin has the focus, we don't touch the any (TAB,SAPCE,CR) key. if( GetActiveWinContext() && GetActiveWinContext()->GetContext() ) { // get the plugin list NPEmbeddedApp * pPlugin = GetActiveWinContext()->GetContext()->pluginList; // check each plugin in the list, to see if a plugin is the parent // of the focus window. while( pPlugin != NULL ) { NPWindow* npWindow = pPlugin->wdata; if( npWindow && npWindow->type == NPWindowTypeWindow ) { // check relation of parent(plugin) - child(msg window) if( npWindow->window && IS_IN_WINDOW( (HWND)npWindow->window, pMsg->hwnd) ) return(FALSE); // plugin has focus, dont touch TAB key } pPlugin = pPlugin->next; } } /* The windows messaging systems such as CWnd::WalkPreTranslateTree(), only walk from leaf to root of the window tree. To navigate in frames(grids), Tab navigation needs to go from one window(view) to its sibling. Therefor, we need to walk the tree. */ CGenericView *pView; UINT forward = GetKeyState(VK_SHIFT)<0 ? 0 : 1 ; // 1 is forward UINT controlKey = GetKeyState(VK_CONTROL)<0 ? 1 : 0 ; // 1 controlKey, go to next group int ii; // IF child A reached the end of tabable elements, and child B // has no tabable elements, we need go back to child A to set // tab focus. That is the "for" loop for. for( ii = 0; ii < 2 && !bTranslated; ii ++ ) { // the chrome(location and starter bar) get Tab focus first if( GetChrome() != NULL ) { if( m_tabFocusInMainFrm == TAB_FOCUS_IN_NULL ) { // first time, if( pMsg->wParam != VK_TAB ) // #49928 only handle Tab key in Chrome return( FALSE ); // set focus to the location box. bTranslated = GetChrome()->procTabNavigation( pMsg->wParam, 1, controlKey ); if( bTranslated ) { m_tabFocusInMainFrm = TAB_FOCUS_IN_CHROME; return( TRUE ); } // else, do nothing, fall to setting focus in views. } else if( m_tabFocusInMainFrm == TAB_FOCUS_IN_CHROME ) { if( pMsg->wParam != VK_TAB ) // #49928 only handle Tab key in Chrome return( FALSE ); bTranslated = GetChrome()->procTabNavigation( pMsg->wParam, 0, controlKey ); if( bTranslated ) { // chrome consummed the Tab key m_tabFocusInMainFrm = TAB_FOCUS_IN_CHROME; return( TRUE ); } else { m_tabFocusInMainFrm = TAB_FOCUS_IN_NULL; // fall to setting focus in views. } } } else { // no chrome, user may just close the chrom if( m_tabFocusInMainFrm == TAB_FOCUS_IN_CHROME ) m_tabFocusInMainFrm = TAB_FOCUS_IN_NULL; // fall to setting focus in views. } if( bTranslated ) return(TRUE); #ifdef DEBUG_aliu // we should have returned, if focus was set in chrome. ASSERT( m_tabFocusInMainFrm != TAB_FOCUS_IN_CHROME ); #endif if( ! GetActiveView() ) { // #55453 something wrong, try my best. bTranslated = setNextTabFocus(forward); // setNextTabableFrame( NULL, forward ); //NULL start with the first frame } else { if( ! GetActiveView()->IsKindOf(RUNTIME_CLASS( CGenericView ) ) ) return(FALSE); // not html, maybe print-preview #44362 // now try to set tab focus to the views(grids) if( m_tabFocusInMainFrm == TAB_FOCUS_IN_GRID ) { // Starting with the active view, procTabNavigation() will // search siblings in this frame window. pView = (CGenericView *) GetActiveView( ); if( pView == NULL ) return(FALSE); // TODO control key is for Tab-group(Form, table) or for Frame??? if( ! controlKey ) { // try active view first bTranslated = pView->procTabNavigation( pMsg->wParam, forward, controlKey ); // for Tab, or SpaceBar if ( bTranslated ) { m_tabFocusInMainFrm = TAB_FOCUS_IN_GRID ; return( TRUE ); // msg handled } } if( pMsg->wParam != VK_TAB ) return( FALSE ); // active frame has nothing to tab to. m_tabFocusInMainFrm = TAB_FOCUS_IN_NULL; // try other frames(if any), starting from this // bTranslated = setNextTabableFrame( this, forward ); } else { // TAB_FOCUS_IN_NULL, // start with the first frame bTranslated = setNextTabFocus(forward); // setNextTabableFrame( NULL, forward ); } } // if( ! GetActiveView() ) if ( bTranslated ) { m_tabFocusInMainFrm = TAB_FOCUS_IN_GRID ; return( TRUE ); // msg handled } } // for( ii = 0; ii < 2; ii ++ ) return(FALSE); } // BOOL CMainFrame::PreTranslateMessage(MSG* pMsg) void CMainFrame::OnToggleFancyFtp() { if(GetMainContext()) { GetMainContext()->GetContext()->fancyFTP = !GetMainContext()->GetContext()->fancyFTP; } } void CMainFrame::OnUpdateToggleFancyFtp(CCmdUI* pCmdUI) { if(GetMainContext()) { pCmdUI->SetCheck(GetMainContext()->GetContext()->fancyFTP); } } void CMainFrame::RefreshNewEncoding(int16 csid, BOOL bIgnore) { if (m_iCSID != csid) { if(GetMainContext()) { int iOldCSID = m_iCSID; // Must set before EDT_SetEncoding. m_iCSID = csid; #ifdef EDITOR if( EDT_IS_EDITOR(GetMainContext()->GetContext()) ) { // EDT_SetEncoding takes care of reloading. if ( ! EDT_SetEncoding(GetMainContext()->GetContext(), csid) ) { // revert m_iCSID m_iCSID = iOldCSID; return; } } else #endif /* EDITOR */ { GetMainContext()->NiceReload(); } } } } // // Toggle the showing of the location bar // void CMainFrame::OnOptionsTitlelocationBar() { if(GetChrome()->GetToolbarVisible(ID_LOCATION_TOOLBAR)) { GetChrome()->ShowToolbar(ID_LOCATION_TOOLBAR, FALSE); m_bLocationBar= FALSE; } else { GetChrome()->ShowToolbar(ID_LOCATION_TOOLBAR, TRUE); m_bLocationBar= TRUE; } } void CMainFrame::OnUpdateOptionsTitlelocationBar(CCmdUI* pCmdUI) { pCmdUI->SetCheck(GetChrome()->GetToolbarVisible(ID_LOCATION_TOOLBAR)); } XP_BEGIN_PROTOS extern char * NET_PrintNetlibStatus(); XP_END_PROTOS void CMainFrame::OnOptionsTogglenetdebug() { if(GetActiveContext() != NULL) { char *rv = NET_PrintNetlibStatus(); FE_Alert(GetActiveContext()->GetContext(), rv); XP_FREE(rv); NET_ToggleTrace(); } } void CMainFrame::OnToggleImageLoad() { CWinCX *pWinCX; if( pWinCX = GetMainWinContext()) { if( prefInfo.m_bAutoLoadImages) { prefInfo.m_bAutoLoadImages = FALSE; GetChrome()->ImagesButton(TRUE); } else { prefInfo.m_bAutoLoadImages = TRUE;; GetChrome()->ImagesButton(FALSE); } } } void CMainFrame::OnUpdateToggleImageLoad(CCmdUI* pCmdUI) { CWinCX *pWinCX; if( pWinCX = GetMainWinContext()) { pCmdUI->SetCheck(prefInfo.m_bAutoLoadImages); } } void CMainFrame::OnNetSearch() { char * url = NULL; PREF_CopyConfigString("internal_url.net_search.url",&url); if(GetMainContext() && url) { GetMainContext()->NormalGetUrl(url); XP_FREE(url); } } void CMainFrame::OnUpdateNetSearch(CCmdUI *pCmdUI) { pCmdUI->Enable(TRUE); } void CMainFrame::OnUpdateSecurity(CCmdUI *pCmdUI) { MWContext *pContext = GetMainContext()->GetContext(); if(EDT_IS_EDITOR(pContext)) CGenericFrame::OnUpdateSecurity(pCmdUI); else { int status = XP_GetSecurityStatus(pContext); BOOL bHasSecurity = status == SSL_SECURITY_STATUS_ON_LOW || status == SSL_SECURITY_STATUS_ON_HIGH; if(m_pCommandToolbar) { switch(status) { case SSL_SECURITY_STATUS_ON_LOW: m_pCommandToolbar->ReplaceButtonBitmapIndex(ID_SECURITY, SECURE_BITMAP_INDEX); break; case SSL_SECURITY_STATUS_ON_HIGH: m_pCommandToolbar->ReplaceButtonBitmapIndex(ID_SECURITY, SECURE_BITMAP_INDEX); break; default: m_pCommandToolbar->ReplaceButtonBitmapIndex(ID_SECURITY, UNSECURE_BITMAP_INDEX); break; } pCmdUI->Enable(TRUE); } else pCmdUI->Enable(FALSE); } } void CMainFrame::OnUpdateSecurityStatus(CCmdUI *pCmdUI) { int status = XP_GetSecurityStatus(GetMainContext()->GetContext()); pCmdUI->Enable(status == SSL_SECURITY_STATUS_ON_LOW || status == SSL_SECURITY_STATUS_ON_HIGH); } void CMainFrame::OnUpdateViewCommandToolbar(CCmdUI *pCmdUI) { CGenericFrame::OnUpdateViewCommandToolbar(pCmdUI); if(!IsEditFrame() && PREF_PrefIsLocked("browser.chrome.show_toolbar")) pCmdUI->Enable(FALSE); } void CMainFrame::OnUpdateViewLocationToolbar(CCmdUI *pCmdUI) { CGenericFrame::OnUpdateViewLocationToolbar(pCmdUI); if(!IsEditFrame() && PREF_PrefIsLocked("browser.chrome.show_url_bar")) pCmdUI->Enable(FALSE); } void CMainFrame::OnUpdateViewCustomToolbar(CCmdUI *pCmdUI) { CGenericFrame::OnUpdateViewCustomToolbar(pCmdUI); if(!IsEditFrame() && PREF_PrefIsLocked("browser.chrome.show_directory_buttons")) pCmdUI->Enable(FALSE); } BOOL CMainFrame::OnCommand(UINT wParam,LONG lParam) { if(CGenericFrame::OnCommand(wParam, lParam)) return TRUE; // Extract the command ID UINT nID = LOWORD(wParam); // IS it a command or a menu? if ((nID == 0) || (LOWORD(lParam) != 0)) { // Menu IDs cannot be 0 // For menus, the low-order word of lParam is zero return FALSE; } // See if it was one of the items in the history list if (IS_HISTORY_ID(nID) && GetMainContext()) { // Make sure the command ID is consistent with the last // selected menu item histBuilder.Execute(nID); return TRUE; } if (IS_SHORTCUT_ID(nID) && GetMainContext()) { LoadShortcut(nID-FIRST_SHORTCUT_ID); } return FALSE; // no obe wanted it } void CMainFrame::OnInitMenuPopup(CMenu* pPopup, UINT nIndex, BOOL bSysMenu) { AfxLockTempMaps(); CGenericFrame::OnInitMenuPopup(pPopup,nIndex,bSysMenu); if (!bSysMenu && pPopup) { // if it contains Back has the first item and nIndex is not 0 then // fill in the menu. nIndex would be 0 if it's a popup or if // it's the first menu in the system if (pPopup->GetMenuItemID(0) == ID_NAVIGATE_BACK && nIndex != 0){ // We need to check whether we have already built the menu. // Even though we destroy the menu items each time the menus go away, // this only happens when the user is all done with the menu bar and // not when each individual pop-up menu is dismissed if (pPopup->GetMenuState(FIRST_HISTORY_MENU_ID, MF_BYCOMMAND) == (UINT)-1) BuildHistoryMenu(pPopup); } } // This function must always be executed, so please, do NOT put any // return statements in the above code! AfxUnlockTempMaps(); } void CMainFrame::GetMessageString( UINT nID, CString& rMessage ) const { // See if it's a history entry if (nID >= FIRST_HISTORY_MENU_ID && nID <= LAST_HISTORY_MENU_ID) { rMessage = histBuilder.GetURL(nID); if (rMessage.IsEmpty()) { ASSERT(FALSE); } } else { CGenericFrame::GetMessageString( nID, rMessage ); } } void CMainFrame::OnMenuSelect(UINT nItemID, UINT nFlags, HMENU hSysMenu) { if (nFlags == 0xFFFF) { HMENU hMenu = ::GetMenu(m_hWnd); // Not all top-level windows have a menu bar (e.g. the chromeless ones) // Also, Editor frame doesn't have these submenus if (hMenu && !IsEditFrame() ) { int nCount; UINT nCmdID; // Menu is going away so destroy all the menu items we // Now cleanup the history menu. We don't need to make any assumptions // about the number of menu items, because there are no separators or // pull-right sub-menus so we can tell by looking at the command IDs HMENU hPopupMenu = FEU_FindSubmenu(hMenu, ID_NAVIGATE_BACK); if (hPopupMenu) { ASSERT(hPopupMenu); nCount = ::GetMenuItemCount(hPopupMenu); // It's easiest to do this by walking backwards over the menu items for (int i = nCount - 1; i >= 0; i--) { nCmdID = ::GetMenuItemID(hPopupMenu, i); if (IS_HISTORY_ID(nCmdID)) VERIFY(::DeleteMenu(hPopupMenu, i, MF_BYPOSITION)); } } } } CGenericFrame::OnMenuSelect(nItemID, nFlags, hSysMenu); } void CMainFrame::BuildHistoryMenu(CMenu * pMenu) { ASSERT_VALID(pMenu); if (!pMenu) return; histBuilder.Fill(pMenu->m_hMenu, MAX_MENU_ITEM_LENGTH, eFILLALL); } LRESULT CMainFrame::OnButtonMenuOpen(WPARAM wParam, LPARAM lParam) { HMENU hMenu = (HMENU) lParam; UINT nCommand = (UINT) LOWORD(wParam); if(nCommand == ID_NAVIGATE_BACK) { histBuilder.Fill(hMenu, MAX_MENU_ITEM_LENGTH, eFILLBACKWARD); } else if(nCommand == ID_NAVIGATE_FORWARD) { histBuilder.Fill(hMenu, MAX_MENU_ITEM_LENGTH, eFILLFORWARD); } else if(nCommand == ID_PLACES) { FillPlacesMenu(hMenu); } return 1; } void CMainFrame::FillPlacesMenu(HMENU hMenu) { CString str; int bOK = PREF_NOERROR; char * label; for(int i = 0; bOK == PREF_NOERROR ; i++) { bOK = PREF_CopyIndexConfigString("toolbar.places.item",i,"label",&label); if (bOK == PREF_NOERROR && label && label[0]) { if (!strcmp(label,"-")) AppendMenu(hMenu, MF_SEPARATOR, FIRST_SHORTCUT_ID+i, ""); else AppendMenu(hMenu, MF_STRING, FIRST_SHORTCUT_ID+i, label); XP_FREE(label); } } } //lpttt->szText can only hold 80 characters #define MAX_TOOLTIP_CHARS 79 //status can only hold 1000 characters #define MAX_STATUS_CHARS 999 LRESULT CMainFrame::OnFillInToolTip(WPARAM wParam, LPARAM lParam) { HWND hwnd = (HWND)wParam; LPTOOLTIPTEXT lpttt = (LPTOOLTIPTEXT) lParam; CToolbarButton *pButton = (CToolbarButton *)CWnd::FromHandle(hwnd); UINT nCommand = pButton->GetButtonCommand(); const char * pTipText = pButton->GetToolTipText(); const char * pText = NULL; if(nCommand == ID_NAVIGATE_BACK || nCommand == ID_NAVIGATE_FORWARD) { pText = FindHistoryToolTipText(nCommand); } else if(nCommand == ID_GO_HOME) { pText = theApp.m_pHomePage; } else if(nCommand == ID_FILE_PRINT) { if(GetActiveWinContext() && GetActiveWinContext()->IsGridCell()) pText = szLoadString(ID_PRINT_FRAME_SELECTED); else if(GetMainContext() && GetMainContext()->IsGridParent()) pText = szLoadString(ID_PRINT_FRAME_NOSELECTION); else pText = szLoadString(ID_PRINT_PAGE); } if(pText == NULL || XP_STRCMP(pText, "") == 0) strncpy(lpttt->szText, pTipText, MAX_TOOLTIP_CHARS); else strncpy(lpttt->szText, pText, MAX_TOOLTIP_CHARS); return 1; } LRESULT CMainFrame::OnFillInToolbarButtonStatus(WPARAM wParam, LPARAM lParam) { UINT nCommand = LOWORD(wParam); char *pStatus = (char*)lParam; if(nCommand == ID_FILE_PRINT) { if(GetActiveWinContext() && GetActiveWinContext()->IsGridCell()) strncpy(pStatus, szLoadString(ID_PRINT_FRAME_SELECTED), MAX_STATUS_CHARS); else if(GetMainContext() && GetMainContext()->IsGridParent()) strncpy(pStatus, szLoadString(ID_PRINT_FRAME_NOSELECTION), MAX_STATUS_CHARS); else strncpy(pStatus, szLoadString(ID_PRINT_PAGE), MAX_STATUS_CHARS); } return 1; } void CMainFrame::OnIncreaseFont() { CGenericFrame::OnIncreaseFont(); } void CMainFrame::OnDecreaseFont() { CGenericFrame::OnDecreaseFont(); } const char *CMainFrame::FindHistoryToolTipText(UINT nCommand) { CGenericFrame * pFrame = (CGenericFrame * )FEU_GetLastActiveFrame(); if(!pFrame) return NULL; CAbstractCX * pCX = pFrame->GetMainContext(); if (!pCX) return NULL; // Get the session history list XP_List* pList = SHIST_GetList(pCX->GetContext()); // Get the pointer to the current history entry History_entry* pCurrentDoc = pCX->GetContext()->hist.cur_doc_ptr; XP_List *pCurrentNode = XP_ListFindObject(pList, pCurrentDoc); if (!pCurrentNode) return NULL; XP_List *pNode = NULL; if(nCommand == ID_NAVIGATE_FORWARD) { pNode = pCurrentNode->next; } else if(nCommand == ID_NAVIGATE_BACK) { pNode = pCurrentNode->prev; } if(pNode == NULL) return NULL; History_entry * pEntry = (History_entry*)pNode->object; //if the page has no title, then the url is in the title field return pEntry->title; } void CMainFrame::OnFlushCache() { FE_FlushCache(); } void CMainFrame::OnOptionsViewToolBar() { LPNSTOOLBAR pIToolBar = NULL; GetChrome()->QueryInterface(IID_INSToolBar, (LPVOID *) &pIToolBar ); if ( pIToolBar && pIToolBar->GetHWnd() ) { if (::IsWindowVisible( pIToolBar->GetHWnd()) ) { m_bShowToolbar = FALSE; } else { m_bShowToolbar = TRUE; } pIToolBar->Show( m_bShowToolbar ); pIToolBar->Release(); } } void CMainFrame::OnHelpMenu() { CGenericFrame::OnHelpMenu(); } // // Toggle the starter bar // void CMainFrame::OnOptionsShowstarterbuttons() { } void CMainFrame::OnUpdateOptionsShowstarterbuttons(CCmdUI* pCmdUI) { } // Post a close message on the approprate system command, can't let // it handle or we GPF when closing the minimized main window. void CMainFrame::OnSysCommand(UINT nID, LPARAM lParam) { if(nID == SC_CLOSE) { PostMessage(WM_CLOSE); return; } CGenericFrame::OnSysCommand(nID, lParam); } // No meaning in generic frame windows? // The only possible thing to undo is typing in the URL/Location edit field void CMainFrame::OnUpdateEditUndo(CCmdUI* pCmdUI) { pCmdUI->Enable(FALSE); }