wxString &OCPNPlatform::GetSharedDataDir() { if(m_SData_Dir.IsEmpty()){ // Establish a "shared data" location /* From the wxWidgets documentation... * * wxStandardPaths::GetDataDir * wxString GetDataDir() const * Return the location of the applications global, i.e. not user-specific, data files. * Unix: prefix/share/appname * Windows: the directory where the executable file is located * Mac: appname.app/Contents/SharedSupport bundle subdirectory */ wxStandardPaths& std_path = GetStdPaths(); m_SData_Dir = std_path.GetDataDir(); appendOSDirSlash( &m_SData_Dir ); #ifdef __OCPN__ANDROID__ wxFileName fdir = wxFileName::DirName(std_path.GetUserConfigDir()); fdir.RemoveLastDir(); m_SData_Dir = fdir.GetPath(); m_SData_Dir += _T("/cache/"); #endif if( g_bportable ) m_SData_Dir = GetHomeDir(); } return m_SData_Dir; }
wxString &OCPNPlatform::GetPrivateDataDir() { if(m_PrivateDataDir.IsEmpty()){ // Establish the prefix of the location of user specific data files wxStandardPaths& std_path = GetStdPaths(); #ifdef __WXMSW__ m_PrivateDataDir = GetHomeDir(); // should be {Documents and Settings}\...... #elif defined __WXOSX__ m_PrivateDataDir = std_path.GetUserConfigDir(); // should be ~/Library/Preferences appendOSDirSlash(&m_PrivateDataDir); m_PrivateDataDir.Append(_T("opencpn")); #else m_PrivateDataDir = std_path.GetUserDataDir(); // should be ~/.opencpn #endif if( g_bportable ) m_PrivateDataDir = GetHomeDir(); #ifdef __OCPN__ANDROID__ m_PrivateDataDir = androidGetPrivateDir(); #endif } return m_PrivateDataDir; }
wxString &OCPNPlatform::GetHomeDir() { if(m_homeDir.IsEmpty()){ // Establish a "home" location // wxStandardPaths& std_path = *dynamic_cast<wxStandardPaths*>(&wxApp::GetTraits()->GetStandardPaths()); wxStandardPaths& std_path = GetStdPaths(); // wxStandardPaths &std_path = ( wxStandardPaths) wxGetApp().GetTraits()->GetStandardPaths(); //TODO Why is the following preferred? Will not compile with gcc... // wxStandardPaths& std_path = wxApp::GetTraits()->GetStandardPaths(); #ifdef __unix__ std_path.SetInstallPrefix(wxString(PREFIX, wxConvUTF8)); #endif #ifdef __WXMSW__ m_homeDir = std_path.GetConfigDir(); // on w98, produces "/windows/Application Data" #else m_homeDir = std_path.GetUserConfigDir(); #endif // On android, make the private data dir on the sdcard, if it exists. // This make debugging easier, as it is not deleted whenever the APK is re-deployed. // This behaviour should go away at Release. #ifdef __OCPN__ANDROID__ if( wxDirExists(_T("/mnt/sdcard")) ){ m_homeDir = _T("/mnt/sdcard/.opencpn"); } #endif if( g_bportable ) m_homeDir = GetExePath(); #ifdef __WXOSX__ appendOSDirSlash(&m_homeDir); m_homeDir.Append(_T("opencpn")); #endif appendOSDirSlash( &m_homeDir ); } return m_homeDir; }
wxString &OCPNPlatform::GetConfigFileName() { if(m_config_file_name.IsEmpty()){ // Establish the location of the config file wxStandardPaths& std_path = GetStdPaths(); #ifdef __WXMSW__ m_config_file_name = _T("opencpn.ini"); m_config_file_name.Prepend( GetHomeDir() ); #elif defined __WXOSX__ m_config_file_name = std_path.GetUserConfigDir(); // should be ~/Library/Preferences appendOSDirSlash(&m_config_file_name); m_config_file_name.Append(_T("opencpn")); appendOSDirSlash(&m_config_file_name); m_config_file_name.Append(_T("opencpn.ini")); #else m_config_file_name = std_path.GetUserDataDir(); // should be ~/.opencpn appendOSDirSlash(&m_config_file_name); m_config_file_name.Append(_T("opencpn.conf")); #endif if( g_bportable ) { m_config_file_name = GetHomeDir(); #ifdef __WXMSW__ m_config_file_name += _T("opencpn.ini"); #elif defined __WXOSX__ m_config_file_name +=_T("opencpn.ini"); #else m_config_file_name += _T("opencpn.conf"); #endif } #ifdef __OCPN__ANDROID__ m_config_file_name = androidGetPrivateDir(); appendOSDirSlash(&m_config_file_name); m_config_file_name += _T("opencpn.conf"); #endif } return m_config_file_name; }
wxString &OCPNPlatform::GetHomeDir() { if(m_homeDir.IsEmpty()){ // Establish a "home" location // wxStandardPaths& std_path = *dynamic_cast<wxStandardPaths*>(&wxApp::GetTraits()->GetStandardPaths()); wxStandardPaths& std_path = GetStdPaths(); // wxStandardPaths &std_path = ( wxStandardPaths) wxGetApp().GetTraits()->GetStandardPaths(); //TODO Why is the following preferred? Will not compile with gcc... // wxStandardPaths& std_path = wxApp::GetTraits()->GetStandardPaths(); #ifdef __unix__ std_path.SetInstallPrefix(wxString(PREFIX, wxConvUTF8)); #endif #ifdef __WXMSW__ m_homeDir = std_path.GetConfigDir(); // on w98, produces "/windows/Application Data" #else m_homeDir = std_path.GetUserConfigDir(); #endif #ifdef __OCPN__ANDROID__ m_homeDir = androidGetHomeDir(); #endif if( g_bportable ) { wxFileName path(GetExePath()); m_homeDir = path.GetPath(); } #ifdef __WXOSX__ appendOSDirSlash(&m_homeDir); m_homeDir.Append(_T("opencpn")); #endif appendOSDirSlash( &m_homeDir ); } return m_homeDir; }
bool OCPNPlatform::InitializeLogFile( void ) { // Establish Log File location mlog_file = GetHomeDir(); #ifdef __WXOSX__ wxFileName LibPref(mlog_file); // starts like "~/Library/Preferences" LibPref.RemoveLastDir();// takes off "Preferences" mlog_file = LibPref.GetFullPath(); appendOSDirSlash(&mlog_file); mlog_file.Append(_T("Logs/"));// so, on OS X, opencpn.log ends up in ~/Library/Logs // which makes it accessible to Applications/Utilities/Console.... #endif // create the opencpn "home" directory if we need to wxFileName wxHomeFiledir( GetHomeDir() ); if( true != wxHomeFiledir.DirExists( wxHomeFiledir.GetPath() ) ) if( !wxHomeFiledir.Mkdir( wxHomeFiledir.GetPath() ) ) { wxASSERT_MSG(false,_T("Cannot create opencpn home directory")); return false; } // create the opencpn "log" directory if we need to wxFileName wxLogFiledir( mlog_file ); if( true != wxLogFiledir.DirExists( wxLogFiledir.GetPath() ) ) { if( !wxLogFiledir.Mkdir( wxLogFiledir.GetPath() ) ) { wxASSERT_MSG(false,_T("Cannot create opencpn log directory")); return false; } } mlog_file.Append( _T("opencpn.log") ); wxString logit = mlog_file; // Constrain the size of the log file if( ::wxFileExists( mlog_file ) ) { if( wxFileName::GetSize( mlog_file ) > 1000000 ) { wxString oldlog = mlog_file; oldlog.Append( _T(".log") ); // Defer the showing of this messagebox until the system locale is established. large_log_message = ( _("Old log will be moved to opencpn.log.log") ); ::wxRenameFile( mlog_file, oldlog ); } } #ifdef __OCPN__ANDROID__ // Force new logfile for each instance // TODO Remove this behaviour on Release if( ::wxFileExists( mlog_file ) ){ ::wxRemoveFile( mlog_file ); } #endif flog = fopen( mlog_file.mb_str(), "a" ); g_logger = new wxLogStderr( flog ); #ifdef __OCPN__ANDROID__ // Trouble printing timestamp g_logger->SetTimestamp((const char *)NULL); #endif #if defined(__WXGTK__) || defined(__WXOSX__) g_logger->SetTimestamp(_T("%H:%M:%S %Z")); #endif m_Oldlogger = wxLog::SetActiveTarget( g_logger ); return true; }
// Called from MyApp() immediately upon entry to MyApp::OnInit() void OCPNPlatform::Initialize_1( void ) { #ifdef OCPN_USE_CRASHRPT #ifndef _DEBUG // Install Windows crash reporting CR_INSTALL_INFO info; memset(&info, 0, sizeof(CR_INSTALL_INFO)); info.cb = sizeof(CR_INSTALL_INFO); info.pszAppName = _T("OpenCPN"); wxString version_crash = str_version_major + _T(".") + str_version_minor + _T(".") + str_version_patch; info.pszAppVersion = version_crash.c_str(); int type = MiniDumpWithDataSegs; // Include the data sections from all loaded modules. // This results in the inclusion of global variables type |= MiniDumpNormal;// | MiniDumpWithPrivateReadWriteMemory | MiniDumpWithIndirectlyReferencedMemory; info.uMiniDumpType = (MINIDUMP_TYPE)type; // Install all available exception handlers.... info.dwFlags = CR_INST_ALL_POSSIBLE_HANDLERS; // Except memory allocation failures info.dwFlags &= ~CR_INST_NEW_OPERATOR_ERROR_HANDLER; // Allow user to attach files info.dwFlags |= CR_INST_ALLOW_ATTACH_MORE_FILES; // Allow user to add more info info.dwFlags |= CR_INST_SHOW_ADDITIONAL_INFO_FIELDS; // URL for sending error reports over HTTP. if(g_bEmailCrashReport){ info.pszEmailTo = _T("*****@*****.**"); info.pszSmtpProxy = _T("mail.bigdumboat.com:587"); info.pszUrl = _T("http://bigdumboat.com/crashrpt/ocpn_crashrpt.php"); info.uPriorities[CR_HTTP] = 1; // First try send report over HTTP } else{ info.dwFlags |= CR_INST_DONT_SEND_REPORT; info.uPriorities[CR_HTTP] = CR_NEGATIVE_PRIORITY; // don't send at all } info.uPriorities[CR_SMTP] = CR_NEGATIVE_PRIORITY; // Second try send report over SMTP info.uPriorities[CR_SMAPI] = CR_NEGATIVE_PRIORITY; //1; // Third try send report over Simple MAPI wxStandardPaths& crash_std_path = g_Platform->GetStdPaths(); wxString crash_rpt_save_locn = crash_std_path.GetConfigDir(); if( g_bportable ) { wxFileName exec_path_crash( crash_std_path.GetExecutablePath() ); crash_rpt_save_locn = exec_path_crash.GetPath( wxPATH_GET_VOLUME | wxPATH_GET_SEPARATOR ); } wxString locn = crash_rpt_save_locn + _T("\\CrashReports"); if(!wxDirExists( locn ) ) wxMkdir( locn ); if(wxDirExists( locn ) ){ wxCharBuffer buf = locn.ToUTF8(); wchar_t wlocn[256]; if(buf && (locn.Length() < sizeof(wlocn)) ){ MultiByteToWideChar( 0, 0, buf.data(), -1, wlocn, sizeof(wlocn)-1); info.pszErrorReportSaveDir = (LPCWSTR)wlocn; } } // Provide privacy policy URL wxFileName exec_path_crash( crash_std_path.GetExecutablePath() ); wxString policy_file = exec_path_crash.GetPath( wxPATH_GET_VOLUME | wxPATH_GET_SEPARATOR ); policy_file += _T("PrivacyPolicy.txt"); policy_file.Prepend(_T("file:")); info.pszPrivacyPolicyURL = policy_file.c_str();; int nResult = crInstall(&info); if(nResult!=0) { TCHAR buff[256]; crGetLastErrorMsg(buff, 256); MessageBox(NULL, buff, _T("crInstall error, Crash Reporting disabled."), MB_OK); } // Establish the crash callback function crSetCrashCallback( CrashCallback, NULL ); // Take screenshot of the app window at the moment of crash crAddScreenshot2(CR_AS_PROCESS_WINDOWS|CR_AS_USE_JPEG_FORMAT, 95); // Mark some files to add to the crash report wxString home_data_crash = crash_std_path.GetConfigDir(); if( g_bportable ) { wxFileName f( crash_std_path.GetExecutablePath() ); home_data_crash = f.GetPath(); } appendOSDirSlash( &home_data_crash ); wxString config_crash = _T("opencpn.ini"); config_crash.Prepend( home_data_crash ); crAddFile2( config_crash.c_str(), NULL, NULL, CR_AF_MISSING_FILE_OK | CR_AF_ALLOW_DELETE ); wxString log_crash = _T("opencpn.log"); log_crash.Prepend( home_data_crash ); crAddFile2( log_crash.c_str(), NULL, NULL, CR_AF_MISSING_FILE_OK | CR_AF_ALLOW_DELETE ); #endif #endif #ifdef LINUX_CRASHRPT #if wxUSE_ON_FATAL_EXCEPTION // fatal exceptions handling wxHandleFatalExceptions (true); #endif #endif #ifdef __WXMSW__ // Invoke my own handler for failures of malloc/new _set_new_handler( MyNewHandler ); // configure malloc to call the New failure handler on failure _set_new_mode(1); #endif // On MSW, force the entire process to run on one CPU core only // This resolves some difficulty with wxThread syncronization #if 0 #ifdef __WXMSW__ //Gets the current process handle HANDLE hProc = GetCurrentProcess(); DWORD procMask; DWORD sysMask; HANDLE hDup; DuplicateHandle( hProc, hProc, hProc, &hDup, 0, FALSE, DUPLICATE_SAME_ACCESS ); //Gets the current process affinity mask GetProcessAffinityMask( hDup, &procMask, &sysMask ); // Take a simple approach, and assume up to 4 processors DWORD newMask; if( ( procMask & 1 ) == 1 ) newMask = 1; else if( ( procMask & 2 ) == 2 ) newMask = 2; else if( ( procMask & 4 ) == 4 ) newMask = 4; else if( ( procMask & 8 ) == 8 ) newMask = 8; //Set te affinity mask for the process BOOL res = SetProcessAffinityMask( hDup, (DWORD_PTR) newMask ); if( res == 0 ) { //Error setting affinity mask!! } #endif #endif #ifdef __WXMSW__ // Handle any Floating Point Exceptions which may leak thru from other // processes. The exception filter is in cutil.c // Seems to only happen for W98 wxPlatformInfo Platform; if( Platform.GetOperatingSystemId() == wxOS_WINDOWS_9X ) SetUnhandledExceptionFilter (&MyUnhandledExceptionFilter); #endif #ifdef __WXMSW__ // _CrtSetBreakAlloc(25503); #endif #ifndef __WXMSW__ // Setup Linux SIGNAL handling, for external program control // Build the sigaction structure sa_all.sa_handler = catch_signals;// point to my handler sigemptyset(&sa_all.sa_mask);// make the blocking set // empty, so that all // other signals will be // unblocked during my handler sa_all.sa_flags = 0; sigaction(SIGUSR1, NULL, &sa_all_old);// save existing action for this signal // Register my request for some signals sigaction(SIGUSR1, &sa_all, NULL); sigaction(SIGUSR1, NULL, &sa_all_old);// inspect existing action for this signal sigaction(SIGTERM, &sa_all, NULL); sigaction(SIGTERM, NULL, &sa_all_old); #endif }