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
2009-01-04 07:31:48 +01:00
# include "config.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
2009-09-10 15:06:40 +02:00
# include "ass_dialogue.h"
2006-01-16 22:02:54 +01:00
# include "ass_file.h"
2007-12-31 07:46:22 +01:00
# include "auto4_base.h"
2010-05-21 03:13:36 +02:00
# include "compat.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"
# include "frame_main.h"
2013-01-26 02:57:46 +01:00
# include "include/aegisub/context.h"
2013-01-04 16:01:50 +01:00
# include "main.h"
2010-05-21 03:13:36 +02:00
# include "libresrc/libresrc.h"
2013-01-07 02:50:09 +01:00
# include "options.h"
2009-09-10 15:06:40 +02:00
# include "plugin_manager.h"
2013-01-26 02:57:46 +01:00
# include "subs_controller.h"
2009-09-10 15:06:40 +02:00
# include "subtitle_format.h"
# include "version.h"
# include "video_context.h"
2012-04-04 00:44:47 +02:00
# include "utils.h"
2006-01-16 22:02:54 +01:00
2013-01-04 16:01:50 +01:00
# include <libaegisub/dispatch.h>
# include <libaegisub/fs.h>
# include <libaegisub/hotkey.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>
2013-01-04 16:01:50 +01:00
# include <libaegisub/path.h>
# include <libaegisub/util.h>
2006-01-16 22:02:54 +01:00
2013-01-04 16:01:50 +01:00
# include <boost/filesystem/fstream.hpp>
# include <boost/format.hpp>
2013-01-29 16:10:35 +01:00
# include <boost/locale.hpp>
2013-01-07 02:50:09 +01:00
# include <sstream>
# include <wx/config.h>
# 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 ;
2010-06-18 04:23:27 +02:00
}
2006-01-16 22:02:54 +01:00
IMPLEMENT_APP ( AegisubApp )
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
2011-09-28 21:43:11 +02:00
# define StartupLog(a) MessageBox(0, L ## a, L"Aegisub startup log", 0)
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 " ) ;
}
2013-01-04 16:01:50 +01:00
wxDEFINE_EVENT ( EVT_CALL_THUNK , wxThreadEvent ) ;
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 ( ) ;
2013-01-29 16:10:35 +01:00
// Set the global locale to the utf-8 version of the current locale
std : : locale : : global ( boost : : locale : : generator ( ) . generate ( " " ) ) ;
2014-01-12 18:53:24 +01:00
# ifndef __APPLE__
// Boost.FileSystem always uses UTF-8 for paths on OS X (since paths
// actually are required to be UTF-8 strings rather than just opaque binary
// blobs like on Linux), so there's no need to imbue the new locale and in
// fact it actively breaks things for unknown reasons when launching the
// app from Finder (but not from the command line).
2013-01-29 16:10:35 +01:00
boost : : filesystem : : path : : imbue ( std : : locale ( ) ) ;
2014-01-12 18:53:24 +01:00
# endif
2013-01-29 16:10:35 +01:00
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 ) {
2013-11-21 18:13:36 +01:00
auto evt = new wxThreadEvent ( EVT_CALL_THUNK ) ;
2013-01-04 16:01:50 +01:00
evt - > SetPayload ( f ) ;
wxTheApp - > QueueEvent ( evt ) ;
} ) ;
wxTheApp - > Bind ( EVT_CALL_THUNK , [ ] ( wxThreadEvent & evt ) {
2012-11-26 04:06:18 +01:00
evt . GetPayload < std : : function < void ( ) > > ( ) ( ) ;
} ) ;
2013-01-04 16:01:50 +01:00
config : : path = new agi : : Path ;
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
2013-06-12 05:38:12 +02:00
agi : : log : : log - > Subscribe ( agi : : util : : 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 " ) ) ;
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 ) ;
2013-06-12 05:38:12 +02:00
agi : : log : : log - > Subscribe ( agi : : util : : 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 ) ) ;
2012-04-06 03:55:22 +02:00
std : : istringstream stream ( GET_DEFAULT_CONFIG ( default_config_platform ) ) ;
config : : opt - > ConfigNext ( stream ) ;
2012-01-08 02:35:56 +01:00
} catch ( agi : : Exception & e ) {
LOG_E ( " config/init " ) < < " Caught exception: " < < e . GetName ( ) < < " -> " < < e . GetMessage ( ) ;
}
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
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 " ) ;
2012-11-13 17:51:01 +01:00
frame = nullptr ;
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
2012-12-23 00:18:38 +01:00
wxString lang = to_wx ( OPT_GET ( " App/Language " ) - > GetString ( ) ) ;
2012-10-02 21:28:55 +02:00
if ( ! lang ) {
2006-01-16 22:02:54 +01:00
lang = locale . PickLanguage ( ) ;
2012-12-23 00:18:38 +01:00
OPT_SET ( " App/Language " ) - > SetString ( from_wx ( lang ) ) ;
2006-01-16 22:02:54 +01:00
}
locale . Init ( lang ) ;
2008-03-07 01:47:57 +01:00
// Load plugins
2013-06-08 06:19:40 +02:00
RegisterBuiltInPlugins ( ) ;
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 " ) ;
2013-01-04 16:01:50 +01:00
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 " ) ;
2013-06-08 06:19:40 +02:00
AssExportFilterChain : : Register ( agi : : util : : make_unique < AssFixStylesFilter > ( ) ) ;
AssExportFilterChain : : Register ( agi : : util : : make_unique < AssTransformFramerateFilter > ( ) ) ;
2006-01-16 22:02:54 +01:00
2013-02-05 16:52:24 +01:00
// Open main frame
StartupLog ( " Create main window " ) ;
frame = new FrameMain ;
SetTopWindow ( frame ) ;
2006-01-16 22:02:54 +01:00
// Get parameter subs
2011-09-28 21:43:11 +02:00
StartupLog ( " Parse command line " ) ;
2006-01-16 22:02:54 +01:00
wxArrayString subs ;
2012-11-04 04:53:03 +01:00
for ( int i = 1 ; i < argc ; + + i )
subs . push_back ( argv [ i ] ) ;
2013-02-05 16:52:24 +01:00
if ( ! subs . empty ( ) )
frame - > LoadList ( subs ) ;
2006-01-16 22:02:54 +01:00
}
2011-09-28 21:43:11 +02:00
catch ( const char * err ) {
wxMessageBox ( err , " Fatal error while initializing " ) ;
2006-01-16 22:02:54 +01:00
return false ;
}
2012-12-31 16:49:57 +01:00
catch ( wxString const & err ) {
wxMessageBox ( err , " Fatal error while initializing " ) ;
return false ;
}
2010-06-03 22:32:25 +02:00
catch ( agi : : Exception const & e ) {
2012-12-30 01:53:30 +01:00
wxMessageBox ( to_wx ( e . GetMessage ( ) ) , " Fatal error while initializing " ) ;
2010-06-03 22:32:25 +02:00
return false ;
}
2006-01-16 22:02:54 +01:00
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 ( ) {
2012-05-16 16:23:16 +02:00
if ( frame )
delete frame ;
2014-03-07 17:33:47 +01:00
if ( wxTheClipboard - > Open ( ) ) {
wxTheClipboard - > Flush ( ) ;
wxTheClipboard - > Close ( ) ;
}
2007-01-15 07:56:35 +01:00
SubtitleFormat : : DestroyFormats ( ) ;
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
2007-01-15 07:56:35 +01:00
delete 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 ;
2007-01-15 06:38:32 +01:00
return wxApp : : OnExit ( ) ;
}
2013-01-07 02:33:18 +01:00
# if wxUSE_STACKWALKER == 1
class StackWalker : public wxStackWalker {
2013-01-04 16:01:50 +01:00
boost : : filesystem : : ofstream fp ;
2013-01-07 02:33:18 +01:00
public :
2013-01-04 16:01:50 +01:00
StackWalker ( std : : string const & cause ) ;
2013-01-07 02:33:18 +01:00
~ StackWalker ( ) ;
2013-11-21 18:13:36 +01:00
void OnStackFrame ( wxStackFrame const & frame ) override ;
2013-01-07 02:33:18 +01:00
} ;
/// @brief Called at the start of walking the stack.
/// @param cause cause of the crash.
2013-01-04 16:01:50 +01:00
StackWalker : : StackWalker ( std : : string const & cause )
2013-01-30 04:35:37 +01:00
: fp ( config : : path - > Decode ( " ?user/crashlog.txt " ) , std : : ios : : app )
2013-01-04 16:01:50 +01:00
{
if ( ! fp . good ( ) ) return ;
fp < < agi : : util : : strftime ( " --- %y-%m-%d %H:%M:%S ------------------ \n " ) ;
fp < < boost : : format ( " VER - %s \n " ) % GetAegisubLongVersionString ( ) ;
fp < < boost : : format ( " FTL - Beginning stack dump for \" %s \" : \n " ) % cause ;
2013-01-07 02:33:18 +01:00
}
/// @brief Callback to format a single frame
/// @param frame frame to parse.
2013-01-04 16:01:50 +01:00
void StackWalker : : OnStackFrame ( wxStackFrame const & frame ) {
if ( ! fp . good ( ) ) return ;
2013-01-07 02:33:18 +01:00
2013-12-10 19:38:46 +01:00
fp < < boost : : format ( " %03u - %p: %s " ) % frame . GetLevel ( ) % frame . GetAddress ( ) % frame . GetName ( ) . utf8_str ( ) . data ( ) ;
2013-01-04 16:01:50 +01:00
if ( frame . HasSourceLocation ( ) )
2013-12-23 19:19:01 +01:00
fp < < boost : : format ( " on %s:%u " ) % frame . GetFileName ( ) . utf8_str ( ) . data ( ) % frame . GetLine ( ) ;
2013-01-04 16:01:50 +01:00
fp < < " \n " ;
2013-01-07 02:33:18 +01:00
}
/// @brief Called at the end of walking the stack.
StackWalker : : ~ StackWalker ( ) {
2013-01-04 16:01:50 +01:00
if ( ! fp . good ( ) ) return ;
2013-01-07 02:33:18 +01:00
2013-01-04 16:01:50 +01:00
fp < < " End of stack dump. \n " ;
fp < < " ---------------------------------------- \n \n " ;
2013-01-07 02:33:18 +01:00
}
# endif
2009-09-02 22:46:15 +02:00
/// Message displayed when an exception has occurred.
const 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. " ) ;
Note: This was done using a script! it's far from perfect but 95% of the work has been done already formatting-wise.
Document all functions, class, struct, union, enum, macro, variable, typedefs. This isn't the actual document in itself but empty documentation using any old documentation if it was there.
This was done using exuberant ctags to get tag info, then a TCL script to parse/remove old comments and convert them into Doxygen-style.
Some notes:
* Anything labeled 'DOCME' needs to be documented, @param and @return have been left blank as it would be annoying to delete the 'DOCME' from every one of those.
* Some multiline comments may have been munged into single line comments
* Leave the /// comments above global variables with a space, if they're harder to read then we'll be less likey to use them.
* Enum comments can go after the enumeration itself '[value] /// comment'
* include/aegisub/*.h haven't been converted yet, this will be done in a later commit
* Some documentation blocks are in the wrong place, in the .h when it should be in the .cpp, or vice versa.
See http://devel.aegisub.org/wiki/Doxygen for some details on Doxygen and a 'style guide'.
Originally committed to SVN as r3312.
2009-07-30 00:59:22 +02:00
2013-01-26 02:57:46 +01:00
static void UnhandledExeception ( bool stackWalk , agi : : Context * c ) {
2012-01-25 20:07:07 +01:00
# if (!defined(_DEBUG) || defined(WITH_EXCEPTIONS)) && (wxUSE_ON_FATAL_EXCEPTION+0)
2013-01-26 02:57:46 +01:00
if ( c - > ass & & c - > subsController ) {
2013-01-30 04:35:37 +01:00
auto 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 ( ) ;
2013-12-23 19:00:24 +01:00
filename . replace_extension ( str ( boost : : format ( " %s.ass " ) % agi : : util : : strftime ( " %Y-%m-%d-%H-%M-%S " ) ) ) ;
path / = filename ;
2013-01-26 02:57:46 +01:00
c - > subsController - > Save ( path ) ;
2009-09-03 07:27:11 +02:00
2010-10-20 02:28:37 +02:00
# if wxUSE_STACKWALKER == 1
if ( stackWalk ) {
2011-09-28 21:43:11 +02:00
StackWalker walker ( " Fatal exception " ) ;
2010-10-20 02:28:37 +02:00
walker . WalkFromException ( ) ;
}
# endif
2006-02-21 06:26:13 +01:00
2010-10-20 02:28:37 +02:00
// Inform user of crash.
2013-01-04 16:01:50 +01:00
wxMessageBox ( wxString : : Format ( exception_message , path . wstring ( ) ) , _ ( " Program error " ) , wxOK | wxICON_ERROR | wxCENTER , nullptr ) ;
2010-10-20 02:28:37 +02:00
}
else if ( LastStartupState ) {
# if wxUSE_STACKWALKER == 1
if ( stackWalk ) {
2011-09-28 21:43:11 +02:00
StackWalker walker ( " Fatal exception " ) ;
2010-10-20 02:28:37 +02:00
walker . WalkFromException ( ) ;
}
# endif
2012-03-29 01:59:19 +02:00
wxMessageBox ( wxString : : Format ( " 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 ( ) {
2013-01-26 02:57:46 +01:00
UnhandledExeception ( false , frame ? frame - > context . get ( ) : nullptr ) ;
2006-01-16 22:02:54 +01:00
}
2009-09-03 07:27:11 +02:00
void AegisubApp : : OnFatalException ( ) {
2013-01-26 02:57:46 +01:00
UnhandledExeception ( true , frame ? frame - > context . get ( ) : nullptr ) ;
2006-02-21 06:26:13 +01:00
}
2013-12-23 18:07:20 +01:00
# define SHOW_EXCEPTION(str) \
wxMessageBox ( wxString : : Format ( _ ( " An unexpected error has occurred. Please save your work and restart Aegisub. \n \n Error Message: %s " ) , str ) , \
" Exception in event handler " , wxOK | wxICON_ERROR | wxCENTER | wxSTAY_ON_TOP )
2010-06-29 12:31:15 +02:00
void AegisubApp : : HandleEvent ( wxEvtHandler * handler , wxEventFunction func , wxEvent & event ) const {
try {
wxApp : : HandleEvent ( handler , func , event ) ;
}
catch ( const agi : : Exception & e ) {
2012-12-23 00:18:38 +01:00
SHOW_EXCEPTION ( to_wx ( e . GetChainedMessage ( ) ) ) ;
2010-06-29 12:31:15 +02:00
}
catch ( const std : : exception & e ) {
2013-01-04 16:01:50 +01:00
SHOW_EXCEPTION ( to_wx ( e . what ( ) ) ) ;
2010-06-29 12:31:15 +02:00
}
catch ( const char * e ) {
2013-01-04 16:01:50 +01:00
SHOW_EXCEPTION ( to_wx ( e ) ) ;
2010-06-29 12:31:15 +02:00
}
catch ( const wxString & e ) {
SHOW_EXCEPTION ( e ) ;
}
2013-12-23 18:07:20 +01:00
catch ( . . . ) {
SHOW_EXCEPTION ( " Unknown error " ) ;
}
}
bool AegisubApp : : OnExceptionInMainLoop ( ) {
try {
throw ;
}
catch ( const agi : : Exception & e ) {
SHOW_EXCEPTION ( to_wx ( e . GetChainedMessage ( ) ) ) ;
}
catch ( const std : : exception & e ) {
SHOW_EXCEPTION ( to_wx ( e . what ( ) ) ) ;
}
catch ( const char * e ) {
SHOW_EXCEPTION ( to_wx ( e ) ) ;
}
catch ( const wxString & e ) {
SHOW_EXCEPTION ( e ) ;
}
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 {
if ( m_exitOnFrameDelete = = Later ) m_exitOnFrameDelete = Yes ;
return MainLoop ( ) ;
}
2013-01-04 16:01:50 +01:00
catch ( const wxString & err ) { error = from_wx ( err ) ; }
2011-09-28 21:43:11 +02:00
catch ( const char * err ) { error = err ; }
2013-01-04 16:01:50 +01:00
catch ( const std : : exception & e ) { error = std : : string ( " std::exception: " ) + e . what ( ) ; }
catch ( const agi : : Exception & e ) { error = " agi::exception: " + e . GetChainedMessage ( ) ; }
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 ( ) ) {
2013-01-30 04:35:37 +01:00
boost : : filesystem : : ofstream file ( config : : path - > Decode ( " ?user/crashlog.txt " ) , std : : ios : : app ) ;
2008-03-10 07:28:21 +01:00
if ( file . is_open ( ) ) {
2013-01-04 16:01:50 +01:00
file < < agi : : util : : strftime ( " --- %y-%m-%d %H:%M:%S ------------------ \n " ) ;
file < < boost : : format ( " VER - %s \n " ) % GetAegisubLongVersionString ( ) ;
file < < boost : : format ( " EXC - Aegisub has crashed with unhandled exception \" %s \" . \n " ) % error ;
file < < " ---------------------------------------- \n \n " ;
2008-03-10 07:28:21 +01:00
file . close ( ) ;
}
2006-01-16 22:02:54 +01:00
2008-03-10 07:28:21 +01:00
OnUnhandledException ( ) ;
2006-01-16 22:02:54 +01:00
}
ExitMainLoop ( ) ;
return 1 ;
}
2006-06-19 04:57:27 +02:00
void AegisubApp : : MacOpenFile ( const wxString & filename ) {
2013-01-26 02:57:46 +01:00
if ( frame & & ! filename . empty ( ) )
frame - > context - > subsController - > Load ( agi : : fs : : path ( filename ) ) ;
2006-06-19 04:57:27 +02:00
}