mirror of https://github.com/WerWolv/ImHex
impr: Added clip library to improve clipboard situation
This commit is contained in:
parent
224fa83c65
commit
96ef758bbd
|
|
@ -47,3 +47,6 @@
|
||||||
[submodule "lib/external/disassembler"]
|
[submodule "lib/external/disassembler"]
|
||||||
path = lib/external/disassembler
|
path = lib/external/disassembler
|
||||||
url = https://github.com/WerWolv/Disassembler
|
url = https://github.com/WerWolv/Disassembler
|
||||||
|
[submodule "lib/third_party/clip"]
|
||||||
|
path = lib/third_party/clip
|
||||||
|
url = https://github.com/dacap/clip
|
||||||
|
|
|
||||||
|
|
@ -761,6 +761,15 @@ macro(addBundledLibraries)
|
||||||
|
|
||||||
add_subdirectory(${THIRD_PARTY_LIBS_FOLDER}/microtar EXCLUDE_FROM_ALL)
|
add_subdirectory(${THIRD_PARTY_LIBS_FOLDER}/microtar EXCLUDE_FROM_ALL)
|
||||||
|
|
||||||
|
set(CLIP_ENABLE_IMAGE OFF CACHE BOOL "")
|
||||||
|
set(CLIP_EXAMPLES OFF CACHE BOOL "")
|
||||||
|
set(CLIP_TESTS OFF CACHE BOOL "")
|
||||||
|
set(CLIP_INSTALL OFF CACHE BOOL "")
|
||||||
|
set(CLIP_X11_WITH_PNG OFF CACHE BOOL "")
|
||||||
|
set(CLIP_SUPPORT_WINXP OFF CACHE BOOL "")
|
||||||
|
add_subdirectory(${THIRD_PARTY_LIBS_FOLDER}/clip EXCLUDE_FROM_ALL)
|
||||||
|
target_include_directories(clip INTERFACE $<BUILD_INTERFACE:${THIRD_PARTY_LIBS_FOLDER}/clip>)
|
||||||
|
|
||||||
add_subdirectory(${EXTERNAL_LIBS_FOLDER}/libwolv EXCLUDE_FROM_ALL)
|
add_subdirectory(${EXTERNAL_LIBS_FOLDER}/libwolv EXCLUDE_FROM_ALL)
|
||||||
|
|
||||||
set(XDGPP_INCLUDE_DIRS "${THIRD_PARTY_LIBS_FOLDER}/xdgpp")
|
set(XDGPP_INCLUDE_DIRS "${THIRD_PARTY_LIBS_FOLDER}/xdgpp")
|
||||||
|
|
|
||||||
|
|
@ -42,6 +42,7 @@ set(LIBIMHEX_SOURCES
|
||||||
source/helpers/keys.cpp
|
source/helpers/keys.cpp
|
||||||
source/helpers/freetype.cpp
|
source/helpers/freetype.cpp
|
||||||
source/helpers/udp_server.cpp
|
source/helpers/udp_server.cpp
|
||||||
|
source/helpers/clipboard.cpp
|
||||||
|
|
||||||
source/test/tests.cpp
|
source/test/tests.cpp
|
||||||
|
|
||||||
|
|
@ -160,8 +161,7 @@ if (NOT IMHEX_EXTERNAL_PLUGIN_BUILD)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
if (NOT EMSCRIPTEN)
|
if (NOT EMSCRIPTEN)
|
||||||
# curl is only used in non-emscripten builds
|
target_link_libraries(libimhex ${LIBIMHEX_LIBRARY_TYPE} CURL::libcurl clip)
|
||||||
target_link_libraries(libimhex ${LIBIMHEX_LIBRARY_TYPE} CURL::libcurl)
|
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
target_include_directories(libimhex ${LIBIMHEX_LIBRARY_TYPE} ${MBEDTLS_INCLUDE_DIR} ${LIBBACKTRACE_INCLUDE_DIRS} ${MAGIC_INCLUDE_DIRS})
|
target_include_directories(libimhex ${LIBIMHEX_LIBRARY_TYPE} ${MBEDTLS_INCLUDE_DIR} ${LIBBACKTRACE_INCLUDE_DIRS} ${MAGIC_INCLUDE_DIRS})
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,16 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <hex.hpp>
|
||||||
|
#include <span>
|
||||||
|
#include <string>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
namespace hex::clipboard {
|
||||||
|
|
||||||
|
void init();
|
||||||
|
void setBinaryData(std::span<const u8> data);
|
||||||
|
[[nodiscard]] std::vector<u8> getBinaryData();
|
||||||
|
void setTextData(const std::string &string);
|
||||||
|
[[nodiscard]] std::string getTextData();
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,91 @@
|
||||||
|
#include <hex/helpers/clipboard.hpp>
|
||||||
|
|
||||||
|
#if __has_include(<clip.h>)
|
||||||
|
#define CLIP_LIBRARY
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if defined(CLIP_LIBRARY)
|
||||||
|
#include <clip.h>
|
||||||
|
#else
|
||||||
|
#include <imgui.h>
|
||||||
|
#include <fmt/color.h>
|
||||||
|
#include <hex/helpers/utils.hpp>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
namespace hex::clipboard {
|
||||||
|
|
||||||
|
#if defined(CLIP_LIBRARY)
|
||||||
|
|
||||||
|
static clip::format s_binaryFormat;
|
||||||
|
static clip::format s_textFormat;
|
||||||
|
|
||||||
|
void init() {
|
||||||
|
s_binaryFormat = clip::register_format("net.werwolv.imhex.binary");
|
||||||
|
s_textFormat = clip::text_format();
|
||||||
|
}
|
||||||
|
|
||||||
|
void setBinaryData(std::span<const u8> data) {
|
||||||
|
clip::lock l;
|
||||||
|
l.set_data(s_binaryFormat, reinterpret_cast<const char*>(data.data()), data.size());
|
||||||
|
}
|
||||||
|
|
||||||
|
std::vector<u8> getBinaryData() {
|
||||||
|
clip::lock l;
|
||||||
|
|
||||||
|
const auto size = l.get_data_length(s_binaryFormat);
|
||||||
|
std::vector<u8> data(size);
|
||||||
|
l.get_data(s_binaryFormat, reinterpret_cast<char*>(data.data()), size);
|
||||||
|
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
|
||||||
|
void setTextData(const std::string &string) {
|
||||||
|
clip::lock l;
|
||||||
|
l.set_data(s_textFormat, string.data(), string.size());
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string getTextData() {
|
||||||
|
clip::lock l;
|
||||||
|
|
||||||
|
const auto size = l.get_data_length(s_binaryFormat);
|
||||||
|
std::string data(size, 0x00);
|
||||||
|
l.get_data(s_textFormat, data.data(), size);
|
||||||
|
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
|
||||||
|
#else
|
||||||
|
|
||||||
|
void init() {}
|
||||||
|
|
||||||
|
void setBinaryData(std::span<const u8> data) {
|
||||||
|
constexpr static auto Format = "{0:02X} ";
|
||||||
|
std::string result;
|
||||||
|
result.reserve(fmt::format(Format, 0x00).size() * data.size_bytes());
|
||||||
|
|
||||||
|
for (const auto &byte : data)
|
||||||
|
result += fmt::format(Format, byte);
|
||||||
|
result.pop_back();
|
||||||
|
|
||||||
|
ImGui::SetClipboardText(result.c_str());
|
||||||
|
}
|
||||||
|
|
||||||
|
std::vector<u8> getBinaryData() {
|
||||||
|
auto clipboard = ImGui::GetClipboardText();
|
||||||
|
if (clipboard == nullptr)
|
||||||
|
return {};
|
||||||
|
|
||||||
|
return parseHexString(clipboard);
|
||||||
|
}
|
||||||
|
|
||||||
|
void setTextData(const std::string &string) {
|
||||||
|
ImGui::SetClipboardText(string.c_str());
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string getTextData() {
|
||||||
|
return ImGui::GetClipboardText();
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1 @@
|
||||||
|
Subproject commit 7a60eabaad167d9dc91eae439cb2c1ab9d49c6ba
|
||||||
|
|
@ -35,8 +35,9 @@
|
||||||
#include <timeapi.h>
|
#include <timeapi.h>
|
||||||
#include <VersionHelpers.h>
|
#include <VersionHelpers.h>
|
||||||
#include <cstdio>
|
#include <cstdio>
|
||||||
|
#include <hex/helpers/clipboard.hpp>
|
||||||
|
|
||||||
#if !defined(STDIN_FILENO)
|
#if !defined(STDIN_FILENO)
|
||||||
#define STDIN_FILENO 0
|
#define STDIN_FILENO 0
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
@ -422,6 +423,8 @@ namespace hex {
|
||||||
}
|
}
|
||||||
|
|
||||||
enumerateFonts();
|
enumerateFonts();
|
||||||
|
|
||||||
|
clipboard::init();
|
||||||
}
|
}
|
||||||
|
|
||||||
class DropManager : public IDropTarget {
|
class DropManager : public IDropTarget {
|
||||||
|
|
|
||||||
|
|
@ -17,6 +17,7 @@
|
||||||
#include <wolv/utils/string.hpp>
|
#include <wolv/utils/string.hpp>
|
||||||
|
|
||||||
#include <ranges>
|
#include <ranges>
|
||||||
|
#include <hex/helpers/clipboard.hpp>
|
||||||
|
|
||||||
namespace hex::plugin::builtin {
|
namespace hex::plugin::builtin {
|
||||||
|
|
||||||
|
|
@ -279,7 +280,7 @@ namespace hex::plugin::builtin {
|
||||||
const auto providerSize = m_selectedProvider->getActualSize();
|
const auto providerSize = m_selectedProvider->getActualSize();
|
||||||
const auto providerEndAddress = baseAddress + providerSize;
|
const auto providerEndAddress = baseAddress + providerSize;
|
||||||
|
|
||||||
ImGui::BeginDisabled(providerSize < requiredSize || selection->getStartAddress() < baseAddress + requiredSize);
|
ImGui::BeginDisabled(providerSize < requiredSize || (selection.has_value() && selection->getStartAddress() < baseAddress + requiredSize));
|
||||||
if (ImGuiExt::DimmedIconButton(ICON_VS_ARROW_LEFT, ImGui::GetStyleColorVec4(ImGuiCol_Text), buttonSize)) {
|
if (ImGuiExt::DimmedIconButton(ICON_VS_ARROW_LEFT, ImGui::GetStyleColorVec4(ImGuiCol_Text), buttonSize)) {
|
||||||
ImHexApi::HexEditor::setSelection(Region { selection->getStartAddress() - requiredSize, requiredSize });
|
ImHexApi::HexEditor::setSelection(Region { selection->getStartAddress() - requiredSize, requiredSize });
|
||||||
}
|
}
|
||||||
|
|
@ -287,7 +288,7 @@ namespace hex::plugin::builtin {
|
||||||
|
|
||||||
ImGui::SameLine();
|
ImGui::SameLine();
|
||||||
|
|
||||||
ImGui::BeginDisabled(providerSize < requiredSize || selection->getEndAddress() > providerEndAddress - requiredSize);
|
ImGui::BeginDisabled(providerSize < requiredSize || (selection.has_value() && selection->getEndAddress() > providerEndAddress - requiredSize));
|
||||||
if (ImGuiExt::DimmedIconButton(ICON_VS_ARROW_RIGHT, ImGui::GetStyleColorVec4(ImGuiCol_Text), buttonSize)) {
|
if (ImGuiExt::DimmedIconButton(ICON_VS_ARROW_RIGHT, ImGui::GetStyleColorVec4(ImGuiCol_Text), buttonSize)) {
|
||||||
ImHexApi::HexEditor::setSelection(Region { selection->getStartAddress() + requiredSize, requiredSize });
|
ImHexApi::HexEditor::setSelection(Region { selection->getStartAddress() + requiredSize, requiredSize });
|
||||||
}
|
}
|
||||||
|
|
@ -436,7 +437,7 @@ namespace hex::plugin::builtin {
|
||||||
|
|
||||||
if (ImGui::BeginPopup("##DataInspectorRowContextMenu")) {
|
if (ImGui::BeginPopup("##DataInspectorRowContextMenu")) {
|
||||||
if (ImGui::MenuItemEx("hex.builtin.view.data_inspector.menu.copy"_lang, ICON_VS_COPY)) {
|
if (ImGui::MenuItemEx("hex.builtin.view.data_inspector.menu.copy"_lang, ICON_VS_COPY)) {
|
||||||
ImGui::SetClipboardText(copyValue.c_str());
|
clipboard::setTextData(copyValue);
|
||||||
}
|
}
|
||||||
if (ImGui::MenuItemEx("hex.builtin.view.data_inspector.menu.edit"_lang, ICON_VS_EDIT, nullptr, false, editable)) {
|
if (ImGui::MenuItemEx("hex.builtin.view.data_inspector.menu.edit"_lang, ICON_VS_EDIT, nullptr, false, editable)) {
|
||||||
entry.editing = true;
|
entry.editing = true;
|
||||||
|
|
@ -593,4 +594,4 @@ namespace hex::plugin::builtin {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -15,6 +15,7 @@
|
||||||
|
|
||||||
#include <content/helpers/demangle.hpp>
|
#include <content/helpers/demangle.hpp>
|
||||||
#include <boost/regex.hpp>
|
#include <boost/regex.hpp>
|
||||||
|
#include <hex/helpers/clipboard.hpp>
|
||||||
|
|
||||||
namespace hex::plugin::builtin {
|
namespace hex::plugin::builtin {
|
||||||
|
|
||||||
|
|
@ -648,9 +649,9 @@ namespace hex::plugin::builtin {
|
||||||
|
|
||||||
if (ImGui::BeginPopup("FindContextMenu")) {
|
if (ImGui::BeginPopup("FindContextMenu")) {
|
||||||
if (ImGui::MenuItemEx("hex.builtin.view.find.context.copy"_lang, ICON_VS_COPY))
|
if (ImGui::MenuItemEx("hex.builtin.view.find.context.copy"_lang, ICON_VS_COPY))
|
||||||
ImGui::SetClipboardText(value.c_str());
|
clipboard::setTextData(value);
|
||||||
if (ImGui::MenuItemEx("hex.builtin.view.find.context.copy_demangle"_lang, ICON_VS_FILES))
|
if (ImGui::MenuItemEx("hex.builtin.view.find.context.copy_demangle"_lang, ICON_VS_FILES))
|
||||||
ImGui::SetClipboardText(hex::plugin::builtin::demangle(value).c_str());
|
clipboard::setTextData(hex::plugin::builtin::demangle(value));
|
||||||
if (ImGui::BeginMenuEx("hex.builtin.view.find.context.replace"_lang, ICON_VS_REPLACE)) {
|
if (ImGui::BeginMenuEx("hex.builtin.view.find.context.replace"_lang, ICON_VS_REPLACE)) {
|
||||||
if (ImGui::BeginTabBar("##replace_tabs")) {
|
if (ImGui::BeginTabBar("##replace_tabs")) {
|
||||||
if (ImGui::BeginTabItem("hex.builtin.view.find.context.replace.hex"_lang)) {
|
if (ImGui::BeginTabItem("hex.builtin.view.find.context.replace.hex"_lang)) {
|
||||||
|
|
|
||||||
|
|
@ -24,6 +24,7 @@
|
||||||
#include <popups/popup_file_chooser.hpp>
|
#include <popups/popup_file_chooser.hpp>
|
||||||
#include <content/popups/popup_blocking_task.hpp>
|
#include <content/popups/popup_blocking_task.hpp>
|
||||||
#include <content/popups/hex_editor/popup_hex_editor_find.hpp>
|
#include <content/popups/hex_editor/popup_hex_editor_find.hpp>
|
||||||
|
#include <hex/helpers/clipboard.hpp>
|
||||||
#include <pl/patterns/pattern.hpp>
|
#include <pl/patterns/pattern.hpp>
|
||||||
#include <hex/helpers/menu_items.hpp>
|
#include <hex/helpers/menu_items.hpp>
|
||||||
#include <wolv/literals.hpp>
|
#include <wolv/literals.hpp>
|
||||||
|
|
@ -744,7 +745,7 @@ namespace hex::plugin::builtin {
|
||||||
}
|
}
|
||||||
|
|
||||||
static void copyBytes(const Region &selection) {
|
static void copyBytes(const Region &selection) {
|
||||||
constexpr static auto Format = "{0:02X} ";
|
//constexpr static auto Format = "{0:02X} ";
|
||||||
|
|
||||||
auto provider = ImHexApi::Provider::get();
|
auto provider = ImHexApi::Provider::get();
|
||||||
if (provider == nullptr)
|
if (provider == nullptr)
|
||||||
|
|
@ -754,33 +755,16 @@ namespace hex::plugin::builtin {
|
||||||
reader.seek(selection.getStartAddress());
|
reader.seek(selection.getStartAddress());
|
||||||
reader.setEndAddress(selection.getEndAddress());
|
reader.setEndAddress(selection.getEndAddress());
|
||||||
|
|
||||||
std::string result;
|
auto bytes = std::vector(reader.begin(), reader.end());
|
||||||
result.reserve(fmt::format(Format, 0x00).size() * selection.getSize());
|
clipboard::setBinaryData(bytes);
|
||||||
|
|
||||||
for (const auto &byte : reader)
|
|
||||||
result += fmt::format(Format, byte);
|
|
||||||
result.pop_back();
|
|
||||||
|
|
||||||
ImGui::SetClipboardText(result.c_str());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void pasteBytes(const Region &selection, bool selectionCheck, bool asPlainText) {
|
static void pasteBytes(const Region &selection, bool selectionCheck, bool) {
|
||||||
auto provider = ImHexApi::Provider::get();
|
auto provider = ImHexApi::Provider::get();
|
||||||
if (provider == nullptr)
|
if (provider == nullptr)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
auto clipboard = ImGui::GetClipboardText();
|
auto buffer = clipboard::getBinaryData();
|
||||||
if (clipboard == nullptr)
|
|
||||||
return;
|
|
||||||
|
|
||||||
std::vector<u8> buffer;
|
|
||||||
if (asPlainText) {
|
|
||||||
// Directly reinterpret clipboard as an array of bytes
|
|
||||||
std::string cp = clipboard;
|
|
||||||
buffer = std::vector<u8>(cp.begin(), cp.end());
|
|
||||||
}
|
|
||||||
else
|
|
||||||
buffer = parseHexString(clipboard);
|
|
||||||
|
|
||||||
if (!selectionCheck) {
|
if (!selectionCheck) {
|
||||||
if (selection.getStartAddress() + buffer.size() >= provider->getActualSize())
|
if (selection.getStartAddress() + buffer.size() >= provider->getActualSize())
|
||||||
|
|
@ -831,7 +815,7 @@ namespace hex::plugin::builtin {
|
||||||
buffer.reserve(selection.size);
|
buffer.reserve(selection.size);
|
||||||
provider->read(selection.getStartAddress(), buffer.data(), selection.size);
|
provider->read(selection.getStartAddress(), buffer.data(), selection.size);
|
||||||
|
|
||||||
ImGui::SetClipboardText(buffer.c_str());
|
clipboard::setTextData(buffer);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void copyCustomEncoding(const EncodingFile &customEncoding, const Region &selection) {
|
static void copyCustomEncoding(const EncodingFile &customEncoding, const Region &selection) {
|
||||||
|
|
@ -851,7 +835,7 @@ namespace hex::plugin::builtin {
|
||||||
offset += size;
|
offset += size;
|
||||||
}
|
}
|
||||||
|
|
||||||
ImGui::SetClipboardText(string.c_str());
|
clipboard::setTextData(string);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ViewHexEditor::registerShortcuts() {
|
void ViewHexEditor::registerShortcuts() {
|
||||||
|
|
@ -1264,7 +1248,7 @@ namespace hex::plugin::builtin {
|
||||||
[] {
|
[] {
|
||||||
auto selection = ImHexApi::HexEditor::getSelection();
|
auto selection = ImHexApi::HexEditor::getSelection();
|
||||||
if (selection.has_value() && selection != Region::Invalid())
|
if (selection.has_value() && selection != Region::Invalid())
|
||||||
ImGui::SetClipboardText(hex::format("0x{:08X}", selection->getStartAddress()).c_str());
|
clipboard::setTextData(hex::format("0x{:08X}", selection->getStartAddress()));
|
||||||
},
|
},
|
||||||
ImHexApi::HexEditor::isSelectionValid);
|
ImHexApi::HexEditor::isSelectionValid);
|
||||||
|
|
||||||
|
|
@ -1291,7 +1275,7 @@ namespace hex::plugin::builtin {
|
||||||
bool enabled = ImHexApi::HexEditor::isSelectionValid();
|
bool enabled = ImHexApi::HexEditor::isSelectionValid();
|
||||||
for (const auto &[unlocalizedName, callback] : ContentRegistry::DataFormatter::impl::getExportMenuEntries()) {
|
for (const auto &[unlocalizedName, callback] : ContentRegistry::DataFormatter::impl::getExportMenuEntries()) {
|
||||||
if (menu::menuItem(Lang(unlocalizedName), Shortcut::None, false, enabled)) {
|
if (menu::menuItem(Lang(unlocalizedName), Shortcut::None, false, enabled)) {
|
||||||
ImGui::SetClipboardText(
|
clipboard::setTextData(
|
||||||
callback(
|
callback(
|
||||||
provider,
|
provider,
|
||||||
selection->getStartAddress(),
|
selection->getStartAddress(),
|
||||||
|
|
|
||||||
|
|
@ -10,6 +10,7 @@
|
||||||
#include <popups/popup_file_chooser.hpp>
|
#include <popups/popup_file_chooser.hpp>
|
||||||
|
|
||||||
#include <filesystem>
|
#include <filesystem>
|
||||||
|
#include <hex/helpers/clipboard.hpp>
|
||||||
|
|
||||||
#include <wolv/io/fs.hpp>
|
#include <wolv/io/fs.hpp>
|
||||||
#include <wolv/literals.hpp>
|
#include <wolv/literals.hpp>
|
||||||
|
|
@ -231,7 +232,7 @@ namespace hex::plugin::yara {
|
||||||
const auto &message = m_consoleMessages->at(i);
|
const auto &message = m_consoleMessages->at(i);
|
||||||
|
|
||||||
if (ImGui::Selectable(message.c_str()))
|
if (ImGui::Selectable(message.c_str()))
|
||||||
ImGui::SetClipboardText(message.c_str());
|
clipboard::setTextData(message);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue