impr: Various fixes and an enhancement for the pattern editor (#1528)
Fixed console error messages using doc comment syntax highlights. Fixed results of find not updating when march case was toggled. Fixed syntax highlights of nested ifdefs. Fixed editor cursor blinks if OS focus goes to another window. Fixed Highlights of "\\\"" was incorrectly handled. --------- Co-authored-by: Nik <werwolv98@gmail.com>
This commit is contained in:
parent
f5987fde5a
commit
3b3701135f
@ -175,7 +175,7 @@ public:
|
|||||||
bool mCaseSensitive;
|
bool mCaseSensitive;
|
||||||
|
|
||||||
LanguageDefinition()
|
LanguageDefinition()
|
||||||
: mGlobalDocComment("/*!"), mDocComment("/**"), mPreprocChar('#'), mAutoIndentation(true), mTokenize(nullptr), mCaseSensitive(true)
|
: mPreprocChar('#'), mAutoIndentation(true), mTokenize(nullptr), mCaseSensitive(true)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -604,7 +604,7 @@ ImU32 TextEditor::GetGlyphColor(const Glyph &aGlyph) const {
|
|||||||
return mPalette[(int)PaletteIndex::Comment];
|
return mPalette[(int)PaletteIndex::Comment];
|
||||||
if (aGlyph.mMultiLineComment)
|
if (aGlyph.mMultiLineComment)
|
||||||
return mPalette[(int)PaletteIndex::MultiLineComment];
|
return mPalette[(int)PaletteIndex::MultiLineComment];
|
||||||
if (aGlyph.mDeactivated && !aGlyph.mPreprocessor)
|
if (aGlyph.mDeactivated)
|
||||||
return mPalette[(int)PaletteIndex::PreprocessorDeactivated];
|
return mPalette[(int)PaletteIndex::PreprocessorDeactivated];
|
||||||
auto const color = mPalette[(int)aGlyph.mColorIndex];
|
auto const color = mPalette[(int)aGlyph.mColorIndex];
|
||||||
if (aGlyph.mPreprocessor) {
|
if (aGlyph.mPreprocessor) {
|
||||||
@ -621,8 +621,18 @@ ImU32 TextEditor::GetGlyphColor(const Glyph &aGlyph) const {
|
|||||||
void TextEditor::HandleKeyboardInputs() {
|
void TextEditor::HandleKeyboardInputs() {
|
||||||
ImGuiIO &io = ImGui::GetIO();
|
ImGuiIO &io = ImGui::GetIO();
|
||||||
auto shift = io.KeyShift;
|
auto shift = io.KeyShift;
|
||||||
auto ctrl = io.ConfigMacOSXBehaviors ? io.KeySuper : io.KeyCtrl;
|
auto left = ImGui::IsKeyPressed(ImGui::GetKeyIndex(ImGuiKey_LeftArrow));
|
||||||
|
auto right = ImGui::IsKeyPressed(ImGui::GetKeyIndex(ImGuiKey_RightArrow));
|
||||||
|
auto up = ImGui::IsKeyPressed(ImGui::GetKeyIndex(ImGuiKey_UpArrow));
|
||||||
|
auto down = ImGui::IsKeyPressed(ImGui::GetKeyIndex(ImGuiKey_DownArrow));
|
||||||
|
auto ctrl = io.ConfigMacOSXBehaviors ? io.KeyAlt : io.KeyCtrl;
|
||||||
auto alt = io.ConfigMacOSXBehaviors ? io.KeyCtrl : io.KeyAlt;
|
auto alt = io.ConfigMacOSXBehaviors ? io.KeyCtrl : io.KeyAlt;
|
||||||
|
auto home = io.ConfigMacOSXBehaviors ? io.KeySuper && left : ImGui::IsKeyPressed(ImGui::GetKeyIndex(ImGuiKey_Home));
|
||||||
|
auto end = io.ConfigMacOSXBehaviors ? io.KeySuper && right : ImGui::IsKeyPressed(ImGui::GetKeyIndex(ImGuiKey_End));
|
||||||
|
auto top = io.ConfigMacOSXBehaviors ? io.KeySuper && up : ctrl && ImGui::IsKeyPressed(ImGui::GetKeyIndex(ImGuiKey_Home));
|
||||||
|
auto bottom = io.ConfigMacOSXBehaviors ? io.KeySuper && down : ctrl && ImGui::IsKeyPressed(ImGui::GetKeyIndex(ImGuiKey_End));
|
||||||
|
auto pageUp = io.ConfigMacOSXBehaviors ? ctrl && up : ImGui::IsKeyPressed(ImGui::GetKeyIndex(ImGuiKey_PageUp));
|
||||||
|
auto pageDown = io.ConfigMacOSXBehaviors ? ctrl && down : ImGui::IsKeyPressed(ImGui::GetKeyIndex(ImGuiKey_PageDown));
|
||||||
|
|
||||||
if (ImGui::IsWindowFocused()) {
|
if (ImGui::IsWindowFocused()) {
|
||||||
if (ImGui::IsWindowHovered())
|
if (ImGui::IsWindowHovered())
|
||||||
@ -638,25 +648,25 @@ void TextEditor::HandleKeyboardInputs() {
|
|||||||
Undo();
|
Undo();
|
||||||
else if (!IsReadOnly() && ctrl && !shift && !alt && ImGui::IsKeyPressed(ImGui::GetKeyIndex(ImGuiKey_Y)))
|
else if (!IsReadOnly() && ctrl && !shift && !alt && ImGui::IsKeyPressed(ImGui::GetKeyIndex(ImGuiKey_Y)))
|
||||||
Redo();
|
Redo();
|
||||||
else if (!ctrl && !alt && ImGui::IsKeyPressed(ImGui::GetKeyIndex(ImGuiKey_UpArrow)))
|
else if (!ctrl && !alt && up)
|
||||||
MoveUp(1, shift);
|
MoveUp(1, shift);
|
||||||
else if (!ctrl && !alt && ImGui::IsKeyPressed(ImGui::GetKeyIndex(ImGuiKey_DownArrow)))
|
else if (!ctrl && !alt && down)
|
||||||
MoveDown(1, shift);
|
MoveDown(1, shift);
|
||||||
else if (!alt && ImGui::IsKeyPressed(ImGui::GetKeyIndex(ImGuiKey_LeftArrow)))
|
else if (!alt && left)
|
||||||
MoveLeft(1, shift, ctrl);
|
MoveLeft(1, shift, ctrl);
|
||||||
else if (!alt && ImGui::IsKeyPressed(ImGui::GetKeyIndex(ImGuiKey_RightArrow)))
|
else if (!alt && right)
|
||||||
MoveRight(1, shift, ctrl);
|
MoveRight(1, shift, ctrl);
|
||||||
else if (!alt && ImGui::IsKeyPressed(ImGui::GetKeyIndex(ImGuiKey_PageUp)))
|
else if (!alt && pageUp)
|
||||||
MoveUp(GetPageSize() - 4, shift);
|
MoveUp(GetPageSize() - 4, shift);
|
||||||
else if (!alt && ImGui::IsKeyPressed(ImGui::GetKeyIndex(ImGuiKey_PageDown)))
|
else if (!alt && pageDown)
|
||||||
MoveDown(GetPageSize() - 4, shift);
|
MoveDown(GetPageSize() - 4, shift);
|
||||||
else if (!alt && ctrl && ImGui::IsKeyPressed(ImGui::GetKeyIndex(ImGuiKey_Home)))
|
else if (!alt && top)
|
||||||
MoveTop(shift);
|
MoveTop(shift);
|
||||||
else if (ctrl && !alt && ImGui::IsKeyPressed(ImGui::GetKeyIndex(ImGuiKey_End)))
|
else if (!alt && bottom)
|
||||||
MoveBottom(shift);
|
MoveBottom(shift);
|
||||||
else if (!ctrl && !alt && ImGui::IsKeyPressed(ImGui::GetKeyIndex(ImGuiKey_Home)))
|
else if (!ctrl && !alt && home)
|
||||||
MoveHome(shift);
|
MoveHome(shift);
|
||||||
else if (!ctrl && !alt && ImGui::IsKeyPressed(ImGui::GetKeyIndex(ImGuiKey_End)))
|
else if (!ctrl && !alt && end)
|
||||||
MoveEnd(shift);
|
MoveEnd(shift);
|
||||||
else if (!IsReadOnly() && !ctrl && !shift && !alt && ImGui::IsKeyPressed(ImGui::GetKeyIndex(ImGuiKey_Delete)))
|
else if (!IsReadOnly() && !ctrl && !shift && !alt && ImGui::IsKeyPressed(ImGui::GetKeyIndex(ImGuiKey_Delete)))
|
||||||
Delete();
|
Delete();
|
||||||
@ -722,7 +732,7 @@ void TextEditor::HandleKeyboardInputs() {
|
|||||||
void TextEditor::HandleMouseInputs() {
|
void TextEditor::HandleMouseInputs() {
|
||||||
ImGuiIO &io = ImGui::GetIO();
|
ImGuiIO &io = ImGui::GetIO();
|
||||||
auto shift = io.KeyShift;
|
auto shift = io.KeyShift;
|
||||||
auto ctrl = io.ConfigMacOSXBehaviors ? io.KeySuper : io.KeyCtrl;
|
auto ctrl = io.ConfigMacOSXBehaviors ? io.KeyAlt : io.KeyCtrl;
|
||||||
auto alt = io.ConfigMacOSXBehaviors ? io.KeyCtrl : io.KeyAlt;
|
auto alt = io.ConfigMacOSXBehaviors ? io.KeyCtrl : io.KeyAlt;
|
||||||
|
|
||||||
if (ImGui::IsWindowHovered()) {
|
if (ImGui::IsWindowHovered()) {
|
||||||
@ -905,7 +915,10 @@ void TextEditor::Render() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (mState.mCursorPosition.mLine == lineNo && mShowCursor) {
|
if (mState.mCursorPosition.mLine == lineNo && mShowCursor) {
|
||||||
auto focused = ImGui::IsWindowFocused();
|
bool focused = false;
|
||||||
|
ImGuiViewport *viewport = ImGui::GetWindowViewport();
|
||||||
|
if (viewport->PlatformUserData != NULL && ImGui::GetPlatformIO().Platform_GetWindowFocus(viewport))
|
||||||
|
focused = ImGui::IsWindowFocused();
|
||||||
|
|
||||||
// Highlight the current line (where the cursor is)
|
// Highlight the current line (where the cursor is)
|
||||||
if (!HasSelection()) {
|
if (!HasSelection()) {
|
||||||
@ -2505,6 +2518,7 @@ void TextEditor::ColorizeInternal() {
|
|||||||
auto firstChar = true; // there is no other non-whitespace characters in the line before
|
auto firstChar = true; // there is no other non-whitespace characters in the line before
|
||||||
auto currentLine = 0;
|
auto currentLine = 0;
|
||||||
auto currentIndex = 0;
|
auto currentIndex = 0;
|
||||||
|
auto commentLength = 0;
|
||||||
auto &startStr = mLanguageDefinition.mCommentStart;
|
auto &startStr = mLanguageDefinition.mCommentStart;
|
||||||
auto &singleStartStr = mLanguageDefinition.mSingleLineComment;
|
auto &singleStartStr = mLanguageDefinition.mSingleLineComment;
|
||||||
auto &docStartStr = mLanguageDefinition.mDocComment;
|
auto &docStartStr = mLanguageDefinition.mDocComment;
|
||||||
@ -2516,6 +2530,14 @@ void TextEditor::ColorizeInternal() {
|
|||||||
while (currentLine < endLine || currentIndex < endIndex) {
|
while (currentLine < endLine || currentIndex < endIndex) {
|
||||||
auto &line = mLines[currentLine];
|
auto &line = mLines[currentLine];
|
||||||
|
|
||||||
|
auto setGlyphFlags = [&](int index) {
|
||||||
|
line[index].mMultiLineComment = withinComment;
|
||||||
|
line[index].mComment = withinSingleLineComment;
|
||||||
|
line[index].mDocComment = withinDocComment;
|
||||||
|
line[index].mGlobalDocComment = withinGlobalDocComment;
|
||||||
|
line[index].mDeactivated = withinNotDef;
|
||||||
|
};
|
||||||
|
|
||||||
if (currentIndex == 0) {
|
if (currentIndex == 0) {
|
||||||
withinSingleLineComment = false;
|
withinSingleLineComment = false;
|
||||||
withinPreproc = false;
|
withinPreproc = false;
|
||||||
@ -2532,24 +2554,12 @@ void TextEditor::ColorizeInternal() {
|
|||||||
bool inComment = (commentStartLine < currentLine || (commentStartLine == currentLine && commentStartIndex <= currentIndex));
|
bool inComment = (commentStartLine < currentLine || (commentStartLine == currentLine && commentStartIndex <= currentIndex));
|
||||||
|
|
||||||
if (withinString) {
|
if (withinString) {
|
||||||
line[currentIndex].mMultiLineComment = withinComment;
|
setGlyphFlags(currentIndex);
|
||||||
line[currentIndex].mComment = withinSingleLineComment;
|
if (c == '\\') {
|
||||||
line[currentIndex].mDocComment = withinDocComment;
|
currentIndex++;
|
||||||
line[currentIndex].mGlobalDocComment = withinGlobalDocComment;
|
setGlyphFlags(currentIndex);
|
||||||
line[currentIndex].mDeactivated = withinNotDef;
|
} else if (c == '\"')
|
||||||
if (c == '\"') {
|
|
||||||
if (currentIndex > 2 && line[currentIndex - 1].mChar == '\\' && line[currentIndex - 2].mChar != '\\') {
|
|
||||||
currentIndex += 1;
|
|
||||||
if (currentIndex < (int)line.size()) {
|
|
||||||
line[currentIndex].mMultiLineComment = withinComment;
|
|
||||||
line[currentIndex].mComment = withinSingleLineComment;
|
|
||||||
line[currentIndex].mDocComment = withinDocComment;
|
|
||||||
line[currentIndex].mGlobalDocComment = withinGlobalDocComment;
|
|
||||||
line[currentIndex].mDeactivated = withinNotDef;
|
|
||||||
}
|
|
||||||
} else
|
|
||||||
withinString = false;
|
withinString = false;
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
if (firstChar && c == mLanguageDefinition.mPreprocChar) {
|
if (firstChar && c == mLanguageDefinition.mPreprocChar) {
|
||||||
withinPreproc = true;
|
withinPreproc = true;
|
||||||
@ -2594,7 +2604,6 @@ void TextEditor::ColorizeInternal() {
|
|||||||
}
|
}
|
||||||
if (!withinNotDef) {
|
if (!withinNotDef) {
|
||||||
bool isConditionMet = std::find(mDefines.begin(),mDefines.end(),identifier) != mDefines.end();
|
bool isConditionMet = std::find(mDefines.begin(),mDefines.end(),identifier) != mDefines.end();
|
||||||
withinNotDef = !isConditionMet;
|
|
||||||
ifDefs.push_back(isConditionMet);
|
ifDefs.push_back(isConditionMet);
|
||||||
} else
|
} else
|
||||||
ifDefs.push_back(false);
|
ifDefs.push_back(false);
|
||||||
@ -2608,7 +2617,6 @@ void TextEditor::ColorizeInternal() {
|
|||||||
}
|
}
|
||||||
if (!withinNotDef) {
|
if (!withinNotDef) {
|
||||||
bool isConditionMet = std::find(mDefines.begin(),mDefines.end(),identifier) == mDefines.end();
|
bool isConditionMet = std::find(mDefines.begin(),mDefines.end(),identifier) == mDefines.end();
|
||||||
withinNotDef = !isConditionMet;
|
|
||||||
ifDefs.push_back(isConditionMet);
|
ifDefs.push_back(isConditionMet);
|
||||||
} else
|
} else
|
||||||
ifDefs.push_back(false);
|
ifDefs.push_back(false);
|
||||||
@ -2616,20 +2624,17 @@ void TextEditor::ColorizeInternal() {
|
|||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (directive == "endif") {
|
if (directive == "endif") {
|
||||||
if (ifDefs.size() > 1)
|
if (ifDefs.size() > 1) {
|
||||||
ifDefs.pop_back();
|
ifDefs.pop_back();
|
||||||
withinNotDef = !ifDefs.back();
|
withinNotDef = !ifDefs.back();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (c == '\"') {
|
if (c == '\"') {
|
||||||
withinString = true;
|
withinString = true;
|
||||||
line[currentIndex].mMultiLineComment = withinComment;
|
setGlyphFlags(currentIndex);
|
||||||
line[currentIndex].mComment = withinSingleLineComment;
|
|
||||||
line[currentIndex].mDocComment = withinDocComment;
|
|
||||||
line[currentIndex].mGlobalDocComment = withinGlobalDocComment;
|
|
||||||
line[currentIndex].mDeactivated = withinNotDef;
|
|
||||||
} else {
|
} else {
|
||||||
auto pred = [](const char &a, const Glyph &b) { return a == b.mChar; };
|
auto pred = [](const char &a, const Glyph &b) { return a == b.mChar; };
|
||||||
|
|
||||||
@ -2653,29 +2658,30 @@ void TextEditor::ColorizeInternal() {
|
|||||||
if (isGlobalDocComment || isDocComment || isComment) {
|
if (isGlobalDocComment || isDocComment || isComment) {
|
||||||
commentStartLine = currentLine;
|
commentStartLine = currentLine;
|
||||||
commentStartIndex = currentIndex;
|
commentStartIndex = currentIndex;
|
||||||
if (isGlobalDocComment)
|
if (isGlobalDocComment) {
|
||||||
withinGlobalDocComment = true;
|
withinGlobalDocComment = true;
|
||||||
else if (isDocComment)
|
commentLength = 3;
|
||||||
|
} else if (isDocComment) {
|
||||||
withinDocComment = true;
|
withinDocComment = true;
|
||||||
else
|
commentLength = 3;
|
||||||
|
} else {
|
||||||
withinComment = true;
|
withinComment = true;
|
||||||
|
commentLength = 2;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
inComment = (commentStartLine < currentLine || (commentStartLine == currentLine && commentStartIndex <= currentIndex));
|
inComment = (commentStartLine < currentLine || (commentStartLine == currentLine && commentStartIndex <= currentIndex));
|
||||||
}
|
}
|
||||||
line[currentIndex].mGlobalDocComment = withinGlobalDocComment;
|
setGlyphFlags(currentIndex);
|
||||||
line[currentIndex].mDocComment = withinDocComment;
|
|
||||||
line[currentIndex].mMultiLineComment = withinComment;
|
|
||||||
line[currentIndex].mComment = withinSingleLineComment;
|
|
||||||
line[currentIndex].mDeactivated = withinNotDef;
|
|
||||||
|
|
||||||
auto &endStr = mLanguageDefinition.mCommentEnd;
|
auto &endStr = mLanguageDefinition.mCommentEnd;
|
||||||
if (compareBack(endStr, line)) {
|
if (compareBack(endStr, line) && ((commentStartLine != currentLine) || (commentStartIndex + commentLength < currentIndex))) {
|
||||||
withinComment = false;
|
withinComment = false;
|
||||||
withinDocComment = false;
|
withinDocComment = false;
|
||||||
withinGlobalDocComment = false;
|
withinGlobalDocComment = false;
|
||||||
commentStartLine = endLine;
|
commentStartLine = endLine;
|
||||||
commentStartIndex = endIndex;
|
commentStartIndex = endIndex;
|
||||||
|
commentLength = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -2684,6 +2690,7 @@ void TextEditor::ColorizeInternal() {
|
|||||||
|
|
||||||
currentIndex += UTF8CharLength(c);
|
currentIndex += UTF8CharLength(c);
|
||||||
if (currentIndex >= (int)line.size()) {
|
if (currentIndex >= (int)line.size()) {
|
||||||
|
withinNotDef = !ifDefs.back();
|
||||||
currentIndex = 0;
|
currentIndex = 0;
|
||||||
++currentLine;
|
++currentLine;
|
||||||
}
|
}
|
||||||
|
@ -14,6 +14,8 @@
|
|||||||
#include <functional>
|
#include <functional>
|
||||||
|
|
||||||
#include <TextEditor.h>
|
#include <TextEditor.h>
|
||||||
|
#include "popups/popup_file_chooser.hpp"
|
||||||
|
#include "hex/api/achievement_manager.hpp"
|
||||||
|
|
||||||
namespace pl::ptrn { class Pattern; }
|
namespace pl::ptrn { class Pattern; }
|
||||||
|
|
||||||
@ -255,6 +257,39 @@ namespace hex::plugin::builtin {
|
|||||||
void registerMenuItems();
|
void registerMenuItems();
|
||||||
void registerHandlers();
|
void registerHandlers();
|
||||||
|
|
||||||
|
std::function<void()> importPatternFile = [&] {
|
||||||
|
auto provider = ImHexApi::Provider::get();
|
||||||
|
const auto basePaths = fs::getDefaultPaths(fs::ImHexPath::Patterns);
|
||||||
|
std::vector<std::fs::path> paths;
|
||||||
|
|
||||||
|
for (const auto &imhexPath : basePaths) {
|
||||||
|
if (!wolv::io::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());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ui::PopupFileChooser::open(
|
||||||
|
basePaths, paths, std::vector<hex::fs::ItemFilter>{ { "Pattern File", "hexpat" } }, false,
|
||||||
|
[this, provider](const std::fs::path &path) {
|
||||||
|
this->loadPatternFile(path, provider);
|
||||||
|
AchievementManager::unlockAchievement("hex.builtin.achievement.patterns", "hex.builtin.achievement.patterns.load_existing.name");
|
||||||
|
}
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
std::function<void()> exportPatternFile = [&] {
|
||||||
|
fs::openFileBrowser(
|
||||||
|
fs::DialogMode::Save, { {"Pattern", "hexpat"} },
|
||||||
|
[this](const auto &path) {
|
||||||
|
wolv::io::File file(path, wolv::io::File::Mode::Create);
|
||||||
|
file.writeString(wolv::util::trim(m_textEditor.GetText()));
|
||||||
|
}
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
void appendEditorText(const std::string &text);
|
void appendEditorText(const std::string &text);
|
||||||
void appendVariable(const std::string &type);
|
void appendVariable(const std::string &type);
|
||||||
void appendArray(const std::string &type, size_t size);
|
void appendArray(const std::string &type, size_t size);
|
||||||
|
@ -135,6 +135,7 @@
|
|||||||
"hex.builtin.menu.file.export.ips32": "IPS32 Patch",
|
"hex.builtin.menu.file.export.ips32": "IPS32 Patch",
|
||||||
"hex.builtin.menu.file.export.bookmark": "Bookmark",
|
"hex.builtin.menu.file.export.bookmark": "Bookmark",
|
||||||
"hex.builtin.menu.file.export.pattern": "Pattern File",
|
"hex.builtin.menu.file.export.pattern": "Pattern File",
|
||||||
|
"hex.builtin.menu.file.export.pattern_file": "Export pattern File",
|
||||||
"hex.builtin.menu.file.export.data_processor": "Data Processor Workspace",
|
"hex.builtin.menu.file.export.data_processor": "Data Processor Workspace",
|
||||||
"hex.builtin.menu.file.export.popup.create": "Cannot export data. Failed to create file!",
|
"hex.builtin.menu.file.export.popup.create": "Cannot export data. Failed to create file!",
|
||||||
"hex.builtin.menu.file.export.report": "Report",
|
"hex.builtin.menu.file.export.report": "Report",
|
||||||
@ -147,6 +148,7 @@
|
|||||||
"hex.builtin.menu.file.import.modified_file": "Modified File",
|
"hex.builtin.menu.file.import.modified_file": "Modified File",
|
||||||
"hex.builtin.menu.file.import.bookmark": "Bookmark",
|
"hex.builtin.menu.file.import.bookmark": "Bookmark",
|
||||||
"hex.builtin.menu.file.import.pattern": "Pattern File",
|
"hex.builtin.menu.file.import.pattern": "Pattern File",
|
||||||
|
"hex.builtin.menu.file.import.pattern_file": "Import pattern File",
|
||||||
"hex.builtin.menu.file.import.data_processor": "Data Processor Workspace",
|
"hex.builtin.menu.file.import.data_processor": "Data Processor Workspace",
|
||||||
"hex.builtin.menu.file.import.custom_encoding": "Custom Encoding File",
|
"hex.builtin.menu.file.import.custom_encoding": "Custom Encoding File",
|
||||||
"hex.builtin.menu.file.import.modified_file.popup.invalid_size": "File selected do not have the same size as the current file. Both sizes must match",
|
"hex.builtin.menu.file.import.modified_file.popup.invalid_size": "File selected do not have the same size as the current file. Both sizes must match",
|
||||||
|
@ -3,13 +3,11 @@
|
|||||||
|
|
||||||
#include <hex/api/content_registry.hpp>
|
#include <hex/api/content_registry.hpp>
|
||||||
#include <hex/api/project_file_manager.hpp>
|
#include <hex/api/project_file_manager.hpp>
|
||||||
#include <hex/api/achievement_manager.hpp>
|
|
||||||
|
|
||||||
#include <pl/patterns/pattern.hpp>
|
#include <pl/patterns/pattern.hpp>
|
||||||
#include <pl/core/preprocessor.hpp>
|
#include <pl/core/preprocessor.hpp>
|
||||||
#include <pl/core/parser.hpp>
|
#include <pl/core/parser.hpp>
|
||||||
#include <pl/core/ast/ast_node_variable_decl.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>
|
#include <pl/core/ast/ast_node_builtin_type.hpp>
|
||||||
|
|
||||||
#include <hex/helpers/fs.hpp>
|
#include <hex/helpers/fs.hpp>
|
||||||
@ -22,11 +20,9 @@
|
|||||||
#include <hex/helpers/fmt.hpp>
|
#include <hex/helpers/fmt.hpp>
|
||||||
#include <fmt/chrono.h>
|
#include <fmt/chrono.h>
|
||||||
|
|
||||||
#include <popups/popup_file_chooser.hpp>
|
|
||||||
#include <popups/popup_question.hpp>
|
#include <popups/popup_question.hpp>
|
||||||
#include <toasts/toast_notification.hpp>
|
#include <toasts/toast_notification.hpp>
|
||||||
|
|
||||||
#include <nlohmann/json.hpp>
|
|
||||||
#include <chrono>
|
#include <chrono>
|
||||||
|
|
||||||
#include <wolv/io/file.hpp>
|
#include <wolv/io/file.hpp>
|
||||||
@ -34,6 +30,8 @@
|
|||||||
#include <wolv/utils/guards.hpp>
|
#include <wolv/utils/guards.hpp>
|
||||||
#include <wolv/utils/lock.hpp>
|
#include <wolv/utils/lock.hpp>
|
||||||
|
|
||||||
|
#include <content/global_actions.hpp>
|
||||||
|
|
||||||
namespace hex::plugin::builtin {
|
namespace hex::plugin::builtin {
|
||||||
|
|
||||||
using namespace hex::literals;
|
using namespace hex::literals;
|
||||||
@ -88,6 +86,9 @@ namespace hex::plugin::builtin {
|
|||||||
langDef.mAutoIndentation = true;
|
langDef.mAutoIndentation = true;
|
||||||
langDef.mPreprocChar = '#';
|
langDef.mPreprocChar = '#';
|
||||||
|
|
||||||
|
langDef.mGlobalDocComment = "/*!";
|
||||||
|
langDef.mDocComment = "/**";
|
||||||
|
|
||||||
langDef.mName = "Pattern Language";
|
langDef.mName = "Pattern Language";
|
||||||
|
|
||||||
initialized = true;
|
initialized = true;
|
||||||
@ -236,6 +237,14 @@ namespace hex::plugin::builtin {
|
|||||||
bool clickedMenuFind = false;
|
bool clickedMenuFind = false;
|
||||||
bool clickedMenuReplace = false;
|
bool clickedMenuReplace = false;
|
||||||
if (ImGui::BeginPopup("##pattern_editor_context_menu")) {
|
if (ImGui::BeginPopup("##pattern_editor_context_menu")) {
|
||||||
|
// no shortcut for this
|
||||||
|
if (ImGui::MenuItem("hex.builtin.menu.file.import.pattern_file"_lang, nullptr, false))
|
||||||
|
importPatternFile();
|
||||||
|
if (ImGui::MenuItem("hex.builtin.menu.file.export.pattern_file"_lang, nullptr, false))
|
||||||
|
exportPatternFile();
|
||||||
|
|
||||||
|
ImGui::Separator();
|
||||||
|
|
||||||
const bool hasSelection = m_textEditor.HasSelection();
|
const bool hasSelection = m_textEditor.HasSelection();
|
||||||
if (ImGui::MenuItem("hex.builtin.view.hex_editor.menu.edit.cut"_lang, Shortcut(CTRLCMD + Keys::X).toString().c_str(), false, hasSelection)) {
|
if (ImGui::MenuItem("hex.builtin.view.hex_editor.menu.edit.cut"_lang, Shortcut(CTRLCMD + Keys::X).toString().c_str(), false, hasSelection)) {
|
||||||
m_textEditor.Cut();
|
m_textEditor.Cut();
|
||||||
@ -306,6 +315,12 @@ namespace hex::plugin::builtin {
|
|||||||
m_replaceMode = true;
|
m_replaceMode = true;
|
||||||
openFindPopup = true;
|
openFindPopup = true;
|
||||||
}
|
}
|
||||||
|
if (ImGui::IsKeyPressed(ImGuiKey_S, false) && ImGui::GetIO().KeyAlt)
|
||||||
|
hex::plugin::builtin::saveProject();
|
||||||
|
if (ImGui::IsKeyPressed(ImGuiKey_O, false) && ImGui::GetIO().KeyAlt)
|
||||||
|
hex::plugin::builtin::openProject();
|
||||||
|
if (ImGui::IsKeyPressed(ImGuiKey_S, false) && ImGui::GetIO().KeyAlt && ImGui::GetIO().KeyShift)
|
||||||
|
hex::plugin::builtin::saveProjectAs();
|
||||||
}
|
}
|
||||||
|
|
||||||
static std::string findWord;
|
static std::string findWord;
|
||||||
@ -685,6 +700,8 @@ namespace hex::plugin::builtin {
|
|||||||
if (altCPressed)
|
if (altCPressed)
|
||||||
matchCase = !matchCase;
|
matchCase = !matchCase;
|
||||||
findReplaceHandler->SetMatchCase(&m_textEditor,matchCase);
|
findReplaceHandler->SetMatchCase(&m_textEditor,matchCase);
|
||||||
|
position = findReplaceHandler->FindPosition(&m_textEditor,m_textEditor.GetCursorPosition(), true);
|
||||||
|
count = findReplaceHandler->GetMatches().size();
|
||||||
updateCount = true;
|
updateCount = true;
|
||||||
requestFocusFind = true;
|
requestFocusFind = true;
|
||||||
}
|
}
|
||||||
@ -1733,39 +1750,11 @@ namespace hex::plugin::builtin {
|
|||||||
void ViewPatternEditor::registerMenuItems() {
|
void ViewPatternEditor::registerMenuItems() {
|
||||||
/* Import Pattern */
|
/* Import Pattern */
|
||||||
ContentRegistry::Interface::addMenuItem({ "hex.builtin.menu.file", "hex.builtin.menu.file.import", "hex.builtin.menu.file.import.pattern" }, ICON_VS_FILE_CODE, 4050, Shortcut::None,
|
ContentRegistry::Interface::addMenuItem({ "hex.builtin.menu.file", "hex.builtin.menu.file.import", "hex.builtin.menu.file.import.pattern" }, ICON_VS_FILE_CODE, 4050, Shortcut::None,
|
||||||
[this] {
|
importPatternFile, ImHexApi::Provider::isValid);
|
||||||
auto provider = ImHexApi::Provider::get();
|
|
||||||
const auto basePaths = fs::getDefaultPaths(fs::ImHexPath::Patterns);
|
|
||||||
std::vector<std::fs::path> paths;
|
|
||||||
|
|
||||||
for (const auto &imhexPath : basePaths) {
|
|
||||||
if (!wolv::io::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());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
ui::PopupFileChooser::open(basePaths, paths, std::vector<hex::fs::ItemFilter>{ { "Pattern File", "hexpat" } }, false,
|
|
||||||
[this, provider](const std::fs::path &path) {
|
|
||||||
this->loadPatternFile(path, provider);
|
|
||||||
AchievementManager::unlockAchievement("hex.builtin.achievement.patterns", "hex.builtin.achievement.patterns.load_existing.name");
|
|
||||||
});
|
|
||||||
}, ImHexApi::Provider::isValid);
|
|
||||||
|
|
||||||
/* Export Pattern */
|
/* Export Pattern */
|
||||||
ContentRegistry::Interface::addMenuItem({ "hex.builtin.menu.file", "hex.builtin.menu.file.export", "hex.builtin.menu.file.export.pattern" }, ICON_VS_FILE_CODE, 7050, Shortcut::None,
|
ContentRegistry::Interface::addMenuItem({ "hex.builtin.menu.file", "hex.builtin.menu.file.export", "hex.builtin.menu.file.export.pattern" }, ICON_VS_FILE_CODE, 7050, Shortcut::None,
|
||||||
[this] {
|
exportPatternFile, [this] {
|
||||||
fs::openFileBrowser(fs::DialogMode::Save, { {"Pattern", "hexpat"} },
|
|
||||||
[this](const auto &path) {
|
|
||||||
wolv::io::File file(path, wolv::io::File::Mode::Create);
|
|
||||||
|
|
||||||
file.writeString(wolv::util::trim(m_textEditor.GetText()));
|
|
||||||
});
|
|
||||||
}, [this] {
|
|
||||||
return !wolv::util::trim(m_textEditor.GetText()).empty() && ImHexApi::Provider::isValid();
|
return !wolv::util::trim(m_textEditor.GetText()).empty() && ImHexApi::Provider::isValid();
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user