diff --git a/plugins/builtin/source/content/views/view_pattern_editor.cpp b/plugins/builtin/source/content/views/view_pattern_editor.cpp index 0ed8301f4b629..c704044900063 100644 --- a/plugins/builtin/source/content/views/view_pattern_editor.cpp +++ b/plugins/builtin/source/content/views/view_pattern_editor.cpp @@ -1500,13 +1500,13 @@ namespace hex::plugin::builtin { } return false; }); + m_runningParsers += 1; TaskManager::createBackgroundTask("hex.builtin.task.parsing_pattern", [this, code = std::move(code), provider](auto &){ this->parsePattern(code, provider); if (m_runAutomatically) m_triggerAutoEvaluate = true; }); - m_runningParsers += 1; m_hasUnevaluatedChanges.get(provider) = false; } @@ -1526,8 +1526,8 @@ namespace hex::plugin::builtin { m_identifierHighlighter.get(provider).updateRequiredInputs(); if (restoreInterruptState) interrupt(); - TaskManager::createBackgroundTask("hex.builtin.task.highlighting_pattern", [this,provider](auto &) { m_identifierHighlighter.get(provider).highlightSourceCode(); }); m_runningHighlighters += 1; + TaskManager::createBackgroundTask("hex.builtin.task.highlighting_pattern", [this,provider](auto &) { m_identifierHighlighter.get(provider).highlightSourceCode(); }); } else if (m_changesWereColored && !m_allStepsCompleted) { m_identifierHighlighter.get(provider).setRequestedIdentifierColors(m_colorizeIdentifiers); m_textEditor.get(provider).getLines().setAllCodeFolds(); @@ -1712,6 +1712,7 @@ namespace hex::plugin::builtin { } return false; }); + m_runningParsers += 1; TaskManager::createBackgroundTask("hex.builtin.task.parsing_pattern", [this, code, provider](auto&) { this->parsePattern(code, provider); }); } } @@ -1755,7 +1756,8 @@ namespace hex::plugin::builtin { m_changesWereParsed = true; m_changesWereColored = false; m_allStepsCompleted = false; - m_runningParsers -= 1; + if (m_runningParsers != 0) + m_runningParsers -= 1; } void ViewPatternEditor::evaluatePattern(const std::string &code, prv::Provider *provider) { diff --git a/plugins/ui/include/ui/text_editor.hpp b/plugins/ui/include/ui/text_editor.hpp index 5a11f90e0531b..64e35c16c78b1 100644 --- a/plugins/ui/include/ui/text_editor.hpp +++ b/plugins/ui/include/ui/text_editor.hpp @@ -676,6 +676,9 @@ namespace hex::ui { Keys getDeactivatedBlocks(); std::string getSelectedText(); void deleteSelection(); + void selectUsingEnd(bool select, const Coordinates &oldPos); + void selectUsingStart(bool select, const Coordinates &oldPos); + void resetInteractiveSelection(); void setTextChanged(bool value) { m_textChanged = value; } bool isTextChanged() { return m_textChanged; } void setLanguageDefinition(const LanguageDefinition &aLanguageDef); @@ -723,6 +726,7 @@ namespace hex::ui { float textDistanceToLineStart(const Coordinates &from); std::string getText(bool addHiddenLines = false); void setCursorPosition(); + void setEditorState(const Coordinates &coordinates, bool setInteractiveStart = true); void ensureSelectionNotFolded(); bool hasSelection(); i32 insertTextAtCursor(const std::string &value); @@ -1003,6 +1007,7 @@ namespace hex::ui { void setSelection(const Range &selection); Range getSelection() const; void selectWordUnderCursor(); + void selectLineUnderCursor(); void selectAll(); bool hasSelection() { return m_lines.hasSelection(); } std::string getSelectedText() { return m_lines.getSelectedText(); } diff --git a/plugins/ui/source/ui/text_editor/codeFolder.cpp b/plugins/ui/source/ui/text_editor/codeFolder.cpp index a61b245fd2884..60eac51e27018 100644 --- a/plugins/ui/source/ui/text_editor/codeFolder.cpp +++ b/plugins/ui/source/ui/text_editor/codeFolder.cpp @@ -14,8 +14,10 @@ namespace hex::ui { using Coordinates = TextEditor::Coordinates; using RangeFromCoordinates = TextEditor::RangeFromCoordinates; using CodeFoldState = TextEditor::CodeFoldState; + using Lines = TextEditor::Lines; + using CodeFoldBlocks = TextEditor::CodeFoldBlocks; - void TextEditor::Lines::skipAttribute() { + void Lines::skipAttribute() { if (sequence(tkn::Separator::LeftBracket, tkn::Separator::LeftBracket)) { while (!sequence(tkn::Separator::RightBracket, tkn::Separator::RightBracket)) @@ -23,7 +25,7 @@ namespace hex::ui { } } - Interval TextEditor::Lines::findBlockInRange(Interval interval) { + Interval Lines::findBlockInRange(Interval interval) { Interval result = NotValid; auto tokenStart = SafeTokenIterator(m_tokens.begin(), m_tokens.end()); @@ -98,7 +100,7 @@ namespace hex::ui { return NotValid; } - Coordinates TextEditor::Lines::findCommentEndCoord(i32 tokenId) { + Coordinates Lines::findCommentEndCoord(i32 tokenId) { Coordinates result = Invalid; auto save = m_curr; m_curr = SafeTokenIterator(m_tokens.begin(), m_tokens.end()) + tokenId; @@ -135,7 +137,7 @@ namespace hex::ui { } //comments imports and includes - void TextEditor::Lines::nonDelimitedFolds() { + void Lines::nonDelimitedFolds() { auto size = m_tokens.size(); if (size > 0) { Interval block = {0,static_cast(size-1)}; @@ -162,7 +164,7 @@ namespace hex::ui { } } - RangeFromCoordinates TextEditor::Lines::getDelimiterLineNumbers(i32 start, i32 end, const std::string &delimiters) { + RangeFromCoordinates Lines::getDelimiterLineNumbers(i32 start, i32 end, const std::string &delimiters) { RangeFromCoordinates result = {Invalid, Invalid}; Coordinates first = Invalid; auto tokenStart = SafeTokenIterator(m_tokens.begin(), m_tokens.end()); @@ -240,7 +242,7 @@ namespace hex::ui { return result; } - void TextEditor::Lines::advanceToNextLine(i32 &lineIndex, i32 ¤tTokenId, Location &location) { + void Lines::advanceToNextLine(i32 &lineIndex, i32 ¤tTokenId, Location &location) { i32 tempLineIndex; if (tempLineIndex = nextLineIndex(lineIndex); lineIndex == tempLineIndex) { lineIndex++; @@ -254,14 +256,14 @@ namespace hex::ui { location = m_curr->location; } - void TextEditor::Lines::incrementTokenId(i32 &lineIndex, i32 ¤tTokenId, Location &location) { + void Lines::incrementTokenId(i32 &lineIndex, i32 ¤tTokenId, Location &location) { currentTokenId++; m_curr = m_startToken + currentTokenId; location = m_curr->location; lineIndex = location.line - 1; } - void TextEditor::Lines::moveToStringIndex(i32 stringIndex, i32 ¤tTokenId, Location &location) { + void Lines::moveToStringIndex(i32 stringIndex, i32 ¤tTokenId, Location &location) { auto curr = m_curr; i32 tempTokenId; auto &line = operator[](location.line - 1); @@ -280,13 +282,13 @@ namespace hex::ui { } - void TextEditor::Lines::resetToTokenId(i32 &lineIndex, i32 ¤tTokenId, Location &location) { + void Lines::resetToTokenId(i32 &lineIndex, i32 ¤tTokenId, Location &location) { m_curr = m_startToken + currentTokenId; location = m_curr->location; lineIndex = location.line - 1; } - i32 TextEditor::Lines::findNextDelimiter(bool openOnly) { + i32 Lines::findNextDelimiter(bool openOnly) { while (!peek(tkn::Separator::EndOfProgram)) { if (peek(tkn::Separator::LeftBrace) || peek(tkn::Separator::LeftBracket) || peek(tkn::Separator::LeftParenthesis) || peek(tkn::Operator::BoolLessThan)) @@ -300,7 +302,7 @@ namespace hex::ui { return getTokenId(); } - TextEditor::CodeFoldBlocks TextEditor::Lines::foldPointsFromSource() { + CodeFoldBlocks Lines::foldPointsFromSource() { auto code = getText(); if (code.empty()) return m_foldPoints; @@ -380,7 +382,7 @@ namespace hex::ui { } - std::pair TextEditor::Lines::findMatchingDelimiter(i32 from) { + std::pair Lines::findMatchingDelimiter(i32 from) { std::string blockDelimiters = "{}[]()<>"; std::pair result = std::make_pair(-1, '\0'); auto tokenStart = SafeTokenIterator(m_tokens.begin(), m_tokens.end()); @@ -466,7 +468,7 @@ namespace hex::ui { m_lines.saveCodeFoldStates(); } - void TextEditor::Lines::saveCodeFoldStates() { + void Lines::saveCodeFoldStates() { i32 codeFoldIndex = 0; Indices closedFoldIncrements; for (auto key: m_codeFoldKeys) { @@ -494,22 +496,22 @@ namespace hex::ui { m_lines.applyCodeFoldStates(); } - void TextEditor::Lines::setCodeFoldState(CodeFoldState state) { + void Lines::setCodeFoldState(CodeFoldState state) { m_codeFoldState = state; saveCodeFoldStates(); } - CodeFoldState TextEditor::Lines::getCodeFoldState() const { + CodeFoldState Lines::getCodeFoldState() const { return m_codeFoldState; } - void TextEditor::Lines::resetCodeFoldStates() { + void Lines::resetCodeFoldStates() { m_codeFoldState.clear(); for (auto key: m_codeFoldKeys) m_codeFoldState[key] = true; } - void TextEditor::Lines::applyCodeFoldStates() { + void Lines::applyCodeFoldStates() { std::string commentLine; for (const auto& line: m_hiddenLines) { @@ -552,7 +554,7 @@ namespace hex::ui { } } - void TextEditor::Lines::closeCodeFold(const Range &key, bool userTriggered) { + void Lines::closeCodeFold(const Range &key, bool userTriggered) { float topRow = 0.0f; if (userTriggered) { @@ -684,7 +686,7 @@ namespace hex::ui { m_foldedLines[currentFoldedLine.m_row].loadSegments(); } - void TextEditor::Lines::openCodeFold(const Range &key) { + void Lines::openCodeFold(const Range &key) { for (const auto& foldedLine : m_foldedLines) { for (auto foldKey : foldedLine.second.m_keys) { if (foldKey.contains(key) && foldKey != key) { @@ -754,11 +756,11 @@ namespace hex::ui { } template - T *TextEditor::Lines::getValue(const i32 index) { + T *Lines::getValue(const i32 index) { return const_cast(std::get_if(&m_curr[index].value)); } - void TextEditor::Lines::next(i32 count) { + void Lines::next(i32 count) { if (count == 0) return; i32 id = getTokenId(); @@ -771,32 +773,32 @@ namespace hex::ui { } enum : u32 { Normal = 0, Not = 1 }; - bool TextEditor::Lines::begin() { + bool Lines::begin() { m_originalPosition = m_curr; return true; } - void TextEditor::Lines::partBegin() { + void Lines::partBegin() { m_partOriginalPosition = m_curr; } - void TextEditor::Lines::reset() { + void Lines::reset() { m_curr = m_originalPosition; } - void TextEditor::Lines::partReset() { + void Lines::partReset() { m_curr = m_partOriginalPosition; } - bool TextEditor::Lines::resetIfFailed(const bool value) { + bool Lines::resetIfFailed(const bool value) { if (!value) reset(); return value; } template - bool TextEditor::Lines::sequenceImpl() { + bool Lines::sequenceImpl() { if constexpr (S == Normal) return true; else if constexpr (S == Not) @@ -806,7 +808,7 @@ namespace hex::ui { } template - bool TextEditor::Lines::matchOne(const Token &token) { + bool Lines::matchOne(const Token &token) { if constexpr (S == Normal) { if (!peek(token)) { partReset(); @@ -827,19 +829,19 @@ namespace hex::ui { } template - bool TextEditor::Lines::sequenceImpl(const auto &... args) { + bool Lines::sequenceImpl(const auto &... args) { return (matchOne(args) && ...); } template - bool TextEditor::Lines::sequence(const Token &token, const auto &... args) { + bool Lines::sequence(const Token &token, const auto &... args) { partBegin(); return sequenceImpl(token, args...); } - bool TextEditor::Lines::isValid() { + bool Lines::isValid() { Token token; try { token = m_curr[0]; @@ -853,7 +855,7 @@ namespace hex::ui { return isLocationValid(token.location); } - bool TextEditor::Lines::peek(const Token &token, const i32 index) { + bool Lines::peek(const Token &token, const i32 index) { if (!isValid()) return false; i32 id = getTokenId(); diff --git a/plugins/ui/source/ui/text_editor/editor.cpp b/plugins/ui/source/ui/text_editor/editor.cpp index 13a16291892be..d0322865ae76b 100644 --- a/plugins/ui/source/ui/text_editor/editor.cpp +++ b/plugins/ui/source/ui/text_editor/editor.cpp @@ -11,11 +11,16 @@ #include "imgui.h" namespace hex::ui { - using StringVector = TextEditor::StringVector; - using Range = TextEditor::Range; - using EditorState = TextEditor::EditorState; + using StringVector = TextEditor::StringVector; + using Range = TextEditor::Range; + using EditorState = TextEditor::EditorState; + using FindReplaceHandler = TextEditor::FindReplaceHandler; + using Lines = TextEditor::Lines; + using Line = TextEditor::Line; + using UndoRecord = TextEditor::UndoRecord; + using UndoAction = TextEditor::UndoAction; - TextEditor::FindReplaceHandler::FindReplaceHandler() : m_matchCase(false), m_wholeWord(false), m_findRegEx(false), m_optionsChanged(false) {} + FindReplaceHandler::FindReplaceHandler() : m_matchCase(false), m_wholeWord(false), m_findRegEx(false), m_optionsChanged(false) {} TextEditor::TextEditor() { m_lines.m_startTime = ImGui::GetTime() * 1000; @@ -30,7 +35,7 @@ namespace hex::ui { TextEditor::~TextEditor() = default; - std::string TextEditor::Lines::getRange(const Range &rangeToGet) { + std::string Lines::getRange(const Range &rangeToGet) { std::string result; auto selection = lineCoordinates(const_cast(rangeToGet)); selection.m_end = rangeToGet.m_end; @@ -52,7 +57,7 @@ namespace hex::ui { return result; } - void TextEditor::Lines::deleteRange(const Range &rangeToDelete) { + void Lines::deleteRange(const Range &rangeToDelete) { if (m_readOnly) return; Range selection = lineCoordinates(const_cast(rangeToDelete)); @@ -81,18 +86,19 @@ namespace hex::ui { m_textChanged = true; } - void TextEditor::Lines::appendLine(const std::string &value) { + void Lines::appendLine(const std::string &value) { auto text = wolv::util::replaceStrings(wolv::util::preprocessText(value), "\000", "."); if (text.empty()) return; + auto maxColumn = stringCharacterCount(text); if (isEmpty()) { m_unfoldedLines[0].m_chars = text; m_unfoldedLines[0].m_colors = std::string(text.size(), 0); m_unfoldedLines[0].m_flags = std::string(text.size(), 0); + m_unfoldedLines[0].m_lineMaxColumn = maxColumn; } else { m_unfoldedLines.emplace_back(text); - auto line = m_unfoldedLines.back(); - line.m_lineMaxColumn = line.maxColumn(); + m_unfoldedLines.back().m_lineMaxColumn = maxColumn; } m_unfoldedLines.back().m_colorized = false; } @@ -105,7 +111,7 @@ namespace hex::ui { m_lines.m_textChanged = true; } - i32 TextEditor::Lines::insertTextAtCursor(const std::string &value) { + i32 Lines::insertTextAtCursor(const std::string &value) { if (value.empty()) return 0; auto start = lineCoordinates(m_state.m_cursorPosition); @@ -131,7 +137,7 @@ namespace hex::ui { return lineCount; } - i32 TextEditor::Lines::insertTextAt(Coordinates /* inout */ &where, const std::string &value) { + i32 Lines::insertTextAt(Coordinates /* inout */ &where, const std::string &value) { if (value.empty()) return 0; auto start = lineCoordinates(where); @@ -167,7 +173,7 @@ namespace hex::ui { backspace(); } - void TextEditor::Lines::removeLines(i32 lineStart, i32 lineEnd) { + void Lines::removeLines(i32 lineStart, i32 lineEnd) { ErrorMarkers errorMarkers; for (auto &errorMarker : m_errorMarkers) { if (errorMarker.first.m_line <= lineStart || errorMarker.first.m_line > lineEnd + 1) { @@ -237,11 +243,11 @@ namespace hex::ui { m_globalRowMaxChanged = true; } - void TextEditor::Lines::removeLine(i32 index) { + void Lines::removeLine(i32 index) { removeLines(index, index); } - void TextEditor::Lines::insertLine(i32 index, const std::string &text) { + void Lines::insertLine(i32 index, const std::string &text) { if (index < 0 || index > size()) return; auto &line = insertLine(index); @@ -250,7 +256,7 @@ namespace hex::ui { m_textChanged = true; } - TextEditor::Line &TextEditor::Lines::insertLine(i32 index) { + Line &Lines::insertLine(i32 index) { m_globalRowMaxChanged = true; if (isEmpty()) return *m_unfoldedLines.insert(m_unfoldedLines.begin(), Line()); @@ -258,7 +264,7 @@ namespace hex::ui { if (index == size()) return *m_unfoldedLines.insert(m_unfoldedLines.end(), Line()); - TextEditor::Line &result = *m_unfoldedLines.insert(m_unfoldedLines.begin() + index, Line()); + Line &result = *m_unfoldedLines.insert(m_unfoldedLines.begin() + index, Line()); result.m_colorized = false; @@ -334,11 +340,12 @@ namespace hex::ui { m_lines.m_unfoldedLines.resize(lineCount); for (const auto &line: vectorString) { + auto maxColumn = stringCharacterCount(line); auto &unfoldedLine = m_lines.m_unfoldedLines[i]; unfoldedLine.setLine(line); unfoldedLine.m_colorized = false; - unfoldedLine.m_lineMaxColumn = unfoldedLine.maxColumn(); + unfoldedLine.m_lineMaxColumn = maxColumn; i++; } } @@ -597,7 +604,7 @@ namespace hex::ui { m_lines.ensureCursorVisible(); } - void TextEditor::Lines::refreshSearchResults() { + void Lines::refreshSearchResults() { std::string findWord = m_findReplaceHandler.getFindWord(); if (!findWord.empty()) { m_findReplaceHandler.resetMatches(); @@ -605,11 +612,11 @@ namespace hex::ui { } } - void TextEditor::Lines::insertText(const std::string &value) { + void Lines::insertText(const std::string &value) { insertText(value.c_str()); } - void TextEditor::Lines::insertText(const char *value) { + void Lines::insertText(const char *value) { if (value == nullptr) return; @@ -619,14 +626,16 @@ namespace hex::ui { colorize(); } - void TextEditor::Lines::deleteSelection() { + void Lines::deleteSelection() { if (m_state.m_selection.m_end == m_state.m_selection.m_start) return; + m_interactiveSelection = m_state.m_selection; - deleteRange(m_state.m_selection); + deleteRange(m_interactiveSelection); + m_interactiveSelection.m_end = m_interactiveSelection.m_start; - setSelection(Range(m_state.m_selection.m_start, m_state.m_selection.m_start)); + setSelection(m_interactiveSelection); setCursorPosition(m_state.m_selection.m_start, false); refreshSearchResults(); colorize(); @@ -881,7 +890,7 @@ namespace hex::ui { m_lines.refreshSearchResults(); } - std::string TextEditor::Lines::getText(bool includeHiddenLines) { + std::string Lines::getText(bool includeHiddenLines) { auto start = lineCoordinates(0, 0); auto size = m_unfoldedLines.size(); auto line = m_unfoldedLines[size - 1]; @@ -911,7 +920,7 @@ namespace hex::ui { return result; } - std::string TextEditor::Lines::getSelectedText() { + std::string Lines::getSelectedText() { return getRange(m_state.m_selection); } @@ -923,7 +932,7 @@ namespace hex::ui { return m_lines.getRange(Range(sanitizedLine, endLine)); } - TextEditor::UndoRecord::UndoRecord( + UndoRecord::UndoRecord( std::string added, Range addedRange, std::string removed, @@ -931,7 +940,7 @@ namespace hex::ui { EditorState before, EditorState after) : m_added(std::move(added)), m_addedRange(addedRange), m_removed(std::move(removed)), m_removedRange(removedRange), m_before(std::move(before)), m_after(std::move(after)) {} - void TextEditor::UndoRecord::undo(TextEditor *editor) { + void UndoRecord::undo(TextEditor *editor) { if (!m_added.empty()) { editor->m_lines.deleteRange(m_addedRange); editor->m_lines.colorize(); @@ -947,7 +956,7 @@ namespace hex::ui { editor->m_lines.ensureCursorVisible(); } - void TextEditor::UndoRecord::redo(TextEditor *editor) { + void UndoRecord::redo(TextEditor *editor) { if (!m_removed.empty()) { editor->m_lines.deleteRange(m_removedRange); editor->m_lines.colorize(); @@ -963,12 +972,12 @@ namespace hex::ui { editor->m_lines.ensureCursorVisible(); } - void TextEditor::UndoAction::undo(TextEditor *editor) { + void UndoAction::undo(TextEditor *editor) { for (auto &record : m_records | std::views::reverse) record.undo(editor); } - void TextEditor::UndoAction::redo(TextEditor *editor) { + void UndoAction::redo(TextEditor *editor) { for (auto &record : m_records) record.redo(editor); } diff --git a/plugins/ui/source/ui/text_editor/highlighter.cpp b/plugins/ui/source/ui/text_editor/highlighter.cpp index 3205b274fb741..624792445253c 100644 --- a/plugins/ui/source/ui/text_editor/highlighter.cpp +++ b/plugins/ui/source/ui/text_editor/highlighter.cpp @@ -4,8 +4,12 @@ #include namespace hex::ui { - extern TextEditor::Palette s_paletteBase; + using Palette = TextEditor::Palette; using Keys = TextEditor::Keys; + using Lines = TextEditor::Lines; + using LanguageDefinition = TextEditor::LanguageDefinition; + + extern Palette s_paletteBase; void TextEditor::setEnableHighlighting(bool enable) { @@ -56,7 +60,7 @@ namespace hex::ui { } } - Keys TextEditor::Lines::getDeactivatedBlocks() { + Keys Lines::getDeactivatedBlocks() { colorizeInternal(); Keys deactivatedBlocks; if (isEmpty()) @@ -93,11 +97,11 @@ namespace hex::ui { } - void TextEditor::Lines::colorize() { + void Lines::colorize() { m_updateFlags = true; } - void TextEditor::Lines::colorizeRange(bool force) { + void Lines::colorizeRange(bool force) { if (isEmpty()) return; @@ -221,7 +225,7 @@ namespace hex::ui { } } - void TextEditor::Lines::colorizeInternal(bool force) { + void Lines::colorizeInternal(bool force) { if (isEmpty()) return; @@ -458,7 +462,7 @@ namespace hex::ui { colorizeRange(force); } - void TextEditor::Lines::setLanguageDefinition(const LanguageDefinition &languageDef) { + void Lines::setLanguageDefinition(const LanguageDefinition &languageDef) { m_languageDefinition = languageDef; m_regexList.clear(); @@ -468,13 +472,13 @@ namespace hex::ui { colorize(); } - const TextEditor::Palette &TextEditor::getPalette() { return s_paletteBase; } + const Palette &TextEditor::getPalette() { return s_paletteBase; } void TextEditor::setPalette(const Palette &value) { s_paletteBase = value; } - const TextEditor::Palette &TextEditor::getDarkPalette() { + const Palette &TextEditor::getDarkPalette() { const static Palette p = { { 0xff7f7f7f, // Default @@ -506,7 +510,7 @@ namespace hex::ui { return p; } - const TextEditor::Palette &TextEditor::getLightPalette() { + const Palette &TextEditor::getLightPalette() { const static Palette p = { { 0xff7f7f7f, // None @@ -538,7 +542,7 @@ namespace hex::ui { return p; } - const TextEditor::Palette &TextEditor::getRetroBluePalette() { + const Palette &TextEditor::getRetroBluePalette() { const static Palette p = { { 0xff00ffff, // None @@ -570,7 +574,7 @@ namespace hex::ui { return p; } - const TextEditor::LanguageDefinition &TextEditor::LanguageDefinition::CPlusPlus() { + const LanguageDefinition &LanguageDefinition::CPlusPlus() { static bool inited = false; static LanguageDefinition langDef; if (!inited) { @@ -643,7 +647,7 @@ namespace hex::ui { return langDef; } - const TextEditor::LanguageDefinition &TextEditor::LanguageDefinition::HLSL() { + const LanguageDefinition &LanguageDefinition::HLSL() { static bool inited = false; static LanguageDefinition langDef; if (!inited) { @@ -729,7 +733,7 @@ namespace hex::ui { return langDef; } - const TextEditor::LanguageDefinition &TextEditor::LanguageDefinition::GLSL() { + const LanguageDefinition &LanguageDefinition::GLSL() { static bool inited = false; static LanguageDefinition langDef; if (!inited) { @@ -780,7 +784,7 @@ namespace hex::ui { return langDef; } - const TextEditor::LanguageDefinition &TextEditor::LanguageDefinition::C() { + const LanguageDefinition &LanguageDefinition::C() { static bool inited = false; static LanguageDefinition langDef; if (!inited) { @@ -847,7 +851,7 @@ namespace hex::ui { return langDef; } - const TextEditor::LanguageDefinition &TextEditor::LanguageDefinition::SQL() { + const LanguageDefinition &LanguageDefinition::SQL() { static bool inited = false; static LanguageDefinition langDef; if (!inited) { @@ -925,7 +929,7 @@ namespace hex::ui { return langDef; } - const TextEditor::LanguageDefinition &TextEditor::LanguageDefinition::AngelScript() { + const LanguageDefinition &LanguageDefinition::AngelScript() { static bool inited = false; static LanguageDefinition langDef; if (!inited) { @@ -978,7 +982,7 @@ namespace hex::ui { return langDef; } - const TextEditor::LanguageDefinition &TextEditor::LanguageDefinition::Lua() { + const LanguageDefinition &LanguageDefinition::Lua() { static bool inited = false; static LanguageDefinition langDef; if (!inited) { diff --git a/plugins/ui/source/ui/text_editor/navigate.cpp b/plugins/ui/source/ui/text_editor/navigate.cpp index 0879bfd5a0560..c5986fca712e2 100644 --- a/plugins/ui/source/ui/text_editor/navigate.cpp +++ b/plugins/ui/source/ui/text_editor/navigate.cpp @@ -4,6 +4,13 @@ namespace hex::ui { + using Coordinates = TextEditor::Coordinates; + using Range = TextEditor::Range; + using Line = TextEditor::Line; + using Lines = TextEditor::Lines; + using MatchedDelimiter = TextEditor::MatchedDelimiter; + + static bool isWordChar(char c) { auto asUChar = static_cast(c); return std::isalnum(asUChar) || c == '_' || asUChar > 0x7F; @@ -30,7 +37,7 @@ namespace hex::ui { m_lines.moveToMatchedDelimiter(select); } - TextEditor::Coordinates TextEditor::Lines::rfind( const std::string &text, const Coordinates &from) { + Coordinates Lines::rfind( const std::string &text, const Coordinates &from) { Coordinates result = Invalid; if (text.empty() || isEmpty() || from.m_line >= size() || from.m_line < 0) return result; @@ -46,7 +53,7 @@ namespace hex::ui { } - TextEditor::Coordinates TextEditor::Lines::find(const std::string &text, const Coordinates &from) { + Coordinates Lines::find(const std::string &text, const Coordinates &from) { Coordinates result = Invalid; if (text.empty() || isEmpty() || from.m_line >= size() || from.m_line < 0) return result; @@ -62,7 +69,40 @@ namespace hex::ui { return result; } - void TextEditor::Lines::moveToMatchedDelimiter(bool select) { + void Lines::resetInteractiveSelection() { + m_interactiveSelection.m_start = m_interactiveSelection.m_end = m_state.m_cursorPosition; + } + + void Lines::selectUsingStart(bool select, const Coordinates &oldPos) { + if (select) { + if (oldPos == m_interactiveSelection.m_end) + m_interactiveSelection.m_end = m_state.m_cursorPosition; + else if (oldPos == m_interactiveSelection.m_start) + m_interactiveSelection.m_start = m_state.m_cursorPosition; + else { + m_interactiveSelection.m_start = oldPos; + m_interactiveSelection.m_end = m_state.m_cursorPosition; + } + } else + resetInteractiveSelection(); + } + + + void Lines::selectUsingEnd(bool select, const Coordinates &oldPos) { + if (select) { + if (oldPos == m_interactiveSelection.m_start) + m_interactiveSelection.m_start = m_state.m_cursorPosition; + else if (oldPos == m_interactiveSelection.m_end) + m_interactiveSelection.m_end = m_state.m_cursorPosition; + else { + m_interactiveSelection.m_start = m_state.m_cursorPosition; + m_interactiveSelection.m_end = oldPos; + } + } else + resetInteractiveSelection(); + } + + void Lines::moveToMatchedDelimiter(bool select) { resetCursorBlinkTime(); if (m_matchedDelimiter.coordinatesNearDelimiter(this, m_state.m_cursorPosition)) { auto oldPos = m_matchedDelimiter.m_nearCursor; @@ -96,7 +136,7 @@ namespace hex::ui { m_lines.ensureCursorVisible(); } - void TextEditor::Lines::moveUp(i32 amount, bool select) { + void Lines::moveUp(i32 amount, bool select) { auto oldPos = m_state.m_cursorPosition; if (amount < 0) { m_scrollYIncrement = -1.0; @@ -117,19 +157,8 @@ namespace hex::ui { m_state.m_cursorPosition.m_line = rowToLineIndex(row); } - if (oldPos != m_state.m_cursorPosition) { - if (select) { - if (oldPos == m_interactiveSelection.m_start) - m_interactiveSelection.m_start = m_state.m_cursorPosition; - else if (oldPos == m_interactiveSelection.m_end) - m_interactiveSelection.m_end = m_state.m_cursorPosition; - else { - m_interactiveSelection.m_start = m_state.m_cursorPosition; - m_interactiveSelection.m_end = oldPos; - } - } else - m_interactiveSelection.m_start = m_interactiveSelection.m_end = m_state.m_cursorPosition; - } + if (oldPos != m_state.m_cursorPosition) + selectUsingEnd(select, oldPos); } void TextEditor::moveDown(i32 amount, bool select) { @@ -140,7 +169,7 @@ namespace hex::ui { m_lines.ensureCursorVisible(); } - void TextEditor::Lines::moveDown(i32 amount, bool select) { + void Lines::moveDown(i32 amount, bool select) { auto oldPos = m_state.m_cursorPosition; if (amount < 0) { m_scrollYIncrement = 1.0; @@ -170,20 +199,8 @@ namespace hex::ui { m_state.m_cursorPosition.m_line = rowToLineIndex(row); } - - if (m_state.m_cursorPosition != oldPos) { - if (select) { - if (oldPos == m_interactiveSelection.m_end) - m_interactiveSelection.m_end = m_state.m_cursorPosition; - else if (oldPos == m_interactiveSelection.m_start) - m_interactiveSelection.m_start = m_state.m_cursorPosition; - else { - m_interactiveSelection.m_start = oldPos; - m_interactiveSelection.m_end = m_state.m_cursorPosition; - } - } else - m_interactiveSelection.m_start = m_interactiveSelection.m_end = m_state.m_cursorPosition; - } + if (m_state.m_cursorPosition != oldPos) + selectUsingStart(select, oldPos); } void TextEditor::moveLeft(i32 amount, bool select, bool wordMode) { @@ -193,7 +210,7 @@ namespace hex::ui { m_lines.ensureCursorVisible(); } - void TextEditor::Lines::moveLeft(i32 amount, bool select, bool wordMode) { + void Lines::moveLeft(i32 amount, bool select, bool wordMode) { auto oldPos = m_state.m_cursorPosition; auto foldedPos = unfoldedToFoldedCoords(oldPos); @@ -201,9 +218,8 @@ namespace hex::ui { return; auto lindex = foldedPos.m_line; - auto line = operator[](lindex); - auto lineMaxColumn = line.maxColumn(); - auto column = std::min(foldedPos.m_column, lineMaxColumn); + auto lineMaxCol = lineMaxColumn(lindex); + auto column = std::min(foldedPos.m_column, lineMaxCol); auto row = lineIndexToRow(lindex); while (amount-- > 0) { @@ -219,17 +235,7 @@ namespace hex::ui { m_state.m_cursorPosition = foldedToUnfoldedCoords(Coordinates( lindex, column - 1)); } - if (select) { - if (oldPos == m_interactiveSelection.m_start) - m_interactiveSelection.m_start = m_state.m_cursorPosition; - else if (oldPos == m_interactiveSelection.m_end) - m_interactiveSelection.m_end = m_state.m_cursorPosition; - else { - m_interactiveSelection.m_start = m_state.m_cursorPosition; - m_interactiveSelection.m_end = oldPos; - } - } else - m_interactiveSelection.m_start = m_interactiveSelection.m_end = m_state.m_cursorPosition; + selectUsingEnd(select, oldPos); } void TextEditor::moveRight(i32 amount, bool select, bool wordMode) { @@ -239,7 +245,7 @@ namespace hex::ui { m_lines.ensureCursorVisible(); } - void TextEditor::Lines::moveRight(i32 amount, bool select, bool wordMode) { + void Lines::moveRight(i32 amount, bool select, bool wordMode) { auto oldPos = m_state.m_cursorPosition; auto foldedPos = unfoldedToFoldedCoords(oldPos); @@ -265,17 +271,7 @@ namespace hex::ui { m_state.m_cursorPosition = foldedToUnfoldedCoords(Coordinates(lindex, column + 1)); } - if (select) { - if (oldPos == m_interactiveSelection.m_end) - m_interactiveSelection.m_end = m_state.m_cursorPosition; - else if (oldPos == m_interactiveSelection.m_start) - m_interactiveSelection.m_start = m_state.m_cursorPosition; - else { - m_interactiveSelection.m_start = oldPos; - m_interactiveSelection.m_end = m_state.m_cursorPosition; - } - } else - m_interactiveSelection.m_start = m_interactiveSelection.m_end = m_state.m_cursorPosition; + selectUsingStart(select, oldPos); } void TextEditor::moveTop(bool select) { @@ -310,7 +306,7 @@ namespace hex::ui { setSelection(m_lines.m_interactiveSelection); } - void TextEditor::Lines::moveHome(bool select) { + void Lines::moveHome(bool select) { auto oldPos = m_state.m_cursorPosition; Coordinates foldedPos = oldPos; auto row = lineIndexToRow(oldPos.m_line); @@ -360,19 +356,9 @@ namespace hex::ui { setCursorPosition(foldedToUnfoldedCoords(Coordinates(foldedPos.m_line, home))); } else setCursorPosition(Coordinates(m_state.m_cursorPosition.m_line, home)); - if (m_state.m_cursorPosition != oldPos) { - if (select) { - if (oldPos == m_interactiveSelection.m_start) - m_interactiveSelection.m_start = m_state.m_cursorPosition; - else if (oldPos == m_interactiveSelection.m_end) - m_interactiveSelection.m_end = m_state.m_cursorPosition; - else { - m_interactiveSelection.m_start = m_state.m_cursorPosition; - m_interactiveSelection.m_end = oldPos; - } - } else - m_interactiveSelection.m_start = m_interactiveSelection.m_end = m_state.m_cursorPosition; - } + + if (m_state.m_cursorPosition != oldPos) + selectUsingEnd(select, oldPos); } void TextEditor::moveEnd(bool select) { @@ -381,7 +367,7 @@ namespace hex::ui { setSelection(m_lines.m_interactiveSelection); } - void TextEditor::Lines::moveEnd(bool select) { + void Lines::moveEnd(bool select) { auto oldPos = m_state.m_cursorPosition; auto row = lineIndexToRow(oldPos.m_line); if (isMultiLineRow(row)) { @@ -394,22 +380,12 @@ namespace hex::ui { setCursorPosition(lineCoordinates(m_state.m_cursorPosition.m_line, lineMaxColumn(oldPos.m_line))); } - if (m_state.m_cursorPosition != oldPos) { - if (select) { - if (oldPos == m_interactiveSelection.m_end) - m_interactiveSelection.m_end = m_state.m_cursorPosition; - else if (oldPos == m_interactiveSelection.m_start) - m_interactiveSelection.m_start = m_state.m_cursorPosition; - else { - m_interactiveSelection.m_start = oldPos; - m_interactiveSelection.m_end = m_state.m_cursorPosition; - } - } else - m_interactiveSelection.m_start = m_interactiveSelection.m_end = m_state.m_cursorPosition; - } + if (m_state.m_cursorPosition != oldPos) + selectUsingStart(select, oldPos); + } - void TextEditor::Lines::setScrollY() { + void Lines::setScrollY() { if (!m_withinRender) { m_setScrollY = true; return; @@ -435,16 +411,17 @@ namespace hex::ui { m_lines.setFocusAtCoords(m_lines.m_state.m_cursorPosition, scrollToCursor); } - void TextEditor::Lines::setFocusAtCoords(const Coordinates &coords, bool scrollToCursor) { + void Lines::setFocusAtCoords(const Coordinates &coords, bool scrollToCursor) { m_focusAtCoords = coords; m_state.m_cursorPosition = coords; m_updateFocus = true; m_scrollToCursor = scrollToCursor; } - void TextEditor::Lines::setCursorPosition(const Coordinates &position, bool unfoldIfNeeded, bool scrollToCursor) { - if (m_state.m_cursorPosition != position) - m_state.m_cursorPosition = lineCoordinates(position); + void Lines::setCursorPosition(const Coordinates &position, bool unfoldIfNeeded, bool scrollToCursor) { + auto positionCoordinates = lineCoordinates(position); + if (m_state.m_cursorPosition != positionCoordinates) + m_state.m_cursorPosition = positionCoordinates; m_unfoldIfNeeded = unfoldIfNeeded; m_focusAtCoords = m_state.m_cursorPosition; @@ -453,11 +430,18 @@ namespace hex::ui { ensureCursorVisible(); } - void TextEditor::Lines::setCursorPosition() { + void Lines::setCursorPosition() { setCursorPosition(m_state.m_selection.m_end); } - bool TextEditor::Coordinates::isValid(Lines &lines) { + void Lines::setEditorState(const Coordinates &coordinates, bool setInteractiveStart) { + m_state.m_cursorPosition = m_interactiveSelection.m_end = coordinates; + if (setInteractiveStart) + m_interactiveSelection.m_start = coordinates; + setSelection(m_interactiveSelection); + } + + bool Coordinates::isValid(Lines &lines) { auto maxLine = lines.size(); if (std::abs(m_line) > maxLine) @@ -466,7 +450,7 @@ namespace hex::ui { return std::abs(m_column) <= maxColumn; } - TextEditor::Coordinates TextEditor::Coordinates::sanitize(Lines &lines) { + Coordinates Coordinates::sanitize(Lines &lines) { i32 lineCount = lines.size(); if (m_line < 0) { @@ -486,11 +470,11 @@ namespace hex::ui { return *this; } - TextEditor::Range::Coordinates TextEditor::lineCoordinates(i32 lineIndex, i32 column) { + Coordinates TextEditor::lineCoordinates(i32 lineIndex, i32 column) { return m_lines.lineCoordinates(lineIndex, column); } - TextEditor::Range::Coordinates TextEditor::Lines::lineCoordinates(i32 lineIndex, i32 column) { + Coordinates Lines::lineCoordinates(i32 lineIndex, i32 column) { if (isEmpty()) return {0, 0}; Coordinates result(lineIndex, column); @@ -498,21 +482,21 @@ namespace hex::ui { return result.sanitize(*this); } - TextEditor::Coordinates TextEditor::lineCoordinates(const Coordinates &value) { + Coordinates TextEditor::lineCoordinates(const Coordinates &value) { return m_lines.lineCoordinates(value); } - TextEditor::Coordinates TextEditor::Lines::lineCoordinates(const Coordinates &value) { + Coordinates Lines::lineCoordinates(const Coordinates &value) { auto result = value; return result.sanitize(*this); } - TextEditor::Range TextEditor::lineCoordinates(const Range &value) { + Range TextEditor::lineCoordinates(const Range &value) { return m_lines.lineCoordinates(value); } - TextEditor::Range TextEditor::Lines::lineCoordinates(const Range &value) { + Range TextEditor::Lines::lineCoordinates(const Range &value) { auto start = lineCoordinates(value.m_start); auto end = lineCoordinates(value.m_end); if (start == Invalid || end == Invalid) @@ -540,7 +524,7 @@ namespace hex::ui { coordinates.m_column += incr; } - TextEditor::Coordinates TextEditor::findWordStart(const Coordinates &from) { + Coordinates TextEditor::findWordStart(const Coordinates &from) { Coordinates at = m_lines.lineCoordinates(from); if (at.m_line >= m_lines.size()) return at; @@ -562,7 +546,7 @@ namespace hex::ui { return m_lines.lineIndexCoords(at.m_line + 1, charIndex); } - TextEditor::Coordinates TextEditor::findWordEnd(const Coordinates &from) { + Coordinates TextEditor::findWordEnd(const Coordinates &from) { Coordinates at = m_lines.lineCoordinates(from); if (at.m_line >= m_lines.size()) return at; @@ -585,7 +569,7 @@ namespace hex::ui { return m_lines.lineIndexCoords(at.m_line + 1, charIndex); } - TextEditor::Coordinates TextEditor::Lines::findNextWord(const Coordinates &from) { + Coordinates Lines::findNextWord(const Coordinates &from) { Coordinates at = unfoldedToFoldedCoords(from); if (at.m_line >= size()) return from; @@ -606,7 +590,7 @@ namespace hex::ui { return foldedToUnfoldedCoords(lineIndexCoords(at.m_line + 1, charIndex)); } - TextEditor::Coordinates TextEditor::Lines::findPreviousWord(const Coordinates &from) { + Coordinates Lines::findPreviousWord(const Coordinates &from) { Coordinates at = unfoldedToFoldedCoords(from); if (at.m_line >= size()) return from; @@ -628,13 +612,13 @@ namespace hex::ui { return foldedToUnfoldedCoords(lineIndexCoords(at.m_line + 1, charIndex)); } - u32 TextEditor::Line::skipSpaces(i32 charIndex) { + u32 Line::skipSpaces(i32 charIndex) { u32 s; for (s = 0; charIndex < (i32) m_chars.size() && m_chars[charIndex] == ' ' && m_flags[charIndex] == 0x00; ++s, ++charIndex); return s; } - u32 TextEditor::Lines::skipSpaces(const Coordinates &from) { + u32 Lines::skipSpaces(const Coordinates &from) { auto lineIndex = from.m_line; if (lineIndex >= (i64) size()) return 0; @@ -643,7 +627,7 @@ namespace hex::ui { return line.skipSpaces(charIndex); } - bool TextEditor::MatchedDelimiter::setNearCursor(Lines *lines,const Coordinates &from) { + bool MatchedDelimiter::setNearCursor(Lines *lines,const Coordinates &from) { Coordinates fromCopy = from; if (fromCopy.m_line >= lines->size()) return false; @@ -658,7 +642,7 @@ namespace hex::ui { return false; } - bool TextEditor::MatchedDelimiter::checkPosition(Lines *lines, Coordinates &from) { + bool MatchedDelimiter::checkPosition(Lines *lines, Coordinates &from) { auto start = lines->lineCoordinates(from); auto lineIndex = start.m_line; auto line = lines->m_unfoldedLines[lineIndex].m_chars; @@ -680,7 +664,7 @@ namespace hex::ui { return false; } - i32 TextEditor::MatchedDelimiter::detectDirection(Lines *lines, const Coordinates &from) { + i32 MatchedDelimiter::detectDirection(Lines *lines, const Coordinates &from) { auto start = lines->lineCoordinates(from); std::string delimiters = "()[]{}<>"; i32 result = -2; // dont check either @@ -715,7 +699,7 @@ namespace hex::ui { return result; } - bool TextEditor::MatchedDelimiter::coordinatesNearDelimiter(Lines *lines, Coordinates &from) { + bool MatchedDelimiter::coordinatesNearDelimiter(Lines *lines, Coordinates &from) { auto start = lines->lineCoordinates(from); if (lines->isEmpty()) return false; @@ -787,7 +771,7 @@ namespace hex::ui { return false; } - TextEditor::Coordinates TextEditor::MatchedDelimiter::findMatchingDelimiter(Lines *lines, Coordinates &from, bool folded) { + Coordinates MatchedDelimiter::findMatchingDelimiter(Lines *lines, Coordinates &from, bool folded) { Coordinates start; Coordinates result = Invalid; if (!folded) @@ -936,7 +920,7 @@ namespace hex::ui { return result; } - void TextEditor::MatchedDelimiter::findMatchingDelimiter(Lines *lines, bool folded) { + void MatchedDelimiter::findMatchingDelimiter(Lines *lines, bool folded) { Coordinates from = m_nearCursor; Coordinates result = findMatchingDelimiter(lines, from, folded); if (result != Invalid) { diff --git a/plugins/ui/source/ui/text_editor/render.cpp b/plugins/ui/source/ui/text_editor/render.cpp index ba72ca810d0dd..f955e94535247 100644 --- a/plugins/ui/source/ui/text_editor/render.cpp +++ b/plugins/ui/source/ui/text_editor/render.cpp @@ -9,7 +9,10 @@ namespace hex::ui { TextEditor::Palette s_paletteBase = TextEditor::getDarkPalette(); - using Keys = TextEditor::Keys; + using Keys = TextEditor::Keys; + using Line = TextEditor::Line; + using Lines = TextEditor::Lines; + using FoldedLine = TextEditor::FoldedLine; inline void TextUnformattedColored(const ImU32 &color, const char *text) { ImGui::PushStyleColor(ImGuiCol_Text, color); @@ -35,7 +38,7 @@ namespace hex::ui { return x; } - void TextEditor::Line::print(i32 lineIndex, i32 maxLineIndex, std::optional position) { + void Line::print(i32 lineIndex, i32 maxLineIndex, std::optional position) { u32 idx = 0; std::string lineNumberStr = std::to_string(lineIndex + 1); auto padding = std::string(std::to_string(maxLineIndex + 1).size() - lineNumberStr.size(),' '); @@ -82,23 +85,23 @@ namespace hex::ui { m_lines.clearErrorMarkers(); } - void TextEditor::Lines::clearErrorMarkers() { + void Lines::clearErrorMarkers() { m_errorMarkers.clear(); m_errorHoverBoxes.clear(); } - void TextEditor::Lines::clearCodeFolds() { + void Lines::clearCodeFolds() { m_codeFolds.clear(); m_codeFoldKeys.clear(); } - void TextEditor::Lines::clearActionables() { + void Lines::clearActionables() { clearErrorMarkers(); clearGotoBoxes(); clearCursorBoxes(); } - bool TextEditor::Lines::lineNeedsDelimiter(i32 lineIndex) { + bool Lines::lineNeedsDelimiter(i32 lineIndex) { auto row = lineIndexToRow(lineIndex); if (row == -1.0 || !m_foldedLines.contains(row)) { if (lineIndex >= (i64)m_unfoldedLines.size() || lineIndex < 0) @@ -112,7 +115,7 @@ namespace hex::ui { auto delimiter = m_codeFoldDelimiters[key].first; if (!delimiter || (delimiter != '(' && delimiter != '[' && delimiter != '{' && delimiter != '<')) return false; - if (key.m_start.m_column >= m_unfoldedLines[lineIndex].m_lineMaxColumn) + if (key.m_start.m_column >= lineMaxColumn(lineIndex)) return true; return !line.contains(delimiter); } @@ -122,15 +125,15 @@ namespace hex::ui { return m_foldedLines.at(row).firstLineNeedsDelimiter(); } - bool TextEditor::FoldedLine::firstLineNeedsDelimiter() { + bool FoldedLine::firstLineNeedsDelimiter() { return ((u8)m_type & (u8)FoldedLine::FoldType::FirstLineNeedsDelimiter); } - bool TextEditor::FoldedLine::addsLastLineToFold() { + bool FoldedLine::addsLastLineToFold() { return (u8)m_type & (u8)FoldedLine::FoldType::AddsLastLine; } - bool TextEditor::FoldedLine::addsFullFirstLineToFold() { + bool FoldedLine::addsFullFirstLineToFold() { return (u8)m_type & (u8)FoldedLine::FoldType::AddsFirstLine; } @@ -174,37 +177,37 @@ namespace hex::ui { return ImGui::GetCurrentWindow()->InnerClipRect.GetHeight() / m_lines.m_charAdvance.y; } - bool TextEditor::Lines::isEndOfLine() { + bool Lines::isEndOfLine() { return isEndOfLine(m_state.m_cursorPosition); } - bool TextEditor::Lines::isStartOfLine() const { + bool Lines::isStartOfLine() const { return m_state.m_cursorPosition.m_column == 0; } - bool TextEditor::Line::isEndOfLine(i32 column) { + bool Line::isEndOfLine(i32 column) { return column >= maxColumn(); } - bool TextEditor::Lines::isEndOfLine(const Coordinates &coordinates) { + bool Lines::isEndOfLine(const Coordinates &coordinates) { if (coordinates.m_line < size()) return m_unfoldedLines[coordinates.m_line].isEndOfLine(coordinates.m_column); return true; } - bool TextEditor::Lines::isEndOfFile(const Coordinates &coordinates) { + bool Lines::isEndOfFile(const Coordinates &coordinates) { if (coordinates.m_line < size()) return isLastLine(coordinates.m_line) && isEndOfLine(coordinates); return true; } - bool TextEditor::Lines::isLastLine() { + bool Lines::isLastLine() { return isLastLine(m_state.m_cursorPosition.m_line); } - bool TextEditor::Lines::isLastLine(i32 lineIndex) { + bool Lines::isLastLine(i32 lineIndex) { auto row = lineIndexToRow(lineIndex); return row == getMaxDisplayedRow(); } @@ -219,14 +222,14 @@ namespace hex::ui { } } - float TextEditor::Lines::getMaxDisplayedRow() { + float Lines::getMaxDisplayedRow() { auto maxRow = getGlobalRowMax(); if (maxRow - m_topRow < m_numberOfLinesDisplayed) return maxRow; return m_topRow + m_numberOfLinesDisplayed; } - float TextEditor::Lines::getGlobalRowMax() { + float Lines::getGlobalRowMax() { float maxRow = size() - 1.0f; if (m_codeFoldsDisabled || m_foldedLines.empty() || m_codeFoldKeys.empty()) return std::floor(maxRow); @@ -1063,8 +1066,8 @@ namespace hex::ui { lineIndex = key.m_end.m_line; m_foldedSegments[2] = m_lines->lineCoordinates( foldedLineIndex, m_ellipsisIndices[0] + Ellipsis.size() - 1); m_foldedSegments[3] = m_lines->lineCoordinates( foldedLineIndex, m_ellipsisIndices[0] + Ellipsis.size()); - m_unfoldedSegments[2] = m_lines->lineCoordinates( lineIndex , m_lines->m_unfoldedLines[lineIndex].maxColumn() - 1); - m_unfoldedSegments[3] = m_lines->lineCoordinates( lineIndex , m_lines->m_unfoldedLines[lineIndex].maxColumn()); + m_unfoldedSegments[2] = m_lines->lineCoordinates( lineIndex , m_lines->lineMaxColumn(lineIndex) - 1); + m_unfoldedSegments[3] = m_lines->lineCoordinates( lineIndex , m_lines->lineMaxColumn(lineIndex)); return; } @@ -1094,7 +1097,7 @@ namespace hex::ui { m_foldedSegments[2 * keyCount] = m_lines->lineCoordinates(foldedLineIndex, m_ellipsisIndices.back() + 3); m_foldedSegments[2 * keyCount + 1] = m_lines->lineCoordinates(foldedLineIndex, m_foldedLine.maxColumn()); m_unfoldedSegments[2 * keyCount] = m_lines->lineCoordinates( lineIndex, delimiterCoordinates.m_end.m_column); - m_unfoldedSegments[2 * keyCount + 1] = m_lines->lineCoordinates( lineIndex, m_lines->m_unfoldedLines[lineIndex].maxColumn()); + m_unfoldedSegments[2 * keyCount + 1] = m_lines->lineCoordinates( lineIndex, m_lines->lineMaxColumn(lineIndex)); } void TextEditor::Lines::removeKeys() { @@ -1270,7 +1273,7 @@ namespace hex::ui { i64 start = ImGui::GetScrollX(); Coordinates head = Coordinates(lineIndex, start / m_lines.m_charAdvance.x); i64 textSize = m_lines.textDistanceToLineStart(head); - auto maxColumn = line.indexColumn(line.size()); + auto maxColumn = line.maxColumn(); if (textSize < start) { while (textSize < start && head.m_column < maxColumn) { head.m_column += 1; diff --git a/plugins/ui/source/ui/text_editor/support.cpp b/plugins/ui/source/ui/text_editor/support.cpp index 665466aa66cf4..2c2b70c4449b4 100644 --- a/plugins/ui/source/ui/text_editor/support.cpp +++ b/plugins/ui/source/ui/text_editor/support.cpp @@ -586,7 +586,7 @@ namespace hex::ui { return m_selection == o.m_selection && m_cursorPosition == o.m_cursorPosition; } - void TextEditor::Lines::setSelection(const Range &selection) { + void Lines::setSelection(const Range &selection) { m_state.m_selection = lineCoordinates(const_cast(selection)); } @@ -594,7 +594,7 @@ namespace hex::ui { m_lines.setSelection(selection); } - Range TextEditor::Lines::getSelection() const { + Range Lines::getSelection() const { return m_state.m_selection; } @@ -607,15 +607,24 @@ namespace hex::ui { setSelection(Range(wordStart, findWordEnd(wordStart))); } + void TextEditor::selectLineUnderCursor() { + auto coordinates = m_lines.m_state.m_cursorPosition; + auto lineIndex = rowToLineIndex(lineIndexToRow(coordinates.m_line)); + auto maxColumn = m_lines.lineMaxColumn(lineIndex); + m_lines.m_state.m_selection.m_start = m_lines.foldedToUnfoldedCoords(Coordinates(lineIndex, 0)); + m_lines.m_state.m_selection.m_end = m_lines.foldedToUnfoldedCoords(Coordinates(lineIndex, maxColumn)); + m_lines.resetInteractiveSelection(); + } + void TextEditor::selectAll() { setSelection(Range(m_lines.lineCoordinates(0, 0), m_lines.lineCoordinates(-1, -1))); } - bool TextEditor::Lines::hasSelection() { + bool Lines::hasSelection() { return !isEmpty() && m_state.m_selection.m_end > m_state.m_selection.m_start; } - void TextEditor::Lines::addUndo(std::vector value) { + void Lines::addUndo(std::vector value) { if (m_readOnly) return; @@ -624,7 +633,7 @@ namespace hex::ui { m_undoIndex++; } - TextEditor::PaletteIndex TextEditor::Lines::getColorIndexFromFlags(Line::Flags flags) { + TextEditor::PaletteIndex Lines::getColorIndexFromFlags(Line::Flags flags) { auto commentBits = flags.m_value & inComment; if (commentBits == (i32) Line::FlagValues::Global) return PaletteIndex::GlobalDocComment; @@ -695,83 +704,62 @@ namespace hex::ui { Left mouse button triple click */ + auto coordinates = screenPosCoordinates(ImGui::GetMousePos()); + if (coordinates == Invalid) + return; + if (tripleClick) { - auto coordinates = screenPosCoordinates(ImGui::GetMousePos()); - if (coordinates == Invalid) - return; if (!ctrl) { m_lines.m_state.m_cursorPosition = coordinates; - auto lineIndex = rowToLineIndex(lineIndexToRow(coordinates.m_line)); - auto line = m_lines[lineIndex]; - m_lines.m_state.m_selection.m_start = m_lines.foldedToUnfoldedCoords(Coordinates(lineIndex, 0)); - m_lines.m_state.m_selection.m_end = m_lines.foldedToUnfoldedCoords(Coordinates(lineIndex, line.maxColumn())); + selectLineUnderCursor(); } m_lastClick = -1.0f; resetBlinking = true; } - /* - Left mouse button double click - */ - + /* + Left mouse button double click + */ else if (doubleClick) { - auto coordinates = screenPosCoordinates(ImGui::GetMousePos()); - if (coordinates == Invalid) - return; if (!ctrl) { - m_lines.m_state.m_cursorPosition = coordinates; - m_lines.m_state.m_selection.m_start = findWordStart(m_lines.m_state.m_cursorPosition); - m_lines.m_state.m_selection.m_end = findWordEnd(m_lines.m_state.m_cursorPosition); + m_lines.setEditorState(coordinates); + selectWordUnderCursor(); } m_lastClick = (float) ImGui::GetTime(); resetBlinking = true; } - /* - Left mouse button click - */ + /* + Left mouse button click + */ else if (click) { - auto coordinates = screenPosCoordinates(ImGui::GetMousePos()); - if (coordinates == Invalid) - return; if (ctrl) { - m_lines.m_state.m_cursorPosition = m_lines.m_interactiveSelection.m_start = m_lines.m_interactiveSelection.m_end = coordinates; + m_lines.setEditorState(coordinates); selectWordUnderCursor(); - } else if (shift) { - m_lines.m_state.m_cursorPosition = m_lines.m_interactiveSelection.m_end = coordinates; - setSelection(m_lines.m_interactiveSelection); - } else { - m_lines.m_state.m_cursorPosition = m_lines.m_interactiveSelection.m_end = m_lines.m_interactiveSelection.m_start = coordinates; - setSelection(m_lines.m_interactiveSelection); - } - m_lines.resetCursorBlinkTime(); + } else if (shift) + m_lines.setEditorState(coordinates, false); + else + m_lines.setEditorState(coordinates); + m_lines.resetCursorBlinkTime(); m_lines.ensureCursorVisible(); m_lastClick = (float) ImGui::GetTime(); } else if (rightClick) { - auto coordinates = screenPosCoordinates(ImGui::GetMousePos()); - if (coordinates == Invalid) - return; auto cursorPosition = coordinates; - if (!m_lines.hasSelection() || m_lines.m_state.m_selection.m_start > cursorPosition || cursorPosition > m_lines.m_state.m_selection.m_end) { - m_lines.m_state.m_cursorPosition = m_lines.m_interactiveSelection.m_start = m_lines.m_interactiveSelection.m_end = cursorPosition; - setSelection(m_lines.m_interactiveSelection); - } - m_lines.resetCursorBlinkTime(); + if (!m_lines.hasSelection() || !m_lines.m_state.m_selection.contains(cursorPosition,Range::EndsInclusive::Both)) + m_lines.setEditorState(cursorPosition); + + resetBlinking = true; m_raiseContextMenu = true; ImGui::SetWindowFocus(); } - // Mouse left button dragging (=> update selection) + // Mouse left button dragging (=> update selection) else if (ImGui::IsMouseDragging(0) && ImGui::IsMouseDown(0)) { - auto coordinates = screenPosCoordinates(ImGui::GetMousePos()); - if (coordinates == Invalid) - return; io.WantCaptureMouse = true; - m_lines.m_state.m_cursorPosition = m_lines.m_interactiveSelection.m_end = coordinates; - setSelection(m_lines.m_interactiveSelection); + m_lines.setEditorState(coordinates, false); m_lines.ensureCursorVisible(); resetBlinking = true; } @@ -1181,7 +1169,7 @@ namespace hex::ui { return true; } - ImRect TextEditor::Lines::getBoxForRow(u32 row) { + ImRect Lines::getBoxForRow(u32 row) { auto boxSize = m_charAdvance.x + (((u32) m_charAdvance.x % 2) ? 2.0f : 1.0f); auto lineStartScreenPos = getLineStartScreenPos(0,row); ImVec2 lineNumberStartScreenPos = ImVec2(m_lineNumbersStartPos.x + m_lineNumberFieldWidth, lineStartScreenPos.y); @@ -1279,7 +1267,7 @@ namespace hex::ui { return m_lines.size(); } - void TextEditor::Lines::setAllCodeFolds() { + void Lines::setAllCodeFolds() { initializeCodeFolds(); CodeFoldBlocks intervals = foldPointsFromSource(); m_codeFoldKeys.clear(); @@ -1321,7 +1309,7 @@ namespace hex::ui { } } - void TextEditor::Lines::removeHiddenLinesFromPattern() { + void Lines::removeHiddenLinesFromPattern() { i32 lineIndex = 0; const auto totalLines = (i32)m_unfoldedLines.size(); while (lineIndex < totalLines && m_unfoldedLines[lineIndex].m_chars.starts_with("//+-")) @@ -1339,7 +1327,7 @@ namespace hex::ui { } } - void TextEditor::Lines::addHiddenLinesToPattern() { + void Lines::addHiddenLinesToPattern() { if (m_hiddenLines.empty()) return; for (const auto &hiddenLine : m_hiddenLines) { @@ -1409,11 +1397,11 @@ namespace hex::ui { } } } - bool TextEditor::Lines::isTokenIdValid(i32 tokenId) { + bool Lines::isTokenIdValid(i32 tokenId) { return tokenId >= 0 && tokenId < (i32) m_tokens.size(); } - bool TextEditor::Lines::isLocationValid(Location location) { + bool Lines::isLocationValid(Location location) { const pl::api::Source *source; try { source = location.source; @@ -1426,7 +1414,7 @@ namespace hex::ui { return location > m_tokens.front().location && location < m_tokens.back().location; } - void TextEditor::Lines::loadFirstTokenIdOfLine() { + void Lines::loadFirstTokenIdOfLine() { const u32 tokenCount = m_tokens.size(); m_firstTokenIdOfLine.clear(); u32 tokenId = 0; @@ -1473,14 +1461,14 @@ namespace hex::ui { } - pl::core::Location TextEditor::Lines::getLocation(i32 tokenId) { + pl::core::Location Lines::getLocation(i32 tokenId) { if (tokenId >= (i32) m_tokens.size()) return Location::Empty(); return m_tokens[tokenId].location; } - i32 TextEditor::Lines::getTokenId(hex::ui::TextEditor::SafeTokenIterator tokenIterator) { + i32 Lines::getTokenId(TextEditor::SafeTokenIterator tokenIterator) { auto start = m_tokens.data(); auto m_start = &tokenIterator.front(); auto m_end = &tokenIterator.back(); @@ -1490,7 +1478,7 @@ namespace hex::ui { return m_start - start; } - i32 TextEditor::Lines::getTokenId() { + i32 Lines::getTokenId() { auto start = m_tokens.data(); auto m_start = &m_curr.front(); auto m_end = &m_curr.back(); @@ -1501,7 +1489,7 @@ namespace hex::ui { } // Get the token index for a given location. - i32 TextEditor::Lines::getTokenId(pl::core::Location location) { + i32 Lines::getTokenId(pl::core::Location location) { if (location == m_tokens.at(0).location) return 0; if (location == m_tokens.back().location) @@ -1531,7 +1519,7 @@ namespace hex::ui { return -1; } - i32 TextEditor::Lines::nextLineIndex(i32 lineIndex) { + i32 Lines::nextLineIndex(i32 lineIndex) { if (lineIndex < 0 || lineIndex >= size()) return -1; auto currentTokenId = m_firstTokenIdOfLine[lineIndex]; diff --git a/plugins/ui/source/ui/text_editor/utf8.cpp b/plugins/ui/source/ui/text_editor/utf8.cpp index 068f961e670f3..229e4aa8fb5c0 100644 --- a/plugins/ui/source/ui/text_editor/utf8.cpp +++ b/plugins/ui/source/ui/text_editor/utf8.cpp @@ -9,8 +9,10 @@ namespace hex::ui { using Coordinates = TextEditor::Coordinates; using Segments = TextEditor::Segments; + using Line = TextEditor::Line; + using Lines = TextEditor::Lines; - TextEditor::Line TextEditor::Line::trim(TrimMode trimMode) { + Line Line::trim(TrimMode trimMode) { if (m_chars.empty()) return m_emptyLine; std::string trimmed = wolv::util::trim(m_chars); @@ -27,7 +29,7 @@ namespace hex::ui { return subLine(idx, trimmed.size()); } - i32 TextEditor::Line::columnIndex(i32 column) const { + i32 Line::columnIndex(i32 column) const { i32 idx = 0; for (i32 col = 0; idx < (i32) size() && col < column; ++col) @@ -36,20 +38,20 @@ namespace hex::ui { return idx; } - i32 TextEditor::Line::maxColumn() { + i32 Line::maxColumn() { if (m_lineMaxColumn > 0) return m_lineMaxColumn; m_lineMaxColumn = indexColumn((i32) size()); return m_lineMaxColumn; } - i32 TextEditor::Line::maxColumn() const { + i32 Line::maxColumn() const { if (m_lineMaxColumn > 0) return m_lineMaxColumn; return indexColumn((i32) size()); } - i32 TextEditor::Line::indexColumn(i32 stringIndex) const { + i32 Line::indexColumn(i32 stringIndex) const { i32 limit = std::max(0, std::min(stringIndex, (i32) size())); i32 col = 0; @@ -59,7 +61,7 @@ namespace hex::ui { return col; } - i32 TextEditor::Line::stringTextSize(const std::string &str) const { + i32 Line::stringTextSize(const std::string &str) const { if (str.empty()) return 0; if (ImGui::GetFont() == nullptr) { @@ -71,24 +73,24 @@ namespace hex::ui { return ImGui::GetFont()->CalcTextSizeA(ImGui::GetFontSize(), FLT_MAX, -1.0f, str.c_str(), nullptr, nullptr).x; } - i32 TextEditor::Line::textSize(u32 index) const { + i32 Line::textSize(u32 index) const { if (m_chars.empty()) return 0; return stringTextSize(m_chars.substr(0, index)); } - i32 TextEditor::Line::textSize() const { + i32 Line::textSize() const { if (m_chars.empty()) return 0; return stringTextSize(m_chars); } - i32 TextEditor::Line::lineTextSize(TrimMode trimMode) { + i32 Line::lineTextSize(TrimMode trimMode) { auto trimmedLine = trim(trimMode); return trimmedLine.textSize(); } - i32 TextEditor::Line::textSizeIndex(float textSize, i32 position) { + i32 Line::textSizeIndex(float textSize, i32 position) { i32 result = textSize / ImGui::GetFont()->CalcTextSizeA(ImGui::GetFontSize(), FLT_MAX, -1.0f, "#", nullptr, nullptr).x; auto currentSize = stringTextSize(m_chars.substr(position, result)); while (currentSize < textSize && (u32)(position + result) < size()) { @@ -130,7 +132,7 @@ namespace hex::ui { return line.indexColumn(stringIndex); } - i32 TextEditor::Lines::lineMaxColumn(i32 lineIndex) { + i32 Lines::lineMaxColumn(i32 lineIndex) { if (lineIndex >= (i64) size() || lineIndex < 0) return 0; @@ -227,7 +229,7 @@ namespace hex::ui { return {coordinates.m_line,line.columnIndex(coordinates.m_column)}; } - i32 TextEditor::Lines::lineCoordsIndex(const Coordinates &coordinates) { + i32 Lines::lineCoordsIndex(const Coordinates &coordinates) { if (coordinates.m_line >= (i64) size()) return -1; @@ -235,44 +237,42 @@ namespace hex::ui { return line.columnIndex(coordinates.m_column); } - Coordinates TextEditor::Lines::lineIndexCoords(i32 lineNumber, i32 stringIndex) { + Coordinates Lines::lineIndexCoords(i32 lineNumber, i32 stringIndex) { if (lineNumber < 1 || lineNumber > size()) return lineCoordinates( 0, 0); auto &line = operator[](lineNumber - 1); return lineCoordinates(lineNumber - 1, line.indexColumn(stringIndex)); } - Segments TextEditor::Lines::unfoldedEllipsisCoordinates(Range delimiterCoordinates) { + Segments Lines::unfoldedEllipsisCoordinates(Range delimiterCoordinates) { auto lineStart = m_unfoldedLines[delimiterCoordinates.m_start.m_line]; auto row = lineIndexToRow(delimiterCoordinates.m_start.m_line); float unfoldedSpan1, unfoldedSpan2, unfoldedSpan3; float unprocessedSpan1, unprocessedSpan2, unprocessedSpan3; - bool adddsBothEnds = true; + bool addsBothEnds = true; if (delimiterCoordinates.m_start.m_line == delimiterCoordinates.m_end.m_line) { unprocessedSpan1 = unfoldedSpan1 = delimiterCoordinates.m_end.m_column - delimiterCoordinates.m_start.m_column - 1; unprocessedSpan3 = unfoldedSpan3 = 0.0f; unprocessedSpan2 = unfoldedSpan2 = 0.0f; } else if (!m_foldedLines[row].addsFullFirstLineToFold() && !m_foldedLines[row].addsLastLineToFold()) { - adddsBothEnds = false; - auto innerLine = m_unfoldedLines[delimiterCoordinates.m_start.m_line]; - unprocessedSpan1 = unfoldedSpan1 = std::max(innerLine.maxColumn() - 1, 0); - innerLine = m_unfoldedLines[delimiterCoordinates.m_end.m_line]; - unprocessedSpan3 = unfoldedSpan3 = std::max(innerLine.maxColumn() - 1, 0); + addsBothEnds = false; + unfoldedSpan1 = std::max(lineMaxColumn(delimiterCoordinates.m_start.m_line) - 1, 0); + unprocessedSpan1 = unfoldedSpan1; + unfoldedSpan3 = std::max(lineMaxColumn(delimiterCoordinates.m_end.m_line) - 1, 0); + unprocessedSpan3 = unfoldedSpan3; unfoldedSpan2 = 0; - for (i32 j = delimiterCoordinates.m_start.m_line + 1; j < delimiterCoordinates.m_end.m_line; j++) { - innerLine = m_unfoldedLines[j]; - unfoldedSpan2 += innerLine.maxColumn(); - } + for (i32 j = delimiterCoordinates.m_start.m_line + 1; j < delimiterCoordinates.m_end.m_line; j++) + unfoldedSpan2 += lineMaxColumn(j); + unprocessedSpan2 = unfoldedSpan2; } else { unprocessedSpan1 = unfoldedSpan1 = std::max(lineStart.maxColumn() - delimiterCoordinates.m_start.m_column - 2, 0); unprocessedSpan3 = unfoldedSpan3 = std::max(delimiterCoordinates.m_end.m_column - 1, 0); unfoldedSpan2 = 0; - for (i32 j = delimiterCoordinates.m_start.m_line + 1; j < delimiterCoordinates.m_end.m_line; j++) { - auto innerLine = m_unfoldedLines[j]; - unfoldedSpan2 += innerLine.maxColumn(); - } + for (i32 j = delimiterCoordinates.m_start.m_line + 1; j < delimiterCoordinates.m_end.m_line; j++) + unfoldedSpan2 += lineMaxColumn(j); + unprocessedSpan2 = unfoldedSpan2; } @@ -287,7 +287,7 @@ namespace hex::ui { float spanFragment = totalUnfoldedSpan / 2.0f; Segments unfoldedEllipsisCoordinates(4); - if (adddsBothEnds) { + if (addsBothEnds) { unfoldedEllipsisCoordinates[0] = lineCoordinates(delimiterCoordinates.m_start.m_line, delimiterCoordinates.m_start.m_column + 1); unfoldedEllipsisCoordinates[3] = delimiterCoordinates.m_end; } else { @@ -310,7 +310,7 @@ namespace hex::ui { if ((unprocessedSpan2 > spanFragment || std::fabs(unprocessedSpan2 - spanFragment) < 0.001) && i < 3) { float lineLength = 0.0f; for (i32 j = delimiterCoordinates.m_start.m_line + 1; j < delimiterCoordinates.m_end.m_line; j++) { - auto currentLineLength = (float) m_unfoldedLines[j].maxColumn(); + auto currentLineLength = (float) lineMaxColumn(j); lineLength += currentLineLength + leftOver; leftOver = 0.0f; while ((lineLength > spanFragment || std::fabs(lineLength-spanFragment) < 0.001) && i < 3) { @@ -333,7 +333,7 @@ namespace hex::ui { return unfoldedEllipsisCoordinates; } - Coordinates TextEditor::Lines::foldedToUnfoldedCoords(const Coordinates &coords) { + Coordinates Lines::foldedToUnfoldedCoords(const Coordinates &coords) { auto row = lineIndexToRow(coords.m_line); if (row == -1.0 || !m_foldedLines.contains(row)) return coords; @@ -382,9 +382,8 @@ namespace hex::ui { auto foldedSegmentStart = foldedLine.m_foldedSegments[foundIndex]; if (foundIndex == 0) { if (lineNeedsDelimiter(key.m_start.m_line)) { - auto line = m_unfoldedLines[key.m_start.m_line]; auto delimiterCoordinates = foldedLine.findDelimiterCoordinates(key); - if (coords.m_column > line.maxColumn()) + if (coords.m_column > lineMaxColumn(key.m_start.m_line)) return delimiterCoordinates.m_start; else return lineCoordinates( unfoldedSegmentStart.m_line, coords.m_column); @@ -402,7 +401,7 @@ namespace hex::ui { else return {coordinate.m_line,coordinate.m_column + 1}; } - bool TextEditor::testfoldMaps(TextEditor::Range toTest) { + bool TextEditor::testfoldMaps(Range toTest) { bool result = true; for (auto test = toTest.getStart(); test <= toTest.getEnd(); test = nextCoordinate(test)) { auto data = test; @@ -414,7 +413,7 @@ namespace hex::ui { return result; } - Coordinates TextEditor::Lines::unfoldedToFoldedCoords(const Coordinates &coords) { + Coordinates Lines::unfoldedToFoldedCoords(const Coordinates &coords) { auto row = lineIndexToRow(coords.m_line); Coordinates result; if (row == -1 || !m_foldedLines.contains(row)) @@ -477,8 +476,8 @@ namespace hex::ui { } else { if (foundIndex == 0) { if (foldedLine.firstLineNeedsDelimiter()) { - auto line = m_unfoldedLines[foldedLine.m_full.m_start.m_line]; - if (coords > lineCoordinates(foldedLine.m_full.m_start.m_line, line.maxColumn())) + auto lineIndex = foldedLine.m_full.m_start.m_line; + if (coords > lineCoordinates(lineIndex, lineMaxColumn(lineIndex))) result.m_column = foldedLine.m_ellipsisIndices[0] - 1; else result.m_column = coords.m_column; @@ -494,7 +493,7 @@ namespace hex::ui { } } - Coordinates TextEditor::Lines::stringIndexCoords(i32 strIndex, const std::string &input) { + Coordinates Lines::stringIndexCoords(i32 strIndex, const std::string &input) { if (strIndex < 0 || strIndex > (i32) input.size()) return lineCoordinates( 0, 0); std::string str = input.substr(0, strIndex);