impr: Added clip library to improve clipboard situation

This commit is contained in:
WerWolv 2025-05-29 19:56:46 +02:00
parent 224fa83c65
commit 96ef758bbd
11 changed files with 146 additions and 36 deletions

3
.gitmodules vendored
View File

@ -47,3 +47,6 @@
[submodule "lib/external/disassembler"]
path = lib/external/disassembler
url = https://github.com/WerWolv/Disassembler
[submodule "lib/third_party/clip"]
path = lib/third_party/clip
url = https://github.com/dacap/clip

View File

@ -761,6 +761,15 @@ macro(addBundledLibraries)
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)
set(XDGPP_INCLUDE_DIRS "${THIRD_PARTY_LIBS_FOLDER}/xdgpp")

View File

@ -42,6 +42,7 @@ set(LIBIMHEX_SOURCES
source/helpers/keys.cpp
source/helpers/freetype.cpp
source/helpers/udp_server.cpp
source/helpers/clipboard.cpp
source/test/tests.cpp
@ -160,8 +161,7 @@ if (NOT IMHEX_EXTERNAL_PLUGIN_BUILD)
endif()
if (NOT EMSCRIPTEN)
# curl is only used in non-emscripten builds
target_link_libraries(libimhex ${LIBIMHEX_LIBRARY_TYPE} CURL::libcurl)
target_link_libraries(libimhex ${LIBIMHEX_LIBRARY_TYPE} CURL::libcurl clip)
endif()
target_include_directories(libimhex ${LIBIMHEX_LIBRARY_TYPE} ${MBEDTLS_INCLUDE_DIR} ${LIBBACKTRACE_INCLUDE_DIRS} ${MAGIC_INCLUDE_DIRS})

View File

@ -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();
}

View File

@ -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
}

1
lib/third_party/clip vendored Submodule

@ -0,0 +1 @@
Subproject commit 7a60eabaad167d9dc91eae439cb2c1ab9d49c6ba

View File

@ -35,8 +35,9 @@
#include <timeapi.h>
#include <VersionHelpers.h>
#include <cstdio>
#include <hex/helpers/clipboard.hpp>
#if !defined(STDIN_FILENO)
#if !defined(STDIN_FILENO)
#define STDIN_FILENO 0
#endif
@ -422,6 +423,8 @@ namespace hex {
}
enumerateFonts();
clipboard::init();
}
class DropManager : public IDropTarget {

View File

@ -17,6 +17,7 @@
#include <wolv/utils/string.hpp>
#include <ranges>
#include <hex/helpers/clipboard.hpp>
namespace hex::plugin::builtin {
@ -279,7 +280,7 @@ namespace hex::plugin::builtin {
const auto providerSize = m_selectedProvider->getActualSize();
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)) {
ImHexApi::HexEditor::setSelection(Region { selection->getStartAddress() - requiredSize, requiredSize });
}
@ -287,7 +288,7 @@ namespace hex::plugin::builtin {
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)) {
ImHexApi::HexEditor::setSelection(Region { selection->getStartAddress() + requiredSize, requiredSize });
}
@ -436,7 +437,7 @@ namespace hex::plugin::builtin {
if (ImGui::BeginPopup("##DataInspectorRowContextMenu")) {
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)) {
entry.editing = true;

View File

@ -15,6 +15,7 @@
#include <content/helpers/demangle.hpp>
#include <boost/regex.hpp>
#include <hex/helpers/clipboard.hpp>
namespace hex::plugin::builtin {
@ -648,9 +649,9 @@ namespace hex::plugin::builtin {
if (ImGui::BeginPopup("FindContextMenu")) {
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))
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::BeginTabBar("##replace_tabs")) {
if (ImGui::BeginTabItem("hex.builtin.view.find.context.replace.hex"_lang)) {

View File

@ -24,6 +24,7 @@
#include <popups/popup_file_chooser.hpp>
#include <content/popups/popup_blocking_task.hpp>
#include <content/popups/hex_editor/popup_hex_editor_find.hpp>
#include <hex/helpers/clipboard.hpp>
#include <pl/patterns/pattern.hpp>
#include <hex/helpers/menu_items.hpp>
#include <wolv/literals.hpp>
@ -744,7 +745,7 @@ namespace hex::plugin::builtin {
}
static void copyBytes(const Region &selection) {
constexpr static auto Format = "{0:02X} ";
//constexpr static auto Format = "{0:02X} ";
auto provider = ImHexApi::Provider::get();
if (provider == nullptr)
@ -754,33 +755,16 @@ namespace hex::plugin::builtin {
reader.seek(selection.getStartAddress());
reader.setEndAddress(selection.getEndAddress());
std::string result;
result.reserve(fmt::format(Format, 0x00).size() * selection.getSize());
for (const auto &byte : reader)
result += fmt::format(Format, byte);
result.pop_back();
ImGui::SetClipboardText(result.c_str());
auto bytes = std::vector(reader.begin(), reader.end());
clipboard::setBinaryData(bytes);
}
static void pasteBytes(const Region &selection, bool selectionCheck, bool asPlainText) {
static void pasteBytes(const Region &selection, bool selectionCheck, bool) {
auto provider = ImHexApi::Provider::get();
if (provider == nullptr)
return;
auto clipboard = ImGui::GetClipboardText();
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);
auto buffer = clipboard::getBinaryData();
if (!selectionCheck) {
if (selection.getStartAddress() + buffer.size() >= provider->getActualSize())
@ -831,7 +815,7 @@ namespace hex::plugin::builtin {
buffer.reserve(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) {
@ -851,7 +835,7 @@ namespace hex::plugin::builtin {
offset += size;
}
ImGui::SetClipboardText(string.c_str());
clipboard::setTextData(string);
}
void ViewHexEditor::registerShortcuts() {
@ -1264,7 +1248,7 @@ namespace hex::plugin::builtin {
[] {
auto selection = ImHexApi::HexEditor::getSelection();
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);
@ -1291,7 +1275,7 @@ namespace hex::plugin::builtin {
bool enabled = ImHexApi::HexEditor::isSelectionValid();
for (const auto &[unlocalizedName, callback] : ContentRegistry::DataFormatter::impl::getExportMenuEntries()) {
if (menu::menuItem(Lang(unlocalizedName), Shortcut::None, false, enabled)) {
ImGui::SetClipboardText(
clipboard::setTextData(
callback(
provider,
selection->getStartAddress(),

View File

@ -10,6 +10,7 @@
#include <popups/popup_file_chooser.hpp>
#include <filesystem>
#include <hex/helpers/clipboard.hpp>
#include <wolv/io/fs.hpp>
#include <wolv/literals.hpp>
@ -231,7 +232,7 @@ namespace hex::plugin::yara {
const auto &message = m_consoleMessages->at(i);
if (ImGui::Selectable(message.c_str()))
ImGui::SetClipboardText(message.c_str());
clipboard::setTextData(message);
}
}
}