Patch: Reverse Debugging Menu
Posted: Thu Jun 12, 2014 6:50 am
Note: Since I'm a total git newb, this patch also includes my previous patch for adding "Select Next" and "Select Previous" to the Search menu.
If you're unfamiliar with reverse debugging with GDB, it's exactly what it sounds like. The only difference is that you first have to break somewhere and then exectue the "record" command, then continue. (recording is slow, just fyi). Then you can reverse-next/step/continue/etc up until the point where you began recording. "Set Exec Direction *" does exactly what it says. If you set it to reverse, the normal forward step/next/etc will instead work backward.
You can already reverse debug in codelite if you just throw the commands at GDB manually via the "debug command" pane, but this patch adds a slew of menu options to the debug menu as well as keyboard shortcuts. It's all documented here: GDB commands, GDB/MI commands.
I couldn't figure out how to disable menu items when the debugger isn't started, didn't look to deeply into it. Everything seems to work a-okay otherwise.
Note: the enable/disable hardware breakpoints is in there because one document claimed they must be disabled in order to use variable watches properly while reverse debugging. However, I have had no problems, that information may be antiquated.
todo:
* grey out all menu options when debugger is not active
* grey out all but "record" menu options when not recording
* "disable hardware breakpoints" should be a checkbox
* "set record direction to reverse" should be a checkbox
* "start/stop recording" should be a checkbox
the patch:
accelerators added
If you're unfamiliar with reverse debugging with GDB, it's exactly what it sounds like. The only difference is that you first have to break somewhere and then exectue the "record" command, then continue. (recording is slow, just fyi). Then you can reverse-next/step/continue/etc up until the point where you began recording. "Set Exec Direction *" does exactly what it says. If you set it to reverse, the normal forward step/next/etc will instead work backward.
You can already reverse debug in codelite if you just throw the commands at GDB manually via the "debug command" pane, but this patch adds a slew of menu options to the debug menu as well as keyboard shortcuts. It's all documented here: GDB commands, GDB/MI commands.
I couldn't figure out how to disable menu items when the debugger isn't started, didn't look to deeply into it. Everything seems to work a-okay otherwise.
Note: the enable/disable hardware breakpoints is in there because one document claimed they must be disabled in order to use variable watches properly while reverse debugging. However, I have had no problems, that information may be antiquated.
todo:
* grey out all menu options when debugger is not active
* grey out all but "record" menu options when not recording
* "disable hardware breakpoints" should be a checkbox
* "set record direction to reverse" should be a checkbox
* "start/stop recording" should be a checkbox
the patch:
Code: Select all
diff --git a/Debugger/dbgcmd.h b/Debugger/dbgcmd.h
index 624a989..4936245 100644
--- a/Debugger/dbgcmd.h
+++ b/Debugger/dbgcmd.h
@@ -131,10 +131,11 @@ public:
/**
* this handler, handles the following commands:
* -exec-run
- * -exec-continue
- * -exec-step
- * -exec-next
- * -exec-finish
+ * -exec-continue [--reverse]
+ * -exec-step [--reverse]
+ * -exec-next [--reverse]
+ * -exec-next-instruction [--reverse]
+ * -exec-finish [--reverse]
*/
class DbgCmdHandlerAsyncCmd : public DbgCmdHandler
{
diff --git a/Debugger/debuggergdb.cpp b/Debugger/debuggergdb.cpp
index a97f0ed..5112de9 100644
--- a/Debugger/debuggergdb.cpp
+++ b/Debugger/debuggergdb.cpp
@@ -323,6 +323,16 @@ bool DbgGdb::NextInstruction()
return WriteCommand( wxT( "-exec-next-instruction" ), new DbgCmdHandlerAsyncCmd( m_observer, this ) );
}
+bool DbgGdb::ReverseNext()
+{
+ return WriteCommand( wxT( "-exec-next --reverse" ), new DbgCmdHandlerAsyncCmd( m_observer, this ) );
+}
+
+bool DbgGdb::ReverseNextInstruction()
+{
+ return WriteCommand( wxT( "-exec-next-instruction --reverse" ), new DbgCmdHandlerAsyncCmd( m_observer, this ) );
+}
+
void DbgGdb::SetBreakpoints()
{
for ( size_t i=0; i< m_bpList.size(); i++ ) {
@@ -509,6 +519,51 @@ bool DbgGdb::StepOut()
return WriteCommand( wxT( "-exec-finish" ), new DbgCmdHandlerAsyncCmd( m_observer, this ) );
}
+bool DbgGdb::Record()
+{
+ return WriteCommand( wxT( "record full" ), new DbgCmdHandlerAsyncCmd( m_observer, this ) );
+}
+
+bool DbgGdb::StopRecord()
+{
+ return WriteCommand( wxT( "record stop" ), new DbgCmdHandlerAsyncCmd( m_observer, this ) );
+}
+
+bool DbgGdb::ReverseContinue()
+{
+ return WriteCommand( wxT( "-exec-continue --reverse" ), new DbgCmdHandlerAsyncCmd( m_observer, this ) );
+}
+
+bool DbgGdb::ReverseStepIn()
+{
+ return WriteCommand( wxT( "-exec-step --reverse" ), new DbgCmdHandlerAsyncCmd( m_observer, this ) );
+}
+
+bool DbgGdb::ReverseStepOut()
+{
+ return WriteCommand( wxT( "-exec-finish --reverse" ), new DbgCmdHandlerAsyncCmd( m_observer, this ) );
+}
+
+bool DbgGdb::SetExecDirectionReverse()
+{
+ return WriteCommand( wxT( "set exec-direction reverse" ), new DbgCmdHandlerAsyncCmd( m_observer, this ) );
+}
+
+bool DbgGdb::SetExecDirectionForward()
+{
+ return WriteCommand( wxT( "set exec-direction forward" ), new DbgCmdHandlerAsyncCmd( m_observer, this ) );
+}
+
+bool DbgGdb::DisableHardwareBreakpoints()
+{
+ return WriteCommand( wxT( "set can-use-hw-watchpoints 0" ), new DbgCmdHandlerAsyncCmd( m_observer, this ) );
+}
+
+bool DbgGdb::EnableHardwareBreakpoints()
+{
+ return WriteCommand( wxT( "set can-use-hw-watchpoints 1" ), new DbgCmdHandlerAsyncCmd( m_observer, this ) );
+}
+
bool DbgGdb::IsRunning()
{
return m_gdbProcess != NULL;
diff --git a/Debugger/debuggergdb.h b/Debugger/debuggergdb.h
index 6aeb983..1f95761 100644
--- a/Debugger/debuggergdb.h
+++ b/Debugger/debuggergdb.h
@@ -132,6 +132,17 @@ public:
virtual bool Next();
virtual bool NextInstruction();
virtual bool Continue();
+ virtual bool Record();
+ virtual bool StopRecord();
+ virtual bool ReverseStepIn();
+ virtual bool ReverseStepOut();
+ virtual bool ReverseNext();
+ virtual bool ReverseNextInstruction();
+ virtual bool ReverseContinue();
+ virtual bool SetExecDirectionReverse();
+ virtual bool SetExecDirectionForward();
+ virtual bool DisableHardwareBreakpoints();
+ virtual bool EnableHardwareBreakpoints();
virtual bool QueryFileLine();
virtual bool Disassemble(const wxString &filename, int lineNumber);
virtual bool Interrupt();
diff --git a/Interfaces/debugger.h b/Interfaces/debugger.h
index b01a41e..181dca3 100644
--- a/Interfaces/debugger.h
+++ b/Interfaces/debugger.h
@@ -43,6 +43,17 @@ enum DebuggerCommands {
DBG_STEPOUT,
DBG_SHOW_CURSOR,
DBG_NEXTI,
+ DBG_RECORD,
+ DBG_STOP_RECORD,
+ DBG_REVERSE_CONTINUE,
+ DBG_REVERSE_NEXT,
+ DBG_REVERSE_STEPIN,
+ DBG_REVERSE_STEPOUT,
+ DBG_REVERSE_NEXTI,
+ DBG_DISABLE_HARDWARE_BREAKPOINTS,
+ DBG_ENABLE_HARDWARE_BREAKPOINTS,
+ DBG_SET_EXEC_DIRECTION_REVERSE,
+ DBG_SET_EXEC_DIRECTION_FORWARD
};
// Breakpoint types. If you add more, LEditor::FillBPtoMarkerArray will also need altering
@@ -700,6 +711,55 @@ public:
*/
virtual bool StepOut() = 0;
/**
+ * \brief begin recording (for gdb reverse debuggubg)
+ */
+ virtual bool Record() = 0;
+ /**
+ * \brief stop recording (for gdb reverse debuggubg)
+ */
+ virtual bool StopRecord() = 0;
+ /**
+ * \brief step to next line
+ * \return true on success, false otherwise
+ */
+ virtual bool ReverseNext() = 0;
+ /**
+ * @brief perform "reverse next instruction" command
+ * @return true on success, false otherwise
+ */
+ virtual bool ReverseNextInstruction() = 0;
+ /**
+ * \brief reverse continue execution of the debugger, until next breakpoint is hit, or program terminates
+ * \return true on success, false otherwise
+ */
+ virtual bool ReverseContinue() = 0;
+ /**
+ * \brief reverse step into method
+ * \return true on success, false otherwise
+ */
+ virtual bool ReverseStepIn() = 0;
+ /**
+ * \brief reverse step out the current method (gdb's 'reverse-finish' command)
+ * \return true on success, false otherwise
+ */
+ virtual bool ReverseStepOut() = 0;
+ /**
+ * \brief set execution direction to reverse (gdb's '-exec-set exec-direction reverse' command)
+ */
+ virtual bool SetExecDirectionReverse() = 0;
+ /**
+ * \brief set execution direction to forward (gdb's '-exec-set exec-direction forward' command)
+ */
+ virtual bool SetExecDirectionForward() = 0;
+ /**
+ * \brief disable hardware breakpoints. This is necessary if you want to use watchpoints while executing the program in reverse.
+ */
+ virtual bool DisableHardwareBreakpoints() = 0;
+ /**
+ * \brief enable hardware breakpoints.
+ */
+ virtual bool EnableHardwareBreakpoints() = 0;
+ /**
* \brief set break point at given file and line, or function
*/
virtual bool Break(const BreakpointInfo& bp) = 0;
diff --git a/LiteEditor.workspace b/LiteEditor.workspace
index 4c8a82e..f756677 100644
--- a/LiteEditor.workspace
+++ b/LiteEditor.workspace
@@ -8,9 +8,9 @@
</Ctags>
<Project Name="wxsqlite3" Path="sdk/wxsqlite3/wxsqlite3.project" Active="No"/>
<Project Name="plugin_sdk" Path="Plugin/plugin_sdk.project" Active="No"/>
- <Project Name="LiteEditor" Path="LiteEditor/LiteEditor.project" Active="Yes"/>
+ <Project Name="LiteEditor" Path="LiteEditor/LiteEditor.project" Active="No"/>
<Project Name="sqlite3" Path="sqlite3/sqlite3.project"/>
- <Project Name="CodeLite" Path="CodeLite/CodeLite.project" Active="No"/>
+ <Project Name="CodeLite" Path="CodeLite/CodeLite.project" Active="Yes"/>
<Project Name="DebuggerGDB" Path="Debugger/DebuggerGDB.project" Active="No"/>
<Project Name="Interfaces" Path="Interfaces/Interfaces.project" Active="No"/>
<Project Name="Gizmos" Path="Gizmos/Gizmos.project" Active="No"/>
@@ -48,7 +48,7 @@
<Project Name="SpellCheck" Path="SpellChecker/SpellCheck.project" Active="No"/>
<Project Name="hunspell" Path="SpellChecker/hunspell/hunspell.project" Active="No"/>
<BuildMatrix>
- <WorkspaceConfiguration Name="Win Release Unicode" Selected="yes">
+ <WorkspaceConfiguration Name="Win Release Unicode" Selected="no">
<Project Name="abbreviation" ConfigName="WinReleaseUnicode"/>
<Project Name="CallGraph" ConfigName="WinReleaseUnicode"/>
<Project Name="CMakePlugin" ConfigName="WinReleaseUnicode"/>
@@ -165,7 +165,7 @@
<Project Name="SpellCheck" ConfigName="DebugUnicode"/>
<Project Name="hunspell" ConfigName="Debug"/>
</WorkspaceConfiguration>
- <WorkspaceConfiguration Name="CMake_Debug" Selected="no">
+ <WorkspaceConfiguration Name="CMake_Debug" Selected="yes">
<Project Name="ZoomNavigator" ConfigName="WinReleaseUnicode"/>
<Project Name="wxsqlite3" ConfigName="WinReleaseUnicode"/>
<Project Name="wxshapeframework" ConfigName="WinReleaseUnicode"/>
diff --git a/LiteEditor/frame.cpp b/LiteEditor/frame.cpp
index 502d1fd..ceb6a40 100644
--- a/LiteEditor/frame.cpp
+++ b/LiteEditor/frame.cpp
@@ -340,6 +340,8 @@ BEGIN_EVENT_TABLE(clMainFrame, wxFrame)
EVT_UPDATE_UI(wxID_FIND, clMainFrame::OnIncrementalSearchUI )
EVT_UPDATE_UI(wxID_REPLACE, clMainFrame::OnFileExistUpdateUI )
+ EVT_UPDATE_UI(XRCID("select_previous"), clMainFrame::OnFileExistUpdateUI )
+ EVT_UPDATE_UI(XRCID("select_next"), clMainFrame::OnFileExistUpdateUI )
EVT_UPDATE_UI(XRCID("find_next"), clMainFrame::OnFileExistUpdateUI )
EVT_UPDATE_UI(XRCID("find_previous"), clMainFrame::OnFileExistUpdateUI )
EVT_UPDATE_UI(XRCID("find_next_at_caret"), clMainFrame::OnFileExistUpdateUI )
@@ -454,6 +456,18 @@ BEGIN_EVENT_TABLE(clMainFrame, wxFrame)
EVT_MENU(XRCID("dbg_next"), clMainFrame::OnDebugCmd)
EVT_MENU(XRCID("dbg_nexti"), clMainFrame::OnDebugCmd)
EVT_MENU(XRCID("show_cursor"), clMainFrame::OnDebugCmd)
+ EVT_MENU(XRCID("dbg_record"), clMainFrame::OnDebugCmd)
+ EVT_MENU(XRCID("dbg_stoprecord"), clMainFrame::OnDebugCmd)
+ EVT_MENU(XRCID("dbg_reverse_stepin"), clMainFrame::OnDebugCmd)
+ EVT_MENU(XRCID("dbg_reverse_next"), clMainFrame::OnDebugCmd)
+ EVT_MENU(XRCID("dbg_reverse_nexti"), clMainFrame::OnDebugCmd)
+ EVT_MENU(XRCID("dbg_reverse_stepout"), clMainFrame::OnDebugCmd)
+ EVT_MENU(XRCID("dbg_reverse_continue"), clMainFrame::OnDebugCmd)
+ EVT_MENU(XRCID("dbg_set_exec_forward"), clMainFrame::OnDebugCmd)
+ EVT_MENU(XRCID("dbg_set_exec_reverse"), clMainFrame::OnDebugCmd)
+ EVT_MENU(XRCID("dbg_disable_hardware_breakpoits"), clMainFrame::OnDebugCmd)
+ EVT_MENU(XRCID("dbg_enable_hardware_breakpoits"), clMainFrame::OnDebugCmd)
+
EVT_MENU(XRCID("add_breakpoint"), clMainFrame::DispatchCommandEvent)
EVT_MENU(XRCID("insert_breakpoint"), clMainFrame::DispatchCommandEvent) // Toggles
EVT_MENU(XRCID("disable_all_breakpoints"), clMainFrame::DispatchCommandEvent)
@@ -3291,11 +3305,55 @@ void clMainFrame::OnDebugCmd(wxCommandEvent &e)
} else if (e.GetId() == XRCID("show_cursor")) {
cmd = DBG_SHOW_CURSOR;
eventId = wxEVT_DBG_UI_SHOW_CURSOR;
-
+
} else if ( e.GetId() == XRCID("dbg_nexti")) {
cmd = DBG_NEXTI;
eventId = wxEVT_DBG_UI_NEXT_INST;
-
+
+ } else if ( e.GetId() == XRCID("dbg_record")) {
+ cmd = DBG_RECORD;
+ eventId = wxEVT_DBG_UI_NEXT_INST;
+
+ } else if ( e.GetId() == XRCID("dbg_stoprecord")) {
+ cmd = DBG_STOP_RECORD;
+ eventId = wxEVT_DBG_UI_NEXT_INST;
+
+ } else if ( e.GetId() == XRCID("dbg_reverse_next")) {
+ cmd = DBG_REVERSE_NEXT;
+ eventId = wxEVT_DBG_UI_NEXT_INST;
+
+ } else if ( e.GetId() == XRCID("dbg_reverse_nexti")) {
+ cmd = DBG_REVERSE_NEXTI;
+ eventId = wxEVT_DBG_UI_NEXT_INST;
+
+ } else if (e.GetId() == XRCID("dbg_reverse_stepin")) {
+ cmd = DBG_REVERSE_STEPIN;
+ eventId = wxEVT_DBG_UI_STEP_IN;
+
+ } else if ( e.GetId() == XRCID("dbg_reverse_stepout")) {
+ cmd = DBG_REVERSE_STEPOUT;
+ eventId = wxEVT_DBG_UI_NEXT_INST;
+
+ } else if ( e.GetId() == XRCID("dbg_reverse_continue")) {
+ cmd = DBG_REVERSE_CONTINUE;
+ eventId = wxEVT_DBG_UI_NEXT_INST;
+
+ } else if ( e.GetId() == XRCID("dbg_set_exec_forward")) {
+ cmd = DBG_SET_EXEC_DIRECTION_FORWARD;
+ eventId = wxEVT_DBG_UI_NEXT_INST;
+
+ } else if ( e.GetId() == XRCID("dbg_set_exec_reverse")) {
+ cmd = DBG_SET_EXEC_DIRECTION_REVERSE;
+ eventId = wxEVT_DBG_UI_NEXT_INST;
+
+ } else if ( e.GetId() == XRCID("dbg_disable_hardware_breakpoits")) {
+ cmd = DBG_DISABLE_HARDWARE_BREAKPOINTS;
+ eventId = wxEVT_DBG_UI_NEXT_INST;
+
+ } else if ( e.GetId() == XRCID("dbg_enable_hardware_breakpoits")) {
+ cmd = DBG_ENABLE_HARDWARE_BREAKPOINTS;
+ eventId = wxEVT_DBG_UI_NEXT_INST;
+
}
// ALlow the plugins to handle this command first
@@ -3321,7 +3379,18 @@ void clMainFrame::OnDebugCmdUI(wxUpdateUIEvent &e)
e.GetId() == XRCID("dbg_stepout") ||
e.GetId() == XRCID("dbg_next") ||
e.GetId() == XRCID("dbg_nexti") ||
- e.GetId() == XRCID("show_cursor")) {
+ e.GetId() == XRCID("show_cursor") ||
+ e.GetId() == XRCID("dbg_record") ||
+ e.GetId() == XRCID("dbg_stoprecord") ||
+ e.GetId() == XRCID("dbg_reverse_stepin") ||
+ e.GetId() == XRCID("dbg_reverse_next") ||
+ e.GetId() == XRCID("dbg_reverse_nexti") ||
+ e.GetId() == XRCID("dbg_reverse_stepout") ||
+ e.GetId() == XRCID("dbg_reverse_continue") ||
+ e.GetId() == XRCID("dbg_set_exec_forward") ||
+ e.GetId() == XRCID("dbg_set_exec_reverse") ||
+ e.GetId() == XRCID("dbg_disable_hardware_breakpoits") ||
+ e.GetId() == XRCID("dbg_enable_hardware_breakpoits")) {
IDebugger *dbgr = DebuggerMgr::Get().GetActiveDebugger();
e.Enable(eventIsRunning.IsAnswer() || (dbgr && dbgr->IsRunning()) );
}
diff --git a/LiteEditor/manager.cpp b/LiteEditor/manager.cpp
index a2205d3..af09565 100644
--- a/LiteEditor/manager.cpp
+++ b/LiteEditor/manager.cpp
@@ -2631,6 +2631,47 @@ void Manager::DbgDoSimpleCommand ( int cmd )
clMainFrame::Get()->GetDebuggerPane()->GetWatchesTable()->ResetTableColors();
dbgr->NextInstruction();
break;
+ case DBG_REVERSE_NEXT:
+ clMainFrame::Get()->GetDebuggerPane()->GetLocalsTable()->ResetTableColors();
+ clMainFrame::Get()->GetDebuggerPane()->GetWatchesTable()->ResetTableColors();
+ dbgr->ReverseNext();
+ break;
+ case DBG_REVERSE_STEPIN:
+ clMainFrame::Get()->GetDebuggerPane()->GetLocalsTable()->ResetTableColors();
+ clMainFrame::Get()->GetDebuggerPane()->GetWatchesTable()->ResetTableColors();
+ dbgr->ReverseStepIn();
+ break;
+ case DBG_REVERSE_STEPOUT:
+ clMainFrame::Get()->GetDebuggerPane()->GetLocalsTable()->ResetTableColors();
+ clMainFrame::Get()->GetDebuggerPane()->GetWatchesTable()->ResetTableColors();
+ dbgr->ReverseStepOut();
+ break;
+ case DBG_REVERSE_NEXTI:
+ clMainFrame::Get()->GetDebuggerPane()->GetLocalsTable()->ResetTableColors();
+ clMainFrame::Get()->GetDebuggerPane()->GetWatchesTable()->ResetTableColors();
+ dbgr->ReverseNextInstruction();
+ break;
+ case DBG_DISABLE_HARDWARE_BREAKPOINTS:
+ dbgr->DisableHardwareBreakpoints();
+ break;
+ case DBG_ENABLE_HARDWARE_BREAKPOINTS:
+ dbgr->EnableHardwareBreakpoints();
+ break;
+ case DBG_SET_EXEC_DIRECTION_REVERSE:
+ dbgr->SetExecDirectionReverse();
+ break;
+ case DBG_SET_EXEC_DIRECTION_FORWARD:
+ dbgr->SetExecDirectionForward();
+ break;
+ case DBG_RECORD:
+ dbgr->Record();
+ break;
+ case DBG_STOP_RECORD:
+ dbgr->StopRecord();
+ break;
+ case DBG_REVERSE_CONTINUE:
+ dbgr->ReverseContinue();
+ break;
default:
break;
}
diff --git a/LiteEditor/quickfindbar.cpp b/LiteEditor/quickfindbar.cpp
index fd7309a..f32534e 100644
--- a/LiteEditor/quickfindbar.cpp
+++ b/LiteEditor/quickfindbar.cpp
@@ -79,6 +79,8 @@ QuickFindBar::QuickFindBar(wxWindow* parent, wxWindowID id)
wxTheApp->Connect(wxID_COPY, wxEVT_UPDATE_UI, wxUpdateUIEventHandler(QuickFindBar::OnEditUI), NULL, this);
wxTheApp->Connect(wxID_PASTE, wxEVT_UPDATE_UI, wxUpdateUIEventHandler(QuickFindBar::OnEditUI), NULL, this);
wxTheApp->Connect(wxID_SELECTALL, wxEVT_UPDATE_UI, wxUpdateUIEventHandler(QuickFindBar::OnEditUI), NULL, this);
+ wxTheApp->Connect(XRCID("select_previous"), wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler(QuickFindBar::OnSelectPrevious), NULL, this);
+ wxTheApp->Connect(XRCID("select_next"), wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler(QuickFindBar::OnSelectNext), NULL, this);
wxTheApp->Connect(XRCID("find_next"), wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler(QuickFindBar::OnFindNext), NULL, this);
wxTheApp->Connect(XRCID("find_previous"), wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler(QuickFindBar::OnFindPrevious), NULL, this);
wxTheApp->Connect(XRCID("find_next_at_caret"), wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler(QuickFindBar::OnFindNextCaret), NULL, this);
@@ -536,6 +538,34 @@ void QuickFindBar::OnFindPrevious(wxCommandEvent& e)
DoSearch(false, false);
}
+void QuickFindBar::OnSelectPrevious(wxCommandEvent& e)
+{
+ CHECK_FOCUS_WIN();
+
+ // Highlighted text takes precedence over the current search string
+ wxString selectedText = DoGetSelectedText();
+ if (selectedText.IsEmpty() == false) {
+ m_findWhat->ChangeValue(selectedText);
+ m_findWhat->SelectAll();
+ }
+
+ DoSearch(false, false, true);
+}
+
+void QuickFindBar::OnSelectNext(wxCommandEvent& e)
+{
+ CHECK_FOCUS_WIN();
+
+ // Highlighted text takes precedence over the current search string
+ wxString selectedText = DoGetSelectedText();
+ if (selectedText.IsEmpty() == false) {
+ m_findWhat->ChangeValue( selectedText );
+ m_findWhat->SelectAll();
+ }
+
+ DoSearch(true, false, true);
+}
+
void QuickFindBar::OnFindNextCaret(wxCommandEvent& e)
{
CHECK_FOCUS_WIN();
@@ -718,6 +748,8 @@ QuickFindBar::~QuickFindBar()
wxTheApp->Disconnect(wxID_COPY, wxEVT_UPDATE_UI, wxUpdateUIEventHandler(QuickFindBar::OnEditUI), NULL, this);
wxTheApp->Disconnect(wxID_PASTE, wxEVT_UPDATE_UI, wxUpdateUIEventHandler(QuickFindBar::OnEditUI), NULL, this);
wxTheApp->Disconnect(wxID_SELECTALL, wxEVT_UPDATE_UI, wxUpdateUIEventHandler(QuickFindBar::OnEditUI), NULL, this);
+ wxTheApp->Disconnect(XRCID("select_previous"), wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler(QuickFindBar::OnSelectPrevious), NULL, this);
+ wxTheApp->Disconnect(XRCID("select_next"), wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler(QuickFindBar::OnSelectNext), NULL, this);
wxTheApp->Disconnect(XRCID("find_next"), wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler(QuickFindBar::OnFindNext), NULL, this);
wxTheApp->Disconnect(XRCID("find_previous"), wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler(QuickFindBar::OnFindPrevious), NULL, this);
wxTheApp->Disconnect(XRCID("find_next_at_caret"), wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler(QuickFindBar::OnFindNextCaret), NULL, this);
diff --git a/LiteEditor/quickfindbar.h b/LiteEditor/quickfindbar.h
index a8da969..e8bc48e 100644
--- a/LiteEditor/quickfindbar.h
+++ b/LiteEditor/quickfindbar.h
@@ -76,6 +76,8 @@ protected:
void OnReceivingFocus(wxFocusEvent& event);
void OnReleaseEditor(wxCommandEvent &e);
+ void OnSelectPrevious (wxCommandEvent &e);
+ void OnSelectNext (wxCommandEvent &e);
void OnFindNext (wxCommandEvent &e);
void OnFindPrevious (wxCommandEvent &e);
void OnFindNextCaret (wxCommandEvent &e);
diff --git a/Runtime/rc/menu.xrc b/Runtime/rc/menu.xrc
index a672b63..8940e8f 100644
--- a/Runtime/rc/menu.xrc
+++ b/Runtime/rc/menu.xrc
@@ -292,6 +292,12 @@
<object class="wxMenuItem" name="wxID_REPLACE">
<label>&Replace...</label>
</object>
+ <object class="wxMenuItem" name="select_previous">
+ <label>Select Previous Occu&rrence</label>
+ </object>
+ <object class="wxMenuItem" name="select_next">
+ <label>Select Next &Occurrence</label>
+ </object>
<object class="wxMenuItem" name="find_next">
<label>Find &Next</label>
</object>
@@ -506,6 +512,47 @@
<object class="wxMenuItem" name="dbg_stepout">
<label>Step &Out</label>
</object>
+
+ <object class="wxMenu" name="debugger_reverse_debugging">
+ <label>GDB &Reverse Debugging</label>
+ <style>wxMENU_TEAROFF</style>
+ <object class="wxMenuItem" name="dbg_record">
+ <label>&Begin Recording</label>
+ </object>
+ <object class="wxMenuItem" name="dbg_stoprecord">
+ <label>&Stop Recording</label>
+ </object>
+ <object class="wxMenuItem" name="wxID_SEPARATOR"/>
+ <object class="wxMenuItem" name="dbg_reverse_stepin">
+ <label>Reverse Step &Into</label>
+ </object>
+ <object class="wxMenuItem" name="dbg_reverse_next">
+ <label>Reverse &Next</label>
+ </object>
+ <object class="wxMenuItem" name="dbg_reverse_nexti">
+ <label>Reverse Next Ins&truction</label>
+ </object>
+ <object class="wxMenuItem" name="dbg_reverse_stepout">
+ <label>Reverse Step &Out</label>
+ </object>
+ <object class="wxMenuItem" name="dbg_reverse_continue">
+ <label>Reverse &Continue</label>
+ </object>
+ <object class="wxMenuItem" name="wxID_SEPARATOR"/>
+ <object class="wxMenuItem" name="dbg_set_exec_forward">
+ <label>Set Exec Direction To &Forward</label>
+ </object>
+ <object class="wxMenuItem" name="dbg_set_exec_reverse">
+ <label>Set Exec Direction To &Reverse</label>
+ </object>
+ <object class="wxMenuItem" name="wxID_SEPARATOR"/>
+ <object class="wxMenuItem" name="dbg_disable_hardware_breakpoits">
+ <label>&Disable Hardware Breakpoints</label>
+ </object>
+ <object class="wxMenuItem" name="dbg_enable_hardware_breakpoits">
+ <label>&Enable Hardware Breakpoints</label>
+ </object>
+ </object>
<object class="wxMenuItem" name="wxID_SEPARATOR"/>
<object class="wxMenuItem" name="show_cursor">
<label>Show &Cursor</label>
@@ -529,7 +576,7 @@
</object>
<object class="wxMenuItem" name="wxID_SEPARATOR"/>
<object class="wxMenu" name="debugger_windows">
- <label>GDB Windows</label>
+ <label>GDB &Windows</label>
<style>wxMENU_TEAROFF</style>
<object class="wxMenuItem" name="debugger_win_locals">
<label>Locals</label>
Code: Select all
dbg_reverse_stepout|Debugger|Reverse Step Out|Shift-Alt-O
dbg_reverse_stepin|Debugger|Reverse Step Into|Shift-Alt-I
dbg_reverse_next|Debugger|Reverse Next|Shift-Alt-N
dbg_reverse_nexti|Debugger|Reverse Next Instruction|Shift-Alt-T
dbg_reverse_continue|Debugger|Reverse Continue|Shift-Alt-C
dbg_record|Debugger|Begin Record|Shift-Alt-B
dbg_stoprecord|Debugger|Stop Record|Shift-Alt-S
dbg_set_exec_forward|Debugger|Set Exec Direction To Forward|Shift-Alt-F
dbg_set_exec_reverse|Debugger|Set Exec Direction To Reverse|Shift-Alt-R
dbg_disable_hardware_breakpoits|Debugger|Disable Hardware Breakpoints|Shift-Alt-D
dbg_enable_hardware_breakpoits|Debugger|Enable Hardware Breakpoints|Shift-Alt-W