mirror of https://github.com/WerWolv/ImHex
feat: Add support for custom inspector edit widgets
This commit is contained in:
parent
21e61bfce6
commit
de25ce7fbb
|
|
@ -8,6 +8,7 @@
|
||||||
#include <optional>
|
#include <optional>
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
#include <bit>
|
||||||
|
|
||||||
EXPORT_MODULE namespace hex {
|
EXPORT_MODULE namespace hex {
|
||||||
|
|
||||||
|
|
@ -22,8 +23,10 @@ EXPORT_MODULE namespace hex {
|
||||||
|
|
||||||
namespace impl {
|
namespace impl {
|
||||||
|
|
||||||
|
struct DoNotUseThisByItselfTag {};
|
||||||
|
|
||||||
using DisplayFunction = std::function<std::string()>;
|
using DisplayFunction = std::function<std::string()>;
|
||||||
using EditingFunction = std::function<std::vector<u8>(std::string, std::endian)>;
|
using EditingFunction = std::function<std::optional<std::vector<u8>>(std::string&, std::endian, DoNotUseThisByItselfTag)>;
|
||||||
using GeneratorFunction = std::function<DisplayFunction(const std::vector<u8> &, std::endian, NumberDisplayStyle)>;
|
using GeneratorFunction = std::function<DisplayFunction(const std::vector<u8> &, std::endian, NumberDisplayStyle)>;
|
||||||
|
|
||||||
struct Entry {
|
struct Entry {
|
||||||
|
|
@ -38,6 +41,35 @@ EXPORT_MODULE namespace hex {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
namespace EditWidget {
|
||||||
|
|
||||||
|
class Widget {
|
||||||
|
public:
|
||||||
|
using Function = std::function<std::vector<u8>(const std::string&, std::endian)>;
|
||||||
|
|
||||||
|
explicit Widget(const Function &function) : m_function(function) {}
|
||||||
|
|
||||||
|
virtual ~Widget() = default;
|
||||||
|
virtual std::optional<std::vector<u8>> draw(std::string &value, std::endian endian) = 0;
|
||||||
|
std::optional<std::vector<u8>> operator()(std::string &value, std::endian endian, impl::DoNotUseThisByItselfTag) {
|
||||||
|
return draw(value, endian);
|
||||||
|
}
|
||||||
|
|
||||||
|
std::vector<u8> getBytes(const std::string &value, std::endian endian) const {
|
||||||
|
return m_function(value, endian);
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
Function m_function;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct TextInput : Widget {
|
||||||
|
explicit TextInput(const Function &function) : Widget(function) {}
|
||||||
|
std::optional<std::vector<u8>> draw(std::string &value, std::endian endian) override;
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Adds a new entry to the data inspector
|
* @brief Adds a new entry to the data inspector
|
||||||
* @param unlocalizedName The unlocalized name of the entry
|
* @param unlocalizedName The unlocalized name of the entry
|
||||||
|
|
|
||||||
|
|
@ -870,6 +870,18 @@ namespace hex {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
namespace EditWidget {
|
||||||
|
std::optional<std::vector<u8>> TextInput::draw(std::string &value, std::endian endian) {
|
||||||
|
if (ImGui::InputText("##InspectorLineEditing", value,
|
||||||
|
ImGuiInputTextFlags_EnterReturnsTrue |
|
||||||
|
ImGuiInputTextFlags_AutoSelectAll)) {
|
||||||
|
return getBytes(value, endian);
|
||||||
|
}
|
||||||
|
|
||||||
|
return std::nullopt;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void add(const UnlocalizedString &unlocalizedName, size_t requiredSize, impl::GeneratorFunction displayGeneratorFunction, std::optional<impl::EditingFunction> editingFunction) {
|
void add(const UnlocalizedString &unlocalizedName, size_t requiredSize, impl::GeneratorFunction displayGeneratorFunction, std::optional<impl::EditingFunction> editingFunction) {
|
||||||
log::debug("Registered new data inspector format: {}", unlocalizedName.get());
|
log::debug("Registered new data inspector format: {}", unlocalizedName.get());
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -33,7 +33,8 @@ namespace hex::plugin::builtin {
|
||||||
};
|
};
|
||||||
|
|
||||||
template<std::unsigned_integral T, size_t Size = sizeof(T)>
|
template<std::unsigned_integral T, size_t Size = sizeof(T)>
|
||||||
static std::vector<u8> stringToUnsigned(const std::string &value, std::endian endian) requires(sizeof(T) <= sizeof(u64)) {
|
static ContentRegistry::DataInspector::impl::EditingFunction stringToUnsigned() requires(sizeof(T) <= sizeof(u64)) {
|
||||||
|
return ContentRegistry::DataInspector::EditWidget::TextInput([](const std::string &value, std::endian endian) -> std::vector<u8> {
|
||||||
const auto result = wolv::util::from_chars<u64>(value).value_or(0);
|
const auto result = wolv::util::from_chars<u64>(value).value_or(0);
|
||||||
if (result > std::numeric_limits<T>::max()) return {};
|
if (result > std::numeric_limits<T>::max()) return {};
|
||||||
|
|
||||||
|
|
@ -44,10 +45,12 @@ namespace hex::plugin::builtin {
|
||||||
std::reverse(bytes.begin(), bytes.end());
|
std::reverse(bytes.begin(), bytes.end());
|
||||||
|
|
||||||
return bytes;
|
return bytes;
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
template<std::signed_integral T, size_t Size = sizeof(T)>
|
template<std::signed_integral T, size_t Size = sizeof(T)>
|
||||||
static std::vector<u8> stringToSigned(const std::string &value, std::endian endian) requires(sizeof(T) <= sizeof(u64)) {
|
static ContentRegistry::DataInspector::impl::EditingFunction stringToSigned() requires(sizeof(T) <= sizeof(u64)) {
|
||||||
|
return ContentRegistry::DataInspector::EditWidget::TextInput([](const std::string &value, std::endian endian) -> std::vector<u8> {
|
||||||
const auto result = wolv::util::from_chars<i64>(value).value_or(0);
|
const auto result = wolv::util::from_chars<i64>(value).value_or(0);
|
||||||
if (result > std::numeric_limits<T>::max() || result < std::numeric_limits<T>::min()) return {};
|
if (result > std::numeric_limits<T>::max() || result < std::numeric_limits<T>::min()) return {};
|
||||||
|
|
||||||
|
|
@ -58,10 +61,12 @@ namespace hex::plugin::builtin {
|
||||||
std::reverse(bytes.begin(), bytes.end());
|
std::reverse(bytes.begin(), bytes.end());
|
||||||
|
|
||||||
return bytes;
|
return bytes;
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
template<std::floating_point T>
|
template<std::floating_point T>
|
||||||
static std::vector<u8> stringToFloat(const std::string &value, std::endian endian) requires(sizeof(T) <= sizeof(long double)) {
|
static ContentRegistry::DataInspector::impl::EditingFunction stringToFloat() requires(sizeof(T) <= sizeof(long double)) {
|
||||||
|
return ContentRegistry::DataInspector::EditWidget::TextInput([](const std::string &value, std::endian endian) -> std::vector<u8> {
|
||||||
const T result = wolv::util::from_chars<double>(value).value_or(0);
|
const T result = wolv::util::from_chars<double>(value).value_or(0);
|
||||||
|
|
||||||
std::vector<u8> bytes(sizeof(T), 0x00);
|
std::vector<u8> bytes(sizeof(T), 0x00);
|
||||||
|
|
@ -71,16 +76,17 @@ namespace hex::plugin::builtin {
|
||||||
std::reverse(bytes.begin(), bytes.end());
|
std::reverse(bytes.begin(), bytes.end());
|
||||||
|
|
||||||
return bytes;
|
return bytes;
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
template<std::integral T, size_t Size = sizeof(T)>
|
template<std::integral T, size_t Size = sizeof(T)>
|
||||||
static std::vector<u8> stringToInteger(const std::string &value, std::endian endian) requires(sizeof(T) <= sizeof(u64)) {
|
static ContentRegistry::DataInspector::impl::EditingFunction stringToInteger() requires(sizeof(T) <= sizeof(u64)) {
|
||||||
if constexpr (std::unsigned_integral<T>)
|
if constexpr (std::unsigned_integral<T>)
|
||||||
return stringToUnsigned<T, Size>(value, endian);
|
return stringToUnsigned<T, Size>();
|
||||||
else if constexpr (std::signed_integral<T>)
|
else if constexpr (std::signed_integral<T>)
|
||||||
return stringToSigned<T, Size>(value, endian);
|
return stringToSigned<T, Size>();
|
||||||
else
|
else
|
||||||
return {};
|
static_assert("Unsupported type for stringToInteger");
|
||||||
}
|
}
|
||||||
|
|
||||||
template<std::unsigned_integral T, size_t Size = sizeof(T)>
|
template<std::unsigned_integral T, size_t Size = sizeof(T)>
|
||||||
|
|
@ -154,7 +160,8 @@ namespace hex::plugin::builtin {
|
||||||
ImGui::TextUnformatted(binary.c_str());
|
ImGui::TextUnformatted(binary.c_str());
|
||||||
return binary;
|
return binary;
|
||||||
};
|
};
|
||||||
}, [](const std::string &value, std::endian endian) -> std::vector<u8> {
|
},
|
||||||
|
ContentRegistry::DataInspector::EditWidget::TextInput([](const std::string &value, std::endian endian) -> std::vector<u8> {
|
||||||
std::ignore = endian;
|
std::ignore = endian;
|
||||||
|
|
||||||
std::string binary = value;
|
std::string binary = value;
|
||||||
|
|
@ -167,69 +174,69 @@ namespace hex::plugin::builtin {
|
||||||
return { result.value() };
|
return { result.value() };
|
||||||
else
|
else
|
||||||
return { };
|
return { };
|
||||||
}
|
})
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
ContentRegistry::DataInspector::add("hex.builtin.inspector.u8", sizeof(u8),
|
ContentRegistry::DataInspector::add("hex.builtin.inspector.u8", sizeof(u8),
|
||||||
drawString<u8>(integerToString<u8>),
|
drawString<u8>(integerToString<u8>),
|
||||||
stringToInteger<u8>
|
stringToInteger<u8>()
|
||||||
);
|
);
|
||||||
|
|
||||||
ContentRegistry::DataInspector::add("hex.builtin.inspector.i8", sizeof(i8),
|
ContentRegistry::DataInspector::add("hex.builtin.inspector.i8", sizeof(i8),
|
||||||
drawString<i8>(integerToString<i8>),
|
drawString<i8>(integerToString<i8>),
|
||||||
stringToInteger<i8>
|
stringToInteger<i8>()
|
||||||
);
|
);
|
||||||
|
|
||||||
ContentRegistry::DataInspector::add("hex.builtin.inspector.u16", sizeof(u16),
|
ContentRegistry::DataInspector::add("hex.builtin.inspector.u16", sizeof(u16),
|
||||||
drawString<u16>(integerToString<u16>),
|
drawString<u16>(integerToString<u16>),
|
||||||
stringToInteger<u16>
|
stringToInteger<u16>()
|
||||||
);
|
);
|
||||||
|
|
||||||
ContentRegistry::DataInspector::add("hex.builtin.inspector.i16", sizeof(i16),
|
ContentRegistry::DataInspector::add("hex.builtin.inspector.i16", sizeof(i16),
|
||||||
drawString<i16>(integerToString<i16>),
|
drawString<i16>(integerToString<i16>),
|
||||||
stringToInteger<i16>
|
stringToInteger<i16>()
|
||||||
);
|
);
|
||||||
|
|
||||||
ContentRegistry::DataInspector::add("hex.builtin.inspector.u24", 3,
|
ContentRegistry::DataInspector::add("hex.builtin.inspector.u24", 3,
|
||||||
drawString<u32, 3>(integerToString<u32, 3>),
|
drawString<u32, 3>(integerToString<u32, 3>),
|
||||||
stringToInteger<u32, 3>
|
stringToInteger<u32, 3>()
|
||||||
);
|
);
|
||||||
|
|
||||||
ContentRegistry::DataInspector::add("hex.builtin.inspector.i24", 3,
|
ContentRegistry::DataInspector::add("hex.builtin.inspector.i24", 3,
|
||||||
drawString<i32, 3>(integerToString<i32, 3>),
|
drawString<i32, 3>(integerToString<i32, 3>),
|
||||||
stringToInteger<i32, 3>
|
stringToInteger<i32, 3>()
|
||||||
);
|
);
|
||||||
|
|
||||||
ContentRegistry::DataInspector::add("hex.builtin.inspector.u32", sizeof(u32),
|
ContentRegistry::DataInspector::add("hex.builtin.inspector.u32", sizeof(u32),
|
||||||
drawString<u32>(integerToString<u32>),
|
drawString<u32>(integerToString<u32>),
|
||||||
stringToInteger<u32>
|
stringToInteger<u32>()
|
||||||
);
|
);
|
||||||
|
|
||||||
ContentRegistry::DataInspector::add("hex.builtin.inspector.i32", sizeof(i32),
|
ContentRegistry::DataInspector::add("hex.builtin.inspector.i32", sizeof(i32),
|
||||||
drawString<i32>(integerToString<i32>),
|
drawString<i32>(integerToString<i32>),
|
||||||
stringToInteger<i32>
|
stringToInteger<i32>()
|
||||||
);
|
);
|
||||||
|
|
||||||
ContentRegistry::DataInspector::add("hex.builtin.inspector.u48", 6,
|
ContentRegistry::DataInspector::add("hex.builtin.inspector.u48", 6,
|
||||||
drawString<u64, 6>(integerToString<u64, 6>),
|
drawString<u64, 6>(integerToString<u64, 6>),
|
||||||
stringToInteger<u64, 6>
|
stringToInteger<u64, 6>()
|
||||||
);
|
);
|
||||||
|
|
||||||
ContentRegistry::DataInspector::add("hex.builtin.inspector.i48", 6,
|
ContentRegistry::DataInspector::add("hex.builtin.inspector.i48", 6,
|
||||||
drawString<i64, 6>(integerToString<i64, 6>),
|
drawString<i64, 6>(integerToString<i64, 6>),
|
||||||
stringToInteger<i64, 6>
|
stringToInteger<i64, 6>()
|
||||||
);
|
);
|
||||||
|
|
||||||
ContentRegistry::DataInspector::add("hex.builtin.inspector.u64", sizeof(u64),
|
ContentRegistry::DataInspector::add("hex.builtin.inspector.u64", sizeof(u64),
|
||||||
drawString<u64>(integerToString<u64>),
|
drawString<u64>(integerToString<u64>),
|
||||||
stringToInteger<u64>
|
stringToInteger<u64>()
|
||||||
);
|
);
|
||||||
|
|
||||||
ContentRegistry::DataInspector::add("hex.builtin.inspector.i64", sizeof(i64),
|
ContentRegistry::DataInspector::add("hex.builtin.inspector.i64", sizeof(i64),
|
||||||
drawString<i64>(integerToString<i64>),
|
drawString<i64>(integerToString<i64>),
|
||||||
stringToInteger<i64>
|
stringToInteger<i64>()
|
||||||
);
|
);
|
||||||
|
|
||||||
ContentRegistry::DataInspector::add("hex.builtin.inspector.float16", sizeof(u16),
|
ContentRegistry::DataInspector::add("hex.builtin.inspector.float16", sizeof(u16),
|
||||||
|
|
@ -255,7 +262,7 @@ namespace hex::plugin::builtin {
|
||||||
auto value = fmt::format(fmt::runtime(formatString), hex::changeEndianness(result, endian));
|
auto value = fmt::format(fmt::runtime(formatString), hex::changeEndianness(result, endian));
|
||||||
return [value] { ImGui::TextUnformatted(value.c_str()); return value; };
|
return [value] { ImGui::TextUnformatted(value.c_str()); return value; };
|
||||||
},
|
},
|
||||||
stringToFloat<float>
|
stringToFloat<float>()
|
||||||
);
|
);
|
||||||
|
|
||||||
ContentRegistry::DataInspector::add("hex.builtin.inspector.double", sizeof(double),
|
ContentRegistry::DataInspector::add("hex.builtin.inspector.double", sizeof(double),
|
||||||
|
|
@ -268,7 +275,7 @@ namespace hex::plugin::builtin {
|
||||||
auto value = fmt::format(fmt::runtime(formatString), hex::changeEndianness(result, endian));
|
auto value = fmt::format(fmt::runtime(formatString), hex::changeEndianness(result, endian));
|
||||||
return [value] { ImGui::TextUnformatted(value.c_str()); return value; };
|
return [value] { ImGui::TextUnformatted(value.c_str()); return value; };
|
||||||
},
|
},
|
||||||
stringToFloat<double>
|
stringToFloat<double>()
|
||||||
);
|
);
|
||||||
|
|
||||||
ContentRegistry::DataInspector::add("hex.builtin.inspector.long_double", sizeof(long double),
|
ContentRegistry::DataInspector::add("hex.builtin.inspector.long_double", sizeof(long double),
|
||||||
|
|
@ -281,7 +288,7 @@ namespace hex::plugin::builtin {
|
||||||
auto value = fmt::format(fmt::runtime(formatString), hex::changeEndianness(result, endian));
|
auto value = fmt::format(fmt::runtime(formatString), hex::changeEndianness(result, endian));
|
||||||
return [value] { ImGui::TextUnformatted(value.c_str()); return value; };
|
return [value] { ImGui::TextUnformatted(value.c_str()); return value; };
|
||||||
},
|
},
|
||||||
stringToFloat<long double>
|
stringToFloat<long double>()
|
||||||
);
|
);
|
||||||
|
|
||||||
ContentRegistry::DataInspector::add("hex.builtin.inspector.bfloat16", sizeof(u16),
|
ContentRegistry::DataInspector::add("hex.builtin.inspector.bfloat16", sizeof(u16),
|
||||||
|
|
@ -359,11 +366,11 @@ namespace hex::plugin::builtin {
|
||||||
|
|
||||||
return [value] { ImGui::TextUnformatted(value.c_str()); return value; };
|
return [value] { ImGui::TextUnformatted(value.c_str()); return value; };
|
||||||
},
|
},
|
||||||
[](const std::string &value, std::endian endian) -> std::vector<u8> {
|
ContentRegistry::DataInspector::EditWidget::TextInput([](const std::string &value, std::endian endian) -> std::vector<u8> {
|
||||||
std::ignore = endian;
|
std::ignore = endian;
|
||||||
|
|
||||||
return hex::crypt::encodeSleb128(wolv::util::from_chars<i64>(value).value_or(0));
|
return hex::crypt::encodeSleb128(wolv::util::from_chars<i64>(value).value_or(0));
|
||||||
}
|
})
|
||||||
);
|
);
|
||||||
|
|
||||||
ContentRegistry::DataInspector::add("hex.builtin.inspector.uleb128", 1, (sizeof(u128) * 8 / 7) + 1,
|
ContentRegistry::DataInspector::add("hex.builtin.inspector.uleb128", 1, (sizeof(u128) * 8 / 7) + 1,
|
||||||
|
|
@ -376,11 +383,11 @@ namespace hex::plugin::builtin {
|
||||||
|
|
||||||
return [value] { ImGui::TextUnformatted(value.c_str()); return value; };
|
return [value] { ImGui::TextUnformatted(value.c_str()); return value; };
|
||||||
},
|
},
|
||||||
[](const std::string &value, std::endian endian) -> std::vector<u8> {
|
ContentRegistry::DataInspector::EditWidget::TextInput([](const std::string &value, std::endian endian) -> std::vector<u8> {
|
||||||
std::ignore = endian;
|
std::ignore = endian;
|
||||||
|
|
||||||
return hex::crypt::encodeUleb128(wolv::util::from_chars<u64>(value).value_or(0));
|
return hex::crypt::encodeUleb128(wolv::util::from_chars<u64>(value).value_or(0));
|
||||||
}
|
})
|
||||||
);
|
);
|
||||||
|
|
||||||
ContentRegistry::DataInspector::add("hex.builtin.inspector.bool", sizeof(bool),
|
ContentRegistry::DataInspector::add("hex.builtin.inspector.bool", sizeof(bool),
|
||||||
|
|
@ -411,13 +418,13 @@ namespace hex::plugin::builtin {
|
||||||
auto value = makePrintable(*reinterpret_cast<char8_t *>(buffer.data()));
|
auto value = makePrintable(*reinterpret_cast<char8_t *>(buffer.data()));
|
||||||
return [value] { ImGuiExt::TextFormatted("'{0}'", value.c_str()); return value; };
|
return [value] { ImGuiExt::TextFormatted("'{0}'", value.c_str()); return value; };
|
||||||
},
|
},
|
||||||
[](const std::string &value, std::endian endian) -> std::vector<u8> {
|
ContentRegistry::DataInspector::EditWidget::TextInput([](const std::string &value, std::endian endian) -> std::vector<u8> {
|
||||||
std::ignore = endian;
|
std::ignore = endian;
|
||||||
|
|
||||||
if (value.length() > 1) return { };
|
if (value.length() > 1) return { };
|
||||||
|
|
||||||
return { u8(value[0]) };
|
return { u8(value[0]) };
|
||||||
}
|
})
|
||||||
);
|
);
|
||||||
|
|
||||||
ContentRegistry::DataInspector::add("hex.builtin.inspector.wide", sizeof(wchar_t),
|
ContentRegistry::DataInspector::add("hex.builtin.inspector.wide", sizeof(wchar_t),
|
||||||
|
|
@ -432,7 +439,7 @@ namespace hex::plugin::builtin {
|
||||||
auto value = fmt::format("{0}", c <= 255 ? makePrintable(c) : wolv::util::wstringToUtf8(std::wstring(&c, 1)).value_or("???"));
|
auto value = fmt::format("{0}", c <= 255 ? makePrintable(c) : wolv::util::wstringToUtf8(std::wstring(&c, 1)).value_or("???"));
|
||||||
return [value] { ImGuiExt::TextFormatted("L'{0}'", value.c_str()); return value; };
|
return [value] { ImGuiExt::TextFormatted("L'{0}'", value.c_str()); return value; };
|
||||||
},
|
},
|
||||||
[](const std::string &value, std::endian endian) -> std::vector<u8> {
|
ContentRegistry::DataInspector::EditWidget::TextInput([](const std::string &value, std::endian endian) -> std::vector<u8> {
|
||||||
std::vector<u8> bytes;
|
std::vector<u8> bytes;
|
||||||
auto wideString = wolv::util::utf8ToWstring(value);
|
auto wideString = wolv::util::utf8ToWstring(value);
|
||||||
if (!wideString.has_value())
|
if (!wideString.has_value())
|
||||||
|
|
@ -445,7 +452,7 @@ namespace hex::plugin::builtin {
|
||||||
std::reverse(bytes.begin(), bytes.end());
|
std::reverse(bytes.begin(), bytes.end());
|
||||||
|
|
||||||
return bytes;
|
return bytes;
|
||||||
}
|
})
|
||||||
);
|
);
|
||||||
|
|
||||||
ContentRegistry::DataInspector::add("hex.builtin.inspector.char16", sizeof(char16_t),
|
ContentRegistry::DataInspector::add("hex.builtin.inspector.char16", sizeof(char16_t),
|
||||||
|
|
@ -460,7 +467,7 @@ namespace hex::plugin::builtin {
|
||||||
auto value = fmt::format("{0}", c <= 255 ? makePrintable(c) : wolv::util::utf16ToUtf8(std::u16string(&c, 1)).value_or("???"));
|
auto value = fmt::format("{0}", c <= 255 ? makePrintable(c) : wolv::util::utf16ToUtf8(std::u16string(&c, 1)).value_or("???"));
|
||||||
return [value] { ImGuiExt::TextFormatted("u'{0}'", value.c_str()); return value; };
|
return [value] { ImGuiExt::TextFormatted("u'{0}'", value.c_str()); return value; };
|
||||||
},
|
},
|
||||||
[](const std::string &value, std::endian endian) -> std::vector<u8> {
|
ContentRegistry::DataInspector::EditWidget::TextInput([](const std::string &value, std::endian endian) -> std::vector<u8> {
|
||||||
std::vector<u8> bytes;
|
std::vector<u8> bytes;
|
||||||
auto wideString = wolv::util::utf8ToUtf16(value);
|
auto wideString = wolv::util::utf8ToUtf16(value);
|
||||||
if (!wideString.has_value())
|
if (!wideString.has_value())
|
||||||
|
|
@ -473,7 +480,7 @@ namespace hex::plugin::builtin {
|
||||||
std::reverse(bytes.begin(), bytes.end());
|
std::reverse(bytes.begin(), bytes.end());
|
||||||
|
|
||||||
return bytes;
|
return bytes;
|
||||||
}
|
})
|
||||||
);
|
);
|
||||||
|
|
||||||
ContentRegistry::DataInspector::add("hex.builtin.inspector.char32", sizeof(char32_t),
|
ContentRegistry::DataInspector::add("hex.builtin.inspector.char32", sizeof(char32_t),
|
||||||
|
|
@ -488,7 +495,7 @@ namespace hex::plugin::builtin {
|
||||||
auto value = fmt::format("{0}", c <= 255 ? makePrintable(c) : wolv::util::utf32ToUtf8(std::u32string(&c, 1)).value_or("???"));
|
auto value = fmt::format("{0}", c <= 255 ? makePrintable(c) : wolv::util::utf32ToUtf8(std::u32string(&c, 1)).value_or("???"));
|
||||||
return [value] { ImGuiExt::TextFormatted("U'{0}'", value.c_str()); return value; };
|
return [value] { ImGuiExt::TextFormatted("U'{0}'", value.c_str()); return value; };
|
||||||
},
|
},
|
||||||
[](const std::string &value, std::endian endian) -> std::vector<u8> {
|
ContentRegistry::DataInspector::EditWidget::TextInput([](const std::string &value, std::endian endian) -> std::vector<u8> {
|
||||||
std::vector<u8> bytes;
|
std::vector<u8> bytes;
|
||||||
auto wideString = wolv::util::utf8ToUtf32(value);
|
auto wideString = wolv::util::utf8ToUtf32(value);
|
||||||
if (!wideString.has_value())
|
if (!wideString.has_value())
|
||||||
|
|
@ -501,7 +508,7 @@ namespace hex::plugin::builtin {
|
||||||
std::reverse(bytes.begin(), bytes.end());
|
std::reverse(bytes.begin(), bytes.end());
|
||||||
|
|
||||||
return bytes;
|
return bytes;
|
||||||
}
|
})
|
||||||
);
|
);
|
||||||
|
|
||||||
ContentRegistry::DataInspector::add("hex.builtin.inspector.utf8", sizeof(char8_t) * 4,
|
ContentRegistry::DataInspector::add("hex.builtin.inspector.utf8", sizeof(char8_t) * 4,
|
||||||
|
|
@ -551,11 +558,11 @@ namespace hex::plugin::builtin {
|
||||||
|
|
||||||
return [value, copyValue] { ImGuiExt::TextFormatted("\"{0}\"", value.c_str()); return copyValue; };
|
return [value, copyValue] { ImGuiExt::TextFormatted("\"{0}\"", value.c_str()); return copyValue; };
|
||||||
},
|
},
|
||||||
[](const std::string &value, std::endian endian) -> std::vector<u8> {
|
ContentRegistry::DataInspector::EditWidget::TextInput([](const std::string &value, std::endian endian) -> std::vector<u8> {
|
||||||
std::ignore = endian;
|
std::ignore = endian;
|
||||||
|
|
||||||
return hex::decodeByteString(value);
|
return hex::decodeByteString(value);
|
||||||
}
|
})
|
||||||
);
|
);
|
||||||
|
|
||||||
ContentRegistry::DataInspector::add("hex.builtin.inspector.wstring", sizeof(wchar_t),
|
ContentRegistry::DataInspector::add("hex.builtin.inspector.wstring", sizeof(wchar_t),
|
||||||
|
|
@ -588,7 +595,7 @@ namespace hex::plugin::builtin {
|
||||||
|
|
||||||
return [value, copyValue] { ImGuiExt::TextFormatted("L\"{0}\"", value.c_str()); return copyValue; };
|
return [value, copyValue] { ImGuiExt::TextFormatted("L\"{0}\"", value.c_str()); return copyValue; };
|
||||||
},
|
},
|
||||||
[](const std::string &value, std::endian endian) -> std::vector<u8> {
|
ContentRegistry::DataInspector::EditWidget::TextInput([](const std::string &value, std::endian endian) -> std::vector<u8> {
|
||||||
auto utf8 = hex::decodeByteString(value);
|
auto utf8 = hex::decodeByteString(value);
|
||||||
auto wstring = wolv::util::utf8ToWstring({ utf8.begin(), utf8.end() });
|
auto wstring = wolv::util::utf8ToWstring({ utf8.begin(), utf8.end() });
|
||||||
if (!wstring.has_value())
|
if (!wstring.has_value())
|
||||||
|
|
@ -601,7 +608,7 @@ namespace hex::plugin::builtin {
|
||||||
std::vector<u8> bytes(wstring->size() * sizeof(wchar_t), 0x00);
|
std::vector<u8> bytes(wstring->size() * sizeof(wchar_t), 0x00);
|
||||||
std::memcpy(bytes.data(), wstring->data(), bytes.size());
|
std::memcpy(bytes.data(), wstring->data(), bytes.size());
|
||||||
return bytes;
|
return bytes;
|
||||||
}
|
})
|
||||||
);
|
);
|
||||||
|
|
||||||
ContentRegistry::DataInspector::add("hex.builtin.inspector.string16", sizeof(char16_t),
|
ContentRegistry::DataInspector::add("hex.builtin.inspector.string16", sizeof(char16_t),
|
||||||
|
|
@ -634,7 +641,7 @@ namespace hex::plugin::builtin {
|
||||||
|
|
||||||
return [value, copyValue] { ImGuiExt::TextFormatted("u\"{0}\"", value.c_str()); return copyValue; };
|
return [value, copyValue] { ImGuiExt::TextFormatted("u\"{0}\"", value.c_str()); return copyValue; };
|
||||||
},
|
},
|
||||||
[](const std::string &value, std::endian endian) -> std::vector<u8> {
|
ContentRegistry::DataInspector::EditWidget::TextInput([](const std::string &value, std::endian endian) -> std::vector<u8> {
|
||||||
auto utf8 = hex::decodeByteString(value);
|
auto utf8 = hex::decodeByteString(value);
|
||||||
auto utf16 = wolv::util::utf8ToUtf16({ utf8.begin(), utf8.end() });
|
auto utf16 = wolv::util::utf8ToUtf16({ utf8.begin(), utf8.end() });
|
||||||
if (!utf16.has_value())
|
if (!utf16.has_value())
|
||||||
|
|
@ -647,7 +654,7 @@ namespace hex::plugin::builtin {
|
||||||
std::vector<u8> bytes(utf16->size() * sizeof(char16_t), 0x00);
|
std::vector<u8> bytes(utf16->size() * sizeof(char16_t), 0x00);
|
||||||
std::memcpy(bytes.data(), utf16->data(), bytes.size());
|
std::memcpy(bytes.data(), utf16->data(), bytes.size());
|
||||||
return bytes;
|
return bytes;
|
||||||
}
|
})
|
||||||
);
|
);
|
||||||
|
|
||||||
ContentRegistry::DataInspector::add("hex.builtin.inspector.string32", sizeof(char32_t),
|
ContentRegistry::DataInspector::add("hex.builtin.inspector.string32", sizeof(char32_t),
|
||||||
|
|
@ -680,7 +687,7 @@ namespace hex::plugin::builtin {
|
||||||
|
|
||||||
return [value, copyValue] { ImGuiExt::TextFormatted("U\"{0}\"", value.c_str()); return copyValue; };
|
return [value, copyValue] { ImGuiExt::TextFormatted("U\"{0}\"", value.c_str()); return copyValue; };
|
||||||
},
|
},
|
||||||
[](const std::string &value, std::endian endian) -> std::vector<u8> {
|
ContentRegistry::DataInspector::EditWidget::TextInput([](const std::string &value, std::endian endian) -> std::vector<u8> {
|
||||||
auto utf8 = hex::decodeByteString(value);
|
auto utf8 = hex::decodeByteString(value);
|
||||||
auto utf32 = wolv::util::utf8ToUtf32({ utf8.begin(), utf8.end() });
|
auto utf32 = wolv::util::utf8ToUtf32({ utf8.begin(), utf8.end() });
|
||||||
if (!utf32.has_value())
|
if (!utf32.has_value())
|
||||||
|
|
@ -693,7 +700,7 @@ namespace hex::plugin::builtin {
|
||||||
std::vector<u8> bytes(utf32->size() * sizeof(char32_t), 0x00);
|
std::vector<u8> bytes(utf32->size() * sizeof(char32_t), 0x00);
|
||||||
std::memcpy(bytes.data(), utf32->data(), bytes.size());
|
std::memcpy(bytes.data(), utf32->data(), bytes.size());
|
||||||
return bytes;
|
return bytes;
|
||||||
}
|
})
|
||||||
);
|
);
|
||||||
|
|
||||||
ContentRegistry::DataInspector::add("hex.builtin.inspector.custom_encoding", 1, [encodingFile = EncodingFile()](const std::vector<u8> &, std::endian, Style) mutable {
|
ContentRegistry::DataInspector::add("hex.builtin.inspector.custom_encoding", 1, [encodingFile = EncodingFile()](const std::vector<u8> &, std::endian, Style) mutable {
|
||||||
|
|
|
||||||
|
|
@ -198,8 +198,7 @@ namespace hex::plugin::builtin {
|
||||||
// Set up the editing function if a write formatter is available
|
// Set up the editing function if a write formatter is available
|
||||||
std::optional<ContentRegistry::DataInspector::impl::EditingFunction> editingFunction;
|
std::optional<ContentRegistry::DataInspector::impl::EditingFunction> editingFunction;
|
||||||
if (!pattern->getWriteFormatterFunction().empty()) {
|
if (!pattern->getWriteFormatterFunction().empty()) {
|
||||||
editingFunction = [&pattern](const std::string &value,
|
editingFunction = ContentRegistry::DataInspector::EditWidget::TextInput([&pattern](const std::string &value, std::endian) -> std::vector<u8> {
|
||||||
std::endian) -> std::vector<u8> {
|
|
||||||
try {
|
try {
|
||||||
pattern->setValue(value);
|
pattern->setValue(value);
|
||||||
} catch (const pl::core::err::EvaluatorError::Exception &error) {
|
} catch (const pl::core::err::EvaluatorError::Exception &error) {
|
||||||
|
|
@ -208,7 +207,7 @@ namespace hex::plugin::builtin {
|
||||||
}
|
}
|
||||||
|
|
||||||
return {};
|
return {};
|
||||||
};
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
|
|
@ -441,7 +440,7 @@ namespace hex::plugin::builtin {
|
||||||
ImGui::SameLine();
|
ImGui::SameLine();
|
||||||
|
|
||||||
// Handle copying the value to the clipboard when clicking the row
|
// Handle copying the value to the clipboard when clicking the row
|
||||||
if (ImGui::Selectable("##InspectorLine", m_selectedEntryName == entry.unlocalizedName, ImGuiSelectableFlags_SpanAllColumns | ImGuiSelectableFlags_AllowOverlap)) {
|
if (ImGui::Selectable("##InspectorLine", m_selectedEntryName == entry.unlocalizedName, ImGuiSelectableFlags_SpanAllColumns | ImGuiSelectableFlags_AllowOverlap | ImGuiSelectableFlags_AllowDoubleClick)) {
|
||||||
m_selectedEntryName = entry.unlocalizedName;
|
m_selectedEntryName = entry.unlocalizedName;
|
||||||
if (auto selection = ImHexApi::HexEditor::getSelection(); selection.has_value()) {
|
if (auto selection = ImHexApi::HexEditor::getSelection(); selection.has_value()) {
|
||||||
ImHexApi::HexEditor::setSelection(Region { selection->getStartAddress(), entry.requiredSize });
|
ImHexApi::HexEditor::setSelection(Region { selection->getStartAddress(), entry.requiredSize });
|
||||||
|
|
@ -476,10 +475,7 @@ namespace hex::plugin::builtin {
|
||||||
}
|
}
|
||||||
ImGui::EndPopup();
|
ImGui::EndPopup();
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (ImGui::IsKeyPressed(ImGuiKey_Escape)) {
|
if (ImGui::IsKeyPressed(ImGuiKey_Escape)) {
|
||||||
entry.editing = false;
|
entry.editing = false;
|
||||||
}
|
}
|
||||||
|
|
@ -489,18 +485,14 @@ namespace hex::plugin::builtin {
|
||||||
ImGui::SetNextItemWidth(-1);
|
ImGui::SetNextItemWidth(-1);
|
||||||
ImGui::SetKeyboardFocusHere();
|
ImGui::SetKeyboardFocusHere();
|
||||||
|
|
||||||
// Draw input text box
|
// Draw editing widget and capture edited value
|
||||||
if (ImGui::InputText("##InspectorLineEditing", m_editingValue,
|
auto bytes = (*entry.editingFunction)(m_editingValue, m_endian, {});
|
||||||
ImGuiInputTextFlags_EnterReturnsTrue |
|
if (bytes.has_value()) {
|
||||||
ImGuiInputTextFlags_AutoSelectAll)) {
|
|
||||||
// Turn the entered value into bytes
|
|
||||||
auto bytes = entry.editingFunction.value()(m_editingValue, m_endian);
|
|
||||||
|
|
||||||
if (m_invert)
|
if (m_invert)
|
||||||
std::ranges::transform(bytes, bytes.begin(), [](auto byte) { return byte ^ 0xFF; });
|
std::ranges::transform(*bytes, bytes->begin(), [](auto byte) { return byte ^ 0xFF; });
|
||||||
|
|
||||||
// Write those bytes to the selected provider at the current address
|
// Write those bytes to the selected provider at the current address
|
||||||
m_selectedProvider->write(m_startAddress, bytes.data(), bytes.size());
|
m_selectedProvider->write(m_startAddress, bytes->data(), bytes->size());
|
||||||
|
|
||||||
// Disable editing mode
|
// Disable editing mode
|
||||||
m_editingValue.clear();
|
m_editingValue.clear();
|
||||||
|
|
@ -519,6 +511,8 @@ namespace hex::plugin::builtin {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
void ViewDataInspector::drawEndianSetting() {
|
void ViewDataInspector::drawEndianSetting() {
|
||||||
if (ui::endiannessSlider(m_endian)) {
|
if (ui::endiannessSlider(m_endian)) {
|
||||||
m_shouldInvalidate = true;
|
m_shouldInvalidate = true;
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue