diff --git a/Dalamud/Interface/Internal/ImGuiClipboardFunctionProvider.cs b/Dalamud/Interface/Internal/ImGuiClipboardFunctionProvider.cs
index 20e49823a..f14210b97 100644
--- a/Dalamud/Interface/Internal/ImGuiClipboardFunctionProvider.cs
+++ b/Dalamud/Interface/Internal/ImGuiClipboardFunctionProvider.cs
@@ -171,43 +171,61 @@ internal sealed unsafe class ImGuiClipboardFunctionProvider : IServiceType, IDis
_ => 0xFFFD,
};
+ ///
+ /// Replaces a sequence with another.
+ ///
+ /// The buffer.
+ /// Offset of the sequence to be replaced.
+ /// Length of the sequence to be replaced.
+ /// The replacement sequence.
+ /// The length of .
+ public static int ReplaceSequence(
+ ref ImVectorWrapper buf,
+ int offset,
+ int length,
+ ReadOnlySpan replacement)
+ {
+ var i = 0;
+ for (; i < replacement.Length; i++)
+ {
+ if (length >= i + 1)
+ buf[offset++] = replacement[i];
+ else
+ buf.Insert(offset++, replacement[i]);
+ }
+
+ for (; i < length; i++)
+ buf.RemoveAt(offset);
+
+ return replacement.Length;
+ }
+
///
/// Normalize the given text for our use case.
///
/// The buffer.
public static void Normalize(ref ImVectorWrapper buf)
{
+ // Ensure an implicit null after the end of the string.
+ buf.EnsureCapacity(buf.Length + 1);
+ buf.StorageSpan[buf.Length] = 0;
+
for (var i = 0; i < buf.Length;)
{
- // Already correct?
- if (buf[i] is 0x0D && buf[i + 1] is 0x0A)
- {
- i += 2;
- continue;
- }
-
var cb = CountBytes(buf.Data + i, buf.Length - i);
var currInt = GetCodepoint(buf.Data + i, cb);
switch (currInt)
{
- case 0xFFFF: // Simply invalid
+ // Note that buf.Data[i + 1] is always defined. See the beginning of the function.
+ case '\r' when buf.Data[i + 1] == '\n': // Already CR LF?
+ i += 2;
+ continue;
+
+ case 0xFFFE or 0xFFFF: // Simply invalid
case > char.MaxValue: // ImWchar is same size with char; does not support
case >= 0xD800 and <= 0xDBFF: // UTF-16 surrogate; does not support
// Replace with \uFFFD in UTF-8: EF BF BD
- buf[i++] = 0xEF;
-
- if (cb >= 2)
- buf[i++] = 0xBF;
- else
- buf.Insert(i++, 0xBF);
-
- if (cb >= 3)
- buf[i++] = 0xBD;
- else
- buf.Insert(i++, 0xBD);
-
- if (cb >= 4)
- buf.RemoveAt(i);
+ i += ReplaceSequence(ref buf, i, cb, "\uFFFD"u8);
break;
// See String.Manipulation.cs: IndexOfNewlineChar.
@@ -217,18 +235,7 @@ internal sealed unsafe class ImGuiClipboardFunctionProvider : IServiceType, IDis
case '\u0085': // NEL; Next Line
case '\u2028': // LS; Line Separator
case '\u2029': // PS; Paragraph Separator
- buf[i++] = 0x0D;
-
- if (cb >= 2)
- buf[i++] = 0x0A;
- else
- buf.Insert(i++, 0x0A);
-
- if (cb >= 3)
- buf.RemoveAt(i);
-
- if (cb >= 4)
- buf.RemoveAt(i);
+ i += ReplaceSequence(ref buf, i, cb, "\r\n"u8);
break;
default: