From 52952652de111d71e377ffd184990c1b5b9063e4 Mon Sep 17 00:00:00 2001 From: paxcut <53811119+paxcut@users.noreply.github.com> Date: Tue, 2 Sep 2025 15:30:50 -0700 Subject: [PATCH] Fixes for next release. (#2429) Attempt to fix WerWolv's strange off by one problem when using the mouse. Added a popup question for files that contain long lines (>1024 bytes). Also improved the handling of large lines, so it won't stall the app. May also contain other smaller issue fixes. --- plugins/builtin/romfs/lang/en_US.json | 1 + plugins/ui/include/ui/text_editor.hpp | 22 +++-- plugins/ui/source/ui/text_editor/editor.cpp | 64 +++++++------ plugins/ui/source/ui/text_editor/navigate.cpp | 12 +-- plugins/ui/source/ui/text_editor/render.cpp | 57 ++++++++++-- plugins/ui/source/ui/text_editor/support.cpp | 44 +++------ plugins/ui/source/ui/text_editor/utf8.cpp | 90 +++++++++---------- 7 files changed, 162 insertions(+), 128 deletions(-) diff --git a/plugins/builtin/romfs/lang/en_US.json b/plugins/builtin/romfs/lang/en_US.json index f345f9ca9..ab27b4c1d 100644 --- a/plugins/builtin/romfs/lang/en_US.json +++ b/plugins/builtin/romfs/lang/en_US.json @@ -1048,6 +1048,7 @@ "hex.builtin.view.pattern_editor.menu.edit.copy": "Copy", "hex.builtin.view.pattern_editor.shortcut.copy": "Copy Selection to the Clipboard", "hex.builtin.view.pattern_editor.shortcut.cut": "Copy Selection to the Clipboard and Delete it", + "hex.builtin.view.pattern_editor.warning_paste_large": "The clipboard contains a large amount of data. Are you sure you want to paste it?", "hex.builtin.view.pattern_editor.shortcut.paste": "Paste Clipboard Contents at the Cursor Position", "hex.builtin.view.pattern_editor.menu.edit.paste": "Paste", "hex.builtin.view.pattern_editor.menu.edit.undo": "Undo", diff --git a/plugins/ui/include/ui/text_editor.hpp b/plugins/ui/include/ui/text_editor.hpp index 66081e279..54032a3aa 100644 --- a/plugins/ui/include/ui/text_editor.hpp +++ b/plugins/ui/include/ui/text_editor.hpp @@ -324,16 +324,19 @@ namespace hex::ui { std::string m_colors; std::string m_flags; bool m_colorized = false; - i32 m_lineMaxColumn; + i32 m_lineTextSize; - Line() : m_chars(), m_colors(), m_flags(), m_colorized(false), m_lineMaxColumn(-1) {} + Line() : m_chars(), m_colors(), m_flags(), m_colorized(false), m_lineTextSize(-1) {} explicit Line(const char *line) { Line(std::string(line)); } explicit Line(const std::string &line) : - m_chars(line), m_colors(std::string(line.size(), 0x00)), m_flags(std::string(line.size(), 0x00)), m_colorized(false), m_lineMaxColumn(getMaxCharColumn()) {} - Line(const Line &line) : m_chars(line.m_chars), m_colors(line.m_colors), m_flags(line.m_flags), m_colorized(line.m_colorized), m_lineMaxColumn(line.m_lineMaxColumn) {} + m_chars(line), m_colors(std::string(line.size(), 0x00)), m_flags(std::string(line.size(), 0x00)), m_colorized(false), m_lineTextSize( + getLineTextSize()) {} + Line(const Line &line) : m_chars(line.m_chars), m_colors(line.m_colors), m_flags(line.m_flags), m_colorized(line.m_colorized), m_lineTextSize(line.m_lineTextSize) {} - i32 getCharacterColumn(i32 index) const; - i32 getMaxCharColumn() const; + i32 getCharColumn(i32 stringIndex) const; + i32 getColumnIndex(i32 column) const; + i32 getLineTextSize(); + i32 getStringTextSize(const std::string &str) const; LineIterator begin(); LineIterator end(); Line &operator=(const Line &line); @@ -500,7 +503,7 @@ namespace hex::ui { void drawText(Coordinates &lineStart, u64 i, u32 tokenLength, char color); void postRender(const char *title, ImVec2 position, float lineNo); ImVec2 calculateCharAdvance() const; - float textDistanceToLineStart(const Coordinates &from) const; + float textDistanceToLineStart(const Coordinates &from); // Highlighting public: void colorize(); @@ -529,6 +532,7 @@ namespace hex::ui { void copy(); void cut(); void paste(); + void doPaste(const char *clipText); void deleteChar(); void insertText(const std::string &value); void insertText(const char *value); @@ -621,9 +625,9 @@ namespace hex::ui { Coordinates lineCoordsToIndexCoords(const Coordinates &coordinates) const; i32 lineCoordinatesToIndex(const Coordinates &coordinates) const; Coordinates getCharacterCoordinates(i32 line, i32 index); - i32 getLineCharacterCount(i32 line); + i32 getLineCharColumn(i32 lineIndex, i32 stringIndex); u64 getLineByteCount(i32 line) const; - i32 getLineMaxColumn(i32 line); + i32 getLineMaxCharColumn(i32 lineIndex); public: FindReplaceHandler m_findReplaceHandler; diff --git a/plugins/ui/source/ui/text_editor/editor.cpp b/plugins/ui/source/ui/text_editor/editor.cpp index e20dc39f6..73b5d5c34 100644 --- a/plugins/ui/source/ui/text_editor/editor.cpp +++ b/plugins/ui/source/ui/text_editor/editor.cpp @@ -1,12 +1,10 @@ #include #include -#include #include #include #include -#include -#include #include +#include #define IMGUI_DEFINE_MATH_OPERATORS #include "imgui.h" @@ -227,6 +225,7 @@ namespace hex::ui { m_lines.resize(1); m_lines[0].clear(); } else { + m_lines.clear(); m_lines.resize(lineCount); u64 i = 0; for (auto line: vectorString) { @@ -276,7 +275,7 @@ namespace hex::ui { --end.m_line; if (end.m_line >= (i32) m_lines.size()) end.m_line = isEmpty() ? 0 : (i32) m_lines.size() - 1; - end.m_column = getLineMaxColumn(end.m_line); + end.m_column = getLineMaxCharColumn(end.m_line); u.m_removedSelection = Selection(start, end); u.m_removed = getText(u.m_removedSelection); @@ -530,7 +529,7 @@ namespace hex::ui { setCursorPosition(pos); auto &line = m_lines[pos.m_line]; - if (pos.m_column == getLineMaxColumn(pos.m_line)) { + if (pos.m_column == getLineMaxCharColumn(pos.m_line)) { if (pos.m_line == (i32) m_lines.size() - 1) return; @@ -589,7 +588,7 @@ namespace hex::ui { advance(u.m_removedSelection.m_end); auto &prevLine = m_lines[pos.m_line - 1]; - auto prevSize = getLineMaxColumn(pos.m_line - 1); + auto prevSize = getLineMaxCharColumn(pos.m_line - 1); if (prevSize == 0) prevLine = line; else @@ -684,34 +683,45 @@ namespace hex::ui { refreshSearchResults(); } + void TextEditor::doPaste(const char *clipText) { + UndoRecord u; + if (clipText != nullptr) { + auto clipTextStr = wolv::util::preprocessText(clipText); + + u.m_before = m_state; + + if (hasSelection()) { + u.m_removed = getSelectedText(); + u.m_removedSelection = m_state.m_selection; + deleteSelection(); + } + + u.m_added = clipTextStr; + u.m_addedSelection.m_start = setCoordinates(m_state.m_cursorPosition); + insertText(clipTextStr); + + u.m_addedSelection.m_end = setCoordinates(m_state.m_cursorPosition); + u.m_after = m_state; + addUndo(u); + } + refreshSearchResults(); + } + void TextEditor::paste() { if (m_readOnly) return; - auto clipText = ImGui::GetClipboardText(); + const char *clipText = ImGui::GetClipboardText(); if (clipText != nullptr) { - auto len = strlen(clipText); - if (len > 0) { - std::string text = wolv::util::preprocessText(clipText); - UndoRecord u; - u.m_before = m_state; - - if (hasSelection()) { - u.m_removed = getSelectedText(); - u.m_removedSelection = m_state.m_selection; - deleteSelection(); - } - - u.m_added = text; - u.m_addedSelection.m_start = setCoordinates(m_state.m_cursorPosition); - insertText(text); - - u.m_addedSelection.m_end = setCoordinates(m_state.m_cursorPosition); - u.m_after = m_state; - addUndo(u); + auto stringVector = wolv::util::splitString(clipText, "\n", false); + if (std::any_of(stringVector.begin(), stringVector.end(), [](const std::string &s) { return s.size() > 1024; })) { + ui::PopupQuestion::open("hex.builtin.view.pattern_editor.warning_paste_large"_lang, [this, clipText]() { + this->doPaste(clipText); + }, [] {}); + } else { + doPaste(clipText); } } - refreshSearchResults(); } bool TextEditor::canUndo() { diff --git a/plugins/ui/source/ui/text_editor/navigate.cpp b/plugins/ui/source/ui/text_editor/navigate.cpp index 15b8bf3d7..a2da8b89f 100644 --- a/plugins/ui/source/ui/text_editor/navigate.cpp +++ b/plugins/ui/source/ui/text_editor/navigate.cpp @@ -124,7 +124,7 @@ namespace hex::ui { return; auto lindex = m_state.m_cursorPosition.m_line; - auto lineMaxColumn = getLineMaxColumn(lindex); + auto lineMaxColumn = getLineMaxCharColumn(lindex); auto column = std::min(m_state.m_cursorPosition.m_column, lineMaxColumn); while (amount-- > 0) { @@ -167,7 +167,7 @@ namespace hex::ui { return; auto lindex = m_state.m_cursorPosition.m_line; - auto lineMaxColumn = getLineMaxColumn(lindex); + auto lineMaxColumn = getLineMaxCharColumn(lindex); auto column = std::min(m_state.m_cursorPosition.m_column, lineMaxColumn); while (amount-- > 0) { @@ -247,7 +247,7 @@ namespace hex::ui { else { postIdx = postfix.find_first_not_of(" "); if (postIdx == std::string::npos) - home = getLineMaxColumn(oldPos.m_line); + home = getLineMaxCharColumn(oldPos.m_line); else if (postIdx == 0) home = 0; else @@ -262,7 +262,7 @@ namespace hex::ui { else { postIdx = postfix.find_first_not_of(" "); if (postIdx == std::string::npos) - home = getLineMaxColumn(oldPos.m_line); + home = getLineMaxCharColumn(oldPos.m_line); else home = oldPos.m_column + postIdx; } @@ -288,7 +288,7 @@ namespace hex::ui { void TextEditor::moveEnd(bool select) { resetCursorBlinkTime(); auto oldPos = m_state.m_cursorPosition; - setCursorPosition(setCoordinates(m_state.m_cursorPosition.m_line, getLineMaxColumn(oldPos.m_line))); + setCursorPosition(setCoordinates(m_state.m_cursorPosition.m_line, getLineMaxCharColumn(oldPos.m_line))); if (m_state.m_cursorPosition != oldPos) { if (select) { @@ -339,7 +339,7 @@ namespace hex::ui { else result.m_line = std::clamp(line, 0, lineCount - 1); - auto maxColumn = getLineMaxColumn(result.m_line) + 1; + auto maxColumn = getLineMaxCharColumn(result.m_line) + 1; if (column < 0 && maxColumn + column >= 0) result.m_column = maxColumn + column; else diff --git a/plugins/ui/source/ui/text_editor/render.cpp b/plugins/ui/source/ui/text_editor/render.cpp index fbe55738c..549368f72 100644 --- a/plugins/ui/source/ui/text_editor/render.cpp +++ b/plugins/ui/source/ui/text_editor/render.cpp @@ -287,18 +287,52 @@ namespace hex::ui { continue; } auto colors = m_lines[lineNo].m_colors; - u64 colorsSize = std::min((u64)std::floor(textEditorSize.x / m_charAdvance.x), (u64) colors.size()); - u64 i = ImGui::GetScrollX() / m_charAdvance.x; - u64 maxI = i + colorsSize; + auto lineSize = line.getLineTextSize(); + i64 colorsSize = std::min((u64)textEditorSize.x, (u64) lineSize); + i64 start = ImGui::GetScrollX(); + i64 textSize = 0; + Coordinates head = Coordinates(lineNo, start / m_charAdvance.x); + textSize = textDistanceToLineStart(head); + auto maxColumn = line.getCharColumn(line.size()); + if (textSize < start) { + while (textSize < start && head.m_column < maxColumn) { + head.m_column += 1; + textSize = textDistanceToLineStart(head); + } + } else { + while (textSize > start && head.m_column > 0) { + head.m_column -= 1; + textSize = textDistanceToLineStart(head); + } + } + Coordinates current = Coordinates(lineNo, (start + colorsSize) / m_charAdvance.x); + textSize = textDistanceToLineStart(current); + if (textSize < start + colorsSize) { + while (textSize < start + colorsSize && current.m_column < maxColumn) { + current.m_column += 1; + textSize = textDistanceToLineStart(current); + } + } else { + while (textSize > start + colorsSize && current.m_column > 0) { + current.m_column -= 1; + textSize = textDistanceToLineStart(current); + } + } + + u64 i = line.getColumnIndex(head.m_column); + u64 maxI = line.getColumnIndex(current.m_column); while (i < maxI) { char color = std::clamp(colors[i], (char) PaletteIndex::Default, (char) ((u8) PaletteIndex::Max - 1)); auto index = colors.find_first_not_of(color, i); - index -= i; + if (index == std::string::npos) + index = maxI; + else + index -= i; u32 tokenLength = std::clamp((u64) index,(u64) 1, maxI - i); if (m_updateFocus) setFocus(); - auto lineStart = setCoordinates(lineNo, i); + auto lineStart = setCoordinates(lineNo, line.getCharColumn(i)); drawText(lineStart, i, tokenLength, color); @@ -571,10 +605,17 @@ namespace hex::ui { return ImVec2(fontSize, ImGui::GetTextLineHeightWithSpacing() * m_lineSpacing); } - float TextEditor::textDistanceToLineStart(const Coordinates &aFrom) const { + float TextEditor::textDistanceToLineStart(const Coordinates &aFrom) { auto &line = m_lines[aFrom.m_line]; i32 colIndex = lineCoordinatesToIndex(aFrom); - auto substr = line.m_chars.substr(0, colIndex); - return ImGui::GetFont()->CalcTextSizeA(ImGui::GetFontSize(), FLT_MAX, -1.0f, substr.c_str(), nullptr, nullptr).x; + auto substr1 = line.m_chars.substr(0, colIndex); + auto substr2 =line.m_chars.substr(colIndex, line.m_chars.size() - colIndex); + if (substr2.size() < substr1.size()) { + auto distanceToEnd = line.getStringTextSize(substr2.c_str()); + line.m_lineTextSize = line.getLineTextSize(); + return line.m_lineTextSize - distanceToEnd; + } + + return line.getStringTextSize(substr1.c_str()); } } \ No newline at end of file diff --git a/plugins/ui/source/ui/text_editor/support.cpp b/plugins/ui/source/ui/text_editor/support.cpp index 8f70e211a..676f88173 100644 --- a/plugins/ui/source/ui/text_editor/support.cpp +++ b/plugins/ui/source/ui/text_editor/support.cpp @@ -156,7 +156,7 @@ namespace hex::ui { m_colors = line.m_colors; m_flags = line.m_flags; m_colorized = line.m_colorized; - m_lineMaxColumn = line.m_lineMaxColumn; + m_lineTextSize = line.m_lineTextSize; return *this; } @@ -165,7 +165,7 @@ namespace hex::ui { m_colors = std::move(line.m_colors); m_flags = std::move(line.m_flags); m_colorized = line.m_colorized; - m_lineMaxColumn = line.m_lineMaxColumn; + m_lineTextSize = line.m_lineTextSize; return *this; } @@ -198,7 +198,7 @@ namespace hex::ui { m_colors.push_back(0x00); m_flags.push_back(0x00); m_colorized = false; - m_lineMaxColumn = -1; + m_lineTextSize = -1; } bool TextEditor::Line::empty() const { @@ -278,12 +278,7 @@ namespace hex::ui { void TextEditor::Line::append(LineIterator begin, LineIterator end) { if (begin.m_charsIter < end.m_charsIter) { m_chars.append(begin.m_charsIter, end.m_charsIter); - std::string charsAppended(begin.m_charsIter, end.m_charsIter); - - if (m_lineMaxColumn < 0) - m_lineMaxColumn = this->getMaxCharColumn(); - - m_lineMaxColumn += TextEditor::getStringCharacterCount(charsAppended); + m_lineTextSize = -1; } if (begin.m_colorsIter < end.m_colorsIter) m_colors.append(begin.m_colorsIter, end.m_colorsIter); @@ -317,12 +312,7 @@ namespace hex::ui { m_colors.insert(iter.m_colorsIter, beginLine.m_colorsIter, endLine.m_colorsIter); m_flags.insert(iter.m_flagsIter, beginLine.m_flagsIter, endLine.m_flagsIter); m_colorized = false; - std::string charsInserted(beginLine.m_charsIter, endLine.m_charsIter); - - if (m_lineMaxColumn < 0) - m_lineMaxColumn = this->getMaxCharColumn(); - - m_lineMaxColumn += TextEditor::getStringCharacterCount(charsInserted); + m_lineTextSize = -1; } } @@ -331,12 +321,7 @@ namespace hex::ui { m_colors.erase(begin.m_colorsIter); m_flags.erase(begin.m_flagsIter); m_colorized = false; - std::string charsErased(begin.m_charsIter, end().m_charsIter); - - if (m_lineMaxColumn < 0) - m_lineMaxColumn = this->getMaxCharColumn(); - - m_lineMaxColumn -= TextEditor::getStringCharacterCount(charsErased); + m_lineTextSize = -1; } void TextEditor::Line::erase(LineIterator begin, u64 count) { @@ -346,12 +331,7 @@ namespace hex::ui { m_colors.erase(begin.m_colorsIter, begin.m_colorsIter + count); m_flags.erase(begin.m_flagsIter, begin.m_flagsIter + count); m_colorized = false; - std::string charsErased(begin.m_charsIter, begin.m_charsIter + count); - - if (m_lineMaxColumn < 0) - m_lineMaxColumn = this->getMaxCharColumn(); - - m_lineMaxColumn -= TextEditor::getStringCharacterCount(charsErased); + m_lineTextSize = -1; } void TextEditor::Line::erase(u64 start, u64 length) { @@ -374,7 +354,7 @@ namespace hex::ui { m_colors.clear(); m_flags.clear(); m_colorized = false; - m_lineMaxColumn = 0; + m_lineTextSize = -1; } void TextEditor::Line::setLine(const std::string &text) { @@ -382,7 +362,7 @@ namespace hex::ui { m_colors = std::string(text.size(), 0x00); m_flags = std::string(text.size(), 0x00); m_colorized = false; - m_lineMaxColumn = -1; + m_lineTextSize = -1; } void TextEditor::Line::setLine(const Line &text) { @@ -390,7 +370,7 @@ namespace hex::ui { m_colors = text.m_colors; m_flags = text.m_flags; m_colorized = text.m_colorized; - m_lineMaxColumn = text.m_lineMaxColumn; + m_lineTextSize = text.m_lineTextSize; } bool TextEditor::Line::needsUpdate() const { @@ -520,7 +500,7 @@ namespace hex::ui { m_state.m_cursorPosition = screenPosToCoordinates(ImGui::GetMousePos()); auto line = m_state.m_cursorPosition.m_line; m_state.m_selection.m_start = setCoordinates(line, 0); - m_state.m_selection.m_end = setCoordinates(line, getLineMaxColumn(line)); + m_state.m_selection.m_end = setCoordinates(line, getLineMaxCharColumn(line)); } m_lastClick = -1.0f; @@ -824,7 +804,7 @@ namespace hex::ui { editor->m_state.m_cursorPosition = editor->m_state.m_selection.m_start; if (editor->isStartOfLine()) { editor->m_state.m_cursorPosition.m_line--; - editor->m_state.m_cursorPosition.m_column = editor->getLineMaxColumn(editor->m_state.m_cursorPosition.m_line); + editor->m_state.m_cursorPosition.m_column = editor->getLineMaxCharColumn(editor->m_state.m_cursorPosition.m_line); } else editor->m_state.m_cursorPosition.m_column--; } diff --git a/plugins/ui/source/ui/text_editor/utf8.cpp b/plugins/ui/source/ui/text_editor/utf8.cpp index 7235fb83a..6bfc74767 100644 --- a/plugins/ui/source/ui/text_editor/utf8.cpp +++ b/plugins/ui/source/ui/text_editor/utf8.cpp @@ -1,7 +1,37 @@ #include +#include #include namespace hex::ui { + + i32 TextEditor::Line::getColumnIndex(i32 column) const { + + i32 idx = 0; + for (i32 col = 0; idx < (i32) size() && col < column; ++col) + idx += TextEditor::utf8CharLength(m_chars[idx]); + + return idx; + } + + i32 TextEditor::Line::getCharColumn(i32 stringIndex) const { + i32 limit = std::max(0, std::min(stringIndex, (i32) size())); + + i32 col = 0; + for (i32 idx = 0; idx < limit; col++) + idx += TextEditor::utf8CharLength(m_chars[idx]); + + return col; + } + + i32 TextEditor::Line::getStringTextSize(const std::string &str) const { + return ImGui::GetFont()->CalcTextSizeA(ImGui::GetFontSize(), FLT_MAX, -1.0f, str.c_str(), nullptr, nullptr).x; + } + + i32 TextEditor::Line::getLineTextSize() { + m_lineTextSize = getStringTextSize(m_chars); + return m_lineTextSize; + } + // https://en.wikipedia.org/wiki/UTF-8 // We assume that the char is a standalone character (<128) or a leading byte of an UTF-8 code sequence (non-10xxxxxx code) i32 TextEditor::utf8CharLength(u8 c) { @@ -27,20 +57,18 @@ namespace hex::ui { return count; } - i32 TextEditor::getLineCharacterCount(i32 lineIndex) { + i32 TextEditor::getLineCharColumn(i32 lineIndex, i32 stringIndex) { if (lineIndex >= (i64) m_lines.size() || lineIndex < 0) return 0; Line &line = m_lines[lineIndex]; - if (line.m_lineMaxColumn != -1) - return line.m_lineMaxColumn; - else { - auto str = line.m_chars; - i32 count = 0; - for (u32 idx = 0; idx < str.size(); count++) - idx += TextEditor::utf8CharLength(str[idx]); - line.m_lineMaxColumn = count; - return count; - } + return line.getCharColumn(stringIndex); + } + + i32 TextEditor::getLineMaxCharColumn(i32 lineIndex) { + if (lineIndex >= (i64) m_lines.size() || lineIndex < 0) + return 0; + Line &line = m_lines[lineIndex]; + return line.getCharColumn(line.size()); } // "Borrowed" from ImGui source @@ -83,24 +111,13 @@ namespace hex::ui { return size; } - static i32 utf8CharCount(const std::string &line, i32 start, i32 numChars) { - if (line.empty()) - return 0; - - i32 index = 0; - for (i32 column = 0; start + index < (i32) line.size() && column < numChars; ++column) - index += TextEditor::utf8CharLength(line[start + index]); - - return index; - } - TextEditor::Coordinates TextEditor::screenPosToCoordinates(const ImVec2 &position) { ImVec2 local = position - ImGui::GetCursorScreenPos(); i32 lineNo = std::max(0, (i32) floor(local.y / m_charAdvance.y)); - if (local.x < (m_leftMargin - 2) || lineNo >= (i32) m_lines.size() || m_lines[lineNo].empty()) + if (local.x < (m_leftMargin - 2_scaled) || lineNo >= (i32) m_lines.size() || m_lines[lineNo].empty()) return setCoordinates(std::min(lineNo, (i32) m_lines.size() - 1), 0); std::string line = m_lines[lineNo].m_chars; - local.x -= (m_leftMargin - 5); + local.x -= (m_leftMargin - 5_scaled); i32 count = 0; u64 length; i32 increase; @@ -123,7 +140,7 @@ namespace hex::ui { return Invalid; const auto &line = m_lines[coordinates.m_line]; - return Coordinates(coordinates.m_line,utf8CharCount(line.m_chars, 0, coordinates.m_column)); + return Coordinates(coordinates.m_line,line.getColumnIndex(coordinates.m_column)); } i32 TextEditor::lineCoordinatesToIndex(const Coordinates &coordinates) const { @@ -131,29 +148,14 @@ namespace hex::ui { return -1; const auto &line = m_lines[coordinates.m_line]; - return utf8CharCount(line.m_chars, 0, coordinates.m_column); - } - - i32 TextEditor::Line::getCharacterColumn(i32 index) const { - i32 col = 0; - i32 i = 0; - while (i < index && i < (i32) size()) { - auto c = m_chars[i]; - i += TextEditor::utf8CharLength(c); - col++; - } - return col; - } - - i32 TextEditor::Line::getMaxCharColumn() const { - return getCharacterColumn(size()); + return line.getColumnIndex(coordinates.m_column); } TextEditor::Coordinates TextEditor::getCharacterCoordinates(i32 lineIndex, i32 strIndex) { if (lineIndex < 0 || lineIndex >= (i32) m_lines.size()) return Coordinates(0, 0); auto &line = m_lines[lineIndex]; - return setCoordinates(lineIndex, line.getCharacterColumn(strIndex)); + return setCoordinates(lineIndex, line.getCharColumn(strIndex)); } u64 TextEditor::getLineByteCount(i32 lineIndex) const { @@ -164,10 +166,6 @@ namespace hex::ui { return line.size(); } - i32 TextEditor::getLineMaxColumn(i32 lineIndex) { - return getLineCharacterCount(lineIndex); - } - TextEditor::Coordinates TextEditor::stringIndexToCoordinates(i32 strIndex, const std::string &input) { if (strIndex < 0 || strIndex > (i32) input.size()) return TextEditor::Coordinates(0, 0);