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:
@@ -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();
|
||||
}
|
||||
|
@@ -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
|
||||
|
@@ -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>
|
||||
|
@@ -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 =
|
||||
|
@@ -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>
|
||||
|
@@ -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;
|
||||
|
@@ -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>
|
||||
|
@@ -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);
|
||||
|
@@ -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>
|
||||
|
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -460,7 +460,8 @@ Use <samp>Navigate > Find Next</samp> to find the next match, and
|
||||
<samp>Navigate > 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 > Go To</samp> to jump to an offset, address,
|
||||
or label. Remember that offsets and addresses are always hexadecimal,
|
||||
|
Reference in New Issue
Block a user