diff --git a/lib/external/libwolv b/lib/external/libwolv index 56f77945f..52cb24b18 160000 --- a/lib/external/libwolv +++ b/lib/external/libwolv @@ -1 +1 @@ -Subproject commit 56f77945fe292a4d00afdb1961f2b7e87a88be4c +Subproject commit 52cb24b1842cfc3e9cc681ba67090b0327efb2a3 diff --git a/plugins/builtin/source/content/views/view_hex_editor.cpp b/plugins/builtin/source/content/views/view_hex_editor.cpp index 47939dfc2..a2f9deb02 100644 --- a/plugins/builtin/source/content/views/view_hex_editor.cpp +++ b/plugins/builtin/source/content/views/view_hex_editor.cpp @@ -1345,7 +1345,8 @@ namespace hex::plugin::builtin { /* Skip until */ ContentRegistry::UserInterface::addMenuItemSubMenu({ "hex.builtin.menu.file", "hex.builtin.view.hex_editor.menu.file.skip_until" }, ICON_VS_DEBUG_STEP_OVER, 1610, []{}, - canSearchForDifferingByte); + canSearchForDifferingByte, + this); /* Skip until previous differing byte */ ContentRegistry::UserInterface::addMenuItem({ @@ -1384,7 +1385,8 @@ namespace hex::plugin::builtin { ui::ToastInfo::open("hex.builtin.view.hex_editor.menu.file.skip_until.beginning_reached"_lang); } }, - canSearchForDifferingByte); + canSearchForDifferingByte, + this); /* Skip until next differing byte */ ContentRegistry::UserInterface::addMenuItem({ @@ -1423,7 +1425,8 @@ namespace hex::plugin::builtin { ui::ToastInfo::open("hex.builtin.view.hex_editor.menu.file.skip_until.end_reached"_lang); } }, - canSearchForDifferingByte); + canSearchForDifferingByte, + this); ContentRegistry::UserInterface::addMenuItemSeparator({ "hex.builtin.menu.edit" }, 1100, this); diff --git a/plugins/diffing/include/content/views/view_diff.hpp b/plugins/diffing/include/content/views/view_diff.hpp index 43bba97f7..34b8f9526 100644 --- a/plugins/diffing/include/content/views/view_diff.hpp +++ b/plugins/diffing/include/content/views/view_diff.hpp @@ -36,6 +36,8 @@ namespace hex::plugin::diffing { std::function(u64, const u8*, size_t)> createCompareFunction(size_t otherIndex) const; void analyze(prv::Provider *providerA, prv::Provider *providerB); + void registerMenuItems(); + void reset(); private: @@ -45,6 +47,9 @@ namespace hex::plugin::diffing { std::atomic m_analyzed = false; std::atomic m_analysisInterrupted = false; ContentRegistry::Diffing::Algorithm *m_algorithm = nullptr; + + u64 m_selectedAddress = 0; + prv::Provider *m_selectedProvider = nullptr; }; -} \ No newline at end of file +} diff --git a/plugins/diffing/romfs/lang/en_US.json b/plugins/diffing/romfs/lang/en_US.json index fd753858c..493a6be46 100644 --- a/plugins/diffing/romfs/lang/en_US.json +++ b/plugins/diffing/romfs/lang/en_US.json @@ -14,5 +14,10 @@ "hex.diffing.view.diff.algorithm": "Diffing Algorithm", "hex.diffing.view.diff.settings": "No settings available", "hex.diffing.view.diff.settings.no_settings": "No settings available", - "hex.diffing.view.diff.task.diffing": "Diffing data..." -} \ No newline at end of file + "hex.diffing.view.diff.task.diffing": "Diffing data...", + "hex.diffing.view.diff.menu.file.jumping": "Jump Between Differences", + "hex.diffing.view.diff.menu.file.jumping.prev_diff": "Jump to Previous Difference", + "hex.diffing.view.diff.menu.file.jumping.next_diff": "Jump to Next Difference", + "hex.diffing.view.diff.jumping.beginning_reached": "No more differences till the beginning of the file", + "hex.diffing.view.diff.jumping.end_reached": "No more differences till the end of the file" +} diff --git a/plugins/diffing/source/content/views/view_diff.cpp b/plugins/diffing/source/content/views/view_diff.cpp index 731cc5452..cd4697329 100644 --- a/plugins/diffing/source/content/views/view_diff.cpp +++ b/plugins/diffing/source/content/views/view_diff.cpp @@ -1,12 +1,15 @@ #include "content/views/view_diff.hpp" +#include #include #include +#include #include #include #include +#include #include namespace hex::plugin::diffing { @@ -22,14 +25,28 @@ namespace hex::plugin::diffing { m_analysisInterrupted = m_analyzed = false; }); + // Handle region selection + EventRegionSelected::subscribe(this, [this](const auto ®ion) { + // Save current selection + if (!ImHexApi::Provider::isValid() || region == Region::Invalid()) { + m_selectedProvider = nullptr; + } else { + m_selectedAddress = region.address; + m_selectedProvider = region.getProvider(); + } + }); + // Set the background highlight callbacks for the two hex editor columns m_columns[0].hexEditor.setBackgroundHighlightCallback(this->createCompareFunction(1)); m_columns[1].hexEditor.setBackgroundHighlightCallback(this->createCompareFunction(0)); + + this->registerMenuItems(); } ViewDiff::~ViewDiff() { EventProviderClosed::unsubscribe(this); EventDataChanged::unsubscribe(this); + EventRegionSelected::unsubscribe(this); } namespace { @@ -133,6 +150,7 @@ namespace hex::plugin::diffing { column.diffTree.clear(); column.differences.clear(); } + m_analysisInterrupted = m_analyzed = false; } @@ -441,5 +459,88 @@ namespace hex::plugin::diffing { } } + void ViewDiff::registerMenuItems() { + ContentRegistry::UserInterface::addMenuItemSeparator({ "hex.builtin.menu.file" }, 1700, this); + ContentRegistry::UserInterface::addMenuItemSubMenu({ "hex.builtin.menu.file", "hex.diffing.view.diff.menu.file.jumping" }, ICON_TA_ARROWS_MOVE_HORIZONTAL, 1710, + []{}, + [this]{ return (bool) m_analyzed; }, + this); + + ContentRegistry::UserInterface::addMenuItem({ + "hex.builtin.menu.file", + "hex.diffing.view.diff.menu.file.jumping", + "hex.diffing.view.diff.menu.file.jumping.prev_diff" + }, + ICON_TA_ARROW_BAR_TO_LEFT_DASHED, + 1720, + CTRLCMD + Keys::Left, + [this] { + if (m_selectedProvider == nullptr) + return; + + // Get the column of the currently selected region + auto providers = ImHexApi::Provider::getProviders(); + Column *selectedColumn = nullptr; + for (auto &column : m_columns) { + if (providers[column.provider] == m_selectedProvider) { + selectedColumn = &column; + break; + } + } + + if (selectedColumn == nullptr) + return; + + // Jump to previous difference + auto prevRange = selectedColumn->diffTree.prevInterval(m_selectedAddress); + if (prevRange.has_value()) { + selectedColumn->hexEditor.setSelection(prevRange->interval.start, prevRange->interval.end); + selectedColumn->hexEditor.jumpToSelection(); + } else { + ui::ToastInfo::open("hex.diffing.view.diff.jumping.beginning_reached"_lang); + } + }, + [this]{ return (bool) m_analyzed; }, + this + ); + + ContentRegistry::UserInterface::addMenuItem({ + "hex.builtin.menu.file", + "hex.diffing.view.diff.menu.file.jumping", + "hex.diffing.view.diff.menu.file.jumping.next_diff" + }, + ICON_TA_ARROW_BAR_TO_RIGHT_DASHED, + 1730, + CTRLCMD + Keys::Right, + [this] { + if (m_selectedProvider == nullptr) + return; + + // Get the column of the currently selected region + auto providers = ImHexApi::Provider::getProviders(); + Column *selectedColumn = nullptr; + for (auto &column : m_columns) { + if (providers[column.provider] == m_selectedProvider) { + selectedColumn = &column; + break; + } + } + + if (selectedColumn == nullptr) + return; + + // Jump to next difference + auto nextRange = selectedColumn->diffTree.nextInterval(m_selectedAddress); + if (nextRange.has_value()) { + selectedColumn->hexEditor.setSelection(nextRange->interval.start, nextRange->interval.end); + selectedColumn->hexEditor.jumpToSelection(); + } else { + ui::ToastInfo::open("hex.diffing.view.diff.jumping.end_reached"_lang); + } + }, + [this]{ return (bool) m_analyzed; }, + this + ); + } }