From 7117592f38860eb80bec85df5abea52e5b867b20 Mon Sep 17 00:00:00 2001
From: WerWolv <werwolv98@gmail.com>
Date: Wed, 16 Feb 2022 14:57:13 +0100
Subject: [PATCH] sys: Add highlighting provider function support, move pattern
 highlighting code out of hex editor

---
 lib/libimhex/include/hex/api/imhex_api.hpp    | 24 +++++++---
 lib/libimhex/source/api/imhex_api.cpp         | 48 +++++++++++++++----
 main/source/init/tasks.cpp                    |  3 +-
 .../include/content/views/view_hex_editor.hpp |  8 ++--
 .../source/content/views/view_hex_editor.cpp  | 17 ++++---
 .../content/views/view_pattern_editor.cpp     | 13 +++++
 6 files changed, 83 insertions(+), 30 deletions(-)

diff --git a/lib/libimhex/include/hex/api/imhex_api.hpp b/lib/libimhex/include/hex/api/imhex_api.hpp
index 347525f6f..037ae40a2 100644
--- a/lib/libimhex/include/hex/api/imhex_api.hpp
+++ b/lib/libimhex/include/hex/api/imhex_api.hpp
@@ -3,8 +3,9 @@
 #include <hex.hpp>
 
 #include <list>
-#include <vector>
+#include <optional>
 #include <string>
+#include <vector>
 
 #include <hex/helpers/concepts.hpp>
 #include <hex/api/task.hpp>
