1
0
mirror of https://github.com/fadden/6502bench.git synced 2025-07-16 03:24:08 +00:00

Add "find all" feature

This uses the same (very weak) string search as the current Find
feature, but does it over the entire file.  Matches are added to a
table of results and displayed in the same dialog used by the
References panel "copy out" feature.

The reference table now jumps to a Location rather than just the
closest offset, so that we can jump to the middle of a multi-line
comment.
This commit is contained in:
Andy McFadden
2025-06-27 14:27:40 -07:00
parent afd55d36e3
commit b6e6363234
11 changed files with 144 additions and 22 deletions

View File

@@ -568,6 +568,8 @@ namespace SourceGen {
return line.Parts;
}
public const char SEARCH_SEP = '\u203b'; // REFERENCE MARK
/// <summary>
/// Returns a string with the concatenation of the searchable portions of the line.
/// Different sections are separated with an unlikely unicode character. The goal
@@ -579,17 +581,15 @@ namespace SourceGen {
public string GetSearchString(int index) {
Line line = mLineList[index];
if (line.SearchString == null) {
const char sep = '\u203b'; // REFERENCE MARK
FormattedParts parts = GetFormattedParts(index);
StringBuilder sb = new StringBuilder();
// Some parts may be null, e.g. for long comments. Append() can deal.
sb.Append(parts.Label);
sb.Append(sep);
sb.Append(SEARCH_SEP);
sb.Append(parts.Opcode);
sb.Append(sep);
sb.Append(SEARCH_SEP);
sb.Append(parts.Operand);
sb.Append(sep);
sb.Append(SEARCH_SEP);
sb.Append(parts.Comment);
line.SearchString = sb.ToString();
}

View File

@@ -3220,7 +3220,7 @@ namespace SourceGen {
}
public void Find() {
FindBox dlg = new FindBox(mMainWin, mFindString);
FindBox dlg = new FindBox(mMainWin, mFindString, false);
if (dlg.ShowDialog() == true) {
mFindString = dlg.TextToFind;
mFindStartIndex = -1;
@@ -3304,6 +3304,58 @@ namespace SourceGen {
//mMainWin.CodeListView_Focus();
}
// Finds all matches in the file. Does not alter the the current position.
public void FindAll() {
FindBox dlg = new FindBox(mMainWin, mFindString, true);
if (dlg.ShowDialog() == false) {
return;
}
mFindString = dlg.TextToFind;
string SEARCH_SEP_STR = "" + LineListGen.SEARCH_SEP;
List<ReferenceTable.ReferenceTableItem> items =
new List<ReferenceTable.ReferenceTableItem>();
for (int index = 0; index < CodeLineList.Count; index++) {
string searchStr = CodeLineList.GetSearchString(index);
int matchPos = searchStr.IndexOf(mFindString,
StringComparison.InvariantCultureIgnoreCase);
if (matchPos >= 0) {
int offset = CodeLineList[index].FileOffset;
string offsetStr, addrStr, msgStr;
if (offset >= 0) {
offsetStr = mFormatter.FormatOffset24(offset);
Anattrib attr = mProject.GetAnattrib(offset);
if (attr.Address >= 0) {
addrStr = mFormatter.FormatAddress(attr.Address, attr.Address > 0xffff);
} else {
addrStr = string.Empty;
}
} else {
offsetStr = "-";
addrStr = string.Empty;
}
msgStr = searchStr.Replace(SEARCH_SEP_STR, " ");
// Create a reference table entry.
int lineDelta = index - CodeLineList.FindLineIndexByOffset(offset);
bool isNote = (CodeLineList[index].LineType == LineListGen.Line.Type.Note);
NavStack.Location loc = new NavStack.Location(offset, lineDelta,
isNote ? NavStack.GoToMode.JumpToNote : NavStack.GoToMode.JumpToAdjIndex);
items.Add(new ReferenceTable.ReferenceTableItem(loc,
offsetStr, addrStr, msgStr));
}
}
if (items.Count > 0) {
ShowReferenceTable(items);
} else {
MessageBox.Show(Res.Strings.FIND_ALL_NO_MATCH,
Res.Strings.FIND_ALL_CAPTION, MessageBoxButton.OK,
MessageBoxImage.Information);
}
}
public bool CanFormatAsWord() {
EntityCounts counts = SelectionAnalysis.mEntityCounts;
// This is insufficient -- we need to know how many bytes are selected, and

View File

@@ -100,6 +100,8 @@ limitations under the License.
<system:String x:Key="str_FileFilterSym65">SourceGen symbols (*.sym65)|*.sym65</system:String>
<system:String x:Key="str_FileFilterText">Text files (*.txt)|*.txt</system:String>
<system:String x:Key="str_FileInfoFmt">File is {0:N1} KB of raw data.</system:String>
<system:String x:Key="str_FindAllCaption">Find All...</system:String>
<system:String x:Key="str_FindAllNoMatch">No matches found.</system:String>
<system:String x:Key="str_FindReachedStart">Find reached the starting point of the search.</system:String>
<system:String x:Key="str_FindReachedStartCaption">Find...</system:String>
<system:String x:Key="str_FontDescriptorFmt">{0}-point {1}</system:String>

View File

@@ -181,6 +181,10 @@ namespace SourceGen.Res {
(string)Application.Current.FindResource("str_FileFilterText");
public static string FILE_INFO_FMT =
(string)Application.Current.FindResource("str_FileInfoFmt");
public static string FIND_ALL_CAPTION =
(string)Application.Current.FindResource("str_FindAllCaption");
public static string FIND_ALL_NO_MATCH =
(string)Application.Current.FindResource("str_FindAllNoMatch");
public static string FIND_REACHED_START =
(string)Application.Current.FindResource("str_FindReachedStart");
public static string FIND_REACHED_START_CAPTION =

View File

@@ -19,6 +19,7 @@ limitations under the License.
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:system="clr-namespace:System;assembly=mscorlib"
xmlns:local="clr-namespace:SourceGen.WpfGui"
mc:Ignorable="d"
Title="Find..."
@@ -26,13 +27,19 @@ limitations under the License.
ShowInTaskbar="False" WindowStartupLocation="CenterOwner"
ContentRendered="Window_ContentRendered"
PreviewKeyDown="Window_KeyEventHandler">
<Window.Resources>
<system:String x:Key="str_FindTitle">Find...</system:String>
<system:String x:Key="str_FindAllTitle">Find All...</system:String>
</Window.Resources>
<StackPanel Margin="8">
<StackPanel Orientation="Horizontal">
<TextBox Name="findTextBox" Width="200" Text="{Binding TextToFind}"/>
<Button Content="Find" Width="70" IsDefault="True" Margin="16,0,0,0"
Click="OkButton_Click"/>
</StackPanel>
<StackPanel Orientation="Horizontal" Margin="0,8,0,0">
<StackPanel Orientation="Horizontal" Margin="0,8,0,0" Visibility="{Binding DirectionVis}">
<RadioButton Content="_Forward" IsChecked="{Binding IsForward}"/>
<RadioButton Content="_Backward" Margin="16,0,0,0" IsChecked="{Binding IsBackward}"/>
</StackPanel>

View File

@@ -48,6 +48,8 @@ namespace SourceGen.WpfGui {
set { mIsBackward = value; OnPropertyChanged(); }
}
public Visibility DirectionVis { get; set; }
// INotifyPropertyChanged implementation
public event PropertyChangedEventHandler PropertyChanged;
private void OnPropertyChanged([CallerMemberName] string propertyName = "") {
@@ -58,13 +60,20 @@ namespace SourceGen.WpfGui {
/// <summary>
/// Constructor. Pass in the last string searched for, to use as the initial value.
/// </summary>
public FindBox(Window owner, string findStr) {
public FindBox(Window owner, string findStr, bool isFindAll) {
InitializeComponent();
Owner = owner;
DataContext = this;
Debug.Assert(findStr != null);
TextToFind = findStr;
if (isFindAll) {
DirectionVis = Visibility.Collapsed;
Title = (string)FindResource("str_FindAllTitle");
} else {
DirectionVis = Visibility.Visible;
Title = (string)FindResource("str_FindTitle");
}
if (sLastSearchBackward) {
IsBackward = true;

View File

@@ -125,6 +125,11 @@ limitations under the License.
<KeyGesture>Ctrl+Shift+E</KeyGesture>
</RoutedUICommand.InputGestures>
</RoutedUICommand>
<RoutedUICommand x:Key="FindAllCmd" Text="Find All">
<RoutedUICommand.InputGestures>
<KeyGesture>Ctrl+Shift+F</KeyGesture>
</RoutedUICommand.InputGestures>
</RoutedUICommand>
<RoutedUICommand x:Key="FindNextCmd" Text="Find Next">
<RoutedUICommand.InputGestures>
<KeyGesture>F3</KeyGesture>
@@ -284,6 +289,8 @@ limitations under the License.
CanExecute="IsProjectOpen" Executed="ExportCmd_Executed"/>
<CommandBinding Command="Find"
CanExecute="IsProjectOpen" Executed="FindCmd_Executed"/>
<CommandBinding Command="{StaticResource FindAllCmd}"
CanExecute="IsProjectOpen" Executed="FindAllCmd_Executed"/>
<CommandBinding Command="{StaticResource FindNextCmd}"
CanExecute="IsProjectOpen" Executed="FindNextCmd_Executed"/>
<CommandBinding Command="{StaticResource FindPreviousCmd}"
@@ -434,6 +441,7 @@ limitations under the License.
<MenuItem Command="Find"/>
<MenuItem Command="{StaticResource FindNextCmd}"/>
<MenuItem Command="{StaticResource FindPreviousCmd}"/>
<MenuItem Command="{StaticResource FindAllCmd}"/>
<Separator/>
<MenuItem Command="{StaticResource ViewAddressMapCmd}"/>
</MenuItem>

View File

@@ -1328,6 +1328,10 @@ namespace SourceGen.WpfGui {
mMainCtrl.Find();
}
private void FindAllCmd_Executed(object sender, ExecutedRoutedEventArgs e) {
mMainCtrl.FindAll();
}
private void FindNextCmd_Executed(object sender, ExecutedRoutedEventArgs e) {
mMainCtrl.FindNext();
}
@@ -1758,7 +1762,9 @@ namespace SourceGen.WpfGui {
List<ReferenceTable.ReferenceTableItem> newItems =
new List<ReferenceTable.ReferenceTableItem>();
foreach (ReferencesListItem item in ReferencesList) {
newItems.Add(new ReferenceTable.ReferenceTableItem(item.OffsetValue,
NavStack.Location loc = new NavStack.Location(item.OffsetValue, 0,
NavStack.GoToMode.JumpToCodeData);
newItems.Add(new ReferenceTable.ReferenceTableItem(loc,
item.Offset, item.Addr, item.Type));
}
mMainCtrl.ShowReferenceTable(newItems);

View File

@@ -19,6 +19,7 @@ limitations under the License.
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:system="clr-namespace:System;assembly=mscorlib"
xmlns:local="clr-namespace:SourceGen.WpfGui"
mc:Ignorable="d"
Title="Reference List"
@@ -26,6 +27,11 @@ limitations under the License.
ShowInTaskbar="True"
PreviewKeyDown="Window_KeyEventHandler" Closing="Window_Closing">
<Window.Resources>
<system:String x:Key="str_EntryCountSingleFmt">{0} entry</system:String>
<system:String x:Key="str_EntryCountPluralFmt">{0} entries</system:String>
</Window.Resources>
<Grid Margin="8">
<Grid.RowDefinitions>
<RowDefinition Height="*"/>
@@ -45,13 +51,16 @@ limitations under the License.
<DataGrid.Columns>
<DataGridTextColumn Header="Offset" Width="53" Binding="{Binding Offset}"/>
<DataGridTextColumn Header="Addr" Width="53" Binding="{Binding Addr}"/>
<DataGridTextColumn Header="Type" Width="119" Binding="{Binding Type}"/>
<DataGridTextColumn Header="Text" Width="*" Binding="{Binding Text}"/>
</DataGrid.Columns>
</DataGrid>
<StackPanel Grid.Row="1" Margin="0,5,0,0" Orientation="Horizontal">
<!-- Bind the checkbox directly to the window's Topmost property. -->
<CheckBox Content="Always on top" IsChecked="{Binding Path=Topmost}"/>
<StackPanel Orientation="Horizontal" Margin="20,0,0,0">
<TextBlock Text="{Binding CountText, FallbackValue=MM entries}"/>
</StackPanel>
</StackPanel>
</Grid>
</Window>

View File

@@ -16,7 +16,9 @@
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Diagnostics;
using System.Runtime.CompilerServices;
using System.Windows;
using System.Windows.Input;
@@ -27,23 +29,30 @@ namespace SourceGen.WpfGui {
/// Side window with references to the project. This could be copied out of the References
/// panel or generated from a "find all" command.
/// </summary>
public partial class ReferenceTable : Window {
public partial class ReferenceTable : Window, INotifyPropertyChanged {
// INotifyPropertyChanged implementation
public event PropertyChangedEventHandler PropertyChanged;
private void OnPropertyChanged([CallerMemberName] string propertyName = "") {
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
public class ReferenceTableItem {
public int OffsetValue { get; private set; }
public NavStack.Location Location { get; private set; }
public string Offset { get; private set; }
public string Addr { get; private set; }
public string Type { get; private set; }
public string Text { get; private set; }
public ReferenceTableItem(int offsetValue, string offset, string addr, string type) {
OffsetValue = offsetValue;
public ReferenceTableItem(NavStack.Location location,
string offset, string addr, string text) {
Location = location;
Offset = offset;
Addr = addr;
Type = type;
Text = text;
}
public override string ToString() {
return "[ReferenceTableItem: off=" + Offset + " addr=" + Addr + " type=" +
Type + "]";
return "[ReferenceTableItem: loc=" + Location + " addr=" + Addr + " text=" +
Text + "]";
}
}
@@ -53,8 +62,15 @@ namespace SourceGen.WpfGui {
public ObservableCollection<ReferenceTableItem> ReferencesList { get; private set; } =
new ObservableCollection<ReferenceTableItem>();
public string CountText {
get { return mCountText; }
set { mCountText = value; OnPropertyChanged(); }
}
private string mCountText;
private MainController mMainCtrl;
public ReferenceTable(Window owner, MainController mainCtrl) {
InitializeComponent();
Owner = owner;
@@ -64,6 +80,13 @@ namespace SourceGen.WpfGui {
Topmost = sAlwaysOnTop;
}
private void SetCount(int count) {
string fmt = (count == 1) ?
(string)FindResource("str_EntryCountSingleFmt") :
(string)FindResource("str_EntryCountPluralFmt");
CountText = string.Format(fmt, count);
}
/// <summary>
/// Replaces the existing list of items with a new list.
/// </summary>
@@ -72,6 +95,7 @@ namespace SourceGen.WpfGui {
foreach (ReferenceTableItem item in items) {
ReferencesList.Add(item);
}
SetCount(ReferencesList.Count);
}
// Catch ESC key.
@@ -83,10 +107,11 @@ namespace SourceGen.WpfGui {
}
// Remember the "always on top" setting.
private void Window_Closing(object sender, System.ComponentModel.CancelEventArgs e) {
private void Window_Closing(object sender, CancelEventArgs e) {
sAlwaysOnTop = Topmost;
}
// Move the main window code list to the selected item.
private void ReferencesList_MouseDoubleClick(object sender, MouseButtonEventArgs e) {
if (!tableDataGrid.GetClickRowColItem(e, out int unusedRow, out int unusedCol,
out object item)) {
@@ -96,8 +121,7 @@ namespace SourceGen.WpfGui {
ReferenceTableItem rli = (ReferenceTableItem)item;
// Jump to the offset, then shift the focus back to the code list.
mMainCtrl.GoToLocation(new NavStack.Location(rli.OffsetValue, 0,
NavStack.GoToMode.JumpToCodeData), true);
mMainCtrl.GoToLocation(rli.Location, true);
}
}
}

View File

@@ -460,7 +460,8 @@ Use <samp>Navigate &gt; Find Next</samp> to find the next match, and
<samp>Navigate &gt; Find Previous</samp> to find the previous match.
Note "next" is always downward, and "previous" is always upward,
regardless of the direction of the initial search chosen in the
Find dialog.</p>
Find dialog. The <samp>Find All</samp> feature finds all matches and
reports them in a separate window.</p>
<p>Use <samp>Navigate &gt; Go To</samp> to jump to an offset, address,
or label. Remember that offsets and addresses are always hexadecimal,