From b4213de4c087c5705859ef212ee86592395a4e2a Mon Sep 17 00:00:00 2001
From: Andy McFadden
Date: Fri, 1 Nov 2019 18:44:22 -0700
Subject: [PATCH] Add "Go to Last Change" feature
Jumps to the first offset associated with the change at the top of
the Undo stack. We generally jump to the code/data offset, not the
specific line affected. It's possible to do better (and we do, for
Notes), but probably not worthwhile.
---
SourceGen/DisasmProject.cs | 14 ++++++
SourceGen/MainController.cs | 52 +++++++++++++++++++++++
SourceGen/RuntimeData/Help/end-notes.html | 4 +-
SourceGen/RuntimeData/Help/mainwin.html | 22 +++++++---
SourceGen/UndoableChange.cs | 1 +
SourceGen/WpfGui/MainWindow.xaml | 4 ++
SourceGen/WpfGui/MainWindow.xaml.cs | 4 ++
7 files changed, 95 insertions(+), 6 deletions(-)
diff --git a/SourceGen/DisasmProject.cs b/SourceGen/DisasmProject.cs
index bb828e7..7a87a46 100644
--- a/SourceGen/DisasmProject.cs
+++ b/SourceGen/DisasmProject.cs
@@ -1830,6 +1830,20 @@ namespace SourceGen {
}
}
+ ///
+ /// Returns the change at the top of the list, i.e. the one that would be popped off
+ /// if we hit "undo".
+ ///
+ /// The change set. The caller must not modify it.
+ public ChangeSet GetTopChange() {
+ Debug.Assert(mUndoList.Count > 0);
+ Debug.Assert(mUndoTop > 0);
+ return mUndoList[mUndoTop - 1];
+ }
+
+ ///
+ /// Generate undo/redo history, for the debug window.
+ ///
public string DebugGetUndoRedoHistory() {
StringBuilder sb = new StringBuilder();
sb.Append("Bracketed change will be overwritten by next action\r\n\r\n");
diff --git a/SourceGen/MainController.cs b/SourceGen/MainController.cs
index 7137946..96df507 100644
--- a/SourceGen/MainController.cs
+++ b/SourceGen/MainController.cs
@@ -2570,6 +2570,58 @@ namespace SourceGen {
return new NavStack.Location(offset, lineDelta, isNote);
}
+ public void GotoLastChange() {
+ ChangeSet cs = mProject.GetTopChange();
+ Debug.Assert(cs.Count > 0);
+
+ // Get the offset from the first change in the set. Ignore the rest.
+ UndoableChange uc = cs[0];
+ int offset;
+ bool isNote = false;
+ if (uc.HasOffset) {
+ offset = uc.Offset;
+
+ // If we altered a Note, and didn't remove it, jump to the note instead of
+ // the nearby code/data.
+ //
+ // TODO(someday): we can do similar things for comment edits, e.g. if it's
+ // SetLongComment we can find the line on which the comment starts and
+ // pass that as a line delta.
+ if (uc.Type == UndoableChange.ChangeType.SetNote &&
+ uc.NewValue != null) {
+ isNote = true;
+ }
+ } else if (uc.Type == UndoableChange.ChangeType.SetProjectProperties) {
+ // some chance it modified the EQU statements... jump there
+ offset = 0;
+ } else if (uc.Type == UndoableChange.ChangeType.SetTypeHint) {
+ TypedRangeSet newSet = (TypedRangeSet)uc.NewValue;
+ if (newSet.Count == 0) {
+ // unexpected
+ Debug.Assert(false);
+ return;
+ }
+
+ // Get the offset of the first entry.
+ IEnumerator iter =
+ (IEnumerator)newSet.GetEnumerator();
+ iter.MoveNext();
+ TypedRangeSet.Tuple firstOffset = iter.Current;
+ offset = firstOffset.Value;
+ } else {
+ Debug.Assert(false);
+ return;
+ }
+
+ if (isNote) {
+ GoToLocation(new NavStack.Location(offset, 0, true),
+ GoToMode.JumpToNote, true);
+ } else {
+ GoToLocation(new NavStack.Location(offset, 0, false),
+ GoToMode.JumpToCodeData, true);
+ }
+ }
+
public bool CanNavigateBackward() {
return mNavStack.HasBackward;
}
diff --git a/SourceGen/RuntimeData/Help/end-notes.html b/SourceGen/RuntimeData/Help/end-notes.html
index ccb1c67..7ace0fd 100644
--- a/SourceGen/RuntimeData/Help/end-notes.html
+++ b/SourceGen/RuntimeData/Help/end-notes.html
@@ -18,7 +18,9 @@
school in the late 1980s, I read Don Lancaster's
Enhancing Your Apple II, Vol. 1 (available for download
here). This
-included a very detailed methodology for disassembling 6502 software.
+included a very detailed methodology for disassembling 6502 software
+(nicely reformatted
+here).
I wanted to give it a try, so I generated a monitor listing of an
operating system (called "RDOS") that SSI used on their games, and
printed it out on my Epson RX-80 -- tractor feed paper was helpful for
diff --git a/SourceGen/RuntimeData/Help/mainwin.html b/SourceGen/RuntimeData/Help/mainwin.html
index 07c4a57..48093fe 100644
--- a/SourceGen/RuntimeData/Help/mainwin.html
+++ b/SourceGen/RuntimeData/Help/mainwin.html
@@ -372,11 +372,23 @@ with a '+'. If you have a label that is also a valid hexadecimal
address, like "FEED", the label takes precedence. To jump to the address
write "$FEED" instead.
-When you jump around, by double-clicking on an opcode or an entry
-in one of the side windows, the currently-selected line is added to
-a navigation stack. You can use the arrows on the toolbar to navigate
-forward or backward, or Navigate > Nav Forward and
-Navigate > Nav Backward. (You can use Alt+Left/Right Arrow, or
+
When you edit something, lines throughout the listing can change. This
+is different from a source code editor, where editing a line just changes
+that line. To allow you to watch the effects changes have, the undo/redo
+commands try to keep the listing in the same position.
+If you want to go to the place where the last change (i.e. the change
+that will be undone by the next Undo operation) was made,
+Navigate > Go to Last Change will jump to the first offset
+associated with the most recent change.
+If the last change was to the project properties, it will jump to the
+first offset in the file.
+
+When you jump around, e.g. by double-clicking on an opcode or an entry
+in one of the side windows, the previously-selected line is added to
+a navigation stack. You can use Navigate > Nav Forward and
+Navigate > Nav Backward to move forward and backward through the
+stack. (The curly arrows on the left side of the toolbar may be more
+convenient. You can use Alt+Left/Right Arrow, or
Ctrl+- / Ctrl+Shift+-, as keyboard shortcuts.)
diff --git a/SourceGen/UndoableChange.cs b/SourceGen/UndoableChange.cs
index e3bc1c5..35f6e5d 100644
--- a/SourceGen/UndoableChange.cs
+++ b/SourceGen/UndoableChange.cs
@@ -206,6 +206,7 @@ namespace SourceGen {
/// Change record.
public static UndoableChange CreateTypeHintChange(TypedRangeSet undoSet,
TypedRangeSet newSet) {
+ Debug.Assert(undoSet != null && newSet != null);
if (newSet.Count == 0) {
Debug.WriteLine("Empty hint change?");
}
diff --git a/SourceGen/WpfGui/MainWindow.xaml b/SourceGen/WpfGui/MainWindow.xaml
index faf9013..c5f76e0 100644
--- a/SourceGen/WpfGui/MainWindow.xaml
+++ b/SourceGen/WpfGui/MainWindow.xaml
@@ -124,6 +124,7 @@ limitations under the License.
Ctrl+G
+
@@ -239,6 +240,8 @@ limitations under the License.
CanExecute="CanFormatAddressTable" Executed="FormatAddressTableCmd_Executed"/>
+
+
diff --git a/SourceGen/WpfGui/MainWindow.xaml.cs b/SourceGen/WpfGui/MainWindow.xaml.cs
index 0afe3c9..509d2f0 100644
--- a/SourceGen/WpfGui/MainWindow.xaml.cs
+++ b/SourceGen/WpfGui/MainWindow.xaml.cs
@@ -1211,6 +1211,10 @@ namespace SourceGen.WpfGui {
mMainCtrl.Goto();
}
+ private void GotoLastChangeCmd_Executed(object sender, ExecutedRoutedEventArgs e) {
+ mMainCtrl.GotoLastChange();
+ }
+
private void HelpCmd_Executed(object sender, ExecutedRoutedEventArgs e) {
mMainCtrl.ShowHelp();
}