diff --git a/lib/libimhex/include/hex/providers/provider.hpp b/lib/libimhex/include/hex/providers/provider.hpp index 53b603236..06037227c 100644 --- a/lib/libimhex/include/hex/providers/provider.hpp +++ b/lib/libimhex/include/hex/providers/provider.hpp @@ -35,6 +35,7 @@ namespace hex::prv { virtual void resize(size_t newSize); virtual void insert(u64 offset, size_t size); + virtual void remove(u64 offset, size_t size); virtual void save(); virtual void saveAs(const std::fs::path &path); diff --git a/lib/libimhex/source/providers/provider.cpp b/lib/libimhex/source/providers/provider.cpp index 71e7beedc..c761f93e7 100644 --- a/lib/libimhex/source/providers/provider.cpp +++ b/lib/libimhex/source/providers/provider.cpp @@ -63,6 +63,22 @@ namespace hex::prv { patches.insert({ address + size, value }); } + void Provider::remove(u64 offset, size_t size) { + auto &patches = getPatches(); + + std::vector> patchesToMove; + + for (auto &[address, value] : patches) { + if (address > offset) + patchesToMove.emplace_back(address, value); + } + + for (const auto &[address, value] : patchesToMove) + patches.erase(address); + for (const auto &[address, value] : patchesToMove) + patches.insert({ address - size, value }); + } + void Provider::applyOverlays(u64 offset, void *buffer, size_t size) { for (auto &overlay : this->m_overlays) { auto overlayOffset = overlay->getAddress(); diff --git a/plugins/builtin/include/content/providers/file_provider.hpp b/plugins/builtin/include/content/providers/file_provider.hpp index 177c29612..55a8ce352 100644 --- a/plugins/builtin/include/content/providers/file_provider.hpp +++ b/plugins/builtin/include/content/providers/file_provider.hpp @@ -32,6 +32,7 @@ namespace hex::plugin::builtin::prv { void resize(size_t newSize) override; void insert(u64 offset, size_t size) override; + void remove(u64 offset, size_t size) override; void readRaw(u64 offset, void *buffer, size_t size) override; void writeRaw(u64 offset, const void *buffer, size_t size) override; diff --git a/plugins/builtin/source/content/providers/file_provider.cpp b/plugins/builtin/source/content/providers/file_provider.cpp index 2ec7b125f..a2340b504 100644 --- a/plugins/builtin/source/content/providers/file_provider.cpp +++ b/plugins/builtin/source/content/providers/file_provider.cpp @@ -123,7 +123,7 @@ namespace hex::plugin::builtin::prv { auto position = oldSize; while (position > offset) { - size_t readSize = (position >= (offset + buffer.size())) ? buffer.size() : (position - offset); + const auto readSize = std::min(position - offset, buffer.size()); position -= readSize; @@ -135,6 +135,28 @@ namespace hex::plugin::builtin::prv { Provider::insert(offset, size); } + void FileProvider::remove(u64 offset, size_t size) { + auto oldSize = this->getActualSize(); + this->resize(oldSize + size); + + std::vector buffer(0x1000); + + const auto newSize = oldSize - size; + auto position = offset; + while (position < newSize) { + const auto readSize = std::min(newSize - position, buffer.size()); + + this->readRaw(position + size, buffer.data(), readSize); + this->writeRaw(position, buffer.data(), readSize); + + position += readSize; + } + + this->resize(newSize); + + Provider::insert(offset, size); + } + size_t FileProvider::getRealTimeSize() { #if defined(OS_LINUX) if (struct stat newStats; (this->m_fileStatsValid = fstat(this->m_file, &newStats) == 0)) { diff --git a/plugins/builtin/source/content/views/view_hex_editor.cpp b/plugins/builtin/source/content/views/view_hex_editor.cpp index e0d6c1d8b..dc7a60b89 100644 --- a/plugins/builtin/source/content/views/view_hex_editor.cpp +++ b/plugins/builtin/source/content/views/view_hex_editor.cpp @@ -328,6 +328,37 @@ namespace hex::plugin::builtin { u64 m_size; }; + class PopupRemove : public ViewHexEditor::Popup { + public: + PopupRemove(u64 address, size_t size) : m_address(address), m_size(size) {} + + void draw(ViewHexEditor *editor) override { + ImGui::TextUnformatted("hex.builtin.view.hex_editor.menu.edit.remove"_lang); + + ImGui::InputHexadecimal("hex.common.address"_lang, &this->m_address); + ImGui::InputHexadecimal("hex.common.size"_lang, &this->m_size); + + View::confirmButtons("hex.builtin.common.set"_lang, "hex.builtin.common.cancel"_lang, + [&, this]{ + remove(this->m_address, static_cast(this->m_size)); + editor->closePopup(); + }, + [&]{ + editor->closePopup(); + }); + } + + private: + static void remove(u64 address, size_t size) { + if (ImHexApi::Provider::isValid()) + ImHexApi::Provider::get()->remove(address, size); + } + + private: + u64 m_address; + u64 m_size; + }; + ViewHexEditor::ViewHexEditor() : View("hex.builtin.view.hex_editor.name") { this->m_currDataVisualizer = ContentRegistry::HexEditor::impl::getVisualizers()["hex.builtin.visualizer.hexadecimal.8bit"]; @@ -1373,6 +1404,10 @@ namespace hex::plugin::builtin { if (ImGui::MenuItem("hex.builtin.view.hex_editor.menu.edit.insert"_lang, nullptr, false, providerValid && provider->isResizable())) { this->openPopup(this->getSelection().getStartAddress(), 0x00); } + + if (ImGui::MenuItem("hex.builtin.view.hex_editor.menu.edit.remove"_lang, nullptr, false, providerValid && provider->isResizable())) { + this->openPopup(this->getSelection().getStartAddress(), 0x00); + } }); } diff --git a/plugins/builtin/source/lang/en_US.cpp b/plugins/builtin/source/lang/en_US.cpp index 74fc1d633..63f4587a7 100644 --- a/plugins/builtin/source/lang/en_US.cpp +++ b/plugins/builtin/source/lang/en_US.cpp @@ -278,6 +278,7 @@ namespace hex::plugin::builtin { { "hex.builtin.view.hex_editor.menu.edit.set_base", "Set base address" }, { "hex.builtin.view.hex_editor.menu.edit.resize", "Resize..." }, { "hex.builtin.view.hex_editor.menu.edit.insert", "Insert..." }, + { "hex.builtin.view.hex_editor.menu.edit.remove", "Remove..." }, { "hex.builtin.view.information.name", "Data Information" }, { "hex.builtin.view.information.control", "Control" },