@@ -32,21 +33,32 @@ namespace hex {
             class Highlighting {
             public:
                 Highlighting() = default;
-                Highlighting(Region region, color_t color, const std::string &tooltip = "");
+                Highlighting(Region region, color_t color, std::string tooltip = "");
 
                 [[nodiscard]] const Region &getRegion() const { return this->m_region; }
                 [[nodiscard]] const color_t &getColor() const { return this->m_color; }
                 [[nodiscard]] const std::string &getTooltip() const { return this->m_tooltip; }
 
             private:
-                Region m_region;
-                color_t m_color;
+                Region m_region = {};
+                color_t m_color = 0x00;
                 std::string m_tooltip;
             };
 
-            u32 addHighlight(const Region &region, color_t color, std::string tooltip = "");
+            namespace impl {
+
+                using HighlightingFunction = std::function<std::optional<Highlighting>(u64)>;
+
+                std::map<u32, Highlighting> &getHighlights();
+                std::map<u32, HighlightingFunction> &getHighlightingFunctions();
+
+            }
+
+            u32 addHighlight(const Region &region, color_t color, const std::string &tooltip = "");
             void removeHighlight(u32 id);
-            std::map<u32, Highlighting> &getHighlights();
+
+            u32 addHighlightingProvider(const impl::HighlightingFunction &function);
+            void removeHighlightingProvider(u32 id);
 
             Region getSelection();
             void setSelection(const Region &region);
diff --git a/lib/libimhex/source/api/imhex_api.cpp b/lib/libimhex/source/api/imhex_api.cpp
index c324a6edd..58e94a6f6 100644
--- a/lib/libimhex/source/api/imhex_api.cpp
+++ b/lib/libimhex/source/api/imhex_api.cpp
@@ -2,6 +2,7 @@
 
 #include <hex/api/event.hpp>
 #include <hex/providers/provider.hpp>
+#include <utility>
 
 #include <unistd.h>
 
@@ -26,16 +27,29 @@ namespace hex {
 
     namespace ImHexApi::HexEditor {
 
-        static std::map<u32, ImHexApi::HexEditor::Highlighting> s_highlights;
-
-        Highlighting::Highlighting(Region region, color_t color, const std::string &tooltip)
-            : m_region(region), m_color(color), m_tooltip(tooltip) {
+        Highlighting::Highlighting(Region region, color_t color, std::string tooltip)
+            : m_region(region), m_color(color), m_tooltip(std::move(tooltip)) {
         }
 
-        u32 addHighlight(const Region &region, color_t color, std::string tooltip) {
-            auto id = s_highlights.size();
+        namespace impl {
 
-            s_highlights.insert({
+            static std::map<u32, Highlighting> s_highlights;
+            std::map<u32, Highlighting> &getHighlights() {
+                return s_highlights;
+            }
+
+            static std::map<u32, HighlightingFunction> s_highlightingFunctions;
+            std::map<u32, HighlightingFunction> &getHighlightingFunctions() {
+                return s_highlightingFunctions;
+            }
+
+        }
+
+        u32 addHighlight(const Region &region, color_t color, const std::string &tooltip) {
+            auto &highlights = impl::getHighlights();
+            auto id          = highlights.size();
+
+            highlights.insert({
                 id, Highlighting {region, color, tooltip}
             });
 
@@ -45,13 +59,27 @@ namespace hex {
         }
 
         void removeHighlight(u32 id) {
-            s_highlights.erase(id);
+            impl::getHighlights().erase(id);
 
             EventManager::post<EventHighlightingChanged>();
         }
 
-        std::map<u32, Highlighting> &getHighlights() {
-            return s_highlights;
+        u32 addHighlightingProvider(const impl::HighlightingFunction &function) {
+            auto &highlightFuncs = impl::getHighlightingFunctions();
+
+            auto id = highlightFuncs.size();
+
+            highlightFuncs.insert({ id, function });
+
+            EventManager::post<EventHighlightingChanged>();
+
+            return id;
+        }
+
+        void removeHighlightingProvider(u32 id) {
+            impl::getHighlightingFunctions().erase(id);
+
+            EventManager::post<EventHighlightingChanged>();
         }
 
         Region getSelection() {
diff --git a/main/source/init/tasks.cpp b/main/source/init/tasks.cpp
index a439ae463..fc57a928b 100644
--- a/main/source/init/tasks.cpp
+++ b/main/source/init/tasks.cpp
@@ -165,7 +165,8 @@ namespace hex::init {
     bool deleteSharedData() {
         ImHexApi::System::getInitArguments().clear();
         ImHexApi::Tasks::getDeferredCalls().clear();
-        ImHexApi::HexEditor::getHighlights().clear();
+        ImHexApi::HexEditor::impl::getHighlights().clear();
+        ImHexApi::HexEditor::impl::getHighlightingFunctions().clear();
 
         while (ImHexApi::Provider::isValid())
             ImHexApi::Provider::remove(ImHexApi::Provider::get());
diff --git a/plugins/builtin/include/content/views/view_hex_editor.hpp b/plugins/builtin/include/content/views/view_hex_editor.hpp
index f063eedb1..e6fe091eb 100644
--- a/plugins/builtin/include/content/views/view_hex_editor.hpp
+++ b/plugins/builtin/include/content/views/view_hex_editor.hpp
@@ -43,9 +43,9 @@ namespace hex::plugin::builtin {
 
         std::vector<char> m_searchStringBuffer;
         std::vector<char> m_searchHexBuffer;
-        SearchFunction m_searchFunction = nullptr;
-        std::vector<std::pair<u64, u64>> *m_lastSearchBuffer;
-        bool m_searchRequested = false;
+        SearchFunction m_searchFunction                      = nullptr;
+        std::vector<std::pair<u64, u64>> *m_lastSearchBuffer = nullptr;
+        bool m_searchRequested                               = false;
 
         i64 m_lastSearchIndex = 0;
         std::vector<std::pair<u64, u64>> m_lastStringSearch;
@@ -53,7 +53,7 @@ namespace hex::plugin::builtin {
 
         u64 m_gotoAddressAbsolute = 0;
         i64 m_gotoAddressRelative = 0;
-        bool m_gotoRequested = false;
+        bool m_gotoRequested      = false;
 
         char m_baseAddressBuffer[0x20] = { 0 };
         u64 m_resizeSize               = 0;
diff --git a/plugins/builtin/source/content/views/view_hex_editor.cpp b/plugins/builtin/source/content/views/view_hex_editor.cpp
index f41f15d15..34f369e31 100644
--- a/plugins/builtin/source/content/views/view_hex_editor.cpp
+++ b/plugins/builtin/source/content/views/view_hex_editor.cpp
@@ -1,6 +1,8 @@
 #include "content/views/view_hex_editor.hpp"
 
 #include <hex/api/imhex_api.hpp>
+#include <hex/api/content_registry.hpp>
+
 #include <hex/providers/provider.hpp>
 #include <hex/helpers/crypto.hpp>
 #include <hex/helpers/file.hpp>
@@ -9,7 +11,6 @@
 #include <hex/helpers/project_file_handler.hpp>
 #include <hex/helpers/loader_script_handler.hpp>
 
-#include <hex/pattern_language/pattern_data.hpp>
 #include <content/providers/file_provider.hpp>
 
 
@@ -97,7 +98,7 @@ namespace hex::plugin::builtin {
                     std::optional<color_t> highlightColor;
                     std::string highlightTooltip;
 
-                    for (const auto &[id, highlight] : ImHexApi::HexEditor::getHighlights()) {
+                    for (const auto &[id, highlight] : ImHexApi::HexEditor::impl::getHighlights()) {
                         auto &region  = highlight.getRegion();
                         auto &color   = highlight.getColor();
                         auto &tooltip = highlight.getTooltip();
@@ -108,13 +109,11 @@ namespace hex::plugin::builtin {
                         }
                     }
 
-                    auto patterns = provider->getPatternLanguageRuntime().getPatterns();
-                    for (const auto &pattern : patterns) {
-                        auto child = pattern->getPattern(blockStartOffset + i);
-                        if (child != nullptr) {
-                            auto color     = (child->getColor() & 0x00FFFFFF) | alpha;
-                            highlightColor = highlightColor.has_value() ? ImAlphaBlendColors(color, highlightColor.value()) : color;
-                            break;
+                    for (const auto &[id, function] : ImHexApi::HexEditor::impl::getHighlightingFunctions()) {
+                        auto highlight = function(blockStartOffset + i);
+                        if (highlight.has_value()) {
+                            highlightColor   = highlightColor.has_value() ? ImAlphaBlendColors(highlight->getColor(), highlightColor.value()) : highlight->getColor();
+                            highlightTooltip = highlight->getTooltip();
                         }
                     }
 
diff --git a/plugins/builtin/source/content/views/view_pattern_editor.cpp b/plugins/builtin/source/content/views/view_pattern_editor.cpp
index b829f06cd..02cbb3c53 100644
--- a/plugins/builtin/source/content/views/view_pattern_editor.cpp
+++ b/plugins/builtin/source/content/views/view_pattern_editor.cpp
@@ -222,6 +222,19 @@ namespace hex::plugin::builtin {
                     });
             }
         });
+
+
+        ImHexApi::HexEditor::addHighlightingProvider([](u64 address) -> std::optional<ImHexApi::HexEditor::Highlighting> {
+            auto patterns = ImHexApi::Provider::get()->getPatternLanguageRuntime().getPatterns();
+            for (const auto &pattern : patterns) {
+                auto child = pattern->getPattern(address);
+                if (child != nullptr) {
+                    return ImHexApi::HexEditor::Highlighting(Region { address, 1 }, child->getColor(), child->getVariableName());
+                }
+            }
+
+            return std::nullopt;
+        });
     }
 
     ViewPatternEditor::~ViewPatternEditor() {