From 67efea644491e89eec2f2954a07e4242bf87e53c Mon Sep 17 00:00:00 2001 From: Zackary Newman <34630441+Zman350x@users.noreply.github.com> Date: Sun, 14 Sep 2025 00:10:38 -0400 Subject: [PATCH] =?UTF-8?q?Fix=20segfault=20when=20opening=20recent=20file?= =?UTF-8?q?=20with=20pattern=20sync;=20Don't=20show=20p=E2=80=A6=20(#2448)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit …attern selection popup when pattern is already open This PR does two things. Most importantly, it fixes a segfault that can be caused by opening a recent file with pattern sync enabled. Secondly, it makes it so that the pattern selection popup does not appear if you already have text in the pattern editor for a given provider (due to CLI args, a project file, pattern sync, etc.). If you open a file normally, that text field is empty and the popup will appear so you can select a pre-made pattern like usual. --- .../content/views/view_pattern_editor.hpp | 8 +- .../text_highlighting/pattern_language.cpp | 146 +++++++++++------- .../content/views/view_pattern_editor.cpp | 11 ++ .../ui/source/ui/text_editor/highlighter.cpp | 27 +--- 4 files changed, 110 insertions(+), 82 deletions(-) diff --git a/plugins/builtin/include/content/views/view_pattern_editor.hpp b/plugins/builtin/include/content/views/view_pattern_editor.hpp index e84ddf6a6..044ebc6f4 100644 --- a/plugins/builtin/include/content/views/view_pattern_editor.hpp +++ b/plugins/builtin/include/content/views/view_pattern_editor.hpp @@ -40,8 +40,12 @@ namespace hex::plugin::builtin { return &m_editorRuntime; } - ui::TextEditor &getTextEditor() { - return m_textEditor; + ui::TextEditor *getTextEditor() { + auto provider = ImHexApi::Provider::get(); + if (provider == nullptr) + return nullptr; + + return &m_textEditor.get(provider); } bool getChangesWereParsed() const { diff --git a/plugins/builtin/source/content/text_highlighting/pattern_language.cpp b/plugins/builtin/source/content/text_highlighting/pattern_language.cpp index 1e019a24d..50cb2aeca 100644 --- a/plugins/builtin/source/content/text_highlighting/pattern_language.cpp +++ b/plugins/builtin/source/content/text_highlighting/pattern_language.cpp @@ -1252,7 +1252,11 @@ namespace hex::plugin::builtin { } } } - m_viewPatternEditor->getTextEditor().setErrorMarkers(errorMarkers); + ui::TextEditor *editor = m_viewPatternEditor->getTextEditor(); + if (editor != nullptr) + editor->setErrorMarkers(errorMarkers); + else + log::warn("Text editor not found, provider is null"); } // creates a map from variable names to a vector of token indices @@ -1590,7 +1594,11 @@ namespace hex::plugin::builtin { lineOfColors[tokenOffset + j] = color; } } - m_viewPatternEditor->getTextEditor().setColorizedLine(line, lineOfColors); + ui::TextEditor *editor = m_viewPatternEditor->getTextEditor(); + if (editor != nullptr) + editor->setColorizedLine(line, lineOfColors); + else + log::warn("Text editor not found, provider is null"); } } @@ -1918,8 +1926,13 @@ namespace hex::plugin::builtin { if (!m_lines.empty()) m_lines.clear(); - if (m_text.empty()) - m_text = m_viewPatternEditor->getTextEditor().getText(); + if (m_text.empty()) { + ui::TextEditor *editor = m_viewPatternEditor->getTextEditor(); + if (editor != nullptr) + m_text = editor->getText(); + else + log::warn("Text editor not found, provider is null"); + } m_lines = wolv::util::splitString(m_text, "\n"); m_lines.push_back(""); @@ -2248,72 +2261,85 @@ namespace hex::plugin::builtin { } }; try { - m_runningColorizers++; - auto preprocessor = patternLanguage->get()->getInternals().preprocessor.get(); - auto parser = patternLanguage->get()->getInternals().parser.get(); - using Types = std::map>; - Types types = parser->getTypes(); + m_runningColorizers++; + auto preprocessor = patternLanguage->get()->getInternals().preprocessor.get(); + auto parser = patternLanguage->get()->getInternals().parser.get(); + using Types = std::map>; + Types types = parser->getTypes(); - if (!m_UDTs.empty()) - m_UDTs.clear(); - for (auto &[name, type]: types) - m_UDTs.push_back(name); + if (!m_UDTs.empty()) + m_UDTs.clear(); + for (auto &[name, type]: types) + m_UDTs.push_back(name); - // Namespaces from included files. - m_nameSpaces.clear(); - m_nameSpaces = preprocessor->getNamespaces(); - clearVariables(); + // Namespaces from included files. + m_nameSpaces.clear(); + m_nameSpaces = preprocessor->getNamespaces(); + clearVariables(); + + m_parsedImports = preprocessor->getParsedImports(); + for (auto &[name, tokens]: m_parsedImports) { + m_tokens = tokens; + m_text = tokens[0].location.source->content; + if (m_text.empty() || m_text == "\n") + return; + loadText(); + processSource(); + if (!m_tokenColors.empty()) + m_tokenColors.clear(); + } + + m_tokens = preprocessor->getResult(); + if (m_tokens.empty()) + return; + + if (!m_globalTokenRange.empty()) + m_globalTokenRange.clear(); + m_globalTokenRange.insert(Interval(0, m_tokens.size()-1)); + + ui::TextEditor *editor = m_viewPatternEditor->getTextEditor(); + if (editor != nullptr) + m_text = editor->getText(); + else + log::warn("Text editor not found, provider is null"); - m_parsedImports = preprocessor->getParsedImports(); - for (auto &[name, tokens]: m_parsedImports) { - m_tokens = tokens; - m_text = tokens[0].location.source->content; if (m_text.empty() || m_text == "\n") return; loadText(); - processSource(); - if (!m_tokenColors.empty()) - m_tokenColors.clear(); - } - m_tokens = preprocessor->getResult(); - if (m_tokens.empty()) - return; + getAllTokenRanges(IdentifierType::NameSpace); + getAllTokenRanges(IdentifierType::UDT); + getAllTokenRanges(IdentifierType::Function); + getGlobalTokenRanges(); + fixGlobalVariables(); + setInitialColors(); + loadInstances(); + getAllTokenRanges(IdentifierType::Attribute); + getDefinitions(); + fixAutos(); + fixChains(); - if (!m_globalTokenRange.empty()) - m_globalTokenRange.clear(); - m_globalTokenRange.insert(Interval(0, m_tokens.size()-1)); + m_excludedLocations = preprocessor->getExcludedLocations(); - m_text = m_viewPatternEditor->getTextEditor().getText(); + colorRemainingIdentifierTokens(); + setRequestedIdentifierColors(); - if (m_text.empty() || m_text == "\n") - return; - loadText(); + editor = m_viewPatternEditor->getTextEditor(); + if (editor != nullptr) + editor->clearErrorMarkers(); + else + log::warn("Text editor not found, provider is null"); + m_compileErrors = patternLanguage->get()->getCompileErrors(); - getAllTokenRanges(IdentifierType::NameSpace); - getAllTokenRanges(IdentifierType::UDT); - getAllTokenRanges(IdentifierType::Function); - getGlobalTokenRanges(); - fixGlobalVariables(); - setInitialColors(); - loadInstances(); - getAllTokenRanges(IdentifierType::Attribute); - getDefinitions(); - fixAutos(); - fixChains(); - - m_excludedLocations = preprocessor->getExcludedLocations(); - - colorRemainingIdentifierTokens(); - setRequestedIdentifierColors(); - - m_viewPatternEditor->getTextEditor().clearErrorMarkers(); - m_compileErrors = patternLanguage->get()->getCompileErrors(); - - if (!m_compileErrors.empty()) - renderErrors(); - else - m_viewPatternEditor->getTextEditor().clearErrorMarkers(); + if (!m_compileErrors.empty()) + renderErrors(); + else { + editor = m_viewPatternEditor->getTextEditor(); + if (editor != nullptr) + editor->clearErrorMarkers(); + else + log::warn("Text editor not found, provider is null"); + } } catch (const std::out_of_range &e) { log::debug("TextHighlighter::highlightSourceCode: Out of range error: {}", e.what()); m_wasInterrupted = true; @@ -2321,4 +2347,4 @@ namespace hex::plugin::builtin { } return; } -} \ No newline at end of file +} diff --git a/plugins/builtin/source/content/views/view_pattern_editor.cpp b/plugins/builtin/source/content/views/view_pattern_editor.cpp index 8a855b422..d21ffc721 100644 --- a/plugins/builtin/source/content/views/view_pattern_editor.cpp +++ b/plugins/builtin/source/content/views/view_pattern_editor.cpp @@ -45,6 +45,7 @@ #include #include #include +#include namespace hex::plugin::builtin { @@ -70,6 +71,16 @@ namespace hex::plugin::builtin { return; } + ui::TextEditor *editor = m_view->getTextEditor(); + if (editor != nullptr) { + if (!editor->isEmpty()) { + this->close(); + return; + } + } else { + log::warn("Text editor not found, provider is null"); + } + ImGuiExt::TextFormattedWrapped("{}", static_cast("hex.builtin.view.pattern_editor.accept_pattern.desc"_lang)); if (ImGui::BeginListBox("##patterns_accept", ImVec2(400_scaled, 0))) { diff --git a/plugins/ui/source/ui/text_editor/highlighter.cpp b/plugins/ui/source/ui/text_editor/highlighter.cpp index 33c44ef13..2bdbd2f6f 100644 --- a/plugins/ui/source/ui/text_editor/highlighter.cpp +++ b/plugins/ui/source/ui/text_editor/highlighter.cpp @@ -1,5 +1,6 @@ #include #include +#include #include namespace hex::ui { @@ -50,8 +51,11 @@ namespace hex::ui { std::smatch results; std::string id; - if (m_languageDefinition.m_tokenize == nullptr) + if (m_languageDefinition.m_tokenize == nullptr) { m_languageDefinition.m_tokenize = [](strConstIter, strConstIter, strConstIter &, strConstIter &, PaletteIndex &) { return false; }; + log::warn("Syntax highlighting tokenize callback is nullptr"); + return; + } i32 linesSize = m_lines.size(); for (i32 i = 0; i < linesSize; ++i) { auto &line = m_lines[i]; @@ -74,28 +78,11 @@ namespace hex::ui { PaletteIndex token_color = PaletteIndex::Default; bool hasTokenizeResult = m_languageDefinition.m_tokenize(current.m_charsIter, last.m_charsIter, token_begin, token_end, token_color); - auto token_offset = token_begin - first.m_charsIter; - - if (!hasTokenizeResult) { - // todo : remove - // printf("using regex for %.*s\n", first + 10 < last ? 10 : i32(last - first), first); - - for (auto &p: m_regexList) { - if (std::regex_search(first.m_charsIter, last.m_charsIter, results, p.first, std::regex_constants::match_continuous)) { - hasTokenizeResult = true; - - const auto &v = results.begin(); - token_begin = v->first; - token_end = v->second; - token_color = p.second; - break; - } - } - } if (!hasTokenizeResult) current = current + 1; else { + auto token_offset = token_begin - first.m_charsIter; current = first + token_offset; u64 token_length = 0; Line::Flags flags(0); @@ -1181,4 +1168,4 @@ namespace hex::ui { return false; } -} \ No newline at end of file +}