1
0
mirror of synced 2025-01-19 01:24:15 +01:00

patterns: Added menu to Edit menu for placing types at current selection

This commit is contained in:
WerWolv 2022-10-21 10:03:37 +02:00
parent 6d08a4386d
commit 241b93aab5
13 changed files with 388 additions and 242 deletions

@ -1 +1 @@
Subproject commit 46f133bee5a2b5f2d465bb553204f76c088b4d54
Subproject commit 2233e1ab6b1a29be8ee6a2074c88b2c4ed40503b

View File

@ -201,6 +201,7 @@ namespace hex {
std::vector<std::string> splitString(const std::string &string, const std::string &delimiter);
std::string combineStrings(const std::vector<std::string> &strings, const std::string &delimiter = "");
std::string replaceStrings(std::string string, const std::string &search, const std::string &replace);
std::string toEngineeringString(double value);

View File

@ -232,6 +232,17 @@ namespace hex {
return result.substr(0, result.length() - delimiter.length());
}
std::string replaceStrings(std::string string, const std::string &search, const std::string &replace) {
if (search.empty())
return string;
std::size_t pos;
while ((pos = string.find(search)) != std::string::npos)
string.replace(pos, search.size(), replace);
return string;
}
std::string toEngineeringString(double value) {
constexpr static std::array Suffixes = { "a", "f", "p", "n", "u", "m", "", "k", "M", "G", "T", "P", "E" };

View File

@ -104,6 +104,10 @@ namespace hex::plugin::builtin {
void parsePattern(const std::string &code);
void evaluatePattern(const std::string &code);
void registerEvents();
void registerMenuItems();
void registerHandlers();
};
}

View File

@ -4,6 +4,7 @@
#include <pl/patterns/pattern.hpp>
#include <pl/core/preprocessor.hpp>
#include <pl/core/parser.hpp>
#include <pl/core/ast/ast_node_variable_decl.hpp>
#include <pl/core/ast/ast_node_type_decl.hpp>
#include <pl/core/ast/ast_node_builtin_type.hpp>
@ -17,6 +18,7 @@
#include <content/helpers/provider_extra_data.hpp>
#include <nlohmann/json.hpp>
#include <ranges>
namespace hex::plugin::builtin {
@ -89,247 +91,9 @@ namespace hex::plugin::builtin {
this->m_envVarEntries.push_back({ 0, "", 0, EnvVarType::Integer });
this->m_envVarIdCounter = 1;
EventManager::subscribe<RequestSetPatternLanguageCode>(this, [this](const std::string &code) {
this->m_textEditor.SetText(code);
});
EventManager::subscribe<EventSettingsChanged>(this, [this] {
{
auto syncPatternSource = ContentRegistry::Settings::getSetting("hex.builtin.setting.general", "hex.builtin.setting.general.sync_pattern_source");
if (syncPatternSource.is_number())
this->m_syncPatternSourceCode = static_cast<int>(syncPatternSource);
}
{
auto autoLoadPatterns = ContentRegistry::Settings::getSetting("hex.builtin.setting.general", "hex.builtin.setting.general.auto_load_patterns");
if (autoLoadPatterns.is_number())
this->m_autoLoadPatterns = static_cast<int>(autoLoadPatterns);
}
});
EventManager::subscribe<EventProviderOpened>(this, [this](prv::Provider *provider) {
auto &patternLanguageData = ProviderExtraData::get(provider).patternLanguage;
patternLanguageData.runtime = std::make_unique<pl::PatternLanguage>();
ContentRegistry::PatternLanguage::configureRuntime(*patternLanguageData.runtime, provider);
TaskManager::createBackgroundTask("Analyzing file content", [this, provider, &data = patternLanguageData](auto &) {
if (!this->m_autoLoadPatterns)
return;
// Copy over current pattern source code to the new provider
if (!this->m_syncPatternSourceCode) {
data.sourceCode = this->m_textEditor.GetText();
}
std::scoped_lock lock(data.runtimeMutex);
auto &runtime = data.runtime;
auto mimeType = magic::getMIMEType(provider);
bool foundCorrectType = false;
runtime->addPragma("MIME", [&mimeType, &foundCorrectType](pl::PatternLanguage &runtime, const std::string &value) {
hex::unused(runtime);
if (value == mimeType) {
foundCorrectType = true;
return true;
}
return !std::all_of(value.begin(), value.end(), isspace) && !value.ends_with('\n') && !value.ends_with('\r');
});
this->m_possiblePatternFiles.clear();
std::error_code errorCode;
for (const auto &dir : fs::getDefaultPaths(fs::ImHexPath::Patterns)) {
for (auto &entry : std::fs::recursive_directory_iterator(dir, errorCode)) {
foundCorrectType = false;
if (!entry.is_regular_file())
continue;
fs::File file(entry.path(), fs::File::Mode::Read);
if (!file.isValid())
continue;
runtime->getInternals().preprocessor->preprocess(*runtime, file.readString());
if (foundCorrectType)
this->m_possiblePatternFiles.push_back(entry.path());
runtime->reset();
}
}
runtime->addPragma("MIME", [](pl::PatternLanguage&, const std::string &value) { return !value.empty(); });
if (!this->m_possiblePatternFiles.empty()) {
this->m_selectedPatternFile = 0;
EventManager::post<RequestOpenPopup>("hex.builtin.view.pattern_editor.accept_pattern"_lang);
this->m_acceptPatternWindowOpen = true;
}
});
});
EventManager::subscribe<EventProviderChanged>(this, [this](prv::Provider *oldProvider, prv::Provider *newProvider) {
if (!this->m_syncPatternSourceCode) {
if (oldProvider != nullptr) ProviderExtraData::get(oldProvider).patternLanguage.sourceCode = this->m_textEditor.GetText();
if (newProvider != nullptr)
this->m_textEditor.SetText(ProviderExtraData::get(newProvider).patternLanguage.sourceCode);
else
this->m_textEditor.SetText("");
auto lines = this->m_textEditor.GetTextLines();
lines.pop_back();
this->m_textEditor.SetTextLines(lines);
}
});
/* Settings */
{
EventManager::subscribe<RequestChangeTheme>(this, [this](u32 theme) {
switch (theme) {
default:
case 1: /* Dark theme */
this->m_textEditor.SetPalette(TextEditor::GetDarkPalette());
break;
case 2: /* Light theme */
this->m_textEditor.SetPalette(TextEditor::GetLightPalette());
break;
case 3: /* Classic theme */
this->m_textEditor.SetPalette(TextEditor::GetRetroBluePalette());
break;
}
});
}
ContentRegistry::FileHandler::add({ ".hexpat", ".pat" }, [](const std::fs::path &path) -> bool {
fs::File file(path, fs::File::Mode::Read);
if (file.isValid()) {
EventManager::post<RequestSetPatternLanguageCode>(file.readString());
return true;
} else {
return false;
}
});
ContentRegistry::Interface::addMenuItem("hex.builtin.menu.file", 2000, [&, this] {
bool providerValid = ImHexApi::Provider::isValid();
if (ImGui::MenuItem("hex.builtin.view.pattern_editor.menu.file.load_pattern"_lang, nullptr, false, providerValid)) {
std::vector<std::fs::path> paths;
for (const auto &imhexPath : fs::getDefaultPaths(fs::ImHexPath::Patterns)) {
if (!fs::exists(imhexPath)) continue;
std::error_code error;
for (auto &entry : std::fs::recursive_directory_iterator(imhexPath, error)) {
if (entry.is_regular_file() && entry.path().extension() == ".hexpat") {
paths.push_back(entry.path());
}
}
}
View::showFileChooserPopup(paths, { {"Pattern File", "hexpat"} },
[this](const std::fs::path &path) {
this->loadPatternFile(path);
});
}
if (ImGui::MenuItem("hex.builtin.view.pattern_editor.menu.file.save_pattern"_lang, nullptr, false, providerValid)) {
fs::openFileBrowser(fs::DialogMode::Save, { {"Pattern", "hexpat"} },
[this](const auto &path) {
fs::File file(path, fs::File::Mode::Create);
file.write(this->m_textEditor.GetText());
});
}
});
ImHexApi::HexEditor::addBackgroundHighlightingProvider([this](u64 address, const u8 *data, size_t size, bool) -> std::optional<color_t> {
hex::unused(data, size);
if (this->m_runningEvaluators != 0)
return std::nullopt;
std::optional<ImColor> color;
for (const auto &pattern : ProviderExtraData::getCurrent().patternLanguage.runtime->getPatternsAtAddress(address)) {
if (pattern->isHidden())
continue;
if (color.has_value())
color = ImAlphaBlendColors(*color, pattern->getColor());
else
color = pattern->getColor();
}
return color;
});
ImHexApi::HexEditor::addTooltipProvider([this](u64 address, const u8 *data, size_t size) {
hex::unused(data, size);
auto patterns = ProviderExtraData::getCurrent().patternLanguage.runtime->getPatternsAtAddress(address);
if (!patterns.empty() && !std::all_of(patterns.begin(), patterns.end(), [](const auto &pattern) { return pattern->isHidden(); })) {
ImGui::BeginTooltip();
for (const auto &pattern : patterns) {
if (pattern->isHidden())
continue;
auto tooltipColor = (pattern->getColor() & 0x00FF'FFFF) | 0x7000'0000;
ImGui::PushID(pattern);
if (ImGui::BeginTable("##tooltips", 1, ImGuiTableFlags_RowBg | ImGuiTableFlags_NoClip)) {
ImGui::TableNextRow();
ImGui::TableNextColumn();
this->drawPatternTooltip(pattern);
ImGui::PushStyleColor(ImGuiCol_TableRowBg, tooltipColor);
ImGui::PushStyleColor(ImGuiCol_TableRowBgAlt, tooltipColor);
ImGui::EndTable();
ImGui::PopStyleColor(2);
}
ImGui::PopID();
}
ImGui::EndTooltip();
}
});
ProjectFile::registerPerProviderHandler({
.basePath = "pattern_source_code.hexpat",
.required = false,
.load = [this](prv::Provider *provider, const std::fs::path &basePath, Tar &tar) {
std::string sourceCode = tar.readString(basePath);
if (!this->m_syncPatternSourceCode)
ProviderExtraData::get(provider).patternLanguage.sourceCode = sourceCode;
if (provider == ImHexApi::Provider::get())
this->m_textEditor.SetText(sourceCode);
return true;
},
.store = [this](prv::Provider *provider, const std::fs::path &basePath, Tar &tar) {
std::string sourceCode;
if (provider == ImHexApi::Provider::get())
ProviderExtraData::get(provider).patternLanguage.sourceCode = this->m_textEditor.GetText();
if (this->m_syncPatternSourceCode)
sourceCode = this->m_textEditor.GetText();
else
sourceCode = ProviderExtraData::get(provider).patternLanguage.sourceCode;
tar.write(basePath, sourceCode);
return true;
}
});
this->registerEvents();
this->registerMenuItems();
this->registerHandlers();
}
ViewPatternEditor::~ViewPatternEditor() {
@ -871,4 +635,330 @@ namespace hex::plugin::builtin {
});
}
void ViewPatternEditor::registerEvents() {
EventManager::subscribe<RequestSetPatternLanguageCode>(this, [this](const std::string &code) {
this->m_textEditor.SetText(code);
});
EventManager::subscribe<EventSettingsChanged>(this, [this] {
{
auto syncPatternSource = ContentRegistry::Settings::getSetting("hex.builtin.setting.general", "hex.builtin.setting.general.sync_pattern_source");
if (syncPatternSource.is_number())
this->m_syncPatternSourceCode = static_cast<int>(syncPatternSource);
}
{
auto autoLoadPatterns = ContentRegistry::Settings::getSetting("hex.builtin.setting.general", "hex.builtin.setting.general.auto_load_patterns");
if (autoLoadPatterns.is_number())
this->m_autoLoadPatterns = static_cast<int>(autoLoadPatterns);
}
});
EventManager::subscribe<EventProviderOpened>(this, [this](prv::Provider *provider) {
auto &patternLanguageData = ProviderExtraData::get(provider).patternLanguage;
patternLanguageData.runtime = std::make_unique<pl::PatternLanguage>();
ContentRegistry::PatternLanguage::configureRuntime(*patternLanguageData.runtime, provider);
TaskManager::createBackgroundTask("Analyzing file content", [this, provider, &data = patternLanguageData](auto &) {
if (!this->m_autoLoadPatterns)
return;
// Copy over current pattern source code to the new provider
if (!this->m_syncPatternSourceCode) {
data.sourceCode = this->m_textEditor.GetText();
}
std::scoped_lock lock(data.runtimeMutex);
auto &runtime = data.runtime;
auto mimeType = magic::getMIMEType(provider);
bool foundCorrectType = false;
runtime->addPragma("MIME", [&mimeType, &foundCorrectType](pl::PatternLanguage &runtime, const std::string &value) {
hex::unused(runtime);
if (value == mimeType) {
foundCorrectType = true;
return true;
}
return !std::all_of(value.begin(), value.end(), isspace) && !value.ends_with('\n') && !value.ends_with('\r');
});
this->m_possiblePatternFiles.clear();
std::error_code errorCode;
for (const auto &dir : fs::getDefaultPaths(fs::ImHexPath::Patterns)) {
for (auto &entry : std::fs::recursive_directory_iterator(dir, errorCode)) {
foundCorrectType = false;
if (!entry.is_regular_file())
continue;
fs::File file(entry.path(), fs::File::Mode::Read);
if (!file.isValid())
continue;
runtime->getInternals().preprocessor->preprocess(*runtime, file.readString());
if (foundCorrectType)
this->m_possiblePatternFiles.push_back(entry.path());
runtime->reset();
}
}
runtime->addPragma("MIME", [](pl::PatternLanguage&, const std::string &value) { return !value.empty(); });
if (!this->m_possiblePatternFiles.empty()) {
this->m_selectedPatternFile = 0;
EventManager::post<RequestOpenPopup>("hex.builtin.view.pattern_editor.accept_pattern"_lang);
this->m_acceptPatternWindowOpen = true;
}
});
});
EventManager::subscribe<EventProviderChanged>(this, [this](prv::Provider *oldProvider, prv::Provider *newProvider) {
if (!this->m_syncPatternSourceCode) {
if (oldProvider != nullptr) ProviderExtraData::get(oldProvider).patternLanguage.sourceCode = this->m_textEditor.GetText();
if (newProvider != nullptr)
this->m_textEditor.SetText(ProviderExtraData::get(newProvider).patternLanguage.sourceCode);
else
this->m_textEditor.SetText("");
auto lines = this->m_textEditor.GetTextLines();
lines.pop_back();
this->m_textEditor.SetTextLines(lines);
}
});
EventManager::subscribe<RequestChangeTheme>(this, [this](u32 theme) {
switch (theme) {
default:
case 1: /* Dark theme */
this->m_textEditor.SetPalette(TextEditor::GetDarkPalette());
break;
case 2: /* Light theme */
this->m_textEditor.SetPalette(TextEditor::GetLightPalette());
break;
case 3: /* Classic theme */
this->m_textEditor.SetPalette(TextEditor::GetRetroBluePalette());
break;
}
});
}
static void createNestedMenu(const std::vector<std::string> &menus, const std::function<void()> &function) {
if (menus.empty())
return;
if (menus.size() == 1) {
if (ImGui::MenuItem(menus.front().c_str()))
function();
} else {
if (ImGui::BeginMenu(menus.front().c_str())) {
createNestedMenu({ menus.begin() + 1, menus.end() }, function);
ImGui::EndMenu();
}
}
}
void ViewPatternEditor::registerMenuItems() {
ContentRegistry::Interface::addMenuItem("hex.builtin.menu.file", 2000, [&, this] {
bool providerValid = ImHexApi::Provider::isValid();
if (ImGui::MenuItem("hex.builtin.view.pattern_editor.menu.file.load_pattern"_lang, nullptr, false, providerValid)) {
std::vector<std::fs::path> paths;
for (const auto &imhexPath : fs::getDefaultPaths(fs::ImHexPath::Patterns)) {
if (!fs::exists(imhexPath)) continue;
std::error_code error;
for (auto &entry : std::fs::recursive_directory_iterator(imhexPath, error)) {
if (entry.is_regular_file() && entry.path().extension() == ".hexpat") {
paths.push_back(entry.path());
}
}
}
View::showFileChooserPopup(paths, { {"Pattern File", "hexpat"} },
[this](const std::fs::path &path) {
this->loadPatternFile(path);
});
}
if (ImGui::MenuItem("hex.builtin.view.pattern_editor.menu.file.save_pattern"_lang, nullptr, false, providerValid)) {
fs::openFileBrowser(fs::DialogMode::Save, { {"Pattern", "hexpat"} },
[this](const auto &path) {
fs::File file(path, fs::File::Mode::Create);
file.write(this->m_textEditor.GetText());
});
}
});
// Place Pattern Type...
ContentRegistry::Interface::addMenuItem("hex.builtin.menu.edit", 3000, [this] {
bool available = ImHexApi::Provider::isValid() && ImHexApi::HexEditor::isSelectionValid() && this->m_runningParsers == 0;
auto selection = ImHexApi::HexEditor::getSelection();
const auto &types = this->m_parserRuntime->getInternals().parser->getTypes();
const auto appendEditorText = [this](const std::string &text){
this->m_textEditor.SetCursorPosition(TextEditor::Coordinates { this->m_textEditor.GetTotalLines(), 0 });
this->m_textEditor.InsertText(hex::format("\n{0}", text));
this->m_hasUnevaluatedChanges = true;
};
const auto appendVariable = [&](const std::string &type) {
appendEditorText(hex::format("{0} {0}_at_0x{1:02X} @ 0x{1:02X};", type, selection->getStartAddress()));
};
const auto appendArray = [&](const std::string &type, size_t size) {
appendEditorText(hex::format("{0} {0}_array_at_0x{1:02X}[0x{2:02X}] @ 0x{1:02X};", type, selection->getStartAddress(), (selection->getSize() + (size - 1)) / size));
};
if (ImGui::BeginMenu("hex.builtin.view.pattern_editor.menu.edit.place_pattern"_lang, available)) {
if (ImGui::BeginMenu("hex.builtin.view.pattern_editor.menu.edit.place_pattern.builtin"_lang)) {
constexpr static std::array<std::pair<const char *, size_t>, 21> Types = {{
{ "u8", 1 }, { "u16", 2 }, { "u24", 3 }, { "u32", 4 }, { "u48", 6 }, { "u64", 8 }, { "u96", 12 }, { "u128", 16 },
{ "s8", 1 }, { "s16", 2 }, { "s24", 3 }, { "s32", 4 }, { "s48", 6 }, { "s64", 8 }, { "s96", 12 }, { "s128", 16 },
{ "float", 4 }, { "double", 8 },
{ "bool", 1 }, { "char", 1 }, { "char16", 2 }
}};
if (ImGui::BeginMenu("hex.builtin.view.pattern_editor.menu.edit.place_pattern.builtin.single"_lang)) {
for (const auto &[type, size] : Types)
if (ImGui::MenuItem(type))
appendVariable(type);
ImGui::EndMenu();
}
if (ImGui::BeginMenu("hex.builtin.view.pattern_editor.menu.edit.place_pattern.builtin.array"_lang)) {
for (const auto &[type, size] : Types)
if (ImGui::MenuItem(type))
appendArray(type, size);
ImGui::EndMenu();
}
ImGui::EndMenu();
}
if (ImGui::BeginMenu("hex.builtin.view.pattern_editor.menu.edit.place_pattern.custom"_lang, !types.empty())) {
for (const auto &[typeName, type] : types) {
if (type->isTemplateType())
continue;
createNestedMenu(hex::splitString(typeName, "::"), [&] {
std::string variableName;
for (char &c : hex::replaceStrings(typeName, "::", "_"))
variableName += static_cast<char>(std::tolower(c));
variableName += hex::format("_at_0x{:02X}", selection->getStartAddress());
appendEditorText(hex::format("{0} {1} @ 0x{2:02X};", typeName, variableName, selection->getStartAddress()));
});
}
ImGui::EndMenu();
}
ImGui::EndMenu();
}
});
}
void ViewPatternEditor::registerHandlers() {
ContentRegistry::FileHandler::add({ ".hexpat", ".pat" }, [](const std::fs::path &path) -> bool {
fs::File file(path, fs::File::Mode::Read);
if (file.isValid()) {
EventManager::post<RequestSetPatternLanguageCode>(file.readString());
return true;
} else {
return false;
}
});
ImHexApi::HexEditor::addBackgroundHighlightingProvider([this](u64 address, const u8 *data, size_t size, bool) -> std::optional<color_t> {
hex::unused(data, size);
if (this->m_runningEvaluators != 0)
return std::nullopt;
std::optional<ImColor> color;
for (const auto &pattern : ProviderExtraData::getCurrent().patternLanguage.runtime->getPatternsAtAddress(address)) {
if (pattern->isHidden())
continue;
if (color.has_value())
color = ImAlphaBlendColors(*color, pattern->getColor());
else
color = pattern->getColor();
}
return color;
});
ImHexApi::HexEditor::addTooltipProvider([this](u64 address, const u8 *data, size_t size) {
hex::unused(data, size);
auto patterns = ProviderExtraData::getCurrent().patternLanguage.runtime->getPatternsAtAddress(address);
if (!patterns.empty() && !std::all_of(patterns.begin(), patterns.end(), [](const auto &pattern) { return pattern->isHidden(); })) {
ImGui::BeginTooltip();
for (const auto &pattern : patterns) {
if (pattern->isHidden())
continue;
auto tooltipColor = (pattern->getColor() & 0x00FF'FFFF) | 0x7000'0000;
ImGui::PushID(pattern);
if (ImGui::BeginTable("##tooltips", 1, ImGuiTableFlags_RowBg | ImGuiTableFlags_NoClip)) {
ImGui::TableNextRow();
ImGui::TableNextColumn();
this->drawPatternTooltip(pattern);
ImGui::PushStyleColor(ImGuiCol_TableRowBg, tooltipColor);
ImGui::PushStyleColor(ImGuiCol_TableRowBgAlt, tooltipColor);
ImGui::EndTable();
ImGui::PopStyleColor(2);
}
ImGui::PopID();
}
ImGui::EndTooltip();
}
});
ProjectFile::registerPerProviderHandler({
.basePath = "pattern_source_code.hexpat",
.required = false,
.load = [this](prv::Provider *provider, const std::fs::path &basePath, Tar &tar) {
std::string sourceCode = tar.readString(basePath);
if (!this->m_syncPatternSourceCode)
ProviderExtraData::get(provider).patternLanguage.sourceCode = sourceCode;
if (provider == ImHexApi::Provider::get())
this->m_textEditor.SetText(sourceCode);
return true;
},
.store = [this](prv::Provider *provider, const std::fs::path &basePath, Tar &tar) {
std::string sourceCode;
if (provider == ImHexApi::Provider::get())
ProviderExtraData::get(provider).patternLanguage.sourceCode = this->m_textEditor.GetText();
if (this->m_syncPatternSourceCode)
sourceCode = this->m_textEditor.GetText();
else
sourceCode = ProviderExtraData::get(provider).patternLanguage.sourceCode;
tar.write(basePath, sourceCode);
return true;
}
});
}
}

View File

@ -374,6 +374,11 @@ namespace hex::plugin::builtin {
{ "hex.builtin.view.pattern_editor.accept_pattern.question", "Ausgewähltes Pattern anwenden?" },
{ "hex.builtin.view.pattern_editor.menu.file.load_pattern", "Pattern laden..." },
{ "hex.builtin.view.pattern_editor.menu.file.save_pattern", "Pattern speichern..." },
{ "hex.builtin.view.pattern_editor.menu.edit.place_pattern", "Pattern platzieren..." },
{ "hex.builtin.view.pattern_editor.menu.edit.place_pattern.builtin", "Built-in Type" },
{ "hex.builtin.view.pattern_editor.menu.edit.place_pattern.builtin.single", "Einzeln" },
{ "hex.builtin.view.pattern_editor.menu.edit.place_pattern.builtin.array", "Array" },
{ "hex.builtin.view.pattern_editor.menu.edit.place_pattern.custom", "Benutzerdefinierter Type" },
{ "hex.builtin.view.pattern_editor.open_pattern", "Pattern öffnen" },
{ "hex.builtin.view.pattern_editor.evaluating", "Evaluieren..." },
{ "hex.builtin.view.pattern_editor.auto", "Auto evaluieren" },

View File

@ -377,6 +377,11 @@ namespace hex::plugin::builtin {
{ "hex.builtin.view.pattern_editor.accept_pattern.question", "Do you want to apply the selected pattern?" },
{ "hex.builtin.view.pattern_editor.menu.file.load_pattern", "Load pattern..." },
{ "hex.builtin.view.pattern_editor.menu.file.save_pattern", "Save pattern..." },
{ "hex.builtin.view.pattern_editor.menu.edit.place_pattern", "Place pattern..." },
{ "hex.builtin.view.pattern_editor.menu.edit.place_pattern.builtin", "Built-in Type" },
{ "hex.builtin.view.pattern_editor.menu.edit.place_pattern.builtin.single", "Single" },
{ "hex.builtin.view.pattern_editor.menu.edit.place_pattern.builtin.array", "Array" },
{ "hex.builtin.view.pattern_editor.menu.edit.place_pattern.custom", "Custom Type" },
{ "hex.builtin.view.pattern_editor.open_pattern", "Open pattern" },
{ "hex.builtin.view.pattern_editor.evaluating", "Evaluating..." },
{ "hex.builtin.view.pattern_editor.auto", "Auto evaluate" },

View File

@ -380,6 +380,11 @@ namespace hex::plugin::builtin {
{ "hex.builtin.view.pattern_editor.accept_pattern.question", "Vuoi applicare i patter selezionati" },
{ "hex.builtin.view.pattern_editor.menu.file.load_pattern", "Caricamento dei pattern..." },
{ "hex.builtin.view.pattern_editor.menu.file.save_pattern", "Salva pattern..." },
//{ "hex.builtin.view.pattern_editor.menu.edit.place_pattern", "Place pattern..." },
// { "hex.builtin.view.pattern_editor.menu.edit.place_pattern.builtin", "Built-in Type" },
// { "hex.builtin.view.pattern_editor.menu.edit.place_pattern.builtin.single", "Single" },
// { "hex.builtin.view.pattern_editor.menu.edit.place_pattern.builtin.array", "Array" },
// { "hex.builtin.view.pattern_editor.menu.edit.place_pattern.custom", "Custom Type" },
{ "hex.builtin.view.pattern_editor.open_pattern", "Apri pattern" },
{ "hex.builtin.view.pattern_editor.evaluating", "Valutazione..." },
{ "hex.builtin.view.pattern_editor.auto", "Auto valutazione" },

View File

@ -379,6 +379,11 @@ namespace hex::plugin::builtin {
{ "hex.builtin.view.pattern_editor.accept_pattern.question", "選択したパターンを反映してよろしいですか?" },
{ "hex.builtin.view.pattern_editor.menu.file.load_pattern", "パターンを読み込み…" },
{ "hex.builtin.view.pattern_editor.menu.file.save_pattern", "パターンを保存…" },
//{ "hex.builtin.view.pattern_editor.menu.edit.place_pattern", "Place pattern..." },
// { "hex.builtin.view.pattern_editor.menu.edit.place_pattern.builtin", "Built-in Type" },
// { "hex.builtin.view.pattern_editor.menu.edit.place_pattern.builtin.single", "Single" },
// { "hex.builtin.view.pattern_editor.menu.edit.place_pattern.builtin.array", "Array" },
// { "hex.builtin.view.pattern_editor.menu.edit.place_pattern.custom", "Custom Type" },
{ "hex.builtin.view.pattern_editor.open_pattern", "パターンを開く" },
{ "hex.builtin.view.pattern_editor.evaluating", "実行中…" }, //?
{ "hex.builtin.view.pattern_editor.auto", "常に実行" }, //?

View File

@ -376,6 +376,11 @@ namespace hex::plugin::builtin {
{ "hex.builtin.view.pattern_editor.accept_pattern.question", "선택한 패턴을 적용하시겠습니까?" },
{ "hex.builtin.view.pattern_editor.menu.file.load_pattern", "패턴 불러오기..." },
{ "hex.builtin.view.pattern_editor.menu.file.save_pattern", "패턴 저장하기..." },
//{ "hex.builtin.view.pattern_editor.menu.edit.place_pattern", "Place pattern..." },
// { "hex.builtin.view.pattern_editor.menu.edit.place_pattern.builtin", "Built-in Type" },
// { "hex.builtin.view.pattern_editor.menu.edit.place_pattern.builtin.single", "Single" },
// { "hex.builtin.view.pattern_editor.menu.edit.place_pattern.builtin.array", "Array" },
// { "hex.builtin.view.pattern_editor.menu.edit.place_pattern.custom", "Custom Type" },
{ "hex.builtin.view.pattern_editor.open_pattern", "패턴 열기" },
{ "hex.builtin.view.pattern_editor.evaluating", "평가 중..." },
{ "hex.builtin.view.pattern_editor.auto", "자동 평가" },

View File

@ -376,6 +376,11 @@ namespace hex::plugin::builtin {
{ "hex.builtin.view.pattern_editor.accept_pattern.question", "Deseja aplicar o padrão selecionado?" },
{ "hex.builtin.view.pattern_editor.menu.file.load_pattern", "Carregando padrão..." },
{ "hex.builtin.view.pattern_editor.menu.file.save_pattern", "Salvando padrão..." },
//{ "hex.builtin.view.pattern_editor.menu.edit.place_pattern", "Place pattern..." },
// { "hex.builtin.view.pattern_editor.menu.edit.place_pattern.builtin", "Built-in Type" },
// { "hex.builtin.view.pattern_editor.menu.edit.place_pattern.builtin.single", "Single" },
// { "hex.builtin.view.pattern_editor.menu.edit.place_pattern.builtin.array", "Array" },
// { "hex.builtin.view.pattern_editor.menu.edit.place_pattern.custom", "Custom Type" },
{ "hex.builtin.view.pattern_editor.open_pattern", "Abrir padrão" },
{ "hex.builtin.view.pattern_editor.evaluating", "Avaliando..." },
{ "hex.builtin.view.pattern_editor.auto", "Auto Avaliar" },

View File

@ -379,6 +379,11 @@ namespace hex::plugin::builtin {
{ "hex.builtin.view.pattern_editor.accept_pattern.question", "是否应用找到的模式?" },
{ "hex.builtin.view.pattern_editor.menu.file.load_pattern", "加载模式文件..." },
{ "hex.builtin.view.pattern_editor.menu.file.save_pattern", "保存模式文件..." },
//{ "hex.builtin.view.pattern_editor.menu.edit.place_pattern", "Place pattern..." },
// { "hex.builtin.view.pattern_editor.menu.edit.place_pattern.builtin", "Built-in Type" },
// { "hex.builtin.view.pattern_editor.menu.edit.place_pattern.builtin.single", "Single" },
// { "hex.builtin.view.pattern_editor.menu.edit.place_pattern.builtin.array", "Array" },
// { "hex.builtin.view.pattern_editor.menu.edit.place_pattern.custom", "Custom Type" },
{ "hex.builtin.view.pattern_editor.open_pattern", "打开模式" },
{ "hex.builtin.view.pattern_editor.evaluating", "计算中..." },
{ "hex.builtin.view.pattern_editor.auto", "自动计算" },

View File

@ -376,6 +376,11 @@ namespace hex::plugin::builtin {
{ "hex.builtin.view.pattern_editor.accept_pattern.question", "Do you want to apply the selected pattern?" },
{ "hex.builtin.view.pattern_editor.menu.file.load_pattern", "載入模式..." },
{ "hex.builtin.view.pattern_editor.menu.file.save_pattern", "儲存模式..." },
//{ "hex.builtin.view.pattern_editor.menu.edit.place_pattern", "Place pattern..." },
// { "hex.builtin.view.pattern_editor.menu.edit.place_pattern.builtin", "Built-in Type" },
// { "hex.builtin.view.pattern_editor.menu.edit.place_pattern.builtin.single", "Single" },
// { "hex.builtin.view.pattern_editor.menu.edit.place_pattern.builtin.array", "Array" },
// { "hex.builtin.view.pattern_editor.menu.edit.place_pattern.custom", "Custom Type" },
{ "hex.builtin.view.pattern_editor.open_pattern", "開啟模式" },
{ "hex.builtin.view.pattern_editor.evaluating", "Evaluating..." },
{ "hex.builtin.view.pattern_editor.auto", "Auto evaluate" },