mirror of
https://github.com/WerWolv/ImHex.git
synced 2026-03-28 07:47:03 -05:00
refactor: move hex editor popups to their own files (#2536)
This commit is contained in:
@@ -95,7 +95,17 @@ add_imhex_plugin(
|
||||
source/content/tutorials/tutorials.cpp
|
||||
source/content/tutorials/introduction.cpp
|
||||
|
||||
source/content/popups/hex_editor/popup_hex_editor_base_address.cpp
|
||||
source/content/popups/hex_editor/popup_hex_editor_decoded_string.cpp
|
||||
source/content/popups/hex_editor/popup_hex_editor_fill.cpp
|
||||
source/content/popups/hex_editor/popup_hex_editor_find.cpp
|
||||
source/content/popups/hex_editor/popup_hex_editor_goto.cpp
|
||||
source/content/popups/hex_editor/popup_hex_editor_insert.cpp
|
||||
source/content/popups/hex_editor/popup_hex_editor_page_size.cpp
|
||||
source/content/popups/hex_editor/popup_hex_editor_paste_behaviour.cpp
|
||||
source/content/popups/hex_editor/popup_hex_editor_remove.cpp
|
||||
source/content/popups/hex_editor/popup_hex_editor_resize.cpp
|
||||
source/content/popups/hex_editor/popup_hex_editor_select.cpp
|
||||
|
||||
source/content/views/view_hex_editor.cpp
|
||||
source/content/views/view_pattern_editor.cpp
|
||||
|
||||
@@ -0,0 +1,18 @@
|
||||
#pragma once
|
||||
|
||||
#include <content/views/view_hex_editor.hpp>
|
||||
#include <hex/api/localization_manager.hpp>
|
||||
|
||||
namespace hex::plugin::builtin {
|
||||
|
||||
class PopupBaseAddress : public ViewHexEditor::Popup {
|
||||
public:
|
||||
explicit PopupBaseAddress(u64 baseAddress);
|
||||
void draw(ViewHexEditor *editor) override;
|
||||
[[nodiscard]] UnlocalizedString getTitle() const override;
|
||||
|
||||
private:
|
||||
static void setBaseAddress(u64 baseAddress);
|
||||
u64 m_baseAddress;
|
||||
};
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <content/views/view_hex_editor.hpp>
|
||||
#include <hex/api/localization_manager.hpp>
|
||||
#include <ui/text_editor.hpp>
|
||||
#include <string>
|
||||
|
||||
namespace hex::plugin::builtin {
|
||||
|
||||
class PopupDecodedString final : public ViewHexEditor::Popup {
|
||||
public:
|
||||
explicit PopupDecodedString(std::string decodedString);
|
||||
|
||||
void draw(ViewHexEditor *) override;
|
||||
|
||||
[[nodiscard]] UnlocalizedString getTitle() const override;
|
||||
|
||||
[[nodiscard]] bool canBePinned() const override;
|
||||
[[nodiscard]] ImGuiWindowFlags getFlags() const override;
|
||||
|
||||
private:
|
||||
std::string m_decodedString;
|
||||
ui::TextEditor m_editor;
|
||||
};
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
#pragma once
|
||||
|
||||
#include <content/views/view_hex_editor.hpp>
|
||||
#include <hex/api/localization_manager.hpp>
|
||||
#include <string>
|
||||
|
||||
namespace hex::plugin::builtin {
|
||||
|
||||
class PopupFill : public ViewHexEditor::Popup {
|
||||
public:
|
||||
PopupFill(u64 address, size_t size);
|
||||
void draw(ViewHexEditor *editor) override;
|
||||
[[nodiscard]] UnlocalizedString getTitle() const override;
|
||||
|
||||
private:
|
||||
static void fill(u64 address, size_t size, std::string input);
|
||||
u64 m_address;
|
||||
u64 m_size;
|
||||
std::string m_input;
|
||||
};
|
||||
}
|
||||
@@ -0,0 +1,31 @@
|
||||
#pragma once
|
||||
|
||||
#include <content/views/view_hex_editor.hpp>
|
||||
#include <hex/api/localization_manager.hpp>
|
||||
#include <wolv/math_eval/math_evaluator.hpp>
|
||||
#include <optional>
|
||||
#include <string>
|
||||
|
||||
namespace hex::plugin::builtin {
|
||||
|
||||
class PopupGoto : public ViewHexEditor::Popup {
|
||||
public:
|
||||
void draw(ViewHexEditor *editor) override;
|
||||
[[nodiscard]] UnlocalizedString getTitle() const override;
|
||||
bool canBePinned() const override;
|
||||
|
||||
private:
|
||||
enum class Mode : u8 {
|
||||
Absolute,
|
||||
Relative,
|
||||
Begin,
|
||||
End
|
||||
};
|
||||
|
||||
Mode m_mode = Mode::Absolute;
|
||||
std::optional<u64> m_newAddress;
|
||||
bool m_requestFocus = true;
|
||||
std::string m_input = "0x";
|
||||
wolv::math_eval::MathEvaluator<i128> m_evaluator;
|
||||
};
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
#pragma once
|
||||
|
||||
#include <content/views/view_hex_editor.hpp>
|
||||
#include <hex/api/localization_manager.hpp>
|
||||
|
||||
namespace hex::plugin::builtin {
|
||||
|
||||
class PopupInsert : public ViewHexEditor::Popup {
|
||||
public:
|
||||
PopupInsert(u64 address, size_t size);
|
||||
void draw(ViewHexEditor *editor) override;
|
||||
[[nodiscard]] UnlocalizedString getTitle() const override;
|
||||
|
||||
private:
|
||||
static void insert(u64 address, size_t size);
|
||||
u64 m_address;
|
||||
u64 m_size;
|
||||
};
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
#pragma once
|
||||
|
||||
#include <content/views/view_hex_editor.hpp>
|
||||
#include <hex/api/localization_manager.hpp>
|
||||
|
||||
namespace hex::plugin::builtin {
|
||||
|
||||
class PopupPageSize : public ViewHexEditor::Popup {
|
||||
public:
|
||||
explicit PopupPageSize(u64 pageSize);
|
||||
void draw(ViewHexEditor *editor) override;
|
||||
[[nodiscard]] UnlocalizedString getTitle() const override;
|
||||
|
||||
private:
|
||||
static void setPageSize(u64 pageSize);
|
||||
u64 m_pageSize;
|
||||
};
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
#pragma once
|
||||
|
||||
#include <content/views/view_hex_editor.hpp>
|
||||
#include <hex/api/localization_manager.hpp>
|
||||
#include <hex/helpers/utils.hpp>
|
||||
#include <functional>
|
||||
|
||||
namespace hex::plugin::builtin {
|
||||
|
||||
class PopupPasteBehaviour final : public ViewHexEditor::Popup {
|
||||
public:
|
||||
explicit PopupPasteBehaviour(const Region &selection, const std::function<void(const Region &selection, bool selectionCheck)> &pasteCallback);
|
||||
void draw(ViewHexEditor *editor) override;
|
||||
[[nodiscard]] UnlocalizedString getTitle() const override;
|
||||
|
||||
private:
|
||||
Region m_selection;
|
||||
std::function<void(const Region &selection, bool selectionCheck)> m_pasteCallback;
|
||||
};
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
#pragma once
|
||||
|
||||
#include <content/views/view_hex_editor.hpp>
|
||||
#include <hex/api/localization_manager.hpp>
|
||||
|
||||
namespace hex::plugin::builtin {
|
||||
|
||||
class PopupRemove : public ViewHexEditor::Popup {
|
||||
public:
|
||||
PopupRemove(u64 address, size_t size);
|
||||
void draw(ViewHexEditor *editor) override;
|
||||
[[nodiscard]] UnlocalizedString getTitle() const override;
|
||||
|
||||
private:
|
||||
static void remove(u64 address, size_t size);
|
||||
u64 m_address;
|
||||
u64 m_size;
|
||||
};
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
#pragma once
|
||||
|
||||
#include <content/views/view_hex_editor.hpp>
|
||||
#include <hex/api/localization_manager.hpp>
|
||||
|
||||
namespace hex::plugin::builtin {
|
||||
|
||||
class PopupResize : public ViewHexEditor::Popup {
|
||||
public:
|
||||
explicit PopupResize(u64 currSize);
|
||||
void draw(ViewHexEditor *editor) override;
|
||||
[[nodiscard]] UnlocalizedString getTitle() const override;
|
||||
|
||||
private:
|
||||
static void resize(size_t newSize);
|
||||
u64 m_size;
|
||||
};
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
#pragma once
|
||||
|
||||
#include <content/views/view_hex_editor.hpp>
|
||||
#include <hex/api/localization_manager.hpp>
|
||||
#include <hex/helpers/utils.hpp>
|
||||
|
||||
namespace hex::plugin::builtin {
|
||||
|
||||
class PopupSelect : public ViewHexEditor::Popup {
|
||||
public:
|
||||
PopupSelect(u64 address, size_t size);
|
||||
void draw(ViewHexEditor *editor) override;
|
||||
[[nodiscard]] UnlocalizedString getTitle() const override;
|
||||
[[nodiscard]] bool canBePinned() const override;
|
||||
|
||||
private:
|
||||
Region m_region = { 0, 1 };
|
||||
bool m_justOpened = true;
|
||||
};
|
||||
}
|
||||
@@ -0,0 +1,39 @@
|
||||
#include "content/popups/hex_editor/popup_hex_editor_base_address.hpp"
|
||||
#include "content/views/view_hex_editor.hpp"
|
||||
|
||||
#include <hex/api/content_registry/settings.hpp>
|
||||
#include <hex/api/content_registry/user_interface.hpp>
|
||||
#include <content/differing_byte_searcher.hpp>
|
||||
|
||||
namespace hex::plugin::builtin {
|
||||
|
||||
PopupBaseAddress::PopupBaseAddress(u64 baseAddress) : m_baseAddress(baseAddress) {}
|
||||
|
||||
void PopupBaseAddress::draw(ViewHexEditor *editor) {
|
||||
ImGuiExt::InputHexadecimal("##base_address", &m_baseAddress);
|
||||
if (ImGui::IsItemFocused() && (ImGui::IsKeyPressed(ImGuiKey_Enter) || ImGui::IsKeyPressed(ImGuiKey_KeypadEnter))) {
|
||||
setBaseAddress(m_baseAddress);
|
||||
editor->closePopup();
|
||||
}
|
||||
|
||||
ImGuiExt::ConfirmButtons("hex.ui.common.set"_lang, "hex.ui.common.cancel"_lang,
|
||||
[&, this]{
|
||||
setBaseAddress(m_baseAddress);
|
||||
editor->closePopup();
|
||||
},
|
||||
[&]{
|
||||
editor->closePopup();
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
UnlocalizedString PopupBaseAddress::getTitle() const {
|
||||
return "hex.builtin.view.hex_editor.menu.edit.set_base";
|
||||
}
|
||||
|
||||
void PopupBaseAddress::setBaseAddress(u64 baseAddress) {
|
||||
if (ImHexApi::Provider::isValid())
|
||||
ImHexApi::Provider::get()->setBaseAddress(baseAddress);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,48 @@
|
||||
#include "content/popups/hex_editor/popup_hex_editor_decoded_string.hpp"
|
||||
#include "content/views/view_hex_editor.hpp"
|
||||
|
||||
#include <hex/api/content_registry/settings.hpp>
|
||||
#include <hex/api/content_registry/pattern_language.hpp>
|
||||
|
||||
#include <content/differing_byte_searcher.hpp>
|
||||
|
||||
#include <popups/popup_file_chooser.hpp>
|
||||
|
||||
#include <ui/text_editor.hpp>
|
||||
|
||||
namespace hex::plugin::builtin {
|
||||
|
||||
PopupDecodedString::PopupDecodedString(std::string decodedString) : m_decodedString(std::move(decodedString)) {
|
||||
}
|
||||
|
||||
void PopupDecodedString::draw(ViewHexEditor *) {
|
||||
ImGui::PushStyleVar(ImGuiStyleVar_FramePadding, ImVec2());
|
||||
ImGui::PushStyleVar(ImGuiStyleVar_FrameBorderSize, 0.0F);
|
||||
ImGui::PushStyleColor(ImGuiCol_FrameBg, ImVec4());
|
||||
|
||||
auto text = wolv::util::trim(wolv::util::wrapMonospacedString(
|
||||
m_decodedString,
|
||||
ImGui::CalcTextSize("M").x,
|
||||
std::max(100_scaled, ImGui::GetContentRegionAvail().x - ImGui::GetStyle().ScrollbarSize - ImGui::GetStyle().FrameBorderSize)
|
||||
));
|
||||
|
||||
ImGui::InputTextMultiline(
|
||||
"##",
|
||||
text.data(),
|
||||
text.size() + 1,
|
||||
ImGui::GetContentRegionAvail(),
|
||||
ImGuiInputTextFlags_ReadOnly | ImGuiInputTextFlags_NoHorizontalScroll
|
||||
);
|
||||
|
||||
ImGui::PopStyleColor();
|
||||
ImGui::PopStyleVar(2);
|
||||
}
|
||||
|
||||
UnlocalizedString PopupDecodedString::getTitle() const {
|
||||
return "hex.builtin.view.hex_editor.menu.edit.decoded_string.popup.title";
|
||||
}
|
||||
|
||||
bool PopupDecodedString::canBePinned() const { return true; }
|
||||
ImGuiWindowFlags PopupDecodedString::getFlags() const { return ImGuiWindowFlags_None; }
|
||||
|
||||
}
|
||||
@@ -0,0 +1,89 @@
|
||||
#include "content/popups/hex_editor/popup_hex_editor_fill.hpp"
|
||||
#include "content/views/view_hex_editor.hpp"
|
||||
|
||||
#include <hex/api/content_registry/settings.hpp>
|
||||
#include <hex/api/content_registry/user_interface.hpp>
|
||||
#include <hex/api/content_registry/pattern_language.hpp>
|
||||
#include <hex/api/achievement_manager.hpp>
|
||||
|
||||
#include <content/differing_byte_searcher.hpp>
|
||||
|
||||
#include <hex/helpers/utils.hpp>
|
||||
#include <hex/helpers/crypto.hpp>
|
||||
|
||||
#include <fonts/vscode_icons.hpp>
|
||||
|
||||
#include <ui/text_editor.hpp>
|
||||
#include <wolv/literals.hpp>
|
||||
|
||||
using namespace wolv::literals;
|
||||
|
||||
namespace hex::plugin::builtin {
|
||||
|
||||
PopupFill::PopupFill(u64 address, size_t size) : m_address(address), m_size(size) {}
|
||||
|
||||
void PopupFill::draw(ViewHexEditor *editor) {
|
||||
ImGuiExt::InputHexadecimal("hex.ui.common.address"_lang, &m_address);
|
||||
ImGuiExt::InputHexadecimal("hex.ui.common.size"_lang, &m_size);
|
||||
|
||||
ImGui::Separator();
|
||||
|
||||
ImGuiExt::InputTextIcon("hex.ui.common.bytes"_lang, ICON_VS_SYMBOL_NAMESPACE, m_input);
|
||||
|
||||
ImGuiExt::ConfirmButtons("hex.ui.common.set"_lang, "hex.ui.common.cancel"_lang,
|
||||
[&, this] {
|
||||
fill(m_address, m_size, m_input);
|
||||
editor->closePopup();
|
||||
},
|
||||
[&] {
|
||||
editor->closePopup();
|
||||
});
|
||||
|
||||
if (ImGui::IsWindowFocused() && (ImGui::IsKeyPressed(ImGuiKey_Enter) || ImGui::IsKeyPressed(ImGuiKey_KeypadEnter))) {
|
||||
fill(m_address, m_size, m_input);
|
||||
editor->closePopup();
|
||||
}
|
||||
}
|
||||
|
||||
UnlocalizedString PopupFill::getTitle() const {
|
||||
return "hex.builtin.view.hex_editor.menu.edit.fill";
|
||||
}
|
||||
|
||||
void PopupFill::fill(u64 address, size_t size, std::string input) {
|
||||
if (!ImHexApi::Provider::isValid())
|
||||
return;
|
||||
|
||||
std::erase(input, ' ');
|
||||
|
||||
auto bytes = crypt::decode16(input);
|
||||
if (bytes.empty())
|
||||
return;
|
||||
|
||||
auto provider = ImHexApi::Provider::get();
|
||||
u32 patchCount = 0;
|
||||
|
||||
// Group the fill pattern into a larger chunk
|
||||
constexpr static auto BatchFillSize = 1_MiB;
|
||||
std::vector<u8> batchData;
|
||||
if (bytes.size() < BatchFillSize) {
|
||||
batchData.resize(std::min<u64>(alignTo<u64>(BatchFillSize, bytes.size()), size));
|
||||
for (u64 i = 0; i < batchData.size(); i += bytes.size()) {
|
||||
auto remainingSize = std::min<size_t>(batchData.size() - i, bytes.size());
|
||||
std::copy_n(bytes.begin(), remainingSize, batchData.begin() + i);
|
||||
}
|
||||
} else {
|
||||
batchData = std::move(bytes);
|
||||
}
|
||||
|
||||
const auto startAddress = provider->getBaseAddress() + address;
|
||||
for (u64 i = 0; i < size; i += batchData.size()) {
|
||||
auto remainingSize = std::min<size_t>(size - i, batchData.size());
|
||||
provider->write(startAddress + i, batchData.data(), remainingSize);
|
||||
patchCount += 1;
|
||||
}
|
||||
provider->getUndoStack().groupOperations(patchCount, "hex.builtin.undo_operation.fill");
|
||||
|
||||
AchievementManager::unlockAchievement("hex.builtin.achievement.hex_editor", "hex.builtin.achievement.hex_editor.fill.name");
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,15 +1,24 @@
|
||||
#include "content/popups/hex_editor/popup_hex_editor_find.hpp"
|
||||
|
||||
#include "content/views/view_hex_editor.hpp"
|
||||
|
||||
#include <hex/api/content_registry/views.hpp>
|
||||
#include <hex/helpers/crypto.hpp>
|
||||
#include <hex/api/content_registry/settings.hpp>
|
||||
#include <hex/api/content_registry/user_interface.hpp>
|
||||
#include <hex/api/content_registry/pattern_language.hpp>
|
||||
#include <hex/api/achievement_manager.hpp>
|
||||
|
||||
#include <content/differing_byte_searcher.hpp>
|
||||
|
||||
#include <hex/helpers/utils.hpp>
|
||||
#include <hex/helpers/crypto.hpp>
|
||||
|
||||
#include <hex/providers/buffered_reader.hpp>
|
||||
|
||||
#include <fonts/vscode_icons.hpp>
|
||||
|
||||
#include <bit>
|
||||
#include <popups/popup_file_chooser.hpp>
|
||||
|
||||
#include <ui/text_editor.hpp>
|
||||
|
||||
namespace hex::plugin::builtin {
|
||||
|
||||
|
||||
@@ -0,0 +1,122 @@
|
||||
#include "content/popups/hex_editor/popup_hex_editor_goto.hpp"
|
||||
#include "content/views/view_hex_editor.hpp"
|
||||
|
||||
#include <hex/api/content_registry/settings.hpp>
|
||||
#include <hex/api/content_registry/user_interface.hpp>
|
||||
|
||||
#include <content/differing_byte_searcher.hpp>
|
||||
|
||||
#include <toasts/toast_notification.hpp>
|
||||
|
||||
#include <fonts/vscode_icons.hpp>
|
||||
|
||||
#include <pl/patterns/pattern.hpp>
|
||||
|
||||
namespace hex::plugin::builtin {
|
||||
|
||||
void PopupGoto::draw(ViewHexEditor *editor) {
|
||||
bool updateAddress = false;
|
||||
if (ImGui::BeginTabBar("goto_tabs")) {
|
||||
if (ImGui::BeginTabItem("hex.builtin.view.hex_editor.goto.offset.absolute"_lang)) {
|
||||
m_mode = Mode::Absolute;
|
||||
updateAddress = true;
|
||||
ImGui::EndTabItem();
|
||||
}
|
||||
|
||||
ImGui::BeginDisabled(!editor->isSelectionValid());
|
||||
if (ImGui::BeginTabItem("hex.builtin.view.hex_editor.goto.offset.relative"_lang)) {
|
||||
m_mode = Mode::Relative;
|
||||
updateAddress = true;
|
||||
ImGui::EndTabItem();
|
||||
}
|
||||
ImGui::EndDisabled();
|
||||
|
||||
if (ImGui::BeginTabItem("hex.builtin.view.hex_editor.goto.offset.begin"_lang)) {
|
||||
m_mode = Mode::Begin;
|
||||
updateAddress = true;
|
||||
ImGui::EndTabItem();
|
||||
}
|
||||
|
||||
if (ImGui::BeginTabItem("hex.builtin.view.hex_editor.goto.offset.end"_lang)) {
|
||||
m_mode = Mode::End;
|
||||
updateAddress = true;
|
||||
ImGui::EndTabItem();
|
||||
}
|
||||
|
||||
if (m_requestFocus){
|
||||
ImGui::SetKeyboardFocusHere();
|
||||
m_requestFocus = false;
|
||||
}
|
||||
|
||||
if (ImGuiExt::InputTextIcon("##input", ICON_VS_SYMBOL_OPERATOR, m_input)) {
|
||||
updateAddress = true;
|
||||
}
|
||||
|
||||
if (updateAddress) {
|
||||
if (auto result = m_evaluator.evaluate(m_input); result.has_value()) {
|
||||
const auto inputResult = u64(result.value());
|
||||
auto provider = ImHexApi::Provider::get();
|
||||
|
||||
switch (m_mode) {
|
||||
case Mode::Absolute: {
|
||||
m_newAddress = inputResult;
|
||||
}
|
||||
break;
|
||||
case Mode::Relative: {
|
||||
const auto selection = editor->getSelection();
|
||||
m_newAddress = selection.getStartAddress() + inputResult;
|
||||
}
|
||||
break;
|
||||
case Mode::Begin: {
|
||||
m_newAddress = provider->getBaseAddress() + provider->getCurrentPageAddress() + inputResult;
|
||||
}
|
||||
break;
|
||||
case Mode::End: {
|
||||
m_newAddress = provider->getActualSize() - inputResult;
|
||||
}
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
m_newAddress.reset();
|
||||
}
|
||||
}
|
||||
|
||||
bool isOffsetValid = m_newAddress <= ImHexApi::Provider::get()->getActualSize();
|
||||
|
||||
bool executeGoto = false;
|
||||
|
||||
if (ImGui::IsWindowFocused() && (ImGui::IsKeyPressed(ImGuiKey_Enter) || ImGui::IsKeyPressed(ImGuiKey_KeypadEnter))) {
|
||||
executeGoto = true;
|
||||
}
|
||||
|
||||
ImGui::BeginDisabled(!m_newAddress.has_value() || !isOffsetValid);
|
||||
{
|
||||
const auto label = fmt::format("{} {}", "hex.builtin.view.hex_editor.menu.file.goto"_lang, m_newAddress.has_value() ? fmt::format("0x{:08X}", *m_newAddress) : "???");
|
||||
const auto buttonWidth = ImGui::GetWindowWidth() - ImGui::GetStyle().WindowPadding.x * 2;
|
||||
if (ImGuiExt::DimmedButton(label.c_str(), ImVec2(buttonWidth, 0))) {
|
||||
executeGoto = true;
|
||||
}
|
||||
}
|
||||
ImGui::EndDisabled();
|
||||
|
||||
if (executeGoto && m_newAddress.has_value()) {
|
||||
editor->setSelection(*m_newAddress, *m_newAddress);
|
||||
editor->jumpToSelection();
|
||||
|
||||
if (!this->isPinned())
|
||||
editor->closePopup();
|
||||
}
|
||||
|
||||
ImGui::EndTabBar();
|
||||
}
|
||||
}
|
||||
|
||||
UnlocalizedString PopupGoto::getTitle() const {
|
||||
return "hex.builtin.view.hex_editor.menu.file.goto";
|
||||
}
|
||||
|
||||
bool PopupGoto::canBePinned() const {
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,41 @@
|
||||
#include "content/popups/hex_editor/popup_hex_editor_insert.hpp"
|
||||
#include "content/views/view_hex_editor.hpp"
|
||||
|
||||
#include <hex/api/content_registry/settings.hpp>
|
||||
#include <hex/api/content_registry/user_interface.hpp>
|
||||
|
||||
#include <content/differing_byte_searcher.hpp>
|
||||
|
||||
namespace hex::plugin::builtin {
|
||||
|
||||
PopupInsert::PopupInsert(u64 address, size_t size) : m_address(address), m_size(size) {}
|
||||
|
||||
void PopupInsert::draw(ViewHexEditor *editor) {
|
||||
ImGuiExt::InputHexadecimal("hex.ui.common.address"_lang, &m_address);
|
||||
ImGuiExt::InputHexadecimal("hex.ui.common.size"_lang, &m_size);
|
||||
|
||||
ImGuiExt::ConfirmButtons("hex.ui.common.set"_lang, "hex.ui.common.cancel"_lang,
|
||||
[&, this]{
|
||||
insert(m_address, m_size);
|
||||
editor->closePopup();
|
||||
},
|
||||
[&]{
|
||||
editor->closePopup();
|
||||
});
|
||||
|
||||
if (ImGui::IsWindowFocused() && (ImGui::IsKeyPressed(ImGuiKey_Enter) || ImGui::IsKeyPressed(ImGuiKey_KeypadEnter))) {
|
||||
insert(m_address, m_size);
|
||||
editor->closePopup();
|
||||
}
|
||||
}
|
||||
|
||||
UnlocalizedString PopupInsert::getTitle() const {
|
||||
return "hex.builtin.view.hex_editor.menu.edit.insert";
|
||||
}
|
||||
|
||||
void PopupInsert::insert(u64 address, size_t size) {
|
||||
if (ImHexApi::Provider::isValid())
|
||||
ImHexApi::Provider::get()->insert(address, size);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,44 @@
|
||||
#include "content/popups/hex_editor/popup_hex_editor_page_size.hpp"
|
||||
#include "content/views/view_hex_editor.hpp"
|
||||
|
||||
#include <hex/api/content_registry/settings.hpp>
|
||||
#include <hex/api/content_registry/user_interface.hpp>
|
||||
|
||||
#include <content/differing_byte_searcher.hpp>
|
||||
|
||||
namespace hex::plugin::builtin {
|
||||
|
||||
PopupPageSize::PopupPageSize(u64 pageSize) : m_pageSize(pageSize) {}
|
||||
|
||||
void PopupPageSize::draw(ViewHexEditor *editor) {
|
||||
ImGuiExt::InputHexadecimal("##page_size", &m_pageSize);
|
||||
if (ImGui::IsItemFocused() && (ImGui::IsKeyPressed(ImGuiKey_Enter) || ImGui::IsKeyPressed(ImGuiKey_KeypadEnter))) {
|
||||
setPageSize(m_pageSize);
|
||||
editor->closePopup();
|
||||
}
|
||||
|
||||
ImGuiExt::ConfirmButtons("hex.ui.common.set"_lang, "hex.ui.common.cancel"_lang,
|
||||
[&, this]{
|
||||
setPageSize(m_pageSize);
|
||||
editor->closePopup();
|
||||
},
|
||||
[&]{
|
||||
editor->closePopup();
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
UnlocalizedString PopupPageSize::getTitle() const {
|
||||
return "hex.builtin.view.hex_editor.menu.edit.set_page_size";
|
||||
}
|
||||
|
||||
void PopupPageSize::setPageSize(u64 pageSize) {
|
||||
if (ImHexApi::Provider::isValid()) {
|
||||
auto provider = ImHexApi::Provider::get();
|
||||
|
||||
provider->setPageSize(pageSize);
|
||||
provider->setCurrentPage(0);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,45 @@
|
||||
#include "content/popups/hex_editor/popup_hex_editor_paste_behaviour.hpp"
|
||||
#include "content/views/view_hex_editor.hpp"
|
||||
|
||||
#include <hex/api/content_registry/settings.hpp>
|
||||
|
||||
#include <ui/text_editor.hpp>
|
||||
|
||||
namespace hex::plugin::builtin {
|
||||
|
||||
PopupPasteBehaviour::PopupPasteBehaviour(const Region &selection, const std::function<void(const Region &selection, bool selectionCheck)> &pasteCallback)
|
||||
: m_selection(), m_pasteCallback(pasteCallback) {
|
||||
m_selection = Region { .address=selection.getStartAddress(), .size=selection.getSize() };
|
||||
}
|
||||
|
||||
void PopupPasteBehaviour::draw(ViewHexEditor *editor) {
|
||||
const auto width = ImGui::GetWindowWidth();
|
||||
|
||||
ImGui::TextWrapped("%s", "hex.builtin.view.hex_editor.menu.edit.paste.popup.description"_lang.get());
|
||||
ImGui::TextUnformatted("hex.builtin.view.hex_editor.menu.edit.paste.popup.hint"_lang);
|
||||
|
||||
ImGui::Separator();
|
||||
|
||||
if (ImGui::Button("hex.builtin.view.hex_editor.menu.edit.paste.popup.button.selection"_lang, ImVec2(width / 4, 0))) {
|
||||
m_pasteCallback(m_selection, true);
|
||||
editor->closePopup();
|
||||
}
|
||||
|
||||
ImGui::SameLine();
|
||||
if (ImGui::Button("hex.builtin.view.hex_editor.menu.edit.paste.popup.button.everything"_lang, ImVec2(width / 4, 0))) {
|
||||
m_pasteCallback(m_selection, false);
|
||||
editor->closePopup();
|
||||
}
|
||||
|
||||
ImGui::SameLine(ImGui::GetWindowWidth() - ImGui::GetCursorPosX() - (width / 6));
|
||||
if (ImGui::Button("hex.ui.common.cancel"_lang, ImVec2(width / 6, 0))) {
|
||||
// Cancel the action, without updating settings nor pasting.
|
||||
editor->closePopup();
|
||||
}
|
||||
}
|
||||
|
||||
UnlocalizedString PopupPasteBehaviour::getTitle() const {
|
||||
return "hex.builtin.view.hex_editor.menu.edit.paste.popup.title";
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,43 @@
|
||||
#include "content/popups/hex_editor/popup_hex_editor_remove.hpp"
|
||||
#include "content/views/view_hex_editor.hpp"
|
||||
|
||||
#include <hex/api/content_registry/settings.hpp>
|
||||
#include <hex/api/content_registry/user_interface.hpp>
|
||||
|
||||
#include <content/differing_byte_searcher.hpp>
|
||||
|
||||
#include <ui/text_editor.hpp>
|
||||
|
||||
namespace hex::plugin::builtin {
|
||||
|
||||
PopupRemove::PopupRemove(u64 address, size_t size) : m_address(address), m_size(size) {}
|
||||
|
||||
void PopupRemove::draw(ViewHexEditor *editor) {
|
||||
ImGuiExt::InputHexadecimal("hex.ui.common.address"_lang, &m_address);
|
||||
ImGuiExt::InputHexadecimal("hex.ui.common.size"_lang, &m_size);
|
||||
|
||||
ImGuiExt::ConfirmButtons("hex.ui.common.set"_lang, "hex.ui.common.cancel"_lang,
|
||||
[&, this]{
|
||||
remove(m_address, m_size);
|
||||
editor->closePopup();
|
||||
},
|
||||
[&]{
|
||||
editor->closePopup();
|
||||
});
|
||||
|
||||
if (ImGui::IsWindowFocused() && (ImGui::IsKeyPressed(ImGuiKey_Enter) || ImGui::IsKeyPressed(ImGuiKey_KeypadEnter))) {
|
||||
remove(m_address, m_size);
|
||||
editor->closePopup();
|
||||
}
|
||||
}
|
||||
|
||||
UnlocalizedString PopupRemove::getTitle() const {
|
||||
return "hex.builtin.view.hex_editor.menu.edit.remove";
|
||||
}
|
||||
|
||||
void PopupRemove::remove(u64 address, size_t size) {
|
||||
if (ImHexApi::Provider::isValid())
|
||||
ImHexApi::Provider::get()->remove(address, size);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,39 @@
|
||||
#include "content/popups/hex_editor/popup_hex_editor_resize.hpp"
|
||||
#include "content/views/view_hex_editor.hpp"
|
||||
|
||||
#include <hex/api/content_registry/settings.hpp>
|
||||
#include <hex/api/content_registry/user_interface.hpp>
|
||||
|
||||
#include <content/differing_byte_searcher.hpp>
|
||||
|
||||
namespace hex::plugin::builtin {
|
||||
|
||||
PopupResize::PopupResize(u64 currSize) : m_size(currSize) {}
|
||||
|
||||
void PopupResize::draw(ViewHexEditor *editor) {
|
||||
ImGuiExt::InputHexadecimal("##resize", &m_size);
|
||||
if (ImGui::IsItemFocused() && (ImGui::IsKeyPressed(ImGuiKey_Enter) || ImGui::IsKeyPressed(ImGuiKey_KeypadEnter))) {
|
||||
this->resize(m_size);
|
||||
editor->closePopup();
|
||||
}
|
||||
|
||||
ImGuiExt::ConfirmButtons("hex.ui.common.set"_lang, "hex.ui.common.cancel"_lang,
|
||||
[&, this]{
|
||||
this->resize(m_size);
|
||||
editor->closePopup();
|
||||
},
|
||||
[&]{
|
||||
editor->closePopup();
|
||||
});
|
||||
}
|
||||
|
||||
UnlocalizedString PopupResize::getTitle() const {
|
||||
return "hex.builtin.view.hex_editor.menu.edit.resize";
|
||||
}
|
||||
|
||||
void PopupResize::resize(size_t newSize) {
|
||||
if (ImHexApi::Provider::isValid())
|
||||
ImHexApi::Provider::get()->resize(newSize);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,80 @@
|
||||
#include "content/popups/hex_editor/popup_hex_editor_select.hpp"
|
||||
#include "content/views/view_hex_editor.hpp"
|
||||
|
||||
#include <hex/api/content_registry/settings.hpp>
|
||||
#include <hex/api/content_registry/user_interface.hpp>
|
||||
|
||||
#include <content/differing_byte_searcher.hpp>
|
||||
|
||||
namespace hex::plugin::builtin {
|
||||
|
||||
PopupSelect::PopupSelect(u64 address, size_t size) : m_region({address, size}) {}
|
||||
|
||||
void PopupSelect::draw(ViewHexEditor *editor) {
|
||||
if (ImGui::BeginTabBar("select_tabs")) {
|
||||
if (ImGui::BeginTabItem("hex.builtin.view.hex_editor.select.offset.region"_lang)) {
|
||||
u64 inputA = m_region.getStartAddress();
|
||||
u64 inputB = m_region.getEndAddress();
|
||||
|
||||
if (m_justOpened) {
|
||||
ImGui::SetKeyboardFocusHere();
|
||||
m_justOpened = false;
|
||||
}
|
||||
ImGuiExt::InputHexadecimal("hex.builtin.view.hex_editor.select.offset.begin"_lang, &inputA, ImGuiInputTextFlags_AutoSelectAll);
|
||||
ImGuiExt::InputHexadecimal("hex.builtin.view.hex_editor.select.offset.end"_lang, &inputB, ImGuiInputTextFlags_AutoSelectAll);
|
||||
|
||||
if (inputB < inputA)
|
||||
inputB = inputA;
|
||||
|
||||
m_region = { inputA, (inputB - inputA) + 1 };
|
||||
|
||||
ImGui::EndTabItem();
|
||||
}
|
||||
|
||||
if (ImGui::BeginTabItem("hex.builtin.view.hex_editor.select.offset.size"_lang)) {
|
||||
u64 inputA = m_region.getStartAddress();
|
||||
u64 inputB = m_region.getSize();
|
||||
|
||||
if (m_justOpened) {
|
||||
ImGui::SetKeyboardFocusHere();
|
||||
m_justOpened = false;
|
||||
}
|
||||
ImGuiExt::InputHexadecimal("hex.builtin.view.hex_editor.select.offset.begin"_lang, &inputA, ImGuiInputTextFlags_AutoSelectAll);
|
||||
ImGuiExt::InputHexadecimal("hex.builtin.view.hex_editor.select.offset.size"_lang, &inputB, ImGuiInputTextFlags_AutoSelectAll);
|
||||
|
||||
if (inputB <= 0)
|
||||
inputB = 1;
|
||||
|
||||
m_region = { inputA, inputB };
|
||||
ImGui::EndTabItem();
|
||||
}
|
||||
|
||||
const auto provider = ImHexApi::Provider::get();
|
||||
bool isOffsetValid = m_region.getStartAddress() <= m_region.getEndAddress() &&
|
||||
m_region.getEndAddress() < provider->getActualSize();
|
||||
ImGui::BeginDisabled(!isOffsetValid);
|
||||
{
|
||||
if (ImGui::Button("hex.builtin.view.hex_editor.select.select"_lang) ||
|
||||
(ImGui::IsWindowFocused() && (ImGui::IsKeyPressed(ImGuiKey_Enter) || ImGui::IsKeyPressed(ImGuiKey_KeypadEnter)))) {
|
||||
editor->setSelection(m_region.getStartAddress(), m_region.getEndAddress());
|
||||
editor->jumpToSelection();
|
||||
|
||||
if (!this->isPinned())
|
||||
editor->closePopup();
|
||||
}
|
||||
}
|
||||
ImGui::EndDisabled();
|
||||
|
||||
ImGui::EndTabBar();
|
||||
}
|
||||
}
|
||||
|
||||
UnlocalizedString PopupSelect::getTitle() const {
|
||||
return "hex.builtin.view.hex_editor.menu.edit.select";
|
||||
}
|
||||
|
||||
bool PopupSelect::canBePinned() const {
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -28,6 +28,17 @@
|
||||
#include <fonts/vscode_icons.hpp>
|
||||
|
||||
#include <popups/popup_file_chooser.hpp>
|
||||
|
||||
#include <content/popups/hex_editor/popup_hex_editor_goto.hpp>
|
||||
#include <content/popups/hex_editor/popup_hex_editor_select.hpp>
|
||||
#include <content/popups/hex_editor/popup_hex_editor_base_address.hpp>
|
||||
#include <content/popups/hex_editor/popup_hex_editor_page_size.hpp>
|
||||
#include <content/popups/hex_editor/popup_hex_editor_resize.hpp>
|
||||
#include <content/popups/hex_editor/popup_hex_editor_insert.hpp>
|
||||
#include <content/popups/hex_editor/popup_hex_editor_remove.hpp>
|
||||
#include <content/popups/hex_editor/popup_hex_editor_fill.hpp>
|
||||
#include <content/popups/hex_editor/popup_hex_editor_paste_behaviour.hpp>
|
||||
#include <content/popups/hex_editor/popup_hex_editor_decoded_string.hpp>
|
||||
#include <content/popups/popup_blocking_task.hpp>
|
||||
#include <content/popups/hex_editor/popup_hex_editor_find.hpp>
|
||||
#include <pl/patterns/pattern.hpp>
|
||||
@@ -40,552 +51,6 @@ using namespace wolv::literals;
|
||||
|
||||
namespace hex::plugin::builtin {
|
||||
|
||||
/* Popups */
|
||||
|
||||
class PopupGoto : public ViewHexEditor::Popup {
|
||||
public:
|
||||
void draw(ViewHexEditor *editor) override {
|
||||
bool updateAddress = false;
|
||||
if (ImGui::BeginTabBar("goto_tabs")) {
|
||||
if (ImGui::BeginTabItem("hex.builtin.view.hex_editor.goto.offset.absolute"_lang)) {
|
||||
m_mode = Mode::Absolute;
|
||||
updateAddress = true;
|
||||
ImGui::EndTabItem();
|
||||
}
|
||||
|
||||
ImGui::BeginDisabled(!editor->isSelectionValid());
|
||||
if (ImGui::BeginTabItem("hex.builtin.view.hex_editor.goto.offset.relative"_lang)) {
|
||||
m_mode = Mode::Relative;
|
||||
updateAddress = true;
|
||||
ImGui::EndTabItem();
|
||||
}
|
||||
ImGui::EndDisabled();
|
||||
|
||||
if (ImGui::BeginTabItem("hex.builtin.view.hex_editor.goto.offset.begin"_lang)) {
|
||||
m_mode = Mode::Begin;
|
||||
updateAddress = true;
|
||||
ImGui::EndTabItem();
|
||||
}
|
||||
|
||||
if (ImGui::BeginTabItem("hex.builtin.view.hex_editor.goto.offset.end"_lang)) {
|
||||
m_mode = Mode::End;
|
||||
updateAddress = true;
|
||||
ImGui::EndTabItem();
|
||||
}
|
||||
|
||||
if (m_requestFocus){
|
||||
ImGui::SetKeyboardFocusHere();
|
||||
m_requestFocus = false;
|
||||
}
|
||||
|
||||
if (ImGuiExt::InputTextIcon("##input", ICON_VS_SYMBOL_OPERATOR, m_input)) {
|
||||
updateAddress = true;
|
||||
}
|
||||
|
||||
if (updateAddress) {
|
||||
if (auto result = m_evaluator.evaluate(m_input); result.has_value()) {
|
||||
const auto inputResult = u64(result.value());
|
||||
auto provider = ImHexApi::Provider::get();
|
||||
|
||||
switch (m_mode) {
|
||||
case Mode::Absolute: {
|
||||
m_newAddress = inputResult;
|
||||
}
|
||||
break;
|
||||
case Mode::Relative: {
|
||||
const auto selection = editor->getSelection();
|
||||
m_newAddress = selection.getStartAddress() + inputResult;
|
||||
}
|
||||
break;
|
||||
case Mode::Begin: {
|
||||
m_newAddress = provider->getBaseAddress() + provider->getCurrentPageAddress() + inputResult;
|
||||
}
|
||||
break;
|
||||
case Mode::End: {
|
||||
m_newAddress = provider->getActualSize() - inputResult;
|
||||
}
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
m_newAddress.reset();
|
||||
}
|
||||
}
|
||||
|
||||
bool isOffsetValid = m_newAddress <= ImHexApi::Provider::get()->getActualSize();
|
||||
|
||||
bool executeGoto = false;
|
||||
|
||||
if (ImGui::IsWindowFocused() && (ImGui::IsKeyPressed(ImGuiKey_Enter) || ImGui::IsKeyPressed(ImGuiKey_KeypadEnter))) {
|
||||
executeGoto = true;
|
||||
}
|
||||
|
||||
ImGui::BeginDisabled(!m_newAddress.has_value() || !isOffsetValid);
|
||||
{
|
||||
const auto label = fmt::format("{} {}", "hex.builtin.view.hex_editor.menu.file.goto"_lang, m_newAddress.has_value() ? fmt::format("0x{:08X}", *m_newAddress) : "???");
|
||||
const auto buttonWidth = ImGui::GetWindowWidth() - ImGui::GetStyle().WindowPadding.x * 2;
|
||||
if (ImGuiExt::DimmedButton(label.c_str(), ImVec2(buttonWidth, 0))) {
|
||||
executeGoto = true;
|
||||
}
|
||||
}
|
||||
ImGui::EndDisabled();
|
||||
|
||||
if (executeGoto && m_newAddress.has_value()) {
|
||||
editor->setSelection(*m_newAddress, *m_newAddress);
|
||||
editor->jumpToSelection();
|
||||
|
||||
if (!this->isPinned())
|
||||
editor->closePopup();
|
||||
}
|
||||
|
||||
ImGui::EndTabBar();
|
||||
}
|
||||
}
|
||||
|
||||
[[nodiscard]] UnlocalizedString getTitle() const override {
|
||||
return "hex.builtin.view.hex_editor.menu.file.goto";
|
||||
}
|
||||
|
||||
bool canBePinned() const override {
|
||||
return true;
|
||||
}
|
||||
|
||||
private:
|
||||
enum class Mode : u8 {
|
||||
Absolute,
|
||||
Relative,
|
||||
Begin,
|
||||
End
|
||||
};
|
||||
|
||||
Mode m_mode = Mode::Absolute;
|
||||
std::optional<u64> m_newAddress;
|
||||
|
||||
bool m_requestFocus = true;
|
||||
std::string m_input = "0x";
|
||||
wolv::math_eval::MathEvaluator<i128> m_evaluator;
|
||||
};
|
||||
|
||||
class PopupSelect : public ViewHexEditor::Popup {
|
||||
public:
|
||||
|
||||
PopupSelect(u64 address, size_t size): m_region({address, size}) {}
|
||||
|
||||
void draw(ViewHexEditor *editor) override {
|
||||
if (ImGui::BeginTabBar("select_tabs")) {
|
||||
if (ImGui::BeginTabItem("hex.builtin.view.hex_editor.select.offset.region"_lang)) {
|
||||
u64 inputA = m_region.getStartAddress();
|
||||
u64 inputB = m_region.getEndAddress();
|
||||
|
||||
if (m_justOpened) {
|
||||
ImGui::SetKeyboardFocusHere();
|
||||
m_justOpened = false;
|
||||
}
|
||||
ImGuiExt::InputHexadecimal("hex.builtin.view.hex_editor.select.offset.begin"_lang, &inputA, ImGuiInputTextFlags_AutoSelectAll);
|
||||
ImGuiExt::InputHexadecimal("hex.builtin.view.hex_editor.select.offset.end"_lang, &inputB, ImGuiInputTextFlags_AutoSelectAll);
|
||||
|
||||
if (inputB < inputA)
|
||||
inputB = inputA;
|
||||
|
||||
m_region = { inputA, (inputB - inputA) + 1 };
|
||||
|
||||
ImGui::EndTabItem();
|
||||
}
|
||||
|
||||
if (ImGui::BeginTabItem("hex.builtin.view.hex_editor.select.offset.size"_lang)) {
|
||||
u64 inputA = m_region.getStartAddress();
|
||||
u64 inputB = m_region.getSize();
|
||||
|
||||
if (m_justOpened) {
|
||||
ImGui::SetKeyboardFocusHere();
|
||||
m_justOpened = false;
|
||||
}
|
||||
ImGuiExt::InputHexadecimal("hex.builtin.view.hex_editor.select.offset.begin"_lang, &inputA, ImGuiInputTextFlags_AutoSelectAll);
|
||||
ImGuiExt::InputHexadecimal("hex.builtin.view.hex_editor.select.offset.size"_lang, &inputB, ImGuiInputTextFlags_AutoSelectAll);
|
||||
|
||||
if (inputB <= 0)
|
||||
inputB = 1;
|
||||
|
||||
m_region = { inputA, inputB };
|
||||
ImGui::EndTabItem();
|
||||
}
|
||||
|
||||
const auto provider = ImHexApi::Provider::get();
|
||||
bool isOffsetValid = m_region.getStartAddress() <= m_region.getEndAddress() &&
|
||||
m_region.getEndAddress() < provider->getActualSize();
|
||||
ImGui::BeginDisabled(!isOffsetValid);
|
||||
{
|
||||
if (ImGui::Button("hex.builtin.view.hex_editor.select.select"_lang) ||
|
||||
(ImGui::IsWindowFocused() && (ImGui::IsKeyPressed(ImGuiKey_Enter) || ImGui::IsKeyPressed(ImGuiKey_KeypadEnter)))) {
|
||||
editor->setSelection(m_region.getStartAddress(), m_region.getEndAddress());
|
||||
editor->jumpToSelection();
|
||||
|
||||
if (!this->isPinned())
|
||||
editor->closePopup();
|
||||
}
|
||||
}
|
||||
ImGui::EndDisabled();
|
||||
|
||||
ImGui::EndTabBar();
|
||||
}
|
||||
}
|
||||
|
||||
[[nodiscard]] UnlocalizedString getTitle() const override {
|
||||
return "hex.builtin.view.hex_editor.menu.edit.select";
|
||||
}
|
||||
|
||||
[[nodiscard]] bool canBePinned() const override {
|
||||
return true;
|
||||
}
|
||||
|
||||
private:
|
||||
Region m_region = { 0, 1 };
|
||||
bool m_justOpened = true;
|
||||
};
|
||||
|
||||
class PopupBaseAddress : public ViewHexEditor::Popup {
|
||||
public:
|
||||
explicit PopupBaseAddress(u64 baseAddress) : m_baseAddress(baseAddress) { }
|
||||
|
||||
void draw(ViewHexEditor *editor) override {
|
||||
ImGuiExt::InputHexadecimal("##base_address", &m_baseAddress);
|
||||
if (ImGui::IsItemFocused() && (ImGui::IsKeyPressed(ImGuiKey_Enter) || ImGui::IsKeyPressed(ImGuiKey_KeypadEnter))) {
|
||||
setBaseAddress(m_baseAddress);
|
||||
editor->closePopup();
|
||||
}
|
||||
|
||||
ImGuiExt::ConfirmButtons("hex.ui.common.set"_lang, "hex.ui.common.cancel"_lang,
|
||||
[&, this]{
|
||||
setBaseAddress(m_baseAddress);
|
||||
editor->closePopup();
|
||||
},
|
||||
[&]{
|
||||
editor->closePopup();
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
[[nodiscard]] UnlocalizedString getTitle() const override {
|
||||
return "hex.builtin.view.hex_editor.menu.edit.set_base";
|
||||
}
|
||||
|
||||
private:
|
||||
static void setBaseAddress(u64 baseAddress) {
|
||||
if (ImHexApi::Provider::isValid())
|
||||
ImHexApi::Provider::get()->setBaseAddress(baseAddress);
|
||||
}
|
||||
|
||||
private:
|
||||
u64 m_baseAddress;
|
||||
};
|
||||
|
||||
class PopupPageSize : public ViewHexEditor::Popup {
|
||||
public:
|
||||
explicit PopupPageSize(u64 pageSize) : m_pageSize(pageSize) { }
|
||||
|
||||
void draw(ViewHexEditor *editor) override {
|
||||
ImGuiExt::InputHexadecimal("##page_size", &m_pageSize);
|
||||
if (ImGui::IsItemFocused() && (ImGui::IsKeyPressed(ImGuiKey_Enter) || ImGui::IsKeyPressed(ImGuiKey_KeypadEnter))) {
|
||||
setPageSize(m_pageSize);
|
||||
editor->closePopup();
|
||||
}
|
||||
|
||||
ImGuiExt::ConfirmButtons("hex.ui.common.set"_lang, "hex.ui.common.cancel"_lang,
|
||||
[&, this]{
|
||||
setPageSize(m_pageSize);
|
||||
editor->closePopup();
|
||||
},
|
||||
[&]{
|
||||
editor->closePopup();
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
[[nodiscard]] UnlocalizedString getTitle() const override {
|
||||
return "hex.builtin.view.hex_editor.menu.edit.set_page_size";
|
||||
}
|
||||
|
||||
private:
|
||||
static void setPageSize(u64 pageSize) {
|
||||
if (ImHexApi::Provider::isValid()) {
|
||||
auto provider = ImHexApi::Provider::get();
|
||||
|
||||
provider->setPageSize(pageSize);
|
||||
provider->setCurrentPage(0);
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
u64 m_pageSize;
|
||||
};
|
||||
|
||||
class PopupResize : public ViewHexEditor::Popup {
|
||||
public:
|
||||
explicit PopupResize(u64 currSize) : m_size(currSize) {}
|
||||
|
||||
void draw(ViewHexEditor *editor) override {
|
||||
ImGuiExt::InputHexadecimal("##resize", &m_size);
|
||||
if (ImGui::IsItemFocused() && (ImGui::IsKeyPressed(ImGuiKey_Enter) || ImGui::IsKeyPressed(ImGuiKey_KeypadEnter))) {
|
||||
this->resize(m_size);
|
||||
editor->closePopup();
|
||||
}
|
||||
|
||||
ImGuiExt::ConfirmButtons("hex.ui.common.set"_lang, "hex.ui.common.cancel"_lang,
|
||||
[&, this]{
|
||||
this->resize(m_size);
|
||||
editor->closePopup();
|
||||
},
|
||||
[&]{
|
||||
editor->closePopup();
|
||||
});
|
||||
}
|
||||
|
||||
[[nodiscard]] UnlocalizedString getTitle() const override {
|
||||
return "hex.builtin.view.hex_editor.menu.edit.resize";
|
||||
}
|
||||
|
||||
private:
|
||||
static void resize(size_t newSize) {
|
||||
if (ImHexApi::Provider::isValid())
|
||||
ImHexApi::Provider::get()->resize(newSize);
|
||||
}
|
||||
|
||||
private:
|
||||
u64 m_size;
|
||||
};
|
||||
|
||||
class PopupInsert : public ViewHexEditor::Popup {
|
||||
public:
|
||||
PopupInsert(u64 address, size_t size) : m_address(address), m_size(size) {}
|
||||
|
||||
void draw(ViewHexEditor *editor) override {
|
||||
ImGuiExt::InputHexadecimal("hex.ui.common.address"_lang, &m_address);
|
||||
ImGuiExt::InputHexadecimal("hex.ui.common.size"_lang, &m_size);
|
||||
|
||||
ImGuiExt::ConfirmButtons("hex.ui.common.set"_lang, "hex.ui.common.cancel"_lang,
|
||||
[&, this]{
|
||||
insert(m_address, m_size);
|
||||
editor->closePopup();
|
||||
},
|
||||
[&]{
|
||||
editor->closePopup();
|
||||
});
|
||||
|
||||
if (ImGui::IsWindowFocused() && (ImGui::IsKeyPressed(ImGuiKey_Enter) || ImGui::IsKeyPressed(ImGuiKey_KeypadEnter))) {
|
||||
insert(m_address, m_size);
|
||||
editor->closePopup();
|
||||
}
|
||||
}
|
||||
|
||||
[[nodiscard]] UnlocalizedString getTitle() const override {
|
||||
return "hex.builtin.view.hex_editor.menu.edit.insert";
|
||||
}
|
||||
|
||||
private:
|
||||
static void insert(u64 address, size_t size) {
|
||||
if (ImHexApi::Provider::isValid())
|
||||
ImHexApi::Provider::get()->insert(address, size);
|
||||
}
|
||||
|
||||
private:
|
||||
u64 m_address;
|
||||
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 {
|
||||
ImGuiExt::InputHexadecimal("hex.ui.common.address"_lang, &m_address);
|
||||
ImGuiExt::InputHexadecimal("hex.ui.common.size"_lang, &m_size);
|
||||
|
||||
ImGuiExt::ConfirmButtons("hex.ui.common.set"_lang, "hex.ui.common.cancel"_lang,
|
||||
[&, this]{
|
||||
remove(m_address, m_size);
|
||||
editor->closePopup();
|
||||
},
|
||||
[&]{
|
||||
editor->closePopup();
|
||||
});
|
||||
|
||||
if (ImGui::IsWindowFocused() && (ImGui::IsKeyPressed(ImGuiKey_Enter) || ImGui::IsKeyPressed(ImGuiKey_KeypadEnter))) {
|
||||
remove(m_address, m_size);
|
||||
editor->closePopup();
|
||||
}
|
||||
}
|
||||
|
||||
[[nodiscard]] UnlocalizedString getTitle() const override {
|
||||
return "hex.builtin.view.hex_editor.menu.edit.remove";
|
||||
}
|
||||
|
||||
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;
|
||||
};
|
||||
|
||||
class PopupFill : public ViewHexEditor::Popup {
|
||||
public:
|
||||
PopupFill(u64 address, size_t size) : m_address(address), m_size(size) {}
|
||||
|
||||
void draw(ViewHexEditor *editor) override {
|
||||
ImGuiExt::InputHexadecimal("hex.ui.common.address"_lang, &m_address);
|
||||
ImGuiExt::InputHexadecimal("hex.ui.common.size"_lang, &m_size);
|
||||
|
||||
ImGui::Separator();
|
||||
|
||||
ImGuiExt::InputTextIcon("hex.ui.common.bytes"_lang, ICON_VS_SYMBOL_NAMESPACE, m_input);
|
||||
|
||||
ImGuiExt::ConfirmButtons("hex.ui.common.set"_lang, "hex.ui.common.cancel"_lang,
|
||||
[&, this] {
|
||||
fill(m_address, m_size, m_input);
|
||||
editor->closePopup();
|
||||
},
|
||||
[&] {
|
||||
editor->closePopup();
|
||||
});
|
||||
|
||||
if (ImGui::IsWindowFocused() && (ImGui::IsKeyPressed(ImGuiKey_Enter) || ImGui::IsKeyPressed(ImGuiKey_KeypadEnter))) {
|
||||
fill(m_address, m_size, m_input);
|
||||
editor->closePopup();
|
||||
}
|
||||
}
|
||||
|
||||
[[nodiscard]] UnlocalizedString getTitle() const override {
|
||||
return "hex.builtin.view.hex_editor.menu.edit.fill";
|
||||
}
|
||||
|
||||
private:
|
||||
static void fill(u64 address, size_t size, std::string input) {
|
||||
if (!ImHexApi::Provider::isValid())
|
||||
return;
|
||||
|
||||
std::erase(input, ' ');
|
||||
|
||||
auto bytes = crypt::decode16(input);
|
||||
if (bytes.empty())
|
||||
return;
|
||||
|
||||
auto provider = ImHexApi::Provider::get();
|
||||
u32 patchCount = 0;
|
||||
|
||||
// Group the fill pattern into a larger chunk
|
||||
constexpr static auto BatchFillSize = 1_MiB;
|
||||
std::vector<u8> batchData;
|
||||
if (bytes.size() < BatchFillSize) {
|
||||
batchData.resize(std::min<u64>(alignTo<u64>(BatchFillSize, bytes.size()), size));
|
||||
for (u64 i = 0; i < batchData.size(); i += bytes.size()) {
|
||||
auto remainingSize = std::min<size_t>(batchData.size() - i, bytes.size());
|
||||
std::copy_n(bytes.begin(), remainingSize, batchData.begin() + i);
|
||||
}
|
||||
} else {
|
||||
batchData = std::move(bytes);
|
||||
}
|
||||
|
||||
const auto startAddress = provider->getBaseAddress() + address;
|
||||
for (u64 i = 0; i < size; i += batchData.size()) {
|
||||
auto remainingSize = std::min<size_t>(size - i, batchData.size());
|
||||
provider->write(startAddress + i, batchData.data(), remainingSize);
|
||||
patchCount += 1;
|
||||
}
|
||||
provider->getUndoStack().groupOperations(patchCount, "hex.builtin.undo_operation.fill");
|
||||
|
||||
AchievementManager::unlockAchievement("hex.builtin.achievement.hex_editor", "hex.builtin.achievement.hex_editor.fill.name");
|
||||
}
|
||||
|
||||
private:
|
||||
u64 m_address;
|
||||
u64 m_size;
|
||||
|
||||
std::string m_input;
|
||||
};
|
||||
|
||||
class PopupPasteBehaviour final : public ViewHexEditor::Popup {
|
||||
public:
|
||||
explicit PopupPasteBehaviour(const Region &selection, const auto &pasteCallback) : m_selection(), m_pasteCallback(pasteCallback) {
|
||||
m_selection = Region { .address=selection.getStartAddress(), .size=selection.getSize() };
|
||||
}
|
||||
|
||||
void draw(ViewHexEditor *editor) override {
|
||||
const auto width = ImGui::GetWindowWidth();
|
||||
|
||||
ImGui::TextWrapped("%s", "hex.builtin.view.hex_editor.menu.edit.paste.popup.description"_lang.get());
|
||||
ImGui::TextUnformatted("hex.builtin.view.hex_editor.menu.edit.paste.popup.hint"_lang);
|
||||
|
||||
ImGui::Separator();
|
||||
|
||||
if (ImGui::Button("hex.builtin.view.hex_editor.menu.edit.paste.popup.button.selection"_lang, ImVec2(width / 4, 0))) {
|
||||
m_pasteCallback(m_selection, true);
|
||||
editor->closePopup();
|
||||
}
|
||||
|
||||
ImGui::SameLine();
|
||||
if (ImGui::Button("hex.builtin.view.hex_editor.menu.edit.paste.popup.button.everything"_lang, ImVec2(width / 4, 0))) {
|
||||
m_pasteCallback(m_selection, false);
|
||||
editor->closePopup();
|
||||
}
|
||||
|
||||
ImGui::SameLine(ImGui::GetWindowWidth() - ImGui::GetCursorPosX() - (width / 6));
|
||||
if (ImGui::Button("hex.ui.common.cancel"_lang, ImVec2(width / 6, 0))) {
|
||||
// Cancel the action, without updating settings nor pasting.
|
||||
editor->closePopup();
|
||||
}
|
||||
}
|
||||
|
||||
[[nodiscard]] UnlocalizedString getTitle() const override {
|
||||
return "hex.builtin.view.hex_editor.menu.edit.paste.popup.title";
|
||||
}
|
||||
|
||||
private:
|
||||
Region m_selection;
|
||||
std::function<void(const Region &selection, bool selectionCheck)> m_pasteCallback;
|
||||
};
|
||||
|
||||
class PopupDecodedString final : public ViewHexEditor::Popup {
|
||||
public:
|
||||
explicit PopupDecodedString(std::string decodedString) : m_decodedString(std::move(decodedString)) {
|
||||
}
|
||||
|
||||
void draw(ViewHexEditor *) override {
|
||||
ImGui::PushStyleVar(ImGuiStyleVar_FramePadding, ImVec2());
|
||||
ImGui::PushStyleVar(ImGuiStyleVar_FrameBorderSize, 0.0F);
|
||||
ImGui::PushStyleColor(ImGuiCol_FrameBg, ImVec4());
|
||||
|
||||
auto text = wolv::util::trim(wolv::util::wrapMonospacedString(
|
||||
m_decodedString,
|
||||
ImGui::CalcTextSize("M").x,
|
||||
std::max(100_scaled, ImGui::GetContentRegionAvail().x - ImGui::GetStyle().ScrollbarSize - ImGui::GetStyle().FrameBorderSize)
|
||||
));
|
||||
|
||||
ImGui::InputTextMultiline(
|
||||
"##",
|
||||
text.data(),
|
||||
text.size() + 1,
|
||||
ImGui::GetContentRegionAvail(),
|
||||
ImGuiInputTextFlags_ReadOnly | ImGuiInputTextFlags_NoHorizontalScroll
|
||||
);
|
||||
|
||||
ImGui::PopStyleColor();
|
||||
ImGui::PopStyleVar(2);
|
||||
}
|
||||
|
||||
[[nodiscard]] UnlocalizedString getTitle() const override {
|
||||
return "hex.builtin.view.hex_editor.menu.edit.decoded_string.popup.title";
|
||||
}
|
||||
|
||||
[[nodiscard]] bool canBePinned() const override { return true; }
|
||||
[[nodiscard]] ImGuiWindowFlags getFlags() const override { return ImGuiWindowFlags_None; }
|
||||
|
||||
private:
|
||||
std::string m_decodedString;
|
||||
ui::TextEditor m_editor;
|
||||
};
|
||||
|
||||
/* Hex Editor */
|
||||
|
||||
ViewHexEditor::ViewHexEditor() : View::Window("hex.builtin.view.hex_editor.name", ICON_VS_FILE_BINARY) {
|
||||
|
||||
Reference in New Issue
Block a user