diff --git a/CHANGELOG.md b/CHANGELOG.md
index 90c3afa..562a04c 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -17,6 +17,9 @@ Jump to version:
Additions
- Added GraphicsExtensions.WithRenderTargets, a multi-target version of WithRenderTarget
+Fixes
+- Fixed TextInput not working correctly when using surrogate pairs
+
## 6.2.0
### MLEM
diff --git a/MLEM/Font/CodePointSource.cs b/MLEM/Font/CodePointSource.cs
index fe4e3d2..cae77b2 100644
--- a/MLEM/Font/CodePointSource.cs
+++ b/MLEM/Font/CodePointSource.cs
@@ -63,6 +63,18 @@ namespace MLEM.Font {
return (curr, 1);
}
+ ///
+ /// Returns an index in this code point source that is as close to as possible, but not between two members of a surrogate pair. If the is already not between surrogate pairs, it is returned unchanged.
+ ///
+ /// The index to ensure is not between surrogates.
+ /// Whether the returned index should be increased by 1 (instead of decreased by 1) when it is between surrogates.
+ /// An index close to , but not between surrogates.
+ public int EnsureSurrogateBoundary(int index, bool increase) {
+ if (index < this.Length && char.IsLowSurrogate(this[index]))
+ return increase && index < this.Length - 1 || index <= 0 ? index + 1 : index - 1;
+ return index;
+ }
+
/// Returns an enumerator that iterates through the collection.
/// A that can be used to iterate through the collection.
/// 1
diff --git a/MLEM/Input/TextInput.cs b/MLEM/Input/TextInput.cs
index f91fc87..2061b05 100644
--- a/MLEM/Input/TextInput.cs
+++ b/MLEM/Input/TextInput.cs
@@ -105,7 +105,8 @@ namespace MLEM.Input {
set {
var val = (int) MathHelper.Clamp(value, 0F, this.text.Length);
if (this.caretPos != val) {
- this.caretPos = val;
+ // ensure that we don't move to a location that is between high and low surrogates
+ this.caretPos = new CodePointSource(this.text).EnsureSurrogateBoundary(val, val > this.caretPos);
this.caretBlinkTimer = 0;
this.SetTextDataDirty(false);
}
@@ -360,7 +361,7 @@ namespace MLEM.Input {
if (!this.FilterText(ref strg, removeMismatching))
return;
if (this.MaximumCharacters != null && strg.Length > this.MaximumCharacters)
- strg = strg.Substring(0, this.MaximumCharacters.Value);
+ strg = strg.Substring(0, new CodePointSource(strg).EnsureSurrogateBoundary(this.MaximumCharacters.Value, false));
this.text.Clear();
this.text.Append(strg);
this.CaretPos = this.text.Length;
@@ -378,7 +379,7 @@ namespace MLEM.Input {
if (!this.FilterText(ref strg, removeMismatching))
return false;
if (this.MaximumCharacters != null && this.text.Length + strg.Length > this.MaximumCharacters)
- strg = strg.Substring(0, this.MaximumCharacters.Value - this.text.Length);
+ strg = strg.Substring(0, new CodePointSource(strg).EnsureSurrogateBoundary(this.MaximumCharacters.Value - this.text.Length, false));
this.text.Insert(this.CaretPos, strg);
this.CaretPos += strg.Length;
this.SetTextDataDirty();
@@ -393,7 +394,8 @@ namespace MLEM.Input {
public bool RemoveText(int index, int length) {
if (index < 0 || index >= this.text.Length)
return false;
- this.text.Remove(index, length);
+ var source = new CodePointSource(this.text);
+ this.text.Remove(source.EnsureSurrogateBoundary(index, false), source.EnsureSurrogateBoundary(index + length, true) - index);
// ensure that caret pos is still in bounds
this.CaretPos = this.CaretPos;
this.SetTextDataDirty();