From a5296bab95ad09fa3458c50d0ed712f35cbe44f5 Mon Sep 17 00:00:00 2001 From: WerWolv Date: Fri, 16 Dec 2022 11:20:39 +0100 Subject: [PATCH] feat: Added pattern value editing --- lib/external/pattern_language | 2 +- lib/libimhex/source/api/content_registry.cpp | 12 ++- .../content/helpers/math_evaluator.hpp | 1 + .../source/content/helpers/math_evaluator.cpp | 1 + .../content/views/view_data_inspector.cpp | 5 +- plugins/builtin/source/ui/pattern_drawer.cpp | 92 ++++++++++++++++++- 6 files changed, 103 insertions(+), 10 deletions(-) diff --git a/lib/external/pattern_language b/lib/external/pattern_language index 6b7c486d2..d3e81e685 160000 --- a/lib/external/pattern_language +++ b/lib/external/pattern_language @@ -1 +1 @@ -Subproject commit 6b7c486d2778bd5e95a3339bf920eebfb52aa569 +Subproject commit d3e81e685463416cf2dea4d3ab335b21aa2a39d6 diff --git a/lib/libimhex/source/api/content_registry.cpp b/lib/libimhex/source/api/content_registry.cpp index e57b7ac48..e0d3230d0 100644 --- a/lib/libimhex/source/api/content_registry.cpp +++ b/lib/libimhex/source/api/content_registry.cpp @@ -245,9 +245,15 @@ namespace hex { runtime.reset(); if (provider != nullptr) { - runtime.setDataSource([provider](u64 offset, u8 *buffer, size_t size) { - provider->read(offset, buffer, size); - }, provider->getBaseAddress(), provider->getActualSize()); + runtime.setDataSource(provider->getBaseAddress(), provider->getActualSize(), + [provider](u64 offset, u8 *buffer, size_t size) { + provider->read(offset, buffer, size); + }, + [provider](u64 offset, const u8 *buffer, size_t size) { + if (provider->isWritable()) + provider->write(offset, buffer, size); + } + ); } runtime.setIncludePaths(fs::getDefaultPaths(fs::ImHexPath::PatternsInclude) | fs::getDefaultPaths(fs::ImHexPath::Patterns)); diff --git a/plugins/builtin/include/content/helpers/math_evaluator.hpp b/plugins/builtin/include/content/helpers/math_evaluator.hpp index d8c5551b2..1bbdc04b3 100644 --- a/plugins/builtin/include/content/helpers/math_evaluator.hpp +++ b/plugins/builtin/include/content/helpers/math_evaluator.hpp @@ -119,5 +119,6 @@ namespace hex { extern template class MathEvaluator; extern template class MathEvaluator; + extern template class MathEvaluator; } \ No newline at end of file diff --git a/plugins/builtin/source/content/helpers/math_evaluator.cpp b/plugins/builtin/source/content/helpers/math_evaluator.cpp index 57afa95e1..ec721ccb0 100644 --- a/plugins/builtin/source/content/helpers/math_evaluator.cpp +++ b/plugins/builtin/source/content/helpers/math_evaluator.cpp @@ -469,5 +469,6 @@ namespace hex { template class MathEvaluator; template class MathEvaluator; + template class MathEvaluator; } diff --git a/plugins/builtin/source/content/views/view_data_inspector.cpp b/plugins/builtin/source/content/views/view_data_inspector.cpp index 0f2b4fc92..626327419 100644 --- a/plugins/builtin/source/content/views/view_data_inspector.cpp +++ b/plugins/builtin/source/content/views/view_data_inspector.cpp @@ -87,14 +87,15 @@ namespace hex::plugin::builtin { pl::PatternLanguage runtime; ContentRegistry::PatternLanguage::configureRuntime(runtime, nullptr); - runtime.setDataSource([this, invert](u64 offset, u8 *buffer, size_t size) { + runtime.setDataSource(this->m_selectedProvider->getBaseAddress(), this->m_selectedProvider->getActualSize(), + [this, invert](u64 offset, u8 *buffer, size_t size) { this->m_selectedProvider->read(offset, buffer, size); if (invert) { for (size_t i = 0; i < size; i++) buffer[i] ^= 0xFF; } - }, this->m_selectedProvider->getBaseAddress(), this->m_selectedProvider->getActualSize()); + }); runtime.setDangerousFunctionCallHandler([]{ return false; }); runtime.setDefaultEndian(endian); diff --git a/plugins/builtin/source/ui/pattern_drawer.cpp b/plugins/builtin/source/ui/pattern_drawer.cpp index 92edbfed3..d93567c14 100644 --- a/plugins/builtin/source/ui/pattern_drawer.cpp +++ b/plugins/builtin/source/ui/pattern_drawer.cpp @@ -22,6 +22,7 @@ #include #include #include +#include #include #include @@ -155,7 +156,6 @@ namespace hex::plugin::builtin::ui { drawSizeColumn(pattern); ImGui::TextFormattedColored(ImColor(0xFF9BC64D), "{}", pattern.getFormattedName().empty() ? pattern.getTypeName() : pattern.getFormattedName()); ImGui::TableNextColumn(); - ImGui::TextFormatted("{}", pattern.getFormattedValue()); } } @@ -229,10 +229,32 @@ namespace hex::plugin::builtin::ui { void PatternDrawer::visit(pl::ptrn::PatternBoolean& pattern) { createDefaultEntry(pattern); + + ImGui::PushStyleVar(ImGuiStyleVar_FramePadding, ImVec2(0, 0)); + ImGui::PushItemWidth(ImGui::GetContentRegionAvail().x); + + bool value = hex::get_or(pattern.getValue(), true) != 0; + if (ImGui::Checkbox(pattern.getFormattedValue().c_str(), &value)) + pattern.setValue(value); + + ImGui::PopItemWidth(); + ImGui::PopStyleVar(); } void PatternDrawer::visit(pl::ptrn::PatternCharacter& pattern) { createDefaultEntry(pattern); + + ImGui::PushStyleVar(ImGuiStyleVar_FramePadding, ImVec2(0, 0)); + ImGui::PushItemWidth(ImGui::GetContentRegionAvail().x); + auto value = hex::encodeByteString(pattern.getBytes()); + if (ImGui::InputText("##Character", value.data(), value.size() + 1, ImGuiInputTextFlags_AutoSelectAll | ImGuiInputTextFlags_EnterReturnsTrue)) { + if (!value.empty()) { + auto result = hex::decodeByteString(value); + pattern.setValue(char(result[0])); + } + } + ImGui::PopItemWidth(); + ImGui::PopStyleVar(); } void PatternDrawer::visit(pl::ptrn::PatternEnum& pattern) { @@ -247,11 +269,40 @@ namespace hex::plugin::builtin::ui { drawOffsetColumn(pattern); drawSizeColumn(pattern); drawTypenameColumn(pattern, "enum"); - ImGui::TextFormatted("{}", pattern.getFormattedValue()); + + ImGui::PushStyleVar(ImGuiStyleVar_FramePadding, ImVec2(0, 0)); + ImGui::PushItemWidth(ImGui::GetContentRegionAvail().x); + + if (ImGui::BeginCombo("##Enum", pattern.getFormattedValue().c_str())) { + auto currValue = pl::core::Token::literalToUnsigned(pattern.getValue()); + for (auto &value : pattern.getEnumValues()) { + bool isSelected = pl::core::Token::literalToUnsigned(value.min) <= currValue && pl::core::Token::literalToUnsigned(value.max) >= currValue; + if (ImGui::Selectable(value.name.c_str(), isSelected)) { + pattern.setValue(value.min); + } + if (isSelected) + ImGui::SetItemDefaultFocus(); + } + ImGui::EndCombo(); + } + + ImGui::PopItemWidth(); + ImGui::PopStyleVar(); } void PatternDrawer::visit(pl::ptrn::PatternFloat& pattern) { createDefaultEntry(pattern); + + ImGui::PushStyleVar(ImGuiStyleVar_FramePadding, ImVec2(0, 0)); + ImGui::PushItemWidth(ImGui::GetContentRegionAvail().x); + + auto value = pl::core::Token::literalToFloatingPoint(pattern.getValue()); + if (ImGui::InputDouble("##Value", &value, 0.0, 0.0, "%.6f", ImGuiInputTextFlags_AutoSelectAll | ImGuiInputTextFlags_EnterReturnsTrue)) { + pattern.setValue(value); + } + + ImGui::PopItemWidth(); + ImGui::PopStyleVar(); } void PatternDrawer::visit(pl::ptrn::PatternPadding& pattern) { @@ -287,12 +338,28 @@ namespace hex::plugin::builtin::ui { void PatternDrawer::visit(pl::ptrn::PatternSigned& pattern) { createDefaultEntry(pattern); + + ImGui::PushStyleVar(ImGuiStyleVar_FramePadding, ImVec2(0, 0)); + ImGui::PushItemWidth(ImGui::GetContentRegionAvail().x); + + auto value = pattern.getFormattedValue(); + if (ImGui::InputText("##Value", value.data(), value.size() + 1, ImGuiInputTextFlags_AutoSelectAll | ImGuiInputTextFlags_EnterReturnsTrue)) { + MathEvaluator mathEvaluator; + + if (auto result = mathEvaluator.evaluate(value); result.has_value()) + pattern.setValue(result.value()); + } + + ImGui::PopItemWidth(); + ImGui::PopStyleVar(); } void PatternDrawer::visit(pl::ptrn::PatternString& pattern) { - if (pattern.getSize() > 0) + if (pattern.getSize() > 0) { createDefaultEntry(pattern); + ImGui::TextFormatted("{}", pattern.getFormattedValue()); } + } void PatternDrawer::visit(pl::ptrn::PatternStruct& pattern) { bool open = true; @@ -356,15 +423,30 @@ namespace hex::plugin::builtin::ui { void PatternDrawer::visit(pl::ptrn::PatternUnsigned& pattern) { createDefaultEntry(pattern); + + ImGui::PushStyleVar(ImGuiStyleVar_FramePadding, ImVec2(0, 0)); + ImGui::PushItemWidth(ImGui::GetContentRegionAvail().x); + auto value = pattern.getFormattedValue(); + if (ImGui::InputText("##Value", value.data(), value.size() + 1, ImGuiInputTextFlags_AutoSelectAll | ImGuiInputTextFlags_EnterReturnsTrue)) { + MathEvaluator mathEvaluator; + + if (auto result = mathEvaluator.evaluate(value); result.has_value()) + pattern.setValue(result.value()); + } + ImGui::PopItemWidth(); + ImGui::PopStyleVar(); } void PatternDrawer::visit(pl::ptrn::PatternWideCharacter& pattern) { createDefaultEntry(pattern); + ImGui::TextFormatted("{}", pattern.getFormattedValue()); } void PatternDrawer::visit(pl::ptrn::PatternWideString& pattern) { - if (pattern.getSize() > 0) + if (pattern.getSize() > 0) { createDefaultEntry(pattern); + ImGui::TextFormatted("{}", pattern.getFormattedValue()); + } } void PatternDrawer::draw(pl::ptrn::Pattern& pattern) { @@ -552,7 +634,9 @@ namespace hex::plugin::builtin::ui { ImGui::TableHeadersRow(); for (auto &pattern : this->m_sortedPatterns) { + ImGui::PushID(pattern); this->draw(*pattern); + ImGui::PopID(); } ImGui::EndTable();