mirror of
https://github.com/WerWolv/ImHex.git
synced 2026-03-28 07:47:03 -05:00
feat: Added file information command line option and fullscreen view
This commit is contained in:
2
lib/external/pattern_language
vendored
2
lib/external/pattern_language
vendored
Submodule lib/external/pattern_language updated: c2e4a6752f...153d1d9ce9
@@ -3,6 +3,7 @@
|
||||
#include <hex.hpp>
|
||||
|
||||
#include <hex/helpers/literals.hpp>
|
||||
#include <hex/helpers/fs.hpp>
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
@@ -27,4 +28,14 @@ namespace hex::magic {
|
||||
|
||||
bool isValidMIMEType(const std::string &mimeType);
|
||||
|
||||
struct FoundPattern {
|
||||
std::fs::path patternFilePath;
|
||||
std::string author;
|
||||
std::string description;
|
||||
std::optional<std::string> mimeType;
|
||||
std::optional<u64> magicOffset;
|
||||
};
|
||||
|
||||
std::vector<FoundPattern> findViablePatterns(prv::Provider *provider);
|
||||
|
||||
}
|
||||
@@ -15,6 +15,8 @@
|
||||
#include <string>
|
||||
|
||||
#include <magic.h>
|
||||
#include <hex/api/content_registry/pattern_language.hpp>
|
||||
#include <hex/helpers/binary_pattern.hpp>
|
||||
|
||||
#if defined(_MSC_VER)
|
||||
#include <direct.h>
|
||||
@@ -230,4 +232,127 @@ namespace hex::magic {
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
std::vector<FoundPattern> findViablePatterns(prv::Provider *provider) {
|
||||
std::vector<FoundPattern> result;
|
||||
|
||||
pl::PatternLanguage runtime;
|
||||
ContentRegistry::PatternLanguage::configureRuntime(runtime, provider);
|
||||
|
||||
bool foundCorrectType = false;
|
||||
|
||||
auto mimeType = getMIMEType(provider, 0, 4_KiB, true);
|
||||
|
||||
std::error_code errorCode;
|
||||
for (const auto &dir : paths::Patterns.read()) {
|
||||
for (auto &entry : std::fs::recursive_directory_iterator(dir, errorCode)) {
|
||||
foundCorrectType = false;
|
||||
if (!entry.is_regular_file())
|
||||
continue;
|
||||
|
||||
wolv::io::File file(entry.path(), wolv::io::File::Mode::Read);
|
||||
if (!file.isValid())
|
||||
continue;
|
||||
|
||||
std::string author, description;
|
||||
bool matchedMimeType = false;
|
||||
std::optional<u64> magicOffset;
|
||||
|
||||
|
||||
const auto pragmaValues = runtime.getPragmaValues(file.readString());
|
||||
if (auto it = pragmaValues.find("author"); it != pragmaValues.end())
|
||||
author = it->second;
|
||||
if (auto it = pragmaValues.find("description"); it != pragmaValues.end())
|
||||
description = it->second;
|
||||
|
||||
// Format: #pragma MIME type/subtype
|
||||
for (auto [it, itEnd] = pragmaValues.equal_range("MIME"); it != itEnd; ++it) {
|
||||
if (isValidMIMEType(it->second) && it->second == mimeType) {
|
||||
foundCorrectType = true;
|
||||
matchedMimeType = true;
|
||||
}
|
||||
}
|
||||
// Format: #pragma magic [ AA BB CC DD ] @ 0x12345678
|
||||
for (auto [it, itEnd] = pragmaValues.equal_range("magic"); it != itEnd; ++it) {
|
||||
const auto pattern = [value = it->second]() mutable -> std::optional<BinaryPattern> {
|
||||
value = wolv::util::trim(value);
|
||||
|
||||
if (value.empty())
|
||||
return std::nullopt;
|
||||
|
||||
if (!value.starts_with('['))
|
||||
return std::nullopt;
|
||||
|
||||
value = value.substr(1);
|
||||
|
||||
const auto end = value.find(']');
|
||||
if (end == std::string::npos)
|
||||
return std::nullopt;
|
||||
value.resize(end);
|
||||
|
||||
value = wolv::util::trim(value);
|
||||
|
||||
return BinaryPattern(value);
|
||||
}();
|
||||
|
||||
const auto address = [provider, value = it->second]() mutable -> std::optional<u64> {
|
||||
value = wolv::util::trim(value);
|
||||
|
||||
if (value.empty())
|
||||
return std::nullopt;
|
||||
|
||||
const auto start = value.find('@');
|
||||
if (start == std::string::npos)
|
||||
return std::nullopt;
|
||||
|
||||
value = value.substr(start + 1);
|
||||
value = wolv::util::trim(value);
|
||||
|
||||
size_t end = 0;
|
||||
auto result = std::stoll(value, &end, 0);
|
||||
if (end != value.length())
|
||||
return std::nullopt;
|
||||
|
||||
if (result < 0) {
|
||||
const auto size = provider->getActualSize();
|
||||
if (u64(-result) > size) {
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
return size + result;
|
||||
} else {
|
||||
return result;
|
||||
}
|
||||
}();
|
||||
|
||||
if (address && pattern) {
|
||||
std::vector<u8> bytes(pattern->getSize());
|
||||
if (!bytes.empty()) {
|
||||
provider->read(*address, bytes.data(), bytes.size());
|
||||
|
||||
if (pattern->matches(bytes)) {
|
||||
foundCorrectType = true;
|
||||
magicOffset = *address;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (foundCorrectType) {
|
||||
result.emplace_back(
|
||||
entry.path(),
|
||||
std::move(author),
|
||||
std::move(description),
|
||||
matchedMimeType ? std::make_optional(mimeType) : std::nullopt,
|
||||
magicOffset
|
||||
);
|
||||
}
|
||||
|
||||
runtime.reset();
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -120,6 +120,7 @@ add_imhex_plugin(
|
||||
source/content/views/view_tutorials.cpp
|
||||
|
||||
source/content/views/fullscreen/view_fullscreen_save_editor.cpp
|
||||
source/content/views/fullscreen/view_fullscreen_file_info.cpp
|
||||
|
||||
source/content/text_highlighting/pattern_language.cpp
|
||||
INCLUDES
|
||||
|
||||
@@ -29,6 +29,7 @@ namespace hex::plugin::builtin {
|
||||
void handleDebugModeCommand(const std::vector<std::string> &args);
|
||||
void handleValidatePluginCommand(const std::vector<std::string> &args);
|
||||
void handleSaveEditorCommand(const std::vector<std::string> &args);
|
||||
void handleFileInfoCommand(const std::vector<std::string> &args);
|
||||
|
||||
void registerCommandForwarders();
|
||||
|
||||
|
||||
@@ -0,0 +1,28 @@
|
||||
#pragma once
|
||||
|
||||
#include <content/providers/file_provider.hpp>
|
||||
#include <hex/api/task_manager.hpp>
|
||||
#include <hex/helpers/magic.hpp>
|
||||
#include <hex/ui/view.hpp>
|
||||
#include <ui/markdown.hpp>
|
||||
|
||||
namespace hex::plugin::builtin {
|
||||
|
||||
class ViewFullScreenFileInfo : public View::FullScreen {
|
||||
public:
|
||||
explicit ViewFullScreenFileInfo(std::fs::path filePath);
|
||||
|
||||
void drawContent() override;
|
||||
|
||||
private:
|
||||
std::fs::path m_filePath;
|
||||
FileProvider m_provider;
|
||||
TaskHolder m_analysisTask;
|
||||
|
||||
std::string m_mimeType;
|
||||
std::string m_fileDescription;
|
||||
std::vector<magic::FoundPattern> m_foundPatterns;
|
||||
std::optional<ui::Markdown> m_fullDescription;
|
||||
};
|
||||
|
||||
}
|
||||
@@ -9,6 +9,7 @@
|
||||
|
||||
#include <ui/text_editor.hpp>
|
||||
#include <content/text_highlighting/pattern_language.hpp>
|
||||
#include <hex/helpers/magic.hpp>
|
||||
#include <ui/pattern_drawer.hpp>
|
||||
|
||||
namespace pl::ptrn { class Pattern; }
|
||||
@@ -114,16 +115,10 @@ namespace hex::plugin::builtin {
|
||||
u32 color;
|
||||
};
|
||||
|
||||
struct PossiblePattern {
|
||||
std::fs::path path;
|
||||
std::string author;
|
||||
std::string description;
|
||||
};
|
||||
|
||||
std::unique_ptr<pl::PatternLanguage> m_editorRuntime;
|
||||
|
||||
std::mutex m_possiblePatternFilesMutex;
|
||||
PerProvider<std::vector<PossiblePattern>> m_possiblePatternFiles;
|
||||
PerProvider<std::vector<magic::FoundPattern>> m_possiblePatternFiles;
|
||||
bool m_runAutomatically = false;
|
||||
bool m_triggerEvaluation = false;
|
||||
std::atomic<bool> m_triggerAutoEvaluate = false;
|
||||
|
||||
@@ -794,6 +794,14 @@
|
||||
"hex.builtin.view.find.value.max": "Maximum Value",
|
||||
"hex.builtin.view.find.value.min": "Minimum Value",
|
||||
"hex.builtin.view.find.value.range": "Ranged Search",
|
||||
"hex.builtin.view.fullscreen.file_info.error.file_not_readable": "The selected file could not be opened. Please ensure the file exists and is readable.",
|
||||
"hex.builtin.view.fullscreen.file_info.error.not_identified": "Failed to identify the type of this file.",
|
||||
"hex.builtin.view.fullscreen.file_info.analyzing": "Analyzing Data...",
|
||||
"hex.builtin.view.fullscreen.file_info.match_info": "Match Information",
|
||||
"hex.builtin.view.fullscreen.file_info.match_info.mime": "Matched using MIME Type",
|
||||
"hex.builtin.view.fullscreen.file_info.match_info.magic": "Matched using Magic value at offset 0x{0:04X}",
|
||||
"hex.builtin.view.fullscreen.file_info.information": "Information",
|
||||
"hex.builtin.view.fullscreen.file_info.no_information": "No further information available.",
|
||||
"hex.builtin.view.help.about.commits": "Commit History",
|
||||
"hex.builtin.view.help.about.contributor": "Contributors",
|
||||
"hex.builtin.view.help.about.donations": "Donations",
|
||||
|
||||
@@ -29,6 +29,7 @@
|
||||
|
||||
#include <content/providers/file_provider.hpp>
|
||||
#include <content/views/fullscreen/view_fullscreen_save_editor.hpp>
|
||||
#include <content/views/fullscreen/view_fullscreen_file_info.hpp>
|
||||
|
||||
namespace hex::plugin::builtin {
|
||||
using namespace hex::literals;
|
||||
@@ -521,6 +522,21 @@ namespace hex::plugin::builtin {
|
||||
}
|
||||
}
|
||||
|
||||
void handleFileInfoCommand(const std::vector<std::string> &args) {
|
||||
if (args.size() != 1) {
|
||||
log::println("usage: imhex --file-info <file>");
|
||||
std::exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
const auto path = std::fs::path(args[0]);
|
||||
if (!wolv::io::fs::exists(path)) {
|
||||
log::println("File '{}' does not exist!", args[0]);
|
||||
std::exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
ContentRegistry::Views::setFullScreenView<ViewFullScreenFileInfo>(path);
|
||||
}
|
||||
|
||||
|
||||
void registerCommandForwarders() {
|
||||
hex::subcommands::registerSubCommand("open", [](const std::vector<std::string> &args){
|
||||
|
||||
@@ -0,0 +1,112 @@
|
||||
#include <content/views/fullscreen/view_fullscreen_file_info.hpp>
|
||||
#include <fonts/fonts.hpp>
|
||||
|
||||
#include <hex/api/content_registry/pattern_language.hpp>
|
||||
#include <hex/helpers/magic.hpp>
|
||||
#include <hex/helpers/literals.hpp>
|
||||
|
||||
#include <pl/pattern_language.hpp>
|
||||
#include <pl/core/evaluator.hpp>
|
||||
#include <toasts/toast_notification.hpp>
|
||||
|
||||
namespace hex::plugin::builtin {
|
||||
|
||||
using namespace hex::literals;
|
||||
|
||||
ViewFullScreenFileInfo::ViewFullScreenFileInfo(std::fs::path filePath) : m_filePath(std::move(filePath)) {
|
||||
this->m_provider.setPath(m_filePath);
|
||||
if (!this->m_provider.open()) {
|
||||
ui::ToastError::open("hex.builtin.view.fullscreen.file_info.error.file_not_readable"_lang);
|
||||
}
|
||||
|
||||
m_analysisTask = TaskManager::createBlockingTask("hex.builtin.view.fullscreen.file_info.analyzing", TaskManager::NoProgress, [this] {
|
||||
m_mimeType = magic::getMIMEType(&m_provider);
|
||||
if (!magic::isValidMIMEType(m_mimeType)) {
|
||||
m_mimeType.clear();
|
||||
} else {
|
||||
m_fileDescription = magic::getDescription(&m_provider, 0, 100_KiB, true);
|
||||
}
|
||||
|
||||
m_foundPatterns = magic::findViablePatterns(&m_provider);
|
||||
if (!m_foundPatterns.empty()) {
|
||||
pl::PatternLanguage runtime;
|
||||
ContentRegistry::PatternLanguage::configureRuntime(runtime, &m_provider);
|
||||
|
||||
constexpr static auto DataDescriptionFunction = "get_data_description";
|
||||
if (runtime.executeFile(m_foundPatterns.front().patternFilePath)) {
|
||||
const auto &evaluator = runtime.getInternals().evaluator;
|
||||
const auto &functions = evaluator->getCustomFunctions();
|
||||
if (const auto function = functions.find(DataDescriptionFunction); function != functions.end()) {
|
||||
if (const auto value = function->second.func(evaluator.get(), {}); value.has_value()) {
|
||||
if (value->isString()) {
|
||||
m_fullDescription = ui::Markdown(value->toString());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
void ViewFullScreenFileInfo::drawContent() {
|
||||
if (!m_provider.isReadable()) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (m_analysisTask.isRunning()) {
|
||||
return;
|
||||
}
|
||||
|
||||
const bool foundPatterns = !m_foundPatterns.empty();
|
||||
const bool hasMimeType = !m_mimeType.empty();
|
||||
if (!foundPatterns && !hasMimeType) {
|
||||
ImGuiExt::TextFormattedCentered("hex.builtin.view.fullscreen.file_info.error.not_identified"_lang);
|
||||
return;
|
||||
}
|
||||
|
||||
if (foundPatterns) {
|
||||
const auto &firstMatch = m_foundPatterns.front();
|
||||
|
||||
ImGui::BeginGroup();
|
||||
|
||||
fonts::Default().pushBold(1.2F);
|
||||
ImGuiExt::TextFormattedCenteredHorizontal("{}", firstMatch.description);
|
||||
fonts::Default().pop();
|
||||
|
||||
if (hasMimeType)
|
||||
ImGuiExt::TextFormattedCenteredHorizontal("{}", m_mimeType);
|
||||
if (!m_fileDescription.empty())
|
||||
ImGuiExt::TextFormattedCenteredHorizontal("{}", m_fileDescription);
|
||||
|
||||
ImGui::EndGroup();
|
||||
|
||||
ImGui::SameLine();
|
||||
ImGui::SetCursorPosX(ImGui::GetWindowSize().x - 300_scaled);
|
||||
|
||||
if (ImGuiExt::BeginSubWindow("hex.builtin.view.fullscreen.file_info.match_info"_lang)) {
|
||||
if (firstMatch.mimeType.has_value())
|
||||
ImGuiExt::TextFormattedWrapped("hex.builtin.view.fullscreen.file_info.match_info.mime"_lang);
|
||||
else if (firstMatch.magicOffset.has_value())
|
||||
ImGuiExt::TextFormattedWrapped("hex.builtin.view.fullscreen.file_info.match_info.magic"_lang, *firstMatch.magicOffset);
|
||||
}
|
||||
ImGuiExt::EndSubWindow();
|
||||
} else {
|
||||
fonts::Default().pushBold(1.2F);
|
||||
ImGuiExt::TextFormattedCenteredHorizontal("{}", m_mimeType);
|
||||
fonts::Default().pop();
|
||||
}
|
||||
|
||||
|
||||
ImGui::NewLine();
|
||||
|
||||
if (ImGuiExt::BeginSubWindow("hex.builtin.view.fullscreen.file_info.information"_lang, nullptr, ImGui::GetContentRegionAvail())) {
|
||||
if (m_fullDescription.has_value())
|
||||
m_fullDescription->draw();
|
||||
else
|
||||
ImGuiExt::TextFormattedCentered("hex.builtin.view.fullscreen.file_info.no_information"_lang);
|
||||
}
|
||||
ImGuiExt::EndSubWindow();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -70,7 +70,6 @@ namespace hex::plugin::builtin {
|
||||
if (!this->m_provider.open()) {
|
||||
ui::ToastError::open("The selected file could not be opened. Please ensure the file exists and is readable.");
|
||||
}
|
||||
this->m_provider.convertToMemoryFile();
|
||||
|
||||
ContentRegistry::PatternLanguage::configureRuntime(m_runtime, &m_provider);
|
||||
if (!m_runtime.executeString(this->m_sourceCode)) {
|
||||
|
||||
@@ -70,7 +70,7 @@ namespace hex::plugin::builtin {
|
||||
|
||||
if (ImGui::BeginListBox("##patterns_accept", ImVec2(400_scaled, 0))) {
|
||||
u32 index = 0;
|
||||
for (const auto &[path, author, description] : m_view->m_possiblePatternFiles.get(provider)) {
|
||||
for (const auto &[path, author, description, mimeType, magicOffset] : m_view->m_possiblePatternFiles.get(provider)) {
|
||||
ImGui::PushID(index + 1);
|
||||
auto fileName = wolv::util::toUTF8String(path.filename());
|
||||
|
||||
@@ -105,7 +105,7 @@ namespace hex::plugin::builtin {
|
||||
}
|
||||
|
||||
if (ImGui::IsItemHovered() && ImGui::IsMouseDoubleClicked(0))
|
||||
m_view->loadPatternFile(m_view->m_possiblePatternFiles.get(provider)[m_selectedPatternFile].path, provider, false);
|
||||
m_view->loadPatternFile(m_view->m_possiblePatternFiles.get(provider)[m_selectedPatternFile].patternFilePath, provider, false);
|
||||
|
||||
ImGuiExt::InfoTooltip(wolv::util::toUTF8String(path).c_str());
|
||||
|
||||
@@ -127,7 +127,7 @@ namespace hex::plugin::builtin {
|
||||
|
||||
ImGuiExt::ConfirmButtons("hex.ui.common.yes"_lang, "hex.ui.common.no"_lang,
|
||||
[this, provider] {
|
||||
m_view->loadPatternFile(m_view->m_possiblePatternFiles.get(provider)[m_selectedPatternFile].path, provider, false);
|
||||
m_view->loadPatternFile(m_view->m_possiblePatternFiles.get(provider)[m_selectedPatternFile].patternFilePath, provider, false);
|
||||
this->close();
|
||||
},
|
||||
[this] {
|
||||
@@ -1495,129 +1495,17 @@ namespace hex::plugin::builtin {
|
||||
if (m_shouldAnalyze) {
|
||||
m_shouldAnalyze = false;
|
||||
|
||||
m_analysisTask = TaskManager::createBackgroundTask("hex.builtin.task.analyzing_data", [this, provider](const Task &task) {
|
||||
m_analysisTask = TaskManager::createBackgroundTask("hex.builtin.task.analyzing_data", [this, provider] {
|
||||
if (!m_autoLoadPatterns)
|
||||
return;
|
||||
|
||||
pl::PatternLanguage runtime;
|
||||
ContentRegistry::PatternLanguage::configureRuntime(runtime, provider);
|
||||
auto foundPatterns = magic::findViablePatterns(provider);
|
||||
|
||||
bool foundCorrectType = false;
|
||||
if (!foundPatterns.empty()) {
|
||||
std::scoped_lock lock(m_possiblePatternFilesMutex);
|
||||
|
||||
auto mimeType = magic::getMIMEType(provider, 0, 4_KiB, true);
|
||||
|
||||
m_possiblePatternFiles.get(provider).clear();
|
||||
|
||||
bool popupOpen = false;
|
||||
std::error_code errorCode;
|
||||
for (const auto &dir : paths::Patterns.read()) {
|
||||
for (auto &entry : std::fs::recursive_directory_iterator(dir, errorCode)) {
|
||||
task.update();
|
||||
|
||||
foundCorrectType = false;
|
||||
if (!entry.is_regular_file())
|
||||
continue;
|
||||
|
||||
wolv::io::File file(entry.path(), wolv::io::File::Mode::Read);
|
||||
if (!file.isValid())
|
||||
continue;
|
||||
|
||||
std::string author, description;
|
||||
|
||||
const auto pragmaValues = runtime.getPragmaValues(file.readString());
|
||||
if (auto it = pragmaValues.find("author"); it != pragmaValues.end())
|
||||
author = it->second;
|
||||
if (auto it = pragmaValues.find("description"); it != pragmaValues.end())
|
||||
description = it->second;
|
||||
|
||||
// Format: #pragma MIME type/subtype
|
||||
if (auto it = pragmaValues.find("MIME"); it != pragmaValues.end()) {
|
||||
if (magic::isValidMIMEType(it->second) && it->second == mimeType)
|
||||
foundCorrectType = true;
|
||||
}
|
||||
// Format: #pragma magic [ AA BB CC DD ] @ 0x12345678
|
||||
if (auto it = pragmaValues.find("magic"); it != pragmaValues.end()) {
|
||||
const auto pattern = [value = it->second]() mutable -> std::optional<BinaryPattern> {
|
||||
value = wolv::util::trim(value);
|
||||
|
||||
if (value.empty())
|
||||
return std::nullopt;
|
||||
|
||||
if (!value.starts_with('['))
|
||||
return std::nullopt;
|
||||
|
||||
value = value.substr(1);
|
||||
|
||||
const auto end = value.find(']');
|
||||
if (end == std::string::npos)
|
||||
return std::nullopt;
|
||||
value.resize(end);
|
||||
|
||||
value = wolv::util::trim(value);
|
||||
|
||||
return BinaryPattern(value);
|
||||
}();
|
||||
|
||||
const auto address = [value = it->second, provider]() mutable -> std::optional<u64> {
|
||||
value = wolv::util::trim(value);
|
||||
|
||||
if (value.empty())
|
||||
return std::nullopt;
|
||||
|
||||
const auto start = value.find('@');
|
||||
if (start == std::string::npos)
|
||||
return std::nullopt;
|
||||
|
||||
value = value.substr(start + 1);
|
||||
value = wolv::util::trim(value);
|
||||
|
||||
size_t end = 0;
|
||||
auto result = std::stoll(value, &end, 0);
|
||||
if (end != value.length())
|
||||
return std::nullopt;
|
||||
|
||||
if (result < 0) {
|
||||
const auto size = provider->getActualSize();
|
||||
if (u64(-result) > size) {
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
return size + result;
|
||||
} else {
|
||||
return result;
|
||||
}
|
||||
}();
|
||||
|
||||
if (address && pattern) {
|
||||
std::vector<u8> bytes(pattern->getSize());
|
||||
if (!bytes.empty()) {
|
||||
provider->read(*address, bytes.data(), bytes.size());
|
||||
|
||||
if (pattern->matches(bytes))
|
||||
foundCorrectType = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (foundCorrectType) {
|
||||
{
|
||||
std::scoped_lock lock(m_possiblePatternFilesMutex);
|
||||
|
||||
m_possiblePatternFiles.get(provider).emplace_back(
|
||||
entry.path(),
|
||||
std::move(author),
|
||||
std::move(description)
|
||||
);
|
||||
}
|
||||
|
||||
if (!popupOpen) {
|
||||
PopupAcceptPattern::open(this);
|
||||
popupOpen = true;
|
||||
}
|
||||
}
|
||||
|
||||
runtime.reset();
|
||||
}
|
||||
m_possiblePatternFiles.get(provider) = std::move(foundPatterns);
|
||||
PopupAcceptPattern::open(this);
|
||||
}
|
||||
});
|
||||
}
|
||||
@@ -1959,6 +1847,9 @@ namespace hex::plugin::builtin {
|
||||
|
||||
RequestSetPatternLanguageCode::subscribe(this, [this](const std::string &code) {
|
||||
auto provider = ImHexApi::Provider::get();
|
||||
if (provider == nullptr)
|
||||
return;
|
||||
|
||||
m_textEditor.get(provider).setText(wolv::util::preprocessText(code));
|
||||
m_sourceCode.get(provider) = code;
|
||||
m_hasUnevaluatedChanges.get(provider) = true;
|
||||
@@ -2363,6 +2254,9 @@ namespace hex::plugin::builtin {
|
||||
ContentRegistry::FileTypeHandler::add({ ".hexpat", ".pat" }, [](const std::fs::path &path) -> bool {
|
||||
wolv::io::File file(path, wolv::io::File::Mode::Read);
|
||||
|
||||
if (!ImHexApi::Provider::isValid())
|
||||
return false;
|
||||
|
||||
if (file.isValid()) {
|
||||
RequestSetPatternLanguageCode::post(wolv::util::preprocessText(file.readString()));
|
||||
return true;
|
||||
|
||||
@@ -73,8 +73,8 @@ IMHEX_PLUGIN_SUBCOMMANDS() {
|
||||
{ "open", "o", "Open files passed as argument. [default]", hex::plugin::builtin::handleOpenCommand },
|
||||
{ "new", "n", "Create a new empty file", hex::plugin::builtin::handleNewCommand },
|
||||
|
||||
{ "select", "", "Select a range of bytes in the Hex Editor", hex::plugin::builtin::handleSelectCommand },
|
||||
{ "pattern", "", "Sets the loaded pattern", hex::plugin::builtin::handlePatternCommand },
|
||||
{ "select", "s", "Select a range of bytes in the Hex Editor", hex::plugin::builtin::handleSelectCommand },
|
||||
{ "pattern", "p", "Sets the loaded pattern", hex::plugin::builtin::handlePatternCommand },
|
||||
{ "calc", "", "Evaluate a mathematical expression", hex::plugin::builtin::handleCalcCommand },
|
||||
{ "hash", "", "Calculate the hash of a file", hex::plugin::builtin::handleHashCommand },
|
||||
{ "encode", "", "Encode a string", hex::plugin::builtin::handleEncodeCommand },
|
||||
@@ -87,6 +87,7 @@ IMHEX_PLUGIN_SUBCOMMANDS() {
|
||||
{ "debug-mode", "", "Enables debugging features", hex::plugin::builtin::handleDebugModeCommand, },
|
||||
{ "validate-plugin", "", "Validates that a plugin can be loaded", hex::plugin::builtin::handleValidatePluginCommand },
|
||||
{ "save-editor", "", "Opens a pattern file for save file editing", hex::plugin::builtin::handleSaveEditorCommand },
|
||||
{ "file-info", "i", "Displays information about a file", hex::plugin::builtin::handleFileInfoCommand },
|
||||
};
|
||||
|
||||
IMHEX_PLUGIN_SETUP_BUILTIN("Built-in", "WerWolv", "Default ImHex functionality") {
|
||||
|
||||
Reference in New Issue
Block a user