1
0
mirror of https://github.com/fadden/6502bench.git synced 2024-06-08 13:29:38 +00:00
6502bench/SourceGen/Tools/WpfGui/HexDumpViewer.xaml.cs
Andy McFadden 4322a0c231 Add option to put labels on separate lines
We currently have two options for assembly code output, selected by
a checkbox in the application settings: always put labels on the same
lines as the instruction or data operand, or split the labels onto
their own line if they were wider than the label text field.

This change adds a third option, which puts labels on their own line
whenever possible.  Assemblers don't generally allow this for variable
assignment pseudo-ops like "foo = $1000", but it's accepted for most
other situations.  This is a cosmetic change to the output, and will
not affect the generated code.

The old true/false app setting will be disregarded.  "Split if too
long" will be used by default.

Added test 20280-label-placement to exercise the "split whenever
allowed" behavior.

The "export" function has a similar option that has not been updated
(for no particular reason other than laziness).

Also, simplified the app settings GetEnum / SetEnum calls, which
can infer the enumerated type from the arguments.  This should not
impact behavior.
2024-04-21 16:26:42 -07:00

223 lines
8.0 KiB
C#

/*
* Copyright 2019 faddenSoft
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
using System;
using System.ComponentModel;
using System.Diagnostics;
using System.Runtime.CompilerServices;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Input;
using Asm65;
using CharConvMode = Asm65.Formatter.FormatConfig.CharConvMode;
namespace SourceGen.Tools.WpfGui {
/// <summary>
/// Hex dump viewer.
/// </summary>
public partial class HexDumpViewer : Window, INotifyPropertyChanged {
/// <summary>
/// Maximum length of data we will display.
/// </summary>
public const int MAX_LENGTH = 1 << 24;
/// <summary>
/// ItemsSource for list.
/// </summary>
public VirtualHexDump HexDumpLines { get; private set; }
/// <summary>
/// Formatter that handles the actual string formatting.
///
/// There's currently no way to update this after the dialog is opened, which means
/// we won't track changes to hex case preference if the app settings are updated.
/// I'm okay with that.
/// </summary>
private Formatter mFormatter;
/// <summary>
/// If true, don't include non-ASCII characters in text area. (Without this we might
/// use Unicode bullets or other glyphs for unprintable text.) Bound to a CheckBox.
/// </summary>
public bool AsciiOnlyDump {
get { return mAsciiOnlyDump; }
set {
mAsciiOnlyDump = value;
OnPropertyChanged();
ReplaceFormatter();
}
}
private bool mAsciiOnlyDump;
// INotifyPropertyChanged implementation
public event PropertyChangedEventHandler PropertyChanged;
private void OnPropertyChanged([CallerMemberName] string propertyName = "") {
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
/// <summary>
/// Character conversion combo box item.
/// </summary>
public class CharConvItem {
public string Name { get; private set; }
public CharConvMode Mode { get; private set; }
public CharConvItem(string name, CharConvMode mode) {
Name = name;
Mode = mode;
}
}
public CharConvItem[] CharConvItems { get; private set; }
public HexDumpViewer(Window owner, byte[] data, Formatter formatter) {
InitializeComponent();
Owner = owner;
DataContext = this;
Debug.Assert(data.Length <= MAX_LENGTH);
HexDumpLines = new VirtualHexDump(data, formatter);
mFormatter = formatter;
CharConvItems = new CharConvItem[] {
new CharConvItem((string)FindResource("str_AsciiOnly"),
CharConvMode.Ascii),
new CharConvItem((string)FindResource("str_LowHighAscii"),
CharConvMode.LowHighAscii),
new CharConvItem((string)FindResource("str_C64Petscii"),
CharConvMode.C64Petscii),
new CharConvItem((string)FindResource("str_C64ScreenCode"),
CharConvMode.C64ScreenCode),
};
}
private void Window_Loaded(object sender, RoutedEventArgs e) {
// Restore ASCII-only setting.
AsciiOnlyDump = AppSettings.Global.GetBool(AppSettings.HEXD_ASCII_ONLY, false);
// Restore conv mode setting.
CharConvMode mode =
AppSettings.Global.GetEnum(AppSettings.HEXD_CHAR_CONV, CharConvMode.Ascii);
int index = 0;
for (int i = 0; i < CharConvItems.Length; i++) {
if (CharConvItems[i].Mode == mode) {
index = i;
break;
}
}
charConvComboBox.SelectedIndex = index;
}
// Catch ESC key.
private void Window_KeyEventHandler(object sender, KeyEventArgs e) {
if (e.Key == Key.Escape) {
Close();
}
}
/// <summary>
/// Sets the filename associated with the data. This is for display purposes only.
/// </summary>
public void SetFileName(string fileName) {
Title = fileName + (string)FindResource("str_TitleAddon");
}
private void CharConvComboBox_SelectionChanged(object sender,
SelectionChangedEventArgs e) {
ReplaceFormatter();
}
private void ReplaceFormatter() {
Formatter.FormatConfig config = mFormatter.Config;
CharConvItem item = (CharConvItem)charConvComboBox.SelectedItem;
if (item == null) {
// initializing
return;
}
config.mHexDumpCharConvMode = item.Mode;
config.mHexDumpAsciiOnly = AsciiOnlyDump;
// Keep app settings up to date.
AppSettings.Global.SetBool(AppSettings.HEXD_ASCII_ONLY, mAsciiOnlyDump);
AppSettings.Global.SetEnum(AppSettings.HEXD_CHAR_CONV, item.Mode);
mFormatter = new Formatter(config);
HexDumpLines.Reformat(mFormatter);
}
/// <summary>
/// Sets the scroll position and selection to show the specified range.
/// </summary>
/// <param name="startOffset">First offset to show.</param>
/// <param name="endOffset">Last offset to show.</param>
public void ShowOffsetRange(int startOffset, int endOffset) {
Debug.WriteLine("HexDumpViewer: show +" + startOffset.ToString("x6") + " - +" +
endOffset.ToString("x6"));
int startLine = startOffset / 16;
int endLine = endOffset / 16;
hexDumpData.SelectedItems.Clear();
for (int i = startLine; i <= endLine; i++) {
hexDumpData.SelectedItems.Add(HexDumpLines[i]);
}
// Make sure it's visible.
hexDumpData.ScrollIntoView(HexDumpLines[endLine]);
hexDumpData.ScrollIntoView(HexDumpLines[startLine]);
hexDumpData.Focus();
}
#if false // DataGrid provides this automatically
/// <summary>
/// Generates a string for every selected line, then copies the full thing to the
/// clipboard.
/// </summary>
private void CopySelectionToClipboard() {
ListView.SelectedIndexCollection indices = hexDumpListView.SelectedIndices;
if (indices.Count == 0) {
Debug.WriteLine("Nothing selected");
return;
}
// Try to make the initial allocation big enough to hold the full thing.
// Each line is currently 73 bytes, plus we throw in a CRLF. Doesn't have to
// be exact. With a 16MB max file size we're creating a ~75MB string for the
// clipboard, which .NET and Win10-64 seem to be able to handle.
StringBuilder sb = new StringBuilder(indices.Count * (73 + 2));
try {
Application.UseWaitCursor = true;
Cursor.Current = Cursors.WaitCursor;
foreach (int index in indices) {
mFormatter.FormatHexDump(mData, index * 16, sb);
sb.Append("\r\n");
}
} finally {
Application.UseWaitCursor = false;
Cursor.Current = Cursors.Arrow;
}
Clipboard.SetText(sb.ToString(), TextDataFormat.Text);
}
#endif
}
}