feat: Added basic UI for the new pl section system
This commit is contained in:
parent
901b8f0424
commit
5bbc2fd94c
2
lib/external/pattern_language
vendored
2
lib/external/pattern_language
vendored
@ -1 +1 @@
|
||||
Subproject commit 22cfecfbffbc6dee4879b9f9cfaedc943aca5bd6
|
||||
Subproject commit 2fc96aedca0f665957eec878d75403eff7de5a91
|
@ -692,6 +692,7 @@ namespace hex {
|
||||
style.WindowRounding = 0.0F;
|
||||
|
||||
io.ConfigFlags |= ImGuiConfigFlags_DockingEnable | ImGuiConfigFlags_NavEnableKeyboard;
|
||||
io.ConfigWindowsMoveFromTitleBarOnly = true;
|
||||
|
||||
if (glfwGetPrimaryMonitor() != nullptr) {
|
||||
auto sessionType = hex::getEnvironmentVariable("XDG_SESSION_TYPE");
|
||||
|
@ -21,22 +21,27 @@ namespace hex {
|
||||
|
||||
class HexEditor {
|
||||
public:
|
||||
HexEditor();
|
||||
~HexEditor();
|
||||
HexEditor(std::optional<u64> **selectionStart, std::optional<u64> **selectionEnd, float **scrollPosition);
|
||||
void draw();
|
||||
void draw(prv::Provider *provider, float height = ImGui::GetContentRegionAvail().y);
|
||||
|
||||
private:
|
||||
enum class CellType { None, Hex, ASCII };
|
||||
|
||||
void drawCell(u64 address, u8 *data, size_t size, bool hovered, CellType cellType);
|
||||
void drawCell(prv::Provider *provider, u64 address, u8 *data, size_t size, bool hovered, CellType cellType);
|
||||
void drawSelectionFrame(u32 x, u32 y, u64 byteAddress, u16 bytesPerCell, const ImVec2 &cellPos, const ImVec2 &cellSize) const;
|
||||
void drawEditor(const ImVec2 &size);
|
||||
void drawFooter(const ImVec2 &size);
|
||||
void drawEditor(prv::Provider *provider, const ImVec2 &size);
|
||||
void drawFooter(prv::Provider *provider, const ImVec2 &size);
|
||||
void drawTooltip(u64 address, const u8 *data, size_t size);
|
||||
|
||||
void handleSelection(u64 address, u32 bytesPerCell, const u8 *data, bool cellHovered);
|
||||
std::optional<color_t> applySelectionColor(u64 byteAddress, std::optional<color_t> color);
|
||||
|
||||
public:
|
||||
void setSelectionUnchecked(std::optional<u64> start, std::optional<u64> end) {
|
||||
this->m_selectionStart = start;
|
||||
this->m_selectionEnd = end;
|
||||
}
|
||||
void setSelection(const Region ®ion) { this->setSelection(region.getStartAddress(), region.getEndAddress()); }
|
||||
void setSelection(u128 start, u128 end) {
|
||||
if (!ImHexApi::Provider::isValid())
|
||||
@ -46,10 +51,10 @@ namespace hex {
|
||||
|
||||
const size_t maxAddress = provider->getActualSize() + provider->getBaseAddress() - 1;
|
||||
|
||||
this->m_selectionChanged = **this->m_selectionStart != start || **this->m_selectionEnd != end;
|
||||
this->m_selectionChanged = this->m_selectionStart != start || this->m_selectionEnd != end;
|
||||
|
||||
**this->m_selectionStart = std::clamp<u128>(start, 0, maxAddress);
|
||||
**this->m_selectionEnd = std::clamp<u128>(end, 0, maxAddress);
|
||||
this->m_selectionStart = std::clamp<u128>(start, 0, maxAddress);
|
||||
this->m_selectionEnd = std::clamp<u128>(end, 0, maxAddress);
|
||||
|
||||
if (this->m_selectionChanged) {
|
||||
EventManager::post<EventRegionSelected>(this->getSelection());
|
||||
@ -61,15 +66,15 @@ namespace hex {
|
||||
if (!isSelectionValid())
|
||||
return Region::Invalid();
|
||||
|
||||
const auto start = std::min((*this->m_selectionStart)->value(), (*this->m_selectionEnd)->value());
|
||||
const auto end = std::max((*this->m_selectionStart)->value(), (*this->m_selectionEnd)->value());
|
||||
const auto start = std::min(this->m_selectionStart.value(), this->m_selectionEnd.value());
|
||||
const auto end = std::max(this->m_selectionStart.value(), this->m_selectionEnd.value());
|
||||
const size_t size = end - start + 1;
|
||||
|
||||
return { start, size };
|
||||
}
|
||||
|
||||
[[nodiscard]] bool isSelectionValid() const {
|
||||
return (*this->m_selectionStart)->has_value() && (*this->m_selectionEnd)->has_value();
|
||||
return this->m_selectionStart.has_value() && this->m_selectionEnd.has_value();
|
||||
}
|
||||
|
||||
void jumpToSelection(bool center = true) {
|
||||
@ -135,10 +140,30 @@ namespace hex {
|
||||
this->m_shouldUpdateScrollPosition = true;
|
||||
}
|
||||
|
||||
void setForegroundHighlightCallback(const std::function<std::optional<color_t>(u64, const u8 *, size_t)> &callback) {
|
||||
this->m_foregroundColorCallback = callback;
|
||||
}
|
||||
|
||||
void setBackgroundHighlightCallback(const std::function<std::optional<color_t>(u64, const u8 *, size_t)> &callback) {
|
||||
this->m_backgroundColorCallback = callback;
|
||||
}
|
||||
|
||||
void setTooltipCallback(const std::function<void(u64, const u8 *, size_t)> &callback) {
|
||||
this->m_tooltipCallback = callback;
|
||||
}
|
||||
|
||||
[[nodiscard]] float getScrollPosition() const {
|
||||
return this->m_scrollPosition;
|
||||
}
|
||||
|
||||
void setScrollPosition(float scrollPosition) {
|
||||
this->m_scrollPosition = scrollPosition;
|
||||
}
|
||||
|
||||
private:
|
||||
std::optional<u64> **m_selectionStart;
|
||||
std::optional<u64> **m_selectionEnd;
|
||||
float **m_scrollPosition;
|
||||
std::optional<u64> m_selectionStart;
|
||||
std::optional<u64> m_selectionEnd;
|
||||
float m_scrollPosition = 0;
|
||||
|
||||
u16 m_bytesPerRow = 16;
|
||||
ContentRegistry::HexEditor::DataVisualizer *m_currDataVisualizer;
|
||||
@ -169,6 +194,11 @@ namespace hex {
|
||||
u32 m_byteCellPadding = 0, m_characterCellPadding = 0;
|
||||
|
||||
std::optional<EncodingFile> m_currCustomEncoding;
|
||||
|
||||
static std::optional<color_t> defaultColorCallback(u64, const u8 *, size_t) { return std::nullopt; }
|
||||
static void defaultTooltipCallback(u64, const u8 *, size_t) { }
|
||||
std::function<std::optional<color_t>(u64, const u8 *, size_t)> m_foregroundColorCallback = defaultColorCallback, m_backgroundColorCallback = defaultColorCallback;
|
||||
std::function<void(u64, const u8 *, size_t)> m_tooltipCallback = defaultTooltipCallback;
|
||||
};
|
||||
|
||||
}
|
@ -53,6 +53,7 @@ namespace hex::plugin::builtin {
|
||||
std::vector<std::pair<pl::core::LogConsole::Level, std::string>> lastEvaluationLog;
|
||||
std::map<std::string, pl::core::Token::Literal> lastEvaluationOutVars;
|
||||
std::map<std::string, PatternVariable> patternVariables;
|
||||
std::map<u64, pl::api::Section> sections;
|
||||
|
||||
std::list<EnvVar> envVarEntries;
|
||||
} patternLanguage;
|
||||
|
@ -11,7 +11,7 @@
|
||||
#include <windows.h>
|
||||
#endif
|
||||
|
||||
namespace hex::plugin::builtin::prv {
|
||||
namespace hex::plugin::builtin {
|
||||
|
||||
class DiskProvider : public hex::prv::Provider {
|
||||
public:
|
||||
|
@ -15,7 +15,7 @@
|
||||
#include <sys/fcntl.h>
|
||||
#endif
|
||||
|
||||
namespace hex::plugin::builtin::prv {
|
||||
namespace hex::plugin::builtin {
|
||||
|
||||
class FileProvider : public hex::prv::Provider {
|
||||
public:
|
||||
|
@ -8,7 +8,7 @@
|
||||
#include <string_view>
|
||||
#include <thread>
|
||||
|
||||
namespace hex::plugin::builtin::prv {
|
||||
namespace hex::plugin::builtin {
|
||||
|
||||
class GDBProvider : public hex::prv::Provider {
|
||||
public:
|
||||
|
@ -4,7 +4,7 @@
|
||||
|
||||
#include <IntervalTree.h>
|
||||
|
||||
namespace hex::plugin::builtin::prv {
|
||||
namespace hex::plugin::builtin {
|
||||
|
||||
class IntelHexProvider : public hex::prv::Provider {
|
||||
public:
|
||||
|
@ -3,7 +3,7 @@
|
||||
#include <hex/providers/provider.hpp>
|
||||
#include <hex/api/localization.hpp>
|
||||
|
||||
namespace hex::plugin::builtin::prv {
|
||||
namespace hex::plugin::builtin {
|
||||
|
||||
class MemoryFileProvider : public hex::prv::Provider {
|
||||
public:
|
||||
|
@ -2,7 +2,7 @@
|
||||
|
||||
#include <content/providers/intel_hex_provider.hpp>
|
||||
|
||||
namespace hex::plugin::builtin::prv {
|
||||
namespace hex::plugin::builtin {
|
||||
|
||||
class MotorolaSRECProvider : public IntelHexProvider {
|
||||
public:
|
||||
|
@ -2,7 +2,7 @@
|
||||
|
||||
#include <hex/providers/provider.hpp>
|
||||
|
||||
namespace hex::plugin::builtin::prv {
|
||||
namespace hex::plugin::builtin {
|
||||
|
||||
class NullProvider : public hex::prv::Provider {
|
||||
public:
|
||||
|
@ -15,8 +15,8 @@ namespace hex::plugin::builtin {
|
||||
void drawContent() override;
|
||||
|
||||
private:
|
||||
static bool importBookmarks(prv::Provider *provider, const nlohmann::json &json);
|
||||
static bool exportBookmarks(prv::Provider *provider, nlohmann::json &json);
|
||||
static bool importBookmarks(hex::prv::Provider *provider, const nlohmann::json &json);
|
||||
static bool exportBookmarks(hex::prv::Provider *provider, nlohmann::json &json);
|
||||
|
||||
void registerMenuItems();
|
||||
private:
|
||||
|
@ -14,7 +14,7 @@ namespace hex::plugin::builtin {
|
||||
class ViewHexEditor : public View {
|
||||
public:
|
||||
ViewHexEditor();
|
||||
~ViewHexEditor();
|
||||
~ViewHexEditor() override;
|
||||
|
||||
void drawContent() override;
|
||||
|
||||
@ -44,23 +44,23 @@ namespace hex::plugin::builtin {
|
||||
}
|
||||
|
||||
bool isSelectionValid() {
|
||||
return this->m_hexEditor->isSelectionValid();
|
||||
return this->m_hexEditor.isSelectionValid();
|
||||
}
|
||||
|
||||
Region getSelection() {
|
||||
return this->m_hexEditor->getSelection();
|
||||
return this->m_hexEditor.getSelection();
|
||||
}
|
||||
|
||||
void setSelection(const Region ®ion) {
|
||||
this->m_hexEditor->setSelection(region);
|
||||
this->m_hexEditor.setSelection(region);
|
||||
}
|
||||
|
||||
void setSelection(u128 start, u128 end) {
|
||||
this->m_hexEditor->setSelection(start, end);
|
||||
this->m_hexEditor.setSelection(start, end);
|
||||
}
|
||||
|
||||
void jumpToSelection() {
|
||||
this->m_hexEditor->jumpToSelection();
|
||||
this->m_hexEditor.jumpToSelection();
|
||||
}
|
||||
|
||||
private:
|
||||
@ -70,13 +70,10 @@ namespace hex::plugin::builtin {
|
||||
void registerEvents();
|
||||
void registerMenuItems();
|
||||
|
||||
std::unique_ptr<HexEditor> m_hexEditor;
|
||||
HexEditor m_hexEditor;
|
||||
|
||||
bool m_shouldOpenPopup = false;
|
||||
std::unique_ptr<Popup> m_currPopup;
|
||||
|
||||
std::optional<u64> *m_selectionStart, *m_selectionEnd;
|
||||
float *m_scrollPosition;
|
||||
};
|
||||
|
||||
}
|
@ -4,6 +4,7 @@
|
||||
#include <hex/ui/view.hpp>
|
||||
|
||||
#include <content/helpers/pattern_drawer.hpp>
|
||||
#include <hex/providers/provider.hpp>
|
||||
|
||||
#include <vector>
|
||||
#include <tuple>
|
||||
@ -18,7 +19,7 @@ namespace hex::plugin::builtin {
|
||||
void drawContent() override;
|
||||
|
||||
private:
|
||||
std::map<prv::Provider *, std::vector<pl::ptrn::Pattern*>> m_sortedPatterns;
|
||||
std::map<hex::prv::Provider *, std::vector<pl::ptrn::Pattern*>> m_sortedPatterns;
|
||||
hex::PatternDrawer m_patternDrawer;
|
||||
};
|
||||
|
||||
|
@ -4,7 +4,10 @@
|
||||
#include <pl/pattern_language.hpp>
|
||||
#include <pl/core/errors/error.hpp>
|
||||
#include <hex/providers/provider.hpp>
|
||||
|
||||
#include <content/helpers/provider_extra_data.hpp>
|
||||
#include <content/helpers/hex_editor.hpp>
|
||||
#include <content/providers/memory_file_provider.hpp>
|
||||
|
||||
#include <cstring>
|
||||
#include <filesystem>
|
||||
@ -60,10 +63,14 @@ namespace hex::plugin::builtin {
|
||||
bool m_syncPatternSourceCode = false;
|
||||
bool m_autoLoadPatterns = true;
|
||||
|
||||
std::unique_ptr<MemoryFileProvider> m_sectionProvider = nullptr;
|
||||
HexEditor m_hexEditor;
|
||||
|
||||
private:
|
||||
void drawConsole(ImVec2 size, const std::vector<std::pair<pl::core::LogConsole::Level, std::string>> &console);
|
||||
void drawEnvVars(ImVec2 size, std::list<PlData::EnvVar> &envVars);
|
||||
void drawVariableSettings(ImVec2 size, std::map<std::string, PlData::PatternVariable> &patternVariables);
|
||||
void drawSectionSelector(ImVec2 size, std::map<u64, pl::api::Section> §ions);
|
||||
|
||||
void drawPatternTooltip(pl::ptrn::Pattern *pattern);
|
||||
|
||||
|
@ -19,7 +19,7 @@ namespace hex::plugin::builtin {
|
||||
|
||||
static void openFile(const std::fs::path &path) {
|
||||
auto provider = ImHexApi::Provider::createProvider("hex.builtin.provider.file", true);
|
||||
if (auto *fileProvider = dynamic_cast<prv::FileProvider*>(provider); fileProvider != nullptr) {
|
||||
if (auto *fileProvider = dynamic_cast<FileProvider*>(provider); fileProvider != nullptr) {
|
||||
fileProvider->setPath(path);
|
||||
if (fileProvider->open())
|
||||
EventManager::post<EventProviderOpened>(fileProvider);
|
||||
|
@ -70,8 +70,7 @@ namespace hex {
|
||||
|
||||
/* Hex Editor */
|
||||
|
||||
HexEditor::HexEditor(std::optional<u64> **selectionStart, std::optional<u64> **selectionEnd, float **scrollPosition)
|
||||
: m_selectionStart(selectionStart), m_selectionEnd(selectionEnd), m_scrollPosition(scrollPosition) {
|
||||
HexEditor::HexEditor() {
|
||||
this->m_currDataVisualizer = ContentRegistry::HexEditor::impl::getVisualizers()["hex.builtin.visualizer.hexadecimal.8bit"];
|
||||
|
||||
this->m_grayZeroHighlighter = ImHexApi::HexEditor::addForegroundHighlightingProvider([this](u64 address, const u8 *data, size_t size, bool hasColor) -> std::optional<color_t> {
|
||||
@ -174,42 +173,6 @@ namespace hex {
|
||||
return currColumn > 0 && (currColumn) < columnCount && ((currColumn) % 8) == 0;
|
||||
}
|
||||
|
||||
static std::optional<color_t> queryBackgroundColor(u64 address, const u8 *data, size_t size) {
|
||||
std::optional<color_t> result;
|
||||
for (const auto &[id, callback] : ImHexApi::HexEditor::impl::getBackgroundHighlightingFunctions()) {
|
||||
if (auto color = callback(address, data, size, result.has_value()); color.has_value())
|
||||
return color.value();
|
||||
}
|
||||
|
||||
if (result.has_value())
|
||||
return result;
|
||||
|
||||
for (const auto &[id, highlighting] : ImHexApi::HexEditor::impl::getBackgroundHighlights()) {
|
||||
if (highlighting.getRegion().overlaps({ address, size }))
|
||||
return highlighting.getColor();
|
||||
}
|
||||
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
static std::optional<color_t> queryForegroundColor(u64 address, const u8 *data, size_t size) {
|
||||
std::optional<color_t> result;
|
||||
for (const auto &[id, callback] : ImHexApi::HexEditor::impl::getForegroundHighlightingFunctions()) {
|
||||
if (auto color = callback(address, data, size, result.has_value()); color.has_value())
|
||||
result = color;
|
||||
}
|
||||
|
||||
if (result.has_value())
|
||||
return result;
|
||||
|
||||
for (const auto &[id, highlighting] : ImHexApi::HexEditor::impl::getForegroundHighlights()) {
|
||||
if (highlighting.getRegion().overlaps({ address, size }))
|
||||
return highlighting.getColor();
|
||||
}
|
||||
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
std::optional<color_t> HexEditor::applySelectionColor(u64 byteAddress, std::optional<color_t> color) {
|
||||
if (isSelectionValid()) {
|
||||
auto selection = getSelection();
|
||||
@ -234,13 +197,12 @@ namespace hex {
|
||||
ImColor color;
|
||||
};
|
||||
|
||||
static CustomEncodingData queryCustomEncodingData(const EncodingFile &encodingFile, u64 address) {
|
||||
static CustomEncodingData queryCustomEncodingData(prv::Provider *provider, const EncodingFile &encodingFile, u64 address) {
|
||||
const auto longestSequence = encodingFile.getLongestSequence();
|
||||
|
||||
if (longestSequence == 0)
|
||||
return { ".", 1, 0xFFFF8000 };
|
||||
|
||||
auto provider = ImHexApi::Provider::get();
|
||||
size_t size = std::min<size_t>(longestSequence, provider->getActualSize() - address);
|
||||
|
||||
std::vector<u8> buffer(size);
|
||||
@ -267,41 +229,17 @@ namespace hex {
|
||||
return ImGui::GetCursorScreenPos() - ImGui::GetStyle().CellPadding;
|
||||
}
|
||||
|
||||
static void drawTooltip(u64 address, const u8 *data, size_t size) {
|
||||
void HexEditor::drawTooltip(u64 address, const u8 *data, size_t size) {
|
||||
ImGui::PushStyleVar(ImGuiStyleVar_WindowPadding, scaled(ImVec2(5, 5)));
|
||||
|
||||
for (const auto &[id, callback] : ImHexApi::HexEditor::impl::getTooltipFunctions()) {
|
||||
callback(address, data, size);
|
||||
}
|
||||
|
||||
for (const auto &[id, tooltip] : ImHexApi::HexEditor::impl::getTooltips()) {
|
||||
if (tooltip.getRegion().overlaps({ address, size })) {
|
||||
ImGui::BeginTooltip();
|
||||
if (ImGui::BeginTable("##tooltips", 1, ImGuiTableFlags_NoHostExtendX | ImGuiTableFlags_RowBg | ImGuiTableFlags_NoClip)) {
|
||||
ImGui::TableNextRow();
|
||||
ImGui::TableNextColumn();
|
||||
|
||||
ImGui::ColorButton(tooltip.getValue().c_str(), ImColor(tooltip.getColor()));
|
||||
ImGui::SameLine(0, 10);
|
||||
ImGui::TextUnformatted(tooltip.getValue().c_str());
|
||||
|
||||
ImGui::PushStyleColor(ImGuiCol_TableRowBg, tooltip.getColor());
|
||||
ImGui::PushStyleColor(ImGuiCol_TableRowBgAlt, tooltip.getColor());
|
||||
ImGui::EndTable();
|
||||
ImGui::PopStyleColor(2);
|
||||
}
|
||||
ImGui::EndTooltip();
|
||||
}
|
||||
}
|
||||
this->m_tooltipCallback(address, data, size);
|
||||
|
||||
ImGui::PopStyleVar();
|
||||
}
|
||||
|
||||
void HexEditor::drawCell(u64 address, u8 *data, size_t size, bool hovered, CellType cellType) {
|
||||
void HexEditor::drawCell(prv::Provider *provider, u64 address, u8 *data, size_t size, bool hovered, CellType cellType) {
|
||||
static DataVisualizerAscii asciiVisualizer;
|
||||
|
||||
auto provider = ImHexApi::Provider::get();
|
||||
|
||||
if (this->m_shouldUpdateEditingValue) {
|
||||
this->m_shouldUpdateEditingValue = false;
|
||||
|
||||
@ -396,7 +334,7 @@ namespace hex {
|
||||
drawList->AddLine(cellPos + ImVec2(0, cellSize.y), cellPos + cellSize + ImVec2(1, 0), ImColor(SelectionFrameColor), 1.0F);
|
||||
}
|
||||
|
||||
void HexEditor::drawEditor(const ImVec2 &size) {
|
||||
void HexEditor::drawEditor(prv::Provider *provider, const ImVec2 &size) {
|
||||
const float SeparatorColumWidth = 6_scaled;
|
||||
const auto CharacterSize = ImGui::CalcTextSize("0");
|
||||
|
||||
@ -439,8 +377,7 @@ namespace hex {
|
||||
ImGui::TableNextRow();
|
||||
ImGui::TableNextColumn();
|
||||
|
||||
if (ImHexApi::Provider::isValid()) {
|
||||
auto provider = ImHexApi::Provider::get();
|
||||
if (provider != nullptr && provider->isReadable()) {
|
||||
|
||||
std::pair<Region, bool> validRegion = { Region::Invalid(), false };
|
||||
const auto isCurrRegionValid = [&validRegion, &provider](u64 address){
|
||||
@ -481,8 +418,8 @@ namespace hex {
|
||||
|
||||
// Query cell colors
|
||||
if (x < std::ceil(float(validBytes) / bytesPerCell)) {
|
||||
const auto foregroundColor = queryForegroundColor(byteAddress, &bytes[x * cellBytes], cellBytes);
|
||||
const auto backgroundColor = queryBackgroundColor(byteAddress, &bytes[x * cellBytes], cellBytes);
|
||||
const auto foregroundColor = this->m_foregroundColorCallback(byteAddress, &bytes[x * cellBytes], cellBytes);
|
||||
const auto backgroundColor = this->m_backgroundColorCallback(byteAddress, &bytes[x * cellBytes], cellBytes);
|
||||
|
||||
cellColors.emplace_back(
|
||||
foregroundColor,
|
||||
@ -549,7 +486,7 @@ namespace hex {
|
||||
ImGui::PushStyleVar(ImGuiStyleVar_FramePadding, ImVec2(0, 0));
|
||||
ImGui::PushItemWidth((CharacterSize * maxCharsPerCell).x);
|
||||
if (isCurrRegionValid(byteAddress))
|
||||
this->drawCell(byteAddress, &bytes[x * bytesPerCell], bytesPerCell, cellHovered, CellType::Hex);
|
||||
this->drawCell(provider, byteAddress, &bytes[x * bytesPerCell], bytesPerCell, cellHovered, CellType::Hex);
|
||||
else
|
||||
ImGui::TextFormatted("{}", std::string(maxCharsPerCell, '?'));
|
||||
ImGui::PopItemWidth();
|
||||
@ -606,7 +543,7 @@ namespace hex {
|
||||
if (!isCurrRegionValid(byteAddress))
|
||||
ImGui::TextFormatted("?");
|
||||
else
|
||||
this->drawCell(byteAddress, &bytes[x], 1, cellHovered, CellType::ASCII);
|
||||
this->drawCell(provider, byteAddress, &bytes[x], 1, cellHovered, CellType::ASCII);
|
||||
ImGui::PopItemWidth();
|
||||
ImGui::PopStyleVar();
|
||||
}
|
||||
@ -627,7 +564,7 @@ namespace hex {
|
||||
do {
|
||||
const u64 address = y * this->m_bytesPerRow + offset + provider->getBaseAddress() + provider->getCurrentPageAddress();
|
||||
|
||||
auto result = queryCustomEncodingData(*this->m_currCustomEncoding, address);
|
||||
auto result = queryCustomEncodingData(provider, *this->m_currCustomEncoding, address);
|
||||
offset += std::max<size_t>(1, result.advance);
|
||||
|
||||
encodingData.emplace_back(address, result);
|
||||
@ -684,13 +621,13 @@ namespace hex {
|
||||
auto fractionPerLine = 1.0 / (this->m_visibleRowCount + 1);
|
||||
|
||||
if (y == (u64(clipper.DisplayStart) + 3)) {
|
||||
if (i128((*this->m_selectionEnd)->value() - provider->getBaseAddress() - provider->getCurrentPageAddress()) <= (i64(clipper.DisplayStart + 3) * this->m_bytesPerRow)) {
|
||||
if (i128(this->m_selectionEnd.value() - provider->getBaseAddress() - provider->getCurrentPageAddress()) <= (i64(clipper.DisplayStart + 3) * this->m_bytesPerRow)) {
|
||||
this->m_shouldScrollToSelection = false;
|
||||
ImGui::SetScrollHereY(fractionPerLine * 5);
|
||||
|
||||
}
|
||||
} else if (y == (u64(clipper.DisplayEnd) - 1)) {
|
||||
if (i128((*this->m_selectionEnd)->value() - provider->getBaseAddress() - provider->getCurrentPageAddress()) >= (i64(clipper.DisplayEnd - 2) * this->m_bytesPerRow)) {
|
||||
if (i128(this->m_selectionEnd.value() - provider->getBaseAddress() - provider->getCurrentPageAddress()) >= (i64(clipper.DisplayEnd - 2) * this->m_bytesPerRow)) {
|
||||
this->m_shouldScrollToSelection = false;
|
||||
ImGui::SetScrollHereY(fractionPerLine * (this->m_visibleRowCount));
|
||||
}
|
||||
@ -738,9 +675,9 @@ namespace hex {
|
||||
if (!this->m_syncScrolling) {
|
||||
if (this->m_shouldUpdateScrollPosition) {
|
||||
this->m_shouldUpdateScrollPosition = false;
|
||||
ImGui::SetScrollY(**this->m_scrollPosition);
|
||||
ImGui::SetScrollY(this->m_scrollPosition);
|
||||
} else {
|
||||
**this->m_scrollPosition = ImGui::GetScrollY();
|
||||
this->m_scrollPosition = ImGui::GetScrollY();
|
||||
}
|
||||
}
|
||||
|
||||
@ -756,9 +693,8 @@ namespace hex {
|
||||
this->m_enteredEditingMode = false;
|
||||
}
|
||||
|
||||
void HexEditor::drawFooter(const ImVec2 &size) {
|
||||
if (ImHexApi::Provider::isValid()) {
|
||||
auto provider = ImHexApi::Provider::get();
|
||||
void HexEditor::drawFooter(prv::Provider *provider, const ImVec2 &size) {
|
||||
if (provider != nullptr && provider->isReadable()) {
|
||||
const auto pageCount = provider->getPageCount();
|
||||
constexpr static u32 MinPage = 1;
|
||||
|
||||
@ -835,7 +771,7 @@ namespace hex {
|
||||
drawTooltip(address, data, bytesPerCell);
|
||||
|
||||
auto endAddress = address + bytesPerCell - 1;
|
||||
auto &selectionStart = **this->m_selectionStart;
|
||||
auto &selectionStart = this->m_selectionStart;
|
||||
|
||||
if (ImGui::IsMouseDragging(ImGuiMouseButton_Left)) {
|
||||
this->setSelection(selectionStart.value_or(address), endAddress);
|
||||
@ -852,12 +788,14 @@ namespace hex {
|
||||
}
|
||||
}
|
||||
|
||||
void HexEditor::draw() {
|
||||
const auto FooterSize = ImVec2(ImGui::GetContentRegionAvail().x, ImGui::GetTextLineHeightWithSpacing() * 2.3);
|
||||
const auto TableSize = ImGui::GetContentRegionAvail() - ImVec2(0, FooterSize.y);
|
||||
void HexEditor::draw(prv::Provider *provider, float height) {
|
||||
const auto width = ImGui::GetContentRegionAvail().x;
|
||||
|
||||
this->drawEditor(TableSize);
|
||||
this->drawFooter(FooterSize);
|
||||
const auto FooterSize = ImVec2(width, ImGui::GetTextLineHeightWithSpacing() * 2.3F);
|
||||
const auto TableSize = ImVec2(width, height - FooterSize.y);
|
||||
|
||||
this->drawEditor(provider, TableSize);
|
||||
this->drawFooter(provider, FooterSize);
|
||||
|
||||
this->m_selectionChanged = false;
|
||||
}
|
||||
|
@ -118,10 +118,12 @@ namespace hex {
|
||||
}
|
||||
|
||||
void drawCommentTooltip(const pl::ptrn::Pattern &pattern) {
|
||||
if (ImGui::IsItemHovered(ImGuiHoveredFlags_AllowWhenBlockedByActiveItem) && pattern.getComment() != nullptr) {
|
||||
ImGui::BeginTooltip();
|
||||
ImGui::TextUnformatted(pattern.getComment()->c_str());
|
||||
ImGui::EndTooltip();
|
||||
if (ImGui::IsItemHovered(ImGuiHoveredFlags_AllowWhenBlockedByActiveItem)) {
|
||||
if (auto comment = pattern.getComment(); !comment.empty()) {
|
||||
ImGui::BeginTooltip();
|
||||
ImGui::TextUnformatted(pattern.getComment().c_str());
|
||||
ImGui::EndTooltip();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -16,13 +16,13 @@ namespace hex::plugin::builtin {
|
||||
|
||||
void registerProviders() {
|
||||
|
||||
ContentRegistry::Provider::add<prv::FileProvider>(false);
|
||||
ContentRegistry::Provider::add<prv::NullProvider>(false);
|
||||
ContentRegistry::Provider::add<prv::DiskProvider>();
|
||||
ContentRegistry::Provider::add<prv::GDBProvider>();
|
||||
ContentRegistry::Provider::add<prv::IntelHexProvider>();
|
||||
ContentRegistry::Provider::add<prv::MotorolaSRECProvider>();
|
||||
ContentRegistry::Provider::add<prv::MemoryFileProvider>(false);
|
||||
ContentRegistry::Provider::add<FileProvider>(false);
|
||||
ContentRegistry::Provider::add<NullProvider>(false);
|
||||
ContentRegistry::Provider::add<DiskProvider>();
|
||||
ContentRegistry::Provider::add<GDBProvider>();
|
||||
ContentRegistry::Provider::add<IntelHexProvider>();
|
||||
ContentRegistry::Provider::add<MotorolaSRECProvider>();
|
||||
ContentRegistry::Provider::add<MemoryFileProvider>(false);
|
||||
|
||||
ProjectFile::registerHandler({
|
||||
.basePath = "providers",
|
||||
|
@ -24,7 +24,7 @@
|
||||
#define lseek lseek64
|
||||
#endif
|
||||
|
||||
namespace hex::plugin::builtin::prv {
|
||||
namespace hex::plugin::builtin {
|
||||
|
||||
DiskProvider::DiskProvider() : Provider() {
|
||||
|
||||
|
@ -10,7 +10,7 @@
|
||||
|
||||
#include <nlohmann/json.hpp>
|
||||
|
||||
namespace hex::plugin::builtin::prv {
|
||||
namespace hex::plugin::builtin {
|
||||
|
||||
bool FileProvider::isAvailable() const {
|
||||
return this->m_mappedFile != nullptr;
|
||||
|
@ -13,7 +13,7 @@
|
||||
|
||||
#include <nlohmann/json.hpp>
|
||||
|
||||
namespace hex::plugin::builtin::prv {
|
||||
namespace hex::plugin::builtin {
|
||||
|
||||
using namespace std::chrono_literals;
|
||||
|
||||
|
@ -10,7 +10,7 @@
|
||||
|
||||
#include <nlohmann/json.hpp>
|
||||
|
||||
namespace hex::plugin::builtin::prv {
|
||||
namespace hex::plugin::builtin {
|
||||
|
||||
namespace intel_hex {
|
||||
|
||||
|
@ -8,7 +8,7 @@
|
||||
#include <hex/api/event.hpp>
|
||||
#include <hex/helpers/file.hpp>
|
||||
|
||||
namespace hex::plugin::builtin::prv {
|
||||
namespace hex::plugin::builtin {
|
||||
|
||||
bool MemoryFileProvider::open() {
|
||||
this->m_data.resize(1);
|
||||
|
@ -6,7 +6,7 @@
|
||||
#include <hex/helpers/file.hpp>
|
||||
#include <hex/helpers/fmt.hpp>
|
||||
|
||||
namespace hex::plugin::builtin::prv {
|
||||
namespace hex::plugin::builtin {
|
||||
|
||||
namespace motorola_srec {
|
||||
|
||||
|
@ -463,14 +463,66 @@ namespace hex::plugin::builtin {
|
||||
/* Hex Editor */
|
||||
|
||||
ViewHexEditor::ViewHexEditor() : View("hex.builtin.view.hex_editor.name") {
|
||||
this->m_hexEditor = std::make_unique<HexEditor>(&this->m_selectionStart, &this->m_selectionEnd, &this->m_scrollPosition);
|
||||
this->m_hexEditor.setForegroundHighlightCallback([](u64 address, const u8 *data, size_t size) -> std::optional<color_t> {
|
||||
std::optional<color_t> result;
|
||||
for (const auto &[id, callback] : ImHexApi::HexEditor::impl::getForegroundHighlightingFunctions()) {
|
||||
if (auto color = callback(address, data, size, result.has_value()); color.has_value())
|
||||
result = color;
|
||||
}
|
||||
|
||||
EventManager::subscribe<EventProviderChanged>(this, [this](auto *, auto *newProvider) {
|
||||
auto &data = ProviderExtraData::get(newProvider).editor;
|
||||
if (result.has_value())
|
||||
return result;
|
||||
|
||||
this->m_selectionStart = &data.selectionStart;
|
||||
this->m_selectionEnd = &data.selectionEnd;
|
||||
this->m_scrollPosition = &data.scrollPosition;
|
||||
for (const auto &[id, highlighting] : ImHexApi::HexEditor::impl::getForegroundHighlights()) {
|
||||
if (highlighting.getRegion().overlaps({ address, size }))
|
||||
return highlighting.getColor();
|
||||
}
|
||||
|
||||
return std::nullopt;
|
||||
});
|
||||
|
||||
this->m_hexEditor.setBackgroundHighlightCallback([](u64 address, const u8 *data, size_t size) -> std::optional<color_t> {
|
||||
std::optional<color_t> result;
|
||||
for (const auto &[id, callback] : ImHexApi::HexEditor::impl::getBackgroundHighlightingFunctions()) {
|
||||
if (auto color = callback(address, data, size, result.has_value()); color.has_value())
|
||||
return color.value();
|
||||
}
|
||||
|
||||
if (result.has_value())
|
||||
return result;
|
||||
|
||||
for (const auto &[id, highlighting] : ImHexApi::HexEditor::impl::getBackgroundHighlights()) {
|
||||
if (highlighting.getRegion().overlaps({ address, size }))
|
||||
return highlighting.getColor();
|
||||
}
|
||||
|
||||
return std::nullopt;
|
||||
});
|
||||
|
||||
this->m_hexEditor.setTooltipCallback([](u64 address, const u8 *data, size_t size) {
|
||||
for (const auto &[id, callback] : ImHexApi::HexEditor::impl::getTooltipFunctions()) {
|
||||
callback(address, data, size);
|
||||
}
|
||||
|
||||
for (const auto &[id, tooltip] : ImHexApi::HexEditor::impl::getTooltips()) {
|
||||
if (tooltip.getRegion().overlaps({ address, size })) {
|
||||
ImGui::BeginTooltip();
|
||||
if (ImGui::BeginTable("##tooltips", 1, ImGuiTableFlags_NoHostExtendX | ImGuiTableFlags_RowBg | ImGuiTableFlags_NoClip)) {
|
||||
ImGui::TableNextRow();
|
||||
ImGui::TableNextColumn();
|
||||
|
||||
ImGui::ColorButton(tooltip.getValue().c_str(), ImColor(tooltip.getColor()));
|
||||
ImGui::SameLine(0, 10);
|
||||
ImGui::TextUnformatted(tooltip.getValue().c_str());
|
||||
|
||||
ImGui::PushStyleColor(ImGuiCol_TableRowBg, tooltip.getColor());
|
||||
ImGui::PushStyleColor(ImGuiCol_TableRowBgAlt, tooltip.getColor());
|
||||
ImGui::EndTable();
|
||||
ImGui::PopStyleColor(2);
|
||||
}
|
||||
ImGui::EndTooltip();
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
this->registerShortcuts();
|
||||
@ -532,7 +584,7 @@ namespace hex::plugin::builtin {
|
||||
void ViewHexEditor::drawContent() {
|
||||
|
||||
if (ImGui::Begin(View::toWindowName(this->getUnlocalizedName()).c_str(), &this->getWindowOpenState(), ImGuiWindowFlags_NoCollapse | ImGuiWindowFlags_NoNavInputs | ImGuiWindowFlags_NoScrollbar | ImGuiWindowFlags_NoScrollWithMouse)) {
|
||||
this->m_hexEditor->draw();
|
||||
this->m_hexEditor.draw(ImHexApi::Provider::get());
|
||||
this->drawPopup();
|
||||
}
|
||||
ImGui::End();
|
||||
@ -645,20 +697,20 @@ namespace hex::plugin::builtin {
|
||||
ShortcutManager::addShortcut(this, Keys::Up, [this] {
|
||||
auto selection = getSelection();
|
||||
|
||||
if (selection.getEndAddress() >= this->m_hexEditor->getBytesPerRow()) {
|
||||
auto pos = selection.getEndAddress() - this->m_hexEditor->getBytesPerRow();
|
||||
if (selection.getEndAddress() >= this->m_hexEditor.getBytesPerRow()) {
|
||||
auto pos = selection.getEndAddress() - this->m_hexEditor.getBytesPerRow();
|
||||
this->setSelection(pos, pos);
|
||||
this->m_hexEditor->scrollToSelection();
|
||||
this->m_hexEditor->jumpIfOffScreen();
|
||||
this->m_hexEditor.scrollToSelection();
|
||||
this->m_hexEditor.jumpIfOffScreen();
|
||||
}
|
||||
});
|
||||
ShortcutManager::addShortcut(this, Keys::Down, [this] {
|
||||
auto selection = getSelection();
|
||||
|
||||
auto pos = selection.getEndAddress() + this->m_hexEditor->getBytesPerRow();
|
||||
auto pos = selection.getEndAddress() + this->m_hexEditor.getBytesPerRow();
|
||||
this->setSelection(pos, pos);
|
||||
this->m_hexEditor->scrollToSelection();
|
||||
this->m_hexEditor->jumpIfOffScreen();
|
||||
this->m_hexEditor.scrollToSelection();
|
||||
this->m_hexEditor.jumpIfOffScreen();
|
||||
});
|
||||
ShortcutManager::addShortcut(this, Keys::Left, [this] {
|
||||
auto selection = getSelection();
|
||||
@ -666,8 +718,8 @@ namespace hex::plugin::builtin {
|
||||
if (selection.getEndAddress() > 0) {
|
||||
auto pos = selection.getEndAddress() - 1;
|
||||
this->setSelection(pos, pos);
|
||||
this->m_hexEditor->scrollToSelection();
|
||||
this->m_hexEditor->jumpIfOffScreen();
|
||||
this->m_hexEditor.scrollToSelection();
|
||||
this->m_hexEditor.jumpIfOffScreen();
|
||||
}
|
||||
});
|
||||
ShortcutManager::addShortcut(this, Keys::Right, [this] {
|
||||
@ -675,78 +727,78 @@ namespace hex::plugin::builtin {
|
||||
|
||||
auto pos = selection.getEndAddress() + 1;
|
||||
this->setSelection(pos, pos);
|
||||
this->m_hexEditor->scrollToSelection();
|
||||
this->m_hexEditor->jumpIfOffScreen();
|
||||
this->m_hexEditor.scrollToSelection();
|
||||
this->m_hexEditor.jumpIfOffScreen();
|
||||
});
|
||||
|
||||
ShortcutManager::addShortcut(this, Keys::PageUp, [this] {
|
||||
auto selection = getSelection();
|
||||
|
||||
u64 visibleByteCount = this->m_hexEditor->getBytesPerRow() * this->m_hexEditor->getVisibleRowCount();
|
||||
u64 visibleByteCount = this->m_hexEditor.getBytesPerRow() * this->m_hexEditor.getVisibleRowCount();
|
||||
if (selection.getEndAddress() >= visibleByteCount) {
|
||||
auto pos = selection.getEndAddress() - visibleByteCount;
|
||||
this->setSelection(pos, pos);
|
||||
this->m_hexEditor->scrollToSelection();
|
||||
this->m_hexEditor->jumpIfOffScreen();
|
||||
this->m_hexEditor.scrollToSelection();
|
||||
this->m_hexEditor.jumpIfOffScreen();
|
||||
}
|
||||
});
|
||||
ShortcutManager::addShortcut(this, Keys::PageDown, [this] {
|
||||
auto selection = getSelection();
|
||||
|
||||
auto pos = selection.getEndAddress() + (this->m_hexEditor->getBytesPerRow() * this->m_hexEditor->getVisibleRowCount());
|
||||
auto pos = selection.getEndAddress() + (this->m_hexEditor.getBytesPerRow() * this->m_hexEditor.getVisibleRowCount());
|
||||
this->setSelection(pos, pos);
|
||||
this->m_hexEditor->scrollToSelection();
|
||||
this->m_hexEditor->jumpIfOffScreen();
|
||||
this->m_hexEditor.scrollToSelection();
|
||||
this->m_hexEditor.jumpIfOffScreen();
|
||||
});
|
||||
|
||||
// Move selection around
|
||||
ShortcutManager::addShortcut(this, SHIFT + Keys::Up, [this] {
|
||||
auto selection = getSelection();
|
||||
|
||||
this->setSelection(std::max<u64>(selection.getStartAddress(), this->m_hexEditor->getBytesPerRow()) - this->m_hexEditor->getBytesPerRow(), selection.getEndAddress());
|
||||
this->m_hexEditor->scrollToSelection();
|
||||
this->m_hexEditor->jumpIfOffScreen();
|
||||
this->setSelection(std::max<u64>(selection.getStartAddress(), this->m_hexEditor.getBytesPerRow()) - this->m_hexEditor.getBytesPerRow(), selection.getEndAddress());
|
||||
this->m_hexEditor.scrollToSelection();
|
||||
this->m_hexEditor.jumpIfOffScreen();
|
||||
});
|
||||
ShortcutManager::addShortcut(this, SHIFT + Keys::Down, [this] {
|
||||
auto selection = getSelection();
|
||||
|
||||
this->setSelection(selection.getStartAddress() + this->m_hexEditor->getBytesPerRow(), selection.getEndAddress());
|
||||
this->m_hexEditor->scrollToSelection();
|
||||
this->m_hexEditor->jumpIfOffScreen();
|
||||
this->setSelection(selection.getStartAddress() + this->m_hexEditor.getBytesPerRow(), selection.getEndAddress());
|
||||
this->m_hexEditor.scrollToSelection();
|
||||
this->m_hexEditor.jumpIfOffScreen();
|
||||
|
||||
});
|
||||
ShortcutManager::addShortcut(this, SHIFT + Keys::Left, [this] {
|
||||
auto selection = getSelection();
|
||||
|
||||
this->setSelection(std::max<u64>(selection.getStartAddress(), 1) - 1, selection.getEndAddress());
|
||||
this->m_hexEditor->scrollToSelection();
|
||||
this->m_hexEditor->jumpIfOffScreen();
|
||||
this->m_hexEditor.scrollToSelection();
|
||||
this->m_hexEditor.jumpIfOffScreen();
|
||||
});
|
||||
ShortcutManager::addShortcut(this, SHIFT + Keys::Right, [this] {
|
||||
auto selection = getSelection();
|
||||
|
||||
this->setSelection(selection.getStartAddress() + 1, selection.getEndAddress());
|
||||
this->m_hexEditor->scrollToSelection();
|
||||
this->m_hexEditor->jumpIfOffScreen();
|
||||
this->m_hexEditor.scrollToSelection();
|
||||
this->m_hexEditor.jumpIfOffScreen();
|
||||
});
|
||||
ShortcutManager::addShortcut(this, Keys::PageUp, [this] {
|
||||
auto selection = getSelection();
|
||||
u64 visibleByteCount = this->m_hexEditor->getBytesPerRow() * this->m_hexEditor->getVisibleRowCount();
|
||||
u64 visibleByteCount = this->m_hexEditor.getBytesPerRow() * this->m_hexEditor.getVisibleRowCount();
|
||||
|
||||
if (selection.getEndAddress() >= visibleByteCount) {
|
||||
auto pos = selection.getEndAddress() - visibleByteCount;
|
||||
this->setSelection(pos, selection.getEndAddress());
|
||||
this->m_hexEditor->scrollToSelection();
|
||||
this->m_hexEditor->jumpIfOffScreen();
|
||||
this->m_hexEditor.scrollToSelection();
|
||||
this->m_hexEditor.jumpIfOffScreen();
|
||||
}
|
||||
});
|
||||
ShortcutManager::addShortcut(this, Keys::PageDown, [this] {
|
||||
auto selection = getSelection();
|
||||
auto pos = selection.getEndAddress() + (this->m_hexEditor->getBytesPerRow() * this->m_hexEditor->getVisibleRowCount());
|
||||
auto pos = selection.getEndAddress() + (this->m_hexEditor.getBytesPerRow() * this->m_hexEditor.getVisibleRowCount());
|
||||
|
||||
this->setSelection(pos, selection.getEndAddress());
|
||||
this->m_hexEditor->scrollToSelection();
|
||||
this->m_hexEditor->jumpIfOffScreen();
|
||||
this->m_hexEditor.scrollToSelection();
|
||||
this->m_hexEditor.jumpIfOffScreen();
|
||||
});
|
||||
|
||||
ShortcutManager::addShortcut(this, CTRL + Keys::G, [this] {
|
||||
@ -826,9 +878,25 @@ namespace hex::plugin::builtin {
|
||||
region = getSelection();
|
||||
});
|
||||
|
||||
EventManager::subscribe<EventProviderChanged>(this, [this](auto, auto) {
|
||||
this->m_hexEditor->forceUpdateScrollPosition();
|
||||
EventManager::subscribe<EventProviderChanged>(this, [this](auto *oldProvider, auto *newProvider) {
|
||||
if (oldProvider != nullptr) {
|
||||
auto &oldData = ProviderExtraData::get(oldProvider).editor;
|
||||
|
||||
auto selection = this->m_hexEditor.getSelection();
|
||||
|
||||
oldData.selectionStart = selection.getStartAddress();
|
||||
oldData.selectionEnd = selection.getEndAddress();
|
||||
oldData.scrollPosition = this->m_hexEditor.getScrollPosition();
|
||||
}
|
||||
|
||||
if (newProvider != nullptr) {
|
||||
auto &newData = ProviderExtraData::get(newProvider).editor;
|
||||
|
||||
this->m_hexEditor.setSelectionUnchecked(newData.selectionStart, newData.selectionEnd);
|
||||
this->m_hexEditor.setScrollPosition(newData.scrollPosition);
|
||||
}
|
||||
|
||||
this->m_hexEditor.forceUpdateScrollPosition();
|
||||
if (isSelectionValid())
|
||||
EventManager::post<EventRegionSelected>(getSelection());
|
||||
});
|
||||
@ -867,7 +935,7 @@ namespace hex::plugin::builtin {
|
||||
|
||||
View::showFileChooserPopup(paths, { {"Thingy Table File", "tbl"} },
|
||||
[this](const auto &path) {
|
||||
this->m_hexEditor->setCustomEncoding(EncodingFile(EncodingFile::Type::Thingy, path));
|
||||
this->m_hexEditor.setCustomEncoding(EncodingFile(EncodingFile::Type::Thingy, path));
|
||||
});
|
||||
}
|
||||
});
|
||||
|
@ -129,6 +129,10 @@ namespace hex::plugin::builtin {
|
||||
this->drawVariableSettings(settingsSize, extraData.patternVariables);
|
||||
ImGui::EndTabItem();
|
||||
}
|
||||
if (ImGui::BeginTabItem("hex.builtin.view.pattern_editor.sections"_lang)) {
|
||||
this->drawSectionSelector(settingsSize, extraData.sections);
|
||||
ImGui::EndTabItem();
|
||||
}
|
||||
|
||||
ImGui::EndTabBar();
|
||||
}
|
||||
@ -431,6 +435,58 @@ namespace hex::plugin::builtin {
|
||||
ImGui::EndChild();
|
||||
}
|
||||
|
||||
void ViewPatternEditor::drawSectionSelector(ImVec2 size, std::map<u64, pl::api::Section> §ions) {
|
||||
if (ImGui::BeginTable("##sections_table", 3, ImGuiTableFlags_SizingStretchProp | ImGuiTableFlags_Borders | ImGuiTableFlags_RowBg | ImGuiTableFlags_ScrollY, size)) {
|
||||
ImGui::TableSetupScrollFreeze(0, 1);
|
||||
ImGui::TableSetupColumn("Name", ImGuiTableColumnFlags_WidthStretch, 0.5F);
|
||||
ImGui::TableSetupColumn("Size", ImGuiTableColumnFlags_WidthStretch, 0.5F);
|
||||
ImGui::TableSetupColumn("##button", ImGuiTableColumnFlags_WidthFixed, 20_scaled);
|
||||
|
||||
ImGui::TableHeadersRow();
|
||||
|
||||
for (auto &[id, section] : sections) {
|
||||
ImGui::PushID(id);
|
||||
|
||||
ImGui::TableNextRow();
|
||||
ImGui::TableNextColumn();
|
||||
|
||||
ImGui::TextUnformatted(section.name.c_str());
|
||||
ImGui::TableNextColumn();
|
||||
ImGui::TextFormatted("{} | 0x{:02X}", hex::toByteString(section.data.size()), section.data.size());
|
||||
ImGui::TableNextColumn();
|
||||
if (ImGui::IconButton(ICON_VS_OPEN_PREVIEW, ImGui::GetStyleColorVec4(ImGuiCol_Text))) {
|
||||
this->m_sectionProvider = std::make_unique<MemoryFileProvider>();
|
||||
this->m_sectionProvider->resize(section.data.size());
|
||||
this->m_sectionProvider->writeRaw(0, section.data.data(), section.data.size());
|
||||
|
||||
this->m_hexEditor.setBackgroundHighlightCallback([this, id](u64 address, const u8 *, size_t) -> std::optional<color_t> {
|
||||
if (this->m_runningEvaluators != 0)
|
||||
return std::nullopt;
|
||||
if (!ImHexApi::Provider::isValid())
|
||||
return std::nullopt;
|
||||
|
||||
std::optional<ImColor> color;
|
||||
for (const auto &pattern : ProviderExtraData::getCurrent().patternLanguage.runtime->getPatternsAtAddress(address, id)) {
|
||||
if (pattern->isHidden())
|
||||
continue;
|
||||
|
||||
if (color.has_value())
|
||||
color = ImAlphaBlendColors(*color, pattern->getColor());
|
||||
else
|
||||
color = pattern->getColor();
|
||||
}
|
||||
|
||||
return color;
|
||||
});
|
||||
}
|
||||
|
||||
ImGui::PopID();
|
||||
}
|
||||
|
||||
ImGui::EndTable();
|
||||
}
|
||||
}
|
||||
|
||||
void ViewPatternEditor::drawAlwaysVisible() {
|
||||
auto provider = ImHexApi::Provider::get();
|
||||
|
||||
@ -470,6 +526,18 @@ namespace hex::plugin::builtin {
|
||||
|
||||
ImGui::EndPopup();
|
||||
}
|
||||
|
||||
auto open = this->m_sectionProvider != nullptr && this->m_sectionProvider->isReadable();
|
||||
if (open) {
|
||||
ImGui::SetNextWindowSize(scaled(ImVec2(500, 650)), ImGuiCond_Appearing);
|
||||
if (ImGui::Begin("hex.builtin.view.pattern_editor.section_popup"_lang, &open)) {
|
||||
this->m_hexEditor.draw(this->m_sectionProvider.get());
|
||||
}
|
||||
ImGui::End();
|
||||
}
|
||||
|
||||
if (!open)
|
||||
this->m_sectionProvider = nullptr;
|
||||
}
|
||||
|
||||
|
||||
@ -517,12 +585,12 @@ namespace hex::plugin::builtin {
|
||||
ImGui::TableNextColumn();
|
||||
ImGui::TextFormatted(" {}", pattern->getEndian() == std::endian::little ? "hex.builtin.common.little"_lang : "hex.builtin.common.big"_lang);
|
||||
|
||||
if (const auto &comment = pattern->getComment(); comment != nullptr) {
|
||||
if (const auto &comment = pattern->getComment(); !comment.empty()) {
|
||||
ImGui::TableNextRow();
|
||||
ImGui::TableNextColumn();
|
||||
ImGui::TextFormatted("{} ", "hex.builtin.common.comment"_lang);
|
||||
ImGui::TableNextColumn();
|
||||
ImGui::TextWrapped(" \"%s\"", comment->c_str());
|
||||
ImGui::TextWrapped(" \"%s\"", comment.c_str());
|
||||
}
|
||||
|
||||
ImGui::EndTable();
|
||||
@ -626,6 +694,8 @@ namespace hex::plugin::builtin {
|
||||
ON_SCOPE_EXIT {
|
||||
patternLanguage.lastEvaluationLog = runtime->getConsoleLog();
|
||||
patternLanguage.lastEvaluationOutVars = runtime->getOutVariables();
|
||||
patternLanguage.sections = runtime->getSections();
|
||||
|
||||
this->m_runningEvaluators--;
|
||||
|
||||
this->m_lastEvaluationProcessed = false;
|
||||
|
Loading…
Reference in New Issue
Block a user