fixed a bug where pasting an array could accidentally switch formats if a string was too long

fixed a bug where string arrays were cropping the first character of the strings
This commit is contained in:
Benjamin Popp
2019-01-23 22:18:19 -06:00
parent a97ac3f510
commit 1e59fcd4d3
3 changed files with 52 additions and 19 deletions

View File

@@ -136,8 +136,8 @@ namespace HavenSoft.Gen3Hex.Core.ViewModels {
var run = model.GetNextRun(value);
if (run.Start > value) return;
if (TryUpdate(ref address, run.Start)) {
if (run is PCSRun pcsRun) {
DataForCurrentRunChanged(pcsRun);
if (run is PCSRun || run is ArrayRun) {
DataForCurrentRunChanged(run);
history.ChangeCompleted();
}
}

View File

@@ -662,12 +662,22 @@ namespace HavenSoft.Gen3Hex.Core.ViewModels {
return char.IsLetterOrDigit(input) || char.IsWhiteSpace(input) || input == ArrayStart || input == ArrayEnd || input == StringDelimeter;
} else if (underEdit.OriginalFormat is Anchor anchorFormat && anchorFormat.OriginalFormat is PCS) {
if (input == StringDelimeter) return true;
// if this is the start of a string (as noted by the anchor), crop off the leading " before trying to convert to a byte
var currentText = underEdit.CurrentText;
if (currentText.StartsWith(StringDelimeter.ToString())) currentText = currentText.Substring(1);
return PCSString.PCS.Any(str => str != null && str.StartsWith(currentText + input));
} else if (underEdit.OriginalFormat is PCS) {
if (input == StringDelimeter) return true;
return PCSString.PCS.Any(str => str != null && str.StartsWith(underEdit.CurrentText + input));
var memoryLocation = scroll.ViewPointToDataIndex(point);
var currentText = underEdit.CurrentText;
// if this is the start of an array string segment, crop off the leading " before trying to convert to a byte
if (Model.GetNextRun(memoryLocation) is ArrayRun array) {
var offsets = array.ConvertByteOffsetToArrayOffset(memoryLocation);
if (offsets.SegmentStart == memoryLocation) {
if (currentText.StartsWith(StringDelimeter.ToString())) currentText = currentText.Substring(1);
}
}
return PCSString.PCS.Any(str => str != null && str.StartsWith(currentText + input));
}
if (AllHexCharacters.Contains(input)) {
@@ -801,7 +811,6 @@ namespace HavenSoft.Gen3Hex.Core.ViewModels {
ClearEdits(point);
var memoryLocation = scroll.ViewPointToDataIndex(point);
var run = Model.GetNextRun(memoryLocation);
bool dataChanged = false;
if (run is PCSRun pcsRun) {
while (run.Start + run.Length > memoryLocation) {
history.CurrentChange.ChangeData(Model, memoryLocation, 0xFF);
@@ -809,12 +818,12 @@ namespace HavenSoft.Gen3Hex.Core.ViewModels {
SilentScroll(memoryLocation);
var newRunLength = PCSString.ReadString(Model, run.Start, true);
Model.ObserveRunWritten(history.CurrentChange, new PCSRun(run.Start, newRunLength, run.PointerSources));
dataChanged = true;
}
} else if (run is ArrayRun arrayRun) {
var offsets = arrayRun.ConvertByteOffsetToArrayOffset(memoryLocation);
history.CurrentChange.ChangeData(Model, memoryLocation, 0xFF);
memoryLocation++;
SilentScroll(memoryLocation);
while (offsets.SegmentStart + arrayRun.ElementContent[offsets.SegmentIndex].Length > memoryLocation) {
history.CurrentChange.ChangeData(Model, memoryLocation, 0x00);
memoryLocation++;
@@ -840,21 +849,31 @@ namespace HavenSoft.Gen3Hex.Core.ViewModels {
byte.Parse(underEdit.CurrentText, NumberStyles.HexNumber) :
(byte)Enumerable.Range(0, 0x100).First(i => PCSString.PCS[i] == editText);
// if its the last character being edited, do some stuff
if (pcs != null && run.Length == pcs.Position + 1) {
int extraBytesNeeded = editText == "\\\\" ? 2 : 1;
// last character edit: might require relocation
var newRun = Model.RelocateForExpansion(history.CurrentChange, run, run.Length + extraBytesNeeded);
if (newRun != run) {
ScrollFromRunMove(memoryLocation, pcs.Position, newRun);
memoryLocation += newRun.Start - run.Start;
run = newRun;
}
var position = pcs != null ? pcs.Position : escaped.Position;
history.CurrentChange.ChangeData(Model, memoryLocation + 1, 0xFF);
if (editText == "\\\\") history.CurrentChange.ChangeData(Model, memoryLocation + 2, 0xFF);
run = new PCSRun(run.Start, run.Length + extraBytesNeeded, run.PointerSources);
Model.ObserveRunWritten(history.CurrentChange, run);
// if its the last character being edited, try to expand for strings and truncate for array segments
if (run is PCSRun) {
if (run.Length == position + 1) {
int extraBytesNeeded = editText == "\\\\" ? 2 : 1;
// last character edit: might require relocation
var newRun = Model.RelocateForExpansion(history.CurrentChange, run, run.Length + extraBytesNeeded);
if (newRun != run) {
ScrollFromRunMove(memoryLocation, pcs.Position, newRun);
memoryLocation += newRun.Start - run.Start;
run = newRun;
}
history.CurrentChange.ChangeData(Model, memoryLocation + 1, 0xFF);
if (editText == "\\\\") history.CurrentChange.ChangeData(Model, memoryLocation + 2, 0xFF);
run = new PCSRun(run.Start, run.Length + extraBytesNeeded, run.PointerSources);
Model.ObserveRunWritten(history.CurrentChange, run);
}
} else if (run is ArrayRun arrayRun) {
// don't let them keep appending data if we're at the end of the string segment
var offsets = arrayRun.ConvertByteOffsetToArrayOffset(memoryLocation);
if (arrayRun.ElementContent[offsets.SegmentIndex].Length == position + 1) {
memoryLocation--; // move back one byte and edit that one instead
}
}
history.CurrentChange.ChangeData(Model, memoryLocation, byteValue);

View File

@@ -194,6 +194,20 @@ namespace HavenSoft.Gen3Hex.Tests {
Assert.Equal("\"", ((PCS)viewPort[3, 0].Format).ThisCharacter);
}
[Fact]
public void PastingArrayLeavesArrayFormat() {
var buffer = Enumerable.Repeat((byte)0xFF, 0x200).ToArray();
var model = new PointerAndStringModel(buffer);
var viewPort = new ViewPort(new LoadedFile("file.txt", buffer), model) { Width = 0x10, Height = 0x10 };
viewPort.Edit("^pokenames[name\"\"11] +\"??????????\"+\"BULBASAUR\"");
viewPort.SelectionStart = new Point(0, 0);
viewPort.FollowLink(0, 0);
Assert.Equal("^pokenames[name\"\"11]", viewPort.AnchorText);
Assert.Equal("BULBASAUR", viewPort.Tools.StringTool.Content.Split(new[] { Environment.NewLine }, StringSplitOptions.None).Last());
}
[Fact]
public void ArrayIsRecognizedByStringTool() {
var buffer = Enumerable.Repeat((byte)0xFF, 0x200).ToArray();