📄 debuggergdb.cpp
字号:
{
ed->Show(true);
ed->GetControl()->GotoLine(line - 10); // make sure we can see some context...
ed->GetControl()->GotoLine(line - 1);
ed->MarkLine(ACTIVE_LINE, line - 1);
}
}
}
}
wxString DebuggerGDB::GetEditorWordAtCaret()
{
cbEditor* ed = Manager::Get()->GetEditorManager()->GetBuiltinActiveEditor();
if (!ed)
return _T("");
int start = ed->GetControl()->WordStartPosition(ed->GetControl()->GetCurrentPos(), true);
int end = ed->GetControl()->WordEndPosition(ed->GetControl()->GetCurrentPos(), true);
return ed->GetControl()->GetTextRange(start, end);
}
// events
void DebuggerGDB::OnUpdateUI(wxUpdateUIEvent& event)
{
cbProject* prj = Manager::Get()->GetProjectManager()->GetActiveProject();
cbEditor* ed = Manager::Get()->GetEditorManager()->GetBuiltinActiveEditor();
wxMenuBar* mbar = Manager::Get()->GetAppWindow()->GetMenuBar();
if (mbar)
{
mbar->Enable(idMenuDebug, !m_pProcess && prj);
mbar->Enable(idMenuContinue, m_pProcess && prj && m_ProgramIsStopped);
mbar->Enable(idMenuNext, m_pProcess && prj && m_ProgramIsStopped);
mbar->Enable(idMenuStep, prj && m_ProgramIsStopped);
mbar->Enable(idMenuStepOut, m_pProcess && prj && m_ProgramIsStopped);
mbar->Enable(idMenuRunToCursor, prj && ed && m_ProgramIsStopped);
mbar->Enable(idMenuToggleBreakpoint, prj && ed && m_ProgramIsStopped);
mbar->Enable(idMenuSendCommandToGDB, m_pProcess && m_ProgramIsStopped);
mbar->Enable(idMenuAddSymbolFile, m_pProcess && m_ProgramIsStopped);
mbar->Enable(idMenuBacktrace, m_pProcess && m_ProgramIsStopped);
mbar->Enable(idMenuCPU, m_pProcess && m_ProgramIsStopped);
mbar->Enable(idMenuEditWatches, prj && m_ProgramIsStopped);
mbar->Enable(idMenuStop, m_pProcess && prj);
}
#ifdef implement_debugger_toolbar
wxToolBar* tbar = m_pTbar;//Manager::Get()->GetAppWindow()->GetToolBar();
tbar->EnableTool(idMenuDebug, (!m_pProcess || m_ProgramIsStopped) && prj);
tbar->EnableTool(idMenuRunToCursor, prj && ed && m_ProgramIsStopped);
tbar->EnableTool(idMenuNext, m_pProcess && prj && m_ProgramIsStopped);
tbar->EnableTool(idMenuStep, prj && m_ProgramIsStopped);
tbar->EnableTool(idMenuStepOut, m_pProcess && prj && m_ProgramIsStopped);
tbar->EnableTool(idMenuStop, m_pProcess && prj);
#endif
// allow other UpdateUI handlers to process this event
// *very* important! don't forget it...
event.Skip();
}
void DebuggerGDB::OnDebug(wxCommandEvent& event)
{
if (!m_pProcess)
Debug();
else
{
if (m_ProgramIsStopped)
CmdContinue();
}
}
void DebuggerGDB::OnContinue(wxCommandEvent& event)
{
CmdContinue();
}
void DebuggerGDB::OnNext(wxCommandEvent& event)
{
CmdNext();
}
void DebuggerGDB::OnStep(wxCommandEvent& event)
{
if (!m_pProcess)
{
m_BreakOnEntry = true;
Debug();
}
else CmdStep();
}
void DebuggerGDB::OnStepOut(wxCommandEvent& event)
{
CmdStepOut();
}
void DebuggerGDB::OnRunToCursor(wxCommandEvent& event)
{
CmdRunToCursor();
}
void DebuggerGDB::OnToggleBreakpoint(wxCommandEvent& event)
{
CmdToggleBreakpoint();
}
void DebuggerGDB::OnStop(wxCommandEvent& event)
{
CmdStop();
}
void DebuggerGDB::OnSendCommandToGDB(wxCommandEvent& event)
{
wxString cmd = wxGetTextFromUser(_("Enter command for GDB:"), _("Send command to GDB:"), m_LastCmd);
if (cmd.IsEmpty())
return;
m_LastCmd = cmd;
// Manager::Get()->GetMessageManager()->Log(m_PageIndex, _("Sending command \"%s\" to gdb:"), m_LastCmd.c_str());
// SendCommand("set annotate 0");
SendCommand(m_LastCmd);
// SendCommand("set annotate 2");
}
wxString DebuggerGDB::GetInfoFor(const wxString& dbgCmd)
{
if (!m_pProcess)
return wxEmptyString;
m_TimerPollDebugger.Stop();
wxSafeYield();
SendCommand(dbgCmd);
wxString buf = GetNextOutputLine();
wxString output;
// delay until gdb starts sending output
// (with 0.5 second timeout - approximately)
int i = 0;
while (buf.IsEmpty() && i < 500)
{
buf = GetNextOutputLine();
#if wxVERSION_NUMBER < 2500
wxUsleep(5);
#else
wxMilliSleep(5);
#endif
i += 5;
}
if (buf.IsEmpty())
m_pLog->AddLog(_("Timeout expired waiting for info..."));
// let's do business
while (!buf.IsEmpty())
{
if (buf.StartsWith(g_EscapeChars))
{
// buffer holds an escaped output
buf.Remove(0, 2); // clear it
if (buf.Matches(_T("post-prompt")))
{
// our command has been parsed by gdb, so we start receiving data
buf = GetNextOutputLine();
while (1)
{
if (buf.StartsWith(g_EscapeChars))
{
// escaped output
buf.Remove(0, 2);
if (buf.Matches(_T("pre-prompt"))) // if we encounter this, we 're done
break;
}
else if (!buf.IsEmpty())
{
// clean output
output << buf;
// append new-line when needed, to separate vars
if (!buf.Matches(_T(" = ")) && buf.Find(_T('=')) != -1 && buf.GetChar(buf.Length() - 2) != _T(','))
output << _T('\n');
}
buf = GetNextOutputLine();
}
break;
}
}
buf = GetNextOutputLine();
}
m_TimerPollDebugger.Start(100);
// loop until gdb finishes sending output
// (with 0.5 second timeout - approximately)
i = 0;
while (!buf.IsEmpty() && i < 500)
{
buf = GetNextOutputLine();
//GDB workaround
//If overloaded C++ constructor/destructor, break on all.
if (buf.StartsWith(g_EscapeChars))
{
buf.Remove(0,2);
if (buf.Matches(_T("overload-choice")))
{
SendCommand(_T("1"));
}
}
//end GDB workaround
#if wxVERSION_NUMBER < 2500
wxUsleep(5);
#else
wxMilliSleep(5);
#endif
i += 5;
}
return output;
}
void DebuggerGDB::OnAddSymbolFile(wxCommandEvent& event)
{
wxString file = wxFileSelector(_("Choose file to read symbols from"),
_T(""),
_T(""),
_T(""),
_("Executables and libraries|*.exe;*.dll"),
wxOPEN | wxFILE_MUST_EXIST);
if (file.IsEmpty())
return;
Manager::Get()->GetMessageManager()->Log(m_PageIndex, _("Adding symbol file: %s"), file.c_str());
ConvertToGDBDirectory(file);
SendCommand(_T("add-symbol-file ") + file);
}
void DebuggerGDB::OnBacktrace(wxCommandEvent& event)
{
CmdBacktrace();
}
void DebuggerGDB::OnDisassemble(wxCommandEvent& event)
{
CmdDisassemble();
}
void DebuggerGDB::OnEditWatches(wxCommandEvent& event)
{
wxArrayString watches = m_pTree->GetWatches();
EditArrayStringDlg dlg(Manager::Get()->GetAppWindow(), watches);
if (dlg.ShowModal() == wxID_OK)
{
m_pTree->SetWatches(watches);
}
}
void DebuggerGDB::OnGDBOutput(wxCommandEvent& event)
{
wxString msg = event.GetString();
if (!msg.IsEmpty())
{
ParseOutput(msg);
}
}
void DebuggerGDB::OnGDBError(wxCommandEvent& event)
{
wxString msg = event.GetString();
if (!msg.IsEmpty())
{
ParseOutput(msg);
}
}
void DebuggerGDB::OnGDBTerminated(wxCommandEvent& event)
{
m_TimerPollDebugger.Stop();
m_LastExitCode = event.GetInt();
//the process deletes itself
// m_pProcess = 0L;
ClearActiveMarkFromAllEditors();
Manager::Get()->GetMessageManager()->Log(m_PageIndex, _("Debugger finished with status %d"), m_LastExitCode);
if (m_NoDebugInfo)
{
wxMessageBox(_("This project/target has no debugging info."
"Please change this in the project's build options and retry..."),
_("Error"),
wxICON_STOP);
}
}
void DebuggerGDB::OnBreakpointAdded(CodeBlocksEvent& event)
{
if (!m_pProcess)
return;
cbEditor* ed = event.GetEditor();
if (ed)
{
Manager::Get()->GetMessageManager()->Log(m_PageIndex, _("Breakpoint added: file %s, line %d"), ed->GetFilename().c_str(), event.GetInt() + 1);
/*
ProjectFile* pf = ed->GetProjectFile();
if (!pf)
return;
wxString filename = pf->relativeFilename;
ConvertToGDBFriendly(filename);
// Manager::Get()->GetMessageManager()->Log(m_PageIndex, _("file %s"), filename.c_str());
wxString cmd;
cmd << "break " << filename << ":" << event.GetInt() + 1;
SendCommand(cmd);
*/
}
else
Manager::Get()->GetMessageManager()->Log(m_PageIndex, _("OnBreakpointAdded(): No editor defined!"));
}
void DebuggerGDB::OnBreakpointDeleted(CodeBlocksEvent& event)
{
if (!m_pProcess)
return;
cbEditor* ed = event.GetEditor();
if (ed)
{
Manager::Get()->GetMessageManager()->Log(m_PageIndex, _("Breakpoint deleted: file %s, line %d"), ed->GetFilename().c_str(), event.GetInt() + 1);
/*
ProjectFile* pf = ed->GetProjectFile();
if (!pf)
return;
wxString filename = pf->relativeFilename;
ConvertToGDBFriendly(filename);
// Manager::Get()->GetMessageManager()->Log(m_PageIndex, _("file %s"), filename.c_str());
wxString cmd;
cmd << "clear " << filename << ":" << event.GetInt() + 1;
SendCommand(cmd);
*/
}
else
Manager::Get()->GetMessageManager()->Log(m_PageIndex, _("OnBreakpointDeleted(): No editor defined!"));
}
void DebuggerGDB::OnValueTooltip(CodeBlocksEvent& event)
{
if (!m_pProcess || !m_ProgramIsStopped)
return;
if (!ConfigManager::Get()->Read(_T("debugger_gdb/eval_tooltip"), 0L))
return;
cbEditor* ed = event.GetEditor();
if (!ed)
return;
int style = event.GetInt();
if (style != wxSCI_C_DEFAULT && style != wxSCI_C_OPERATOR && style != wxSCI_C_IDENTIFIER)
return;
wxPoint pt;
pt.x = event.GetX();
pt.y = event.GetY();
int pos = ed->GetControl()->PositionFromPoint(pt);
int start = ed->GetControl()->WordStartPosition(pos, true);
int end = ed->GetControl()->WordEndPosition(pos, true);
wxString token;
if (start >= ed->GetControl()->GetSelectionStart() &&
end <= ed->GetControl()->GetSelectionEnd())
{
token = ed->GetControl()->GetSelectedText();
}
else
token = ed->GetControl()->GetTextRange(start,end);
if (!token.IsEmpty())
{
Manager::Get()->GetMessageManager()->AppendLog(m_PageIndex, _("Value of %s: "), token.c_str());
pt = ed->GetControl()->PointFromPosition(start);
pt = ed->GetControl()->ClientToScreen(pt);
m_EvalRect.x = pt.x;
m_EvalRect.y = pt.y;
pt = ed->GetControl()->PointFromPosition(end);
pt = ed->GetControl()->ClientToScreen(pt);
m_EvalRect.width = pt.x - m_EvalRect.x;
m_EvalRect.height = (pt.y + ed->GetControl()->GetCharHeight()) - m_EvalRect.y;
m_LastEval = token;
wxString tip;
tip = GetInfoFor(_T("p ") + m_LastEval);
int pos = tip.First(_T('\n')); // tip is e.g. "$1 = \n<value>"
if (pos != -1)
tip.Remove(0, pos + 1); // discard first line
Manager::Get()->GetMessageManager()->AppendLog(m_PageIndex, _T("%s\n"), tip.c_str());
tip = token + _T(" = ") + tip;
if (m_EvalWin)
m_EvalWin->Destroy();
m_EvalWin = new wxTipWindow(Manager::Get()->GetAppWindow(), tip, 640, &m_EvalWin, &m_EvalRect);
}
}
void DebuggerGDB::OnIdle(wxIdleEvent& event)
{
if (m_pProcess && ((PipedProcess*)m_pProcess)->HasInput())
event.RequestMore();
else
event.Skip();
}
void DebuggerGDB::OnTimer(wxTimerEvent& event)
{
wxWakeUpIdle();
}
void DebuggerGDB::OnWatchesChanged(wxCommandEvent& event)
{
DoWatches();
}
void DebuggerGDB::OnAddWatch(wxCommandEvent& event)
{
m_pTree->AddWatch(GetEditorWordAtCaret());
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -