2006-01-16 22:02:54 +01:00
// Copyright (c) 2005, Rodrigo Braz Monteiro
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are met:
//
// * Redistributions of source code must retain the above copyright notice,
// this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above copyright notice,
// this list of conditions and the following disclaimer in the documentation
// and/or other materials provided with the distribution.
// * Neither the name of the Aegisub Group nor the names of its contributors
// may be used to endorse or promote products derived from this software
// without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
// POSSIBILITY OF SUCH DAMAGE.
//
2009-07-29 07:43:02 +02:00
// Aegisub Project http://www.aegisub.org/
/// @file main.cpp
/// @brief Main entry point, as well as crash handling
/// @ingroup main
///
2006-01-16 22:02:54 +01:00
2014-03-19 17:15:25 +01:00
# include "main.h"
Merge the dynamic menu, hotkey and toolbar branch to trunk. This doesn't include Windows support as vs2008 was being a major pain. This involves revisions r4921:4950, r4961:5002, r5005:5006, r5008:5056, r5062:5065, r5072, r5081:5082, r5087, r5096:5110, r5124:5125. Updates #1258.
Originally committed to SVN as r5126.
2011-01-05 14:00:46 +01:00
# include "command/command.h"
2011-01-05 19:40:37 +01:00
# include "include/aegisub/hotkey.h"
Merge the dynamic menu, hotkey and toolbar branch to trunk. This doesn't include Windows support as vs2008 was being a major pain. This involves revisions r4921:4950, r4961:5002, r5005:5006, r5008:5056, r5062:5065, r5072, r5081:5082, r5087, r5096:5110, r5124:5125. Updates #1258.
Originally committed to SVN as r5126.
2011-01-05 14:00:46 +01:00
2007-12-31 07:46:22 +01:00
# include "auto4_base.h"
2014-03-24 15:54:22 +01:00
# include "auto4_lua_factory.h"
2010-05-21 03:13:36 +02:00
# include "compat.h"
2014-03-19 17:15:25 +01:00
# include "crash_writer.h"
2014-05-22 21:07:15 +02:00
# include "dialogs.h"
2011-01-21 07:09:04 +01:00
# include "export_fixstyle.h"
2009-09-10 15:06:40 +02:00
# include "export_framerate.h"
2014-05-29 17:28:37 +02:00
# include "format.h"
2009-09-10 15:06:40 +02:00
# include "frame_main.h"
2013-01-26 02:57:46 +01:00
# include "include/aegisub/context.h"
2010-05-21 03:13:36 +02:00
# include "libresrc/libresrc.h"
2013-01-07 02:50:09 +01:00
# include "options.h"
2014-05-22 01:23:28 +02:00
# include "project.h"
2014-05-22 18:52:19 +02:00
# include "subs_controller.h"
2014-03-24 15:54:22 +01:00
# include "subtitles_provider_libass.h"
2012-04-04 00:44:47 +02:00
# include "utils.h"
2015-01-01 17:12:05 +01:00
# include "value_event.h"
2014-05-22 18:52:19 +02:00
# include "version.h"
2006-01-16 22:02:54 +01:00
2013-01-04 16:01:50 +01:00
# include <libaegisub/dispatch.h>
2014-05-29 17:28:37 +02:00
# include <libaegisub/format_path.h>
2013-01-04 16:01:50 +01:00
# include <libaegisub/fs.h>
2010-05-21 03:13:36 +02:00
# include <libaegisub/io.h>
2010-06-01 10:21:30 +02:00
# include <libaegisub/log.h>
2014-04-23 22:53:24 +02:00
# include <libaegisub/make_unique.h>
2013-01-04 16:01:50 +01:00
# include <libaegisub/path.h>
# include <libaegisub/util.h>
2006-01-16 22:02:54 +01:00
2014-03-21 21:41:33 +01:00
# include <boost/interprocess/streams/bufferstream.hpp>
2013-01-29 16:10:35 +01:00
# include <boost/locale.hpp>
2014-05-07 03:16:36 +02:00
# include <locale>
2014-03-08 02:48:00 +01:00
# include <wx/clipbrd.h>
2013-01-07 02:50:09 +01:00
# include <wx/msgdlg.h>
2013-01-04 16:01:50 +01:00
# include <wx/stackwalk.h>
2013-01-07 02:50:09 +01:00
# include <wx/utils.h>
2010-06-18 04:23:27 +02:00
namespace config {
2013-01-04 16:01:50 +01:00
agi : : Options * opt = nullptr ;
agi : : MRUManager * mru = nullptr ;
agi : : Path * path = nullptr ;
2014-06-06 17:24:33 +02:00
Automation4 : : AutoloadScriptManager * global_scripts ;
2010-06-18 04:23:27 +02:00
}
2014-06-06 17:11:22 +02:00
wxIMPLEMENT_APP ( AegisubApp ) ;
2006-01-16 22:02:54 +01:00
2012-11-13 17:51:01 +01:00
static const char * LastStartupState = nullptr ;
2006-01-16 22:02:54 +01:00
2009-06-12 18:59:53 +02:00
# ifdef WITH_STARTUPLOG
2019-09-10 06:15:40 +02:00
# define StartupLog(a) wxMessageBox(wxT(a), wxT("Aegisub startup log"))
2007-07-05 21:11:54 +02:00
# else
2010-10-20 02:28:37 +02:00
# define StartupLog(a) LastStartupState = a
2007-07-05 21:11:54 +02:00
# endif
2011-12-22 22:17:49 +01:00
void AegisubApp : : OnAssertFailure ( const wxChar * file , int line , const wxChar * func , const wxChar * cond , const wxChar * msg ) {
2010-09-15 00:05:19 +02:00
LOG_A ( " wx/assert " ) < < file < < " : " < < line < < " : " < < func < < " () " < < cond < < " : " < < msg ;
2011-12-22 22:17:49 +01:00
wxApp : : OnAssertFailure ( file , line , func , cond , msg ) ;
2010-09-15 00:05:19 +02:00
}
2012-10-25 18:54:59 +02:00
AegisubApp : : AegisubApp ( ) {
// http://trac.wxwidgets.org/ticket/14302
wxSetEnv ( " UBUNTU_MENUPROXY " , " 0 " ) ;
}
2015-01-01 17:12:05 +01:00
namespace {
wxDEFINE_EVENT ( EVT_CALL_THUNK , ValueEvent < agi : : dispatch : : Thunk > ) ;
}
2013-01-04 16:01:50 +01:00
2014-03-19 17:19:20 +01:00
/// Message displayed when an exception has occurred.
static wxString exception_message = " Oops, Aegisub has crashed! \n \n An attempt has been made to save a copy of your file to: \n \n %s \n \n Aegisub will now close. " ;
2010-09-15 00:05:19 +02:00
/// @brief Gets called when application starts.
/// @return bool
2006-01-16 22:02:54 +01:00
bool AegisubApp : : OnInit ( ) {
2011-01-16 08:15:18 +01:00
// App name (yeah, this is a little weird to get rid of an odd warning)
# if defined(__WXMSW__) || defined(__WXMAC__)
2011-09-28 21:43:11 +02:00
SetAppName ( " Aegisub " ) ;
2011-01-16 08:15:18 +01:00
# else
2011-09-28 21:43:11 +02:00
SetAppName ( " aegisub " ) ;
2011-01-16 08:15:18 +01:00
# endif
Merge the dynamic menu, hotkey and toolbar branch to trunk. This doesn't include Windows support as vs2008 was being a major pain. This involves revisions r4921:4950, r4961:5002, r5005:5006, r5008:5056, r5062:5065, r5072, r5081:5082, r5087, r5096:5110, r5124:5125. Updates #1258.
Originally committed to SVN as r5126.
2011-01-05 14:00:46 +01:00
2013-09-21 21:52:11 +02:00
// The logger isn't created on demand on background threads, so force it to
// be created now
( void ) wxLog : : GetActiveTarget ( ) ;
2014-05-07 03:16:36 +02:00
{
// Try to get the UTF-8 version of the current locale
auto locale = boost : : locale : : generator ( ) . generate ( " " ) ;
// Check if we actually got a UTF-8 locale
using codecvt = std : : codecvt < wchar_t , char , std : : mbstate_t > ;
int result = std : : codecvt_base : : error ;
if ( std : : has_facet < codecvt > ( locale ) ) {
2014-05-09 15:30:07 +02:00
wchar_t test [ ] = L " \xFFFE " ;
char buff [ 8 ] ;
auto mb = std : : mbstate_t ( ) ;
const wchar_t * from_next ;
char * to_next ;
result = std : : use_facet < codecvt > ( locale ) . out ( mb ,
test , std : : end ( test ) , from_next ,
buff , std : : end ( buff ) , to_next ) ;
}
// If we didn't get a UTF-8 locale, force it to a known one
if ( result ! = std : : codecvt_base : : ok )
2014-05-07 03:16:36 +02:00
locale = boost : : locale : : generator ( ) . generate ( " en_US.UTF-8 " ) ;
std : : locale : : global ( locale ) ;
}
2014-01-12 18:53:24 +01:00
2013-01-29 16:10:35 +01:00
boost : : filesystem : : path : : imbue ( std : : locale ( ) ) ;
2013-01-04 16:01:50 +01:00
// Pointless `this` capture required due to http://gcc.gnu.org/bugzilla/show_bug.cgi?id=51494
agi : : dispatch : : Init ( [ this ] ( agi : : dispatch : : Thunk f ) {
2015-01-01 17:12:05 +01:00
auto evt = new ValueEvent < agi : : dispatch : : Thunk > ( EVT_CALL_THUNK , - 1 , std : : move ( f ) ) ;
2013-01-04 16:01:50 +01:00
wxTheApp - > QueueEvent ( evt ) ;
} ) ;
2015-01-01 17:12:05 +01:00
wxTheApp - > Bind ( EVT_CALL_THUNK , [ this ] ( ValueEvent < agi : : dispatch : : Thunk > & evt ) {
2014-05-09 15:30:07 +02:00
try {
2015-01-01 17:12:05 +01:00
evt . Get ( ) ( ) ;
2014-05-09 15:30:07 +02:00
}
catch ( . . . ) {
OnExceptionInMainLoop ( ) ;
}
2012-11-26 04:06:18 +01:00
} ) ;
2013-01-04 16:01:50 +01:00
config : : path = new agi : : Path ;
2014-03-19 17:15:25 +01:00
crash_writer : : Initialize ( config : : path - > Decode ( " ?user " ) ) ;
Merge the dynamic menu, hotkey and toolbar branch to trunk. This doesn't include Windows support as vs2008 was being a major pain. This involves revisions r4921:4950, r4961:5002, r5005:5006, r5008:5056, r5062:5065, r5072, r5081:5082, r5087, r5096:5110, r5124:5125. Updates #1258.
Originally committed to SVN as r5126.
2011-01-05 14:00:46 +01:00
2013-01-04 16:01:50 +01:00
agi : : log : : log = new agi : : log : : LogSink ;
2010-06-18 04:23:27 +02:00
# ifdef _DEBUG
2014-04-23 22:53:24 +02:00
agi : : log : : log - > Subscribe ( agi : : make_unique < agi : : log : : EmitSTDOUT > ( ) ) ;
2010-06-18 04:23:27 +02:00
# endif
// Set config file
2012-01-08 02:36:35 +01:00
StartupLog ( " Load local configuration " ) ;
2010-06-18 04:23:27 +02:00
# ifdef __WXMSW__
// Try loading configuration from the install dir if one exists there
try {
2013-01-30 04:35:37 +01:00
auto conf_local ( config : : path - > Decode ( " ?data/config.json " ) ) ;
2013-02-17 04:47:31 +01:00
std : : unique_ptr < std : : istream > localConfig ( agi : : io : : Open ( conf_local ) ) ;
2012-01-08 02:35:56 +01:00
config : : opt = new agi : : Options ( conf_local , GET_DEFAULT_CONFIG ( default_config ) ) ;
// Local config, make ?user mean ?data so all user settings are placed in install dir
2013-01-30 04:35:37 +01:00
config : : path - > SetToken ( " ?user " , config : : path - > Decode ( " ?data " ) ) ;
config : : path - > SetToken ( " ?local " , config : : path - > Decode ( " ?data " ) ) ;
2014-03-19 17:15:25 +01:00
crash_writer : : Initialize ( config : : path - > Decode ( " ?user " ) ) ;
2013-01-04 16:01:50 +01:00
} catch ( agi : : fs : : FileSystemError const & ) {
2010-06-18 04:23:27 +02:00
// File doesn't exist or we can't read it
// Might be worth displaying an error in the second case
}
# endif
2012-01-08 02:35:56 +01:00
2012-01-08 02:36:35 +01:00
StartupLog ( " Create log writer " ) ;
2013-01-30 04:35:37 +01:00
auto path_log = config : : path - > Decode ( " ?user/log/ " ) ;
2013-01-04 16:01:50 +01:00
agi : : fs : : CreateDirectory ( path_log ) ;
2014-04-23 22:53:24 +02:00
agi : : log : : log - > Subscribe ( agi : : make_unique < agi : : log : : JsonEmitter > ( path_log ) ) ;
2012-04-04 00:44:47 +02:00
CleanCache ( path_log , " *.json " , 10 , 100 ) ;
2012-01-08 02:36:35 +01:00
StartupLog ( " Load user configuration " ) ;
2012-01-08 02:35:56 +01:00
try {
if ( ! config : : opt )
2013-01-30 04:35:37 +01:00
config : : opt = new agi : : Options ( config : : path - > Decode ( " ?user/config.json " ) , GET_DEFAULT_CONFIG ( default_config ) ) ;
2014-06-28 02:55:59 +02:00
boost : : interprocess : : ibufferstream stream ( ( const char * ) default_config_platform , sizeof ( default_config_platform ) ) ;
2012-04-06 03:55:22 +02:00
config : : opt - > ConfigNext ( stream ) ;
2012-01-08 02:35:56 +01:00
} catch ( agi : : Exception & e ) {
2014-05-29 14:57:27 +02:00
LOG_E ( " config/init " ) < < " Caught exception: " < < e . GetMessage ( ) ;
2012-01-08 02:35:56 +01:00
}
2010-08-25 21:31:11 +02:00
try {
config : : opt - > ConfigUser ( ) ;
}
catch ( agi : : Exception const & err ) {
2012-12-23 00:18:38 +01:00
wxMessageBox ( " Configuration file is invalid. Error reported: \n " + to_wx ( err . GetMessage ( ) ) , " Error " ) ;
2010-08-25 21:31:11 +02:00
}
2010-06-18 04:23:27 +02:00
2014-05-15 19:19:23 +02:00
# ifdef _WIN32
StartupLog ( " Load installer configuration " ) ;
if ( OPT_GET ( " App/First Start " ) - > GetBool ( ) ) {
try {
auto installer_config = agi : : io : : Open ( config : : path - > Decode ( " ?data/installer_config.json " ) ) ;
config : : opt - > ConfigNext ( * installer_config . get ( ) ) ;
} catch ( agi : : fs : : FileSystemError const & ) {
// Not an error obviously as the user may not have used the installer
}
}
# endif
2012-01-08 02:36:03 +01:00
// Init commands.
cmd : : init_builtin_commands ( ) ;
// Init hotkeys
hotkey : : init ( ) ;
2011-12-30 02:21:03 +01:00
StartupLog ( " Load MRU " ) ;
2013-01-30 04:35:37 +01:00
config : : mru = new agi : : MRUManager ( config : : path - > Decode ( " ?user/mru.json " ) , GET_DEFAULT_CONFIG ( default_mru ) , config : : opt ) ;
2010-06-01 10:21:30 +02:00
2013-01-28 01:50:59 +01:00
agi : : util : : SetThreadName ( " AegiMain " ) ;
2008-03-09 22:00:55 +01:00
2011-09-28 21:43:11 +02:00
StartupLog ( " Inside OnInit " ) ;
2006-01-16 22:02:54 +01:00
try {
// Initialize randomizer
2011-09-28 21:43:11 +02:00
StartupLog ( " Initialize random generator " ) ;
2012-11-13 17:51:01 +01:00
srand ( time ( nullptr ) ) ;
2006-01-16 22:02:54 +01:00
2007-04-03 06:34:56 +02:00
// locale for loading options
2011-09-28 21:43:11 +02:00
StartupLog ( " Set initial locale " ) ;
2007-04-03 06:34:56 +02:00
setlocale ( LC_NUMERIC , " C " ) ;
setlocale ( LC_CTYPE , " C " ) ;
2007-06-22 05:14:25 +02:00
// Crash handling
2012-01-25 20:07:07 +01:00
# if (!defined(_DEBUG) || defined(WITH_EXCEPTIONS)) && (wxUSE_ON_FATAL_EXCEPTION+0)
2011-09-28 21:43:11 +02:00
StartupLog ( " Install exception handler " ) ;
2006-01-16 22:02:54 +01:00
wxHandleFatalExceptions ( true ) ;
2007-07-01 02:19:55 +02:00
# endif
2006-01-16 22:02:54 +01:00
2011-09-28 21:43:11 +02:00
StartupLog ( " Store options back " ) ;
2010-05-21 03:13:36 +02:00
OPT_SET ( " Version/Last Version " ) - > SetInt ( GetSVNRevision ( ) ) ;
2006-01-16 22:02:54 +01:00
2011-09-28 21:43:11 +02:00
StartupLog ( " Initialize final locale " ) ;
2009-01-02 09:49:43 +01:00
2006-01-16 22:02:54 +01:00
// Set locale
2014-05-15 19:19:23 +02:00
auto lang = OPT_GET ( " App/Language " ) - > GetString ( ) ;
if ( lang . empty ( ) | | ( lang ! = " en_US " & & ! locale . HasLanguage ( lang ) ) ) {
2006-01-16 22:02:54 +01:00
lang = locale . PickLanguage ( ) ;
2014-05-15 19:19:23 +02:00
OPT_SET ( " App/Language " ) - > SetString ( lang ) ;
2006-01-16 22:02:54 +01:00
}
locale . Init ( lang ) ;
2014-03-26 19:33:33 +01:00
# ifdef __APPLE__
// When run from an app bundle, LC_CTYPE defaults to "C", which breaks on
// anything involving unicode and in some cases number formatting.
// The right thing to do here would be to query CoreFoundation for the user's
// locale and add .UTF-8 to that, but :effort:
setlocale ( LC_CTYPE , " en_US.UTF-8 " ) ;
# endif
2014-03-19 17:19:20 +01:00
exception_message = _ ( " Oops, Aegisub has crashed! \n \n An attempt has been made to save a copy of your file to: \n \n %s \n \n Aegisub will now close. " ) ;
2008-03-07 01:47:57 +01:00
// Load plugins
2014-04-23 22:53:24 +02:00
Automation4 : : ScriptFactory : : Register ( agi : : make_unique < Automation4 : : LuaScriptFactory > ( ) ) ;
2014-03-24 15:54:22 +01:00
libass : : CacheFonts ( ) ;
2007-04-22 17:45:29 +02:00
2006-12-28 23:31:33 +01:00
// Load Automation scripts
2011-09-28 21:43:11 +02:00
StartupLog ( " Load global Automation scripts " ) ;
2014-06-06 17:24:33 +02:00
config : : global_scripts = new Automation4 : : AutoloadScriptManager ( OPT_GET ( " Path/Automation/Autoload " ) - > GetString ( ) ) ;
2006-12-28 23:31:33 +01:00
2006-01-16 22:02:54 +01:00
// Load export filters
2011-09-28 21:43:11 +02:00
StartupLog ( " Register export filters " ) ;
2014-04-23 22:53:24 +02:00
AssExportFilterChain : : Register ( agi : : make_unique < AssFixStylesFilter > ( ) ) ;
AssExportFilterChain : : Register ( agi : : make_unique < AssTransformFramerateFilter > ( ) ) ;
2006-01-16 22:02:54 +01:00
2014-03-26 19:33:33 +01:00
StartupLog ( " Install PNG handler " ) ;
wxImage : : AddHandler ( new wxPNGHandler ) ;
2013-02-05 16:52:24 +01:00
// Open main frame
StartupLog ( " Create main window " ) ;
2015-08-23 03:17:51 +02:00
NewProjectContext ( ) ;
2013-02-05 16:52:24 +01:00
2014-03-26 19:33:33 +01:00
// Version checker
StartupLog ( " Possibly perform automatic updates check " ) ;
if ( OPT_GET ( " App/First Start " ) - > GetBool ( ) ) {
OPT_SET ( " App/First Start " ) - > SetBool ( false ) ;
# ifdef WITH_UPDATE_CHECKER
int result = wxMessageBox ( _ ( " Do you want Aegisub to check for updates whenever it starts? You can still do it manually via the Help menu. " ) , _ ( " Check for updates? " ) , wxYES_NO | wxCENTER ) ;
OPT_SET ( " App/Auto/Check For Updates " ) - > SetBool ( result = = wxYES ) ;
try {
config : : opt - > Flush ( ) ;
}
catch ( agi : : fs : : FileSystemError const & e ) {
wxMessageBox ( to_wx ( e . GetMessage ( ) ) , " Error saving config file " , wxOK | wxICON_ERROR | wxCENTER ) ;
}
# endif
}
# ifdef WITH_UPDATE_CHECKER
PerformVersionCheck ( false ) ;
# endif
2006-01-16 22:02:54 +01:00
// Get parameter subs
2011-09-28 21:43:11 +02:00
StartupLog ( " Parse command line " ) ;
2016-01-11 04:47:09 +01:00
auto const & args = argv . GetArguments ( ) ;
2016-02-07 04:56:37 +01:00
if ( args . size ( ) > 1 )
OpenFiles ( wxArrayStringsAdapter ( args . size ( ) - 1 , & args [ 1 ] ) ) ;
2006-01-16 22:02:54 +01:00
}
2010-06-03 22:32:25 +02:00
catch ( agi : : Exception const & e ) {
2014-05-22 01:23:28 +02:00
wxMessageBox ( to_wx ( e . GetMessage ( ) ) , " Fatal error while initializing " ) ;
2010-06-03 22:32:25 +02:00
return false ;
}
2014-06-06 17:09:28 +02:00
catch ( std : : exception const & e ) {
wxMessageBox ( to_wx ( e . what ( ) ) , " Fatal error while initializing " ) ;
return false ;
}
2011-08-27 08:29:36 +02:00
# ifndef _DEBUG
2006-01-16 22:02:54 +01:00
catch ( . . . ) {
2011-09-28 21:43:11 +02:00
wxMessageBox ( " Unhandled exception " , " Fatal error while initializing " ) ;
2006-01-16 22:02:54 +01:00
return false ;
}
2011-08-27 08:29:36 +02:00
# endif
2006-01-16 22:02:54 +01:00
2012-10-25 00:21:36 +02:00
StartupLog ( " Clean old autosave files " ) ;
2013-01-30 04:35:37 +01:00
CleanCache ( config : : path - > Decode ( OPT_GET ( " Path/Auto/Save " ) - > GetString ( ) ) , " *.AUTOSAVE.ass " , 100 , 1000 ) ;
2012-10-25 00:21:36 +02:00
2011-09-28 21:43:11 +02:00
StartupLog ( " Initialization complete " ) ;
2006-01-16 22:02:54 +01:00
return true ;
}
2007-01-15 06:38:32 +01:00
int AegisubApp : : OnExit ( ) {
2015-08-23 03:17:51 +02:00
for ( auto frame : frames )
2012-05-16 16:23:16 +02:00
delete frame ;
2015-08-23 03:17:51 +02:00
frames . clear ( ) ;
2012-05-16 16:23:16 +02:00
2014-03-07 17:33:47 +01:00
if ( wxTheClipboard - > Open ( ) ) {
wxTheClipboard - > Flush ( ) ;
wxTheClipboard - > Close ( ) ;
}
2010-06-18 04:23:27 +02:00
delete config : : opt ;
delete config : : mru ;
2011-10-28 22:40:32 +02:00
hotkey : : clear ( ) ;
2011-07-15 19:36:17 +02:00
cmd : : clear ( ) ;
Merge the dynamic menu, hotkey and toolbar branch to trunk. This doesn't include Windows support as vs2008 was being a major pain. This involves revisions r4921:4950, r4961:5002, r5005:5006, r5008:5056, r5062:5065, r5072, r5081:5082, r5087, r5096:5110, r5124:5125. Updates #1258.
Originally committed to SVN as r5126.
2011-01-05 14:00:46 +01:00
2014-06-06 17:24:33 +02:00
delete config : : global_scripts ;
2011-07-15 19:36:26 +02:00
AssExportFilterChain : : Clear ( ) ;
Merge the dynamic menu, hotkey and toolbar branch to trunk. This doesn't include Windows support as vs2008 was being a major pain. This involves revisions r4921:4950, r4961:5002, r5005:5006, r5008:5056, r5062:5065, r5072, r5081:5082, r5087, r5096:5110, r5124:5125. Updates #1258.
Originally committed to SVN as r5126.
2011-01-05 14:00:46 +01:00
// Keep this last!
delete agi : : log : : log ;
2014-03-20 17:50:05 +01:00
crash_writer : : Cleanup ( ) ;
Merge the dynamic menu, hotkey and toolbar branch to trunk. This doesn't include Windows support as vs2008 was being a major pain. This involves revisions r4921:4950, r4961:5002, r5005:5006, r5008:5056, r5062:5065, r5072, r5081:5082, r5087, r5096:5110, r5124:5125. Updates #1258.
Originally committed to SVN as r5126.
2011-01-05 14:00:46 +01:00
2007-01-15 06:38:32 +01:00
return wxApp : : OnExit ( ) ;
}
2015-08-23 03:17:51 +02:00
agi : : Context & AegisubApp : : NewProjectContext ( ) {
auto frame = new FrameMain ;
2016-01-02 22:46:40 +01:00
frame - > Bind ( wxEVT_DESTROY , [ = ] ( wxWindowDestroyEvent & evt ) {
if ( evt . GetWindow ( ) ! = frame ) {
evt . Skip ( ) ;
return ;
}
2015-08-23 03:17:51 +02:00
frames . erase ( remove ( begin ( frames ) , end ( frames ) , frame ) , end ( frames ) ) ;
if ( frames . empty ( ) ) {
ExitMainLoop ( ) ;
}
} ) ;
frames . push_back ( frame ) ;
return * frame - > context ;
}
2015-08-31 03:18:07 +02:00
void AegisubApp : : CloseAll ( ) {
for ( auto frame : frames ) {
if ( ! frame - > Close ( ) )
break ;
}
}
2015-08-23 03:17:51 +02:00
void AegisubApp : : UnhandledException ( bool stackWalk ) {
2012-01-25 20:07:07 +01:00
# if (!defined(_DEBUG) || defined(WITH_EXCEPTIONS)) && (wxUSE_ON_FATAL_EXCEPTION+0)
2015-08-23 03:17:51 +02:00
bool any = false ;
agi : : fs : : path path ;
for ( auto & frame : frames ) {
auto c = frame - > context . get ( ) ;
if ( ! c | | ! c - > ass | | ! c - > subsController ) continue ;
path = config : : path - > Decode ( " ?user/recovered " ) ;
2013-01-04 16:01:50 +01:00
agi : : fs : : CreateDirectory ( path ) ;
2010-10-20 02:28:37 +02:00
2013-01-26 02:57:46 +01:00
auto filename = c - > subsController - > Filename ( ) . stem ( ) ;
2014-05-29 00:19:05 +02:00
filename . replace_extension ( agi : : format ( " %s.ass " , agi : : util : : strftime ( " %Y-%m-%d-%H-%M-%S " ) ) ) ;
2013-12-23 19:00:24 +01:00
path / = filename ;
2013-01-26 02:57:46 +01:00
c - > subsController - > Save ( path ) ;
2009-09-03 07:27:11 +02:00
2015-08-23 03:17:51 +02:00
any = true ;
}
if ( stackWalk )
crash_writer : : Write ( ) ;
2006-02-21 06:26:13 +01:00
2015-08-23 03:17:51 +02:00
if ( any ) {
2010-10-20 02:28:37 +02:00
// Inform user of crash.
2014-05-29 17:28:37 +02:00
wxMessageBox ( agi : : wxformat ( exception_message , path ) , _ ( " Program error " ) , wxOK | wxICON_ERROR | wxCENTER , nullptr ) ;
2010-10-20 02:28:37 +02:00
}
else if ( LastStartupState ) {
2014-05-29 17:28:37 +02:00
wxMessageBox ( fmt_wx ( " Aegisub has crashed while starting up! \n \n The last startup step attempted was: %s. " , LastStartupState ) , _ ( " Program error " ) , wxOK | wxICON_ERROR | wxCENTER ) ;
2010-10-20 02:28:37 +02:00
}
2012-01-25 20:07:07 +01:00
# endif
2010-10-20 02:28:37 +02:00
}
void AegisubApp : : OnUnhandledException ( ) {
2015-08-23 03:17:51 +02:00
UnhandledException ( false ) ;
2006-01-16 22:02:54 +01:00
}
2009-09-03 07:27:11 +02:00
void AegisubApp : : OnFatalException ( ) {
2015-08-23 03:17:51 +02:00
UnhandledException ( true ) ;
2006-02-21 06:26:13 +01:00
}
2013-12-23 18:07:20 +01:00
# define SHOW_EXCEPTION(str) \
2014-05-29 17:28:37 +02:00
wxMessageBox ( fmt_tl ( " An unexpected error has occurred. Please save your work and restart Aegisub. \n \n Error Message: %s " , str ) , \
2013-12-23 18:07:20 +01:00
" Exception in event handler " , wxOK | wxICON_ERROR | wxCENTER | wxSTAY_ON_TOP )
bool AegisubApp : : OnExceptionInMainLoop ( ) {
try {
throw ;
}
catch ( const agi : : Exception & e ) {
2014-05-29 14:57:27 +02:00
SHOW_EXCEPTION ( to_wx ( e . GetMessage ( ) ) ) ;
2013-12-23 18:07:20 +01:00
}
catch ( const std : : exception & e ) {
SHOW_EXCEPTION ( to_wx ( e . what ( ) ) ) ;
}
catch ( . . . ) {
SHOW_EXCEPTION ( " Unknown error " ) ;
}
return true ;
2010-06-29 12:31:15 +02:00
}
2013-12-23 18:07:20 +01:00
# undef SHOW_EXCEPTION
2006-01-16 22:02:54 +01:00
int AegisubApp : : OnRun ( ) {
2013-01-04 16:01:50 +01:00
std : : string error ;
2008-03-10 07:28:21 +01:00
2006-01-16 22:02:54 +01:00
try {
return MainLoop ( ) ;
}
2013-01-04 16:01:50 +01:00
catch ( const std : : exception & e ) { error = std : : string ( " std::exception: " ) + e . what ( ) ; }
2014-05-29 14:57:27 +02:00
catch ( const agi : : Exception & e ) { error = " agi::exception: " + e . GetMessage ( ) ; }
2011-09-28 21:43:11 +02:00
catch ( . . . ) { error = " Program terminated in error. " ; }
2008-03-10 07:28:21 +01:00
// Report errors
2013-01-04 16:01:50 +01:00
if ( ! error . empty ( ) ) {
2014-03-19 17:15:25 +01:00
crash_writer : : Write ( error ) ;
2008-03-10 07:28:21 +01:00
OnUnhandledException ( ) ;
2006-01-16 22:02:54 +01:00
}
ExitMainLoop ( ) ;
return 1 ;
}
2015-08-23 03:17:51 +02:00
void AegisubApp : : MacOpenFiles ( wxArrayString const & filenames ) {
OpenFiles ( filenames ) ;
}
void AegisubApp : : OpenFiles ( wxArrayStringsAdapter filenames ) {
std : : vector < agi : : fs : : path > files ;
2017-12-30 23:43:06 +01:00
for ( size_t i = 0 ; i < filenames . GetCount ( ) ; + + i )
2016-01-11 04:47:09 +01:00
files . push_back ( from_wx ( filenames [ i ] ) ) ;
2015-08-23 03:17:51 +02:00
if ( ! files . empty ( ) )
frames [ 0 ] - > context - > project - > LoadList ( files ) ;
2006-06-19 04:57:27 +02:00
}