From bb00a22fc5441c47d34c8aeb025fa8e0fd72f1cc Mon Sep 17 00:00:00 2001 From: Benjamin Popp Date: Sat, 9 Feb 2019 12:29:47 -0600 Subject: [PATCH] - refactor ViewPort constructor to not need to take in the data array twice - when searching for text, check if the found results are anchors - when adding a text anchor with no name, search for pointers before rejecting it --- src/HexManiac.Core/Models/IDataModel.cs | 5 ++ src/HexManiac.Core/Models/PokemonModel.cs | 42 +++++------ .../ViewModels/ChildViewPort.cs | 2 +- .../ViewModels/EditorViewModel.cs | 2 +- src/HexManiac.Core/ViewModels/ViewPort.cs | 48 +++++++++++-- src/HexManiac.Tests/ArrayRunTests.cs | 34 ++++----- src/HexManiac.Tests/AsciiRunTests.cs | 4 +- src/HexManiac.Tests/ChangeHistoryTests.cs | 12 ++-- src/HexManiac.Tests/NavigationTests.cs | 2 +- src/HexManiac.Tests/PointerModelTests.cs | 72 +++++++++---------- src/HexManiac.Tests/StringModelTests.cs | 69 +++++++++++++----- src/HexManiac.Tests/ToolTests.cs | 14 ++-- src/HexManiac.Tests/ViewPortCursorTests.cs | 2 +- src/HexManiac.Tests/ViewPortEditTests.cs | 4 +- src/HexManiac.Tests/ViewPortSaveTests.cs | 4 +- src/HexManiac.WPF/Windows/App.xaml.cs | 2 +- 16 files changed, 197 insertions(+), 121 deletions(-) diff --git a/src/HexManiac.Core/Models/IDataModel.cs b/src/HexManiac.Core/Models/IDataModel.cs index 4d8cdf99..ce6d9ebc 100644 --- a/src/HexManiac.Core/Models/IDataModel.cs +++ b/src/HexManiac.Core/Models/IDataModel.cs @@ -30,6 +30,7 @@ namespace HavenSoft.HexManiac.Core.Models { void Load(byte[] newData, StoredMetadata metadata); void ExpandData(ModelDelta changeToken, int minimumLength); + IReadOnlyList SearchForPointersToAnchor(ModelDelta changeToken, int address); void WritePointer(ModelDelta changeToken, int address, int pointerDestination); void WriteValue(ModelDelta changeToken, int address, int value); int ReadPointer(int address); @@ -86,6 +87,8 @@ namespace HavenSoft.HexManiac.Core.Models { public abstract IFormattedRun RelocateForExpansion(ModelDelta changeToken, IFormattedRun run, int minimumLength); + public abstract IReadOnlyList SearchForPointersToAnchor(ModelDelta changeToken, int address); + public int ReadValue(int index) { int word = 0; word |= RawData[index + 0] << 0; @@ -130,6 +133,8 @@ namespace HavenSoft.HexManiac.Core.Models { for (int i = 0; i < length; i++) changeToken.ChangeData(this, start + i, 0xFF); } + public override IReadOnlyList SearchForPointersToAnchor(ModelDelta changeToken, int address) => throw new NotImplementedException(); + public override string Copy(int start, int length) { var bytes = Enumerable.Range(start, length).Select(i => RawData[i]); return string.Join(" ", bytes.Select(value => value.ToString("X2"))); diff --git a/src/HexManiac.Core/Models/PokemonModel.cs b/src/HexManiac.Core/Models/PokemonModel.cs index a5622344..0686d651 100644 --- a/src/HexManiac.Core/Models/PokemonModel.cs +++ b/src/HexManiac.Core/Models/PokemonModel.cs @@ -609,6 +609,27 @@ namespace HavenSoft.HexManiac.Core.Models { return new StoredMetadata(anchors, unmappedPointers); } + public override IReadOnlyList SearchForPointersToAnchor(ModelDelta changeToken, int address) { + var results = new List(); + + for (int i = 3; i < RawData.Length; i++) { + if (RawData[i] != 0x08 && RawData[i] != 0x09) continue; + int destination = ReadPointer(i - 3); + if (destination != address) continue; + var index = BinarySearch(i - 3); + if (index >= 0) continue; + index = ~index; + if (index < runs.Count && runs[index].Start <= i) continue; + if (index > 0 && runs[index - 1].Start + runs[index - 1].Length > i - 3) continue; + var newRun = new PointerRun(i - 3); + runs.Insert(index, newRun); + changeToken.AddRun(newRun); + results.Add(i - 3); + } + + return results; + } + private static (string, string) SplitNameAndFormat(string text) { var name = text.Substring(1).Trim(); string format = string.Empty; @@ -724,27 +745,6 @@ namespace HavenSoft.HexManiac.Core.Models { return sources; } - private IReadOnlyList SearchForPointersToAnchor(ModelDelta changeToken, int address) { - var results = new List(); - - for (int i = 3; i < RawData.Length; i++) { - if (RawData[i] != 0x08 && RawData[i] != 0x09) continue; - int destination = ReadPointer(i - 3); - if (destination != address) continue; - var index = BinarySearch(i-3); - if (index >= 0) continue; - index = ~index; - if (index < runs.Count && runs[index].Start <= i) continue; - if (index > 0 && runs[index - 1].Start + runs[index - 1].Length > i - 3) continue; - var newRun = new PointerRun(i - 3); - runs.Insert(index, newRun); - changeToken.AddRun(newRun); - results.Add(i - 3); - } - - return results; - } - private IFormattedRun MoveRun(ModelDelta changeToken, IFormattedRun run, int newStart) { // repoint foreach (var source in run.PointerSources) { diff --git a/src/HexManiac.Core/ViewModels/ChildViewPort.cs b/src/HexManiac.Core/ViewModels/ChildViewPort.cs index e5a30903..c369bb3e 100644 --- a/src/HexManiac.Core/ViewModels/ChildViewPort.cs +++ b/src/HexManiac.Core/ViewModels/ChildViewPort.cs @@ -7,7 +7,7 @@ namespace HavenSoft.HexManiac.Core.ViewModels { public class ChildViewPort : ViewPort, IChildViewPort { public IViewPort Parent { get; } - public ChildViewPort(IViewPort viewPort) : base(new Models.LoadedFile(string.Empty, viewPort.Model.RawData), viewPort.Model) { + public ChildViewPort(IViewPort viewPort) : base(string.Empty, viewPort.Model) { Parent = viewPort; Width = Parent.Width; } diff --git a/src/HexManiac.Core/ViewModels/EditorViewModel.cs b/src/HexManiac.Core/ViewModels/EditorViewModel.cs index 26f43f62..5dfc8dfb 100644 --- a/src/HexManiac.Core/ViewModels/EditorViewModel.cs +++ b/src/HexManiac.Core/ViewModels/EditorViewModel.cs @@ -218,7 +218,7 @@ namespace HavenSoft.HexManiac.Core.ViewModels { var file = arg as LoadedFile ?? fileSystem.OpenFile("GameBoy Advanced", "gba"); if (file == null) return; var metadata = fileSystem.MetadataFor(file.Name); - Add(new ViewPort(file, new AutoSearchModel(file.Contents, metadata))); + Add(new ViewPort(file.Name, new AutoSearchModel(file.Contents, metadata))); }; ImplementFindCommands(); diff --git a/src/HexManiac.Core/ViewModels/ViewPort.cs b/src/HexManiac.Core/ViewModels/ViewPort.cs index 19d9096a..08a19a38 100644 --- a/src/HexManiac.Core/ViewModels/ViewPort.cs +++ b/src/HexManiac.Core/ViewModels/ViewPort.cs @@ -283,12 +283,12 @@ namespace HavenSoft.HexManiac.Core.ViewModels { public ViewPort() : this(new LoadedFile(string.Empty, new byte[0])) { } - public ViewPort(LoadedFile file, IDataModel model = null) { + public ViewPort(string fileName, IDataModel model) { history = new ChangeHistory(RevertChanges); history.PropertyChanged += HistoryPropertyChanged; - Model = model ?? new BasicModel(file.Contents); - FileName = file.Name; + Model = model; + FileName = fileName; scroll = new ScrollRegion { DataLength = Model.Count }; scroll.PropertyChanged += ScrollPropertyChanged; @@ -306,6 +306,8 @@ namespace HavenSoft.HexManiac.Core.ViewModels { RefreshBackingData(); } + public ViewPort(LoadedFile file) : this(file.Name, new BasicModel(file.Contents)) { } + private void ImplementCommands() { clear.CanExecute = CanAlwaysExecute; clear.Execute = arg => { @@ -440,7 +442,9 @@ namespace HavenSoft.HexManiac.Core.ViewModels { var pcsBytes = PCSString.Convert(cleanedSearchString); pcsBytes.RemoveAt(pcsBytes.Count - 1); // remove the 0xFF that was added, since we're searching for a string segment instead of a whole string. searchBytes.AddRange(pcsBytes.Select(b => new PCSSearchByte(b))); - results.AddRange(Search(searchBytes)); + var textResults = Search(searchBytes).ToList(); + ConsiderResultsAsTextRuns(textResults); + results.AddRange(textResults); } // it might be a pointer without angle braces @@ -469,6 +473,25 @@ namespace HavenSoft.HexManiac.Core.ViewModels { return results; } + // for each of the results, we recognized it as text: see if we need to add a matching string run / pointers + private int ConsiderResultsAsTextRuns(IEnumerable searchResults) { + int resultsRecognizedAsTextRuns = 0; + + foreach (var result in searchResults) { + var nextRun = Model.GetNextRun(result); + if (nextRun.Start <= result) continue; + var pointers = Model.SearchForPointersToAnchor(history.CurrentChange, result); + if (pointers.Count == 0) continue; + var newRun = new PCSRun(result, PCSString.ReadString(Model, result, true), pointers); + if (newRun.Length < 1) continue; + if (newRun.Start + newRun.Length > nextRun.Start) continue; + Model.ObserveAnchorWritten(history.CurrentChange, string.Empty, newRun); + resultsRecognizedAsTextRuns++; + } + + return resultsRecognizedAsTextRuns; + } + private byte[] Parse(string content) { var result = new byte[content.Length / 2]; for (int i = 0; i < result.Length; i++) { @@ -919,13 +942,26 @@ namespace HavenSoft.HexManiac.Core.ViewModels { private bool CompleteAnchorEdit(Point point) { var underEdit = (UnderEdit)currentView[point.X, point.Y].Format; var index = scroll.ViewPointToDataIndex(point); - var errorInfo = PokemonModel.ApplyAnchor(Model, history.CurrentChange, index, underEdit.CurrentText); + ErrorInfo errorInfo; + + // if it's an unnamed text anchor, we have special logic for that + if (underEdit.CurrentText == "^\"\" ") { + int count = ConsiderResultsAsTextRuns(new[] { index }); + if (count == 0) { + errorInfo = new ErrorInfo("An anchor with nothing pointing to it must have a name."); + } else { + errorInfo = ErrorInfo.NoError; + } + } else { + errorInfo = PokemonModel.ApplyAnchor(Model, history.CurrentChange, index, underEdit.CurrentText); + } + ClearEdits(point); UpdateToolsFromSelection(index); if (errorInfo == ErrorInfo.NoError) return true; - OnError(this, errorInfo.ErrorMessage); + OnError?.Invoke(this, errorInfo.ErrorMessage); return false; } diff --git a/src/HexManiac.Tests/ArrayRunTests.cs b/src/HexManiac.Tests/ArrayRunTests.cs index 2cee48b4..b5651df1 100644 --- a/src/HexManiac.Tests/ArrayRunTests.cs +++ b/src/HexManiac.Tests/ArrayRunTests.cs @@ -56,7 +56,7 @@ namespace HavenSoft.HexManiac.Tests { var model = new PokemonModel(buffer); ArrayRun.TryParse(model, "[name\"\"12]13", 12, null, out var arrayRun); model.ObserveRunWritten(new ModelDelta(), arrayRun); - var viewPort = new ViewPort(new LoadedFile("file.txt", buffer), model) { PreferredWidth = -1, Width = 12, Height = 20 }; + var viewPort = new ViewPort("file.txt", model) { PreferredWidth = -1, Width = 12, Height = 20 }; // spot checks: it should look like a string that starts where the segment starts var pcs = (PCS)viewPort[0, 4].Format; @@ -87,7 +87,7 @@ namespace HavenSoft.HexManiac.Tests { public void CanParseArrayAnchorAddedFromViewPort() { var buffer = Enumerable.Repeat((byte)0xFF, 0x200).ToArray(); var model = new PokemonModel(buffer); - var viewPort = new ViewPort(new LoadedFile("file.txt", buffer), model) { Width = 0x10, Height = 0x10 }; + var viewPort = new ViewPort("file.txt", model) { Width = 0x10, Height = 0x10 }; viewPort.Edit("^bob[name\"\"14]12 "); @@ -98,7 +98,7 @@ namespace HavenSoft.HexManiac.Tests { public void ChangingAnchorTextWhileAnchorStartIsOutOfViewWorks() { var buffer = Enumerable.Repeat((byte)0xFF, 0x200).ToArray(); var model = new PokemonModel(buffer); - var viewPort = new ViewPort(new LoadedFile("file.txt", buffer), model) { Width = 0x10, Height = 0x10 }; + var viewPort = new ViewPort("file.txt", model) { Width = 0x10, Height = 0x10 }; viewPort.Edit("^bob[name\"\"16]16 "); viewPort.ScrollValue = 2; @@ -113,7 +113,7 @@ namespace HavenSoft.HexManiac.Tests { WriteStrings(buffer, 0x00, "bob", "tom", "sam", "car", "pal", "egg"); var model = new PokemonModel(buffer); - var viewPort = new ViewPort(new LoadedFile("file.txt", buffer), model) { Width = 0x10, Height = 0x10 }; + var viewPort = new ViewPort("file.txt", model) { Width = 0x10, Height = 0x10 }; viewPort.Edit("^words[word\"\"4] "); // notice, no length is given @@ -127,7 +127,7 @@ namespace HavenSoft.HexManiac.Tests { WriteStrings(buffer, 100, "bobb", "tomm", "samm", "carr", "pall", "eggg"); var model = new PokemonModel(buffer); - var viewPort = new ViewPort(new LoadedFile("file.txt", buffer), model) { Width = 0x10, Height = 0x10 }; + var viewPort = new ViewPort("file.txt", model) { Width = 0x10, Height = 0x10 }; viewPort.Edit("^words[word\"\"5] "); // notice, no length is given @@ -156,7 +156,7 @@ namespace HavenSoft.HexManiac.Tests { var model = new PokemonModel(buffer); ArrayRun.TryParse(model, "[word\"\"5]", 0, null, out var arrayRun); model.ObserveAnchorWritten(new ModelDelta(), "words", arrayRun); - var viewPort = new ViewPort(new LoadedFile("file.txt", buffer), model) { Width = 0x10, Height = 0x10 }; + var viewPort = new ViewPort("file.txt", model) { Width = 0x10, Height = 0x10 }; viewPort.SelectionStart = new Point(6, 0); viewPort.Edit("a"); // change "tomm" to "tamm" @@ -168,7 +168,7 @@ namespace HavenSoft.HexManiac.Tests { public void CanPasteArray() { var buffer = Enumerable.Repeat((byte)0xFF, 0x200).ToArray(); var model = new PokemonModel(buffer); - var viewPort = new ViewPort(new LoadedFile("file.txt", buffer), model) { Width = 0x10, Height = 0x10 }; + var viewPort = new ViewPort("file.txt", model) { Width = 0x10, Height = 0x10 }; viewPort.Edit("^strings[name\"\"16] "); viewPort.Edit("+\"bob\" +\"sam\" +\"steve\" +\"kevin\""); @@ -181,7 +181,7 @@ namespace HavenSoft.HexManiac.Tests { public void PastingArrayLeavesArrayFormat() { var buffer = Enumerable.Repeat((byte)0xFF, 0x200).ToArray(); var model = new PokemonModel(buffer); - var viewPort = new ViewPort(new LoadedFile("file.txt", buffer), model) { Width = 0x10, Height = 0x10 }; + var viewPort = new ViewPort("file.txt", model) { Width = 0x10, Height = 0x10 }; viewPort.Edit("^pokenames[name\"\"11] +\"??????????\"+\"BULBASAUR\""); viewPort.SelectionStart = new Point(0, 0); @@ -203,7 +203,7 @@ namespace HavenSoft.HexManiac.Tests { ArrayRun.TryParse(model, "[word\"\"5]", 100, null, out var arrayRun); model.ObserveAnchorWritten(new ModelDelta(), "words", arrayRun); - var viewPort = new ViewPort(new LoadedFile("file.txt", buffer), model) { Width = 0x10, Height = 0x10 }; + var viewPort = new ViewPort("file.txt", model) { Width = 0x10, Height = 0x10 }; viewPort.FollowLink(0, 7); // 7*16 = 112, right in the middle of our data // note that this will change our width to 15, because we're linking to data of width 5 when our maxwidth is 16. @@ -229,7 +229,7 @@ namespace HavenSoft.HexManiac.Tests { ArrayRun.TryParse(model, "[word\"\"5]", 100, null, out var arrayRun); model.ObserveAnchorWritten(new ModelDelta(), "words", arrayRun); - var viewPort = new ViewPort(new LoadedFile("file.txt", buffer), model) { Width = 0x10, Height = 0x10 }; + var viewPort = new ViewPort("file.txt", model) { Width = 0x10, Height = 0x10 }; viewPort.FollowLink(0, 7); // 7*16 = 112, right in the middle of our data @@ -255,7 +255,7 @@ namespace HavenSoft.HexManiac.Tests { var model = new PokemonModel(buffer); model.WritePointer(delta, 0x00, 0x20); model.ObserveRunWritten(delta, new PointerRun(0x00)); - var viewPort = new ViewPort(new LoadedFile("test.txt", buffer), model) { Width = 0x10, Height = 0x10 }; + var viewPort = new ViewPort("file.txt", model) { Width = 0x10, Height = 0x10 }; viewPort.SelectionStart = new Point(0, 2); viewPort.Edit("^testdata[name\"\"16]5 "); @@ -304,7 +304,7 @@ namespace HavenSoft.HexManiac.Tests { model.ObserveRunWritten(delta, new PointerRun(0x00)); model.WritePointer(delta, 0x04, 0x90); model.ObserveRunWritten(delta, new PointerRun(0x04)); // the anchor at 0x90 should prevent a paste overwrite - var viewPort = new ViewPort(new LoadedFile("test.txt", buffer), model) { Width = 0x10, Height = 0x10 }; + var viewPort = new ViewPort("file.txt", model) { Width = 0x10, Height = 0x10 }; viewPort.SelectionStart = new Point(0, 2); viewPort.Edit("^testdata[name\"\"16]5 "); viewPort.OnError += (sender, message) => errors.Add(message); @@ -342,7 +342,7 @@ namespace HavenSoft.HexManiac.Tests { model.ObserveRunWritten(delta, new PointerRun(0x00)); model.WritePointer(delta, 0x04, 0x90); model.ObserveRunWritten(delta, new PointerRun(0x04)); // the anchor at 0x90 should prevent a paste overwrite - var viewPort = new ViewPort(new LoadedFile("test.txt", buffer), model) { Width = 0x10, Height = 0x10 }; + var viewPort = new ViewPort("file.txt", model) { Width = 0x10, Height = 0x10 }; viewPort.SelectionStart = new Point(0, 2); viewPort.Edit("^testdata[name\"\"16]5 "); viewPort.OnError += (sender, message) => errors.Add(message); @@ -381,7 +381,7 @@ namespace HavenSoft.HexManiac.Tests { model.ObserveRunWritten(delta, new PointerRun(0x00)); model.WritePointer(delta, 0x04, 0x90); model.ObserveRunWritten(delta, new PointerRun(0x04)); // the anchor at 0x90 should prevent a paste overwrite - var viewPort = new ViewPort(new LoadedFile("test.txt", buffer), model) { Width = 0x10, Height = 0x10 }; + var viewPort = new ViewPort("file.txt", model) { Width = 0x10, Height = 0x10 }; viewPort.SelectionStart = new Point(0, 2); viewPort.Edit("^testdata[name\"\"16]5 "); viewPort.OnError += (sender, message) => errors.Add(message); @@ -400,7 +400,7 @@ namespace HavenSoft.HexManiac.Tests { public void ArarysSupportIntegers() { var buffer = new byte[0x200]; var model = new PokemonModel(buffer); - var viewPort = new ViewPort(new LoadedFile("test.txt", buffer), model) { Width = 0x10, Height = 0x10 }; + var viewPort = new ViewPort("file.txt", model) { Width = 0x10, Height = 0x10 }; var errors = new List(); viewPort.OnError += (sender, e) => errors.Add(e); @@ -414,7 +414,7 @@ namespace HavenSoft.HexManiac.Tests { public void ArrayExtendsIfBasedOnAnotherNameWhichIsExtended() { var buffer = new byte[0x200]; var model = new PokemonModel(buffer); - var viewPort = new ViewPort(new LoadedFile("test.txt", buffer), model) { Width = 0x10, Height = 0x10 }; + var viewPort = new ViewPort("file.txt", model) { Width = 0x10, Height = 0x10 }; var errors = new List(); viewPort.OnError += (sender, e) => errors.Add(e); @@ -438,7 +438,7 @@ namespace HavenSoft.HexManiac.Tests { public void CanEditIntsInArray() { var buffer = new byte[0x200]; var model = new PokemonModel(buffer); - var viewPort = new ViewPort(new LoadedFile("test.txt", buffer), model) { Width = 0x10, Height = 0x10 }; + var viewPort = new ViewPort("file.txt", model) { Width = 0x10, Height = 0x10 }; var errors = new List(); viewPort.OnError += (sender, e) => errors.Add(e); viewPort.Edit("^sample[code:]8 "); diff --git a/src/HexManiac.Tests/AsciiRunTests.cs b/src/HexManiac.Tests/AsciiRunTests.cs index b70cd3bd..c050036b 100644 --- a/src/HexManiac.Tests/AsciiRunTests.cs +++ b/src/HexManiac.Tests/AsciiRunTests.cs @@ -15,7 +15,7 @@ namespace HavenSoft.HexManiac.Tests { model[0x12] = (byte)'c'; model[0x13] = (byte)'d'; - var viewPort = new ViewPort(new LoadedFile("file.txt", buffer), model) { Width = 0x10, Height = 0x10 }; + var viewPort = new ViewPort("file.txt", model) { Width = 0x10, Height = 0x10 }; viewPort.SelectionStart = new Point(0, 1); viewPort.Edit("^data`asc`4 "); @@ -34,7 +34,7 @@ namespace HavenSoft.HexManiac.Tests { model.ObserveRunWritten(new ModelDelta(), new AsciiRun(0x10, 4)); - var viewPort = new ViewPort(new LoadedFile("file.txt", buffer), model) { Width = 0x10, Height = 0x10 }; + var viewPort = new ViewPort("file.txt", model) { Width = 0x10, Height = 0x10 }; viewPort.SelectionStart = new Point(1, 1); viewPort.Edit("3"); diff --git a/src/HexManiac.Tests/ChangeHistoryTests.cs b/src/HexManiac.Tests/ChangeHistoryTests.cs index f214e7d5..b50f37ff 100644 --- a/src/HexManiac.Tests/ChangeHistoryTests.cs +++ b/src/HexManiac.Tests/ChangeHistoryTests.cs @@ -195,7 +195,7 @@ namespace HavenSoft.HexManiac.Tests { public void CanUndoFormatChange() { var data = new byte[0x100]; var model = new PokemonModel(data); - var viewPort = new ViewPort(new LoadedFile("test.txt", data), model) { Width = 0x10, Height = 0x10 }; + var viewPort = new ViewPort("file.txt", model) { Width = 0x10, Height = 0x10 }; viewPort.SelectionStart = new Point(4, 0); viewPort.Edit("<000030>"); @@ -209,7 +209,7 @@ namespace HavenSoft.HexManiac.Tests { public void CanUndoDataMove() { var buffer = Enumerable.Repeat((byte)0xFF, 0x200).ToArray(); var model = new PokemonModel(buffer); - var viewPort = new ViewPort(new LoadedFile("test.txt", buffer), model) { Width = 0x10, Height = 0x10 }; + var viewPort = new ViewPort("file.txt", model) { Width = 0x10, Height = 0x10 }; viewPort.SelectionStart = new Point(8, 0); viewPort.Edit("<000030>"); @@ -229,7 +229,7 @@ namespace HavenSoft.HexManiac.Tests { public void CanUndoFromToolChange() { var buffer = Enumerable.Repeat((byte)0xFF, 0x200).ToArray(); var model = new PokemonModel(buffer); - var viewPort = new ViewPort(new LoadedFile("test.txt", buffer), model) { Width = 0x10, Height = 0x10 }; + var viewPort = new ViewPort("file.txt", model) { Width = 0x10, Height = 0x10 }; viewPort.Edit("^bob\"\" "); @@ -249,7 +249,7 @@ namespace HavenSoft.HexManiac.Tests { public void UndoCanHandleNameMove() { var buffer = Enumerable.Repeat((byte)0xFF, 0x200).ToArray(); var model = new PokemonModel(buffer); - var viewPort = new ViewPort(new LoadedFile("test.txt", buffer), model) { Width = 0x10, Height = 0x10 }; + var viewPort = new ViewPort("file.txt", model) { Width = 0x10, Height = 0x10 }; // operation 1 viewPort.Edit(" 03 08 24 16 "); @@ -280,7 +280,7 @@ namespace HavenSoft.HexManiac.Tests { public void UndoWorksAfterMidPointerEdit() { var buffer = Enumerable.Repeat((byte)0xFF, 0x200).ToArray(); var model = new PokemonModel(buffer); - var viewPort = new ViewPort(new LoadedFile("test.txt", buffer), model) { Width = 0x10, Height = 0x10 }; + var viewPort = new ViewPort("file.txt", model) { Width = 0x10, Height = 0x10 }; viewPort.Edit("<000100>"); viewPort.SelectionStart = new Point(1, 0); @@ -294,7 +294,7 @@ namespace HavenSoft.HexManiac.Tests { public void UndoRedoRestoresUnmappedNames() { var buffer = Enumerable.Repeat((byte)0xFF, 0x200).ToArray(); var model = new PokemonModel(buffer); - var viewPort = new ViewPort(new LoadedFile("test.txt", buffer), model) { Width = 0x10, Height = 0x10 }; + var viewPort = new ViewPort("file.txt", model) { Width = 0x10, Height = 0x10 }; viewPort.Edit(""); viewPort.SelectionStart = new Point(0, 0); diff --git a/src/HexManiac.Tests/NavigationTests.cs b/src/HexManiac.Tests/NavigationTests.cs index 66811503..84d85846 100644 --- a/src/HexManiac.Tests/NavigationTests.cs +++ b/src/HexManiac.Tests/NavigationTests.cs @@ -198,7 +198,7 @@ namespace HavenSoft.HexManiac.Tests { public void SearchFor6BytesAlsoFindsPointers() { var data = new byte[0x1200]; var model = new PokemonModel(data); - var viewPort = new ViewPort(new LoadedFile("file.txt", data), model); + var viewPort = new ViewPort("file.txt", model); viewPort.Edit("<001060>"); var results = viewPort.Find("001060"); diff --git a/src/HexManiac.Tests/PointerModelTests.cs b/src/HexManiac.Tests/PointerModelTests.cs index 2fb12737..c3cf881d 100644 --- a/src/HexManiac.Tests/PointerModelTests.cs +++ b/src/HexManiac.Tests/PointerModelTests.cs @@ -78,7 +78,7 @@ namespace HavenSoft.HexManiac.Tests { public void ModelUpdatesWhenViewPortChanges() { var buffer = new byte[0x100]; var model = new PokemonModel(buffer); - var viewPort = new ViewPort(new LoadedFile("test.txt", buffer), model); + var viewPort = new ViewPort("file.txt", model); viewPort.Edit("<000020>"); @@ -90,7 +90,7 @@ namespace HavenSoft.HexManiac.Tests { public void WritingNamedAnchorFollowedByPointerToNameWorks() { var buffer = new byte[0x100]; var model = new PokemonModel(buffer); - var viewPort = new ViewPort(new LoadedFile("test.txt", buffer), model); + var viewPort = new ViewPort("file.txt", model); viewPort.SelectionStart = new Point(0, 1); viewPort.Edit("^bob "); @@ -104,7 +104,7 @@ namespace HavenSoft.HexManiac.Tests { public void WritingPointerToNameFollowedByNamedAnchorWorks() { var buffer = new byte[0x100]; var model = new PokemonModel(buffer); - var viewPort = new ViewPort(new LoadedFile("test.txt", buffer), model); + var viewPort = new ViewPort("file.txt", model); viewPort.SelectionStart = new Point(0, 2); viewPort.Edit(""); @@ -118,7 +118,7 @@ namespace HavenSoft.HexManiac.Tests { public void CanWriteAnchorToSameLocationAsPointerWithoutRemovingPointer() { var buffer = new byte[0x100]; var model = new PokemonModel(buffer); - var viewPort = new ViewPort(new LoadedFile("test.txt", buffer), model); + var viewPort = new ViewPort("file.txt", model); viewPort.SelectionStart = new Point(0, 2); viewPort.Edit("<000040>"); @@ -132,7 +132,7 @@ namespace HavenSoft.HexManiac.Tests { public void CanWriteAnchorToSameLocationAsPointerPointingToThatAnchor() { var buffer = new byte[0x100]; var model = new PokemonModel(buffer); - var viewPort = new ViewPort(new LoadedFile("test.txt", buffer), model); + var viewPort = new ViewPort("file.txt", model); viewPort.SelectionStart = new Point(0, 2); viewPort.Edit(""); @@ -147,7 +147,7 @@ namespace HavenSoft.HexManiac.Tests { public void WritingAnAnchorUpdatesPointersToUseThatName() { var buffer = new byte[0x100]; var model = new PokemonModel(buffer); - var viewPort = new ViewPort(new LoadedFile("test.txt", buffer), model); + var viewPort = new ViewPort("file.txt", model); viewPort.SelectionStart = new Point(0, 2); viewPort.Edit("<000004>"); @@ -215,7 +215,7 @@ namespace HavenSoft.HexManiac.Tests { public void PointerCanPointToNameAfterThatNameGetsDeleted() { var buffer = new byte[0x100]; var model = new PokemonModel(buffer); - var viewPort = new ViewPort(new LoadedFile("test.txt", buffer), model) { Width = 16, Height = 16 }; + var viewPort = new ViewPort("file.txt", model) { Width = 0x10, Height = 0x10 }; var token = new ModelDelta(); viewPort.SelectionStart = new Point(0, 1); @@ -237,7 +237,7 @@ namespace HavenSoft.HexManiac.Tests { public void PointerGetsSetToZeroAfterAnchorGetsDeleted() { var buffer = new byte[0x100]; var model = new PokemonModel(buffer); - var viewPort = new ViewPort(new LoadedFile("test.txt", buffer), model) { Width = 16, Height = 16 }; + var viewPort = new ViewPort("file.txt", model) { Width = 0x10, Height = 0x10 }; var token = new ModelDelta(); viewPort.SelectionStart = new Point(0, 1); @@ -259,7 +259,7 @@ namespace HavenSoft.HexManiac.Tests { public void AnchorCarriesSourceInformation() { var buffer = new byte[0x100]; var model = new PokemonModel(buffer); - var viewPort = new ViewPort(new LoadedFile("test.txt", buffer), model) { Width = 16, Height = 16 }; + var viewPort = new ViewPort("file.txt", model) { Width = 0x10, Height = 0x10 }; viewPort.SelectionStart = new Point(0, 1); viewPort.Edit("<000020>"); @@ -271,7 +271,7 @@ namespace HavenSoft.HexManiac.Tests { public void StartingAnAnchorAndGivingItNoNameClearsAnyAnchorNameAtThatPosition() { var buffer = new byte[0x100]; var model = new PokemonModel(buffer); - var viewPort = new ViewPort(new LoadedFile("test.txt", buffer), model) { Width = 0x10, Height = 0x10 }; + var viewPort = new ViewPort("file.txt", model) { Width = 0x10, Height = 0x10 }; viewPort.SelectionStart = new Point(0, 1); viewPort.Edit(""); @@ -290,7 +290,7 @@ namespace HavenSoft.HexManiac.Tests { public void CanRemoveAnchorWithNoReferences() { var buffer = new byte[0x100]; var model = new PokemonModel(buffer); - var viewPort = new ViewPort(new LoadedFile("test.txt", buffer), model) { Width = 0x10, Height = 0x10 }; + var viewPort = new ViewPort("file.txt", model) { Width = 0x10, Height = 0x10 }; viewPort.SelectionStart = new Point(0, 2); viewPort.Edit("^bob ^ "); @@ -302,7 +302,7 @@ namespace HavenSoft.HexManiac.Tests { public void BackspaceClearsDataButNotFormats() { var buffer = new byte[0x100]; var model = new PokemonModel(buffer); - var viewPort = new ViewPort(new LoadedFile("test.txt", buffer), model) { Width = 0x10, Height = 0x10 }; + var viewPort = new ViewPort("file.txt", model) { Width = 0x10, Height = 0x10 }; viewPort.SelectionStart = new Point(0, 1); viewPort.Edit("01 02 03 04"); // 2x4 characters to clear @@ -325,7 +325,7 @@ namespace HavenSoft.HexManiac.Tests { public void WritingOverTwoPointersWorks() { var buffer = new byte[0x100]; var model = new PokemonModel(buffer); - var viewPort = new ViewPort(new LoadedFile("test.txt", buffer), model) { Width = 0x10, Height = 0x10 }; + var viewPort = new ViewPort("file.txt", model) { Width = 0x10, Height = 0x10 }; viewPort.SelectionStart = new Point(0, 1); viewPort.Edit("<000020>"); @@ -353,7 +353,7 @@ namespace HavenSoft.HexManiac.Tests { public void PointerToUnknownLocationShowsUpDifferent() { var buffer = new byte[0x100]; var model = new PokemonModel(buffer); - var viewPort = new ViewPort(new LoadedFile("test.txt", buffer), model) { Width = 0x10, Height = 0x10 }; + var viewPort = new ViewPort("file.txt", model) { Width = 0x10, Height = 0x10 }; viewPort.SelectionStart = new Point(2, 1); viewPort.Edit(""); @@ -367,7 +367,7 @@ namespace HavenSoft.HexManiac.Tests { public void AddingANewNamedPointerToNoLocationOverExistingNamedPointerToNoLocationWorks() { var buffer = new byte[0x100]; var model = new PokemonModel(buffer); - var viewPort = new ViewPort(new LoadedFile("test.txt", buffer), model) { Width = 0x10, Height = 0x10 }; + var viewPort = new ViewPort("file.txt", model) { Width = 0x10, Height = 0x10 }; viewPort.SelectionStart = new Point(2, 1); viewPort.Edit(""); @@ -382,7 +382,7 @@ namespace HavenSoft.HexManiac.Tests { public void CanGotoAnchorName() { var buffer = new byte[0x100]; var model = new PokemonModel(buffer); - var viewPort = new ViewPort(new LoadedFile("test.txt", buffer), model) { Width = 0x10, Height = 0x10 }; + var viewPort = new ViewPort("file.txt", model) { Width = 0x10, Height = 0x10 }; int errorCalls = 0; viewPort.OnError += (sender, e) => errorCalls++; @@ -398,7 +398,7 @@ namespace HavenSoft.HexManiac.Tests { public void CanFindPointer() { var buffer = new byte[0x100]; var model = new PokemonModel(buffer); - var viewPort = new ViewPort(new LoadedFile("test.txt", buffer), model) { Width = 0x10, Height = 0x10 }; + var viewPort = new ViewPort("file.txt", model) { Width = 0x10, Height = 0x10 }; viewPort.SelectionStart = new Point(4, 1); viewPort.Edit("<000058> 23 19"); @@ -411,7 +411,7 @@ namespace HavenSoft.HexManiac.Tests { public void CanUsePointerAsLink() { var buffer = new byte[0x200]; var model = new PokemonModel(buffer); - var viewPort = new ViewPort(new LoadedFile("test.txt", buffer), model) { Width = 0x10, Height = 0x10 }; + var viewPort = new ViewPort("file.txt", model) { Width = 0x10, Height = 0x10 }; viewPort.SelectionStart = new Point(4, 1); viewPort.Edit("<000120>"); @@ -424,7 +424,7 @@ namespace HavenSoft.HexManiac.Tests { public void FindAllSourcesWorks() { var buffer = new byte[0x200]; var model = new PokemonModel(buffer); - var viewPort = new ViewPort(new LoadedFile("test.txt", buffer), model) { Width = 0x10, Height = 0x10 }; + var viewPort = new ViewPort("file.txt", model) { Width = 0x10, Height = 0x10 }; var editor = new EditorViewModel(new StubFileSystem()); editor.Add(viewPort); @@ -441,7 +441,7 @@ namespace HavenSoft.HexManiac.Tests { public void NewAnchorWithSameNameMovesPointersToNewAnchor() { var buffer = new byte[0x200]; var model = new PokemonModel(buffer); - var viewPort = new ViewPort(new LoadedFile("test.txt", buffer), model) { Width = 0x10, Height = 0x10 }; + var viewPort = new ViewPort("file.txt", model) { Width = 0x10, Height = 0x10 }; // put some pointers in the file viewPort.SelectionStart = new Point(4, 1); @@ -465,7 +465,7 @@ namespace HavenSoft.HexManiac.Tests { public void CanCopyAndPastePointers() { var buffer = new byte[0x200]; var fileSystem = new StubFileSystem(); - var viewPort = new ViewPort(new LoadedFile("file.txt", buffer), new PokemonModel(buffer)) { Width = 0x10, Height = 0x10 }; + var viewPort = new ViewPort("file.txt", new PokemonModel(buffer)) { Width = 0x10, Height = 0x10 }; viewPort.SelectionStart = new Point(0, 2); @@ -495,7 +495,7 @@ namespace HavenSoft.HexManiac.Tests { var buffer = new byte[0x200]; var model = new PokemonModel(buffer); var fileSystem = new StubFileSystem(); - var viewPort = new ViewPort(new LoadedFile("file.txt", buffer), model) { Width = 0x10, Height = 0x10 }; + var viewPort = new ViewPort("file.txt", model) { Width = 0x10, Height = 0x10 }; viewPort.Edit(""); viewPort.SelectionStart = new Point(0, 0); @@ -521,7 +521,7 @@ namespace HavenSoft.HexManiac.Tests { public void ArrowMovementWhileTypingAnchorRevertsChange() { var buffer = Enumerable.Repeat((byte)0xFF, 0x200).ToArray(); var model = new PokemonModel(buffer); - var viewPort = new ViewPort(new LoadedFile("test.txt", buffer), model) { Width = 0x10, Height = 0x10 }; + var viewPort = new ViewPort("file.txt", model) { Width = 0x10, Height = 0x10 }; viewPort.Edit("^bob"); // no trailing space: still under edit @@ -534,7 +534,7 @@ namespace HavenSoft.HexManiac.Tests { public void EscapeWhileTypingAnchorCancelsChange() { var buffer = Enumerable.Repeat((byte)0xFF, 0x200).ToArray(); var model = new PokemonModel(buffer); - var viewPort = new ViewPort(new LoadedFile("test.txt", buffer), model) { Width = 0x10, Height = 0x10 }; + var viewPort = new ViewPort("file.txt", model) { Width = 0x10, Height = 0x10 }; viewPort.Edit("^bob"); // no trailing space: still under edit viewPort.Edit(ConsoleKey.Escape); @@ -547,7 +547,7 @@ namespace HavenSoft.HexManiac.Tests { public void StartingAnAnchorOverAnAnchorClearsTheExistingAnchorInfo() { var buffer = Enumerable.Repeat((byte)0xFF, 0x200).ToArray(); var model = new PokemonModel(buffer); - var viewPort = new ViewPort(new LoadedFile("test.txt", buffer), model) { Width = 0x10, Height = 0x10 }; + var viewPort = new ViewPort("file.txt", model) { Width = 0x10, Height = 0x10 }; viewPort.Edit("^bob "); Assert.Equal("^bob", viewPort.AnchorText); @@ -564,7 +564,7 @@ namespace HavenSoft.HexManiac.Tests { var buffer = Enumerable.Repeat((byte)0xFF, 0x200).ToArray(); var model = new PokemonModel(buffer); model.ObserveAnchorWritten(new ModelDelta(), "bob", new NoInfoRun(0x08)); - var viewPort = new ViewPort(new LoadedFile("test.txt", buffer), model) { Width = 0x10, Height = 0x10 }; + var viewPort = new ViewPort("file.txt", model) { Width = 0x10, Height = 0x10 }; viewPort.SelectionStart = new Point(0x08, 0); @@ -576,7 +576,7 @@ namespace HavenSoft.HexManiac.Tests { public void AnchorEditTextUpdatesWhenTypingAnAnchor() { var buffer = Enumerable.Repeat((byte)0xFF, 0x200).ToArray(); var model = new PokemonModel(buffer); - var viewPort = new ViewPort(new LoadedFile("test.txt", buffer), model) { Width = 0x10, Height = 0x10 }; + var viewPort = new ViewPort("file.txt", model) { Width = 0x10, Height = 0x10 }; viewPort.Edit("^partialTe"); // in the middle of typing 'partialText' @@ -589,7 +589,7 @@ namespace HavenSoft.HexManiac.Tests { var buffer = Enumerable.Repeat((byte)0xFF, 0x200).ToArray(); var model = new PokemonModel(buffer); model.ObserveAnchorWritten(new ModelDelta(), "bob", new NoInfoRun(0x08)); - var viewPort = new ViewPort(new LoadedFile("test.txt", buffer), model) { Width = 0x10, Height = 0x10 }; + var viewPort = new ViewPort("file.txt", model) { Width = 0x10, Height = 0x10 }; viewPort.SelectionStart = new Point(0x08, 0); viewPort.AnchorText = "^bob\"\""; @@ -602,7 +602,7 @@ namespace HavenSoft.HexManiac.Tests { var buffer = Enumerable.Repeat((byte)0xFF, 0x200).ToArray(); var model = new PokemonModel(buffer); model.ObserveAnchorWritten(new ModelDelta(), "bob", new NoInfoRun(0x08)); - var viewPort = new ViewPort(new LoadedFile("test.txt", buffer), model) { Width = 0x10, Height = 0x10 }; + var viewPort = new ViewPort("file.txt", model) { Width = 0x10, Height = 0x10 }; viewPort.SelectionStart = new Point(0x08, 0); viewPort.AnchorText = "tom\"\""; @@ -618,7 +618,7 @@ namespace HavenSoft.HexManiac.Tests { model.ObserveRunWritten(new ModelDelta(), new PointerRun(0x010)); model.WritePointer(new ModelDelta(), 0x014, 0x120); model.ObserveRunWritten(new ModelDelta(), new PointerRun(0x014)); - var viewPort = new ViewPort(new LoadedFile("test.txt", data), model) { Width = 0x8, Height = 0x8 }; + var viewPort = new ViewPort("file.txt", model) { Width = 0x8, Height = 0x8 }; viewPort.SelectionStart = new Point(0, 2); // 0x010 viewPort.Edit("00"); // this should remove the first pointer @@ -631,7 +631,7 @@ namespace HavenSoft.HexManiac.Tests { public void CreatingAnOffsetPointerShouldCoerceToTheStartOfExistingPointer() { var data = new byte[0x200]; var model = new PokemonModel(data); - var viewPort = new ViewPort(new LoadedFile("test.txt", data), model) { Width = 0x10, Height = 0x10 }; + var viewPort = new ViewPort("file.txt", model) { Width = 0x10, Height = 0x10 }; viewPort.Edit("<000100>"); viewPort.SelectionStart = new Point(2, 0); @@ -647,7 +647,7 @@ namespace HavenSoft.HexManiac.Tests { var errors = new List(); var data = new byte[0x200]; var model = new PokemonModel(data); - var viewPort = new ViewPort(new LoadedFile("test.txt", data), model) { Width = 0x10, Height = 0x10 }; + var viewPort = new ViewPort("file.txt", model) { Width = 0x10, Height = 0x10 }; viewPort.OnError += (sender, message) => errors.Add(message); viewPort.Edit("<000400>"); @@ -659,7 +659,7 @@ namespace HavenSoft.HexManiac.Tests { public void ClearingAPointerAlsoRemovesItsAnchor() { var data = new byte[0x200]; var model = new PokemonModel(data); - var viewPort = new ViewPort(new LoadedFile("test.txt", data), model) { Width = 0x10, Height = 0x10 }; + var viewPort = new ViewPort("file.txt", model) { Width = 0x10, Height = 0x10 }; viewPort.Edit("<000100>"); model.ClearFormat(new ModelDelta(), 0x00, 4); @@ -671,7 +671,7 @@ namespace HavenSoft.HexManiac.Tests { public void TypingBracesOnDataTriesToInterpretThatDataAsPointer() { var data = new byte[0x200]; var model = new PokemonModel(data); - var viewPort = new ViewPort(new LoadedFile("test.txt", data), model) { Width = 0x10, Height = 0x10 }; + var viewPort = new ViewPort("file.txt", model) { Width = 0x10, Height = 0x10 }; viewPort.Edit("00 01 00 08"); viewPort.SelectionStart = new Point(0, 0); @@ -684,7 +684,7 @@ namespace HavenSoft.HexManiac.Tests { public void StartingPointerEditAndThenMovingClearsAllEditedCells() { var data = new byte[0x200]; var model = new PokemonModel(data); - var viewPort = new ViewPort(new LoadedFile("test.txt", data), model) { Width = 0x10, Height = 0x10 }; + var viewPort = new ViewPort("file.txt", model) { Width = 0x10, Height = 0x10 }; viewPort.Edit("<"); viewPort.SelectionStart = new Point(2, 2); @@ -704,7 +704,7 @@ namespace HavenSoft.HexManiac.Tests { model.WritePointer(change, 0x23, 0x050); // a pointer that isn't 4-byte aligned, pointing to data that is model.WritePointer(change, 0x10, 0x087); // a pointer that is 4-byte aligned, but pointing to something that isn't model.WritePointer(change, 2, 0xA2); // a pointer that isn't 4-byte aligned, pointing to something not 4-byte aligned - var viewPort = new ViewPort(new LoadedFile("test.txt", data), model) { Width = 0x10, Height = 0x10 }; + var viewPort = new ViewPort("file.txt", model) { Width = 0x10, Height = 0x10 }; // got to 50 and write an anchor viewPort.SelectionStart = new Point(0x0, 0x5); diff --git a/src/HexManiac.Tests/StringModelTests.cs b/src/HexManiac.Tests/StringModelTests.cs index 8db5f276..7250568d 100644 --- a/src/HexManiac.Tests/StringModelTests.cs +++ b/src/HexManiac.Tests/StringModelTests.cs @@ -28,7 +28,7 @@ namespace HavenSoft.HexManiac.Tests { public void CanWriteString() { var buffer = Enumerable.Repeat((byte)0xFF, 0x100).ToArray(); var model = new PokemonModel(buffer); - var viewPort = new ViewPort(new LoadedFile("test.txt", buffer), model); + var viewPort = new ViewPort("test.txt", model); viewPort.Edit("^bob\"\" \"Hello World!\""); @@ -54,7 +54,7 @@ namespace HavenSoft.HexManiac.Tests { public void TryingToWriteStringFormatToNonStringFormatDataFails() { var buffer = new byte[0x100]; var model = new PokemonModel(buffer); - var viewPort = new ViewPort(new LoadedFile("test.txt", buffer), model); + var viewPort = new ViewPort("test.txt", model); var editor = new EditorViewModel(new StubFileSystem()); editor.Add(viewPort); @@ -66,7 +66,7 @@ namespace HavenSoft.HexManiac.Tests { public void CanTruncateString() { var buffer = Enumerable.Repeat((byte)0xFF, 0x100).ToArray(); var model = new PokemonModel(buffer); - var viewPort = new ViewPort(new LoadedFile("test.txt", buffer), model) { Width = 0x10, Height = 0x10 }; + var viewPort = new ViewPort("test.txt", model) { Width = 0x10, Height = 0x10 }; viewPort.Edit("^bob\"\" \"Hello World!\""); @@ -89,7 +89,7 @@ namespace HavenSoft.HexManiac.Tests { public void CanAutoMoveWhenHittingAnchor() { var buffer = Enumerable.Repeat((byte)0xFF, 0x300).ToArray(); var model = new PokemonModel(buffer); - var viewPort = new ViewPort(new LoadedFile("test.txt", buffer), model) { Width = 0x10, Height = 0x10 }; + var viewPort = new ViewPort("test.txt", model) { Width = 0x10, Height = 0x10 }; viewPort.SelectionStart = new Point(8, 0); viewPort.Edit("^bob FF FF FF FF "); @@ -114,7 +114,7 @@ namespace HavenSoft.HexManiac.Tests { public void CanAutoMoveWhenHittingData() { var buffer = Enumerable.Repeat((byte)0xFF, 0x200).ToArray(); var model = new PokemonModel(buffer); - var viewPort = new ViewPort(new LoadedFile("test.txt", buffer), model) { Width = 0x10, Height = 0x10 }; + var viewPort = new ViewPort("test.txt", model) { Width = 0x10, Height = 0x10 }; viewPort.SelectionStart = new Point(8, 0); viewPort.Edit("A1 B3 64 18 "); @@ -140,7 +140,7 @@ namespace HavenSoft.HexManiac.Tests { public void AnchorWithNoNameIsNotValidIfNothingPointsToIt() { var buffer = Enumerable.Repeat((byte)0xFF, 0x200).ToArray(); var model = new PokemonModel(buffer); - var viewPort = new ViewPort(new LoadedFile("test.txt", buffer), model) { Width = 0x10, Height = 0x10 }; + var viewPort = new ViewPort("test.txt", model) { Width = 0x10, Height = 0x10 }; var errors = new List(); viewPort.OnError += (sender, e) => errors.Add(e); @@ -160,7 +160,7 @@ namespace HavenSoft.HexManiac.Tests { public void OpeningStringFormatIncludesOpeningQuote() { var buffer = Enumerable.Repeat((byte)0xFF, 0x200).ToArray(); var model = new PokemonModel(buffer); - var viewPort = new ViewPort(new LoadedFile("test.txt", buffer), model) { Width = 0x10, Height = 0x10 }; + var viewPort = new ViewPort("test.txt", model) { Width = 0x10, Height = 0x10 }; viewPort.Edit("^bob\"\" \"Hello World!\""); var anchor = (Anchor)viewPort[0, 0].Format; @@ -173,7 +173,7 @@ namespace HavenSoft.HexManiac.Tests { var buffer = Enumerable.Repeat((byte)0xFF, 0x200).ToArray(); for (int i = 0; i < 0x10; i++) buffer[i] = 0x00; var model = new PokemonModel(buffer); - var viewPort = new ViewPort(new LoadedFile("test.txt", buffer), model) { Width = 0x10, Height = 0x10 }; + var viewPort = new ViewPort("test.txt", model) { Width = 0x10, Height = 0x10 }; var errors = new List(); viewPort.OnError += (sender, e) => errors.Add(e); @@ -196,7 +196,7 @@ namespace HavenSoft.HexManiac.Tests { var buffer = Enumerable.Repeat((byte)0xFF, 0x200).ToArray(); for (int i = 0; i < 0x10; i++) buffer[i] = 0x00; var model = new PokemonModel(buffer); - var viewPort = new ViewPort(new LoadedFile("test.txt", buffer), model) { Width = 0x10, Height = 0x10 }; + var viewPort = new ViewPort("test.txt", model) { Width = 0x10, Height = 0x10 }; // add an anchor with some data on the 2nd line viewPort.SelectionStart = new Point(0, 1); @@ -212,7 +212,7 @@ namespace HavenSoft.HexManiac.Tests { var buffer = Enumerable.Repeat((byte)0xFF, 0x200).ToArray(); for (int i = 0; i < 0x10; i++) buffer[i] = 0x00; var model = new PokemonModel(buffer); - var viewPort = new ViewPort(new LoadedFile("test.txt", buffer), model) { Width = 0x10, Height = 0x10 }; + var viewPort = new ViewPort("test.txt", model) { Width = 0x10, Height = 0x10 }; viewPort.Edit("^bob\"\" \"Some Content \\\\03More Content\""); @@ -225,7 +225,7 @@ namespace HavenSoft.HexManiac.Tests { var buffer = Enumerable.Repeat((byte)0xFF, 0x200).ToArray(); for (int i = 0; i < 0x10; i++) buffer[i] = 0x00; var model = new PokemonModel(buffer); - var viewPort = new ViewPort(new LoadedFile("test.txt", buffer), model) { Width = 0x10, Height = 0x10 }; + var viewPort = new ViewPort("test.txt", model) { Width = 0x10, Height = 0x10 }; var fileSystem = new StubFileSystem(); viewPort.Edit("^bob\"\" \"Hello World!\""); @@ -241,7 +241,7 @@ namespace HavenSoft.HexManiac.Tests { var buffer = Enumerable.Repeat((byte)0xFF, 0x200).ToArray(); for (int i = 0; i < 0x10; i++) buffer[i] = 0x00; var model = new PokemonModel(buffer); - var viewPort = new ViewPort(new LoadedFile("test.txt", buffer), model) { Width = 0x10, Height = 0x10 }; + var viewPort = new ViewPort("test.txt", model) { Width = 0x10, Height = 0x10 }; viewPort.Edit("^bob\"\" \"Text and BULBASAUR!\""); var results = viewPort.Find("\"bulbasaur\""); @@ -254,7 +254,7 @@ namespace HavenSoft.HexManiac.Tests { var buffer = Enumerable.Repeat((byte)0xFF, 0x200).ToArray(); for (int i = 0; i < 0x10; i++) buffer[i] = 0x00; var model = new PokemonModel(buffer); - var viewPort = new ViewPort(new LoadedFile("test.txt", buffer), model) { Width = 0x10, Height = 0x10 }; + var viewPort = new ViewPort("test.txt", model) { Width = 0x10, Height = 0x10 }; viewPort.Edit("^bob\"\" \"Text and BULBASAUR!\""); var results = viewPort.Find("bulbasaur"); @@ -272,7 +272,7 @@ namespace HavenSoft.HexManiac.Tests { buffer[3] = 0x08; Array.Copy(bytes, 0, buffer, 0x08, bytes.Length); var model = new PokemonModel(buffer); - var viewPort = new ViewPort(new LoadedFile("test.txt", buffer), model) { Width = 0x10, Height = 0x10 }; + var viewPort = new ViewPort("test.txt", model) { Width = 0x10, Height = 0x10 }; viewPort.SelectionStart = new Point(0x08, 0); viewPort.Edit("^"); @@ -291,7 +291,7 @@ namespace HavenSoft.HexManiac.Tests { buffer[3] = 0x08; Array.Copy(bytes, 0, buffer, 0x08, bytes.Length); var model = new PokemonModel(buffer); - var viewPort = new ViewPort(new LoadedFile("test.txt", buffer), model) { Width = 0x10, Height = 0x10 }; + var viewPort = new ViewPort("test.txt", model) { Width = 0x10, Height = 0x10 }; viewPort.SelectionStart = new Point(0x08, 0); viewPort.Edit("^"); @@ -306,7 +306,7 @@ namespace HavenSoft.HexManiac.Tests { var bytes = PCSString.Convert("Hello World!").ToArray(); Array.Copy(bytes, 0, buffer, 0x08, bytes.Length); var model = new PokemonModel(buffer); - var viewPort = new ViewPort(new LoadedFile("test.txt", buffer), model) { Width = 0x10, Height = 0x10 }; + var viewPort = new ViewPort("test.txt", model) { Width = 0x10, Height = 0x10 }; viewPort.SelectionStart = new Point(0x08, 0); viewPort.Edit("^bob "); @@ -326,7 +326,7 @@ namespace HavenSoft.HexManiac.Tests { buffer[2] = 0x00; buffer[3] = 0x08; var model = new PokemonModel(buffer); - var viewPort = new ViewPort(new LoadedFile("test.txt", buffer), model) { Width = 0x10, Height = 0x10 }; + var viewPort = new ViewPort("test.txt", model) { Width = 0x10, Height = 0x10 }; viewPort.SelectionStart = new Point(0x0C, 0); viewPort.Edit(ConsoleKey.Backspace); @@ -350,5 +350,40 @@ namespace HavenSoft.HexManiac.Tests { Assert.Equal(int.MaxValue, model.GetNextRun(0).Start); } + + [Fact] + public void StringSearchAutomaticallySearchesForPointersToResults() { + var text = "This is the song that never ends."; + var bytes = PCSString.Convert(text).ToArray(); + var buffer = new byte[0x200]; + Array.Copy(bytes, 0, buffer, 0x32, bytes.Length); // the data itself, positioned at x32 (won't be automatically found on load) + Array.Copy(new byte[] { 0x32, 0, 0, 0x08 }, 0, buffer, 0x10, 4); // the pointer to the data. Pointer is aligned, but data is not. + var model = new PokemonModel(buffer); + var viewPort = new ViewPort("test.gba", model); + + // the act of searching should find the anchor + var results = viewPort.Find("this is the song"); + + Assert.Single(results); + Assert.Single(model.GetNextRun(0x32).PointerSources); + } + + [Fact] + public void UnnamedStringAnchorAutomaticallySearchesForPointersToAnchor() { + var text = "This is the song that never ends."; + var bytes = PCSString.Convert(text).ToArray(); + var buffer = new byte[0x200]; + Array.Copy(bytes, 0, buffer, 0x32, bytes.Length); // the data itself, positioned at x32 (won't be automatically found on load) + Array.Copy(new byte[] { 0x32, 0, 0, 0x08 }, 0, buffer, 0x10, 4); // the pointer to the data. Pointer is aligned, but data is not. + var model = new PokemonModel(buffer); + var viewPort = new ViewPort("test.gba", model) { Width = 0x10, Height = 0x10 }; + + // the act of dropping an anchor should search for pointers + viewPort.SelectionStart = new Point(2, 3); + viewPort.Edit("^\"\" "); + + Assert.Equal(0x32, model.GetNextRun(0x32).Start); + Assert.Single(model.GetNextRun(0x32).PointerSources); + } } } diff --git a/src/HexManiac.Tests/ToolTests.cs b/src/HexManiac.Tests/ToolTests.cs index 7b9c3ab1..975de319 100644 --- a/src/HexManiac.Tests/ToolTests.cs +++ b/src/HexManiac.Tests/ToolTests.cs @@ -21,7 +21,7 @@ namespace HavenSoft.HexManiac.Tests { public void StringToolCanOpenOnChosenData() { var buffer = Enumerable.Repeat((byte)0xFF, 0x200).ToArray(); var model = new PokemonModel(buffer); - var viewPort = new ViewPort(new LoadedFile("test.txt", buffer), model) { Width = 0x10, Height = 0x10 }; + var viewPort = new ViewPort("file.txt", model) { Width = 0x10, Height = 0x10 }; viewPort.Edit("^bob\"\" \"Some Text\" 00 <000100>"); var toolProperties = new List(); viewPort.Tools.PropertyChanged += (sender, e) => toolProperties.Add(e.PropertyName); @@ -35,7 +35,7 @@ namespace HavenSoft.HexManiac.Tests { public void StringToolEditsAreReflectedInViewPort() { var buffer = Enumerable.Repeat((byte)0xFF, 0x200).ToArray(); var model = new PokemonModel(buffer); - var viewPort = new ViewPort(new LoadedFile("test.txt", buffer), model) { Width = 0x10, Height = 0x10 }; + var viewPort = new ViewPort("file.txt", model) { Width = 0x10, Height = 0x10 }; viewPort.Edit("^bob\"\" \"Some Text\" 00 <000100>"); viewPort.Tools.StringTool.Address = 0; @@ -48,7 +48,7 @@ namespace HavenSoft.HexManiac.Tests { public void StringToolCanMoveData() { var buffer = Enumerable.Repeat((byte)0xFF, 0x200).ToArray(); var model = new PokemonModel(buffer); - var viewPort = new ViewPort(new LoadedFile("test.txt", buffer), model) { Width = 0x10, Height = 0x10 }; + var viewPort = new ViewPort("file.txt", model) { Width = 0x10, Height = 0x10 }; viewPort.Edit("^bob\"\" \"Some Text\" 00 <000100>"); var toolProperties = new List(); viewPort.Tools.StringTool.PropertyChanged += (sender, e) => toolProperties.Add(e.PropertyName); @@ -63,7 +63,7 @@ namespace HavenSoft.HexManiac.Tests { public void ViewPortMovesWhenStringToolMovesData() { var buffer = Enumerable.Repeat((byte)0xFF, 0x200).ToArray(); var model = new PokemonModel(buffer); - var viewPort = new ViewPort(new LoadedFile("test.txt", buffer), model) { Width = 0x10, Height = 0x10 }; + var viewPort = new ViewPort("file.txt", model) { Width = 0x10, Height = 0x10 }; viewPort.Edit("^bob\"\" \"Some Text\" 00 <000100>"); viewPort.Tools.StringTool.Address = 0; @@ -75,7 +75,7 @@ namespace HavenSoft.HexManiac.Tests { public void StringToolMultiCharacterDeleteCleansUpUnusedBytes() { var buffer = Enumerable.Repeat((byte)0xFF, 0x200).ToArray(); var model = new PokemonModel(buffer); - var viewPort = new ViewPort(new LoadedFile("test.txt", buffer), model) { Width = 0x10, Height = 0x10 }; + var viewPort = new ViewPort("file.txt", model) { Width = 0x10, Height = 0x10 }; viewPort.Edit("^bob\"\" \"Some Text\" 00 <000100>"); viewPort.Tools.StringTool.Address = 0; @@ -100,7 +100,7 @@ namespace HavenSoft.HexManiac.Tests { public void StringToolContentUpdatesWhenViewPortChange() { var buffer = Enumerable.Repeat((byte)0xFF, 0x200).ToArray(); var model = new PokemonModel(buffer); - var viewPort = new ViewPort(new LoadedFile("test.txt", buffer), model) { Width = 0x10, Height = 0x10 }; + var viewPort = new ViewPort("file.txt", model) { Width = 0x10, Height = 0x10 }; viewPort.Edit("^bob\"\" \"Some Text\""); viewPort.SelectionStart = new Point(3, 0); // select the 'e' in 'Some' @@ -114,7 +114,7 @@ namespace HavenSoft.HexManiac.Tests { public void ToolSelectionChangeUpdatesViewPortSelection() { var buffer = Enumerable.Repeat((byte)0xFF, 0x200).ToArray(); var model = new PokemonModel(buffer); - var viewPort = new ViewPort(new LoadedFile("test.txt", buffer), model) { Width = 0x10, Height = 0x10 }; + var viewPort = new ViewPort("file.txt", model) { Width = 0x10, Height = 0x10 }; viewPort.Edit("^bob\"\" \"Some Text\""); viewPort.SelectionStart = new Point(3, 0); viewPort.FollowLink(3, 0); diff --git a/src/HexManiac.Tests/ViewPortCursorTests.cs b/src/HexManiac.Tests/ViewPortCursorTests.cs index 02d92744..4fa3c881 100644 --- a/src/HexManiac.Tests/ViewPortCursorTests.cs +++ b/src/HexManiac.Tests/ViewPortCursorTests.cs @@ -214,7 +214,7 @@ namespace HavenSoft.HexManiac.Tests { public void CanExpandSelection() { var data = new byte[0x200]; var model = new PokemonModel(data); - var viewPort = new ViewPort(new LoadedFile("test.txt", data), model) { Width = 0x10, Height = 0x10 }; + var viewPort = new ViewPort("file.txt", model) { Width = 0x10, Height = 0x10 }; viewPort.Edit("<000100>"); viewPort.SelectionStart = new Point(1, 0); diff --git a/src/HexManiac.Tests/ViewPortEditTests.cs b/src/HexManiac.Tests/ViewPortEditTests.cs index 0c8ed6dd..4668b35c 100644 --- a/src/HexManiac.Tests/ViewPortEditTests.cs +++ b/src/HexManiac.Tests/ViewPortEditTests.cs @@ -242,7 +242,7 @@ namespace HavenSoft.HexManiac.Tests { [Fact] public void CanClearData() { var loadedFile = new LoadedFile("test", new byte[1000]); - var viewPort = new ViewPort(loadedFile, new PokemonModel(loadedFile.Contents)) { Width = 5, Height = 5 }; + var viewPort = new ViewPort(loadedFile.Name, new PokemonModel(loadedFile.Contents)) { PreferredWidth = -1, Width = 5, Height = 5 }; viewPort.SelectionStart = new Point(0, 0); viewPort.SelectionEnd = new Point(3, 3); @@ -302,7 +302,7 @@ namespace HavenSoft.HexManiac.Tests { public void ClearRemovesFormats() { var data = new byte[0x200]; var model = new PokemonModel(data); - var viewPort = new ViewPort(new LoadedFile("file.txt", data), model); + var viewPort = new ViewPort("file.txt", model) { Width = 0x10, Height = 0x10 }; viewPort.Edit("<000100>"); viewPort.SelectionStart = new Point(2, 0); diff --git a/src/HexManiac.Tests/ViewPortSaveTests.cs b/src/HexManiac.Tests/ViewPortSaveTests.cs index 827072c3..af517fa0 100644 --- a/src/HexManiac.Tests/ViewPortSaveTests.cs +++ b/src/HexManiac.Tests/ViewPortSaveTests.cs @@ -303,7 +303,7 @@ namespace HavenSoft.HexManiac.Tests { public void CanSaveAndLoadNamesAndFormats() { var buffer = Enumerable.Repeat((byte)0xFF, 0x200).ToArray(); var model = new PokemonModel(buffer); - var viewPort = new ViewPort(new LoadedFile("test.txt", buffer), model) { Width = 0x10, Height = 0x10 }; + var viewPort = new ViewPort("file.txt", model) { Width = 0x10, Height = 0x10 }; StoredMetadata metadata = null; var fileSystem = new StubFileSystem { Save = (file, md) => { metadata = md; return true; } }; @@ -311,7 +311,7 @@ namespace HavenSoft.HexManiac.Tests { viewPort.Save.Execute(fileSystem); var model2 = new PokemonModel(buffer, metadata); - var viewPort2 = new ViewPort(new LoadedFile("test.txt", buffer), model2) { Width = 0x10, Height = 0x10 }; + var viewPort2 = new ViewPort("file.txt", model) { Width = 0x10, Height = 0x10 }; Assert.Equal("bob", ((Anchor)viewPort2[0, 0].Format).Name); } diff --git a/src/HexManiac.WPF/Windows/App.xaml.cs b/src/HexManiac.WPF/Windows/App.xaml.cs index 0fd292b5..878f8009 100644 --- a/src/HexManiac.WPF/Windows/App.xaml.cs +++ b/src/HexManiac.WPF/Windows/App.xaml.cs @@ -42,7 +42,7 @@ namespace HavenSoft.HexManiac.WPF.Windows { var loadedFile = fileSystem.LoadFile(fileName); var metadata = fileSystem.MetadataFor(fileName); var model = new AutoSearchModel(loadedFile.Contents, metadata); - editor.Add(new ViewPort(loadedFile, model)); + editor.Add(new ViewPort(loadedFile.Name, model)); return editor; } }