allow users to type pointers that lead into arrays that support inner anchors

This commit is contained in:
Benjamin Popp
2019-03-11 22:58:49 -05:00
parent 2c3f79242e
commit 9d7d1caef3
4 changed files with 36 additions and 3 deletions

View File

@@ -238,7 +238,7 @@ namespace HavenSoft.HexManiac.Core.Models {
var arrayName = GetAnchorFromAddress(-1, array.Start);
var arrayIndex = (address - array.Start) / array.ElementLength;
var indexMod = (address - array.Start) % array.ElementLength;
if (indexMod == 0) return $"{arrayName}/{arrayIndex}";
if (indexMod == 0) return $"{arrayName}{ArrayAnchorSeparator}{arrayIndex}";
}
return string.Empty;
@@ -337,7 +337,13 @@ namespace HavenSoft.HexManiac.Core.Models {
var destination = ReadPointer(start);
if (destination < 0 || destination >= Count) return;
int index = BinarySearch(destination);
if (index < 0) {
if (index < 0 && ~index > 0 && runs[~index - 1] is ArrayRun array && array.SupportsPointersToElements && (destination - array.Start) % array.ElementLength == 0) {
// the pointer points into an array that supports inner anchors
index = ~index - 1;
changeToken.RemoveRun(array);
runs[index] = array.AddSourcePointingWithinArray(start);
changeToken.AddRun(runs[index]);
} else if (index < 0) {
// the pointer is brand new
index = ~index;
var newRun = new NoInfoRun(destination, new[] { start });

View File

@@ -72,6 +72,7 @@ namespace HavenSoft.HexManiac.Core.Models.Runs {
public const char ArrayEnd = ']';
public const char SingleByteIntegerFormat = '.';
public const char DoubleByteIntegerFormat = ':';
public const char ArrayAnchorSeparator = '/';
private readonly IDataModel owner;
@@ -254,6 +255,16 @@ namespace HavenSoft.HexManiac.Core.Models.Runs {
return new ArrayRun(owner, newFormat, Start, ElementCount + elementCount, ElementContent, PointerSources, PointerSourcesForInnerElements);
}
public ArrayRun AddSourcePointingWithinArray(int source) {
var destination = owner.ReadPointer(source);
var index = (destination - Start) / ElementLength;
if (index < 0 || index >= ElementCount) throw new IndexOutOfRangeException();
if (index == 0) throw new NotImplementedException();
var newInnerPointerSources = PointerSourcesForInnerElements.ToList();
newInnerPointerSources[index] = newInnerPointerSources[index].Concat(new[] { source }).ToList();
return new ArrayRun(owner, FormatString, Start, ElementCount, ElementContent, PointerSources, newInnerPointerSources);
}
public ArrayRun AddSourcesPointingWithinArray(ModelDelta changeToken) {
if (ElementCount < 2) return this;

View File

@@ -747,7 +747,7 @@ namespace HavenSoft.HexManiac.Core.ViewModels {
return true;
}
} else if (underEdit.CurrentText.StartsWith(PointerStart.ToString())) {
return char.IsLetterOrDigit(input) || input == PointerEnd;
return char.IsLetterOrDigit(input) || input == ArrayAnchorSeparator || input == PointerEnd;
} else if (underEdit.CurrentText.StartsWith(GotoMarker.ToString())) {
return char.IsLetterOrDigit(input) || char.IsWhiteSpace(input);
} else if (underEdit.CurrentText.StartsWith(AnchorStart.ToString())) {

View File

@@ -588,6 +588,22 @@ namespace HavenSoft.HexManiac.Tests {
Assert.StartsWith("^", run.FormatString);
}
[Fact]
public void CanCreateNewPointerUsingArrayNameAndIndex() {
var data = new byte[0x200];
var changeToken = new ModelDelta();
var model = new PokemonModel(data);
var viewport = new ViewPort("name", model) { Width = 0x10, Height = 0x10 };
viewport.Edit("^array^[content\"\"8]8 ");
viewport.SelectionStart = new Point(0, 6);
viewport.Edit("<array/3>");
var run = (ArrayRun)model.GetNextRun(0);
Assert.Single(run.PointerSourcesForInnerElements[3]);
}
private static void WriteStrings(byte[] buffer, int start, params string[] content) {
foreach (var item in content) {
var bytes = PCSString.Convert(item).ToArray();