From 4333b8c35149d6787b26efecb8d97a2be1f4a3e3 Mon Sep 17 00:00:00 2001 From: paxcut <53811119+paxcut@users.noreply.github.com> Date: Sun, 24 Nov 2024 03:31:06 -0700 Subject: [PATCH] fix: Text cursor not moving to the correct location with ctrl+c -> ctrl+v (#1951) This code fixes issue #1950 This PR depends on PR [#27 ](https://github.com/WerWolv/libwolv/pull/27) on libwolv repo ### Problem description See description of the problem on the issue linked above ### Implementation description The code in the PR uses function added to the libwolv repository to remove tabs if they exist on the provider. Additionally, any pasted tab on the pattern editor will be translated to spaces automatically. This code was tested successfully using the pattern posted in the issue. --- .../ColorTextEditor/source/TextEditor.cpp | 12 ++++++++++++ .../content/views/view_pattern_editor.hpp | 2 ++ .../content/views/view_pattern_editor.cpp | 18 ++++++++++++++---- 3 files changed, 28 insertions(+), 4 deletions(-) diff --git a/lib/third_party/imgui/ColorTextEditor/source/TextEditor.cpp b/lib/third_party/imgui/ColorTextEditor/source/TextEditor.cpp index f41129506..0c0da39df 100644 --- a/lib/third_party/imgui/ColorTextEditor/source/TextEditor.cpp +++ b/lib/third_party/imgui/ColorTextEditor/source/TextEditor.cpp @@ -247,6 +247,18 @@ int TextEditor::InsertTextAt(Coordinates & /* inout */ aWhere, const char *aValu if (*aValue == '\r') { // skip ++aValue; + } else if (*aValue == '\t') { + auto &line = mLines[aWhere.mLine]; + auto c = GetCharacterColumn(aWhere.mLine, cindex); + auto r = c % mTabSize; + auto d = mTabSize - r; + auto i = d; + while (i-- > 0) + line.insert(line.begin() + cindex++, Glyph(' ', PaletteIndex::Default)); + + cindex += d; + aWhere.mColumn += d; + aValue++; } else if (*aValue == '\n') { if (cindex < (int)mLines[aWhere.mLine].size()) { auto &newLine = InsertLine(aWhere.mLine + 1); diff --git a/plugins/builtin/include/content/views/view_pattern_editor.hpp b/plugins/builtin/include/content/views/view_pattern_editor.hpp index c7dfeb4d2..29f9497b4 100644 --- a/plugins/builtin/include/content/views/view_pattern_editor.hpp +++ b/plugins/builtin/include/content/views/view_pattern_editor.hpp @@ -73,6 +73,8 @@ namespace hex::plugin::builtin { } public: + std::string preprocessText(const std::string &code); + struct VirtualFile { std::fs::path path; std::vector data; diff --git a/plugins/builtin/source/content/views/view_pattern_editor.cpp b/plugins/builtin/source/content/views/view_pattern_editor.cpp index a1e31abf4..006b9c62d 100644 --- a/plugins/builtin/source/content/views/view_pattern_editor.cpp +++ b/plugins/builtin/source/content/views/view_pattern_editor.cpp @@ -1662,7 +1662,7 @@ namespace hex::plugin::builtin { void ViewPatternEditor::loadPatternFile(const std::fs::path &path, prv::Provider *provider) { wolv::io::File file(path, wolv::io::File::Mode::Read); if (file.isValid()) { - auto code = file.readString(); + auto code = preprocessText(file.readString()); this->evaluatePattern(code, provider); m_textEditor.SetText(code); @@ -1826,6 +1826,15 @@ namespace hex::plugin::builtin { }); } + std::string ViewPatternEditor::preprocessText(const std::string &code) { + std::string result = wolv::util::replaceStrings(code, "\r\n", "\n"); + result = wolv::util::replaceStrings(result, "\r", "\n"); + result = wolv::util::replaceTabsWithSpaces(result, 4); + while (result.ends_with('\n')) + result.pop_back(); + return result; + } + void ViewPatternEditor::registerEvents() { RequestPatternEditorSelectionChange::subscribe(this, [this](u32 line, u32 column) { if (line == 0) @@ -1849,8 +1858,9 @@ namespace hex::plugin::builtin { }); RequestSetPatternLanguageCode::subscribe(this, [this](const std::string &code) { - m_textEditor.SetText(code); - m_sourceCode.set(ImHexApi::Provider::get(), code); + const std::string preprocessed = preprocessText(code); + m_textEditor.SetText(preprocessed); + m_sourceCode.set(ImHexApi::Provider::get(), preprocessed); m_hasUnevaluatedChanges = true; }); @@ -2109,7 +2119,7 @@ namespace hex::plugin::builtin { .basePath = "pattern_source_code.hexpat", .required = false, .load = [this](prv::Provider *provider, const std::fs::path &basePath, const Tar &tar) { - const auto sourceCode = tar.readString(basePath); + const auto sourceCode = preprocessText(tar.readString(basePath)); m_sourceCode.set(provider, sourceCode);