#pragma once #include #include #include #include #include #include #include #include #include #include #include #include #include namespace pl::ptrn { class Pattern; } namespace hex::plugin::builtin { class ViewPatternEditor : public View { public: ViewPatternEditor(); ~ViewPatternEditor() override; void drawAlwaysVisible() override; void drawContent() override; private: enum class DangerousFunctionPerms : u8 { Ask, Allow, Deny }; class PopupAcceptPattern : public Popup { public: explicit PopupAcceptPattern(ViewPatternEditor *view) : Popup("hex.builtin.view.pattern_editor.accept_pattern"), m_view(view) {} void drawContent() override { auto* provider = ImHexApi::Provider::get(); ImGui::TextFormattedWrapped("{}", static_cast("hex.builtin.view.pattern_editor.accept_pattern.desc"_lang)); std::vector entries; entries.resize(this->m_view->m_possiblePatternFiles.get(provider).size()); for (u32 i = 0; i < entries.size(); i++) { entries[i] = wolv::util::toUTF8String(this->m_view->m_possiblePatternFiles.get(provider)[i].filename()); } if (ImGui::BeginListBox("##patterns_accept", ImVec2(-FLT_MIN, 0))) { u32 index = 0; for (auto &path : this->m_view->m_possiblePatternFiles.get(provider)) { if (ImGui::Selectable(wolv::util::toUTF8String(path.filename()).c_str(), index == this->m_selectedPatternFile, ImGuiSelectableFlags_DontClosePopups)) this->m_selectedPatternFile = index; if (ImGui::IsItemHovered() && ImGui::IsMouseDoubleClicked(0)) this->m_view->loadPatternFile(this->m_view->m_possiblePatternFiles.get(provider)[this->m_selectedPatternFile], provider); ImGui::InfoTooltip(wolv::util::toUTF8String(path).c_str()); index++; } // Close the popup if there aren't any patterns available if (index == 0) this->close(); ImGui::EndListBox(); } ImGui::NewLine(); ImGui::TextUnformatted("hex.builtin.view.pattern_editor.accept_pattern.question"_lang); confirmButtons("hex.builtin.common.yes"_lang, "hex.builtin.common.no"_lang, [this, provider] { this->m_view->loadPatternFile(this->m_view->m_possiblePatternFiles.get(provider)[this->m_selectedPatternFile], provider); this->close(); }, [this] { this->close(); } ); if (ImGui::IsKeyPressed(ImGuiKey_Escape)) this->close(); } [[nodiscard]] ImGuiWindowFlags getFlags() const override { return ImGuiWindowFlags_AlwaysAutoResize | ImGuiWindowFlags_NoResize; } private: ViewPatternEditor *m_view; u32 m_selectedPatternFile = 0; }; private: struct PatternVariable { bool inVariable; bool outVariable; pl::core::Token::ValueType type; pl::core::Token::Literal value; }; enum class EnvVarType { Integer, Float, String, Bool }; struct EnvVar { u64 id; std::string name; pl::core::Token::Literal value; EnvVarType type; bool operator==(const EnvVar &other) const { return this->id == other.id; } }; struct AccessData { float progress; u32 color; }; std::unique_ptr m_parserRuntime; PerProvider> m_possiblePatternFiles; bool m_runAutomatically = false; bool m_triggerEvaluation = false; std::atomic m_triggerAutoEvaluate = false; bool m_lastEvaluationProcessed = true; bool m_lastEvaluationResult = false; std::atomic m_runningEvaluators = 0; std::atomic m_runningParsers = 0; bool m_hasUnevaluatedChanges = false; TextEditor m_textEditor, m_consoleEditor; std::atomic m_consoleNeedsUpdate = false; std::atomic m_dangerousFunctionCalled = false; std::atomic m_dangerousFunctionsAllowed = DangerousFunctionPerms::Ask; bool m_syncPatternSourceCode = false; bool m_autoLoadPatterns = true; std::map> m_sectionWindowDrawer; ui::HexEditor m_sectionHexEditor; PerProvider m_sourceCode; PerProvider> m_console; PerProvider m_executionDone = true; std::mutex m_logMutex; PerProvider> m_lastEvaluationError; PerProvider> m_lastEvaluationOutVars; PerProvider> m_patternVariables; PerProvider> m_sections; PerProvider> m_envVarEntries; PerProvider m_shouldAnalyze; PerProvider m_breakpointHit; PerProvider> m_debuggerDrawer; std::atomic m_resetDebuggerVariables; int m_debuggerScopeIndex = 0; std::array m_accessHistory; u32 m_accessHistoryIndex = 0; private: void drawConsole(ImVec2 size); void drawEnvVars(ImVec2 size, std::list &envVars); void drawVariableSettings(ImVec2 size, std::map &patternVariables); void drawSectionSelector(ImVec2 size, const std::map §ions); void drawDebugger(ImVec2 size); void drawPatternTooltip(pl::ptrn::Pattern *pattern); void loadPatternFile(const std::fs::path &path, prv::Provider *provider); void parsePattern(const std::string &code, prv::Provider *provider); void evaluatePattern(const std::string &code, prv::Provider *provider); void registerEvents(); void registerMenuItems(); void registerHandlers(); void appendEditorText(const std::string &text); void appendVariable(const std::string &type); void appendArray(const std::string &type, size_t size); }; }