/* -*- 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. */ // netscape.cpp : Defines the class behaviors for the application. // #include "stdafx.h" #define XP_CPLUSPLUS // temporary hack - jsw // XP Includes #include "np.h" #include "cvffc.h" #include "prefapi.h" #ifdef XP_WIN32 #include "shcut.h" #endif #include "libevent.h" #include "wfemsg.h" // Misc Includes #include "res\appicon.h" #include "custom.h" #include "dialog.h" #include "ngdwtrst.h" #include "oleregis.h" #include "sysinfo.h" #include "timer.h" #include "winproto.h" #include "cmdparse.h" #include "ddecmd.h" #include "apiapi.h" #include "apipage.h" #include "logindg.h" #include "hiddenfr.h" #include "cxprint.h" #include "cxicon.h" #include "navfram.h" #include "secnav.h" #include "prefs.h" #include "nsIDefaultBrowser.h" #ifdef MOZ_OFFLINE #include "offlndlg.h" #endif /* MOZ_OFFLINE */ #include "pw_public.h" extern "C" { #include "cookies.h" }; #ifdef MOZ_LOC_INDEP #include "li_public.h" #endif /* MOZ_LOC_INDEP */ #ifdef MOZ_NGLAYOUT #include "nscore.h" #include "nsDebug.h" #include "prlink.h" #endif #ifdef _DEBUG #undef THIS_FILE static char BASED_CODE THIS_FILE[] = __FILE__; #endif #ifndef VER_PLATFORM_WIN32_WINDOWS #define VER_PLATFORM_WIN32_WINDOWS 1 #endif #ifdef __BORLANDC__ #define _mkdir mkdir #endif // Registry key constants static const CString strMARKUP_KEY = "NetscapeMarkup"; static const CString strOPEN_CMD_FMT = "%s\\shell\\open\\command"; static const CString strDDE_EXEC_FMT = "%s\\shell\\open\\ddeexec"; static const CString strDDE_APP_FMT = "%s\\shell\\open\\ddeexec\\Application"; static const CString strDDE_APP_NAME = "NSShell"; static const CString strDDE_OLDAPP_NAME = "Netscape"; static const CString strDEF_ICON_FMT = "%s\\DefaultIcon"; static const CString strDDE_EXEC_VALUE = "%1"; static const CString strDDE_TOPIC_FMT = "%s\\shell\\open\\ddeexec\\Topic"; static const CString strEDIT_CMD_FMT = "%s\\shell\\edit\\command"; // li_stuff static int LIActive = 0; #if defined( _DEBUG) && defined( XP_WIN32 ) int CNetscapeApp::InitConsoleWindow(void) { STARTUPINFO si = {0}; // initialize all members to zero si.cb = sizeof(STARTUPINFO); AllocConsole(); // get that console window freopen("CONOUT$", "a", stderr); // redirect stderr to console // Warn user fputs( "Netscape stderr output window\n" "DO NOT CLOSE THIS WINDOW, it will terminate Netscape\n", stderr); // launch command interpreter to keep window open return CreateProcess(NULL, // module name "cmd.exe", // gotta run something NULL, // process security attributes NULL, // thread security attributes TRUE, // process inherits handles CREATE_SUSPENDED, // creation flags NULL, // new environment NULL, // current directory &si, // &m_pi); // } #endif ///////////////////////////////////////////////////////////////////////////// // CNetscapeApp construction CNetscapeApp::CNetscapeApp() { // Initially allow UNC file access. m_bUNC = TRUE; // No slave context yet. m_pSlaveCX = NULL; m_pRDFCX = NULL; // Explicitly clear the idle binding to timeout code. m_bIdleProcessTimeouts = FALSE; // Not in init instance. m_bInInitInstance = FALSE; // Flag for frames created to use m_iFrameCmdShow m_bInGetCriticalFiles = FALSE; // Flag for frames created while getting early files // These are just HTML dialogs and need not have toolbars, etc m_iFrameCmdShow = -1; // No windows / frames or Hotlist yet m_bDontLoadHome = FALSE; m_pMainWnd = NULL; m_pUpdateWhatsNewWnd = NULL; m_pFrameList = NULL; m_pHiddenFrame = NULL; m_pBookmarks = NULL; m_pNetcasterWindow = NULL; m_iTemplateLocationCount = 0; pIconDC = pImageDC = NULL; m_ParentAppWindow = NULL; m_bChildWindow = FALSE; m_bParseTelnetURLs = FALSE; m_bNetworkProfile = FALSE; // no dialup stuff yet m_bKioskMode = FALSE; m_bSuperKioskMode = FALSE; #ifdef MOZ_MAIL_NEWS m_bCreateMail = FALSE; m_bCreateNews = FALSE; #endif /* MOZ_MAIL_NEWS */ m_bCreateNetcaster = FALSE; m_bCreateCalendar = FALSE; #ifdef MOZ_MAIL_NEWS m_bCreateInbox = FALSE;//causes the inbox to be started m_bCreateFolders = FALSE;//causes the folders frame window to be started m_bCreateFolder = FALSE;//causes a particular folder in the folders frame window to open m_bCreateCompose = FALSE;//causes the compose window to be opened, 3 different possibilities #endif /* MOZ_MAIL_NEWS */ #ifdef EDITOR m_bCreateEdit = FALSE;//brings up the edit window #endif /* EDITOR */ #ifdef MOZ_MAIL_NEWS m_bCreateAddress = FALSE;//openes the address book window #endif /* MOZ_MAIL_NEWS */ m_bCreateLDIF_IMPORT = FALSE;//imports an LDIF file m_bCreateLDIF_EXPORT = FALSE;//imports an LDIF file m_bCreateBrowser = FALSE;//forces the browser to launch despite preferences settings. m_bHasArguments = FALSE;//signals that switch parameters need parsing m_bAccountSetupStartupJava = FALSE; m_bCreateNewProfile = FALSE; m_bProfileManager = FALSE; m_bCreateJavaDebugAgent = FALSE; m_bAccountSetup = FALSE; m_bAlwaysDockTaskBar = FALSE; m_bShowNetscapeButton = FALSE; // No global java event queue yet... mozilla_event_queue = NULL; m_hPostalLib = NULL; m_fnOpenMailSession = NULL; m_fnComposeMailMessage = NULL; m_fnUnRegisterMailClient = NULL; m_fnShowMailBox = NULL; m_fnShowMessageCenter = NULL; m_fnCloseMailSession = NULL; m_fnGetMenuItemString = NULL; m_bInitMapi = TRUE; m_bExitStatus = FALSE; InitTime(); // Desktop integration preference stuff. m_bShowPrefsOnStartup = FALSE; #ifdef MOZ_MAIL_NEWS m_bCreateInboxMAPI = FALSE; // rhp - for MAPI m_bCreateNABWin = FALSE; // rhp - for Address Book API #endif /* MOZ_MAIL_NEWS */ #ifdef XP_WIN16 m_nMsgLast = WM_NULL; ::GetCursorPos(&m_ptCursorLast); #endif /* This is the very first TRACE call in the client. * If we want the output to work outside the debugger, * we must pass the output file handle to the C runtime debug * output routines. Note: "CONOUT$" is the name of "/dev/tty" */ #if defined( _DEBUG) && defined( XP_WIN32 ) m_pi.hProcess = 0; char * mozTraceFileName = getenv("MOZTRCFILE"); if (mozTraceFileName) { HANDLE hTraceFile = INVALID_HANDLE_VALUE; int success; if (!strcmp( "CONOUT$", mozTraceFileName)) { success = InitConsoleWindow(); } else { // This freopen doesn't work, so do it the hard way, use CreateFile. // success = (NULL != freopen(mozTraceFileName, "a", stderr)); hTraceFile = CreateFile( mozTraceFileName, /* GENERIC_READ | */ GENERIC_WRITE, /* FILE_SHARE_READ | */ FILE_SHARE_WRITE, NULL, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL /* | FILE_FLAG_WRITE_THROUGH */, NULL); success = (hTraceFile != INVALID_HANDLE_VALUE); if (success) { SetStdHandle(STD_ERROR_HANDLE, hTraceFile); } } if (success) { _CrtSetReportFile(_CRT_WARN, _CRTDBG_FILE_STDERR); _CrtSetReportMode(_CRT_WARN, _CRTDBG_MODE_FILE); } else { LPVOID lpMsgBuf; DWORD lastErr = GetLastError(); FormatMessage( FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM, NULL, lastErr, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language (LPTSTR) &lpMsgBuf, 0, NULL ); // Display the string. MessageBox( NULL, (char *)lpMsgBuf, "Create trace file", MB_OK|MB_ICONINFORMATION ); // Free the buffer. LocalFree( lpMsgBuf ); } } #endif TRACE("Netscape App Constructor! \n"); } void CNetscapeApp::InitTime() { m_ttStartTime = ::time(NULL); m_dwLastMsgTick = m_dwStartTick = m_dwMsgTick = ::GetTickCount(); } BOOL CNetscapeApp::LoadPageSetupOptions() { ApiPageSetup(api,0); api->SetMargins ( (long) GetProfileInt ( "Page Setup", "Left", 720 ), (long) GetProfileInt ( "Page Setup", "Right", 720 ), (long) GetProfileInt ( "Page Setup", "Top", 720 ), (long) GetProfileInt ( "Page Setup", "Bottom", 720 ) ); api->Header ( GetProfileInt ( "Page Setup", "Header", PRINT_TITLE | PRINT_URL ) ); api->Footer ( GetProfileInt ( "Page Setup","Footer", PRINT_PAGECOUNT | PRINT_PAGENO | PRINT_DATE ) ); api->SolidLines ( GetProfileInt ( "Page Setup", "SolidLines", 0 ) ); api->BlackLines ( GetProfileInt ( "Page Setup", "BlackLines", 0 ) ); api->BlackText ( GetProfileInt ( "Page Setup", "BlackText", 0 ) ); api->ReverseOrder ( GetProfileInt ( "Page Setup", "Reverse", 0 ) ); return TRUE; } void CNetscapeApp::SavePageSetupOptions() { ApiPageSetup(api,0); long mleft, mright, mtop, mbottom; // save margins api->GetMargins ( &mleft, &mright, &mtop, &mbottom ); theApp.WriteProfileInt ( "Page Setup", "left", LOWORD(mleft) ); theApp.WriteProfileInt ( "Page Setup", "right", LOWORD(mright) ); theApp.WriteProfileInt ( "Page Setup", "top", LOWORD(mtop) ); theApp.WriteProfileInt ( "Page Setup", "bottom",LOWORD(mbottom) ); // save miscellaneous page setup flags theApp.WriteProfileInt ( "Page Setup", "Header", api->Header ( ) ); theApp.WriteProfileInt ( "Page Setup", "Footer", api->Footer ( ) ); theApp.WriteProfileInt ( "Page Setup", "SolidLines", api->SolidLines ( ) ); theApp.WriteProfileInt ( "Page Setup", "BlackText", api->BlackText ( ) ); theApp.WriteProfileInt ( "Page Setup", "BlackLines", api->BlackLines ( ) ); theApp.WriteProfileInt ( "Page Setup", "Reverse", api->ReverseOrder ( ) ); } // // Parse the command line for INI file location and home page // void CNetscapeApp::parseCommandLine(char * commandLine) { // assume no startup URL or profile m_CmdLineLoadURL = NULL; m_CmdLineProfile = NULL; if(IsRuntimeSwitch("-P",FALSE)) { // extract the quoted profile name..the format is -P"jonm@netscape.com" CString csCommandLine = commandLine; int iFirstQuote = csCommandLine.Find("-P\""); if( iFirstQuote != -1 ){ iFirstQuote += 2; csCommandLine = csCommandLine.Mid(iFirstQuote+1); int iLastQuote = csCommandLine.Find('\"'); if( iLastQuote == -1 ){ // No last quote -- remove first quote from command line strcpy( (commandLine+iFirstQuote), (commandLine+iFirstQuote+1)); } else { m_CmdLineProfile = XP_STRDUP(csCommandLine.Left(iLastQuote)); // Remove the extracted string from command line strcpy( (commandLine+iFirstQuote), (commandLine+iFirstQuote+iLastQuote+2)); } IsRuntimeSwitch("-P",TRUE); // now remove the -P from the command line } } // Extract a filepath enclosed in quotes // MUST have both quotes, or we ignore it and strip away the first quote CString csCommandLine = commandLine; int iFirstQuote = csCommandLine.Find('\"'); if( iFirstQuote != -1 ){ csCommandLine = csCommandLine.Mid(iFirstQuote+1); int iLastQuote = csCommandLine.Find('\"'); if( iLastQuote == -1 ){ // No last quote -- remove first quote from command line strcpy( (commandLine+iFirstQuote), (commandLine+iFirstQuote+1)); } else { m_CmdLineLoadURL = XP_STRDUP(csCommandLine.Left(iLastQuote)); // Remove the extracted string from command line strcpy( (commandLine+iFirstQuote), (commandLine+iFirstQuote+iLastQuote+2)); } } // Need way to track if used command line -i switch. // BOOL bIniOption = FALSE; // Check for the INI file location. CString csINI; CString csParentHwnd; // kiosk mode if(IsRuntimeSwitch("-k", TRUE)) m_bKioskMode = TRUE; // super kiosk mode if(IsRuntimeSwitch("-sk", TRUE)) { m_bKioskMode = TRUE; m_bSuperKioskMode = TRUE; } // load home page? if(IsRuntimeSwitch("-H", TRUE)) m_bDontLoadHome = TRUE; #ifdef MOZ_MAIL_NEWS if(IsRuntimeSwitch("-mail",TRUE)) m_bCreateMail = TRUE; #endif /* MOZ_MAIL_NEWS */ if(IsRuntimeSwitch("-netcaster",TRUE)) m_bCreateNetcaster = TRUE; #ifdef MOZ_MAIL_NEWS if(IsRuntimeSwitch("-news",TRUE)) m_bCreateNews = TRUE; #endif /* MOZ_MAIL_NEWS */ if(IsRuntimeSwitch("-calendar",TRUE)) m_bCreateCalendar = TRUE; if(IsRuntimeSwitch("-new_profile",TRUE)) m_bCreateNewProfile = TRUE; if(IsRuntimeSwitch("-profile_manager",TRUE)) m_bProfileManager = TRUE; if (IsRuntimeSwitch("-parse_telnet")) m_bParseTelnetURLs = TRUE; #if defined(OJI) || defined(JAVA) if(IsRuntimeSwitch("-javadebug",TRUE)) { m_bCreateJavaDebugAgent = TRUE; } #endif //This is a rather hideous hack to allow Navigator as a child window. //It is turned off until such time as it is deemed safe and absolutely necessary. /*if(IsRuntimeSwitch("-child",FALSE)) { csParentHwnd = RuntimeStringSwitch("-child"); sscanf(csParentHwnd, "%x", &m_ParentAppWindow); } */ if(IsRuntimeSwitch("-new_account",TRUE)){ m_bAccountSetup = TRUE; m_bAlwaysDockTaskBar = TRUE; m_bAccountSetupStartupJava = TRUE; } if(IsRuntimeSwitch("-start_java",TRUE)) m_bAccountSetupStartupJava = TRUE; // do *NOT* let /I be a run time switch because IsRuntimeSwitch // is currently not smart enough to deal with http://foo/index.html // correctly if(IsRuntimeSwitch("-I", FALSE)) { csINI = RuntimeStringSwitch("-I"); } #ifdef XP_WIN16 if(csINI.IsEmpty() == FALSE) { // Make sure it's a good location. if(FEU_SanityCheckFile(csINI) == FALSE) { MessageBox(NULL, szLoadString(IDS_INVALID_INIFILE), szLoadString(AFX_IDS_APP_TITLE), MB_OK); } else { // This is our new INI file theApp.m_pszProfileName = (const char *)XP_STRDUP(csINI); bIniOption = TRUE; } } #endif #ifdef EDITOR // This is used to tst for edit startup and // is only TRUE if we are a Gold version m_bCmdEdit = FALSE; CString csEditFile; // Look for Start-Editor switch if(IsRuntimeSwitch("-EDIT",FALSE)) { csEditFile = RuntimeStringSwitch("-EDIT"); m_bCmdEdit = TRUE; } if ( m_bCmdEdit ) { // Copy the returnd string back to the command line XP_STRCPY( commandLine, LPCSTR(csEditFile) ); } #endif // EDITOR // Pointer into command line as we parse it // char *curLoc = m_lpCmdLine; // Skip the white space. while(curLoc && *curLoc != '\0' && isspace(*curLoc)) curLoc++; if( m_CmdLineLoadURL == NULL ){ // still stuff left --- assume its a file to load. // if someone dragged a file onto us this will be a DOS path // when we get around to calling OnNormalLoad() to actually // load the page it will get interpreted correctly. if(curLoc && *curLoc) { // if first char is a double quote don't copy it over if(curLoc[0] == '\"') m_CmdLineLoadURL = XP_STRDUP(&(curLoc[1])); else m_CmdLineLoadURL = XP_STRDUP(curLoc); // Win9x conveniently brackets the filename in double quotes // convert them to spaces and let the netlib strip them out for(char * c = m_CmdLineLoadURL; c && *c; c++) if(*c == '\"') *c = ' '; } } #ifdef XP_WIN16 // If they didn't use the command line -i to specify // the location of the INI file, attempt to use // the location specified in the win.ini file. // Scope the function call correctly or you will get // the wrong information. // The return buffer will never be empty. // // Revised: // Order of INI preference is as follows: // command line // win.ini // current directory // windows directory // After resolution from win.ini down, then make // sure the the win.ini file actually contains // the correct reference; otherwise replace it. // if(!bIniOption) { const char *cp_NotInIni = "Garrett 'Archibald Cox' Blythe"; const char *cp_WinIniSection = XP_STRDUP(szLoadString(IDS_WIN_INI_SECTION)); const char *cp_IniFile = XP_STRDUP(szLoadString(IDS_INI_FILE_NAME)); const char *cp_WinIniEntry = "ini"; // Figure out the app's path for the default value. // Tack on netscape.ini on the end. // auto char ca_default[_MAX_PATH]; ::GetModuleFileName(m_hInstance, ca_default, _MAX_PATH); auto char *cp_lastslash = ::strrchr(ca_default, '\\') + 1; ::strcpy(cp_lastslash, cp_IniFile); // Check the win.ini file for an entry pointing to the ini file. // auto char ca_iniBuff[_MAX_PATH]; ::GetProfileString(cp_WinIniSection, cp_WinIniEntry, cp_NotInIni, ca_iniBuff, _MAX_PATH); // If it isn't located in the ini file, set a flag, // and copy over a default file name. // auto int i_UpdateWinIni = FALSE; if(::strcmp(cp_NotInIni, ca_iniBuff) == 0) { i_UpdateWinIni = TRUE; ::strcpy(ca_iniBuff, ca_default); } m_pszProfileName = (const char *)XP_STRDUP(ca_iniBuff); // Does it exist? // if(FEU_SanityCheckFile(m_pszProfileName) == FALSE) { // Well, shoot. // Attempt to use the windows directory for the INI file. // char ca_windir[_MAX_PATH]; ::GetWindowsDirectory(ca_windir, _MAX_PATH); if(ca_windir[::strlen(ca_windir) - 1] != '\\') { ::strcat(ca_windir, "\\"); } ::strcat(ca_windir, cp_IniFile); if(FEU_SanityCheckFile(ca_windir) == FALSE) { // Unable to locate any INI file. // We are going to use the original default, because // we know the directory exists. // Update the win.ini file regardless; there is no good location anyhow. // XP_FREE((void *)m_pszProfileName); m_pszProfileName = (const char *)XP_STRDUP(ca_default); i_UpdateWinIni = TRUE; } else { // Use INI in windows directory. // XP_FREE((void *)m_pszProfileName); m_pszProfileName = (const char *)XP_STRDUP(ca_windir); // Add this to the win.ini file to avoid confusion // in the future. // i_UpdateWinIni = TRUE; } } // Update the win.ini file if need be. // if(i_UpdateWinIni == TRUE) ::WriteProfileString(cp_WinIniSection, cp_WinIniEntry, m_pszProfileName); } #endif // XP_WIN16 } // CNetscapeApp::parseCommandLine /**************************************************************************** * * CNetscapeApp::CheckDefaultBrowser * * PARAMETERS: * none * * RETURNS: * void * * DESCRIPTION: * This function checks the registry to see if we are still registered * as the "default browser" (listed under http key and other extensions), * since the MS Explorer has a nasty habit of kicking us out! If not, * we prompt the user to restore our registry settings and make us * the default again. * ****************************************************************************/ void CNetscapeApp::CheckDefaultBrowser() { // We're only worrying about this for Win32 #ifdef XP_WIN32 XP_Bool prefBool = FALSE; PREF_GetBoolPref("browser.wfe.ignore_def_check",&prefBool); if ( !prefBool ) { MakeDefaultBrowser(); } #endif // XP_WIN32 } // END OF FUNCTION CNetscapeApp::CheckDefaultBrowser() void CNetscapeApp::MakeDefaultBrowser() { #ifdef XP_WIN32 // Create IDefaultBrowser interface. nsIDefaultBrowser *pDefaultBrowser = nsIDefaultBrowser::GetInterface(); if ( pDefaultBrowser ) { // Ask if "default browser" dialog is required and display it if so. if ( !pDefaultBrowser->IsDefaultBrowser() ) { if ( pDefaultBrowser->DisplayDialog() == IDC_SHOW_DESKTOP_PREFS ) { theApp.m_splash.ShowWindow(SW_HIDE); wfe_DisplayPreferences(NULL); } } pDefaultBrowser->Release(); } #endif // XP_WIN32 } int CNetscapeApp::RuntimeIntSwitch(const char *pSwitch) { int iRetval = -1; // Search for the switch in the command line. char *pFound = strcasestr(m_lpCmdLine, pSwitch); if(pFound == NULL) { return(iRetval); } // Okay, found it. Now, go beyond it, and return the value following as an int. char *pStart = pFound; pFound += strlen(pSwitch); while(isspace(*pFound)) { pFound++; } sscanf(pFound, "%d", &iRetval); // Take the entire thing out of the command line. while(FALSE == isspace(*pFound) && *pFound != '\0') { pFound++; } char *pTravEnd = pFound; char *pTraverse = pStart; *pTraverse = *pTravEnd; while(*pTraverse != '\0') { pTraverse++; pTravEnd++; *pTraverse = *pTravEnd; } return(iRetval); } static BOOL IsCommand( const char *pszCmdLine, const char *pszOffset, const char *pszSwitch ) { // // Let's be somewhat smart and make sure this is really a command and not e.g., /netscape/stuff.html // For now we just ensure the command is sandwiched between spaces e.g., "netscape.exe / /somewhere/doc.html" // if( *pszOffset != '/' ) { return TRUE; } if( pszOffset != pszCmdLine ) { if( !isspace( *(pszOffset-1) ) ) { // Must have a preceding space if not the beginning of the cmd line return FALSE; } } if( !isspace( *(pszOffset + _tcslen( pszSwitch )) ) ) { // Must have a traling space return FALSE; } return TRUE; } CString CNetscapeApp::RuntimeStringSwitch(const char *pSwitch, BOOL bCheckCommand) { CString csRetval; // Search for the switch in the command line. char *pFound = strcasestr(m_lpCmdLine, pSwitch); // Don't attempt to be smart about the command if asked not to be, as the // command detector is not smart about complex switches like /printto // being detected by /print. if( !pFound || (bCheckCommand && !IsCommand( m_lpCmdLine, pFound, pSwitch )) ) { return csRetval; } // Okay, found it. Now, go beyond it, and return the value following as a string. char *pStart = pFound; pFound += strlen(pSwitch); while(isspace(*pFound)) { pFound++; } // Take the entire thing out of the command line. // Respect quotes (spaces allowed inside of quotes). BOOL bQuote = FALSE; while((!isspace(*pFound) || bQuote) && *pFound != '\0') { if(*pFound == '\"') { if(bQuote) { bQuote = FALSE; } else { bQuote = TRUE; } } csRetval += *pFound; pFound++; } char *pTravEnd = pFound; char *pTraverse = pStart; // OK, so pTraverse points to the first character of the command line switch // and pTravEnd points to the first character after the string part of the // command. While there are bits of command line left copy them over while(*pTravEnd != '\0') { *pTraverse++ = *pTravEnd++; } // Make sure we are NULL terminated *pTraverse = '\0'; return(csRetval); } BOOL CNetscapeApp::IsRuntimeSwitch(const char *pSwitch, BOOL bRemove) { // Search for the switch in the command line. // Don't take it out by default char *pFound = strcasestr(m_lpCmdLine, pSwitch); if(pFound == NULL || // Switch must be at beginning of command line // or have a space in front of it to avoid // mangling filenames ( (pFound != m_lpCmdLine) && *(pFound-1) != ' ' ) ) { return(FALSE); } if (bRemove) { // remove the flag from the command line char *pTravEnd = pFound + strlen(pSwitch); char *pTraverse = pFound; *pTraverse = *pTravEnd; while(*pTraverse != '\0') { pTraverse++; pTravEnd++; *pTraverse = *pTravEnd; } } return(TRUE); } BOOL CNetscapeApp::IsRuntimeSwitch(const char *pSwitch, char *pszCommandLine, BOOL bRemove) { // Search for the switch in the command line. // Don't take it out by default char *pFound = strcasestr(pszCommandLine, pSwitch); if(pFound == NULL || // Switch must be at beginning of command line // or have a space in front of it to avoid // mangling filenames ( (pFound != pszCommandLine) && *(pFound-1) != ' ' ) ) { return(FALSE); } if (bRemove) { // remove the flag from the command line char *pTravEnd = pFound + strlen(pSwitch); char *pTraverse = pFound; *pTraverse = *pTravEnd; while(*pTraverse != '\0') { pTraverse++; pTravEnd++; *pTraverse = *pTravEnd; } } return(TRUE); } void CNetscapeApp::StoreVersionInReg() { // Figure out the versioning information about the binary. CString csVersion; char *tmpBuf; char *ptr = NULL; csVersion = ResolveShortAppVersion(); // we need to replace square brackets with parens to store into ini file tmpBuf = (char *)XP_ALLOC(csVersion.GetLength() + 1); strcpy(tmpBuf,csVersion); // point to start ptr = tmpBuf; while (ptr && *ptr) { if (*ptr == '[') *ptr = '('; if (*ptr == ']') *ptr = ')'; ptr++; } long result; #ifdef XP_WIN32 HKEY hKeyRet = NULL; CString csSub = "SOFTWARE\\Netscape\\Netscape Navigator\\"; result = RegOpenKeyEx(HKEY_LOCAL_MACHINE, csSub, NULL, KEY_SET_VALUE, &hKeyRet); if (result == ERROR_SUCCESS) { RegSetValueEx(hKeyRet,"CurrentVersion",NULL,REG_SZ,(const BYTE *)tmpBuf,strlen(tmpBuf)+1); RegCloseKey(hKeyRet); } #else CString csNSCPini; login_GetIniFilePath(csNSCPini); result = ::WritePrivateProfileString("Netscape Navigator", "CurrentVersion", tmpBuf ,csNSCPini); #endif if (tmpBuf) XP_FREE(tmpBuf); return; } CString CNetscapeApp::ResolveShortAppVersion() { // Figure out the versioning information about the binary. CString csVersion; char *tmpversionBuf; tmpversionBuf = (char *)XP_ALLOC(15); //Loading from netscape.exe instead of resdll.dll since the string has been moved #109455 LoadString(::AfxGetInstanceHandle(), IDS_APP_VERSION, tmpversionBuf, 15); csVersion = tmpversionBuf; csVersion += " ["; csVersion += XP_AppLanguage; csVersion += "]"; if (tmpversionBuf) XP_FREE(tmpversionBuf); return csVersion; } CString CNetscapeApp::ResolveAppVersion() { // Figure out the versioning information about the binary. CString csVersion; csVersion = ResolveShortAppVersion(); // Start building the return value. // Version and Platform. BOOL bShowBuildBits = FALSE; CString csReturn; csReturn += csVersion; char *pCustAgent = NULL; int iError = PREF_CopyConfigString("user_agent",&pCustAgent); if (PREF_ERROR != iError && pCustAgent) { if (*pCustAgent) { csReturn += "C-"; csReturn += pCustAgent; csReturn += ' '; } XP_FREE(pCustAgent); } csReturn += " (Win"; if(sysInfo.m_bWin16 == TRUE) { if(sysInfo.m_bWin32s == TRUE) { csReturn += "32s"; bShowBuildBits = TRUE; } else if(sysInfo.m_bWinNT == TRUE) { csReturn += "NT"; bShowBuildBits = TRUE; } else if(sysInfo.m_bWin4 == TRUE) { csReturn += "95"; bShowBuildBits = TRUE; } else { csReturn += "16"; } } else if(sysInfo.m_bWin32 == TRUE) { if(sysInfo.m_bWin32s == TRUE) { csReturn += "32s"; bShowBuildBits = TRUE; } else if(sysInfo.m_bWinNT == TRUE) { csReturn += "NT"; if(sysInfo.m_dwMajor > 4) { csReturn += (char)('0' + sysInfo.m_dwMajor); } } else if(sysInfo.m_bWin4 == TRUE) { if(sysInfo.m_dwMinor >= 10) { csReturn += "98"; } else { csReturn += "95"; } } else { TRACE("What OS are you on anyhow?\n"); csReturn += "dows"; bShowBuildBits = TRUE; ASSERT(0); } } else { TRACE("What OS are you on anyhow?\n"); csReturn += "dows"; bShowBuildBits = TRUE; ASSERT(0); } csReturn += "; "; // Security. csReturn += SECNAV_SecurityVersion(PR_FALSE); // Only show the build bits if the OS is ambiguous. if(bShowBuildBits == TRUE) { csReturn += "; "; // Build type. #if defined(WIN32) || defined(__WIN32__) csReturn += "32bit"; #else csReturn += "16bit"; #endif } #ifndef MOZ_COMMUNICATOR_NAME csReturn += " ;Nav"; #endif /* MOZ_COMMUNICATOR_NAME */ csReturn += ")"; return(csReturn); } // // Overload GetProfileString to get out of the registry if we are a Win32 // application // CString CNetscapeApp::GetProfileString(LPCTSTR lpszSection, LPCTSTR lpszEntry, LPCTSTR lpszDefault) { #ifdef XP_WIN16 return(CWinApp::GetProfileString(lpszSection, lpszEntry, lpszDefault)); #else HKEY hKey; long result; DWORD type, size; char buffer[255]; char * pString; static CString csStr; sprintf(buffer, "Software\\%s\\%s\\%s", "Netscape", "Netscape Navigator", lpszSection); csStr = lpszDefault; // get a pointer to this entry result = RegOpenKeyEx(HKEY_CURRENT_USER, buffer, NULL, KEY_QUERY_VALUE, &hKey); if(result != ERROR_SUCCESS) return(csStr); // see how much space we need size = 0; result = RegQueryValueEx(hKey, (char *) lpszEntry, NULL, &type, NULL, &size); // if we didn't find it just use the default if((result != ERROR_SUCCESS) || (size == 0)) { RegCloseKey(hKey); return(csStr); } // allocate space to hold the string pString = (char *) XP_ALLOC(size * sizeof(char)); // actually load the string now that we have the space result = RegQueryValueEx(hKey, (char *) lpszEntry, NULL, &type, (LPBYTE) pString, &size); // use default id something went wrong this time if(result == ERROR_SUCCESS) csStr = pString; XP_FREE(pString); RegCloseKey(hKey); return(csStr); #endif } // // Overload GetProfileInt to get out of the registry if we are a Win32 // application // UINT CNetscapeApp::GetProfileInt(LPCTSTR lpszSection, LPCTSTR lpszEntry, int nDefault) { #ifdef XP_WIN16 return(CWinApp::GetProfileInt(lpszSection, lpszEntry, nDefault)); #else HKEY hKey; long result; DWORD type, size; char buffer[255]; sprintf(buffer, "Software\\%s\\%s\\%s", "Netscape", "Netscape Navigator", lpszSection); result = RegOpenKeyEx(HKEY_CURRENT_USER, buffer, NULL, KEY_QUERY_VALUE, &hKey); // use default if something went wrong this time if(result != ERROR_SUCCESS) return(nDefault); int value; size = sizeof(int); result = RegQueryValueEx(hKey, (char *) lpszEntry, NULL, &type, (LPBYTE) &value, &size); RegCloseKey(hKey); // use default if something went wrong this time if(result != ERROR_SUCCESS) return(nDefault); return(value); #endif } // // Overload WriteProfileString to write to the registry if we are a Win32 // application // BOOL CNetscapeApp::WriteProfileString(LPCTSTR lpszSection, LPCTSTR lpszEntry, LPCTSTR lpszValue) { #ifdef XP_WIN16 return(CWinApp::WriteProfileString(lpszSection, lpszEntry, lpszValue)); #else HKEY hKey; DWORD dwDisposition; long result; char buffer[255]; if (lpszValue == NULL) { sprintf(buffer, "Software\\%s\\%s\\%s", "Netscape", "Netscape Navigator", lpszSection); // Open the key to the section result = RegOpenKeyEx(HKEY_CURRENT_USER, buffer, NULL, KEY_WRITE, &hKey); if (result == ERROR_SUCCESS) { // Delete the value ::RegDeleteValue(hKey, lpszEntry); // Close the key ::RegCloseKey(hKey); } return TRUE; } // The MSDN CD sez RegSetValueEx() should create the key if it // doesn't exist but it doesn't seem to be respecting hierarchies sprintf(buffer, "Software\\%s\\%s\\%s", "Netscape", "Netscape Navigator", lpszSection); result = RegCreateKeyEx(HKEY_CURRENT_USER, buffer, NULL, NULL, NULL, KEY_ALL_ACCESS, NULL, &hKey, &dwDisposition); if(result != ERROR_SUCCESS) return(0); result = RegSetValueEx(hKey, lpszEntry, NULL, REG_SZ, (LPBYTE) lpszValue, XP_STRLEN(lpszValue) + 1); RegCloseKey(hKey); return(result == ERROR_SUCCESS); #endif } // // Overload WriteProfileInt to write to the registry if we are a Win32 // application // BOOL CNetscapeApp::WriteProfileInt(LPCTSTR lpszSection, LPCTSTR lpszEntry, int nValue) { #ifdef XP_WIN16 return(CWinApp::WriteProfileInt(lpszSection, lpszEntry, nValue)); #else HKEY hKey; DWORD dwDisposition; long result; char buffer[255]; // The MSDN CD sez RegSetValueEx() should create the key if it // doesn't exist but it doesn't seem to be respecting hierarchies sprintf(buffer, "Software\\%s\\%s\\%s", "Netscape", "Netscape Navigator", lpszSection); result = RegCreateKeyEx(HKEY_CURRENT_USER, buffer, NULL, NULL, NULL, KEY_ALL_ACCESS, NULL, &hKey, &dwDisposition); if(result != ERROR_SUCCESS) return(0); result = RegSetValueEx(hKey, lpszEntry, NULL, REG_DWORD, (LPBYTE) &nValue, sizeof(int)); RegCloseKey(hKey); return(result == ERROR_SUCCESS); #endif } DWORD CNetscapeApp::GetPrivateProfileString(LPCSTR lpSectionName, LPCSTR lpKeyName, LPCSTR lpDefault, LPSTR lpReturnedString, DWORD nSize, LPCSTR lpFileName) { #ifdef XP_WIN16 return((DWORD) ::GetPrivateProfileString(lpSectionName, lpKeyName, lpDefault, lpReturnedString, CASTINT(nSize), lpFileName)); #else // For safty, automatically copy two nulls into the return value. // This will ensure any code looking into this string will fail. *lpReturnedString = *(lpReturnedString + 1) = '\0'; // We don't handle empty sections! // However, we could with a little code. if(lpSectionName == NULL) { ASSERT(0); return(0); } // See if we're getting a full section, or just one specific key. if(lpKeyName != NULL) { // Name value pair requested. CString csValue = GetProfileString(lpSectionName, lpKeyName, lpDefault); if(csValue.IsEmpty() == TRUE) { return(0); } // Copy over the string. strncpy(lpReturnedString, csValue, nSize); // End the string manually (might not have appended NULL). *(lpReturnedString + nSize - 1) = '\0'; // Return the length. return(strlen(lpReturnedString)); } // Create the appropriate key. // We'll need to enumerate over everything. HKEY hKey; DWORD dwDisposition; char aBuffer[256]; sprintf(aBuffer, "Software\\%s\\%s\\%s", "Netscape", "Netscape Navigator", lpSectionName); long lResult = RegCreateKeyEx(HKEY_CURRENT_USER, aBuffer, NULL, NULL, NULL, KEY_ALL_ACCESS, NULL, &hKey, &dwDisposition); if(lResult != ERROR_SUCCESS) { return(0); } // Enumerate everything. // We stick all values into the same string. // Each is followed by a '\0'. // The final one is followed by '\0''\0'. // Be careful not to overrun the buffer size. char *pTraverse = lpReturnedString; char *pValue = new char[2048]; char *pTraverseValue; DWORD dwValueSize; for(int iIndex = 0; 1; iIndex++) { dwValueSize = 2048; if(RegEnumValue(hKey, iIndex, pValue, &dwValueSize, NULL, NULL, NULL, NULL) != ERROR_SUCCESS) { // No more indexes/values left. break; } // Copy this into the return value. pTraverseValue = pValue; while((DWORD)(pTraverse - lpReturnedString) != nSize) { *pTraverse = *pTraverseValue; pTraverse++; if(*pTraverseValue == '\0') { break; } pTraverseValue++; } // Check to see if we're at the end of the rope. if((DWORD)(pTraverse - lpReturnedString) == nSize) { // Need to set the final two chars to NULL. pTraverse -= 2; *pTraverse = '\0'; pTraverse++; *pTraverse = '\0'; pTraverse++; break; } } // Done with the buffer and Key. delete[] pValue; RegCloseKey(hKey); // Now, we make sure we have two NULLs at the end of the string. if(pTraverse == lpReturnedString) { // We didn't do squat. // Increment this so that the return value is correct. pTraverse += 2; } else if((DWORD)(pTraverse - lpReturnedString) != nSize) { *pTraverse = '\0'; pTraverse++; } // Return the number of chars copied over. return((DWORD)(pTraverse - lpReturnedString) - 2); #endif } // // This method re-implements the CWnd::SendMessageToDescendants() BUT // only notifies permanent MFC windows... // void PASCAL CNetscapeApp::SendMessageToDescendants(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) { // walk through HWNDs to avoid creating temporary CWnd objects // unless we need to call this function recursively for (HWND hWndChild = ::GetTopWindow(hWnd); hWndChild != NULL; hWndChild = ::GetNextWindow(hWndChild, GW_HWNDNEXT)) { // Don't send to non-permanent windows CWnd* pWnd = CWnd::FromHandlePermanent(hWndChild); if (pWnd != NULL) { // call window proc directly since it is a C++ window #ifdef XP_WIN32 AfxCallWndProc(pWnd, pWnd->m_hWnd, message, wParam, lParam); #else _AfxCallWndProc(pWnd, pWnd->m_hWnd, message, wParam, lParam); #endif if ( ::GetTopWindow(hWndChild) != NULL) { // Only recurse if current window is MFC CNetscapeApp::SendMessageToDescendants(hWndChild, message, wParam, lParam); } } } } int CNetscapeApp::MessageBox(HWND hWnd, LPCSTR lpszText, LPCSTR lpszCaption /* = NULL */, UINT nType /* = MB_OK */) { if (lpszCaption == NULL) lpszCaption = AfxGetAppName(); m_splash.ShowWindow(SW_HIDE); int result = ::MessageBox(hWnd, lpszText, lpszCaption, nType); m_splash.ShowWindow(SW_SHOW); m_splash.UpdateWindow(); return result; } // Register misc shell extensions supported. void CNetscapeApp::EnableShellStuff() { char aPath[_MAX_PATH]; if(::GetModuleFileName(m_hInstance, aPath, _MAX_PATH)) { #ifdef XP_WIN32 // should use short file name. char aShortPath[_MAX_PATH + 1]; if(::GetShortPathName(aPath, aShortPath, sizeof(aShortPath))) { strcpy(aPath, aShortPath); } #endif CString csMunge; // The Print Command. csMunge = aPath; csMunge += " /print(\"%1\")"; FEU_RegistryWizard(HKEY_CLASSES_ROOT, "NetscapeMarkup\\shell\\print\\command", csMunge); FEU_RegistryWizard(HKEY_CLASSES_ROOT, "NetscapeMarkup\\shell\\print\\ddeexec", "[print(\"%1\")]"); FEU_RegistryWizard(HKEY_CLASSES_ROOT, "NetscapeMarkup\\shell\\print\\ddeexec\\Application", strDDE_APP_NAME); // The PrintTo Command. csMunge = aPath; csMunge += " /printto(\"%1\",\"%2\",\"%3\",\"%4\")"; FEU_RegistryWizard(HKEY_CLASSES_ROOT, "NetscapeMarkup\\shell\\PrintTo\\command", csMunge); FEU_RegistryWizard(HKEY_CLASSES_ROOT, "NetscapeMarkup\\shell\\PrintTo\\ddeexec", "[printto(\"%1\",\"%2\",\"%3\",\"%4\")]"); FEU_RegistryWizard(HKEY_CLASSES_ROOT, "NetscapeMarkup\\shell\\PrintTo\\ddeexec\\Application", strDDE_APP_NAME); } } ///////////////////////////////////////////////////////////////////////////// // Exit the whole application void CNetscapeApp::OnAppSuperExit() { // Dont ask user. CommonAppExit(); } void CNetscapeApp::OnAppExit() { int iExit = IDOK; #ifdef MOZ_OFFLINE // Check prompt synchronization preference. If set bring up // prompt otherwise, bring up regular dialog. XP_Bool promptSynch = TRUE; PREF_GetBoolPref("offline.prompt_synch_on_exit", &promptSynch); if(promptSynch) { CAskSynchronizeExitDlg synchPromptDlg; iExit = synchPromptDlg.DoModal(); // false alarm, user didn't really want to exit if(iExit == IDCANCEL) { return; } else if(iExit == IDYES) { if(CanCloseAllFrames()) { m_bSynchronizingExit = TRUE; WFE_Synchronize(NULL, TRUE); } return; } } else { #endif /* MOZ_OFFLINE */ // if more than one top level window prompt to make sure they // want to exit if(m_pFrameList && m_pFrameList->m_pNext){ iExit = ::MessageBox(NULL, szLoadString(IDS_CLOSEWINDOWS_EXIT), szLoadString(IDS_EXIT_CONFIRMATION), MB_ICONQUESTION | MB_YESNO | MB_DEFBUTTON2); // false alarm, user didn't really want to exit if(IDNO == iExit) return; } #ifdef MOZ_OFFLINE } #endif /* MOZ_OFFLINE */ CommonAppExit(); } void CNetscapeApp::CommonAppExit() { // Make sure each frame window really does want to close for (CGenericFrame *pFrame = m_pFrameList; NULL != pFrame; pFrame = pFrame->m_pNext) { CDocument* pDocument = pFrame->GetActiveDocument(); } #ifdef MOZ_OFFLINE //if we are synchronizing on exit then we've already checked this. if(!m_bSynchronizingExit) { #endif /* MOZ_OFFLINE */ // Make sure each frame window really does want to close for (pFrame = m_pFrameList; NULL != pFrame; pFrame = pFrame->m_pNext) { CDocument* pDocument = pFrame->GetActiveDocument(); if (pDocument && !pDocument->CanCloseFrame(pFrame)) { // Document doesn't want to close so don't close any of the frames // Clear the flags previously set // so we prompt to save edit changes next time we try to close CGenericFrame *pCurrentFrame = pFrame; for (pFrame = m_pFrameList; pCurrentFrame != pFrame; pFrame = pFrame->m_pNext) { pFrame->m_bSkipSaveEditChanges = FALSE; } // We aren't going to close -- get out! return; } // Set flag to prevent prompting for saving edit changes // in CEditFrame::OnClose() since this was done in CanCloseFrame() pFrame->m_bSkipSaveEditChanges = TRUE; } #ifdef MOZ_OFFLINE } #endif /* MOZ_OFFLINE */ // Set wether or not the app is exiting. m_bExit = TRUE; #ifdef MOZ_MAIL_NEWS WFE_MSGSearchClose(); #endif /* MOZ_MAIL_NEWS */ // Go through each frame, closing it.... CGenericFrame *pNext = NULL; for(pFrame = m_pFrameList; NULL != pFrame; pFrame = pNext) { // Extract the frame from the list. pNext = pFrame->m_pNext; pFrame->PostMessage(WM_CLOSE); } } #ifdef MOZ_OFFLINE BOOL CNetscapeApp::CanCloseAllFrames() { for (CGenericFrame *pFrame = m_pFrameList; NULL != pFrame; pFrame = pFrame->m_pNext) { CDocument* pDocument = pFrame->GetActiveDocument(); if (pDocument && !pDocument->CanCloseFrame(pFrame)) { // Document doesn't want to close so don't close any of the frames // Clear the flags previously set // so we prompt to save edit changes next time we try to close CGenericFrame *pCurrentFrame = pFrame; for (pFrame = m_pFrameList; pCurrentFrame != pFrame; pFrame = pFrame->m_pNext) { pFrame->m_bSkipSaveEditChanges = FALSE; } // We aren't going to close -- get out! return FALSE; } // Set flag to prevent prompting for saving edit changes // in CEditFrame::OnClose() since this was done in CanCloseFrame() pFrame->m_bSkipSaveEditChanges = TRUE; } if(theApp.m_pBookmarks != NULL && ::IsWindow(theApp.m_pBookmarks->m_hWnd)) { if(WS_DISABLED & ::GetWindowLong(theApp.m_pBookmarks->m_hWnd, GWL_STYLE)) { return FALSE; } } return TRUE; } void CNetscapeApp::HideFrames() { // Go through each frame and hide it CGenericFrame *pFrame; CGenericFrame *pNext = NULL; for(pFrame = m_pFrameList; NULL != pFrame; pFrame = pNext) { // Extract the frame from the list. pNext = pFrame->m_pNext; //Hide all of it's children CWnd *pDesktop = CWnd::GetDesktopWindow(); if(pDesktop) { CWnd* pChild = pDesktop->GetWindow(GW_CHILD); while(pChild != NULL) { if(pChild->GetParent() == pFrame) { pChild->ShowWindow(SW_HIDE); } pChild = pChild->GetNextWindow(); } } pFrame->ShowWindow(SW_HIDE); } if(theApp.m_pBookmarks != NULL && ::IsWindow(theApp.m_pBookmarks->m_hWnd)) { theApp.m_pBookmarks->ShowWindow(SW_HIDE); } //if there's a search frame then close it WFE_MSGSearchClose(); } #endif /* MOZ_OFFLINE */ ///////////////////////////////////////////////////////////////////////////// // CNetscapeApp commands #if _MSC_VER > 1100 // Warn others of possible logic missing from newer versions of MFC and NS code. #pragma message(__FILE__ ": Check CNetscapeApp::[Run|NSPumpMessage|IsIdleMessage] for compatibility with new MFC source") #endif // Mainly as CWinThread::Run except for the NSPumpMessage call (PumpMessage non virtual on win16). int CNetscapeApp::Run() { BOOL bIdle = TRUE; LONG lIdleCount = 0; for(;;) { while(bIdle && !::PeekMessage(&m_msgCur, NULL, NULL, NULL, PM_NOREMOVE)) { if (!OnIdle(lIdleCount++)) bIdle = FALSE; } #ifdef XP_WIN16 #if defined(OJI) || defined(JAVA) || defined(MOCHA) /* ** On Win16 the only way for another thread to run is to explicitly ** yield... */ extern void fe_yield(void); fe_yield(); #endif /* OJI || JAVA || MOCHA */ #endif /* XP_WIN16 */ do { if(!NSPumpMessage()) { return(ExitInstance()); } if(IsIdleMessage(&m_msgCur)) { bIdle = TRUE; lIdleCount = 0; } } while(::PeekMessage(&m_msgCur, NULL, NULL, NULL, PM_NOREMOVE)); } } // Mainly as CWinThread::PumpMessage except for giving priority to certain events. // NSPumpMessage instead of PumpMessage as non-virtual on Win16 BOOL CNetscapeApp::NSPumpMessage() { BOOL bRetval = FALSE; BOOL bPeeked = FALSE; // Net dike (see hiddenfr.h). gNetFloodStage++; if((gNetFloodStage % NET_FLOWCONTROL) != 0) { bPeeked = bRetval = ::PeekMessage(&m_msgCur, NULL, 0, NET_MESSAGERANGE, PM_REMOVE); if(bPeeked && m_msgCur.message == WM_QUIT) { bRetval = FALSE; } } // As normal PumpMessage if(!bPeeked) { // Wait for message or getting a registered message. bRetval = ::GetMessage(&m_msgCur, NULL, NULL, NULL); } if(bRetval) { // Update tick count used in GetMessageTime call. // This can be used as an ID to tell wether or not a message // was generated from this dispatch function. m_dwLastMsgTick = m_msgCur.time; // Update time by MSG tickcount. // Allow 30 second play period for messages before resetting clock or // assuming roll over on the tick counter (49.7 days) if(m_msgCur.time > m_dwMsgTick) { m_dwMsgTick = m_msgCur.time; } else if((m_msgCur.time + 30000) < m_dwMsgTick) { InitTime(); } if(m_msgCur.message != WM_KICKIDLE && !PreTranslateMessage(&m_msgCur)) { ::TranslateMessage(&m_msgCur); ::DispatchMessage(&m_msgCur); } } return(bRetval); } BOOL CNetscapeApp::IsIdleMessage(MSG *pMsg) { ASSERT(pMsg); if (pMsg->message == msg_NetActivity || pMsg->message == msg_FoundDNS || pMsg->message == msg_ForceIOSelect || pMsg->message == m_msgNSPREventNotify) { return FALSE; } // We have to be careful about how often we go idle. We don't want timer // messages (e.g. animation timer) or Winsock async notifications to cause // us to go idle. We need to filter WM_GETDLGCODE messages, because clicking // in the URL bar generates an endless stream of them switch (pMsg->message) { case WM_KEYDOWN: if (pMsg->wParam == VK_SHIFT || pMsg->wParam == VK_CONTROL) { // Avoid consuming all of the CPU when the Shift/Control // keys are held down if (LOWORD(pMsg->lParam) > 0) { return FALSE; } } break; case WM_TIMER: case WM_GETDLGCODE: case WM_MOUSEMOVE: case WM_NCMOUSEMOVE: return FALSE; } // As CWinThread::IsIdleMessage if(pMsg->message == WM_MOUSEMOVE || pMsg->message == WM_NCMOUSEMOVE) { if (m_ptCursorLast == pMsg->pt && pMsg->message == m_nMsgLast) { return FALSE; } m_ptCursorLast = pMsg->pt; m_nMsgLast = pMsg->message; return TRUE; } return(pMsg->message != WM_PAINT && pMsg->message != 0x0118); } // This is just so we can call NET_PollSockets, will go away when // both NGLayout and Mozilla are using the same netlib. #ifdef MOZ_NGLAYOUT typedef void (*NET_PollSocketsType)(); static NET_PollSocketsType NGL_NET_PollSockets = nsnull; #endif BOOL CNetscapeApp::OnIdle(LONG lCount) { // call base class idle first BOOL bResult = CWinApp::OnIdle(lCount); // ZZZ: We don't need to do this in the 32-bit version, because CWinApp::InIdle // already sends a WM_IDLEUPDATECMDUI to each of the frames #ifdef XP_WIN16 #if defined(OJI) || defined(JAVA) || defined(MOCHA) /* ** On Win16 the only way for another thread to run is to explicitly ** yield... */ extern void fe_yield(void); fe_yield(); #endif /* OJI || JAVA || MOCHA */ // Update the UI of the frames. if(lCount == 0) { CGenericFrame * f; // update command buttons etc from the top down for(f = m_pFrameList; f; f = f->m_pNext) { if (f) { CNetscapeApp::SendMessageToDescendants(f->m_hWnd, WM_IDLEUPDATECMDUI, (WPARAM)TRUE, (LPARAM)0); } } return(TRUE); } #endif // Do we really have to do manual binding to timeout code? // This is set if the code was unable to allocate a timer. if(m_bIdleProcessTimeouts) { TRACE("Yo!: processing timeouts in idle binding.\n"); wfe_ProcessTimeouts(); bResult = TRUE; } // Poll the socket list and call Netlib if(NET_PollSockets()) bResult = TRUE; // This is just so we can call NET_PollSockets in the DLL, // this will go away when // both NGLayout and Mozilla are using the same netlib. #ifdef MOZ_NGLAYOUT if (nsnull == NGL_NET_PollSockets) { PRLibrary *netlib = PR_LoadLibrary("netlib"); NS_ASSERTION(netlib,"Could not load netlib dll."); NGL_NET_PollSockets = (NET_PollSocketsType)PR_FindSymbol(netlib,"NET_PollSockets"); NS_ASSERTION(NGL_NET_PollSockets,"Could not find NET_PollSockets in netlib.dll"); // This is a hack, we never release netlib.dll. } TRACE("Calling NGL_NET_PollSockets\n"); NGL_NET_PollSockets(); #endif #ifdef MOZ_MAIL_NEWS // currently just to give NeoAccess a chance to do some chores // If we become a real CNeoApp, this won't be neccesary. // --- DREAM ON --- MSG_OnIdle(); #endif /* MOZ_MAIL_NEWS */ // Good time to free up heap and unused COM Dlls when really going idle. if(bResult == FALSE) { CoFreeUnusedLibraries(); #ifdef XP_WIN32 _heapmin(); #endif } return(bResult); } BOOL CNetscapeApp::OnDDECommand(char *pszCommand) { TRACE("DDE command: %s\n", pszCommand); //////////// The block below belongs to Abe Jarrett ///////////// // Intercept all commandline DDE commands before Intercepting Print commands if (strcasestr(pszCommand,"cmdline") != NULL) { if (ProcessCommandLineDDE(pszCommand)) return TRUE; else return FALSE; } //////////// The above belongs to Abe Jarrett ///////////////////////// ////////////////////////////////////////////////////////////////////////////// // Intercept all print commands before we reach the below. BOOL bPrint = FALSE; BOOL bPrintTo = FALSE; char *pszCompare = pszCommand + 1; if(strnicmp(pszCompare, "print(", 6) == 0) { bPrint = TRUE; TRACE("Handling command to print\n"); } else if(strnicmp(pszCompare, "printto(", 8) == 0) { bPrintTo = TRUE; TRACE("Handling command to printto\n"); } if(bPrint || bPrintTo) { // There are four arguments that we figure out for each print job. // 1) What to print. // 2) The destination printer // 3) The printer driver used for printing // 4) The destination port for printing // // They will all be represented as strings. // All but 1 can be NULL, which means to use the default setting. // There should be no UI interaction except for authentication and other such // backend stuff that we have no control over. // Each argument is quoted. // Each quoted argument is seperated by a comma. char *pArg1 = FEU_ExtractCommaDilimetedQuotedString(pszCommand, 1); char *pArg2 = FEU_ExtractCommaDilimetedQuotedString(pszCommand, 2); char *pArg3 = FEU_ExtractCommaDilimetedQuotedString(pszCommand, 3); char *pArg4 = FEU_ExtractCommaDilimetedQuotedString(pszCommand, 4); #ifdef MOZ_NGLAYOUT XP_ASSERT(0); #else // Do it. CPrintCX::AutomatedPrint(pArg1, pArg2, pArg3, pArg4); #endif // Get rid of any allocations that FEU did for us. if(pArg1) { XP_FREE(pArg1); } if(pArg2) { XP_FREE(pArg2); } if(pArg3) { XP_FREE(pArg3); } if(pArg4) { XP_FREE(pArg4); } // Handled. return(TRUE); } BOOL bTranslate = TRUE; // Copy the string to mess with. char *pDelete = XP_STRDUP(pszCommand); char *pOpen = pDelete; #ifdef EDITOR // edit format is "[edit("%s")]" - no whitespace allowed, one per line if (strnicmp(pOpen, "[edit(\"", 7) == 0) { pOpen += 7; char *pEnd = strchr(pOpen, '"'); if (pOpen == NULL) { XP_FREE(pDelete); return FALSE; // illegally terminated } // trim the string, and edit the file *pEnd = '\0'; // This will do the WFE_ConvertFile2Url before loading URL FE_LoadUrl( pOpen, LOAD_URL_COMPOSER); XP_FREE(pDelete); return TRUE; } #endif /* EDITOR */ // open format is "[open("%s")]" - no whitespace allowed, one per line if (strnicmp(pOpen, "[open(\"", 7) != 0) { if ( strnicmp(pOpen, "[openurl(\"", 10) != 0 ) { XP_FREE(pDelete); //Added by CLM - memory leak return FALSE; } else { bTranslate = FALSE; pOpen += 10; } } else { pOpen += 7; } char *pEnd = strchr(pOpen, '"'); if (pEnd == NULL) { XP_FREE(pDelete); return FALSE; // illegally terminated } // trim the string, and open the file *pEnd = '\0'; // Convert the name to a URL. CString csUrl; WFE_ConvertFile2Url(csUrl, pOpen); // Open it in a new window. // Use the first window as the provider of the context. URL_Struct *pUrl = NET_CreateURLStruct(csUrl, NET_DONT_RELOAD); if(m_pFrameList && m_pFrameList->GetMainContext()) { if (bTranslate) { MWContext *pContext = m_pFrameList->GetMainContext()->GetContext(); CFE_CreateNewDocWindow(pContext, pUrl); } else { CFrameGlue * pFrame = CFrameGlue::GetLastActiveFrame(MWContextBrowser); if (pFrame != NULL && pFrame->GetMainContext() && pFrame->GetMainContext()->GetContext() && !pFrame->GetMainContext()->GetContext()->restricted_target) { CAbstractCX * pCX = pFrame->GetMainContext(); if (pCX != NULL) { CFrameWnd * pFrameWnd = pFrame->GetFrameWnd(); if( pFrameWnd ){ // We need to bring window to the top if(pFrameWnd->IsIconic()) { pFrameWnd->ShowWindow(SW_RESTORE); } pFrameWnd->BringWindowToTop(); } pCX->NormalGetUrl(csUrl); } /* end if */ } /* end if */ else { CFE_CreateNewDocWindow(NULL, pUrl); } /* end else */ } /* end else */ } else { CFE_CreateNewDocWindow(NULL, pUrl); } XP_FREE(pDelete); return(TRUE); } // // Generic help handler // void CNetscapeApp::OnHelp() { #ifdef XP_WIN16 if (SENT_MESSAGE!=m_helpstate) { if (m_pMainWnd) { CWnd *t_wnd=m_pMainWnd->GetActiveWindow(); if (t_wnd) { m_helpstate=SENT_MESSAGE; t_wnd->SendMessage(WM_COMMAND,ID_HELP); m_helpstate=NOT_SENT; } } } #endif } void CNetscapeApp::ReleaseAppFont(HFONT logFont) { XP_List *theList = m_appFontList; NsWinFont* theFont = (NsWinFont*)XP_ListNextObject(theList); while (theFont) { if (theFont->hFont == logFont) break; theFont = (NsWinFont*)XP_ListNextObject(theList); } if (theFont) { // release the font use. theFont->refCount--; if (theFont->refCount == 0) { // no one use this font anymore, release it. XP_ListRemoveObject (m_appFontList, theFont); VERIFY(::DeleteObject(theFont->hFont)); XP_DELETE(theFont); theFont = NULL; } } } HFONT CNetscapeApp::CreateAppFont(LOGFONT& logFont) { NsWinFont* theFont; if (m_appFontList == NULL) { m_appFontList = XP_ListNew(); theFont = XP_NEW( NsWinFont); memcpy(&theFont->logFontStruct, &logFont, sizeof(LOGFONT)); theFont->hFont = CreateFontIndirect( &logFont ); theFont->refCount = 1; XP_ListAddObject (m_appFontList, (void*)theFont); } else { XP_List *theList = m_appFontList; theFont = (NsWinFont*)XP_ListNextObject(theList); while (theFont) { const LOGFONT& l1 = logFont; const LOGFONT& l2 = theFont->logFontStruct; if ((memcmp(&l1, &l2, sizeof(LOGFONT) - sizeof(l1.lfFaceName)) == 0) && (strcmp(l1.lfFaceName, l2.lfFaceName) == 0)) break; theFont = (NsWinFont*)XP_ListNextObject(theList); } if (!theFont) { // we do not found a font cached fot this LOGFONT yet. theFont = XP_NEW( NsWinFont); memcpy(&theFont->logFontStruct, &logFont, sizeof(LOGFONT)); theFont->hFont = CreateFontIndirect( &logFont ); XP_ListAddObject (m_appFontList, (void*)theFont); theFont->refCount = 1; } else { theFont->refCount++; } } return theFont->hFont; } CNSNavFrame* CNetscapeApp::CreateNewNavCenter(CNSGenFrame* pParentFrame, BOOL useViewType, HT_ViewType viewType) { CNSNavFrame* theItem; theItem = new CNSNavFrame(); theItem->CreateNewNavCenter(pParentFrame, useViewType, viewType); return theItem; }