diff --git a/common/include/Pcsx2Defs.h b/common/include/Pcsx2Defs.h index d1a2ee125..2218b0b57 100644 --- a/common/include/Pcsx2Defs.h +++ b/common/include/Pcsx2Defs.h @@ -70,7 +70,11 @@ # endif # else # define jBREAKPOINT() __debugbreak(); -# define jASSUME(exp) do { if(exp) ; else jBREAKPOINT(); } while(0); +# ifdef wxASSERT +# define jASSUME(exp) wxASSERT(exp) +# else +# define jASSUME(exp) do { if(exp) ; else jBREAKPOINT(); } while(0); +# endif # endif #endif diff --git a/common/include/x86emitter/inlines.inl b/common/include/x86emitter/inlines.inl index e2c097b37..f1eec1b44 100644 --- a/common/include/x86emitter/inlines.inl +++ b/common/include/x86emitter/inlines.inl @@ -203,7 +203,7 @@ namespace x86Emitter Factor++; else { - jASSUME( Index.IsEmpty() ); // or die if we already have an index! + DevAssert( Index.IsEmpty(), "x86Emitter: Only one scaled index register is allowed in an address modifier." ); Index = src; Factor = 2; } @@ -213,7 +213,7 @@ namespace x86Emitter else if( Index.IsEmpty() ) Index = src; else - assert( false ); // oops, only 2 regs allowed per ModRm! + wxASSERT_MSG( false, L"x86Emitter: address modifiers cannot have more than two index registers." ); // oops, only 2 regs allowed per ModRm! return *this; } @@ -237,7 +237,7 @@ namespace x86Emitter else if( Index == src.Index ) Factor++; else - assert( false ); // oops, only 2 regs allowed! + wxASSERT_MSG( false, L"x86Emitter: address modifiers cannot have more than two index registers." ); // oops, only 2 regs allowed per ModRm! return *this; } @@ -283,7 +283,7 @@ namespace x86Emitter { if( !is_s8( displacement ) ) { - assert( false ); + wxASSERT( false ); // Don't ask. --arcum42 #if !defined(__LINUX__) || !defined(DEBUG) diff --git a/pcsx2/Linux/LnxKeyCodes.cpp b/pcsx2/Linux/LnxKeyCodes.cpp index 9a97dd8df..bdc3529cd 100644 --- a/pcsx2/Linux/LnxKeyCodes.cpp +++ b/pcsx2/Linux/LnxKeyCodes.cpp @@ -282,7 +282,7 @@ int TranslateGDKtoWXK( u32 keysym ) // window, same as the Win32 one. Not sure how doable it is, and it's not as urgent // anyway since Linux has better generic console support and commandline piping. // -PipeRedirectionBase* NewPipeRedir() +PipeRedirectionBase* NewPipeRedir( FILE* stdstream ) { return NULL; } diff --git a/pcsx2/PluginManager.cpp b/pcsx2/PluginManager.cpp index afabf938d..dd617b688 100644 --- a/pcsx2/PluginManager.cpp +++ b/pcsx2/PluginManager.cpp @@ -664,8 +664,7 @@ PluginManager::PluginManager( const wxString (&folders)[PluginId_Count] ) { Console::Status( "Loading plugins..." ); - const PluginInfo* pi = tbl_PluginInfo-1; - while( ++pi, pi->shortname != NULL ) + const PluginInfo* pi = tbl_PluginInfo; do { const PluginsEnum_t pid = pi->id; @@ -700,7 +699,7 @@ PluginManager::PluginManager( const wxString (&folders)[PluginId_Count] ) // Bind Optional Functions // (leave pointer null and do not generate error) - } + } while( ++pi, pi->shortname != NULL ); // Hack for PAD's stupid parameter passed on Init PADinit = (_PADinit)m_info[PluginId_PAD].CommonBindings.Init; @@ -916,9 +915,9 @@ void PluginManager::Open() { Console::Status( "Opening plugins..." ); - const PluginInfo* pi = tbl_PluginInfo-1; - while( ++pi, pi->shortname != NULL ) + const PluginInfo* pi = tbl_PluginInfo; do { g_plugins->Open( pi->id ); + } while( ++pi, pi->shortname != NULL ); Console::Status( "Plugins opened successfully." ); } @@ -970,8 +969,7 @@ void PluginManager::Close( bool closegs ) void PluginManager::Init() { bool printlog = false; - const PluginInfo* pi = tbl_PluginInfo-1; - while( ++pi, pi->shortname != NULL ) + const PluginInfo* pi = tbl_PluginInfo; do { const PluginsEnum_t pid = pi->id; @@ -985,7 +983,7 @@ void PluginManager::Init() m_info[pid].IsInitialized = true; if( 0 != m_info[pid].CommonBindings.Init() ) throw Exception::PluginInitError( pid ); - } + } while( ++pi, pi->shortname != NULL ); if( EmuPlugins.Mcd == NULL ) { @@ -1106,13 +1104,10 @@ void PluginManager::Freeze( PluginsEnum_t pid, SaveStateBase& state ) bool PluginManager::KeyEvent( const keyEvent& evt ) { - const PluginInfo* pi = tbl_PluginInfo-1; - - while( ++pi, pi->shortname != NULL ) - { + const PluginInfo* pi = tbl_PluginInfo; do { if( pi->id != PluginId_PAD ) m_info[pi->id].CommonBindings.KeyEvent( const_cast(&evt) ); - } + } while( ++pi, pi->shortname != NULL ); return false; } @@ -1135,9 +1130,9 @@ PluginManager* PluginManager_Create( const wxChar* (&folders)[PluginId_Count] ) { wxString passins[PluginId_Count]; - const PluginInfo* pi = tbl_PluginInfo-1; - while( ++pi, pi->shortname != NULL ) + const PluginInfo* pi = tbl_PluginInfo; do { passins[pi->id] = folders[pi->id]; + } while( ++pi, pi->shortname != NULL ); return PluginManager_Create( passins ); } diff --git a/pcsx2/VUops.cpp b/pcsx2/VUops.cpp index c5523b69e..72d9308df 100644 --- a/pcsx2/VUops.cpp +++ b/pcsx2/VUops.cpp @@ -318,22 +318,20 @@ __forceinline void _vuAddLowerStalls(VURegs * VU, _VURegsNum *VUregsn) { #ifndef INT_VUDOUBLEHACK static float __fastcall vuDouble(u32 f) { - switch(f & 0x7f800000){ + switch(f & 0x7f800000) + { case 0x0: f &= 0x80000000; return *(float*)&f; break; case 0x7f800000: { - u32 d; - d = (f & 0x80000000)|0x7f7fffff; + u32 d = (f & 0x80000000)|0x7f7fffff; return *(float*)&d; break; } - default: - return *(float*)&f; - break; } + return *(float*)&f; } #else static __forceinline float vuDouble(u32 f) diff --git a/pcsx2/gui/App.h b/pcsx2/gui/App.h index 0e6f87a65..8652a6332 100644 --- a/pcsx2/gui/App.h +++ b/pcsx2/gui/App.h @@ -298,7 +298,8 @@ protected: wxScopedPtr m_ToolbarImages; wxScopedPtr m_Bitmap_Logo; - wxScopedPtrm_PipeRedirHandle; + wxScopedPtrm_StdoutRedirHandle; + wxScopedPtrm_StderrRedirHandle; public: wxScopedPtr m_CoreAllocs; diff --git a/pcsx2/gui/AppMain.cpp b/pcsx2/gui/AppMain.cpp index 1b730e891..94b770efe 100644 --- a/pcsx2/gui/AppMain.cpp +++ b/pcsx2/gui/AppMain.cpp @@ -325,13 +325,11 @@ void Pcsx2App::OnInitCmdLine( wxCmdLineParser& parser ) parser.AddSwitch( wxEmptyString,L"forcewiz",_("Forces PCSX2 to start the First-time Wizard") ); - const PluginInfo* pi = tbl_PluginInfo-1; - while( ++pi, pi->shortname != NULL ) - { + const PluginInfo* pi = tbl_PluginInfo; do { parser.AddOption( wxEmptyString, pi->GetShortname().Lower(), wxsFormat( _("specify the file to use as the %s plugin"), pi->GetShortname().c_str() ) ); - } + } while( ++pi, pi->shortname != NULL ); parser.SetSwitchChars( L"-" ); } @@ -356,8 +354,7 @@ bool Pcsx2App::OnCmdLineParsed( wxCmdLineParser& parser ) //bool yay = parser.Found(L"nogui"); m_ForceWizard = parser.Found( L"forcewiz" ); - const PluginInfo* pi = tbl_PluginInfo-1; - while( ++pi, pi->shortname != NULL ) + const PluginInfo* pi = tbl_PluginInfo; do { wxString dest; if( !parser.Found( pi->GetShortname().Lower(), &dest ) ) continue; @@ -377,7 +374,7 @@ bool Pcsx2App::OnCmdLineParsed( wxCmdLineParser& parser ) if( !result ) return false; } - } + } while( ++pi, pi->shortname != NULL ); parser.Found( L"cfgpath", &OverrideOptions.SettingsFolder ); @@ -394,16 +391,9 @@ bool Pcsx2App::OnInit() g_Conf.reset( new AppConfig() ); - try - { - m_PipeRedirHandle.reset( NewPipeRedir() ); - wxLocale::AddCatalogLookupPathPrefix( wxGetCwd() ); - } - catch( Exception::RuntimeError& ex ) - { - // Entirely non-critical errors. Log 'em and move along. - Console::Error( ex.FormatDiagnosticMessage() ); - } + m_StdoutRedirHandle.reset( NewPipeRedir(stdout) ); + m_StderrRedirHandle.reset( NewPipeRedir(stderr) ); + wxLocale::AddCatalogLookupPathPrefix( wxGetCwd() ); #define pxMessageBoxEventThing(func) \ (wxObjectEventFunction)(wxEventFunction)wxStaticCastEvent(pxMessageBoxEventFunction, &func ) diff --git a/pcsx2/gui/ConsoleLogger.h b/pcsx2/gui/ConsoleLogger.h index 18a72967c..699b9c330 100644 --- a/pcsx2/gui/ConsoleLogger.h +++ b/pcsx2/gui/ConsoleLogger.h @@ -42,7 +42,7 @@ protected: PipeRedirectionBase() {} }; -extern PipeRedirectionBase* NewPipeRedir(); +extern PipeRedirectionBase* NewPipeRedir( FILE* stdstream ); // -------------------------------------------------------------------------------------- // pxLogConsole diff --git a/pcsx2/gui/Dialogs/AboutBoxDialog.cpp b/pcsx2/gui/Dialogs/AboutBoxDialog.cpp index 36742ca27..03405eede 100644 --- a/pcsx2/gui/Dialogs/AboutBoxDialog.cpp +++ b/pcsx2/gui/Dialogs/AboutBoxDialog.cpp @@ -47,19 +47,18 @@ namespace Dialogs // -------------------------------------------------------------------------------------- Dialogs::AboutBoxDialog::AboutBoxDialog( wxWindow* parent, int id ): - wxDialog( parent, id, _("About PCSX2"), parent->GetPosition()-wxSize( 32, 32 ) ), - m_bitmap_logo( this, wxID_ANY, wxGetApp().GetLogoBitmap(), - wxDefaultPosition, wxDefaultSize, wxBORDER_SUNKEN ), - m_bitmap_ps2system( this, wxID_ANY, wxBitmap( EmbeddedImage().Get() ), + wxDialogWithHelpers( parent, id, _("About PCSX2"), false ), + m_bitmap_dualshock( this, wxID_ANY, wxBitmap( EmbeddedImage().Get() ), wxDefaultPosition, wxDefaultSize, wxBORDER_SUNKEN ) { - static const wxString LabelAuthors = wxString::FromAscii( - "PCSX2, a PS2 emulator\n\n" - "Active Devs: Arcum42, Refraction," - "drk||raziel, cottonvibes, gigaherz," - "rama, Jake.Stine, saqib, Tmkk" + static const wxString LabelAuthors = wxString::FromUTF8( + "Developers" "\n\n" - "Inactive devs: Alexey silinov, Aumatt," + "v0.9.6+: Arcum42, Refraction," + "drk||raziel, cottonvibes, gigaherz," + "rama, Jake.Stine, saqib, Tmkk, pseudonym" + "\n\n" + "Previous versions: Alexey silinov, Aumatt," "Florin, goldfinger, Linuzappz, loser," "Nachbrenner, shadow, Zerofrog" "\n\n" @@ -70,19 +69,23 @@ Dialogs::AboutBoxDialog::AboutBoxDialog( wxWindow* parent, int id ): "Webmasters: CKemu, Falcon4ever" ); - static const wxString LabelGreets = wxString::FromAscii( - "Contributors: Hiryu and Sjeep for libcvd (the iso parsing and\n" - "filesystem driver code), nneeve, pseudonym\n" - "\n" - "Plugin Specialists: ChickenLiver (Lilypad), Efp (efp),\n" - "Gabest (Gsdx, Cdvdolio, Xpad)\n" - "\n" - "Special thanks to: black_wd, Belmont, BGome, _Demo_, Dreamtime,\n" + static const wxString LabelGreets = wxString::FromUTF8( + "Contributors" + "\n\n" + "Hiryu and Sjeep for libcvd (the iso parsing and" + "filesystem driver code), nneeve (fpu and vu help)" + "\n\n" + "Plugin Specialists: ChickenLiver (Lilypad), Efp (efp)," + "Gabest (Gsdx, Cdvdolio, Xpad), Zeydlitz (ZZogl)" + "\n\n" + "Special thanks to: black_wd, Belmont, BGome, _Demo_, Dreamtime," "F|RES, MrBrown, razorblade, Seta-san, Skarmeth" ); wxBoxSizer& mainSizer = *new wxBoxSizer( wxVERTICAL ); + AddStaticText( mainSizer, _("PCSX2 - Playstation 2 Emulator") ); + // This sizer holds text of the authors and a logo! wxBoxSizer& AuthLogoSizer = *new wxBoxSizer( wxHORIZONTAL ); @@ -95,20 +98,19 @@ Dialogs::AboutBoxDialog::AboutBoxDialog( wxWindow* parent, int id ): StaticTextCentered* label_auth = new StaticTextCentered( this, LabelAuthors ); StaticTextCentered* label_greets = new StaticTextCentered( this, LabelGreets ); - label_auth->Wrap( m_bitmap_logo.GetSize().GetWidth() / 2 ); - label_greets->Wrap( (m_bitmap_logo.GetSize().GetWidth() * 4) / 3 ); + label_auth->Wrap( 340 ); + label_greets->Wrap( 200 ); - aboutUs.Add( label_auth, SizerFlags::StdSpace() ); + aboutUs.Add( label_auth, SizerFlags::StdExpand() ); contribs.Add( label_greets, SizerFlags::StdExpand() ); AuthLogoSizer.Add( &aboutUs ); AuthLogoSizer.AddSpacer( 7 ); - AuthLogoSizer.Add( &m_bitmap_logo, wxSizerFlags().Border( wxALL, 4 ) ); + AuthLogoSizer.Add( &contribs ); ContribSizer.AddStretchSpacer( 1 ); - ContribSizer.Add( &m_bitmap_ps2system, SizerFlags::StdSpace() ); + ContribSizer.Add( &m_bitmap_dualshock, SizerFlags::StdSpace() ); ContribSizer.AddStretchSpacer( 1 ); - ContribSizer.Add( &contribs, wxSizerFlags(7).HorzBorder().Expand() ); mainSizer.Add( &AuthLogoSizer, SizerFlags::StdSpace() ); @@ -123,4 +125,6 @@ Dialogs::AboutBoxDialog::AboutBoxDialog( wxWindow* parent, int id ): mainSizer.Add( new wxButton( this, wxID_OK, L"I've seen enough"), SizerFlags::StdCenter() ); SetSizerAndFit( &mainSizer ); + + CenterOnScreen(); } diff --git a/pcsx2/gui/Dialogs/FirstTimeWizard.cpp b/pcsx2/gui/Dialogs/FirstTimeWizard.cpp index 7e355fe2b..f6827bc2d 100644 --- a/pcsx2/gui/Dialogs/FirstTimeWizard.cpp +++ b/pcsx2/gui/Dialogs/FirstTimeWizard.cpp @@ -121,7 +121,7 @@ FirstTimeWizard::FirstTimeWizard( wxWindow* parent ) : Connect( wxEVT_COMMAND_LISTBOX_DOUBLECLICKED, wxCommandEventHandler(FirstTimeWizard::OnDoubleClicked) ); } -FirstTimeWizard::~FirstTimeWizard() +FirstTimeWizard::~FirstTimeWizard() throw() { g_ApplyState.DoCleanup(); } diff --git a/pcsx2/gui/Dialogs/ModalPopups.h b/pcsx2/gui/Dialogs/ModalPopups.h index b741ee84d..347ad986b 100644 --- a/pcsx2/gui/Dialogs/ModalPopups.h +++ b/pcsx2/gui/Dialogs/ModalPopups.h @@ -48,7 +48,7 @@ protected: public: FirstTimeWizard( wxWindow* parent ); - virtual ~FirstTimeWizard(); + virtual ~FirstTimeWizard() throw(); wxWizardPage *GetUsermodePage() const { return &m_page_usermode; } wxWizardPage *GetPostUsermodePage() const { return &m_page_plugins; } @@ -66,15 +66,15 @@ protected: namespace Dialogs { - class AboutBoxDialog: public wxDialog + class AboutBoxDialog: public wxDialogWithHelpers { public: AboutBoxDialog( wxWindow* parent=NULL, int id=DialogId_About ); + virtual ~AboutBoxDialog() throw() {} protected: - wxStaticBitmap m_bitmap_logo; - wxStaticBitmap m_bitmap_ps2system; - + //wxStaticBitmap m_bitmap_logo; + wxStaticBitmap m_bitmap_dualshock; }; class PickUserModeDialog : public wxDialogWithHelpers @@ -85,6 +85,7 @@ namespace Dialogs public: PickUserModeDialog( wxWindow* parent, int id=wxID_ANY ); + virtual ~PickUserModeDialog() throw() {} protected: void OnOk_Click( wxCommandEvent& evt ); @@ -95,6 +96,7 @@ namespace Dialogs { public: ImportSettingsDialog( wxWindow* parent ); + virtual ~ImportSettingsDialog() throw() {} protected: void OnImport_Click( wxCommandEvent& evt ); diff --git a/pcsx2/gui/Panels/ConfigurationPanels.h b/pcsx2/gui/Panels/ConfigurationPanels.h index 7d647d65a..243ffb49b 100644 --- a/pcsx2/gui/Panels/ConfigurationPanels.h +++ b/pcsx2/gui/Panels/ConfigurationPanels.h @@ -114,7 +114,7 @@ namespace Panels void StartWizard(); bool ApplyAll( bool saveOnSuccess=true ); bool ApplyPage( int pageid, bool saveOnSuccess=true ); - void DoCleanup(); + void DoCleanup() throw(); }; extern StaticApplyState g_ApplyState; diff --git a/pcsx2/gui/Panels/MiscPanelStuff.cpp b/pcsx2/gui/Panels/MiscPanelStuff.cpp index 8c5229f90..2dd494fcc 100644 --- a/pcsx2/gui/Panels/MiscPanelStuff.cpp +++ b/pcsx2/gui/Panels/MiscPanelStuff.cpp @@ -30,7 +30,7 @@ Panels::StaticApplyState Panels::g_ApplyState; // on dialog destruction. It asserts if the ApplyList hasn't been cleaned up // and then cleans it up forcefully. // -void Panels::StaticApplyState::DoCleanup() +void Panels::StaticApplyState::DoCleanup() throw() { wxASSERT_MSG( PanelList.size() != 0, L"PanelList list hasn't been cleaned up." ); PanelList.clear(); diff --git a/pcsx2/gui/Panels/PluginSelectorPanel.cpp b/pcsx2/gui/Panels/PluginSelectorPanel.cpp index 9115e16dc..84bee4ac7 100644 --- a/pcsx2/gui/Panels/PluginSelectorPanel.cpp +++ b/pcsx2/gui/Panels/PluginSelectorPanel.cpp @@ -303,12 +303,10 @@ void Panels::PluginSelectorPanel::Apply() // Need to unload the current emulation state if the user changed plugins, because // the whole plugin system needs to be re-loaded. - const PluginInfo* pi = tbl_PluginInfo-1; - while( ++pi, pi->shortname != NULL ) - { + const PluginInfo* pi = tbl_PluginInfo; do { if( g_Conf->FullpathTo( pi->id ) != g_Conf->FullpathTo( pi->id ) ) break; - } + } while( ++pi, pi->shortname != NULL ); if( pi->shortname != NULL ) { diff --git a/pcsx2/gui/Plugins.cpp b/pcsx2/gui/Plugins.cpp index a396f2d6d..62aee125a 100644 --- a/pcsx2/gui/Plugins.cpp +++ b/pcsx2/gui/Plugins.cpp @@ -158,14 +158,13 @@ void Pcsx2App::ReloadPlugins() wxString passins[PluginId_Count]; - const PluginInfo* pi = tbl_PluginInfo-1; - while( ++pi, pi->shortname != NULL ) + const PluginInfo* pi = tbl_PluginInfo; do { passins[pi->id] = OverrideOptions.Filenames[pi->id].GetFullPath(); if( passins[pi->id].IsEmpty() || !wxFileExists( passins[pi->id] ) ) passins[pi->id] = g_Conf->FullpathTo( pi->id ); - } + } while( ++pi, pi->shortname != NULL ); _loadTask.reset( new LoadPluginsTask( passins ) ); // ... and when it finishes it posts up a OnLoadPluginsComplete(). Bye. :) diff --git a/pcsx2/gui/Resources/Dualshock.jpg b/pcsx2/gui/Resources/Dualshock.jpg new file mode 100644 index 000000000..12ccd2cd2 Binary files /dev/null and b/pcsx2/gui/Resources/Dualshock.jpg differ diff --git a/pcsx2/gui/Resources/Dualshock.png b/pcsx2/gui/Resources/Dualshock.png deleted file mode 100644 index 12f7d063a..000000000 Binary files a/pcsx2/gui/Resources/Dualshock.png and /dev/null differ diff --git a/pcsx2/windows/VCprojects/pcsx2_2008.vcproj b/pcsx2/windows/VCprojects/pcsx2_2008.vcproj index d025d434b..d952a0fa4 100644 --- a/pcsx2/windows/VCprojects/pcsx2_2008.vcproj +++ b/pcsx2/windows/VCprojects/pcsx2_2008.vcproj @@ -2362,7 +2362,7 @@ @@ -2380,7 +2380,7 @@ @@ -2390,7 +2390,7 @@ diff --git a/pcsx2/windows/WinConsolePipe.cpp b/pcsx2/windows/WinConsolePipe.cpp index a32900fc8..64573a15d 100644 --- a/pcsx2/windows/WinConsolePipe.cpp +++ b/pcsx2/windows/WinConsolePipe.cpp @@ -72,14 +72,14 @@ namespace Exception using namespace Threading; -static void CreatePipe( HANDLE& ph_Pipe, HANDLE& ph_File ) +static __forceinline void CreatePipe( HANDLE& ph_Pipe, HANDLE& ph_File ) { // Create a threadsafe unique name for the Pipe static int s32_Counter = 0; wxString s_PipeName; s_PipeName.Printf( L"\\\\.\\pipe\\pcsxPipe%X_%X_%X_%X", - GetCurrentProcessId(), GetCurrentThreadId(), GetTickCount(), s32_Counter++); + GetCurrentProcessId(), GetCurrentThreadId(), GetTickCount(), ++s32_Counter); SECURITY_ATTRIBUTES k_Secur; k_Secur.nLength = sizeof(SECURITY_ATTRIBUTES); @@ -108,8 +108,10 @@ static void CreatePipe( HANDLE& ph_Pipe, HANDLE& ph_File ) // Reads from the Pipe and appends the read data to ps_Data // returns TRUE if something was printed to console, or false if the stdout/err were idle. -static bool ReadPipe(HANDLE h_Pipe, Console::Colors color ) +static __forceinline bool ReadPipe(HANDLE h_Pipe, Console::Colors color ) { + if( h_Pipe == INVALID_HANDLE_VALUE ) return false; + // IMPORTANT: Check if there is data that can be read. // The first console output will be lost if ReadFile() is called before data becomes available! // It does not make any sense but the following 5 lines are indispensable!! @@ -143,22 +145,19 @@ static bool ReadPipe(HANDLE h_Pipe, Console::Colors color ) class WinPipeThread : public PersistentThread { protected: - const HANDLE& mh_OutPipe; - const HANDLE& mh_ErrPipe; + const HANDLE& m_outpipe; + const Console::Colors m_color; public: - WinPipeThread( const HANDLE& outpipe, const HANDLE& errpipe ) : - mh_OutPipe( outpipe ) - , mh_ErrPipe( errpipe ) - //, mk_OverOut( overout ) - //, mk_OverErr( overerr ) + WinPipeThread( const HANDLE& outpipe, Console::Colors color ) : + m_outpipe( outpipe ) + , m_color( color ) { } virtual ~WinPipeThread() throw() { PersistentThread::Cancel(); - SetThreadPriority( GetCurrentThread(), THREAD_PRIORITY_BELOW_NORMAL ); } protected: @@ -166,12 +165,12 @@ protected: { try { + SetThreadPriority( GetCurrentThread(), THREAD_PRIORITY_BELOW_NORMAL ); while( true ) { Sleep( 100 ); pthread_testcancel(); - ReadPipe(mh_OutPipe, Color_Black ); - ReadPipe(mh_ErrPipe, Color_Red ); + ReadPipe(m_outpipe, m_color ); } } catch( Exception::Win32Error& ex ) @@ -189,88 +188,94 @@ class WinPipeRedirection : public PipeRedirectionBase DeclareNoncopyableObject( WinPipeRedirection ); protected: - HANDLE mh_OutPipe; - HANDLE mh_ErrPipe; - HANDLE mh_OutFile; - HANDLE mh_ErrFile; - - int m_hCrtOut; - int m_hCrtErr; - - FILE* h_fpOut; - FILE* h_fpErr; + HANDLE m_pipe; + HANDLE m_file; + int m_crtFile; + FILE* m_fp; WinPipeThread m_Thread; public: - WinPipeRedirection(); + WinPipeRedirection( FILE* stdstream ); virtual ~WinPipeRedirection() throw(); + + void Cleanup() throw(); }; -WinPipeRedirection::WinPipeRedirection() : - mh_OutPipe(INVALID_HANDLE_VALUE) -, mh_ErrPipe(INVALID_HANDLE_VALUE) -, mh_OutFile(INVALID_HANDLE_VALUE) -, mh_ErrFile(INVALID_HANDLE_VALUE) -, m_hCrtOut(-1) -, m_hCrtErr(-1) -, h_fpOut(NULL) -, h_fpErr(NULL) - -, m_Thread( mh_OutPipe, mh_ErrPipe ) +WinPipeRedirection::WinPipeRedirection( FILE* stdstream ) : + m_pipe(INVALID_HANDLE_VALUE) +, m_file(INVALID_HANDLE_VALUE) +, m_crtFile(-1) +, m_fp(NULL) +, m_Thread( m_pipe, (stdstream == stderr) ? Color_Red : Color_Black ) { - CreatePipe(mh_OutPipe, mh_OutFile ); - CreatePipe(mh_ErrPipe, mh_ErrFile ); + try + { + wxASSERT( stdstream == stderr || stdstream == stdout ); + DWORD stdhandle = ( stdstream == stderr ) ? STD_ERROR_HANDLE : STD_OUTPUT_HANDLE; - SetStdHandle( STD_OUTPUT_HANDLE, mh_OutFile ); - SetStdHandle( STD_ERROR_HANDLE, mh_ErrFile ); + CreatePipe( m_pipe, m_file ); + SetStdHandle( stdhandle, m_file ); - m_hCrtOut = _open_osfhandle( (intptr_t)GetStdHandle(STD_OUTPUT_HANDLE), _O_TEXT ); - m_hCrtErr = _open_osfhandle( (intptr_t)GetStdHandle(STD_ERROR_HANDLE), _O_TEXT ); + // In some cases GetStdHandle can fail, even when the one we just assigned above is valid. + HANDLE newhandle = GetStdHandle(stdhandle); + if( newhandle == INVALID_HANDLE_VALUE ) + throw Exception::Win32Error( "GetStdHandle failed." ); - h_fpOut = _fdopen( m_hCrtOut, "w" ); - h_fpErr = _fdopen( m_hCrtErr, "w" ); + if( newhandle == NULL ) + throw Exception::RuntimeError( "GetStdHandle returned NULL." ); // not a Win32error (no error code) - *stdout = *h_fpOut; - *stderr = *h_fpErr; + m_crtFile = _open_osfhandle( (intptr_t)newhandle, _O_TEXT ); + m_fp = _fdopen( m_crtFile, "w" ); - setvbuf( stdout, NULL, _IONBF, 0 ); - setvbuf( stderr, NULL, _IONBF, 0 ); + *stdstream = *m_fp; + setvbuf( stdstream, NULL, _IONBF, 0 ); - m_Thread.Start(); + m_Thread.Start(); + } + catch( ... ) + { + Cleanup(); throw; + } } -WinPipeRedirection::~WinPipeRedirection() throw() +WinPipeRedirection::~WinPipeRedirection() +{ + Cleanup(); +} + +void WinPipeRedirection::Cleanup() throw() { m_Thread.Cancel(); - #define safe_CloseHandle( ptr ) \ - ((void) (( ( ptr != INVALID_HANDLE_VALUE ) && (!!CloseHandle( ptr ), !!0) ), ptr = INVALID_HANDLE_VALUE)) - - safe_CloseHandle(mh_OutPipe); - safe_CloseHandle(mh_ErrPipe); - - if( h_fpOut != NULL ) + if( m_fp != NULL ) { - fclose( h_fpOut ); - h_fpOut = NULL; - } - - if( h_fpErr != NULL ) - { - fclose( h_fpErr ); - h_fpErr = NULL; + fclose( m_fp ); + m_fp = NULL; } - #define safe_close( ptr ) \ - ((void) (( ( ptr != -1 ) && (!!_close( ptr ), !!0) ), ptr = -1)) + // crtFile is closed implicitly when closing m_fp + // m_file is closed implicitly when closing crtFile - // CrtOut and CrtErr are closed implicitly when closing fpOut/fpErr - // OutFile and ErrFile are closed implicitly when closing m_hCrtOut/Err + if( m_pipe != INVALID_HANDLE_VALUE ) + { + CloseHandle( m_pipe ); + m_pipe = INVALID_HANDLE_VALUE; + } } // The win32 specific implementation of PipeRedirection. -PipeRedirectionBase* NewPipeRedir() +PipeRedirectionBase* NewPipeRedir( FILE* stdstream ) { - return new WinPipeRedirection(); + try + { + return new WinPipeRedirection( stdstream ); + } + catch( Exception::RuntimeError& ex ) + { + // Entirely non-critical errors. Log 'em and move along. + Console::Error( ex.FormatDiagnosticMessage() ); + } + + return NULL; }