From 4907ea138c980192df45904907a200f6d7b0522a Mon Sep 17 00:00:00 2001 From: Jimmy Chang Date: Tue, 11 Aug 2026 01:41:04 +0800 Subject: [PATCH] Handle multi-byte characters correctly in text fields Two independent defects made non-ASCII text unusable in EditControl. Pasting replaced every byte >= 0x80 with "?" before inserting. In a field carrying a filename filter the "?" was then stripped again as an illegal character, so pasted text disappeared outright rather than merely being mangled. Drop the substitution and let the bytes through; Insert() still applies the control's own filter. Backspace and delete removed a fixed single byte, which splits a multi-byte character and leaves an invalid sequence behind. Caret movement already steps by whole characters through utf8.next, so deletion now derives its length from the same helper. The ctrl-modified word-wise paths are untouched. --- src/Classes/EditControl.lua | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/src/Classes/EditControl.lua b/src/Classes/EditControl.lua index 97ce2c92fe1..606e8aa0cb8 100644 --- a/src/Classes/EditControl.lua +++ b/src/Classes/EditControl.lua @@ -530,7 +530,6 @@ function EditClass:OnKeyDown(key, doubleClick) if self.pasteFilter then text = self.pasteFilter(text) end - text = text:gsub("[\128-\255]","?") if self.sel and self.sel ~= self.caret then self:ReplaceSel(text) else @@ -607,8 +606,10 @@ function EditClass:OnKeyDown(key, doubleClick) if self.sel and self.sel ~= self.caret then self:ReplaceSel("") elseif self.caret > 1 then - local len = 1 + -- Remove one whole character, which may be several bytes wide. + local len = self.caret - (utf8.next(self.buf, self.caret, -1) or 1) if IsKeyDown("CTRL") then + len = 1 while self.caret - len > 1 and self.buf:sub(self.caret - len, self.caret - len):match("%s") and not self.buf:sub(self.caret - len - 1, self.caret - len - 1):match("\n") do len = len + 1 end @@ -632,8 +633,10 @@ function EditClass:OnKeyDown(key, doubleClick) if self.sel and self.sel ~= self.caret then self:ReplaceSel("") elseif self.caret <= #self.buf then - local len = 1 + -- Remove one whole character, which may be several bytes wide. + local len = (utf8.next(self.buf, self.caret, 1) or (#self.buf + 1)) - self.caret if IsKeyDown("CTRL") then + len = 1 while self.caret + len <= #self.buf and self.buf:sub(self.caret + len - 1, self.caret + len - 1):match("%s") and not self.buf:sub(self.caret + len, self.caret + len):match("\n") do len = len + 1 end