diff --git a/src/HexManiac.Core/Models/IDataModel.cs b/src/HexManiac.Core/Models/IDataModel.cs index 11a1f34f..51d07580 100644 --- a/src/HexManiac.Core/Models/IDataModel.cs +++ b/src/HexManiac.Core/Models/IDataModel.cs @@ -220,7 +220,9 @@ namespace HavenSoft.HexManiac.Core.Models { } public static IReadOnlyList GetNewWordAutocompleteOptions(this IDataModel model, string text, int selectedIndex) { - var options = model.GetAutoCompleteAnchorNameOptions(text.Substring(2)); + if (text.Length >= 2) text = text.Substring(2); + else return null; + var options = model.GetAutoCompleteAnchorNameOptions(text); options = options.Select(option => $"::{option} ").ToList(); return AutoCompleteSelectionItem.Generate(options, selectedIndex); } diff --git a/src/HexManiac.Core/ViewModels/ViewPort.cs b/src/HexManiac.Core/ViewModels/ViewPort.cs index 3cb9a4ae..6a075584 100644 --- a/src/HexManiac.Core/ViewModels/ViewPort.cs +++ b/src/HexManiac.Core/ViewModels/ViewPort.cs @@ -54,12 +54,16 @@ namespace HavenSoft.HexManiac.Core.ViewModels { public int Width { get => scroll.Width; - set => selection.ChangeWidth(value); + set { + using (ModelCacheScope.CreateScope(Model)) selection.ChangeWidth(value); + } } public int Height { get => scroll.Height; - set => scroll.Height = value; + set { + using (ModelCacheScope.CreateScope(Model)) scroll.Height = value; + } } public int MinimumScroll => scroll.MinimumScroll; @@ -933,21 +937,31 @@ namespace HavenSoft.HexManiac.Core.ViewModels { var format = currentView[x, y].Format; if (format is Anchor anchor) format = anchor.OriginalFormat; - // follow pointer - if (format is Pointer pointer) { - if (pointer.Destination != Pointer.NULL) { - selection.GotoAddress(pointer.Destination); - } else if (string.IsNullOrEmpty(pointer.DestinationName)) { - OnError(this, $"null pointers point to nothing, so going to their source isn't possible."); - } else { - OnError(this, $"Pointer destination {pointer.DestinationName} not found."); - } - } - - // open tool - var byteOffset = scroll.ViewPointToDataIndex(new Point(x, y)); - var currentRun = Model.GetNextRun(byteOffset); using (ModelCacheScope.CreateScope(Model)) { + // follow pointer + if (format is Pointer pointer) { + if (pointer.Destination != Pointer.NULL) { + selection.GotoAddress(pointer.Destination); + } else if (string.IsNullOrEmpty(pointer.DestinationName)) { + OnError(this, $"null pointers point to nothing, so going to their source isn't possible."); + } else { + OnError(this, $"Pointer destination {pointer.DestinationName} not found."); + } + } + + // follow word value source + if (format is MatchedWord word) { + var address = Model.GetAddressFromAnchor(history.CurrentChange, -1, word.Name.Substring(2)); + if (address == Pointer.NULL) { + OnError(this, $"No table with name '{word.Name.Substring(2)}' was found."); + } else { + selection.GotoAddress(address); + } + } + + // open tool + var byteOffset = scroll.ViewPointToDataIndex(new Point(x, y)); + var currentRun = Model.GetNextRun(byteOffset); if (currentRun is IStreamRun) { Tools.StringTool.Address = currentRun.Start; Tools.SelectedIndex = Tools.IndexOf(Tools.StringTool); @@ -1069,7 +1083,7 @@ namespace HavenSoft.HexManiac.Core.ViewModels { } else if (newText.StartsWith(":")) { return Model.GetNewWordAutocompleteOptions(newText, selectedIndex); } else { - throw new NotImplementedException(); + return null; } } } @@ -1147,7 +1161,7 @@ namespace HavenSoft.HexManiac.Core.ViewModels { (Point, Point) pair(int start, int end) => (scroll.DataIndexToViewPoint(start), scroll.DataIndexToViewPoint(end)); - if (run is PointerRun) return pair(run.Start, run.Start + run.Length - 1); + if (run is PointerRun || run is WordRun) return pair(run.Start, run.Start + run.Length - 1); if (run is EggMoveRun || run is PLMRun) { var even = (index - run.Start) % 2 == 0; if (even) return pair(index, index + 1); diff --git a/src/HexManiac.Core/ViewModels/Visitors/ContinueCellEdit.cs b/src/HexManiac.Core/ViewModels/Visitors/ContinueCellEdit.cs index a9080046..72271ed2 100644 --- a/src/HexManiac.Core/ViewModels/Visitors/ContinueCellEdit.cs +++ b/src/HexManiac.Core/ViewModels/Visitors/ContinueCellEdit.cs @@ -25,18 +25,20 @@ namespace HavenSoft.HexManiac.Core.ViewModels.Visitors { public void Visit(Undefined dataFormat, byte data) => Visit((None)null, data); public void Visit(None dataFormat, byte data) { - if (UnderEdit.CurrentText[0] == PointerStart) { - Result = char.IsLetterOrDigit(Input) || Input == ArrayAnchorSeparator || Input == PointerEnd || Input == ' '; - return; - } - - if (UnderEdit.CurrentText[0] == ':') { - if (UnderEdit.CurrentText.Length == 1) { - Result = Input == ':'; - } else { - Result = char.IsLetterOrDigit(Input) || Input == ' '; + if (UnderEdit.CurrentText.Length > 0) { + if (UnderEdit.CurrentText[0] == PointerStart) { + Result = char.IsLetterOrDigit(Input) || Input == ArrayAnchorSeparator || Input == PointerEnd || Input == ' '; + return; + } + + if (UnderEdit.CurrentText[0] == ':') { + if (UnderEdit.CurrentText.Length == 1) { + Result = Input == ':'; + } else { + Result = char.IsLetterOrDigit(Input) || Input == ' '; + } + return; } - return; } Result = ViewPort.AllHexCharacters.Contains(Input); diff --git a/src/HexManiac.WPF/Implementations/FormatDrawer.cs b/src/HexManiac.WPF/Implementations/FormatDrawer.cs index 7759bfdd..701777a8 100644 --- a/src/HexManiac.WPF/Implementations/FormatDrawer.cs +++ b/src/HexManiac.WPF/Implementations/FormatDrawer.cs @@ -102,7 +102,7 @@ namespace HavenSoft.HexManiac.WPF.Implementations { else collector.Collect(x, 1, byteText[cell.Value]); } else if (format is BitArray array) { collector.Collect(x, 1, byteText[cell.Value]); - } else if (format is MatchedWord word) { + } else if (format is MatchedWord word && word.Position == 0) { collector.Collect(x, 4, word.Name); } }