From 13e079d1b806f61ed36c1b15657bb3cd6c3948d5 Mon Sep 17 00:00:00 2001 From: BioTheWolff <47079795+BioTheWolff@users.noreply.github.com> Date: Sat, 14 Dec 2024 16:52:14 +0100 Subject: [PATCH] feat: Add capability to paste as string literal in files (#1998) ### Problem description As suggested in #1904, ImHex could benefit from having the capability of pasting text directly into the editor. This also complements the "Copy as... ASCII string" capability already implemented in the software. ### Implementation description A new shortcut called `Paste all as string` (to resemble the naming of the `ASCII string` copy option) now allows to paste plaintext directly. This shortcut is mapped to the `CTRL + ALT + SHIFT + V` keybind. Internally, a new flag called `asPlainText` has been added to the `pasteBytes` function, to minimise code changes and streamline code readability. The buffer is a simple type cast of the clipboard, without any modification applied, which is then handed to the provider's `write` function. ### Screenshots The new shortcut is visible in the menu, just below the other paste options: ![image](https://github.com/user-attachments/assets/41a2a512-5c39-4984-bab6-114c58266351) --------- Signed-off-by: BioTheWolff <47079795+BioTheWolff@users.noreply.github.com> --- plugins/builtin/romfs/lang/en_US.json | 2 ++ .../source/content/views/view_hex_editor.cpp | 31 +++++++++++++++---- 2 files changed, 27 insertions(+), 6 deletions(-) diff --git a/plugins/builtin/romfs/lang/en_US.json b/plugins/builtin/romfs/lang/en_US.json index 0fd6bb5fc..42848f607 100644 --- a/plugins/builtin/romfs/lang/en_US.json +++ b/plugins/builtin/romfs/lang/en_US.json @@ -818,7 +818,9 @@ "hex.builtin.view.hex_editor.menu.edit.jump_to.curr_pattern": "Current Pattern", "hex.builtin.view.hex_editor.menu.edit.open_in_new_provider": "Open selection view...", "hex.builtin.view.hex_editor.menu.edit.paste": "Paste", + "hex.builtin.view.hex_editor.menu.edit.paste_as": "Paste...", "hex.builtin.view.hex_editor.menu.edit.paste_all": "Paste all", + "hex.builtin.view.hex_editor.menu.edit.paste_all_string": "Paste all as string", "hex.builtin.view.hex_editor.menu.edit.remove": "Remove...", "hex.builtin.view.hex_editor.menu.edit.resize": "Resize...", "hex.builtin.view.hex_editor.menu.edit.select_all": "Select all", diff --git a/plugins/builtin/source/content/views/view_hex_editor.cpp b/plugins/builtin/source/content/views/view_hex_editor.cpp index 3b5a8d152..b61b33f6c 100644 --- a/plugins/builtin/source/content/views/view_hex_editor.cpp +++ b/plugins/builtin/source/content/views/view_hex_editor.cpp @@ -702,7 +702,7 @@ namespace hex::plugin::builtin { ImGui::SetClipboardText(result.c_str()); } - static void pasteBytes(const Region &selection, bool selectionCheck) { + static void pasteBytes(const Region &selection, bool selectionCheck, bool asPlainText) { auto provider = ImHexApi::Provider::get(); if (provider == nullptr) return; @@ -711,7 +711,14 @@ namespace hex::plugin::builtin { if (clipboard == nullptr) return; - auto buffer = parseHexString(clipboard); + std::vector buffer; + if (asPlainText) { + // Directly reinterpret clipboard as an array of bytes + std::string cp = clipboard; + buffer = std::vector(cp.begin(), cp.end()); + } + else + buffer = parseHexString(clipboard); if (!selectionCheck) { if (selection.getStartAddress() + buffer.size() >= provider->getActualSize()) @@ -1184,15 +1191,27 @@ namespace hex::plugin::builtin { /* Paste */ ContentRegistry::Interface::addMenuItem({ "hex.builtin.menu.edit", "hex.builtin.view.hex_editor.menu.edit.paste" }, ICON_VS_OUTPUT, 1450, CurrentView + CTRLCMD + Keys::V, [] { - pasteBytes(ImHexApi::HexEditor::getSelection().value_or( ImHexApi::HexEditor::ProviderRegion(Region { 0, 0 }, ImHexApi::Provider::get())), true); + pasteBytes(ImHexApi::HexEditor::getSelection().value_or( ImHexApi::HexEditor::ProviderRegion(Region { 0, 0 }, ImHexApi::Provider::get())), true, false); }, ImHexApi::HexEditor::isSelectionValid, this); - /* Paste All */ - ContentRegistry::Interface::addMenuItem({ "hex.builtin.menu.edit", "hex.builtin.view.hex_editor.menu.edit.paste_all" }, ICON_VS_CLIPPY, 1500, CurrentView + CTRLCMD + SHIFT + Keys::V, + /* Paste... */ + ContentRegistry::Interface::addMenuItemSubMenu({ "hex.builtin.menu.edit", "hex.builtin.view.hex_editor.menu.edit.paste_as" }, ICON_VS_CLIPPY, 1490, []{}, ImHexApi::HexEditor::isSelectionValid); + + /* Paste... > Paste all */ + ContentRegistry::Interface::addMenuItem({ "hex.builtin.menu.edit", "hex.builtin.view.hex_editor.menu.edit.paste_as", "hex.builtin.view.hex_editor.menu.edit.paste_all" }, ICON_VS_CLIPPY, 1500, CurrentView + CTRLCMD + SHIFT + Keys::V, [] { - pasteBytes(ImHexApi::HexEditor::getSelection().value_or( ImHexApi::HexEditor::ProviderRegion(Region { 0, 0 }, ImHexApi::Provider::get())), false); + pasteBytes(ImHexApi::HexEditor::getSelection().value_or( ImHexApi::HexEditor::ProviderRegion(Region { 0, 0 }, ImHexApi::Provider::get())), false, false); + }, + ImHexApi::HexEditor::isSelectionValid, + this); + + /* Paste... > Paste all as string */ + ContentRegistry::Interface::addMenuItem({ "hex.builtin.menu.edit", "hex.builtin.view.hex_editor.menu.edit.paste_as", "hex.builtin.view.hex_editor.menu.edit.paste_all_string" }, ICON_VS_SYMBOL_TEXT, 1510, + Shortcut::None, + [] { + pasteBytes(ImHexApi::HexEditor::getSelection().value_or( ImHexApi::HexEditor::ProviderRegion(Region { 0, 0 }, ImHexApi::Provider::get())), false, true); }, ImHexApi::HexEditor::isSelectionValid, this);