diff --git a/lib/external/pattern_language b/lib/external/pattern_language index 22cfecfbf..2fc96aedc 160000 --- a/lib/external/pattern_language +++ b/lib/external/pattern_language @@ -1 +1 @@ -Subproject commit 22cfecfbffbc6dee4879b9f9cfaedc943aca5bd6 +Subproject commit 2fc96aedca0f665957eec878d75403eff7de5a91 diff --git a/main/source/window/window.cpp b/main/source/window/window.cpp index 202630971..391696744 100644 --- a/main/source/window/window.cpp +++ b/main/source/window/window.cpp @@ -692,6 +692,7 @@ namespace hex { style.WindowRounding = 0.0F; io.ConfigFlags |= ImGuiConfigFlags_DockingEnable | ImGuiConfigFlags_NavEnableKeyboard; + io.ConfigWindowsMoveFromTitleBarOnly = true; if (glfwGetPrimaryMonitor() != nullptr) { auto sessionType = hex::getEnvironmentVariable("XDG_SESSION_TYPE"); diff --git a/plugins/builtin/include/content/helpers/hex_editor.hpp b/plugins/builtin/include/content/helpers/hex_editor.hpp index 560f1f259..0fba7d0f5 100644 --- a/plugins/builtin/include/content/helpers/hex_editor.hpp +++ b/plugins/builtin/include/content/helpers/hex_editor.hpp @@ -21,22 +21,27 @@ namespace hex { class HexEditor { public: + HexEditor(); ~HexEditor(); - HexEditor(std::optional **selectionStart, std::optional **selectionEnd, float **scrollPosition); - void draw(); + void draw(prv::Provider *provider, float height = ImGui::GetContentRegionAvail().y); private: enum class CellType { None, Hex, ASCII }; - void drawCell(u64 address, u8 *data, size_t size, bool hovered, CellType cellType); + void drawCell(prv::Provider *provider, u64 address, u8 *data, size_t size, bool hovered, CellType cellType); void drawSelectionFrame(u32 x, u32 y, u64 byteAddress, u16 bytesPerCell, const ImVec2 &cellPos, const ImVec2 &cellSize) const; - void drawEditor(const ImVec2 &size); - void drawFooter(const ImVec2 &size); + void drawEditor(prv::Provider *provider, const ImVec2 &size); + void drawFooter(prv::Provider *provider, const ImVec2 &size); + void drawTooltip(u64 address, const u8 *data, size_t size); void handleSelection(u64 address, u32 bytesPerCell, const u8 *data, bool cellHovered); std::optional applySelectionColor(u64 byteAddress, std::optional color); public: + void setSelectionUnchecked(std::optional start, std::optional end) { + this->m_selectionStart = start; + this->m_selectionEnd = end; + } void setSelection(const Region ®ion) { this->setSelection(region.getStartAddress(), region.getEndAddress()); } void setSelection(u128 start, u128 end) { if (!ImHexApi::Provider::isValid()) @@ -46,10 +51,10 @@ namespace hex { const size_t maxAddress = provider->getActualSize() + provider->getBaseAddress() - 1; - this->m_selectionChanged = **this->m_selectionStart != start || **this->m_selectionEnd != end; + this->m_selectionChanged = this->m_selectionStart != start || this->m_selectionEnd != end; - **this->m_selectionStart = std::clamp(start, 0, maxAddress); - **this->m_selectionEnd = std::clamp(end, 0, maxAddress); + this->m_selectionStart = std::clamp(start, 0, maxAddress); + this->m_selectionEnd = std::clamp(end, 0, maxAddress); if (this->m_selectionChanged) { EventManager::post(this->getSelection()); @@ -61,15 +66,15 @@ namespace hex { if (!isSelectionValid()) return Region::Invalid(); - const auto start = std::min((*this->m_selectionStart)->value(), (*this->m_selectionEnd)->value()); - const auto end = std::max((*this->m_selectionStart)->value(), (*this->m_selectionEnd)->value()); + const auto start = std::min(this->m_selectionStart.value(), this->m_selectionEnd.value()); + const auto end = std::max(this->m_selectionStart.value(), this->m_selectionEnd.value()); const size_t size = end - start + 1; return { start, size }; } [[nodiscard]] bool isSelectionValid() const { - return (*this->m_selectionStart)->has_value() && (*this->m_selectionEnd)->has_value(); + return this->m_selectionStart.has_value() && this->m_selectionEnd.has_value(); } void jumpToSelection(bool center = true) { @@ -135,10 +140,30 @@ namespace hex { this->m_shouldUpdateScrollPosition = true; } + void setForegroundHighlightCallback(const std::function(u64, const u8 *, size_t)> &callback) { + this->m_foregroundColorCallback = callback; + } + + void setBackgroundHighlightCallback(const std::function(u64, const u8 *, size_t)> &callback) { + this->m_backgroundColorCallback = callback; + } + + void setTooltipCallback(const std::function &callback) { + this->m_tooltipCallback = callback; + } + + [[nodiscard]] float getScrollPosition() const { + return this->m_scrollPosition; + } + + void setScrollPosition(float scrollPosition) { + this->m_scrollPosition = scrollPosition; + } + private: - std::optional **m_selectionStart; - std::optional **m_selectionEnd; - float **m_scrollPosition; + std::optional m_selectionStart; + std::optional m_selectionEnd; + float m_scrollPosition = 0; u16 m_bytesPerRow = 16; ContentRegistry::HexEditor::DataVisualizer *m_currDataVisualizer; @@ -169,6 +194,11 @@ namespace hex { u32 m_byteCellPadding = 0, m_characterCellPadding = 0; std::optional m_currCustomEncoding; + + static std::optional defaultColorCallback(u64, const u8 *, size_t) { return std::nullopt; } + static void defaultTooltipCallback(u64, const u8 *, size_t) { } + std::function(u64, const u8 *, size_t)> m_foregroundColorCallback = defaultColorCallback, m_backgroundColorCallback = defaultColorCallback; + std::function m_tooltipCallback = defaultTooltipCallback; }; } \ No newline at end of file diff --git a/plugins/builtin/include/content/helpers/provider_extra_data.hpp b/plugins/builtin/include/content/helpers/provider_extra_data.hpp index 28df90c99..e90064382 100644 --- a/plugins/builtin/include/content/helpers/provider_extra_data.hpp +++ b/plugins/builtin/include/content/helpers/provider_extra_data.hpp @@ -53,6 +53,7 @@ namespace hex::plugin::builtin { std::vector> lastEvaluationLog; std::map lastEvaluationOutVars; std::map patternVariables; + std::map sections; std::list envVarEntries; } patternLanguage; diff --git a/plugins/builtin/include/content/providers/disk_provider.hpp b/plugins/builtin/include/content/providers/disk_provider.hpp index ea9127844..c2bcbbdc5 100644 --- a/plugins/builtin/include/content/providers/disk_provider.hpp +++ b/plugins/builtin/include/content/providers/disk_provider.hpp @@ -11,7 +11,7 @@ #include #endif -namespace hex::plugin::builtin::prv { +namespace hex::plugin::builtin { class DiskProvider : public hex::prv::Provider { public: diff --git a/plugins/builtin/include/content/providers/file_provider.hpp b/plugins/builtin/include/content/providers/file_provider.hpp index fb4c3c844..61da65cc8 100644 --- a/plugins/builtin/include/content/providers/file_provider.hpp +++ b/plugins/builtin/include/content/providers/file_provider.hpp @@ -15,7 +15,7 @@ #include #endif -namespace hex::plugin::builtin::prv { +namespace hex::plugin::builtin { class FileProvider : public hex::prv::Provider { public: diff --git a/plugins/builtin/include/content/providers/gdb_provider.hpp b/plugins/builtin/include/content/providers/gdb_provider.hpp index 3557c4f03..9118dd907 100644 --- a/plugins/builtin/include/content/providers/gdb_provider.hpp +++ b/plugins/builtin/include/content/providers/gdb_provider.hpp @@ -8,7 +8,7 @@ #include #include -namespace hex::plugin::builtin::prv { +namespace hex::plugin::builtin { class GDBProvider : public hex::prv::Provider { public: diff --git a/plugins/builtin/include/content/providers/intel_hex_provider.hpp b/plugins/builtin/include/content/providers/intel_hex_provider.hpp index 5a0e8a64f..9e789bd44 100644 --- a/plugins/builtin/include/content/providers/intel_hex_provider.hpp +++ b/plugins/builtin/include/content/providers/intel_hex_provider.hpp @@ -4,7 +4,7 @@ #include -namespace hex::plugin::builtin::prv { +namespace hex::plugin::builtin { class IntelHexProvider : public hex::prv::Provider { public: diff --git a/plugins/builtin/include/content/providers/memory_file_provider.hpp b/plugins/builtin/include/content/providers/memory_file_provider.hpp index b94e02ada..b26267eb3 100644 --- a/plugins/builtin/include/content/providers/memory_file_provider.hpp +++ b/plugins/builtin/include/content/providers/memory_file_provider.hpp @@ -3,7 +3,7 @@ #include #include -namespace hex::plugin::builtin::prv { +namespace hex::plugin::builtin { class MemoryFileProvider : public hex::prv::Provider { public: diff --git a/plugins/builtin/include/content/providers/motorola_srec_provider.hpp b/plugins/builtin/include/content/providers/motorola_srec_provider.hpp index db911cdd9..7bfa443ef 100644 --- a/plugins/builtin/include/content/providers/motorola_srec_provider.hpp +++ b/plugins/builtin/include/content/providers/motorola_srec_provider.hpp @@ -2,7 +2,7 @@ #include -namespace hex::plugin::builtin::prv { +namespace hex::plugin::builtin { class MotorolaSRECProvider : public IntelHexProvider { public: diff --git a/plugins/builtin/include/content/providers/null_provider.hpp b/plugins/builtin/include/content/providers/null_provider.hpp index 7bf697bcb..583158ca1 100644 --- a/plugins/builtin/include/content/providers/null_provider.hpp +++ b/plugins/builtin/include/content/providers/null_provider.hpp @@ -2,7 +2,7 @@ #include -namespace hex::plugin::builtin::prv { +namespace hex::plugin::builtin { class NullProvider : public hex::prv::Provider { public: diff --git a/plugins/builtin/include/content/views/view_bookmarks.hpp b/plugins/builtin/include/content/views/view_bookmarks.hpp index 2c17e39b8..7ff4ebdfe 100644 --- a/plugins/builtin/include/content/views/view_bookmarks.hpp +++ b/plugins/builtin/include/content/views/view_bookmarks.hpp @@ -15,8 +15,8 @@ namespace hex::plugin::builtin { void drawContent() override; private: - static bool importBookmarks(prv::Provider *provider, const nlohmann::json &json); - static bool exportBookmarks(prv::Provider *provider, nlohmann::json &json); + static bool importBookmarks(hex::prv::Provider *provider, const nlohmann::json &json); + static bool exportBookmarks(hex::prv::Provider *provider, nlohmann::json &json); void registerMenuItems(); private: diff --git a/plugins/builtin/include/content/views/view_hex_editor.hpp b/plugins/builtin/include/content/views/view_hex_editor.hpp index 753778bc9..c7d34e4b4 100644 --- a/plugins/builtin/include/content/views/view_hex_editor.hpp +++ b/plugins/builtin/include/content/views/view_hex_editor.hpp @@ -14,7 +14,7 @@ namespace hex::plugin::builtin { class ViewHexEditor : public View { public: ViewHexEditor(); - ~ViewHexEditor(); + ~ViewHexEditor() override; void drawContent() override; @@ -44,23 +44,23 @@ namespace hex::plugin::builtin { } bool isSelectionValid() { - return this->m_hexEditor->isSelectionValid(); + return this->m_hexEditor.isSelectionValid(); } Region getSelection() { - return this->m_hexEditor->getSelection(); + return this->m_hexEditor.getSelection(); } void setSelection(const Region ®ion) { - this->m_hexEditor->setSelection(region); + this->m_hexEditor.setSelection(region); } void setSelection(u128 start, u128 end) { - this->m_hexEditor->setSelection(start, end); + this->m_hexEditor.setSelection(start, end); } void jumpToSelection() { - this->m_hexEditor->jumpToSelection(); + this->m_hexEditor.jumpToSelection(); } private: @@ -70,13 +70,10 @@ namespace hex::plugin::builtin { void registerEvents(); void registerMenuItems(); - std::unique_ptr m_hexEditor; + HexEditor m_hexEditor; bool m_shouldOpenPopup = false; std::unique_ptr m_currPopup; - - std::optional *m_selectionStart, *m_selectionEnd; - float *m_scrollPosition; }; } \ No newline at end of file diff --git a/plugins/builtin/include/content/views/view_pattern_data.hpp b/plugins/builtin/include/content/views/view_pattern_data.hpp index 8265d9e27..2f4491715 100644 --- a/plugins/builtin/include/content/views/view_pattern_data.hpp +++ b/plugins/builtin/include/content/views/view_pattern_data.hpp @@ -4,6 +4,7 @@ #include #include +#include #include #include @@ -18,7 +19,7 @@ namespace hex::plugin::builtin { void drawContent() override; private: - std::map> m_sortedPatterns; + std::map> m_sortedPatterns; hex::PatternDrawer m_patternDrawer; }; diff --git a/plugins/builtin/include/content/views/view_pattern_editor.hpp b/plugins/builtin/include/content/views/view_pattern_editor.hpp index 42756812f..5add04995 100644 --- a/plugins/builtin/include/content/views/view_pattern_editor.hpp +++ b/plugins/builtin/include/content/views/view_pattern_editor.hpp @@ -4,7 +4,10 @@ #include #include #include + #include +#include +#include #include #include @@ -60,10 +63,14 @@ namespace hex::plugin::builtin { bool m_syncPatternSourceCode = false; bool m_autoLoadPatterns = true; + std::unique_ptr m_sectionProvider = nullptr; + HexEditor m_hexEditor; + private: void drawConsole(ImVec2 size, const std::vector> &console); void drawEnvVars(ImVec2 size, std::list &envVars); void drawVariableSettings(ImVec2 size, std::map &patternVariables); + void drawSectionSelector(ImVec2 size, std::map §ions); void drawPatternTooltip(pl::ptrn::Pattern *pattern); diff --git a/plugins/builtin/source/content/events.cpp b/plugins/builtin/source/content/events.cpp index b91ceae77..0bf44b6fd 100644 --- a/plugins/builtin/source/content/events.cpp +++ b/plugins/builtin/source/content/events.cpp @@ -19,7 +19,7 @@ namespace hex::plugin::builtin { static void openFile(const std::fs::path &path) { auto provider = ImHexApi::Provider::createProvider("hex.builtin.provider.file", true); - if (auto *fileProvider = dynamic_cast(provider); fileProvider != nullptr) { + if (auto *fileProvider = dynamic_cast(provider); fileProvider != nullptr) { fileProvider->setPath(path); if (fileProvider->open()) EventManager::post(fileProvider); diff --git a/plugins/builtin/source/content/helpers/hex_editor.cpp b/plugins/builtin/source/content/helpers/hex_editor.cpp index ff6509f2b..7461fdf96 100644 --- a/plugins/builtin/source/content/helpers/hex_editor.cpp +++ b/plugins/builtin/source/content/helpers/hex_editor.cpp @@ -70,8 +70,7 @@ namespace hex { /* Hex Editor */ - HexEditor::HexEditor(std::optional **selectionStart, std::optional **selectionEnd, float **scrollPosition) - : m_selectionStart(selectionStart), m_selectionEnd(selectionEnd), m_scrollPosition(scrollPosition) { + HexEditor::HexEditor() { this->m_currDataVisualizer = ContentRegistry::HexEditor::impl::getVisualizers()["hex.builtin.visualizer.hexadecimal.8bit"]; this->m_grayZeroHighlighter = ImHexApi::HexEditor::addForegroundHighlightingProvider([this](u64 address, const u8 *data, size_t size, bool hasColor) -> std::optional { @@ -174,42 +173,6 @@ namespace hex { return currColumn > 0 && (currColumn) < columnCount && ((currColumn) % 8) == 0; } - static std::optional queryBackgroundColor(u64 address, const u8 *data, size_t size) { - std::optional result; - for (const auto &[id, callback] : ImHexApi::HexEditor::impl::getBackgroundHighlightingFunctions()) { - if (auto color = callback(address, data, size, result.has_value()); color.has_value()) - return color.value(); - } - - if (result.has_value()) - return result; - - for (const auto &[id, highlighting] : ImHexApi::HexEditor::impl::getBackgroundHighlights()) { - if (highlighting.getRegion().overlaps({ address, size })) - return highlighting.getColor(); - } - - return std::nullopt; - } - - static std::optional queryForegroundColor(u64 address, const u8 *data, size_t size) { - std::optional result; - for (const auto &[id, callback] : ImHexApi::HexEditor::impl::getForegroundHighlightingFunctions()) { - if (auto color = callback(address, data, size, result.has_value()); color.has_value()) - result = color; - } - - if (result.has_value()) - return result; - - for (const auto &[id, highlighting] : ImHexApi::HexEditor::impl::getForegroundHighlights()) { - if (highlighting.getRegion().overlaps({ address, size })) - return highlighting.getColor(); - } - - return std::nullopt; - } - std::optional HexEditor::applySelectionColor(u64 byteAddress, std::optional color) { if (isSelectionValid()) { auto selection = getSelection(); @@ -234,13 +197,12 @@ namespace hex { ImColor color; }; - static CustomEncodingData queryCustomEncodingData(const EncodingFile &encodingFile, u64 address) { + static CustomEncodingData queryCustomEncodingData(prv::Provider *provider, const EncodingFile &encodingFile, u64 address) { const auto longestSequence = encodingFile.getLongestSequence(); if (longestSequence == 0) return { ".", 1, 0xFFFF8000 }; - auto provider = ImHexApi::Provider::get(); size_t size = std::min(longestSequence, provider->getActualSize() - address); std::vector buffer(size); @@ -267,41 +229,17 @@ namespace hex { return ImGui::GetCursorScreenPos() - ImGui::GetStyle().CellPadding; } - static void drawTooltip(u64 address, const u8 *data, size_t size) { + void HexEditor::drawTooltip(u64 address, const u8 *data, size_t size) { ImGui::PushStyleVar(ImGuiStyleVar_WindowPadding, scaled(ImVec2(5, 5))); - for (const auto &[id, callback] : ImHexApi::HexEditor::impl::getTooltipFunctions()) { - callback(address, data, size); - } - - for (const auto &[id, tooltip] : ImHexApi::HexEditor::impl::getTooltips()) { - if (tooltip.getRegion().overlaps({ address, size })) { - ImGui::BeginTooltip(); - if (ImGui::BeginTable("##tooltips", 1, ImGuiTableFlags_NoHostExtendX | ImGuiTableFlags_RowBg | ImGuiTableFlags_NoClip)) { - ImGui::TableNextRow(); - ImGui::TableNextColumn(); - - ImGui::ColorButton(tooltip.getValue().c_str(), ImColor(tooltip.getColor())); - ImGui::SameLine(0, 10); - ImGui::TextUnformatted(tooltip.getValue().c_str()); - - ImGui::PushStyleColor(ImGuiCol_TableRowBg, tooltip.getColor()); - ImGui::PushStyleColor(ImGuiCol_TableRowBgAlt, tooltip.getColor()); - ImGui::EndTable(); - ImGui::PopStyleColor(2); - } - ImGui::EndTooltip(); - } - } + this->m_tooltipCallback(address, data, size); ImGui::PopStyleVar(); } - void HexEditor::drawCell(u64 address, u8 *data, size_t size, bool hovered, CellType cellType) { + void HexEditor::drawCell(prv::Provider *provider, u64 address, u8 *data, size_t size, bool hovered, CellType cellType) { static DataVisualizerAscii asciiVisualizer; - auto provider = ImHexApi::Provider::get(); - if (this->m_shouldUpdateEditingValue) { this->m_shouldUpdateEditingValue = false; @@ -396,7 +334,7 @@ namespace hex { drawList->AddLine(cellPos + ImVec2(0, cellSize.y), cellPos + cellSize + ImVec2(1, 0), ImColor(SelectionFrameColor), 1.0F); } - void HexEditor::drawEditor(const ImVec2 &size) { + void HexEditor::drawEditor(prv::Provider *provider, const ImVec2 &size) { const float SeparatorColumWidth = 6_scaled; const auto CharacterSize = ImGui::CalcTextSize("0"); @@ -439,8 +377,7 @@ namespace hex { ImGui::TableNextRow(); ImGui::TableNextColumn(); - if (ImHexApi::Provider::isValid()) { - auto provider = ImHexApi::Provider::get(); + if (provider != nullptr && provider->isReadable()) { std::pair validRegion = { Region::Invalid(), false }; const auto isCurrRegionValid = [&validRegion, &provider](u64 address){ @@ -481,8 +418,8 @@ namespace hex { // Query cell colors if (x < std::ceil(float(validBytes) / bytesPerCell)) { - const auto foregroundColor = queryForegroundColor(byteAddress, &bytes[x * cellBytes], cellBytes); - const auto backgroundColor = queryBackgroundColor(byteAddress, &bytes[x * cellBytes], cellBytes); + const auto foregroundColor = this->m_foregroundColorCallback(byteAddress, &bytes[x * cellBytes], cellBytes); + const auto backgroundColor = this->m_backgroundColorCallback(byteAddress, &bytes[x * cellBytes], cellBytes); cellColors.emplace_back( foregroundColor, @@ -549,7 +486,7 @@ namespace hex { ImGui::PushStyleVar(ImGuiStyleVar_FramePadding, ImVec2(0, 0)); ImGui::PushItemWidth((CharacterSize * maxCharsPerCell).x); if (isCurrRegionValid(byteAddress)) - this->drawCell(byteAddress, &bytes[x * bytesPerCell], bytesPerCell, cellHovered, CellType::Hex); + this->drawCell(provider, byteAddress, &bytes[x * bytesPerCell], bytesPerCell, cellHovered, CellType::Hex); else ImGui::TextFormatted("{}", std::string(maxCharsPerCell, '?')); ImGui::PopItemWidth(); @@ -606,7 +543,7 @@ namespace hex { if (!isCurrRegionValid(byteAddress)) ImGui::TextFormatted("?"); else - this->drawCell(byteAddress, &bytes[x], 1, cellHovered, CellType::ASCII); + this->drawCell(provider, byteAddress, &bytes[x], 1, cellHovered, CellType::ASCII); ImGui::PopItemWidth(); ImGui::PopStyleVar(); } @@ -627,7 +564,7 @@ namespace hex { do { const u64 address = y * this->m_bytesPerRow + offset + provider->getBaseAddress() + provider->getCurrentPageAddress(); - auto result = queryCustomEncodingData(*this->m_currCustomEncoding, address); + auto result = queryCustomEncodingData(provider, *this->m_currCustomEncoding, address); offset += std::max(1, result.advance); encodingData.emplace_back(address, result); @@ -684,13 +621,13 @@ namespace hex { auto fractionPerLine = 1.0 / (this->m_visibleRowCount + 1); if (y == (u64(clipper.DisplayStart) + 3)) { - if (i128((*this->m_selectionEnd)->value() - provider->getBaseAddress() - provider->getCurrentPageAddress()) <= (i64(clipper.DisplayStart + 3) * this->m_bytesPerRow)) { + if (i128(this->m_selectionEnd.value() - provider->getBaseAddress() - provider->getCurrentPageAddress()) <= (i64(clipper.DisplayStart + 3) * this->m_bytesPerRow)) { this->m_shouldScrollToSelection = false; ImGui::SetScrollHereY(fractionPerLine * 5); } } else if (y == (u64(clipper.DisplayEnd) - 1)) { - if (i128((*this->m_selectionEnd)->value() - provider->getBaseAddress() - provider->getCurrentPageAddress()) >= (i64(clipper.DisplayEnd - 2) * this->m_bytesPerRow)) { + if (i128(this->m_selectionEnd.value() - provider->getBaseAddress() - provider->getCurrentPageAddress()) >= (i64(clipper.DisplayEnd - 2) * this->m_bytesPerRow)) { this->m_shouldScrollToSelection = false; ImGui::SetScrollHereY(fractionPerLine * (this->m_visibleRowCount)); } @@ -738,9 +675,9 @@ namespace hex { if (!this->m_syncScrolling) { if (this->m_shouldUpdateScrollPosition) { this->m_shouldUpdateScrollPosition = false; - ImGui::SetScrollY(**this->m_scrollPosition); + ImGui::SetScrollY(this->m_scrollPosition); } else { - **this->m_scrollPosition = ImGui::GetScrollY(); + this->m_scrollPosition = ImGui::GetScrollY(); } } @@ -756,9 +693,8 @@ namespace hex { this->m_enteredEditingMode = false; } - void HexEditor::drawFooter(const ImVec2 &size) { - if (ImHexApi::Provider::isValid()) { - auto provider = ImHexApi::Provider::get(); + void HexEditor::drawFooter(prv::Provider *provider, const ImVec2 &size) { + if (provider != nullptr && provider->isReadable()) { const auto pageCount = provider->getPageCount(); constexpr static u32 MinPage = 1; @@ -835,7 +771,7 @@ namespace hex { drawTooltip(address, data, bytesPerCell); auto endAddress = address + bytesPerCell - 1; - auto &selectionStart = **this->m_selectionStart; + auto &selectionStart = this->m_selectionStart; if (ImGui::IsMouseDragging(ImGuiMouseButton_Left)) { this->setSelection(selectionStart.value_or(address), endAddress); @@ -852,12 +788,14 @@ namespace hex { } } - void HexEditor::draw() { - const auto FooterSize = ImVec2(ImGui::GetContentRegionAvail().x, ImGui::GetTextLineHeightWithSpacing() * 2.3); - const auto TableSize = ImGui::GetContentRegionAvail() - ImVec2(0, FooterSize.y); + void HexEditor::draw(prv::Provider *provider, float height) { + const auto width = ImGui::GetContentRegionAvail().x; - this->drawEditor(TableSize); - this->drawFooter(FooterSize); + const auto FooterSize = ImVec2(width, ImGui::GetTextLineHeightWithSpacing() * 2.3F); + const auto TableSize = ImVec2(width, height - FooterSize.y); + + this->drawEditor(provider, TableSize); + this->drawFooter(provider, FooterSize); this->m_selectionChanged = false; } diff --git a/plugins/builtin/source/content/helpers/pattern_drawer.cpp b/plugins/builtin/source/content/helpers/pattern_drawer.cpp index ffd1ec0da..107307fc3 100644 --- a/plugins/builtin/source/content/helpers/pattern_drawer.cpp +++ b/plugins/builtin/source/content/helpers/pattern_drawer.cpp @@ -118,10 +118,12 @@ namespace hex { } void drawCommentTooltip(const pl::ptrn::Pattern &pattern) { - if (ImGui::IsItemHovered(ImGuiHoveredFlags_AllowWhenBlockedByActiveItem) && pattern.getComment() != nullptr) { - ImGui::BeginTooltip(); - ImGui::TextUnformatted(pattern.getComment()->c_str()); - ImGui::EndTooltip(); + if (ImGui::IsItemHovered(ImGuiHoveredFlags_AllowWhenBlockedByActiveItem)) { + if (auto comment = pattern.getComment(); !comment.empty()) { + ImGui::BeginTooltip(); + ImGui::TextUnformatted(pattern.getComment().c_str()); + ImGui::EndTooltip(); + } } } diff --git a/plugins/builtin/source/content/providers.cpp b/plugins/builtin/source/content/providers.cpp index 88c35ef30..dafd03aaa 100644 --- a/plugins/builtin/source/content/providers.cpp +++ b/plugins/builtin/source/content/providers.cpp @@ -16,13 +16,13 @@ namespace hex::plugin::builtin { void registerProviders() { - ContentRegistry::Provider::add(false); - ContentRegistry::Provider::add(false); - ContentRegistry::Provider::add(); - ContentRegistry::Provider::add(); - ContentRegistry::Provider::add(); - ContentRegistry::Provider::add(); - ContentRegistry::Provider::add(false); + ContentRegistry::Provider::add(false); + ContentRegistry::Provider::add(false); + ContentRegistry::Provider::add(); + ContentRegistry::Provider::add(); + ContentRegistry::Provider::add(); + ContentRegistry::Provider::add(); + ContentRegistry::Provider::add(false); ProjectFile::registerHandler({ .basePath = "providers", diff --git a/plugins/builtin/source/content/providers/disk_provider.cpp b/plugins/builtin/source/content/providers/disk_provider.cpp index d7926de42..6a38f6fa2 100644 --- a/plugins/builtin/source/content/providers/disk_provider.cpp +++ b/plugins/builtin/source/content/providers/disk_provider.cpp @@ -24,7 +24,7 @@ #define lseek lseek64 #endif -namespace hex::plugin::builtin::prv { +namespace hex::plugin::builtin { DiskProvider::DiskProvider() : Provider() { diff --git a/plugins/builtin/source/content/providers/file_provider.cpp b/plugins/builtin/source/content/providers/file_provider.cpp index 3207cb899..00682dad6 100644 --- a/plugins/builtin/source/content/providers/file_provider.cpp +++ b/plugins/builtin/source/content/providers/file_provider.cpp @@ -10,7 +10,7 @@ #include -namespace hex::plugin::builtin::prv { +namespace hex::plugin::builtin { bool FileProvider::isAvailable() const { return this->m_mappedFile != nullptr; diff --git a/plugins/builtin/source/content/providers/gdb_provider.cpp b/plugins/builtin/source/content/providers/gdb_provider.cpp index 62dc3182f..3bb38e834 100644 --- a/plugins/builtin/source/content/providers/gdb_provider.cpp +++ b/plugins/builtin/source/content/providers/gdb_provider.cpp @@ -13,7 +13,7 @@ #include -namespace hex::plugin::builtin::prv { +namespace hex::plugin::builtin { using namespace std::chrono_literals; diff --git a/plugins/builtin/source/content/providers/intel_hex_provider.cpp b/plugins/builtin/source/content/providers/intel_hex_provider.cpp index 041e71081..7d15cb74e 100644 --- a/plugins/builtin/source/content/providers/intel_hex_provider.cpp +++ b/plugins/builtin/source/content/providers/intel_hex_provider.cpp @@ -10,7 +10,7 @@ #include -namespace hex::plugin::builtin::prv { +namespace hex::plugin::builtin { namespace intel_hex { diff --git a/plugins/builtin/source/content/providers/memory_file_provider.cpp b/plugins/builtin/source/content/providers/memory_file_provider.cpp index 22a568b64..50a2732bb 100644 --- a/plugins/builtin/source/content/providers/memory_file_provider.cpp +++ b/plugins/builtin/source/content/providers/memory_file_provider.cpp @@ -8,7 +8,7 @@ #include #include -namespace hex::plugin::builtin::prv { +namespace hex::plugin::builtin { bool MemoryFileProvider::open() { this->m_data.resize(1); diff --git a/plugins/builtin/source/content/providers/motorola_srec_provider.cpp b/plugins/builtin/source/content/providers/motorola_srec_provider.cpp index 19b40638a..8bd6aece2 100644 --- a/plugins/builtin/source/content/providers/motorola_srec_provider.cpp +++ b/plugins/builtin/source/content/providers/motorola_srec_provider.cpp @@ -6,7 +6,7 @@ #include #include -namespace hex::plugin::builtin::prv { +namespace hex::plugin::builtin { namespace motorola_srec { diff --git a/plugins/builtin/source/content/views/view_hex_editor.cpp b/plugins/builtin/source/content/views/view_hex_editor.cpp index 26045c2d7..bcb07102c 100644 --- a/plugins/builtin/source/content/views/view_hex_editor.cpp +++ b/plugins/builtin/source/content/views/view_hex_editor.cpp @@ -463,14 +463,66 @@ namespace hex::plugin::builtin { /* Hex Editor */ ViewHexEditor::ViewHexEditor() : View("hex.builtin.view.hex_editor.name") { - this->m_hexEditor = std::make_unique(&this->m_selectionStart, &this->m_selectionEnd, &this->m_scrollPosition); + this->m_hexEditor.setForegroundHighlightCallback([](u64 address, const u8 *data, size_t size) -> std::optional { + std::optional result; + for (const auto &[id, callback] : ImHexApi::HexEditor::impl::getForegroundHighlightingFunctions()) { + if (auto color = callback(address, data, size, result.has_value()); color.has_value()) + result = color; + } - EventManager::subscribe(this, [this](auto *, auto *newProvider) { - auto &data = ProviderExtraData::get(newProvider).editor; + if (result.has_value()) + return result; - this->m_selectionStart = &data.selectionStart; - this->m_selectionEnd = &data.selectionEnd; - this->m_scrollPosition = &data.scrollPosition; + for (const auto &[id, highlighting] : ImHexApi::HexEditor::impl::getForegroundHighlights()) { + if (highlighting.getRegion().overlaps({ address, size })) + return highlighting.getColor(); + } + + return std::nullopt; + }); + + this->m_hexEditor.setBackgroundHighlightCallback([](u64 address, const u8 *data, size_t size) -> std::optional { + std::optional result; + for (const auto &[id, callback] : ImHexApi::HexEditor::impl::getBackgroundHighlightingFunctions()) { + if (auto color = callback(address, data, size, result.has_value()); color.has_value()) + return color.value(); + } + + if (result.has_value()) + return result; + + for (const auto &[id, highlighting] : ImHexApi::HexEditor::impl::getBackgroundHighlights()) { + if (highlighting.getRegion().overlaps({ address, size })) + return highlighting.getColor(); + } + + return std::nullopt; + }); + + this->m_hexEditor.setTooltipCallback([](u64 address, const u8 *data, size_t size) { + for (const auto &[id, callback] : ImHexApi::HexEditor::impl::getTooltipFunctions()) { + callback(address, data, size); + } + + for (const auto &[id, tooltip] : ImHexApi::HexEditor::impl::getTooltips()) { + if (tooltip.getRegion().overlaps({ address, size })) { + ImGui::BeginTooltip(); + if (ImGui::BeginTable("##tooltips", 1, ImGuiTableFlags_NoHostExtendX | ImGuiTableFlags_RowBg | ImGuiTableFlags_NoClip)) { + ImGui::TableNextRow(); + ImGui::TableNextColumn(); + + ImGui::ColorButton(tooltip.getValue().c_str(), ImColor(tooltip.getColor())); + ImGui::SameLine(0, 10); + ImGui::TextUnformatted(tooltip.getValue().c_str()); + + ImGui::PushStyleColor(ImGuiCol_TableRowBg, tooltip.getColor()); + ImGui::PushStyleColor(ImGuiCol_TableRowBgAlt, tooltip.getColor()); + ImGui::EndTable(); + ImGui::PopStyleColor(2); + } + ImGui::EndTooltip(); + } + } }); this->registerShortcuts(); @@ -532,7 +584,7 @@ namespace hex::plugin::builtin { void ViewHexEditor::drawContent() { if (ImGui::Begin(View::toWindowName(this->getUnlocalizedName()).c_str(), &this->getWindowOpenState(), ImGuiWindowFlags_NoCollapse | ImGuiWindowFlags_NoNavInputs | ImGuiWindowFlags_NoScrollbar | ImGuiWindowFlags_NoScrollWithMouse)) { - this->m_hexEditor->draw(); + this->m_hexEditor.draw(ImHexApi::Provider::get()); this->drawPopup(); } ImGui::End(); @@ -645,20 +697,20 @@ namespace hex::plugin::builtin { ShortcutManager::addShortcut(this, Keys::Up, [this] { auto selection = getSelection(); - if (selection.getEndAddress() >= this->m_hexEditor->getBytesPerRow()) { - auto pos = selection.getEndAddress() - this->m_hexEditor->getBytesPerRow(); + if (selection.getEndAddress() >= this->m_hexEditor.getBytesPerRow()) { + auto pos = selection.getEndAddress() - this->m_hexEditor.getBytesPerRow(); this->setSelection(pos, pos); - this->m_hexEditor->scrollToSelection(); - this->m_hexEditor->jumpIfOffScreen(); + this->m_hexEditor.scrollToSelection(); + this->m_hexEditor.jumpIfOffScreen(); } }); ShortcutManager::addShortcut(this, Keys::Down, [this] { auto selection = getSelection(); - auto pos = selection.getEndAddress() + this->m_hexEditor->getBytesPerRow(); + auto pos = selection.getEndAddress() + this->m_hexEditor.getBytesPerRow(); this->setSelection(pos, pos); - this->m_hexEditor->scrollToSelection(); - this->m_hexEditor->jumpIfOffScreen(); + this->m_hexEditor.scrollToSelection(); + this->m_hexEditor.jumpIfOffScreen(); }); ShortcutManager::addShortcut(this, Keys::Left, [this] { auto selection = getSelection(); @@ -666,8 +718,8 @@ namespace hex::plugin::builtin { if (selection.getEndAddress() > 0) { auto pos = selection.getEndAddress() - 1; this->setSelection(pos, pos); - this->m_hexEditor->scrollToSelection(); - this->m_hexEditor->jumpIfOffScreen(); + this->m_hexEditor.scrollToSelection(); + this->m_hexEditor.jumpIfOffScreen(); } }); ShortcutManager::addShortcut(this, Keys::Right, [this] { @@ -675,78 +727,78 @@ namespace hex::plugin::builtin { auto pos = selection.getEndAddress() + 1; this->setSelection(pos, pos); - this->m_hexEditor->scrollToSelection(); - this->m_hexEditor->jumpIfOffScreen(); + this->m_hexEditor.scrollToSelection(); + this->m_hexEditor.jumpIfOffScreen(); }); ShortcutManager::addShortcut(this, Keys::PageUp, [this] { auto selection = getSelection(); - u64 visibleByteCount = this->m_hexEditor->getBytesPerRow() * this->m_hexEditor->getVisibleRowCount(); + u64 visibleByteCount = this->m_hexEditor.getBytesPerRow() * this->m_hexEditor.getVisibleRowCount(); if (selection.getEndAddress() >= visibleByteCount) { auto pos = selection.getEndAddress() - visibleByteCount; this->setSelection(pos, pos); - this->m_hexEditor->scrollToSelection(); - this->m_hexEditor->jumpIfOffScreen(); + this->m_hexEditor.scrollToSelection(); + this->m_hexEditor.jumpIfOffScreen(); } }); ShortcutManager::addShortcut(this, Keys::PageDown, [this] { auto selection = getSelection(); - auto pos = selection.getEndAddress() + (this->m_hexEditor->getBytesPerRow() * this->m_hexEditor->getVisibleRowCount()); + auto pos = selection.getEndAddress() + (this->m_hexEditor.getBytesPerRow() * this->m_hexEditor.getVisibleRowCount()); this->setSelection(pos, pos); - this->m_hexEditor->scrollToSelection(); - this->m_hexEditor->jumpIfOffScreen(); + this->m_hexEditor.scrollToSelection(); + this->m_hexEditor.jumpIfOffScreen(); }); // Move selection around ShortcutManager::addShortcut(this, SHIFT + Keys::Up, [this] { auto selection = getSelection(); - this->setSelection(std::max(selection.getStartAddress(), this->m_hexEditor->getBytesPerRow()) - this->m_hexEditor->getBytesPerRow(), selection.getEndAddress()); - this->m_hexEditor->scrollToSelection(); - this->m_hexEditor->jumpIfOffScreen(); + this->setSelection(std::max(selection.getStartAddress(), this->m_hexEditor.getBytesPerRow()) - this->m_hexEditor.getBytesPerRow(), selection.getEndAddress()); + this->m_hexEditor.scrollToSelection(); + this->m_hexEditor.jumpIfOffScreen(); }); ShortcutManager::addShortcut(this, SHIFT + Keys::Down, [this] { auto selection = getSelection(); - this->setSelection(selection.getStartAddress() + this->m_hexEditor->getBytesPerRow(), selection.getEndAddress()); - this->m_hexEditor->scrollToSelection(); - this->m_hexEditor->jumpIfOffScreen(); + this->setSelection(selection.getStartAddress() + this->m_hexEditor.getBytesPerRow(), selection.getEndAddress()); + this->m_hexEditor.scrollToSelection(); + this->m_hexEditor.jumpIfOffScreen(); }); ShortcutManager::addShortcut(this, SHIFT + Keys::Left, [this] { auto selection = getSelection(); this->setSelection(std::max(selection.getStartAddress(), 1) - 1, selection.getEndAddress()); - this->m_hexEditor->scrollToSelection(); - this->m_hexEditor->jumpIfOffScreen(); + this->m_hexEditor.scrollToSelection(); + this->m_hexEditor.jumpIfOffScreen(); }); ShortcutManager::addShortcut(this, SHIFT + Keys::Right, [this] { auto selection = getSelection(); this->setSelection(selection.getStartAddress() + 1, selection.getEndAddress()); - this->m_hexEditor->scrollToSelection(); - this->m_hexEditor->jumpIfOffScreen(); + this->m_hexEditor.scrollToSelection(); + this->m_hexEditor.jumpIfOffScreen(); }); ShortcutManager::addShortcut(this, Keys::PageUp, [this] { auto selection = getSelection(); - u64 visibleByteCount = this->m_hexEditor->getBytesPerRow() * this->m_hexEditor->getVisibleRowCount(); + u64 visibleByteCount = this->m_hexEditor.getBytesPerRow() * this->m_hexEditor.getVisibleRowCount(); if (selection.getEndAddress() >= visibleByteCount) { auto pos = selection.getEndAddress() - visibleByteCount; this->setSelection(pos, selection.getEndAddress()); - this->m_hexEditor->scrollToSelection(); - this->m_hexEditor->jumpIfOffScreen(); + this->m_hexEditor.scrollToSelection(); + this->m_hexEditor.jumpIfOffScreen(); } }); ShortcutManager::addShortcut(this, Keys::PageDown, [this] { auto selection = getSelection(); - auto pos = selection.getEndAddress() + (this->m_hexEditor->getBytesPerRow() * this->m_hexEditor->getVisibleRowCount()); + auto pos = selection.getEndAddress() + (this->m_hexEditor.getBytesPerRow() * this->m_hexEditor.getVisibleRowCount()); this->setSelection(pos, selection.getEndAddress()); - this->m_hexEditor->scrollToSelection(); - this->m_hexEditor->jumpIfOffScreen(); + this->m_hexEditor.scrollToSelection(); + this->m_hexEditor.jumpIfOffScreen(); }); ShortcutManager::addShortcut(this, CTRL + Keys::G, [this] { @@ -826,9 +878,25 @@ namespace hex::plugin::builtin { region = getSelection(); }); - EventManager::subscribe(this, [this](auto, auto) { - this->m_hexEditor->forceUpdateScrollPosition(); + EventManager::subscribe(this, [this](auto *oldProvider, auto *newProvider) { + if (oldProvider != nullptr) { + auto &oldData = ProviderExtraData::get(oldProvider).editor; + auto selection = this->m_hexEditor.getSelection(); + + oldData.selectionStart = selection.getStartAddress(); + oldData.selectionEnd = selection.getEndAddress(); + oldData.scrollPosition = this->m_hexEditor.getScrollPosition(); + } + + if (newProvider != nullptr) { + auto &newData = ProviderExtraData::get(newProvider).editor; + + this->m_hexEditor.setSelectionUnchecked(newData.selectionStart, newData.selectionEnd); + this->m_hexEditor.setScrollPosition(newData.scrollPosition); + } + + this->m_hexEditor.forceUpdateScrollPosition(); if (isSelectionValid()) EventManager::post(getSelection()); }); @@ -867,7 +935,7 @@ namespace hex::plugin::builtin { View::showFileChooserPopup(paths, { {"Thingy Table File", "tbl"} }, [this](const auto &path) { - this->m_hexEditor->setCustomEncoding(EncodingFile(EncodingFile::Type::Thingy, path)); + this->m_hexEditor.setCustomEncoding(EncodingFile(EncodingFile::Type::Thingy, path)); }); } }); diff --git a/plugins/builtin/source/content/views/view_pattern_editor.cpp b/plugins/builtin/source/content/views/view_pattern_editor.cpp index c433c905c..aeb457666 100644 --- a/plugins/builtin/source/content/views/view_pattern_editor.cpp +++ b/plugins/builtin/source/content/views/view_pattern_editor.cpp @@ -129,6 +129,10 @@ namespace hex::plugin::builtin { this->drawVariableSettings(settingsSize, extraData.patternVariables); ImGui::EndTabItem(); } + if (ImGui::BeginTabItem("hex.builtin.view.pattern_editor.sections"_lang)) { + this->drawSectionSelector(settingsSize, extraData.sections); + ImGui::EndTabItem(); + } ImGui::EndTabBar(); } @@ -431,6 +435,58 @@ namespace hex::plugin::builtin { ImGui::EndChild(); } + void ViewPatternEditor::drawSectionSelector(ImVec2 size, std::map §ions) { + if (ImGui::BeginTable("##sections_table", 3, ImGuiTableFlags_SizingStretchProp | ImGuiTableFlags_Borders | ImGuiTableFlags_RowBg | ImGuiTableFlags_ScrollY, size)) { + ImGui::TableSetupScrollFreeze(0, 1); + ImGui::TableSetupColumn("Name", ImGuiTableColumnFlags_WidthStretch, 0.5F); + ImGui::TableSetupColumn("Size", ImGuiTableColumnFlags_WidthStretch, 0.5F); + ImGui::TableSetupColumn("##button", ImGuiTableColumnFlags_WidthFixed, 20_scaled); + + ImGui::TableHeadersRow(); + + for (auto &[id, section] : sections) { + ImGui::PushID(id); + + ImGui::TableNextRow(); + ImGui::TableNextColumn(); + + ImGui::TextUnformatted(section.name.c_str()); + ImGui::TableNextColumn(); + ImGui::TextFormatted("{} | 0x{:02X}", hex::toByteString(section.data.size()), section.data.size()); + ImGui::TableNextColumn(); + if (ImGui::IconButton(ICON_VS_OPEN_PREVIEW, ImGui::GetStyleColorVec4(ImGuiCol_Text))) { + this->m_sectionProvider = std::make_unique(); + this->m_sectionProvider->resize(section.data.size()); + this->m_sectionProvider->writeRaw(0, section.data.data(), section.data.size()); + + this->m_hexEditor.setBackgroundHighlightCallback([this, id](u64 address, const u8 *, size_t) -> std::optional { + if (this->m_runningEvaluators != 0) + return std::nullopt; + if (!ImHexApi::Provider::isValid()) + return std::nullopt; + + std::optional color; + for (const auto &pattern : ProviderExtraData::getCurrent().patternLanguage.runtime->getPatternsAtAddress(address, id)) { + if (pattern->isHidden()) + continue; + + if (color.has_value()) + color = ImAlphaBlendColors(*color, pattern->getColor()); + else + color = pattern->getColor(); + } + + return color; + }); + } + + ImGui::PopID(); + } + + ImGui::EndTable(); + } + } + void ViewPatternEditor::drawAlwaysVisible() { auto provider = ImHexApi::Provider::get(); @@ -470,6 +526,18 @@ namespace hex::plugin::builtin { ImGui::EndPopup(); } + + auto open = this->m_sectionProvider != nullptr && this->m_sectionProvider->isReadable(); + if (open) { + ImGui::SetNextWindowSize(scaled(ImVec2(500, 650)), ImGuiCond_Appearing); + if (ImGui::Begin("hex.builtin.view.pattern_editor.section_popup"_lang, &open)) { + this->m_hexEditor.draw(this->m_sectionProvider.get()); + } + ImGui::End(); + } + + if (!open) + this->m_sectionProvider = nullptr; } @@ -517,12 +585,12 @@ namespace hex::plugin::builtin { ImGui::TableNextColumn(); ImGui::TextFormatted(" {}", pattern->getEndian() == std::endian::little ? "hex.builtin.common.little"_lang : "hex.builtin.common.big"_lang); - if (const auto &comment = pattern->getComment(); comment != nullptr) { + if (const auto &comment = pattern->getComment(); !comment.empty()) { ImGui::TableNextRow(); ImGui::TableNextColumn(); ImGui::TextFormatted("{} ", "hex.builtin.common.comment"_lang); ImGui::TableNextColumn(); - ImGui::TextWrapped(" \"%s\"", comment->c_str()); + ImGui::TextWrapped(" \"%s\"", comment.c_str()); } ImGui::EndTable(); @@ -626,6 +694,8 @@ namespace hex::plugin::builtin { ON_SCOPE_EXIT { patternLanguage.lastEvaluationLog = runtime->getConsoleLog(); patternLanguage.lastEvaluationOutVars = runtime->getOutVariables(); + patternLanguage.sections = runtime->getSections(); + this->m_runningEvaluators--; this->m_lastEvaluationProcessed = false;