Debugger: Source View - Added support for "Find occurrences" feature
This commit is contained in:
parent
a78b14e1ab
commit
8da3c85de4
11 changed files with 270 additions and 82 deletions
|
@ -16,6 +16,7 @@ namespace Mesen.GUI.Debugger.Controls
|
|||
{
|
||||
public event SetNextStatementEventHandler OnSetNextStatement;
|
||||
public event ShowInSplitViewEventHandler OnShowInSplitView;
|
||||
public event ShowInSplitViewEventHandler OnGoToDestination;
|
||||
public event SwitchToSourceEventHandler OnSwitchView;
|
||||
|
||||
private int _lastClickedAddress = Int32.MaxValue;
|
||||
|
@ -212,32 +213,27 @@ namespace Mesen.GUI.Debugger.Controls
|
|||
GoToLocation();
|
||||
}
|
||||
|
||||
public void GoToDestination(GoToDestination dest)
|
||||
{
|
||||
this.OnGoToDestination?.Invoke(Viewer, dest);
|
||||
}
|
||||
|
||||
private GoToDestination GetDestination()
|
||||
{
|
||||
Ld65DbgImporter.DefinitionInfo definitionInfo = _lastClickedSymbol != null ? Viewer.SymbolProvider?.GetSymbolDefinition(_lastClickedSymbol) : null;
|
||||
Ld65DbgImporter.ReferenceInfo definitionInfo = _lastClickedSymbol != null ? Viewer.SymbolProvider?.GetSymbolDefinition(_lastClickedSymbol) : null;
|
||||
AddressTypeInfo addressInfo = _lastClickedSymbol != null ? Viewer.SymbolProvider?.GetSymbolAddressInfo(_lastClickedSymbol) : null;
|
||||
return new GoToDestination() {
|
||||
CpuAddress = _lastClickedAddress >= 0 ? _lastClickedAddress : (addressInfo != null ? InteropEmu.DebugGetRelativeAddress((UInt32)addressInfo.Address, addressInfo.Type) : -1),
|
||||
Label = _lastClickedLabel,
|
||||
AddressInfo = addressInfo,
|
||||
File = definitionInfo?.FileName,
|
||||
Line = definitionInfo?.Line ?? 0
|
||||
Line = definitionInfo?.LineNumber ?? 0
|
||||
};
|
||||
}
|
||||
|
||||
private void GoToLocation()
|
||||
{
|
||||
if(_lastClickedSymbol != null && Viewer is ctrlSourceViewer) {
|
||||
Ld65DbgImporter.DefinitionInfo def = Viewer.SymbolProvider.GetSymbolDefinition(_lastClickedSymbol);
|
||||
if(def != null) {
|
||||
((ctrlSourceViewer)Viewer).ScrollToFileLine(def.FileName, def.Line);
|
||||
return;
|
||||
}
|
||||
} else if(_lastClickedLabel != null) {
|
||||
Viewer.ScrollToAddress(new AddressTypeInfo() { Address = (int)_lastClickedLabel.Address, Type = _lastClickedLabel.AddressType });
|
||||
} else if(_lastClickedAddress >= 0) {
|
||||
Viewer.ScrollToLineNumber((int)_lastClickedAddress);
|
||||
}
|
||||
GoToDestination(GetDestination());
|
||||
}
|
||||
|
||||
private void mnuAddToWatch_Click(object sender, EventArgs e)
|
||||
|
@ -382,7 +378,16 @@ namespace Mesen.GUI.Debugger.Controls
|
|||
|
||||
private void mnuFindOccurrences_Click(object sender, EventArgs e)
|
||||
{
|
||||
Viewer.FindAllOccurrences(_lastWord, true, true);
|
||||
FindOccurrences();
|
||||
}
|
||||
|
||||
private void FindOccurrences()
|
||||
{
|
||||
if(_lastClickedSymbol != null) {
|
||||
Viewer.FindAllOccurrences(_lastClickedSymbol);
|
||||
} else {
|
||||
Viewer.FindAllOccurrences(_lastWord, true, true);
|
||||
}
|
||||
}
|
||||
|
||||
private void mnuUndoPrgChrEdit_Click(object sender, EventArgs e)
|
||||
|
@ -439,7 +444,7 @@ namespace Mesen.GUI.Debugger.Controls
|
|||
} else if(ModifierKeys.HasFlag(Keys.Control)) {
|
||||
AddWatch();
|
||||
} else if(ModifierKeys.HasFlag(Keys.Alt)) {
|
||||
Viewer.FindAllOccurrences(_lastWord, true, true);
|
||||
FindOccurrences();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -473,7 +478,6 @@ namespace Mesen.GUI.Debugger.Controls
|
|||
if(IsSourceView) {
|
||||
items[nameof(mnuMarkSelectionAs)].Visible = false;
|
||||
|
||||
items[nameof(mnuFindOccurrences)].Visible = false;
|
||||
items[nameof(mnuEditSubroutine)].Visible = false;
|
||||
items[nameof(mnuEditSelectedCode)].Visible = false;
|
||||
items[nameof(mnuNavigateForward)].Visible = false;
|
||||
|
|
|
@ -27,7 +27,9 @@ namespace Mesen.GUI.Debugger.Controls
|
|||
|
||||
UInt32? ActiveAddress { get; }
|
||||
|
||||
void FindAllOccurrences(Ld65DbgImporter.SymbolInfo symbol);
|
||||
void FindAllOccurrences(string text, bool matchWholeWord, bool matchCase);
|
||||
|
||||
void SelectActiveAddress(UInt32 activeAddress);
|
||||
void ClearActiveAddress();
|
||||
AddressTypeInfo GetAddressInfo(int lineIndex);
|
||||
|
|
|
@ -10,6 +10,7 @@ using System.Windows.Forms;
|
|||
using Mesen.GUI.Debugger.Controls;
|
||||
using Mesen.GUI.Config;
|
||||
using Mesen.GUI.Controls;
|
||||
using System.Text.RegularExpressions;
|
||||
|
||||
namespace Mesen.GUI.Debugger
|
||||
{
|
||||
|
@ -353,9 +354,51 @@ namespace Mesen.GUI.Debugger
|
|||
}
|
||||
}
|
||||
|
||||
public void FindAllOccurrences(Ld65DbgImporter.SymbolInfo symbol)
|
||||
{
|
||||
FindAllOccurrences(symbol.Name, true, true);
|
||||
}
|
||||
|
||||
public void FindAllOccurrences(string text, bool matchWholeWord, bool matchCase)
|
||||
{
|
||||
ctrlFindOccurrences.FindAllOccurrences(text, matchWholeWord, matchCase);
|
||||
List<FindAllOccurrenceResult> results = new List<FindAllOccurrenceResult>();
|
||||
|
||||
string regexPattern;
|
||||
if(matchWholeWord) {
|
||||
regexPattern = $"([^0-9a-zA-Z_#@]+|^){Regex.Escape(text)}([^0-9a-zA-Z_#@]+|$)";
|
||||
} else {
|
||||
regexPattern = Regex.Escape(text);
|
||||
}
|
||||
|
||||
Regex regex = new Regex(regexPattern, matchCase ? RegexOptions.None : RegexOptions.IgnoreCase);
|
||||
|
||||
for(int i = 0, len = ctrlCodeViewer.LineCount; i < len; i++) {
|
||||
string line = ctrlCodeViewer.GetLineContent(i);
|
||||
if(regex.IsMatch(line)) {
|
||||
if(line.StartsWith("__") && line.EndsWith("__")) {
|
||||
line = "Function: " + line.Substring(2, line.Length - 4);
|
||||
}
|
||||
if(line.StartsWith("--") && line.EndsWith("--")) {
|
||||
continue;
|
||||
}
|
||||
|
||||
int j = i;
|
||||
while(j < ctrlCodeViewer.LineCount && ctrlCodeViewer.GetLineNumber(j) < 0) {
|
||||
j++;
|
||||
}
|
||||
|
||||
int cpuAddress = ctrlCodeViewer.GetLineNumber(j);
|
||||
results.Add(new FindAllOccurrenceResult() {
|
||||
MatchedLine = line,
|
||||
Location = "$" + cpuAddress.ToString("X4"),
|
||||
Destination = new GoToDestination() {
|
||||
CpuAddress = cpuAddress
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
ctrlFindOccurrences.FindAllOccurrences(text, results);
|
||||
this.splitContainer.Panel2Collapsed = false;
|
||||
}
|
||||
|
||||
|
|
|
@ -23,15 +23,18 @@ namespace Mesen.GUI.Debugger.Controls
|
|||
|
||||
public ICodeViewer Viewer { get; set; }
|
||||
|
||||
public void FindAllOccurrences(string text, bool matchWholeWord, bool matchCase)
|
||||
public void FindAllOccurrences(string text, List<FindAllOccurrenceResult> results)
|
||||
{
|
||||
this.lstSearchResult.BeginUpdate();
|
||||
this.lstSearchResult.Items.Clear();
|
||||
foreach(Tuple<int, int, string> searchResult in Viewer.CodeViewer.FindAllOccurrences(text, matchWholeWord, matchCase)) {
|
||||
var item = this.lstSearchResult.Items.Add(searchResult.Item1.ToString("X4"));
|
||||
item.Tag = searchResult.Item2;
|
||||
item.SubItems.Add(searchResult.Item3);
|
||||
foreach(FindAllOccurrenceResult searchResult in results) {
|
||||
var item = this.lstSearchResult.Items.Add(searchResult.Location);
|
||||
item.Tag = searchResult.Destination;
|
||||
item.SubItems.Add(searchResult.MatchedLine);
|
||||
item.SubItems.Add("");
|
||||
}
|
||||
this.lstSearchResult.EndUpdate();
|
||||
|
||||
this.lblSearchResult.Text = $"Search results for: {text} ({this.lstSearchResult.Items.Count} results)";
|
||||
this.lstSearchResult.AutoResizeColumns(ColumnHeaderAutoResizeStyle.ColumnContent);
|
||||
this.lstSearchResult.Columns[0].Width += 20;
|
||||
|
@ -54,9 +57,16 @@ namespace Mesen.GUI.Debugger.Controls
|
|||
private void lstSearchResult_DoubleClick(object sender, EventArgs e)
|
||||
{
|
||||
if(lstSearchResult.SelectedItems.Count > 0) {
|
||||
int lineIndex = (int)lstSearchResult.SelectedItems[0].Tag;
|
||||
Viewer.CodeViewer.ScrollToLineIndex(lineIndex);
|
||||
GoToDestination dest = lstSearchResult.SelectedItems[0].Tag as GoToDestination;
|
||||
Viewer.CodeViewerActions.GoToDestination(dest);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public class FindAllOccurrenceResult
|
||||
{
|
||||
public string Location;
|
||||
public string MatchedLine;
|
||||
public GoToDestination Destination;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -549,9 +549,9 @@ namespace Mesen.GUI.Debugger
|
|||
}
|
||||
}
|
||||
|
||||
public List<Tuple<int, int, string>> FindAllOccurrences(string text, bool matchWholeWord, bool matchCase)
|
||||
public string GetLineContent(int lineIndex)
|
||||
{
|
||||
return this.ctrlTextbox.FindAllOccurrences(text, matchWholeWord, matchCase);
|
||||
return this.ctrlTextbox.GetFullWidthString(lineIndex);
|
||||
}
|
||||
|
||||
public void NavigateForward()
|
||||
|
@ -569,8 +569,15 @@ namespace Mesen.GUI.Debugger
|
|||
rangeStart = -1;
|
||||
rangeEnd = -1;
|
||||
int lineIndex = GetLineIndexAtPosition(yPos);
|
||||
|
||||
while(lineIndex < LineCount - 2 && string.IsNullOrWhiteSpace(GetLineNoteAtLineIndex(lineIndex))) {
|
||||
//Find the address of the next line with an address
|
||||
lineIndex++;
|
||||
}
|
||||
|
||||
if(Int32.TryParse(GetLineNoteAtLineIndex(lineIndex), NumberStyles.AllowHexSpecifier, null, out rangeStart)) {
|
||||
while(lineIndex < LineCount - 2 && string.IsNullOrWhiteSpace(GetLineNoteAtLineIndex(lineIndex + 1))) {
|
||||
//Find the next line with an address
|
||||
lineIndex++;
|
||||
}
|
||||
if(Int32.TryParse(GetLineNoteAtLineIndex(lineIndex + 1), NumberStyles.AllowHexSpecifier, null, out rangeEnd)) {
|
||||
|
|
|
@ -40,12 +40,18 @@
|
|||
this.tableLayoutPanel1 = new System.Windows.Forms.TableLayoutPanel();
|
||||
this.lblFile = new System.Windows.Forms.Label();
|
||||
this.cboFile = new System.Windows.Forms.ComboBox();
|
||||
this.splitContainer = new System.Windows.Forms.SplitContainer();
|
||||
this.ctrlCodeViewer = new Mesen.GUI.Debugger.ctrlScrollableTextbox();
|
||||
this.ctrlFindOccurrences = new Mesen.GUI.Debugger.Controls.ctrlFindOccurrences();
|
||||
this.contextMenuMargin = new System.Windows.Forms.ContextMenuStrip(this.components);
|
||||
this.mnuEditBreakpoint = new System.Windows.Forms.ToolStripMenuItem();
|
||||
this.mnuDisableBreakpoint = new System.Windows.Forms.ToolStripMenuItem();
|
||||
this.mnuRemoveBreakpoint = new System.Windows.Forms.ToolStripMenuItem();
|
||||
this.tableLayoutPanel1.SuspendLayout();
|
||||
((System.ComponentModel.ISupportInitialize)(this.splitContainer)).BeginInit();
|
||||
this.splitContainer.Panel1.SuspendLayout();
|
||||
this.splitContainer.Panel2.SuspendLayout();
|
||||
this.splitContainer.SuspendLayout();
|
||||
this.contextMenuMargin.SuspendLayout();
|
||||
this.SuspendLayout();
|
||||
//
|
||||
|
@ -56,14 +62,15 @@
|
|||
this.tableLayoutPanel1.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 100F));
|
||||
this.tableLayoutPanel1.Controls.Add(this.lblFile, 0, 0);
|
||||
this.tableLayoutPanel1.Controls.Add(this.cboFile, 1, 0);
|
||||
this.tableLayoutPanel1.Controls.Add(this.ctrlCodeViewer, 0, 1);
|
||||
this.tableLayoutPanel1.Controls.Add(this.splitContainer, 0, 1);
|
||||
this.tableLayoutPanel1.Dock = System.Windows.Forms.DockStyle.Fill;
|
||||
this.tableLayoutPanel1.Location = new System.Drawing.Point(0, 0);
|
||||
this.tableLayoutPanel1.Name = "tableLayoutPanel1";
|
||||
this.tableLayoutPanel1.RowCount = 2;
|
||||
this.tableLayoutPanel1.RowStyles.Add(new System.Windows.Forms.RowStyle());
|
||||
this.tableLayoutPanel1.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 100F));
|
||||
this.tableLayoutPanel1.Size = new System.Drawing.Size(463, 275);
|
||||
this.tableLayoutPanel1.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 20F));
|
||||
this.tableLayoutPanel1.Size = new System.Drawing.Size(484, 366);
|
||||
this.tableLayoutPanel1.TabIndex = 0;
|
||||
//
|
||||
// lblFile
|
||||
|
@ -84,18 +91,39 @@
|
|||
this.cboFile.Location = new System.Drawing.Point(35, 3);
|
||||
this.cboFile.Margin = new System.Windows.Forms.Padding(3, 3, 0, 3);
|
||||
this.cboFile.Name = "cboFile";
|
||||
this.cboFile.Size = new System.Drawing.Size(428, 21);
|
||||
this.cboFile.Size = new System.Drawing.Size(449, 21);
|
||||
this.cboFile.TabIndex = 1;
|
||||
this.cboFile.SelectedIndexChanged += new System.EventHandler(this.cboFile_SelectedIndexChanged);
|
||||
//
|
||||
// splitContainer
|
||||
//
|
||||
this.tableLayoutPanel1.SetColumnSpan(this.splitContainer, 2);
|
||||
this.splitContainer.Dock = System.Windows.Forms.DockStyle.Fill;
|
||||
this.splitContainer.FixedPanel = System.Windows.Forms.FixedPanel.Panel2;
|
||||
this.splitContainer.Location = new System.Drawing.Point(0, 27);
|
||||
this.splitContainer.Margin = new System.Windows.Forms.Padding(0);
|
||||
this.splitContainer.Name = "splitContainer";
|
||||
this.splitContainer.Orientation = System.Windows.Forms.Orientation.Horizontal;
|
||||
//
|
||||
// splitContainer.Panel1
|
||||
//
|
||||
this.splitContainer.Panel1.Controls.Add(this.ctrlCodeViewer);
|
||||
this.splitContainer.Panel1MinSize = 150;
|
||||
//
|
||||
// splitContainer.Panel2
|
||||
//
|
||||
this.splitContainer.Panel2.Controls.Add(this.ctrlFindOccurrences);
|
||||
this.splitContainer.Size = new System.Drawing.Size(484, 339);
|
||||
this.splitContainer.SplitterDistance = 159;
|
||||
this.splitContainer.TabIndex = 3;
|
||||
//
|
||||
// ctrlCodeViewer
|
||||
//
|
||||
this.ctrlCodeViewer.BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle;
|
||||
this.ctrlCodeViewer.CodeHighlightingEnabled = false;
|
||||
this.tableLayoutPanel1.SetColumnSpan(this.ctrlCodeViewer, 2);
|
||||
this.ctrlCodeViewer.Dock = System.Windows.Forms.DockStyle.Fill;
|
||||
this.ctrlCodeViewer.HideSelection = false;
|
||||
this.ctrlCodeViewer.Location = new System.Drawing.Point(0, 27);
|
||||
this.ctrlCodeViewer.Location = new System.Drawing.Point(0, 0);
|
||||
this.ctrlCodeViewer.Margin = new System.Windows.Forms.Padding(0);
|
||||
this.ctrlCodeViewer.Name = "ctrlCodeViewer";
|
||||
this.ctrlCodeViewer.ShowCompactPrgAddresses = false;
|
||||
|
@ -105,7 +133,7 @@
|
|||
this.ctrlCodeViewer.ShowScrollbars = true;
|
||||
this.ctrlCodeViewer.ShowSingleContentLineNotes = true;
|
||||
this.ctrlCodeViewer.ShowSingleLineLineNumberNotes = false;
|
||||
this.ctrlCodeViewer.Size = new System.Drawing.Size(463, 248);
|
||||
this.ctrlCodeViewer.Size = new System.Drawing.Size(484, 159);
|
||||
this.ctrlCodeViewer.TabIndex = 2;
|
||||
this.ctrlCodeViewer.MouseUp += new System.Windows.Forms.MouseEventHandler(this.ctrlCodeViewer_MouseUp);
|
||||
this.ctrlCodeViewer.MouseMove += new System.Windows.Forms.MouseEventHandler(this.ctrlCodeViewer_MouseMove);
|
||||
|
@ -113,6 +141,16 @@
|
|||
this.ctrlCodeViewer.MouseDoubleClick += new System.Windows.Forms.MouseEventHandler(this.ctrlCodeViewer_MouseDoubleClick);
|
||||
this.ctrlCodeViewer.TextZoomChanged += new System.EventHandler(this.ctrlCodeViewer_TextZoomChanged);
|
||||
//
|
||||
// ctrlFindOccurrences
|
||||
//
|
||||
this.ctrlFindOccurrences.Dock = System.Windows.Forms.DockStyle.Fill;
|
||||
this.ctrlFindOccurrences.Location = new System.Drawing.Point(0, 0);
|
||||
this.ctrlFindOccurrences.Name = "ctrlFindOccurrences";
|
||||
this.ctrlFindOccurrences.Size = new System.Drawing.Size(484, 176);
|
||||
this.ctrlFindOccurrences.TabIndex = 1;
|
||||
this.ctrlFindOccurrences.Viewer = null;
|
||||
this.ctrlFindOccurrences.OnSearchResultsClosed += new System.EventHandler(this.ctrlFindOccurrences_OnSearchResultsClosed);
|
||||
//
|
||||
// contextMenuMargin
|
||||
//
|
||||
this.contextMenuMargin.Items.AddRange(new System.Windows.Forms.ToolStripItem[] {
|
||||
|
@ -153,9 +191,13 @@
|
|||
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
|
||||
this.Controls.Add(this.tableLayoutPanel1);
|
||||
this.Name = "ctrlSourceViewer";
|
||||
this.Size = new System.Drawing.Size(463, 275);
|
||||
this.Size = new System.Drawing.Size(484, 366);
|
||||
this.tableLayoutPanel1.ResumeLayout(false);
|
||||
this.tableLayoutPanel1.PerformLayout();
|
||||
this.splitContainer.Panel1.ResumeLayout(false);
|
||||
this.splitContainer.Panel2.ResumeLayout(false);
|
||||
((System.ComponentModel.ISupportInitialize)(this.splitContainer)).EndInit();
|
||||
this.splitContainer.ResumeLayout(false);
|
||||
this.contextMenuMargin.ResumeLayout(false);
|
||||
this.ResumeLayout(false);
|
||||
|
||||
|
@ -171,5 +213,7 @@
|
|||
private System.Windows.Forms.ToolStripMenuItem mnuEditBreakpoint;
|
||||
private System.Windows.Forms.ToolStripMenuItem mnuDisableBreakpoint;
|
||||
private System.Windows.Forms.ToolStripMenuItem mnuRemoveBreakpoint;
|
||||
private System.Windows.Forms.SplitContainer splitContainer;
|
||||
private ctrlFindOccurrences ctrlFindOccurrences;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -11,6 +11,7 @@ using static Mesen.GUI.Debugger.Ld65DbgImporter;
|
|||
using System.IO;
|
||||
using Mesen.GUI.Config;
|
||||
using Mesen.GUI.Controls;
|
||||
using System.Text.RegularExpressions;
|
||||
|
||||
namespace Mesen.GUI.Debugger.Controls
|
||||
{
|
||||
|
@ -34,6 +35,9 @@ namespace Mesen.GUI.Debugger.Controls
|
|||
if(!IsDesignMode) {
|
||||
_codeViewerActions = new CodeViewerActions(this, true);
|
||||
|
||||
ctrlFindOccurrences.Viewer = this;
|
||||
splitContainer.Panel2Collapsed = true;
|
||||
|
||||
this.SymbolProvider = DebugWorkspaceManager.SymbolProvider;
|
||||
DebugWorkspaceManager.SymbolProviderChanged += UpdateSymbolProvider;
|
||||
}
|
||||
|
@ -382,10 +386,71 @@ namespace Mesen.GUI.Debugger.Controls
|
|||
{
|
||||
//Not supported
|
||||
}
|
||||
|
||||
public void FindAllOccurrences(SymbolInfo symbol)
|
||||
{
|
||||
List<FindAllOccurrenceResult> results = new List<FindAllOccurrenceResult>();
|
||||
|
||||
List<ReferenceInfo> references = _symbolProvider.GetSymbolReferences(symbol);
|
||||
ReferenceInfo definition = _symbolProvider.GetSymbolDefinition(symbol);
|
||||
if(definition != null) {
|
||||
references.Insert(0, definition);
|
||||
}
|
||||
|
||||
foreach(ReferenceInfo reference in references) {
|
||||
results.Add(new FindAllOccurrenceResult() {
|
||||
MatchedLine = reference.LineContent.Trim(),
|
||||
Location = Path.GetFileName(reference.FileName) + ":" + (reference.LineNumber + 1).ToString(),
|
||||
Destination = new GoToDestination() {
|
||||
CpuAddress = -1,
|
||||
Line = reference.LineNumber,
|
||||
File = reference.FileName,
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
ctrlFindOccurrences.FindAllOccurrences(symbol.Name, results);
|
||||
this.splitContainer.Panel2Collapsed = false;
|
||||
}
|
||||
|
||||
public void FindAllOccurrences(string text, bool matchWholeWord, bool matchCase)
|
||||
{
|
||||
//Not supported (yet?)
|
||||
List<FindAllOccurrenceResult> results = new List<FindAllOccurrenceResult>();
|
||||
|
||||
string regexPattern;
|
||||
if(matchWholeWord) {
|
||||
regexPattern = $"([^0-9a-zA-Z_#@]+|^){Regex.Escape(text)}([^0-9a-zA-Z_#@]+|$)";
|
||||
} else {
|
||||
regexPattern = Regex.Escape(text);
|
||||
}
|
||||
|
||||
Regex regex = new Regex(regexPattern, matchCase ? RegexOptions.None : RegexOptions.IgnoreCase);
|
||||
foreach(Ld65DbgImporter.FileInfo file in _symbolProvider.Files.Values) {
|
||||
if(file.Data != null && file.Data.Length > 0 && !file.Name.ToLower().EndsWith(".chr")) {
|
||||
for(int i = 0; i < file.Data.Length; i++) {
|
||||
string line = file.Data[i];
|
||||
if(regex.IsMatch(line)) {
|
||||
results.Add(new FindAllOccurrenceResult() {
|
||||
MatchedLine = line.Trim(),
|
||||
Location = Path.GetFileName(file.Name) + ":" + (i + 1).ToString(),
|
||||
Destination = new GoToDestination() {
|
||||
CpuAddress = -1,
|
||||
Line = i,
|
||||
File = file.Name,
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ctrlFindOccurrences.FindAllOccurrences(text, results);
|
||||
this.splitContainer.Panel2Collapsed = false;
|
||||
}
|
||||
|
||||
private void ctrlFindOccurrences_OnSearchResultsClosed(object sender, EventArgs e)
|
||||
{
|
||||
this.splitContainer.Panel2Collapsed = true;
|
||||
}
|
||||
|
||||
#region Scrollbar / Code highlighting
|
||||
|
|
|
@ -290,39 +290,6 @@ namespace Mesen.GUI.Debugger
|
|||
|
||||
public bool CodeHighlightingEnabled { get; set; } = true;
|
||||
|
||||
public List<Tuple<int, int, string>> FindAllOccurrences(string text, bool matchWholeWord, bool matchCase)
|
||||
{
|
||||
List<Tuple<int, int, string>> result = new List<Tuple<int, int, string>>();
|
||||
string regex;
|
||||
if(matchWholeWord) {
|
||||
regex = $"[^0-9a-zA-Z_#@]+{Regex.Escape(text)}[^0-9a-zA-Z_#@]+";
|
||||
} else {
|
||||
regex = Regex.Escape(text);
|
||||
}
|
||||
|
||||
for(int i = 0, len = _contents.Length; i < len; i++) {
|
||||
string line = _contents[i] + Addressing?[i] + (Comments != null ? ("\t" + Comments[i]) : null);
|
||||
if(Regex.IsMatch(line, regex, matchCase ? RegexOptions.None : RegexOptions.IgnoreCase)) {
|
||||
if(line.StartsWith("__") && line.EndsWith("__")) {
|
||||
line = "Block: " + line.Substring(2, line.Length - 4);
|
||||
}
|
||||
|
||||
if(line.StartsWith("--") && line.EndsWith("--")) {
|
||||
continue;
|
||||
}
|
||||
|
||||
int j = i;
|
||||
while(j < _lineNumbers.Length && _lineNumbers[j] < 0) {
|
||||
j++;
|
||||
}
|
||||
|
||||
var searchResult = new Tuple<int, int, string>(_lineNumbers[j], i, line);
|
||||
result.Add(searchResult);
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
public bool Search(string searchString, bool searchBackwards, bool isNewSearch)
|
||||
{
|
||||
if(string.IsNullOrWhiteSpace(searchString)) {
|
||||
|
@ -505,7 +472,7 @@ namespace Mesen.GUI.Debugger
|
|||
return lineIndex;
|
||||
}
|
||||
|
||||
private string GetFullWidthString(int lineIndex)
|
||||
public string GetFullWidthString(int lineIndex)
|
||||
{
|
||||
string text = _contents[lineIndex] + Addressing?[lineIndex];
|
||||
if(Comments?[lineIndex].Length > 0) {
|
||||
|
|
|
@ -107,21 +107,51 @@ namespace Mesen.GUI.Debugger
|
|||
return null;
|
||||
}
|
||||
|
||||
public DefinitionInfo GetSymbolDefinition(SymbolInfo symbol)
|
||||
private ReferenceInfo GetReferenceInfo(int referenceId)
|
||||
{
|
||||
foreach(int definition in symbol.Definitions) {
|
||||
LineInfo line = _lines[definition];
|
||||
string fileName = _files[line.FileID].Name;
|
||||
FileInfo file;
|
||||
LineInfo line;
|
||||
if(_lines.TryGetValue(referenceId, out line)) {
|
||||
string lineContent = "";
|
||||
if(_files.TryGetValue(line.FileID, out file) && file.Data.Length > line.LineNumber) {
|
||||
lineContent = file.Data[line.LineNumber];
|
||||
}
|
||||
|
||||
return new DefinitionInfo() {
|
||||
FileName = fileName,
|
||||
Line = line.LineNumber
|
||||
return new ReferenceInfo() {
|
||||
FileName = _files[line.FileID].Name,
|
||||
LineNumber = line.LineNumber,
|
||||
LineContent = lineContent
|
||||
};
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
public ReferenceInfo GetSymbolDefinition(SymbolInfo symbol)
|
||||
{
|
||||
foreach(int definition in symbol.Definitions) {
|
||||
ReferenceInfo refInfo = GetReferenceInfo(definition);
|
||||
|
||||
if(refInfo != null) {
|
||||
return refInfo;
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
public List<ReferenceInfo> GetSymbolReferences(SymbolInfo symbol)
|
||||
{
|
||||
List<ReferenceInfo> references = new List<ReferenceInfo>();
|
||||
foreach(int reference in symbol.References) {
|
||||
ReferenceInfo refInfo = GetReferenceInfo(reference);
|
||||
if(refInfo != null) {
|
||||
references.Add(refInfo);
|
||||
}
|
||||
}
|
||||
return references;
|
||||
}
|
||||
|
||||
private SpanInfo GetSymbolDefinitionSpan(SymbolInfo symbol)
|
||||
{
|
||||
foreach(int definition in symbol.Definitions) {
|
||||
|
@ -150,6 +180,12 @@ namespace Mesen.GUI.Debugger
|
|||
|
||||
private SymbolInfo GetMatchingSymbol(SymbolInfo symbol, int rangeStart, int rangeEnd)
|
||||
{
|
||||
AddressTypeInfo symbolAddress = GetSymbolAddressInfo(symbol);
|
||||
if(symbolAddress != null && symbolAddress.Type == AddressType.PrgRom && symbolAddress.Address >= rangeStart && symbolAddress.Address <= rangeEnd) {
|
||||
//If the range start/end matches the symbol's definition, return it
|
||||
return symbol;
|
||||
}
|
||||
|
||||
foreach(int reference in symbol.References) {
|
||||
LineInfo line = _lines[reference];
|
||||
|
||||
|
@ -168,7 +204,7 @@ namespace Mesen.GUI.Debugger
|
|||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
|
@ -827,10 +863,11 @@ namespace Mesen.GUI.Debugger
|
|||
public int? SymbolID;
|
||||
}
|
||||
|
||||
public class DefinitionInfo
|
||||
public class ReferenceInfo
|
||||
{
|
||||
public string FileName;
|
||||
public int Line;
|
||||
public int LineNumber;
|
||||
public string LineContent;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -210,18 +210,22 @@ namespace Mesen.GUI.Debugger
|
|||
|
||||
ctrlDebuggerCode.CodeViewerActions.OnSetNextStatement += ctrlDebuggerCode_OnSetNextStatement;
|
||||
ctrlDebuggerCode.CodeViewerActions.OnShowInSplitView += ctrlDebuggerCode_OnShowInSplitView;
|
||||
ctrlDebuggerCode.CodeViewerActions.OnGoToDestination += ctrlDebuggerCode_OnGoToDestination;
|
||||
ctrlDebuggerCode.CodeViewerActions.OnSwitchView += ctrlDebuggerCode_OnSwitchView;
|
||||
|
||||
ctrlDebuggerCodeSplit.CodeViewerActions.OnSetNextStatement += ctrlDebuggerCode_OnSetNextStatement;
|
||||
ctrlDebuggerCodeSplit.CodeViewerActions.OnShowInSplitView += ctrlDebuggerCode_OnShowInSplitView;
|
||||
ctrlDebuggerCodeSplit.CodeViewerActions.OnGoToDestination += ctrlDebuggerCode_OnGoToDestination;
|
||||
ctrlDebuggerCodeSplit.CodeViewerActions.OnSwitchView += ctrlDebuggerCode_OnSwitchView;
|
||||
|
||||
ctrlSourceViewer.CodeViewerActions.OnSetNextStatement += ctrlDebuggerCode_OnSetNextStatement;
|
||||
ctrlSourceViewer.CodeViewerActions.OnShowInSplitView += ctrlDebuggerCode_OnShowInSplitView;
|
||||
ctrlSourceViewer.CodeViewerActions.OnGoToDestination += ctrlDebuggerCode_OnGoToDestination;
|
||||
ctrlSourceViewer.CodeViewerActions.OnSwitchView += ctrlDebuggerCode_OnSwitchView;
|
||||
|
||||
ctrlSourceViewerSplit.CodeViewerActions.OnSetNextStatement += ctrlDebuggerCode_OnSetNextStatement;
|
||||
ctrlSourceViewerSplit.CodeViewerActions.OnShowInSplitView += ctrlDebuggerCode_OnShowInSplitView;
|
||||
ctrlSourceViewerSplit.CodeViewerActions.OnGoToDestination += ctrlDebuggerCode_OnGoToDestination;
|
||||
ctrlSourceViewerSplit.CodeViewerActions.OnSwitchView += ctrlDebuggerCode_OnSwitchView;
|
||||
|
||||
ctrlDebuggerCode.SetConfig(ConfigManager.Config.DebugInfo.LeftView);
|
||||
|
@ -763,7 +767,12 @@ namespace Mesen.GUI.Debugger
|
|||
int cycleCount = ((model == NesModel.NTSC ? 262 : 312) + extraScanlines) * 341;
|
||||
InteropEmu.DebugPpuStep((UInt32)cycleCount);
|
||||
}
|
||||
|
||||
|
||||
private void ctrlDebuggerCode_OnGoToDestination(ICodeViewer sender, GoToDestination dest)
|
||||
{
|
||||
GoToDestination(sender, dest);
|
||||
}
|
||||
|
||||
private void ctrlDebuggerCode_OnShowInSplitView(ICodeViewer sender, GoToDestination dest)
|
||||
{
|
||||
if(!ConfigManager.Config.DebugInfo.SplitView) {
|
||||
|
|
|
@ -181,7 +181,7 @@ namespace Mesen.GUI.Debugger
|
|||
|
||||
foreach(Ld65DbgImporter.SymbolInfo symbol in _symbolProvider.GetSymbols()) {
|
||||
if(Contains(symbol.Name, searchStrings)) {
|
||||
Ld65DbgImporter.DefinitionInfo def = _symbolProvider.GetSymbolDefinition(symbol);
|
||||
Ld65DbgImporter.ReferenceInfo def = _symbolProvider.GetSymbolDefinition(symbol);
|
||||
AddressTypeInfo addressInfo = _symbolProvider.GetSymbolAddressInfo(symbol);
|
||||
int value = 0;
|
||||
int relAddress = -1;
|
||||
|
@ -214,7 +214,7 @@ namespace Mesen.GUI.Debugger
|
|||
SearchResultType = resultType,
|
||||
Value = value,
|
||||
Filename = def?.FileName ?? "",
|
||||
FileLineNumber = def?.Line ?? 0,
|
||||
FileLineNumber = def?.LineNumber ?? 0,
|
||||
RelativeAddress = relAddress,
|
||||
CodeLabel = LabelManager.GetLabel(symbol.Name)
|
||||
});
|
||||
|
@ -330,7 +330,7 @@ namespace Mesen.GUI.Debugger
|
|||
|
||||
public delegate void GoToDestinationEventHandler(GoToDestination dest);
|
||||
|
||||
public struct GoToDestination
|
||||
public class GoToDestination
|
||||
{
|
||||
public CodeLabel Label;
|
||||
public AddressTypeInfo AddressInfo;
|
||||
|
|
Loading…
Add table
Reference in a new issue