diff --git a/pcsx2/Linux/pcsx2.cbp b/pcsx2/Linux/pcsx2.cbp
index 4363bf97ff..61a3c509b5 100644
--- a/pcsx2/Linux/pcsx2.cbp
+++ b/pcsx2/Linux/pcsx2.cbp
@@ -364,7 +364,8 @@
-
+
+
@@ -456,8 +457,10 @@
+
-
+
+
diff --git a/pcsx2/gui/ConsoleLogger.cpp b/pcsx2/gui/ConsoleLogger.cpp
index 0151f8eb17..3a45a0556c 100644
--- a/pcsx2/gui/ConsoleLogger.cpp
+++ b/pcsx2/gui/ConsoleLogger.cpp
@@ -23,7 +23,7 @@
#include
#ifdef __WXMSW__
-# include // needed for OutputDebugStirng
+# include // needed for OutputDebugString
#endif
BEGIN_DECLARE_EVENT_TYPES()
@@ -39,7 +39,7 @@ DEFINE_EVENT_TYPE(wxEVT_SetTitleText)
DEFINE_EVENT_TYPE(wxEVT_DockConsole)
DEFINE_EVENT_TYPE(wxEVT_FlushQueue)
-// C++ requires abstract destructors to exist, even thought hey're abstract.
+// C++ requires abstract destructors to exist, even though they're abstract.
PipeRedirectionBase::~PipeRedirectionBase() throw() {}
// ----------------------------------------------------------------------------
@@ -236,101 +236,6 @@ enum MenuIDs_t
MenuID_FontSize_Huge,
};
-void __evt_fastcall pxLogTextCtrl::OnCoreThreadStatusChanged( void* obj, wxCommandEvent& evt )
-{
-#ifdef __WXMSW__
- if( obj == NULL ) return;
- pxLogTextCtrl* mframe = (pxLogTextCtrl*)obj;
-
- // WM_VSCROLL makes the scrolling 'smooth' (such that the last line of the log contents
- // are always displayed as the last line of the log window). Unfortunately this also
- // makes logging very slow, so we only send the message for status changes, so that the
- // log aligns itself nicely when we pause emulation or when errors occur.
-
- ::SendMessage((HWND)mframe->GetHWND(), WM_VSCROLL, SB_BOTTOM, (LPARAM)NULL);
- mframe->m_win32_StupidRefreshTricks = 0;
-#endif
-}
-
-void __evt_fastcall pxLogTextCtrl::OnCorePluginStatusChanged( void* obj, PluginEventType& evt )
-{
-#ifdef __WXMSW__
- if( obj == NULL ) return;
- pxLogTextCtrl* mframe = (pxLogTextCtrl*)obj;
-
- // WM_VSCROLL makes the scrolling 'smooth' (such that the last line of the log contents
- // are always displayed as the last line of the log window). Unfortunately this also
- // makes logging very slow, so we only send the message for status changes, so that the
- // log aligns itself nicely when we pause emulation or when errors occur.
-
- ::SendMessage((HWND)mframe->GetHWND(), WM_VSCROLL, SB_BOTTOM, (LPARAM)NULL);
- mframe->m_win32_StupidRefreshTricks = 0;
-#endif
-}
-
-pxLogTextCtrl::pxLogTextCtrl( wxWindow* parent )
- : wxTextCtrl( parent, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize,
- wxTE_MULTILINE | wxHSCROLL | wxTE_READONLY | wxTE_RICH2
- )
-
- , m_Listener_CoreThreadStatus ( wxGetApp().Source_CoreThreadStatus(), CmdEvt_Listener ( this, OnCoreThreadStatusChanged ) )
- , m_Listener_CorePluginStatus ( wxGetApp().Source_CorePluginStatus(), EventListener ( this, OnCorePluginStatusChanged ) )
-{
-#ifdef __WXMSW__
- m_win32_StupidRefreshTricks = 0;
- m_win32_LinesPerScroll = 10;
-#endif
- m_FreezeWrites = false;
-
- Connect( wxEVT_SCROLLWIN_THUMBTRACK, wxScrollWinEventHandler(pxLogTextCtrl::OnThumbTrack) );
- Connect( wxEVT_SCROLLWIN_THUMBRELEASE, wxScrollWinEventHandler(pxLogTextCtrl::OnThumbRelease) );
-
- Connect( wxEVT_SIZE, wxSizeEventHandler(pxLogTextCtrl::OnResize) );
-}
-
-
-void pxLogTextCtrl::OnResize( wxSizeEvent& evt )
-{
-#ifdef __WXMSW__
- // Windows has retarded console window update patterns. This helps smarten them up.
- int ctrly = GetSize().y;
- int fonty;
- GetTextExtent( L"blaH yeah", NULL, &fonty );
- m_win32_LinesPerScroll = (int)((ctrly * 0.72) / fonty);
-#endif
-
- evt.Skip();
-}
-
-void pxLogTextCtrl::OnThumbTrack(wxScrollWinEvent& evt)
-{
- //Console.Warning( "Thumb Tracking!!!" );
- m_FreezeWrites = true;
- evt.Skip();
-}
-
-void pxLogTextCtrl::OnThumbRelease(wxScrollWinEvent& evt)
-{
- //Console.Warning( "Thumb Releasing!!!" );
- m_FreezeWrites = false;
- evt.Skip();
-}
-
-void pxLogTextCtrl::DoFlushUpdate()
-{
-#ifdef __WXMSW__
- // EM_LINESCROLL avoids weird errors when the buffer reaches "max" and starts
- // clearing old history:
- ::SendMessage((HWND)GetHWND(), EM_LINESCROLL, 0, 0xfffffff);
-
- if( ++m_win32_StupidRefreshTricks > m_win32_LinesPerScroll )
- {
- m_win32_StupidRefreshTricks = 0;
- ::SendMessage((HWND)GetHWND(), WM_VSCROLL, SB_BOTTOM, (LPARAM)NULL);
- }
-#endif
-}
-
// ------------------------------------------------------------------------
ConsoleLogFrame::ConsoleLogFrame( MainEmuFrame *parent, const wxString& title, AppConfig::ConsoleLogOptions& options )
: wxFrame(parent, wxID_ANY, title)
@@ -672,7 +577,7 @@ void ConsoleLogFrame::OnFlushEvent( wxCommandEvent& evt )
ScopedLock locker( m_QueueLock );
m_pendingFlushMsg = false;
- if( m_TextCtrl.HasWriteLock() ) return;
+ //if( m_TextCtrl.HasWriteLock() ) return;
if( m_CurQueuePos != 0 )
{
@@ -691,8 +596,6 @@ void ConsoleLogFrame::OnFlushEvent( wxCommandEvent& evt )
}
DoFlushQueue();
- m_TextCtrl.DoFlushUpdate();
-
//m_TextCtrl.Thaw();
}
@@ -758,9 +661,7 @@ void ConsoleLogFrame::DoFlushQueue()
m_TextCtrl.WriteText( &m_QueueBuffer[m_QueueColorSection[i].startpoint] );
}
- // Some reports on Windows7 have corrupted cursor when using insertPoint (or
- // +1 / -1 ). This works better for some reason:
- m_TextCtrl.SetInsertionPointEnd(); //( insertPoint );
+ m_TextCtrl.ConcludeIssue( m_pendingFlushes );
m_QueueColorSection.Clear();
m_CurQueuePos = 0;
@@ -930,188 +831,3 @@ void Pcsx2App::DisableWindowLogging() const
Console_SetActiveHandler( (emuLog!=NULL) ? (IConsoleWriter&)ConsoleWriter_File : (IConsoleWriter&)ConsoleWriter_Buffered );
Threading::Sleep( 5 );
}
-
-DEFINE_EVENT_TYPE( pxEVT_MSGBOX );
-DEFINE_EVENT_TYPE( pxEVT_CallStackBox );
-
-using namespace Threading;
-
-// Thread Safety: Must be called from the GUI thread ONLY.
-static int pxMessageDialog( const wxString& content, const wxString& caption, long flags )
-{
- if( IsDevBuild && !wxThread::IsMain() )
- throw Exception::InvalidOperation( "Function must be called by the main GUI thread only." );
-
- // fixme: If the emulator is currently active and is running in fullscreen mode, then we
- // need to either:
- // 1) Exit fullscreen mode before issuing the popup.
- // 2) Issue the popup with wxSTAY_ON_TOP specified so that the user will see it.
- //
- // And in either case the emulation should be paused/suspended for the user.
-
- return wxMessageDialog( NULL, content, caption, flags ).ShowModal();
-}
-
-// Thread Safety: Must be called from the GUI thread ONLY.
-// fixme: this function should use a custom dialog box that has a wxTextCtrl for the callstack, and
-// uses fixed-width (modern) fonts.
-static int pxCallstackDialog( const wxString& content, const wxString& caption, long flags )
-{
- if( IsDevBuild && !wxThread::IsMain() )
- throw Exception::InvalidOperation( "Function must be called by the main GUI thread only." );
-
- return wxMessageDialog( NULL, content, caption, flags ).ShowModal();
-}
-
-class pxMessageBoxEvent : public wxEvent
-{
-protected:
- MsgboxEventResult& m_Instdata;
- wxString m_Title;
- wxString m_Content;
- long m_Flags;
-
-public:
- pxMessageBoxEvent()
- : wxEvent( 0, pxEVT_MSGBOX )
- , m_Instdata( *(MsgboxEventResult*)NULL )
- , m_Title()
- , m_Content()
- {
- m_Flags = 0;
- }
-
- pxMessageBoxEvent( MsgboxEventResult& instdata, const wxString& title, const wxString& content, long flags )
- : wxEvent( 0, pxEVT_MSGBOX )
- , m_Instdata( instdata )
- , m_Title( title )
- , m_Content( content )
- {
- m_Flags = flags;
- }
-
- pxMessageBoxEvent( const pxMessageBoxEvent& event )
- : wxEvent( event )
- , m_Instdata( event.m_Instdata )
- , m_Title( event.m_Title )
- , m_Content( event.m_Content )
- {
- m_Flags = event.m_Flags;
- }
-
- // Thread Safety: Must be called from the GUI thread ONLY.
- void DoTheDialog()
- {
- int result;
-
- if( m_id == pxEVT_MSGBOX )
- result = pxMessageDialog( m_Content, m_Title, m_Flags );
- else
- result = pxCallstackDialog( m_Content, m_Title, m_Flags );
- m_Instdata.result = result;
- m_Instdata.WaitForMe.Post();
- }
-
- virtual wxEvent *Clone() const { return new pxMessageBoxEvent(*this); }
-
-private:
- DECLARE_DYNAMIC_CLASS_NO_ASSIGN(pxMessageBoxEvent)
-};
-
-IMPLEMENT_DYNAMIC_CLASS( pxMessageBoxEvent, wxEvent )
-
-namespace Msgbox
-{
- // parameters:
- // flags - messagebox type flags, such as wxOK, wxCANCEL, etc.
- //
- static int ThreadedMessageBox( const wxString& content, const wxString& title, long flags, int boxType=pxEVT_MSGBOX )
- {
- // must pass the message to the main gui thread, and then stall this thread, to avoid
- // threaded chaos where our thread keeps running while the popup is awaiting input.
-
- MsgboxEventResult instdat;
- pxMessageBoxEvent tevt( instdat, title, content, flags );
- wxGetApp().AddPendingEvent( tevt );
- instdat.WaitForMe.WaitNoCancel(); // Important! disable cancellation since we're using local stack vars.
- return instdat.result;
- }
-
- void OnEvent( pxMessageBoxEvent& evt )
- {
- evt.DoTheDialog();
- }
-
- // Pops up an alert Dialog Box with a singular "OK" button.
- // Always returns false.
- bool Alert( const wxString& text, const wxString& caption, int icon )
- {
- icon |= wxOK;
- if( wxThread::IsMain() )
- pxMessageDialog( text, caption, icon );
- else
- ThreadedMessageBox( text, caption, icon );
- return false;
- }
-
- // Pops up a dialog box with Ok/Cancel buttons. Returns the result of the inquiry,
- // true if OK, false if cancel.
- bool OkCancel( const wxString& text, const wxString& caption, int icon )
- {
- icon |= wxOK | wxCANCEL;
- if( wxThread::IsMain() )
- {
- return wxID_OK == pxMessageDialog( text, caption, icon );
- }
- else
- {
- return wxID_OK == ThreadedMessageBox( text, caption, icon );
- }
- }
-
- bool YesNo( const wxString& text, const wxString& caption, int icon )
- {
- icon |= wxYES_NO;
- if( wxThread::IsMain() )
- {
- return wxID_YES == pxMessageDialog( text, caption, icon );
- }
- else
- {
- return wxID_YES == ThreadedMessageBox( text, caption, icon );
- }
- }
-
- // [TODO] : This should probably be a fancier looking dialog box with the stacktrace
- // displayed inside a wxTextCtrl.
- static int CallStack( const wxString& errormsg, const wxString& stacktrace, const wxString& prompt, const wxString& caption, int buttons )
- {
- buttons |= wxICON_STOP;
-
- wxString text( errormsg + L"\n\n" + stacktrace + L"\n" + prompt );
-
- if( wxThread::IsMain() )
- {
- return pxCallstackDialog( text, caption, buttons );
- }
- else
- {
- return ThreadedMessageBox( text, caption, buttons, pxEVT_CallStackBox );
- }
- }
-
- int Assertion( const wxString& text, const wxString& stacktrace )
- {
- return CallStack( text, stacktrace,
- L"\nDo you want to stop the program?"
- L"\nOr press [Cancel] to suppress further assertions.",
- L"PCSX2 Assertion Failure",
- wxYES_NO | wxCANCEL
- );
- }
-
- void Except( const Exception::BaseException& src )
- {
- CallStack( src.FormatDisplayMessage(), src.FormatDiagnosticMessage(), wxEmptyString, L"PCSX2 Unhandled Exception", wxOK );
- }
-}
diff --git a/pcsx2/gui/ConsoleLogger.h b/pcsx2/gui/ConsoleLogger.h
index 3fbe7a98fc..0597e34134 100644
--- a/pcsx2/gui/ConsoleLogger.h
+++ b/pcsx2/gui/ConsoleLogger.h
@@ -97,6 +97,7 @@ protected:
#ifdef __WXMSW__
int m_win32_StupidRefreshTricks;
+ int m_win32_LinesPerPage;
int m_win32_LinesPerScroll;
#endif
bool m_FreezeWrites;
@@ -105,7 +106,9 @@ public:
pxLogTextCtrl(wxWindow* parent);
bool HasWriteLock() const { return m_FreezeWrites; }
- void DoFlushUpdate();
+ void ConcludeIssue( int lines );
+
+ virtual void WriteText(const wxString& text);
protected:
virtual void OnThumbTrack(wxScrollWinEvent& event);
@@ -114,7 +117,6 @@ protected:
static void __evt_fastcall OnCoreThreadStatusChanged( void* obj, wxCommandEvent& evt );
static void __evt_fastcall OnCorePluginStatusChanged( void* obj, PluginEventType& evt );
-
};
// --------------------------------------------------------------------------------------
diff --git a/pcsx2/gui/MessageBoxes.cpp b/pcsx2/gui/MessageBoxes.cpp
new file mode 100644
index 0000000000..40d78b4e25
--- /dev/null
+++ b/pcsx2/gui/MessageBoxes.cpp
@@ -0,0 +1,205 @@
+/* PCSX2 - PS2 Emulator for PCs
+ * Copyright (C) 2002-2009 PCSX2 Dev Team
+ *
+ * PCSX2 is free software: you can redistribute it and/or modify it under the terms
+ * of the GNU Lesser General Public License as published by the Free Software Found-
+ * ation, either version 3 of the License, or (at your option) any later version.
+ *
+ * PCSX2 is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
+ * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+ * PURPOSE. See the GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along with PCSX2.
+ * If not, see .
+ */
+
+#include "PrecompiledHeader.h"
+#include "App.h"
+
+DEFINE_EVENT_TYPE( pxEVT_MSGBOX );
+DEFINE_EVENT_TYPE( pxEVT_CallStackBox );
+
+using namespace Threading;
+
+// Thread Safety: Must be called from the GUI thread ONLY.
+static int pxMessageDialog( const wxString& content, const wxString& caption, long flags )
+{
+ if( IsDevBuild && !wxThread::IsMain() )
+ throw Exception::InvalidOperation( "Function must be called by the main GUI thread only." );
+
+ // fixme: If the emulator is currently active and is running in fullscreen mode, then we
+ // need to either:
+ // 1) Exit fullscreen mode before issuing the popup.
+ // 2) Issue the popup with wxSTAY_ON_TOP specified so that the user will see it.
+ //
+ // And in either case the emulation should be paused/suspended for the user.
+
+ return wxMessageDialog( NULL, content, caption, flags ).ShowModal();
+}
+
+// Thread Safety: Must be called from the GUI thread ONLY.
+// fixme: this function should use a custom dialog box that has a wxTextCtrl for the callstack, and
+// uses fixed-width (modern) fonts.
+static int pxCallstackDialog( const wxString& content, const wxString& caption, long flags )
+{
+ if( IsDevBuild && !wxThread::IsMain() )
+ throw Exception::InvalidOperation( "Function must be called by the main GUI thread only." );
+
+ return wxMessageDialog( NULL, content, caption, flags ).ShowModal();
+}
+
+// --------------------------------------------------------------------------------------
+// pxMessageBoxEvent
+// --------------------------------------------------------------------------------------
+class pxMessageBoxEvent : public wxEvent
+{
+protected:
+ MsgboxEventResult& m_Instdata;
+ wxString m_Title;
+ wxString m_Content;
+ long m_Flags;
+
+public:
+ pxMessageBoxEvent()
+ : wxEvent( 0, pxEVT_MSGBOX )
+ , m_Instdata( *(MsgboxEventResult*)NULL )
+ , m_Title()
+ , m_Content()
+ {
+ m_Flags = 0;
+ }
+
+ pxMessageBoxEvent( MsgboxEventResult& instdata, const wxString& title, const wxString& content, long flags )
+ : wxEvent( 0, pxEVT_MSGBOX )
+ , m_Instdata( instdata )
+ , m_Title( title )
+ , m_Content( content )
+ {
+ m_Flags = flags;
+ }
+
+ pxMessageBoxEvent( const pxMessageBoxEvent& event )
+ : wxEvent( event )
+ , m_Instdata( event.m_Instdata )
+ , m_Title( event.m_Title )
+ , m_Content( event.m_Content )
+ {
+ m_Flags = event.m_Flags;
+ }
+
+ // Thread Safety: Must be called from the GUI thread ONLY.
+ void DoTheDialog()
+ {
+ int result;
+
+ if( m_id == pxEVT_MSGBOX )
+ result = pxMessageDialog( m_Content, m_Title, m_Flags );
+ else
+ result = pxCallstackDialog( m_Content, m_Title, m_Flags );
+ m_Instdata.result = result;
+ m_Instdata.WaitForMe.Post();
+ }
+
+ virtual wxEvent *Clone() const { return new pxMessageBoxEvent(*this); }
+
+private:
+ DECLARE_DYNAMIC_CLASS_NO_ASSIGN(pxMessageBoxEvent)
+};
+
+IMPLEMENT_DYNAMIC_CLASS( pxMessageBoxEvent, wxEvent )
+
+namespace Msgbox
+{
+ // parameters:
+ // flags - messagebox type flags, such as wxOK, wxCANCEL, etc.
+ //
+ static int ThreadedMessageBox( const wxString& content, const wxString& title, long flags, int boxType=pxEVT_MSGBOX )
+ {
+ // must pass the message to the main gui thread, and then stall this thread, to avoid
+ // threaded chaos where our thread keeps running while the popup is awaiting input.
+
+ MsgboxEventResult instdat;
+ pxMessageBoxEvent tevt( instdat, title, content, flags );
+ wxGetApp().AddPendingEvent( tevt );
+ instdat.WaitForMe.WaitNoCancel(); // Important! disable cancellation since we're using local stack vars.
+ return instdat.result;
+ }
+
+ void OnEvent( pxMessageBoxEvent& evt )
+ {
+ evt.DoTheDialog();
+ }
+
+ // Pops up an alert Dialog Box with a singular "OK" button.
+ // Always returns false.
+ bool Alert( const wxString& text, const wxString& caption, int icon )
+ {
+ icon |= wxOK;
+ if( wxThread::IsMain() )
+ pxMessageDialog( text, caption, icon );
+ else
+ ThreadedMessageBox( text, caption, icon );
+ return false;
+ }
+
+ // Pops up a dialog box with Ok/Cancel buttons. Returns the result of the inquiry,
+ // true if OK, false if cancel.
+ bool OkCancel( const wxString& text, const wxString& caption, int icon )
+ {
+ icon |= wxOK | wxCANCEL;
+ if( wxThread::IsMain() )
+ {
+ return wxID_OK == pxMessageDialog( text, caption, icon );
+ }
+ else
+ {
+ return wxID_OK == ThreadedMessageBox( text, caption, icon );
+ }
+ }
+
+ bool YesNo( const wxString& text, const wxString& caption, int icon )
+ {
+ icon |= wxYES_NO;
+ if( wxThread::IsMain() )
+ {
+ return wxID_YES == pxMessageDialog( text, caption, icon );
+ }
+ else
+ {
+ return wxID_YES == ThreadedMessageBox( text, caption, icon );
+ }
+ }
+
+ // [TODO] : This should probably be a fancier looking dialog box with the stacktrace
+ // displayed inside a wxTextCtrl.
+ static int CallStack( const wxString& errormsg, const wxString& stacktrace, const wxString& prompt, const wxString& caption, int buttons )
+ {
+ buttons |= wxICON_STOP;
+
+ wxString text( errormsg + L"\n\n" + stacktrace + L"\n" + prompt );
+
+ if( wxThread::IsMain() )
+ {
+ return pxCallstackDialog( text, caption, buttons );
+ }
+ else
+ {
+ return ThreadedMessageBox( text, caption, buttons, pxEVT_CallStackBox );
+ }
+ }
+
+ int Assertion( const wxString& text, const wxString& stacktrace )
+ {
+ return CallStack( text, stacktrace,
+ L"\nDo you want to stop the program?"
+ L"\nOr press [Cancel] to suppress further assertions.",
+ L"PCSX2 Assertion Failure",
+ wxYES_NO | wxCANCEL
+ );
+ }
+
+ void Except( const Exception::BaseException& src )
+ {
+ CallStack( src.FormatDisplayMessage(), src.FormatDiagnosticMessage(), wxEmptyString, L"PCSX2 Unhandled Exception", wxOK );
+ }
+}
diff --git a/pcsx2/gui/pxLogTextCtrl.cpp b/pcsx2/gui/pxLogTextCtrl.cpp
new file mode 100644
index 0000000000..6f5519b4dd
--- /dev/null
+++ b/pcsx2/gui/pxLogTextCtrl.cpp
@@ -0,0 +1,140 @@
+/* PCSX2 - PS2 Emulator for PCs
+ * Copyright (C) 2002-2009 PCSX2 Dev Team
+ *
+ * PCSX2 is free software: you can redistribute it and/or modify it under the terms
+ * of the GNU Lesser General Public License as published by the Free Software Found-
+ * ation, either version 3 of the License, or (at your option) any later version.
+ *
+ * PCSX2 is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
+ * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+ * PURPOSE. See the GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along with PCSX2.
+ * If not, see .
+ */
+
+#include "PrecompiledHeader.h"
+#include "App.h"
+#include "ConsoleLogger.h"
+
+#ifdef __WXMSW__
+# include // needed for windows-specific rich text messages to make scrolling not lame
+#endif
+
+void __evt_fastcall pxLogTextCtrl::OnCoreThreadStatusChanged( void* obj, wxCommandEvent& evt )
+{
+#ifdef __WXMSW__
+ if( obj == NULL ) return;
+ pxLogTextCtrl* mframe = (pxLogTextCtrl*)obj;
+
+ // See ConcludeIssue for details on WM_VSCROLL
+
+ if( mframe->HasWriteLock() ) return;
+ ::SendMessage((HWND)mframe->GetHWND(), WM_VSCROLL, SB_BOTTOM, (LPARAM)NULL);
+ mframe->m_win32_StupidRefreshTricks = 0;
+#endif
+}
+
+void __evt_fastcall pxLogTextCtrl::OnCorePluginStatusChanged( void* obj, PluginEventType& evt )
+{
+#ifdef __WXMSW__
+ if( obj == NULL ) return;
+ pxLogTextCtrl* mframe = (pxLogTextCtrl*)obj;
+
+ // See ConcludeIssue for details on WM_VSCROLL
+
+ if( mframe->HasWriteLock() ) return;
+ ::SendMessage((HWND)mframe->GetHWND(), WM_VSCROLL, SB_BOTTOM, (LPARAM)NULL);
+ mframe->m_win32_StupidRefreshTricks = 0;
+#endif
+}
+
+pxLogTextCtrl::pxLogTextCtrl( wxWindow* parent )
+ : wxTextCtrl( parent, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize,
+ wxTE_MULTILINE | wxHSCROLL | wxTE_READONLY | wxTE_RICH2
+ )
+
+ , m_Listener_CoreThreadStatus ( wxGetApp().Source_CoreThreadStatus(), CmdEvt_Listener ( this, OnCoreThreadStatusChanged ) )
+ , m_Listener_CorePluginStatus ( wxGetApp().Source_CorePluginStatus(), EventListener ( this, OnCorePluginStatusChanged ) )
+{
+#ifdef __WXMSW__
+ m_win32_StupidRefreshTricks = 0;
+ m_win32_LinesPerScroll = 10;
+#endif
+ m_FreezeWrites = false;
+
+ Connect( wxEVT_SCROLLWIN_THUMBTRACK, wxScrollWinEventHandler(pxLogTextCtrl::OnThumbTrack) );
+ Connect( wxEVT_SCROLLWIN_THUMBRELEASE, wxScrollWinEventHandler(pxLogTextCtrl::OnThumbRelease) );
+
+ Connect( wxEVT_SIZE, wxSizeEventHandler(pxLogTextCtrl::OnResize) );
+}
+
+void pxLogTextCtrl::WriteText(const wxString& text)
+{
+ // Don't need the update message -- saves some overhead.
+ DoWriteText( text, SetValue_SelectionOnly );
+}
+
+void pxLogTextCtrl::OnResize( wxSizeEvent& evt )
+{
+#ifdef __WXMSW__
+ // Windows has retarded console window update patterns. This helps smarten them up.
+ int ctrly = GetSize().y;
+ int fonty;
+ GetTextExtent( L"blaH yeah", NULL, &fonty );
+ m_win32_LinesPerPage = (ctrly / fonty) + 1;
+ m_win32_LinesPerScroll = m_win32_LinesPerPage * 0.72;
+#endif
+
+ evt.Skip();
+}
+
+bool m_IsPaused = false;
+
+void pxLogTextCtrl::OnThumbTrack(wxScrollWinEvent& evt)
+{
+ //Console.Warning( "Thumb Tracking!!!" );
+ m_FreezeWrites = true;
+ if( !m_IsPaused )
+ m_IsPaused = CoreThread.Pause();
+
+ evt.Skip();
+}
+
+void pxLogTextCtrl::OnThumbRelease(wxScrollWinEvent& evt)
+{
+ //Console.Warning( "Thumb Releasing!!!" );
+ m_FreezeWrites = false;
+ if( m_IsPaused )
+ {
+ CoreThread.Resume();
+ m_IsPaused = false;
+ }
+ evt.Skip();
+}
+
+void pxLogTextCtrl::ConcludeIssue( int lines )
+{
+ if( HasWriteLock() ) return;
+ SetInsertionPointEnd();
+
+#ifdef __WXMSW__
+
+ // EM_LINESCROLL avoids weird errors when the buffer reaches "max" and starts
+ // clearing old history:
+ ::SendMessage((HWND)GetHWND(), EM_LINESCROLL, 0, 0xfffffff);
+
+ // WM_VSCROLL makes the scrolling 'smooth' (such that the last line of the log contents
+ // are always displayed as the last line of the log window). Unfortunately this also
+ // makes logging very slow, so we only send the message for status changes, so that the
+ // log aligns itself nicely when we pause emulation or when errors occur.
+
+ m_win32_StupidRefreshTricks += lines;
+ m_win32_StupidRefreshTricks %= m_win32_LinesPerPage;
+ if( m_win32_StupidRefreshTricks > m_win32_LinesPerScroll )
+ {
+ m_win32_StupidRefreshTricks = 0;
+ ::SendMessage((HWND)GetHWND(), WM_VSCROLL, SB_BOTTOM, (LPARAM)NULL);
+ }
+#endif
+}
diff --git a/pcsx2/windows/VCprojects/pcsx2_2008.vcproj b/pcsx2/windows/VCprojects/pcsx2_2008.vcproj
index b2fb84439b..9569efc296 100644
--- a/pcsx2/windows/VCprojects/pcsx2_2008.vcproj
+++ b/pcsx2/windows/VCprojects/pcsx2_2008.vcproj
@@ -1808,10 +1808,18 @@
RelativePath="..\..\gui\MemoryCardFile.cpp"
>
+
+
+
+
@@ -1879,41 +1887,7 @@
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+