From 2008558870c591ce0f5d408addd0f741b233395c Mon Sep 17 00:00:00 2001
From: Andy McFadden
Date: Thu, 14 Oct 2021 15:10:32 -0700
Subject: [PATCH] Add "quick set" menu to delimiter settings tab
Added a pop-up menu with three options: default (curly quotes),
straight, and Merlin. Removed the "reset to defaults" buttons.
Also, slightly rearranged the Display Format tab so that the quick
set pop-up is on the left, near the items it affects. Moved the
"use comma-separated format for bulk data" checkbox over as well,
since it's part of the set.
---
Asm65/Formatter.cs | 67 ++-
SourceGen/Res/Strings.xaml | 4 -
SourceGen/Res/Strings.xaml.cs | 8 -
SourceGen/WpfGui/EditAppSettings.xaml | 555 ++++++++++++-----------
SourceGen/WpfGui/EditAppSettings.xaml.cs | 133 +++++-
docs/sgmanual/settings.html | 25 +-
6 files changed, 482 insertions(+), 310 deletions(-)
diff --git a/Asm65/Formatter.cs b/Asm65/Formatter.cs
index 1160b92..984174b 100644
--- a/Asm65/Formatter.cs
+++ b/Asm65/Formatter.cs
@@ -164,15 +164,16 @@ namespace Asm65 {
#region Text Delimiters
///
- /// Container for character and string delimiter pieces. Instances are immutable.
+ /// Container for delimiter pieces for characters or strings. Instances are immutable.
///
///
- /// For single-character operands, a simple concatenation of the four fields, with the
- /// character in the middle, is performed.
+ /// For single-character operands, the generated format string will be a simple
+ /// concatenation of the four fields, with the character in the middle.
///
/// For strings, the prefix is included at the start of the first line, but not included
- /// on subsequent lines. This is primarily intended for the on-screen display, not
- /// assembly source generation. The suffix is not used at all.
+ /// on subsequent lines in a multi-line operand. This is primarily intended for the
+ /// on-screen display, not assembly source generation (which doesn't generally make use
+ /// of a string prefix). The suffix is not used at all.
///
public class DelimiterDef {
public string Prefix { get; private set; }
@@ -203,10 +204,37 @@ namespace Asm65 {
public override string ToString() {
return Prefix + OpenDelim + '#' + CloseDelim + Suffix;
}
+
+ public static bool operator ==(DelimiterDef a, DelimiterDef b) {
+ if (ReferenceEquals(a, b)) {
+ return true; // same object, or both null
+ }
+ if (ReferenceEquals(a, null) || ReferenceEquals(b, null)) {
+ return false; // one is null
+ }
+ // All fields must be equal. Ignore FormatStr, which is generated from the
+ // other fields.
+ return a.Prefix == b.Prefix && a.OpenDelim == b.OpenDelim &&
+ a.CloseDelim == b.CloseDelim && a.Suffix == b.Suffix;
+ }
+ public static bool operator !=(DelimiterDef a, DelimiterDef b) {
+ return !(a == b);
+ }
+ public override bool Equals(object obj) {
+ return obj is DelimiterDef && this == (DelimiterDef)obj;
+ }
+ public override int GetHashCode() {
+ return Prefix.GetHashCode() ^ OpenDelim.GetHashCode() ^ CloseDelim.GetHashCode() ^
+ Suffix.GetHashCode();
+ }
}
public static readonly DelimiterDef SINGLE_QUOTE_DELIM = new DelimiterDef('\'');
public static readonly DelimiterDef DOUBLE_QUOTE_DELIM = new DelimiterDef('"');
+ ///
+ /// Set of DelimiterDef objects, indexed by character encoding. The objects may be
+ /// for character or string encoding.
+ ///
public class DelimiterSet {
private Dictionary mDelimiters =
new Dictionary();
@@ -321,6 +349,35 @@ namespace Asm65 {
offset = commaIndex + 1 + len;
return resultStr;
}
+
+ public static bool operator ==(DelimiterSet a, DelimiterSet b) {
+ if (ReferenceEquals(a, b)) {
+ return true; // same object, or both null
+ }
+ if (ReferenceEquals(a, null) || ReferenceEquals(b, null)) {
+ return false; // one is null
+ }
+ // Compare set contents.
+ if (a.mDelimiters.Count != b.mDelimiters.Count) {
+ return false;
+ }
+ foreach (KeyValuePair kvp in a.mDelimiters) {
+ if (kvp.Value != b.Get(kvp.Key)) {
+ return false;
+ }
+ }
+ return true;
+ }
+ public static bool operator !=(DelimiterSet a, DelimiterSet b) {
+ return !(a == b);
+ }
+ public override bool Equals(object obj) {
+ return obj is DelimiterSet && this == (DelimiterSet)obj;
+ }
+ public override int GetHashCode() {
+ return mDelimiters.GetHashCode();
+ }
+
}
#endregion Text Delimiters
diff --git a/SourceGen/Res/Strings.xaml b/SourceGen/Res/Strings.xaml
index bae056e..1b92d8a 100644
--- a/SourceGen/Res/Strings.xaml
+++ b/SourceGen/Res/Strings.xaml
@@ -40,10 +40,6 @@ limitations under the License.
{0}K6502bench SourceGen v{0}
- ‘#’
- “#”
- pet:“#”
- scr:“#”addrconststkrl
diff --git a/SourceGen/Res/Strings.xaml.cs b/SourceGen/Res/Strings.xaml.cs
index d0f9579..878f2c2 100644
--- a/SourceGen/Res/Strings.xaml.cs
+++ b/SourceGen/Res/Strings.xaml.cs
@@ -55,14 +55,6 @@ namespace SourceGen.Res {
(string)Application.Current.FindResource("str_DataBankK");
public static string DEFAULT_HEADER_COMMENT_FMT =
(string)Application.Current.FindResource("str_DefaultHeaderCommentFmt");
- public static string DEFAULT_ASCII_DELIM_PAT =
- (string)Application.Current.FindResource("str_DefaultAsciiDelimPat");
- public static string DEFAULT_HIGH_ASCII_DELIM_PAT =
- (string)Application.Current.FindResource("str_DefaultHighAsciiDelimPat");
- public static string DEFAULT_C64_PETSCII_DELIM_PAT =
- (string)Application.Current.FindResource("str_DefaultC64PetsciiDelimPat");
- public static string DEFAULT_C64_SCREEN_CODE_DELIM_PAT =
- (string)Application.Current.FindResource("str_DefaultC64ScreenCodeDelimPat");
public static string CLIPFORMAT_ALL_COLUMNS =
(string)Application.Current.FindResource("str_ClipformatAllColumns");
public static string CLIPFORMAT_ASSEMBLER_SOURCE =
diff --git a/SourceGen/WpfGui/EditAppSettings.xaml b/SourceGen/WpfGui/EditAppSettings.xaml
index 5a580a1..30398de 100644
--- a/SourceGen/WpfGui/EditAppSettings.xaml
+++ b/SourceGen/WpfGui/EditAppSettings.xaml
@@ -28,11 +28,13 @@ limitations under the License.
Loaded="Window_Loaded">
+ Custom
+ DefaultCommoncc65Merlin
- Custom
- Default
+ Straight
+ Merlin
@@ -143,282 +145,286 @@ limitations under the License.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
-
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
-
-
-
+
+
+
-
-
-
-
-
+
+
+
+
+
-
-
-
-
-
+
+
+
+
+
-
-
-
-
-
+
+
+
+
+
-
-
-
-
-
+
+
+
+
+
-
+
+
+
+
+
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
@@ -510,10 +516,13 @@ limitations under the License.
FontFamily="{StaticResource GeneralMonoFont}"/>
+
+
-
@@ -526,9 +535,6 @@ limitations under the License.
-
@@ -728,9 +734,8 @@ limitations under the License.
-
+
diff --git a/SourceGen/WpfGui/EditAppSettings.xaml.cs b/SourceGen/WpfGui/EditAppSettings.xaml.cs
index 3d7491b..659ebc6 100644
--- a/SourceGen/WpfGui/EditAppSettings.xaml.cs
+++ b/SourceGen/WpfGui/EditAppSettings.xaml.cs
@@ -139,8 +139,9 @@ namespace SourceGen.WpfGui {
}
// Can't set the selected item yet.
- Construct_PseudoOp();
+ Construct_TextDelimiters();
Construct_DisplayFormat();
+ Construct_PseudoOp();
}
private void Window_Loaded(object sender, RoutedEventArgs e) {
@@ -436,6 +437,77 @@ namespace SourceGen.WpfGui {
#region Text Delimiters
+ public class TextDelimPreset {
+ public const int ID_CUSTOM = -2;
+ public const int ID_DEFAULT = -1;
+ public int Ident { get; private set; } // ID_ value, or zero
+ public string Name { get; private set; }
+ public Formatter.DelimiterSet CharDelims { get; private set; }
+ public Formatter.DelimiterSet StringDelims { get; private set; }
+
+ public TextDelimPreset(int id, string name, Formatter.DelimiterSet charDelims,
+ Formatter.DelimiterSet stringDelims) {
+ Ident = id;
+ Name = name;
+ CharDelims = charDelims;
+ StringDelims = stringDelims;
+ }
+ }
+ public TextDelimPreset[] DelimPresets { get; private set; }
+
+ private void ConstructTextDelimPresets() {
+ // "custom" must be in slot 0
+ DelimPresets = new TextDelimPreset[4];
+ DelimPresets[0] = new TextDelimPreset(TextDelimPreset.ID_CUSTOM,
+ (string)FindResource("str_PresetCustom"), null, null);
+ DelimPresets[1] = new TextDelimPreset(TextDelimPreset.ID_DEFAULT,
+ (string)FindResource("str_PresetDefault"),
+ Formatter.DelimiterSet.GetDefaultCharDelimiters(),
+ Formatter.DelimiterSet.GetDefaultStringDelimiters());
+
+ Formatter.DelimiterSet chrDel = new Formatter.DelimiterSet();
+ chrDel.Set(CharEncoding.Encoding.Ascii,
+ new Formatter.DelimiterDef(string.Empty, '\'', '\'', string.Empty));
+ chrDel.Set(CharEncoding.Encoding.HighAscii,
+ new Formatter.DelimiterDef(string.Empty, '\'', '\'', " | $80"));
+ chrDel.Set(CharEncoding.Encoding.C64Petscii,
+ new Formatter.DelimiterDef("pet:", '\'', '\'', string.Empty));
+ chrDel.Set(CharEncoding.Encoding.C64ScreenCode,
+ new Formatter.DelimiterDef("scr:", '\'', '\'', string.Empty));
+ Formatter.DelimiterSet strDel = new Formatter.DelimiterSet();
+ strDel.Set(CharEncoding.Encoding.Ascii,
+ new Formatter.DelimiterDef(string.Empty, '\"', '\"', string.Empty));
+ strDel.Set(CharEncoding.Encoding.HighAscii,
+ new Formatter.DelimiterDef("\u2191", '\"', '\"', string.Empty));
+ strDel.Set(CharEncoding.Encoding.C64Petscii,
+ new Formatter.DelimiterDef("pet:", '\"', '\"', string.Empty));
+ strDel.Set(CharEncoding.Encoding.C64ScreenCode,
+ new Formatter.DelimiterDef("scr:", '\"', '\"', string.Empty));
+ DelimPresets[2] = new TextDelimPreset(0,
+ (string)FindResource("str_DelimStraight"), chrDel, strDel);
+
+ chrDel = new Formatter.DelimiterSet();
+ chrDel.Set(CharEncoding.Encoding.Ascii,
+ new Formatter.DelimiterDef(string.Empty, '\u2018', '\u2019', string.Empty));
+ chrDel.Set(CharEncoding.Encoding.HighAscii,
+ new Formatter.DelimiterDef(string.Empty, '\u201c', '\u201d', string.Empty));
+ chrDel.Set(CharEncoding.Encoding.C64Petscii,
+ new Formatter.DelimiterDef("pet:", '\u2018', '\u2019', string.Empty));
+ chrDel.Set(CharEncoding.Encoding.C64ScreenCode,
+ new Formatter.DelimiterDef("scr:", '\u2018', '\u2019', string.Empty));
+ strDel = new Formatter.DelimiterSet();
+ strDel.Set(CharEncoding.Encoding.Ascii,
+ new Formatter.DelimiterDef(string.Empty, '\u2018', '\u2019', string.Empty));
+ strDel.Set(CharEncoding.Encoding.HighAscii,
+ new Formatter.DelimiterDef(string.Empty, '\u201c', '\u201d', string.Empty));
+ strDel.Set(CharEncoding.Encoding.C64Petscii,
+ new Formatter.DelimiterDef("pet:", '\u201c', '\u201d', string.Empty));
+ strDel.Set(CharEncoding.Encoding.C64ScreenCode,
+ new Formatter.DelimiterDef("scr:", '\u201c', '\u201d', string.Empty));
+ DelimPresets[3] = new TextDelimPreset(0,
+ (string)FindResource("str_DelimMerlin"), chrDel, strDel);
+ }
+
private class DelimiterTextBoxes {
public CharEncoding.Encoding mEncoding;
public TextBox mPrefix;
@@ -455,8 +527,8 @@ namespace SourceGen.WpfGui {
private DelimiterTextBoxes[] mCharDtb;
private DelimiterTextBoxes[] mStringDtb;
- private void Loaded_TextDelimiters() {
- // Map text boxes to delimiter definitions.
+ private void MapTextDelimControls() {
+ // Map TextBox controls to delimiter definitions.
mCharDtb = new DelimiterTextBoxes[] {
new DelimiterTextBoxes(CharEncoding.Encoding.Ascii,
chrdAsciiPrefix, chrdAsciiOpen, chrdAsciiClose, chrdAsciiSuffix),
@@ -511,6 +583,18 @@ namespace SourceGen.WpfGui {
}
}
+ // prevent recursion
+ private bool mSettingTextDelimCombo;
+
+ private void Construct_TextDelimiters() {
+ ConstructTextDelimPresets();
+ }
+
+ private void Loaded_TextDelimiters() {
+ MapTextDelimControls();
+ UpdateTextDelimQuickCombo();
+ }
+
// Import delimiters from a DelimiterSet to the text fields.
private void ImportDelimiters(Formatter.DelimiterSet delSet, DelimiterTextBoxes[] boxarr) {
foreach (DelimiterTextBoxes boxes in boxarr) {
@@ -540,17 +624,47 @@ namespace SourceGen.WpfGui {
// Invoked when text is changed in any delimiter text box.
private void DelimiterTextChanged(object sender, EventArgs e) {
+ UpdateTextDelimQuickCombo();
IsDirty = true;
}
- private void ChrDelDefaultsButton_Click(object sender, RoutedEventArgs e) {
- Formatter.DelimiterSet chrDel = Formatter.DelimiterSet.GetDefaultCharDelimiters();
- ImportDelimiters(chrDel, mCharDtb);
+ private void TextDelimQuickComboBox_SelectionChanged(object sender,
+ SelectionChangedEventArgs e) {
+ if (mSettingTextDelimCombo) {
+ // We shouldn't actually recurse indefinitely because we'll eventually
+ // decide that nothing is changing, but I feel better having this here.
+ return;
+ }
+
+ TextDelimPreset preset = (TextDelimPreset)textDelimQuickComboBox.SelectedItem;
+ if (preset.Ident == TextDelimPreset.ID_CUSTOM) {
+ // Not an actual preset. Leave the combo box set to "Custom".
+ return;
+ }
+
+ ImportDelimiters(preset.CharDelims, mCharDtb);
+ ImportDelimiters(preset.StringDelims, mStringDtb);
+
+ // dirty flag will be set by change watchers if one or more fields have changed
}
- private void StrDelDefaultsButton_Click(object sender, RoutedEventArgs e) {
- Formatter.DelimiterSet strDel = Formatter.DelimiterSet.GetDefaultStringDelimiters();
- ImportDelimiters(strDel, mStringDtb);
+ private void UpdateTextDelimQuickCombo() {
+ mSettingTextDelimCombo = true;
+
+ // If the current settings match one of the quick sets, update the combo box to
+ // match. Otherwise, set it to "custom".
+ textDelimQuickComboBox.SelectedIndex = 0;
+ Formatter.DelimiterSet inputChars = ExportDelimiters(mCharDtb);
+ Formatter.DelimiterSet inputStrings = ExportDelimiters(mStringDtb);
+ for (int i = 1; i < DelimPresets.Length; i++) {
+ TextDelimPreset preset = DelimPresets[i];
+ if (preset.CharDelims == inputChars && preset.StringDelims == inputStrings) {
+ textDelimQuickComboBox.SelectedIndex = i;
+ break;
+ }
+ }
+
+ mSettingTextDelimCombo = false;
}
#endregion Text Delimiters
@@ -895,6 +1009,7 @@ namespace SourceGen.WpfGui {
set {
mSettings.SetBool(AppSettings.FMT_COMMA_SEP_BULK_DATA, value);
OnPropertyChanged();
+ UpdateDisplayFormatQuickCombo();
IsDirty = true;
}
}
diff --git a/docs/sgmanual/settings.html b/docs/sgmanual/settings.html
index 91b26f3..d937b9d 100644
--- a/docs/sgmanual/settings.html
+++ b/docs/sgmanual/settings.html
@@ -96,16 +96,22 @@ don't look very good at smaller font sizes.)
If one of the delimiter characters appears in the string itself,
the character will be output as hex to avoid confusion. For this
reason, it's generally wise to use delimiter characters that aren't
-part of the ASCII character set. The "Sample Characters" box holds some
-characters that you can copy and paste (with Ctrl+C / Ctrl+V) into the
-delimiter fields.
+part of the ASCII character set, such as "curly" quotes. The
+"Sample Characters" box holds some characters that you can copy and
+paste (with Ctrl+C / Ctrl+V) into the delimiter fields.
For character operands, the prefix and suffix are added to the start
and end of the operand. For string operands, the prefix is added to the
-start of the first line, and suffixes aren't allowed.
+start of the first line, and suffixes aren't allowed.
These options change the way the code list looks on screen. They
do not affect generated code, which must use the delimiter characters
specified by the chosen assembler.
+
The "quick set" pop-up can be used to set the fields for a few
+common configurations. The default set uses curly quotes with a few
+prefixes and suffixes, while "straight" uses the ASCII apostrophe and
+double-quote characters. "Merlin" uses a format similar to what the
+Merlin assembler expects.
@@ -131,6 +137,11 @@ The setting affects label editing as well as display.
If you would like your local variables to be shown with a prefix
character, you can set it in the "local variable prefix" box.
+
The "comma-separated format for bulk data" determines whether large
+blocks of hex look like ABC123 or
+$AB,$C1,$23. The former reduces the number of lines
+required, the latter is more readable.
+
The "quick set" pop-up configures the fields on the left side of the
tab to match the conventions of the specified assembler. Select your
preferred assembler in the combo box to set the fields. The setting
@@ -143,13 +154,9 @@ hex data in the code list "bytes" column from dense (20edfd)
to spaced (20 ed fd). This also affects the format of
clipboard copies and exports.
-
The "comma-separated format for bulk data" determines whether large
-blocks of hex look like ABC123 or
-$AB,$C1,$23. The former reduces the number of lines
-required, the latter is more readable.
Long operands, such as strings and bulk data, are wrapped to a new
line after a certain number of characters. Use the pop-up to configure
-the value. Larger values can make the code easier to read, but smaller
+the value. Larger values can make the code display more compact, but smaller
values allow you to shrink the width of the operand column in the
on-screen listing, moving the comment field closer in.