diff --git a/cmake/build_helpers.cmake b/cmake/build_helpers.cmake index 8cbbdd94b..1ee82a933 100644 --- a/cmake/build_helpers.cmake +++ b/cmake/build_helpers.cmake @@ -268,7 +268,7 @@ macro(setDefaultBuiltTypeIfUnset) endmacro() macro(detectBadClone) - file (GLOB EXTERNAL_DIRS "external/*") + file (GLOB EXTERNAL_DIRS "lib/external/*") foreach (EXTERNAL_DIR ${EXTERNAL_DIRS}) file(GLOB RESULT "${EXTERNAL_DIR}/*") list(LENGTH RESULT ENTRY_COUNT) diff --git a/lib/external/imgui/include/imconfig.h b/lib/external/imgui/include/imconfig.h index 1f707d847..b4801ec23 100644 --- a/lib/external/imgui/include/imconfig.h +++ b/lib/external/imgui/include/imconfig.h @@ -47,6 +47,7 @@ //#define IMGUI_DISABLE_DEFAULT_FILE_FUNCTIONS // Don't implement ImFileOpen/ImFileClose/ImFileRead/ImFileWrite and ImFileHandle so you can implement them yourself if you don't want to link with fopen/fclose/fread/fwrite. This will also disable the LogToTTY() function. //#define IMGUI_DISABLE_DEFAULT_ALLOCATORS // Don't implement default allocators calling malloc()/free() to avoid linking with them. You will need to call ImGui::SetAllocatorFunctions(). //#define IMGUI_DISABLE_SSE // Disable use of SSE intrinsics even if available +#define IMGUI_DEFINE_MATH_OPERATORS //---- Include imgui_user.h at the end of imgui.h as a convenience //#define IMGUI_INCLUDE_IMGUI_USER_H diff --git a/lib/libimhex/CMakeLists.txt b/lib/libimhex/CMakeLists.txt index c23cd3620..e18dee512 100644 --- a/lib/libimhex/CMakeLists.txt +++ b/lib/libimhex/CMakeLists.txt @@ -105,6 +105,8 @@ set(LIBIMHEX_SOURCES source/api/content_registry.cpp source/api/task.cpp source/api/keybinding.cpp + source/api/plugin_manager.cpp + source/api/localization.cpp source/data_processor/attribute.cpp source/data_processor/link.cpp @@ -113,9 +115,7 @@ set(LIBIMHEX_SOURCES source/helpers/utils.cpp source/helpers/paths.cpp source/helpers/magic.cpp - source/helpers/shared_data.cpp source/helpers/crypto.cpp - source/helpers/lang.cpp source/helpers/net.cpp source/helpers/file.cpp source/helpers/socket.cpp @@ -136,8 +136,7 @@ set(LIBIMHEX_SOURCES source/providers/provider.cpp source/ui/imgui_imhex_extensions.cpp - - source/views/view.cpp + source/ui/view.cpp ) if (APPLE) @@ -164,4 +163,4 @@ if (APPLE) target_link_libraries(libimhex PUBLIC ${FOUNDATION}) endif () -target_link_libraries(libimhex PUBLIC imgui nfd magic ${CAPSTONE_LIBRARIES} LLVMDemangle microtar ${NLOHMANN_JSON_LIBRARIES} ${YARA_LIBRARIES} ${LIBCURL_LIBRARIES} ${MBEDTLS_LIBRARIES} ${FMT_LIBRARIES} ${Python_LIBRARIES} libromfs) +target_link_libraries(libimhex PUBLIC dl imgui nfd magic ${CAPSTONE_LIBRARIES} LLVMDemangle microtar ${NLOHMANN_JSON_LIBRARIES} ${YARA_LIBRARIES} ${LIBCURL_LIBRARIES} ${MBEDTLS_LIBRARIES} ${FMT_LIBRARIES} ${Python_LIBRARIES} libromfs) diff --git a/lib/libimhex/include/hex.hpp b/lib/libimhex/include/hex.hpp index d1e67116a..0283742ab 100644 --- a/lib/libimhex/include/hex.hpp +++ b/lib/libimhex/include/hex.hpp @@ -18,6 +18,8 @@ using i32 = std::int32_t; using i64 = std::int64_t; using i128 = __int128_t; +using color_t = u32; + namespace hex { struct Region { diff --git a/lib/libimhex/include/hex/api/content_registry.hpp b/lib/libimhex/include/hex/api/content_registry.hpp index e008eb253..ea99c799d 100644 --- a/lib/libimhex/include/hex/api/content_registry.hpp +++ b/lib/libimhex/include/hex/api/content_registry.hpp @@ -92,6 +92,15 @@ namespace hex { /* Pattern Language Function Registry. Allows adding of new functions that may be used inside the pattern language */ namespace PatternLanguage { + namespace impl { + + struct ColorPalette { + std::string name; + std::vector colors; + }; + + } + constexpr static u32 UnlimitedParameters = 0xFFFF'FFFF; constexpr static u32 MoreParametersThan = 0x8000'0000; constexpr static u32 LessParametersThan = 0x4000'0000; @@ -110,6 +119,12 @@ namespace hex { void addFunction(const Namespace &ns, const std::string &name, u32 parameterCount, const Callback &func); void addDangerousFunction(const Namespace &ns, const std::string &name, u32 parameterCount, const Callback &func); std::map &getFunctions(); + + std::vector& getPalettes(); + void addColorPalette(const std::string &unlocalizedName, const std::vector &colors); + void setSelectedPalette(u32 index); + u32 getNextColor(); + void resetPalette(); } /* View Registry. Allows adding of new windows */ @@ -249,8 +264,6 @@ namespace hex { } - u32 getDockSpaceId(); - void registerMainMenuItem(const std::string &unlocalizedName, u32 priority); void addMenuItem(const std::string &unlocalizedMainMenuName, u32 priority, const impl::DrawCallback &function); @@ -298,7 +311,7 @@ namespace hex { impl::addProviderName(unlocalizedName); } - const std::vector &getEntries(); + std::vector &getEntries(); } diff --git a/lib/libimhex/include/hex/api/event.hpp b/lib/libimhex/include/hex/api/event.hpp index 1c7127f0d..617ae7141 100644 --- a/lib/libimhex/include/hex/api/event.hpp +++ b/lib/libimhex/include/hex/api/event.hpp @@ -113,12 +113,13 @@ namespace hex { EVENT_DEF(EventAbnormalTermination, int); EVENT_DEF(EventOSThemeChanged); EVENT_DEF(EventProviderCreated, prv::Provider *); + EVENT_DEF(EventProviderChanged, prv::Provider *, prv::Provider *); EVENT_DEF(EventFrameBegin); EVENT_DEF(EventFrameEnd); EVENT_DEF(RequestOpenWindow, std::string); EVENT_DEF(RequestSelectionChange, Region); - EVENT_DEF(RequestAddBookmark, ImHexApi::Bookmarks::Entry); + EVENT_DEF(RequestAddBookmark, Region, std::string, std::string, color_t); EVENT_DEF(RequestSetPatternLanguageCode, std::string); EVENT_DEF(RequestChangeWindowTitle, std::string); EVENT_DEF(RequestCloseImHex, bool); diff --git a/lib/libimhex/include/hex/api/imhex_api.hpp b/lib/libimhex/include/hex/api/imhex_api.hpp index ffbd36203..6101fe0ff 100644 --- a/lib/libimhex/include/hex/api/imhex_api.hpp +++ b/lib/libimhex/include/hex/api/imhex_api.hpp @@ -10,6 +10,8 @@ #include #include +#include + namespace hex { namespace prv { @@ -17,34 +19,62 @@ namespace hex { } namespace ImHexApi { + namespace Common { void closeImHex(bool noQuestions = false); void restartImHex(); - }; + } + + namespace HexEditor { + + class Highlighting { + public: + Highlighting() = default; + Highlighting(Region region, color_t color, const std::string &tooltip = ""); + + [[nodiscard]] const Region &getRegion() const { return this->m_region; } + [[nodiscard]] const color_t &getColor() const { return this->m_color; } + [[nodiscard]] const std::string &getTooltip() const { return this->m_tooltip; } + + private: + Region m_region; + color_t m_color; + std::string m_tooltip; + }; + + u32 addHighlight(const Region ®ion, color_t color, std::string tooltip = ""); + void removeHighlight(u32 id); + std::map &getHighlights(); + + } namespace Bookmarks { + struct Entry { Region region; - std::vector name; - std::vector comment; + std::string name; + std::string comment; u32 color; bool locked; + + u32 highlightId; }; - void add(Region region, const std::string &name, const std::string &comment, u32 color = 0x00000000); - void add(u64 addr, size_t size, const std::string &name, const std::string &comment, u32 color = 0x00000000); + void add(Region region, const std::string &name, const std::string &comment, color_t color = 0x00000000); + void add(u64 address, size_t size, const std::string &name, const std::string &comment, color_t color = 0x00000000); - std::list &getEntries(); - }; + } namespace Provider { prv::Provider *get(); const std::vector &getProviders(); + void setCurrentProvider(u32 index); + bool isValid(); void add(prv::Provider *provider); @@ -56,14 +86,51 @@ namespace hex { void remove(prv::Provider *provider); - }; + } namespace Tasks { Task createTask(const std::string &unlocalizedName, u64 maxValue); + void doLater(const std::function &function); + std::vector>& getDeferredCalls(); + } - }; + namespace System { + + namespace impl { + + void setMainWindowPosition(u32 x, u32 y); + void setMainWindowSize(u32 width, u32 height); + void setMainDockSpaceId(ImGuiID id); + + void setGlobalScale(float scale); + + void setProgramArguments(int argc, char **argv, char **envp); + } + + struct ProgramArguments { + int argc; + char **argv; + char **envp; + }; + + const ProgramArguments& getProgramArguments(); + + float getTargetFPS(); + void setTargetFPS(float fps); + + float getGlobalScale(); + + ImVec2 getMainWindowPosition(); + ImVec2 getMainWindowSize(); + ImGuiID getMainDockSpaceId(); + + std::map& getInitArguments(); + + } + + } } diff --git a/lib/libimhex/include/hex/api/keybinding.hpp b/lib/libimhex/include/hex/api/keybinding.hpp index 8bf92c5fb..996775894 100644 --- a/lib/libimhex/include/hex/api/keybinding.hpp +++ b/lib/libimhex/include/hex/api/keybinding.hpp @@ -185,6 +185,10 @@ namespace hex { static void addGlobalShortcut(const Shortcut &shortcut, const std::function &callback); static void addShortcut(View *view, const Shortcut &shortcut, const std::function &callback); static void process(View *currentView, bool ctrl, bool alt, bool shift, bool super, bool focused, u32 keyCode); + + static void clearShortcuts(); + private: + static std::map> s_globalShortcuts; }; } \ No newline at end of file diff --git a/lib/libimhex/include/hex/helpers/lang.hpp b/lib/libimhex/include/hex/api/localization.hpp similarity index 89% rename from lib/libimhex/include/hex/helpers/lang.hpp rename to lib/libimhex/include/hex/api/localization.hpp index 7ee720fa9..e88ca75f8 100644 --- a/lib/libimhex/include/hex/helpers/lang.hpp +++ b/lib/libimhex/include/hex/api/localization.hpp @@ -35,10 +35,13 @@ namespace hex { static void setFallbackLanguage(const std::string &language); static const std::string &getFallbackLanguage(); + static void resetLanguageStrings(); + private: std::string m_unlocalizedString; static std::string s_fallbackLanguage; + static std::map s_currStrings; }; std::string operator+(const std::string &&left, const LangEntry &&right); @@ -49,13 +52,8 @@ namespace hex { std::string operator+(const LangEntry &&left, const char *right); std::string operator+(const LangEntry &&left, const LangEntry &&right); - namespace lang_literals { - - inline LangEntry operator""_lang(const char *string, size_t) { - return LangEntry(string); - } - + inline LangEntry operator""_lang(const char *string, size_t) { + return LangEntry(string); } - } \ No newline at end of file diff --git a/main/include/helpers/plugin_manager.hpp b/lib/libimhex/include/hex/api/plugin_manager.hpp similarity index 89% rename from main/include/helpers/plugin_manager.hpp rename to lib/libimhex/include/hex/api/plugin_manager.hpp index e06315e9c..eb8d006b1 100644 --- a/main/include/helpers/plugin_manager.hpp +++ b/lib/libimhex/include/hex/api/plugin_manager.hpp @@ -24,6 +24,7 @@ namespace hex { [[nodiscard]] std::string getPluginDescription() const; [[nodiscard]] std::string getCompatibleVersion() const; void setImGuiContext(ImGuiContext *ctx) const; + [[nodiscard]] bool isBuiltinPlugin() const; [[nodiscard]] const fs::path &getPath() const; @@ -36,6 +37,7 @@ namespace hex { using GetPluginDescriptionFunc = const char *(*)(); using GetCompatibleVersionFunc = const char *(*)(); using SetImGuiContextFunc = void (*)(ImGuiContext *); + using IsBuiltinPluginFunc = bool(*)(); void *m_handle = nullptr; fs::path m_path; @@ -48,6 +50,7 @@ namespace hex { GetPluginDescriptionFunc m_getPluginDescriptionFunction = nullptr; GetCompatibleVersionFunc m_getCompatibleVersionFunction = nullptr; SetImGuiContextFunc m_setImGuiContextFunction = nullptr; + IsBuiltinPluginFunc m_isBuiltinPluginFunction = nullptr; template [[nodiscard]] auto getPluginFunction(const std::string &symbol) { @@ -71,8 +74,8 @@ namespace hex { } private: - static inline fs::path s_pluginFolder; - static inline std::vector s_plugins; + static fs::path s_pluginFolder; + static std::vector s_plugins; }; } \ No newline at end of file diff --git a/lib/libimhex/include/hex/api/task.hpp b/lib/libimhex/include/hex/api/task.hpp index f5a4e3d5b..ec0ca08ac 100644 --- a/lib/libimhex/include/hex/api/task.hpp +++ b/lib/libimhex/include/hex/api/task.hpp @@ -2,6 +2,8 @@ #include +#include +#include #include namespace hex { @@ -21,9 +23,16 @@ namespace hex { [[nodiscard]] bool isPending() const; + static size_t getRunningTaskCount(); + static std::list& getRunningTasks() { return Task::s_runningTasks; } + static std::mutex& getTaskMutex() { return Task::s_taskMutex; } + private: std::string m_name; u64 m_maxValue, m_currValue; + + static std::list s_runningTasks; + static std::mutex s_taskMutex; }; } \ No newline at end of file diff --git a/lib/libimhex/include/hex/data_processor/attribute.hpp b/lib/libimhex/include/hex/data_processor/attribute.hpp index 9d40c65f5..5526c9a09 100644 --- a/lib/libimhex/include/hex/data_processor/attribute.hpp +++ b/lib/libimhex/include/hex/data_processor/attribute.hpp @@ -27,8 +27,8 @@ namespace hex::dp { Attribute(IOType ioType, Type type, std::string unlocalizedName); ~Attribute(); - [[nodiscard]] u32 getID() const { return this->m_id; } - void setID(u32 id) { this->m_id = id; } + [[nodiscard]] u32 getId() const { return this->m_id; } + void setId(u32 id) { this->m_id = id; } [[nodiscard]] IOType getIOType() const { return this->m_ioType; } [[nodiscard]] Type getType() const { return this->m_type; } @@ -42,6 +42,11 @@ namespace hex::dp { [[nodiscard]] std::optional> &getOutputData() { return this->m_outputData; } + static void setIdCounter(u32 id) { + if (id > Attribute::s_idCounter) + Attribute::s_idCounter = id; + } + private: u32 m_id; IOType m_ioType; @@ -54,6 +59,8 @@ namespace hex::dp { friend class Node; void setParentNode(Node *node) { this->m_parentNode = node; } + + static u32 s_idCounter; }; } \ No newline at end of file diff --git a/lib/libimhex/include/hex/data_processor/link.hpp b/lib/libimhex/include/hex/data_processor/link.hpp index c0eed809a..bacd37904 100644 --- a/lib/libimhex/include/hex/data_processor/link.hpp +++ b/lib/libimhex/include/hex/data_processor/link.hpp @@ -8,15 +8,22 @@ namespace hex::dp { public: Link(u32 from, u32 to); - [[nodiscard]] u32 getID() const { return this->m_id; } + [[nodiscard]] u32 getId() const { return this->m_id; } void setID(u32 id) { this->m_id = id; } - [[nodiscard]] u32 getFromID() const { return this->m_from; } - [[nodiscard]] u32 getToID() const { return this->m_to; } + [[nodiscard]] u32 getFromId() const { return this->m_from; } + [[nodiscard]] u32 getToId() const { return this->m_to; } + + static void setIdCounter(u32 id) { + if (id > Link::s_idCounter) + Link::s_idCounter = id; + } private: u32 m_id; u32 m_from, m_to; + + static u32 s_idCounter; }; } \ No newline at end of file diff --git a/lib/libimhex/include/hex/data_processor/node.hpp b/lib/libimhex/include/hex/data_processor/node.hpp index 26f09c1ad..672ca33e7 100644 --- a/lib/libimhex/include/hex/data_processor/node.hpp +++ b/lib/libimhex/include/hex/data_processor/node.hpp @@ -22,8 +22,8 @@ namespace hex::dp { virtual ~Node() = default; - [[nodiscard]] u32 getID() const { return this->m_id; } - void setID(u32 id) { this->m_id = id; } + [[nodiscard]] u32 getId() const { return this->m_id; } + void setId(u32 id) { this->m_id = id; } [[nodiscard]] const std::string &getUnlocalizedName() const { return this->m_unlocalizedName; } void setUnlocalizedName(const std::string &unlocalizedName) { this->m_unlocalizedName = unlocalizedName; } @@ -52,6 +52,11 @@ namespace hex::dp { this->m_processedInputs.clear(); } + static void setIdCounter(u32 id) { + if (id > Node::s_idCounter) + Node::s_idCounter = id; + } + private: u32 m_id; std::string m_unlocalizedTitle, m_unlocalizedName; @@ -59,6 +64,8 @@ namespace hex::dp { std::set m_processedInputs; prv::Overlay *m_overlay = nullptr; + static u32 s_idCounter; + Attribute *getConnectedInputAttribute(u32 index) { if (index >= this->getAttributes().size()) throw std::runtime_error("Attribute index out of bounds!"); diff --git a/lib/libimhex/include/hex/helpers/shared_data.hpp b/lib/libimhex/include/hex/helpers/shared_data.hpp deleted file mode 100644 index c30024848..000000000 --- a/lib/libimhex/include/hex/helpers/shared_data.hpp +++ /dev/null @@ -1,135 +0,0 @@ -#pragma once - -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include - -#include - -#include - -namespace hex { - class SharedData; -} - -namespace hex::plugin::internal { - void initializePlugin(SharedData &sharedData); -} - -namespace hex { - - namespace prv { - class Provider; - } - namespace dp { - class Node; - } - namespace pl { - class PatternData; - } - - class View; - - class SharedData { - SharedData() = default; - - public: - SharedData(const SharedData &) = delete; - SharedData(SharedData &&) = delete; - - friend class Window; - - template - static T &getVariable(std::string variableName) { - return std::any_cast(SharedData::sharedVariables[variableName]); - } - - template - static void setVariable(std::string variableName, T value) { - SharedData::sharedVariables[variableName] = value; - } - - static void clearVariables() { - SharedData::sharedVariables.clear(); - } - - public: - static std::vector> deferredCalls; - - static std::vector providers; - static u32 currentProvider; - - static std::map> settingsEntries; - static nlohmann::json settingsJson; - static std::vector commandPaletteCommands; - static std::map patternLanguageFunctions; - static std::map views; - static std::vector toolsEntries; - static std::vector dataInspectorEntries; - static u32 patternPaletteOffset; - static std::string popupMessage; - static std::list bookmarkEntries; - static std::vector patternData; - - static u32 selectableFileIndex; - static std::vector selectableFiles; - static std::function selectableFileOpenCallback; - static std::vector selectableFilesValidExtensions; - - static std::map languageNames; - static std::map> languageDefinitions; - static std::map loadedLanguageStrings; - - static ImGuiID dockSpaceId; - - static std::multimap mainMenuItems; - static std::multimap menuItems; - static std::vector welcomeScreenEntries; - static std::vector footerItems; - static std::vector toolbarItems; - static std::vector sidebarItems; - static std::vector layouts; - - static std::map> globalShortcuts; - - static std::mutex tasksMutex; - static std::list runningTasks; - - static std::vector providerNames; - - static std::vector dataProcessorNodes; - static u32 dataProcessorNodeIdCounter; - static u32 dataProcessorLinkIdCounter; - static u32 dataProcessorAttrIdCounter; - - static std::vector dataFormatters; - static std::vector fileHandlers; - - static std::list recentFilePaths; - - static int mainArgc; - static char **mainArgv; - static char **mainEnvp; - - static ImFontAtlas *fontAtlas; - static ImFontConfig fontConfig; - static ImVec2 windowPos; - static ImVec2 windowSize; - - static float globalScale; - static float fontScale; - - private: - static std::map sharedVariables; - }; - -} diff --git a/lib/libimhex/include/hex/pattern_language/ast_node.hpp b/lib/libimhex/include/hex/pattern_language/ast_node.hpp index 945146df8..262c10716 100644 --- a/lib/libimhex/include/hex/pattern_language/ast_node.hpp +++ b/lib/libimhex/include/hex/pattern_language/ast_node.hpp @@ -400,21 +400,21 @@ namespace hex::pl { PatternData *pattern; if (Token::isUnsigned(this->m_type)) - pattern = new PatternDataUnsigned(offset, size); + pattern = new PatternDataUnsigned(evaluator, offset, size); else if (Token::isSigned(this->m_type)) - pattern = new PatternDataSigned(offset, size); + pattern = new PatternDataSigned(evaluator, offset, size); else if (Token::isFloatingPoint(this->m_type)) - pattern = new PatternDataFloat(offset, size); + pattern = new PatternDataFloat(evaluator, offset, size); else if (this->m_type == Token::ValueType::Boolean) - pattern = new PatternDataBoolean(offset); + pattern = new PatternDataBoolean(evaluator, offset); else if (this->m_type == Token::ValueType::Character) - pattern = new PatternDataCharacter(offset); + pattern = new PatternDataCharacter(evaluator, offset); else if (this->m_type == Token::ValueType::Character16) - pattern = new PatternDataCharacter16(offset); + pattern = new PatternDataCharacter16(evaluator, offset); else if (this->m_type == Token::ValueType::Padding) - pattern = new PatternDataPadding(offset, 1); + pattern = new PatternDataPadding(evaluator, offset, 1); else if (this->m_type == Token::ValueType::String) - pattern = new PatternDataString(offset, 1); + pattern = new PatternDataString(evaluator, offset, 1); else if (this->m_type == Token::ValueType::Auto) return { nullptr }; else @@ -972,13 +972,13 @@ namespace hex::pl { PatternData *outputPattern; if (dynamic_cast(templatePattern)) { - outputPattern = new PatternDataPadding(startOffset, 0); + outputPattern = new PatternDataPadding(evaluator, startOffset, 0); } else if (dynamic_cast(templatePattern)) { - outputPattern = new PatternDataString(startOffset, 0); + outputPattern = new PatternDataString(evaluator, startOffset, 0); } else if (dynamic_cast(templatePattern)) { - outputPattern = new PatternDataString16(startOffset, 0); + outputPattern = new PatternDataString16(evaluator, startOffset, 0); } else { - auto arrayPattern = new PatternDataStaticArray(startOffset, 0); + auto arrayPattern = new PatternDataStaticArray(evaluator, startOffset, 0); arrayPattern->setEntries(templatePattern->clone(), entryCount); outputPattern = arrayPattern; } @@ -995,7 +995,7 @@ namespace hex::pl { } PatternData *createDynamicArray(Evaluator *evaluator) const { - auto arrayPattern = new PatternDataDynamicArray(evaluator->dataOffset(), 0); + auto arrayPattern = new PatternDataDynamicArray(evaluator, evaluator->dataOffset(), 0); arrayPattern->setVariableName(this->m_name); std::vector entries; @@ -1192,7 +1192,7 @@ namespace hex::pl { auto sizePattern = this->m_sizeType->createPatterns(evaluator).front(); ON_SCOPE_EXIT { delete sizePattern; }; - auto pattern = new PatternDataPointer(startOffset, sizePattern->getSize()); + auto pattern = new PatternDataPointer(evaluator, startOffset, sizePattern->getSize()); pattern->setVariableName(this->m_name); auto endOffset = evaluator->dataOffset(); @@ -1298,7 +1298,7 @@ namespace hex::pl { } [[nodiscard]] std::vector createPatterns(Evaluator *evaluator) const override { - auto pattern = new PatternDataStruct(evaluator->dataOffset(), 0); + auto pattern = new PatternDataStruct(evaluator, evaluator->dataOffset(), 0); u64 startOffset = evaluator->dataOffset(); std::vector memberPatterns; @@ -1370,7 +1370,7 @@ namespace hex::pl { } [[nodiscard]] std::vector createPatterns(Evaluator *evaluator) const override { - auto pattern = new PatternDataUnion(evaluator->dataOffset(), 0); + auto pattern = new PatternDataUnion(evaluator, evaluator->dataOffset(), 0); size_t size = 0; std::vector memberPatterns; @@ -1430,7 +1430,7 @@ namespace hex::pl { } [[nodiscard]] std::vector createPatterns(Evaluator *evaluator) const override { - auto pattern = new PatternDataEnum(evaluator->dataOffset(), 0); + auto pattern = new PatternDataEnum(evaluator, evaluator->dataOffset(), 0); auto enumCleanup = SCOPE_GUARD { delete pattern; }; @@ -1487,7 +1487,7 @@ namespace hex::pl { void addEntry(const std::string &name, ASTNode *size) { this->m_entries.emplace_back(name, size); } [[nodiscard]] std::vector createPatterns(Evaluator *evaluator) const override { - auto pattern = new PatternDataBitfield(evaluator->dataOffset(), 0); + auto pattern = new PatternDataBitfield(evaluator, evaluator->dataOffset(), 0); size_t bitOffset = 0; std::vector fields; @@ -1511,7 +1511,7 @@ namespace hex::pl { // If a field is named padding, it was created through a padding expression and only advances the bit position if (name != "padding") { - auto field = new PatternDataBitfieldField(evaluator->dataOffset(), bitOffset, bitSize, pattern); + auto field = new PatternDataBitfieldField(evaluator, evaluator->dataOffset(), bitOffset, bitSize, pattern); field->setVariableName(name); fields.push_back(field); } @@ -1627,7 +1627,7 @@ namespace hex::pl { std::visit(overloaded { [&](char assignmentValue) { if (assignmentValue != 0x00) value = std::string({ assignmentValue }); }, - [&](const std::string &assignmentValue) { value = assignmentValue; }, + [&](std::string assignmentValue) { value = assignmentValue; }, [&, this](PatternData *const &assignmentValue) { if (!dynamic_cast(assignmentValue) && !dynamic_cast(assignmentValue)) LogConsole::abortEvaluation(hex::format("cannot assign '{}' to string", pattern->getTypeName()), this); diff --git a/lib/libimhex/include/hex/pattern_language/pattern_data.hpp b/lib/libimhex/include/hex/pattern_language/pattern_data.hpp index ea9dad343..1e75747ae 100644 --- a/lib/libimhex/include/hex/pattern_language/pattern_data.hpp +++ b/lib/libimhex/include/hex/pattern_language/pattern_data.hpp @@ -8,7 +8,7 @@ #include #include -#include +#include #include #include #include @@ -55,47 +55,39 @@ namespace hex::pl { class PatternCreationLimiter { public: - explicit PatternCreationLimiter() { - if (PatternCreationLimiter::s_evaluator == nullptr) return; + explicit PatternCreationLimiter(Evaluator *evaluator) : m_evaluator(evaluator) { + if (getEvaluator() == nullptr) return; - PatternCreationLimiter::s_evaluator->patternCreated(); + getEvaluator()->patternCreated(); } - PatternCreationLimiter(const PatternCreationLimiter &other) { - if (PatternCreationLimiter::s_evaluator == nullptr) return; - - PatternCreationLimiter::s_evaluator->patternCreated(); - } + PatternCreationLimiter(const PatternCreationLimiter &other) : PatternCreationLimiter(other.m_evaluator) { } virtual ~PatternCreationLimiter() { - if (PatternCreationLimiter::s_evaluator == nullptr) return; + if (getEvaluator() == nullptr) return; - PatternCreationLimiter::s_evaluator->patternDestroyed(); + getEvaluator()->patternDestroyed(); } [[nodiscard]] - static Evaluator *getEvaluator() { - return PatternCreationLimiter::s_evaluator; + Evaluator* getEvaluator() const { + return this->m_evaluator; } - - public: - static Evaluator *s_evaluator; + private: + Evaluator *m_evaluator = nullptr; }; class PatternData : public PatternCreationLimiter, public Cloneable { public: - PatternData(u64 offset, size_t size, u32 color = 0) - : PatternCreationLimiter(), m_offset(offset), m_size(size), m_color(color) { + PatternData(Evaluator *evaluator, u64 offset, size_t size, u32 color = 0) + : PatternCreationLimiter(evaluator), m_offset(offset), m_size(size), m_color(color) { constexpr u32 Palette[] = { 0x70b4771f, 0x700e7fff, 0x702ca02c, 0x702827d6, 0x70bd6794, 0x704b568c, 0x70c277e3, 0x707f7f7f, 0x7022bdbc, 0x70cfbe17 }; if (color != 0) return; - this->m_color = Palette[SharedData::patternPaletteOffset++]; + this->m_color = ContentRegistry::PatternLanguage::getNextColor(); this->m_manualColor = false; - - if (SharedData::patternPaletteOffset >= (sizeof(Palette) / sizeof(u32))) - SharedData::patternPaletteOffset = 0; } PatternData(const PatternData &other) = default; @@ -125,8 +117,8 @@ namespace hex::pl { [[nodiscard]] bool hasOverriddenColor() const { return this->m_manualColor; } [[nodiscard]] std::endian getEndian() const { - if (PatternData::getEvaluator() == nullptr) return std::endian::native; - else return this->m_endian.value_or(PatternData::getEvaluator()->getDefaultEndian()); + if (this->getEvaluator() == nullptr) return std::endian::native; + else return this->m_endian.value_or(this->getEvaluator()->getDefaultEndian()); } virtual void setEndian(std::endian endian) { this->m_endian = endian; } [[nodiscard]] bool hasOverriddenEndian() const { return this->m_endian.has_value(); } @@ -155,7 +147,7 @@ namespace hex::pl { for (u64 i = 0; i < this->getSize(); i++) highlight.insert({ this->getOffset() + i, this->getColor() }); - PatternData::getEvaluator()->handleAbort(); + this->getEvaluator()->handleAbort(); } virtual void sort(ImGuiTableSortSpecs *sortSpecs, prv::Provider *provider) { } @@ -217,8 +209,6 @@ namespace hex::pl { this->createEntry(provider); } - static void resetPalette() { SharedData::patternPaletteOffset = 0; } - void setHidden(bool hidden) { this->m_hidden = hidden; } @@ -256,7 +246,7 @@ namespace hex::pl { return value; else { try { - auto result = this->m_formatterFunction->func(PatternData::getEvaluator(), { literal }); + auto result = this->m_formatterFunction->func(this->getEvaluator(), { literal }); if (result.has_value()) { if (auto displayValue = std::get_if(&result.value()); displayValue != nullptr) @@ -326,7 +316,7 @@ namespace hex::pl { class PatternDataPadding : public PatternData { public: - PatternDataPadding(u64 offset, size_t size) : PatternData(offset, size, 0xFF000000) { } + PatternDataPadding(Evaluator *evaluator, u64 offset, size_t size) : PatternData(evaluator, offset, size, 0xFF000000) { } [[nodiscard]] PatternData *clone() const override { @@ -345,8 +335,8 @@ namespace hex::pl { class PatternDataPointer : public PatternData { public: - PatternDataPointer(u64 offset, size_t size, u32 color = 0) - : PatternData(offset, size, color), m_pointedAt(nullptr) { + PatternDataPointer(Evaluator *evaluator, u64 offset, size_t size, u32 color = 0) + : PatternData(evaluator, offset, size, color), m_pointedAt(nullptr) { } PatternDataPointer(const PatternDataPointer &other) : PatternData(other) { @@ -476,8 +466,8 @@ namespace hex::pl { class PatternDataUnsigned : public PatternData { public: - PatternDataUnsigned(u64 offset, size_t size, u32 color = 0) - : PatternData(offset, size, color) { } + PatternDataUnsigned(Evaluator *evaluator, u64 offset, size_t size, u32 color = 0) + : PatternData(evaluator, offset, size, color) { } [[nodiscard]] PatternData *clone() const override { @@ -514,8 +504,8 @@ namespace hex::pl { class PatternDataSigned : public PatternData { public: - PatternDataSigned(u64 offset, size_t size, u32 color = 0) - : PatternData(offset, size, color) { } + PatternDataSigned(Evaluator *evaluator, u64 offset, size_t size, u32 color = 0) + : PatternData(evaluator, offset, size, color) { } [[nodiscard]] PatternData *clone() const override { @@ -553,8 +543,8 @@ namespace hex::pl { class PatternDataFloat : public PatternData { public: - PatternDataFloat(u64 offset, size_t size, u32 color = 0) - : PatternData(offset, size, color) { } + PatternDataFloat(Evaluator *evaluator, u64 offset, size_t size, u32 color = 0) + : PatternData(evaluator, offset, size, color) { } [[nodiscard]] PatternData *clone() const override { @@ -593,8 +583,8 @@ namespace hex::pl { class PatternDataBoolean : public PatternData { public: - explicit PatternDataBoolean(u64 offset, u32 color = 0) - : PatternData(offset, 1, color) { } + explicit PatternDataBoolean(Evaluator *evaluator, u64 offset, u32 color = 0) + : PatternData(evaluator, offset, 1, color) { } [[nodiscard]] PatternData *clone() const override { @@ -622,8 +612,8 @@ namespace hex::pl { class PatternDataCharacter : public PatternData { public: - explicit PatternDataCharacter(u64 offset, u32 color = 0) - : PatternData(offset, 1, color) { } + explicit PatternDataCharacter(Evaluator *evaluator, u64 offset, u32 color = 0) + : PatternData(evaluator, offset, 1, color) { } [[nodiscard]] PatternData *clone() const override { @@ -646,8 +636,8 @@ namespace hex::pl { class PatternDataCharacter16 : public PatternData { public: - explicit PatternDataCharacter16(u64 offset, u32 color = 0) - : PatternData(offset, 2, color) { } + explicit PatternDataCharacter16(Evaluator *evaluator, u64 offset, u32 color = 0) + : PatternData(evaluator, offset, 2, color) { } [[nodiscard]] PatternData *clone() const override { @@ -680,8 +670,8 @@ namespace hex::pl { class PatternDataString : public PatternData { public: - PatternDataString(u64 offset, size_t size, u32 color = 0) - : PatternData(offset, size, color) { } + PatternDataString(Evaluator *evaluator, u64 offset, size_t size, u32 color = 0) + : PatternData(evaluator, offset, size, color) { } [[nodiscard]] PatternData *clone() const override { @@ -721,8 +711,8 @@ namespace hex::pl { class PatternDataString16 : public PatternData { public: - PatternDataString16(u64 offset, size_t size, u32 color = 0) - : PatternData(offset, size, color) { } + PatternDataString16(Evaluator *evaluator, u64 offset, size_t size, u32 color = 0) + : PatternData(evaluator, offset, size, color) { } [[nodiscard]] PatternData *clone() const override { @@ -774,8 +764,8 @@ namespace hex::pl { class PatternDataDynamicArray : public PatternData, public Inlinable { public: - PatternDataDynamicArray(u64 offset, size_t size, u32 color = 0) - : PatternData(offset, size, color) { + PatternDataDynamicArray(Evaluator *evaluator, u64 offset, size_t size, u32 color = 0) + : PatternData(evaluator, offset, size, color) { } PatternDataDynamicArray(const PatternDataDynamicArray &other) : PatternData(other) { @@ -931,8 +921,8 @@ namespace hex::pl { class PatternDataStaticArray : public PatternData, public Inlinable { public: - PatternDataStaticArray(u64 offset, size_t size, u32 color = 0) - : PatternData(offset, size, color) { + PatternDataStaticArray(Evaluator *evaluator, u64 offset, size_t size, u32 color = 0) + : PatternData(evaluator, offset, size, color) { } PatternDataStaticArray(const PatternDataStaticArray &other) : PatternData(other) { @@ -1089,8 +1079,8 @@ namespace hex::pl { class PatternDataStruct : public PatternData, public Inlinable { public: - PatternDataStruct(u64 offset, size_t size, u32 color = 0) - : PatternData(offset, size, color) { + PatternDataStruct(Evaluator *evaluator, u64 offset, size_t size, u32 color = 0) + : PatternData(evaluator, offset, size, color) { } PatternDataStruct(const PatternDataStruct &other) : PatternData(other) { @@ -1237,8 +1227,8 @@ namespace hex::pl { class PatternDataUnion : public PatternData, public Inlinable { public: - PatternDataUnion(u64 offset, size_t size, u32 color = 0) - : PatternData(offset, size, color) { + PatternDataUnion(Evaluator *evaluator, u64 offset, size_t size, u32 color = 0) + : PatternData(evaluator, offset, size, color) { } PatternDataUnion(const PatternDataUnion &other) : PatternData(other) { @@ -1386,8 +1376,8 @@ namespace hex::pl { class PatternDataEnum : public PatternData { public: - PatternDataEnum(u64 offset, size_t size, u32 color = 0) - : PatternData(offset, size, color) { + PatternDataEnum(Evaluator *evaluator, u64 offset, size_t size, u32 color = 0) + : PatternData(evaluator, offset, size, color) { } [[nodiscard]] @@ -1482,8 +1472,8 @@ namespace hex::pl { class PatternDataBitfieldField : public PatternData { public: - PatternDataBitfieldField(u64 offset, u8 bitOffset, u8 bitSize, PatternData *bitField, u32 color = 0) - : m_bitOffset(bitOffset), m_bitSize(bitSize), m_bitField(bitField), PatternData(offset, 0, color) { + PatternDataBitfieldField(Evaluator *evaluator, u64 offset, u8 bitOffset, u8 bitSize, PatternData *bitField, u32 color = 0) + : PatternData(evaluator, offset, 0, color), m_bitOffset(bitOffset), m_bitSize(bitSize), m_bitField(bitField) { } [[nodiscard]] @@ -1552,8 +1542,8 @@ namespace hex::pl { class PatternDataBitfield : public PatternData, public Inlinable { public: - PatternDataBitfield(u64 offset, size_t size, u32 color = 0) - : PatternData(offset, size, color) { + PatternDataBitfield(Evaluator *evaluator, u64 offset, size_t size, u32 color = 0) + : PatternData(evaluator, offset, size, color) { } PatternDataBitfield(const PatternDataBitfield &other) : PatternData(other) { diff --git a/lib/libimhex/include/hex/pattern_language/pattern_language.hpp b/lib/libimhex/include/hex/pattern_language/pattern_language.hpp index 59fb55854..55f01bc0f 100644 --- a/lib/libimhex/include/hex/pattern_language/pattern_language.hpp +++ b/lib/libimhex/include/hex/pattern_language/pattern_language.hpp @@ -33,8 +33,8 @@ namespace hex::pl { ~PatternLanguage(); [[nodiscard]] std::optional> parseString(const std::string &code); - [[nodiscard]] std::optional> executeString(prv::Provider *provider, const std::string &string, const std::map &envVars = {}, const std::map &inVariables = {}); - [[nodiscard]] std::optional> executeFile(prv::Provider *provider, const fs::path &path, const std::map &envVars = {}, const std::map &inVariables = {}); + [[nodiscard]] bool executeString(prv::Provider *provider, const std::string &string, const std::map &envVars = {}, const std::map &inVariables = {}); + [[nodiscard]] bool executeFile(prv::Provider *provider, const fs::path &path, const std::map &envVars = {}, const std::map &inVariables = {}); [[nodiscard]] const std::vector &getCurrentAST() const; void abort(); @@ -49,6 +49,13 @@ namespace hex::pl { [[nodiscard]] bool hasDangerousFunctionBeenCalled() const; void allowDangerousFunctions(bool allow); + [[nodiscard]] std::vector &getPatterns() { + return this->m_patterns; + } + + void reset(); + bool isRunning() const { return this->m_running; } + private: Preprocessor *m_preprocessor; Lexer *m_lexer; @@ -59,6 +66,10 @@ namespace hex::pl { std::vector m_currAST; std::optional m_currError; + + std::vector m_patterns; + + bool m_running = false; }; } \ No newline at end of file diff --git a/lib/libimhex/include/hex/providers/provider.hpp b/lib/libimhex/include/hex/providers/provider.hpp index fa12738a4..5c97a59ea 100644 --- a/lib/libimhex/include/hex/providers/provider.hpp +++ b/lib/libimhex/include/hex/providers/provider.hpp @@ -2,13 +2,14 @@ #include +#include #include #include #include #include -#include #include +#include namespace hex::prv { @@ -78,6 +79,9 @@ namespace hex::prv { virtual void drawLoadInterface(); virtual void drawInterface(); + pl::PatternLanguage& getPatternLanguageRuntime() { return this->m_patternLanguageRuntime; } + std::string& getPatternLanguageSourceCode() { return this->m_patternLanguageSourceCode; } + protected: u32 m_currPage = 0; u64 m_baseAddress = 0; @@ -85,6 +89,9 @@ namespace hex::prv { u32 m_patchTreeOffset = 0; std::list> m_patches; std::list m_overlays; + + pl::PatternLanguage m_patternLanguageRuntime; + std::string m_patternLanguageSourceCode; }; } \ No newline at end of file diff --git a/lib/libimhex/include/hex/views/view.hpp b/lib/libimhex/include/hex/ui/view.hpp similarity index 59% rename from lib/libimhex/include/hex/views/view.hpp rename to lib/libimhex/include/hex/ui/view.hpp index 074a2c999..d4baabcbc 100644 --- a/lib/libimhex/include/hex/views/view.hpp +++ b/lib/libimhex/include/hex/ui/view.hpp @@ -14,7 +14,7 @@ #include #include -#include +#include #include #include @@ -23,8 +23,6 @@ namespace hex { - using namespace hex::lang_literals; - class View { public: explicit View(std::string unlocalizedViewName); @@ -32,11 +30,8 @@ namespace hex { virtual void drawContent() = 0; virtual void drawAlwaysVisible() { } - virtual bool isAvailable() const; - virtual bool shouldProcess() const { return this->isAvailable() && this->getWindowOpenState(); } - - static void doLater(std::function &&function); - static std::vector> &getDeferedCalls(); + [[nodiscard]] virtual bool isAvailable() const; + [[nodiscard]] virtual bool shouldProcess() const { return this->isAvailable() && this->getWindowOpenState(); } static void drawCommonInterfaces(); @@ -46,12 +41,12 @@ namespace hex { static void showFileChooserPopup(const std::vector &paths, const std::vector &validExtensions, const std::function &callback); - virtual bool hasViewMenuItemEntry() const; - virtual ImVec2 getMinSize() const; - virtual ImVec2 getMaxSize() const; + [[nodiscard]] virtual bool hasViewMenuItemEntry() const; + [[nodiscard]] virtual ImVec2 getMinSize() const; + [[nodiscard]] virtual ImVec2 getMaxSize() const; - bool &getWindowOpenState(); - const bool &getWindowOpenState() const; + [[nodiscard]] bool &getWindowOpenState(); + [[nodiscard]] const bool &getWindowOpenState() const; [[nodiscard]] const std::string &getUnlocalizedName() const; [[nodiscard]] std::string getName() const; @@ -63,11 +58,27 @@ namespace hex { return LangEntry(unlocalizedName) + "###" + unlocalizedName; } + static ImFontAtlas *getFontAtlas() { return View::s_fontAtlas; } + static void setFontAtlas(ImFontAtlas *atlas) { View::s_fontAtlas = atlas; } + + static ImFontConfig getFontConfig() { return View::s_fontConfig; } + static void setFontConfig(ImFontConfig config) { View::s_fontConfig = config; } + private: std::string m_unlocalizedViewName; bool m_windowOpen = false; std::map> m_shortcuts; + static std::string s_popupMessage; + + static u32 s_selectableFileIndex; + static std::vector s_selectableFiles; + static std::function s_selectableFileOpenCallback; + static std::vector s_selectableFilesValidExtensions; + + static ImFontAtlas *s_fontAtlas; + static ImFontConfig s_fontConfig; + friend class ShortcutManager; }; diff --git a/lib/libimhex/source/api/content_registry.cpp b/lib/libimhex/source/api/content_registry.cpp index a8640b226..ea33b2953 100644 --- a/lib/libimhex/source/api/content_registry.cpp +++ b/lib/libimhex/source/api/content_registry.cpp @@ -1,9 +1,10 @@ #include -#include #include #include +#include + #include #include @@ -141,7 +142,9 @@ namespace hex { std::map> &ContentRegistry::Settings::getEntries() { - return SharedData::settingsEntries; + static std::map> entries; + + return entries; } nlohmann::json ContentRegistry::Settings::getSetting(const std::string &unlocalizedCategory, const std::string &unlocalizedName) { @@ -154,7 +157,9 @@ namespace hex { } nlohmann::json &ContentRegistry::Settings::getSettingsData() { - return SharedData::settingsJson; + static nlohmann::json settings; + + return settings; } @@ -167,7 +172,9 @@ namespace hex { } std::vector &ContentRegistry::CommandPaletteCommands::getEntries() { - return SharedData::commandPaletteCommands; + static std::vector commands; + + return commands; } @@ -197,7 +204,50 @@ namespace hex { } std::map &ContentRegistry::PatternLanguage::getFunctions() { - return SharedData::patternLanguageFunctions; + static std::map functions; + + return functions; + } + + + static std::vector s_colorPalettes; + static u32 s_colorIndex; + static u32 s_selectedColorPalette; + + std::vector &ContentRegistry::PatternLanguage::getPalettes() { + return s_colorPalettes; + } + + void ContentRegistry::PatternLanguage::addColorPalette(const std::string &unlocalizedName, const std::vector &colors) { + s_colorPalettes.push_back({ + unlocalizedName, + colors + }); + } + + void ContentRegistry::PatternLanguage::setSelectedPalette(u32 index) { + if (index < s_colorPalettes.size()) + s_selectedColorPalette = index; + + resetPalette(); + } + + u32 ContentRegistry::PatternLanguage::getNextColor() { + if (s_colorPalettes.empty()) + return 0x00; + + auto &currColors = s_colorPalettes[s_selectedColorPalette].colors; + + u32 color = currColors[s_colorIndex]; + + s_colorIndex++; + s_colorIndex %= currColors.size(); + + return color; + } + + void ContentRegistry::PatternLanguage::resetPalette() { + s_colorIndex = 0; } @@ -210,7 +260,9 @@ namespace hex { } std::map &ContentRegistry::Views::getEntries() { - return SharedData::views; + static std::map views; + + return views; } View *ContentRegistry::Views::getViewByName(const std::string &unlocalizedName) { @@ -232,7 +284,9 @@ namespace hex { } std::vector &ContentRegistry::Tools::getEntries() { - return SharedData::toolsEntries; + static std::vector entries; + + return entries; } @@ -245,7 +299,9 @@ namespace hex { } std::vector &ContentRegistry::DataInspector::getEntries() { - return SharedData::dataInspectorEntries; + static std::vector entries; + + return entries; } /* Data Processor Nodes */ @@ -261,7 +317,9 @@ namespace hex { } std::vector &ContentRegistry::DataProcessorNode::getEntries() { - return SharedData::dataProcessorNodes; + static std::vector nodes; + + return nodes; } /* Languages */ @@ -279,20 +337,20 @@ namespace hex { } std::map &ContentRegistry::Language::getLanguages() { - return SharedData::languageNames; + static std::map languages; + + return languages; } std::map> &ContentRegistry::Language::getLanguageDefinitions() { - return SharedData::languageDefinitions; + static std::map> definitions; + + return definitions; } /* Interface */ - u32 ContentRegistry::Interface::getDockSpaceId() { - return SharedData::dockSpaceId; - } - void ContentRegistry::Interface::registerMainMenuItem(const std::string &unlocalizedName, u32 priority) { log::info("Registered new main menu item: {}", unlocalizedName); @@ -331,27 +389,41 @@ namespace hex { std::multimap &ContentRegistry::Interface::getMainMenuItems() { - return SharedData::mainMenuItems; + static std::multimap items; + + return items; } std::multimap &ContentRegistry::Interface::getMenuItems() { - return SharedData::menuItems; + static std::multimap items; + + return items; } std::vector &ContentRegistry::Interface::getWelcomeScreenEntries() { - return SharedData::welcomeScreenEntries; + static std::vector entries; + + return entries; } std::vector &ContentRegistry::Interface::getFooterItems() { - return SharedData::footerItems; + static std::vector items; + + return items; } std::vector &ContentRegistry::Interface::getToolbarItems() { - return SharedData::toolbarItems; + static std::vector items; + + return items; } std::vector &ContentRegistry::Interface::getSidebarItems() { - return SharedData::sidebarItems; + static std::vector items; + + return items; } std::vector &ContentRegistry::Interface::getLayouts() { - return SharedData::layouts; + static std::vector layouts; + + return layouts; } @@ -360,11 +432,13 @@ namespace hex { void ContentRegistry::Provider::impl::addProviderName(const std::string &unlocalizedName) { log::info("Registered new provider: {}", unlocalizedName); - SharedData::providerNames.push_back(unlocalizedName); + getEntries().push_back(unlocalizedName); } - const std::vector &ContentRegistry::Provider::getEntries() { - return SharedData::providerNames; + std::vector &ContentRegistry::Provider::getEntries() { + static std::vector providerNames; + + return providerNames; } @@ -373,11 +447,13 @@ namespace hex { void ContentRegistry::DataFormatter::add(const std::string &unlocalizedName, const impl::Callback &callback) { log::info("Registered new data formatter: {}", unlocalizedName); - ContentRegistry::DataFormatter::getEntries().push_back({ unlocalizedName, callback }); + getEntries().push_back({ unlocalizedName, callback }); } std::vector &ContentRegistry::DataFormatter::getEntries() { - return SharedData::dataFormatters; + static std::vector entries; + + return entries; } @@ -387,10 +463,12 @@ namespace hex { for (const auto &extension : extensions) log::info("Registered new data handler for extensions: {}", extension); - ContentRegistry::FileHandler::getEntries().push_back({ extensions, callback }); + getEntries().push_back({ extensions, callback }); } std::vector &ContentRegistry::FileHandler::getEntries() { - return SharedData::fileHandlers; + static std::vector entries; + + return entries; } } \ No newline at end of file diff --git a/lib/libimhex/source/api/imhex_api.cpp b/lib/libimhex/source/api/imhex_api.cpp index 804d13249..2fbc8877d 100644 --- a/lib/libimhex/source/api/imhex_api.cpp +++ b/lib/libimhex/source/api/imhex_api.cpp @@ -1,89 +1,213 @@ #include #include -#include +#include #include -#include - namespace hex { - void ImHexApi::Common::closeImHex(bool noQuestions) { - EventManager::post(noQuestions); - } + namespace ImHexApi::Common { + + void closeImHex(bool noQuestions) { + EventManager::post(noQuestions); + } + + void restartImHex() { + EventManager::post(false); + std::atexit([] { + auto &programArgs = ImHexApi::System::getProgramArguments(); + execve(programArgs.argv[0], programArgs.argv, programArgs.envp); + }); + } - void ImHexApi::Common::restartImHex() { - EventManager::post(false); - std::atexit([] { - execve(SharedData::mainArgv[0], SharedData::mainArgv, SharedData::mainEnvp); - }); } - void ImHexApi::Bookmarks::add(Region region, const std::string &name, const std::string &comment, u32 color) { - Entry entry; + namespace ImHexApi::HexEditor { - entry.region = region; + static std::map s_highlights; - entry.name.reserve(name.length()); - entry.comment.reserve(comment.length()); - std::copy(name.begin(), name.end(), std::back_inserter(entry.name)); - std::copy(comment.begin(), comment.end(), std::back_inserter(entry.comment)); - entry.locked = false; + Highlighting::Highlighting(Region region, color_t color, const std::string &tooltip) + : m_region(region), m_color(color), m_tooltip(tooltip) { + } - entry.color = color; + u32 addHighlight(const Region ®ion, color_t color, std::string tooltip) { + auto id = s_highlights.size(); - EventManager::post(entry); - } + s_highlights.insert({ id, Highlighting{ region, color, tooltip } }); - void ImHexApi::Bookmarks::add(u64 addr, size_t size, const std::string &name, const std::string &comment, u32 color) { - Bookmarks::add(Region { addr, size }, name, comment, color); - } + return id; + } + + void removeHighlight(u32 id) { + s_highlights.erase(id); + } + + std::map &getHighlights() { + return s_highlights; + } - std::list &ImHexApi::Bookmarks::getEntries() { - return SharedData::bookmarkEntries; } - prv::Provider *ImHexApi::Provider::get() { - if (!ImHexApi::Provider::isValid()) - return nullptr; + namespace ImHexApi::Bookmarks { - return SharedData::providers[SharedData::currentProvider]; - } + void add(Region region, const std::string &name, const std::string &comment, u32 color) { + EventManager::post(region, name, comment, color); + } - const std::vector &ImHexApi::Provider::getProviders() { - return SharedData::providers; - } + void add(u64 address, size_t size, const std::string &name, const std::string &comment, u32 color) { + add(Region { address, size }, name, comment, color); + } - bool ImHexApi::Provider::isValid() { - return !SharedData::providers.empty(); - } - - void ImHexApi::Provider::add(prv::Provider *provider) { - SharedData::providers.push_back(provider); - SharedData::currentProvider = SharedData::providers.size() - 1; - - EventManager::post(provider); - } - - void ImHexApi::Provider::remove(prv::Provider *provider) { - auto &providers = SharedData::providers; - - auto it = std::find(providers.begin(), providers.end(), provider); - - providers.erase(it); - - if (it - providers.begin() == SharedData::currentProvider) - SharedData::currentProvider = 0; - - delete provider; } - Task ImHexApi::Tasks::createTask(const std::string &unlocalizedName, u64 maxValue) { - return Task(unlocalizedName, maxValue); + namespace ImHexApi::Provider { + + static u32 s_currentProvider; + static std::vector s_providers; + + prv::Provider *get() { + if (!ImHexApi::Provider::isValid()) + return nullptr; + + return s_providers[s_currentProvider]; + } + + const std::vector &getProviders() { + return s_providers; + } + + void setCurrentProvider(u32 index) { + if (index < s_providers.size()) { + auto oldProvider = get(); + s_currentProvider = index; + EventManager::post(oldProvider, get()); + } + } + + bool isValid() { + return !s_providers.empty(); + } + + void add(prv::Provider *provider) { + s_providers.push_back(provider); + setCurrentProvider(s_providers.size() - 1); + + EventManager::post(provider); + } + + void remove(prv::Provider *provider) { + auto it = std::find(s_providers.begin(), s_providers.end(), provider); + + s_providers.erase(it); + + if (it - s_providers.begin() == s_currentProvider) + s_currentProvider = 0; + + delete provider; + } + + } + + + namespace ImHexApi::Tasks { + + Task createTask(const std::string &unlocalizedName, u64 maxValue) { + return Task(unlocalizedName, maxValue); + } + + + std::vector> s_deferredCalls; + + void doLater(const std::function &function) { + getDeferredCalls().push_back(function); + } + + std::vector>& getDeferredCalls() { + return s_deferredCalls; + } + + } + + + namespace ImHexApi::System { + + namespace impl { + + static ImVec2 s_mainWindowPos; + static ImVec2 s_mainWindowSize; + void setMainWindowPosition(u32 x, u32 y) { + s_mainWindowPos = ImVec2(x, y); + } + + void setMainWindowSize(u32 width, u32 height) { + s_mainWindowSize = ImVec2(width, height); + } + + static ImGuiID s_mainDockSpaceId; + void setMainDockSpaceId(ImGuiID id) { + s_mainDockSpaceId = id; + } + + + static float s_globalScale; + void setGlobalScale(float scale) { + s_globalScale = scale; + } + + + static ProgramArguments s_programArguments; + void setProgramArguments(int argc, char **argv, char **envp) { + s_programArguments.argc = argc; + s_programArguments.argv = argv; + s_programArguments.envp = envp; + } + + } + + + + const ProgramArguments& getProgramArguments() { + return impl::s_programArguments; + } + + + static float s_targetFPS = 60.0F; + + float getTargetFPS() { + return s_targetFPS; + } + + void setTargetFPS(float fps) { + s_targetFPS = fps; + } + + float getGlobalScale() { + return impl::s_globalScale; + } + + + ImVec2 getMainWindowPosition() { + return impl::s_mainWindowPos; + } + + ImVec2 getMainWindowSize() { + return impl::s_mainWindowSize; + } + + + ImGuiID getMainDockSpaceId() { + return impl::s_mainDockSpaceId; + } + + std::map& getInitArguments() { + static std::map initArgs; + + return initArgs; + } } } diff --git a/lib/libimhex/source/api/keybinding.cpp b/lib/libimhex/source/api/keybinding.cpp index f0990616a..6a3ee5813 100644 --- a/lib/libimhex/source/api/keybinding.cpp +++ b/lib/libimhex/source/api/keybinding.cpp @@ -1,13 +1,14 @@ #include -#include #include -#include +#include namespace hex { + std::map> ShortcutManager::s_globalShortcuts; + void ShortcutManager::addGlobalShortcut(const Shortcut &shortcut, const std::function &callback) { - SharedData::globalShortcuts.insert({ shortcut, callback }); + ShortcutManager::s_globalShortcuts.insert({ shortcut, callback }); } void ShortcutManager::addShortcut(View *view, const Shortcut &shortcut, const std::function &callback) { @@ -30,8 +31,12 @@ namespace hex { if (focused && currentView->m_shortcuts.contains(pressedShortcut)) currentView->m_shortcuts[pressedShortcut](); - else if (SharedData::globalShortcuts.contains(pressedShortcut)) - SharedData::globalShortcuts[pressedShortcut](); + else if (ShortcutManager::s_globalShortcuts.contains(pressedShortcut)) + ShortcutManager::s_globalShortcuts[pressedShortcut](); + } + + void ShortcutManager::clearShortcuts() { + ShortcutManager::s_globalShortcuts.clear(); } } \ No newline at end of file diff --git a/lib/libimhex/source/helpers/lang.cpp b/lib/libimhex/source/api/localization.cpp similarity index 84% rename from lib/libimhex/source/helpers/lang.cpp rename to lib/libimhex/source/api/localization.cpp index 1a44c07de..363dba82d 100644 --- a/lib/libimhex/source/helpers/lang.cpp +++ b/lib/libimhex/source/api/localization.cpp @@ -1,10 +1,11 @@ -#include "hex/helpers/lang.hpp" +#include -#include "hex/helpers/shared_data.hpp" +#include namespace hex { std::string LangEntry::s_fallbackLanguage; + std::map LangEntry::s_currStrings; LanguageDefinition::LanguageDefinition(std::initializer_list> entries) { for (auto pair : entries) @@ -60,7 +61,7 @@ namespace hex { } const std::string &LangEntry::get() const { - auto &lang = SharedData::loadedLanguageStrings; + auto &lang = LangEntry::s_currStrings; if (lang.contains(this->m_unlocalizedString)) return lang[this->m_unlocalizedString]; else @@ -68,7 +69,7 @@ namespace hex { } void LangEntry::loadLanguage(const std::string &language) { - SharedData::loadedLanguageStrings.clear(); + LangEntry::s_currStrings.clear(); auto &definitions = ContentRegistry::Language::getLanguageDefinitions(); @@ -76,12 +77,12 @@ namespace hex { return; for (auto &definition : definitions[language]) - SharedData::loadedLanguageStrings.insert(definition.getEntries().begin(), definition.getEntries().end()); + LangEntry::s_currStrings.insert(definition.getEntries().begin(), definition.getEntries().end()); const auto fallbackLanguage = LangEntry::getFallbackLanguage(); if (language != fallbackLanguage) { for (auto &definition : definitions[fallbackLanguage]) - SharedData::loadedLanguageStrings.insert(definition.getEntries().begin(), definition.getEntries().end()); + LangEntry::s_currStrings.insert(definition.getEntries().begin(), definition.getEntries().end()); } } @@ -97,4 +98,8 @@ namespace hex { return LangEntry::s_fallbackLanguage; } + void LangEntry::resetLanguageStrings() { + LangEntry::s_currStrings.clear(); + } + } \ No newline at end of file diff --git a/main/source/helpers/plugin_manager.cpp b/lib/libimhex/source/api/plugin_manager.cpp similarity index 61% rename from main/source/helpers/plugin_manager.cpp rename to lib/libimhex/source/api/plugin_manager.cpp index 3519b7a38..9021f5d77 100644 --- a/main/source/helpers/plugin_manager.cpp +++ b/lib/libimhex/source/api/plugin_manager.cpp @@ -1,4 +1,4 @@ -#include "helpers/plugin_manager.hpp" +#include #include @@ -17,32 +17,35 @@ namespace hex { auto pluginName = fs::path(path).stem().string(); - this->m_initializePluginFunction = getPluginFunction("initializePlugin"); - this->m_getPluginNameFunction = getPluginFunction("getPluginName"); - this->m_getPluginAuthorFunction = getPluginFunction("getPluginAuthor"); - this->m_getPluginDescriptionFunction = getPluginFunction("getPluginDescription"); - this->m_getCompatibleVersionFunction = getPluginFunction("getCompatibleVersion"); - this->m_setImGuiContextFunction = getPluginFunction("setImGuiContext"); + this->m_initializePluginFunction = getPluginFunction("initializePlugin"); + this->m_getPluginNameFunction = getPluginFunction("getPluginName"); + this->m_getPluginAuthorFunction = getPluginFunction("getPluginAuthor"); + this->m_getPluginDescriptionFunction = getPluginFunction("getPluginDescription"); + this->m_getCompatibleVersionFunction = getPluginFunction("getCompatibleVersion"); + this->m_setImGuiContextFunction = getPluginFunction("setImGuiContext"); + this->m_isBuiltinPluginFunction = getPluginFunction("isBuiltinPlugin"); } Plugin::Plugin(Plugin &&other) noexcept { this->m_handle = other.m_handle; this->m_path = std::move(other.m_path); - this->m_initializePluginFunction = other.m_initializePluginFunction; - this->m_getPluginNameFunction = other.m_getPluginNameFunction; - this->m_getPluginAuthorFunction = other.m_getPluginAuthorFunction; - this->m_getPluginDescriptionFunction = other.m_getPluginDescriptionFunction; - this->m_getCompatibleVersionFunction = other.m_getCompatibleVersionFunction; - this->m_setImGuiContextFunction = other.m_setImGuiContextFunction; + this->m_initializePluginFunction = other.m_initializePluginFunction; + this->m_getPluginNameFunction = other.m_getPluginNameFunction; + this->m_getPluginAuthorFunction = other.m_getPluginAuthorFunction; + this->m_getPluginDescriptionFunction = other.m_getPluginDescriptionFunction; + this->m_getCompatibleVersionFunction = other.m_getCompatibleVersionFunction; + this->m_setImGuiContextFunction = other.m_setImGuiContextFunction; + this->m_isBuiltinPluginFunction = other.m_isBuiltinPluginFunction; - other.m_handle = nullptr; - other.m_initializePluginFunction = nullptr; - other.m_getPluginNameFunction = nullptr; - other.m_getPluginAuthorFunction = nullptr; - other.m_getPluginDescriptionFunction = nullptr; - other.m_getCompatibleVersionFunction = nullptr; - other.m_setImGuiContextFunction = nullptr; + other.m_handle = nullptr; + other.m_initializePluginFunction = nullptr; + other.m_getPluginNameFunction = nullptr; + other.m_getPluginAuthorFunction = nullptr; + other.m_getPluginDescriptionFunction = nullptr; + other.m_getCompatibleVersionFunction = nullptr; + other.m_setImGuiContextFunction = nullptr; + other.m_isBuiltinPluginFunction = nullptr; } Plugin::~Plugin() { @@ -100,6 +103,13 @@ namespace hex { this->m_setImGuiContextFunction(ctx); } + [[nodiscard]] bool Plugin::isBuiltinPlugin() const { + if (this->m_isBuiltinPluginFunction != nullptr) + return this->m_isBuiltinPluginFunction(); + else + return false; + } + const fs::path &Plugin::getPath() const { return this->m_path; } @@ -114,6 +124,9 @@ namespace hex { } + fs::path PluginManager::s_pluginFolder; + std::vector PluginManager::s_plugins; + bool PluginManager::load(const fs::path &pluginFolder) { if (!fs::exists(pluginFolder)) return false; diff --git a/lib/libimhex/source/api/task.cpp b/lib/libimhex/source/api/task.cpp index 306b043e0..6a9c1d8be 100644 --- a/lib/libimhex/source/api/task.cpp +++ b/lib/libimhex/source/api/task.cpp @@ -1,11 +1,16 @@ #include -#include +#include namespace hex { + std::list Task::s_runningTasks; + std::mutex Task::s_taskMutex; + Task::Task(const std::string &unlocalizedName, u64 maxValue) : m_name(LangEntry(unlocalizedName)), m_maxValue(maxValue), m_currValue(0) { - SharedData::runningTasks.push_back(this); + std::scoped_lock lock(Task::s_taskMutex); + + Task::s_runningTasks.push_back(this); } Task::~Task() { @@ -13,7 +18,9 @@ namespace hex { } void Task::finish() { - SharedData::runningTasks.remove(this); + std::scoped_lock lock(Task::s_taskMutex); + + Task::s_runningTasks.remove(this); } void Task::setMaxValue(u64 maxValue) { @@ -40,4 +47,10 @@ namespace hex { return this->m_name; } + size_t Task::getRunningTaskCount() { + std::scoped_lock lock(Task::s_taskMutex); + + return Task::s_runningTasks.size(); + } + } \ No newline at end of file diff --git a/lib/libimhex/source/data_processor/attribute.cpp b/lib/libimhex/source/data_processor/attribute.cpp index 28b47b4bd..aa303d85e 100644 --- a/lib/libimhex/source/data_processor/attribute.cpp +++ b/lib/libimhex/source/data_processor/attribute.cpp @@ -1,10 +1,11 @@ #include -#include namespace hex::dp { - Attribute::Attribute(IOType ioType, Type type, std::string unlocalizedName) : m_id(SharedData::dataProcessorAttrIdCounter++), m_ioType(ioType), m_type(type), m_unlocalizedName(std::move(unlocalizedName)) { + u32 Attribute::s_idCounter = 1; + + Attribute::Attribute(IOType ioType, Type type, std::string unlocalizedName) : m_id(Attribute::s_idCounter++), m_ioType(ioType), m_type(type), m_unlocalizedName(std::move(unlocalizedName)) { } Attribute::~Attribute() { diff --git a/lib/libimhex/source/data_processor/link.cpp b/lib/libimhex/source/data_processor/link.cpp index e43dcbf63..d9da3721f 100644 --- a/lib/libimhex/source/data_processor/link.cpp +++ b/lib/libimhex/source/data_processor/link.cpp @@ -1,10 +1,11 @@ #include -#include namespace hex::dp { - Link::Link(u32 from, u32 to) : m_id(SharedData::dataProcessorLinkIdCounter++), m_from(from), m_to(to) { } + u32 Link::s_idCounter = 1; + + Link::Link(u32 from, u32 to) : m_id(Link::s_idCounter++), m_from(from), m_to(to) { } } \ No newline at end of file diff --git a/lib/libimhex/source/data_processor/node.cpp b/lib/libimhex/source/data_processor/node.cpp index 8e0d062cd..5d5571256 100644 --- a/lib/libimhex/source/data_processor/node.cpp +++ b/lib/libimhex/source/data_processor/node.cpp @@ -1,12 +1,15 @@ #include -#include - #include +#include +#include + namespace hex::dp { - Node::Node(std::string unlocalizedTitle, std::vector attributes) : m_id(SharedData::dataProcessorNodeIdCounter++), m_unlocalizedTitle(std::move(unlocalizedTitle)), m_attributes(std::move(attributes)) { + u32 Node::s_idCounter = 1; + + Node::Node(std::string unlocalizedTitle, std::vector attributes) : m_id(Node::s_idCounter++), m_unlocalizedTitle(std::move(unlocalizedTitle)), m_attributes(std::move(attributes)) { for (auto &attr : this->m_attributes) attr.setParentNode(this); } diff --git a/lib/libimhex/source/helpers/loader_script_handler.cpp b/lib/libimhex/source/helpers/loader_script_handler.cpp index 39008d070..be336b812 100644 --- a/lib/libimhex/source/helpers/loader_script_handler.cpp +++ b/lib/libimhex/source/helpers/loader_script_handler.cpp @@ -3,7 +3,7 @@ #include #include #include -#include +#include #include #define PY_SSIZE_T_CLEAN @@ -179,7 +179,7 @@ namespace hex { } bool LoaderScript::processFile(const fs::path &scriptPath) { - Py_SetProgramName(Py_DecodeLocale((SharedData::mainArgv)[0], nullptr)); + Py_SetProgramName(Py_DecodeLocale("ImHex", nullptr)); for (const auto &dir : hex::getPath(ImHexPath::Python)) { if (fs::exists(fs::path(dir / "lib" / "python" PYTHON_VERSION_MAJOR_MINOR))) { diff --git a/lib/libimhex/source/helpers/project_file_handler.cpp b/lib/libimhex/source/helpers/project_file_handler.cpp index ac21dc47c..a6def008f 100644 --- a/lib/libimhex/source/helpers/project_file_handler.cpp +++ b/lib/libimhex/source/helpers/project_file_handler.cpp @@ -64,7 +64,7 @@ namespace hex { for (auto &element : projectFileData["bookmarks"].items()) { ImHexApi::Bookmarks::Entry entry; from_json(element.value(), entry); - ProjectFile::s_bookmarks.push_back(entry); + ProjectFile::s_bookmarks.emplace_back(std::move(entry)); } } catch (json::exception &e) { diff --git a/lib/libimhex/source/helpers/shared_data.cpp b/lib/libimhex/source/helpers/shared_data.cpp deleted file mode 100644 index fe12de7fd..000000000 --- a/lib/libimhex/source/helpers/shared_data.cpp +++ /dev/null @@ -1,74 +0,0 @@ -#include - -#include - -namespace hex { - - std::vector> SharedData::deferredCalls; - - std::vector SharedData::providers; - u32 SharedData::currentProvider; - - std::map> SharedData::settingsEntries; - nlohmann::json SharedData::settingsJson; - std::vector SharedData::commandPaletteCommands; - std::map SharedData::patternLanguageFunctions; - std::map SharedData::views; - std::vector SharedData::toolsEntries; - std::vector SharedData::dataInspectorEntries; - u32 SharedData::patternPaletteOffset; - std::string SharedData::popupMessage; - std::list SharedData::bookmarkEntries; - std::vector SharedData::patternData; - - u32 SharedData::selectableFileIndex; - std::vector SharedData::selectableFiles; - std::function SharedData::selectableFileOpenCallback; - std::vector SharedData::selectableFilesValidExtensions; - - std::map SharedData::languageNames; - std::map> SharedData::languageDefinitions; - std::map SharedData::loadedLanguageStrings; - - ImGuiID SharedData::dockSpaceId; - - std::multimap SharedData::mainMenuItems; - std::multimap SharedData::menuItems; - - std::vector SharedData::welcomeScreenEntries; - std::vector SharedData::footerItems; - std::vector SharedData::sidebarItems; - std::vector SharedData::toolbarItems; - std::vector SharedData::layouts; - - std::map> SharedData::globalShortcuts; - - std::mutex SharedData::tasksMutex; - std::list SharedData::runningTasks; - - std::vector SharedData::providerNames; - - std::vector SharedData::dataProcessorNodes; - u32 SharedData::dataProcessorNodeIdCounter = 1; - u32 SharedData::dataProcessorLinkIdCounter = 1; - u32 SharedData::dataProcessorAttrIdCounter = 1; - - std::vector SharedData::dataFormatters; - std::vector SharedData::fileHandlers; - - std::list SharedData::recentFilePaths; - - int SharedData::mainArgc; - char **SharedData::mainArgv; - char **SharedData::mainEnvp; - - ImFontAtlas *SharedData::fontAtlas; - ImFontConfig SharedData::fontConfig; - ImVec2 SharedData::windowPos; - ImVec2 SharedData::windowSize; - - float SharedData::globalScale; - float SharedData::fontScale; - - std::map SharedData::sharedVariables; -} diff --git a/lib/libimhex/source/helpers/utils.cpp b/lib/libimhex/source/helpers/utils.cpp index 2a81fe041..6adb33160 100644 --- a/lib/libimhex/source/helpers/utils.cpp +++ b/lib/libimhex/source/helpers/utils.cpp @@ -5,8 +5,13 @@ #include #include +#include + #include -#include + +#include +#define IMGUI_DEFINE_MATH_OPERATORS +#include #if defined(OS_WINDOWS) #include @@ -20,15 +25,15 @@ namespace hex { long double operator""_scaled(long double value) { - return value * SharedData::globalScale; + return value * ImHexApi::System::getGlobalScale(); } long double operator""_scaled(unsigned long long value) { - return value * SharedData::globalScale; + return value * ImHexApi::System::getGlobalScale(); } ImVec2 scaled(const ImVec2 &vector) { - return vector * SharedData::globalScale; + return vector * ImHexApi::System::getGlobalScale(); } std::string to_string(u128 value) { diff --git a/lib/libimhex/source/pattern_language/evaluator.cpp b/lib/libimhex/source/pattern_language/evaluator.cpp index 42320fb31..9753d5da8 100644 --- a/lib/libimhex/source/pattern_language/evaluator.cpp +++ b/lib/libimhex/source/pattern_language/evaluator.cpp @@ -4,8 +4,6 @@ namespace hex::pl { - Evaluator *PatternCreationLimiter::s_evaluator = nullptr; - void Evaluator::createParameterPack(const std::string &name, const std::vector &values) { this->getScope(0).parameterPack = ParameterPack { name, @@ -31,19 +29,19 @@ namespace hex::pl { LogConsole::abortEvaluation("cannot determine type of auto variable", type); if (std::get_if(&value.value()) != nullptr) - pattern = new PatternDataUnsigned(0, sizeof(u128)); + pattern = new PatternDataUnsigned(this, 0, sizeof(u128)); else if (std::get_if(&value.value()) != nullptr) - pattern = new PatternDataSigned(0, sizeof(i128)); + pattern = new PatternDataSigned(this, 0, sizeof(i128)); else if (std::get_if(&value.value()) != nullptr) - pattern = new PatternDataFloat(0, sizeof(double)); + pattern = new PatternDataFloat(this, 0, sizeof(double)); else if (std::get_if(&value.value()) != nullptr) - pattern = new PatternDataBoolean(0); + pattern = new PatternDataBoolean(this, 0); else if (std::get_if(&value.value()) != nullptr) - pattern = new PatternDataCharacter(0); + pattern = new PatternDataCharacter(this, 0); else if (std::get_if(&value.value()) != nullptr) pattern = std::get(value.value())->clone(); else if (std::get_if(&value.value()) != nullptr) - pattern = new PatternDataString(0, 1); + pattern = new PatternDataString(this, 0, 1); else LogConsole::abortEvaluation("cannot determine type of auto variable", type); } @@ -154,8 +152,6 @@ namespace hex::pl { std::vector patterns; - PatternCreationLimiter::s_evaluator = this; - try { this->setCurrentControlFlowStatement(ControlFlowStatement::None); pushScope(nullptr, patterns); diff --git a/lib/libimhex/source/pattern_language/parser.cpp b/lib/libimhex/source/pattern_language/parser.cpp index 56dd019e9..4350e7866 100644 --- a/lib/libimhex/source/pattern_language/parser.cpp +++ b/lib/libimhex/source/pattern_language/parser.cpp @@ -663,10 +663,18 @@ namespace hex::pl { if (!MATCHES(sequence(SEPARATOR_COMMA))) throwParserError("expected ',' after for loop condition"); - if (!MATCHES(sequence(IDENTIFIER, OPERATOR_ASSIGNMENT))) - throwParserError("expected for loop variable assignment"); + ASTNode *postExpression = nullptr; + if (MATCHES(sequence(IDENTIFIER, OPERATOR_ASSIGNMENT))) + postExpression = parseFunctionVariableAssignment(getValue(-2).get()); + else if (MATCHES(sequence(OPERATOR_DOLLAR, OPERATOR_ASSIGNMENT))) + postExpression = parseFunctionVariableAssignment("$"); + else if (MATCHES(oneOf(IDENTIFIER) && oneOf(OPERATOR_PLUS, OPERATOR_MINUS, OPERATOR_STAR, OPERATOR_SLASH, OPERATOR_PERCENT, OPERATOR_SHIFTLEFT, OPERATOR_SHIFTRIGHT, OPERATOR_BITOR, OPERATOR_BITAND, OPERATOR_BITXOR) && sequence(OPERATOR_ASSIGNMENT))) + postExpression = parseFunctionVariableCompoundAssignment(getValue(-3).get()); + else if (MATCHES(oneOf(OPERATOR_DOLLAR) && oneOf(OPERATOR_PLUS, OPERATOR_MINUS, OPERATOR_STAR, OPERATOR_SLASH, OPERATOR_PERCENT, OPERATOR_SHIFTLEFT, OPERATOR_SHIFTRIGHT, OPERATOR_BITOR, OPERATOR_BITAND, OPERATOR_BITXOR) && sequence(OPERATOR_ASSIGNMENT))) + postExpression = parseFunctionVariableCompoundAssignment("$"); + else + throwParserError("expected variable assignment in for loop post expression"); - auto postExpression = parseFunctionVariableAssignment(getValue(-2).get()); auto postExpressionCleanup = SCOPE_GUARD { delete postExpression; }; std::vector body; diff --git a/lib/libimhex/source/pattern_language/pattern_language.cpp b/lib/libimhex/source/pattern_language/pattern_language.cpp index 2a5dc0d6a..ab58b2a14 100644 --- a/lib/libimhex/source/pattern_language/pattern_language.cpp +++ b/lib/libimhex/source/pattern_language/pattern_language.cpp @@ -123,7 +123,10 @@ namespace hex::pl { return ast; } - std::optional> PatternLanguage::executeString(prv::Provider *provider, const std::string &code, const std::map &envVars, const std::map &inVariables) { + bool PatternLanguage::executeString(prv::Provider *provider, const std::string &code, const std::map &envVars, const std::map &inVariables) { + this->m_running = true; + ON_SCOPE_EXIT { this->m_running = false; }; + this->m_currError.reset(); this->m_evaluator->getConsole().clear(); this->m_evaluator->setProvider(provider); @@ -143,20 +146,22 @@ namespace hex::pl { auto ast = this->parseString(code); if (!ast) - return std::nullopt; + return false; this->m_currAST = ast.value(); auto patterns = this->m_evaluator->evaluate(ast.value()); if (!patterns.has_value()) { this->m_currError = this->m_evaluator->getConsole().getLastHardError(); - return std::nullopt; + return false; } - return patterns; + this->m_patterns = std::move(patterns.value()); + + return true; } - std::optional> PatternLanguage::executeFile(prv::Provider *provider, const fs::path &path, const std::map &envVars, const std::map &inVariables) { + bool PatternLanguage::executeFile(prv::Provider *provider, const fs::path &path, const std::map &envVars, const std::map &inVariables) { File file(path, File::Mode::Read); return this->executeString(provider, file.readString(), envVars, inVariables); @@ -200,4 +205,12 @@ namespace hex::pl { return this->m_evaluator->hasDangerousFunctionBeenCalled(); } + void PatternLanguage::reset() { + for (auto &pattern : this->m_patterns) + delete pattern; + this->m_patterns.clear(); + + this->m_currAST.clear(); + } + } \ No newline at end of file diff --git a/lib/libimhex/source/providers/provider.cpp b/lib/libimhex/source/providers/provider.cpp index 2eb59eb51..2c80c226f 100644 --- a/lib/libimhex/source/providers/provider.cpp +++ b/lib/libimhex/source/providers/provider.cpp @@ -2,6 +2,7 @@ #include #include +#include #include #include diff --git a/lib/libimhex/source/views/view.cpp b/lib/libimhex/source/ui/view.cpp similarity index 68% rename from lib/libimhex/source/views/view.cpp rename to lib/libimhex/source/ui/view.cpp index 0dedb50a2..8d37f4b16 100644 --- a/lib/libimhex/source/views/view.cpp +++ b/lib/libimhex/source/ui/view.cpp @@ -1,4 +1,4 @@ -#include +#include #include @@ -6,48 +6,54 @@ #include #include -#include - namespace hex { + std::string View::s_popupMessage; + + u32 View::s_selectableFileIndex; + std::vector View::s_selectableFiles; + std::function View::s_selectableFileOpenCallback; + std::vector View::s_selectableFilesValidExtensions; + + ImFontAtlas *View::s_fontAtlas; + ImFontConfig View::s_fontConfig; + View::View(std::string unlocalizedName) : m_unlocalizedViewName(unlocalizedName) { } bool View::isAvailable() const { return ImHexApi::Provider::isValid() && ImHexApi::Provider::get()->isAvailable(); } - std::vector> &View::getDeferedCalls() { - return SharedData::deferredCalls; - } - void View::drawCommonInterfaces() { + auto windowSize = ImHexApi::System::getMainWindowSize(); + ImGui::SetNextWindowSizeConstraints(scaled(ImVec2(400, 100)), scaled(ImVec2(600, 300))); if (ImGui::BeginPopupModal("hex.common.info"_lang, nullptr, ImGuiWindowFlags_AlwaysAutoResize)) { - ImGui::TextFormattedWrapped("{}", SharedData::popupMessage.c_str()); + ImGui::TextFormattedWrapped("{}", s_popupMessage.c_str()); ImGui::NewLine(); ImGui::Separator(); if (ImGui::Button("hex.common.okay"_lang) || ImGui::IsKeyDown(ImGuiKey_Escape)) ImGui::CloseCurrentPopup(); - ImGui::SetWindowPos((SharedData::windowSize - ImGui::GetWindowSize()) / 2, ImGuiCond_Appearing); + ImGui::SetWindowPos((windowSize - ImGui::GetWindowSize()) / 2, ImGuiCond_Appearing); ImGui::EndPopup(); } ImGui::SetNextWindowSizeConstraints(scaled(ImVec2(400, 100)), scaled(ImVec2(600, 300))); if (ImGui::BeginPopupModal("hex.common.error"_lang, nullptr, ImGuiWindowFlags_AlwaysAutoResize)) { - ImGui::TextFormattedWrapped("{}", SharedData::popupMessage.c_str()); + ImGui::TextFormattedWrapped("{}", s_popupMessage.c_str()); ImGui::NewLine(); ImGui::Separator(); if (ImGui::Button("hex.common.okay"_lang) || ImGui::IsKeyDown(ImGuiKey_Escape)) ImGui::CloseCurrentPopup(); - ImGui::SetWindowPos((SharedData::windowSize - ImGui::GetWindowSize()) / 2, ImGuiCond_Appearing); + ImGui::SetWindowPos((windowSize - ImGui::GetWindowSize()) / 2, ImGuiCond_Appearing); ImGui::EndPopup(); } ImGui::SetNextWindowSizeConstraints(scaled(ImVec2(400, 100)), scaled(ImVec2(600, 300))); if (ImGui::BeginPopupModal("hex.common.fatal"_lang, nullptr, ImGuiWindowFlags_AlwaysAutoResize)) { - ImGui::TextFormattedWrapped("{}", SharedData::popupMessage.c_str()); + ImGui::TextFormattedWrapped("{}", s_popupMessage.c_str()); ImGui::NewLine(); ImGui::Separator(); if (ImGui::Button("hex.common.okay"_lang) || ImGui::IsKeyDown(ImGuiKey_Escape)) { @@ -55,7 +61,7 @@ namespace hex { ImGui::CloseCurrentPopup(); } - ImGui::SetWindowPos((SharedData::windowSize - ImGui::GetWindowSize()) / 2, ImGuiCond_Appearing); + ImGui::SetWindowPos((windowSize - ImGui::GetWindowSize()) / 2, ImGuiCond_Appearing); ImGui::EndPopup(); } @@ -66,9 +72,9 @@ namespace hex { if (ImGui::BeginListBox("##files", ImVec2(300_scaled, 0))) { u32 index = 0; - for (auto &path : SharedData::selectableFiles) { - if (ImGui::Selectable(path.filename().string().c_str(), index == SharedData::selectableFileIndex)) - SharedData::selectableFileIndex = index; + for (auto &path : View::s_selectableFiles) { + if (ImGui::Selectable(path.filename().string().c_str(), index == View::s_selectableFileIndex)) + View::s_selectableFileIndex = index; index++; } @@ -76,15 +82,15 @@ namespace hex { } if (ImGui::Button("hex.common.open"_lang)) { - SharedData::selectableFileOpenCallback(SharedData::selectableFiles[SharedData::selectableFileIndex]); + View::s_selectableFileOpenCallback(View::s_selectableFiles[View::s_selectableFileIndex]); ImGui::CloseCurrentPopup(); } ImGui::SameLine(); if (ImGui::Button("hex.common.browse"_lang)) { - hex::openFileBrowser("hex.common.open"_lang, DialogMode::Open, SharedData::selectableFilesValidExtensions, [](const auto &path) { - SharedData::selectableFileOpenCallback(path); + hex::openFileBrowser("hex.common.open"_lang, DialogMode::Open, View::s_selectableFilesValidExtensions, [](const auto &path) { + View::s_selectableFileOpenCallback(path); ImGui::CloseCurrentPopup(); }); } @@ -94,30 +100,30 @@ namespace hex { } void View::showMessagePopup(const std::string &message) { - SharedData::popupMessage = message; + s_popupMessage = message; - View::doLater([] { ImGui::OpenPopup("hex.common.info"_lang); }); + ImHexApi::Tasks::doLater([] { ImGui::OpenPopup("hex.common.info"_lang); }); } void View::showErrorPopup(const std::string &errorMessage) { - SharedData::popupMessage = errorMessage; + s_popupMessage = errorMessage; - View::doLater([] { ImGui::OpenPopup("hex.common.error"_lang); }); + ImHexApi::Tasks::doLater([] { ImGui::OpenPopup("hex.common.error"_lang); }); } void View::showFatalPopup(const std::string &errorMessage) { - SharedData::popupMessage = errorMessage; + s_popupMessage = errorMessage; - View::doLater([] { ImGui::OpenPopup("hex.common.fatal"_lang); }); + ImHexApi::Tasks::doLater([] { ImGui::OpenPopup("hex.common.fatal"_lang); }); } void View::showFileChooserPopup(const std::vector &paths, const std::vector &validExtensions, const std::function &callback) { - SharedData::selectableFileIndex = 0; - SharedData::selectableFiles = paths; - SharedData::selectableFilesValidExtensions = validExtensions; - SharedData::selectableFileOpenCallback = callback; + View::s_selectableFileIndex = 0; + View::s_selectableFiles = paths; + View::s_selectableFilesValidExtensions = validExtensions; + View::s_selectableFileOpenCallback = callback; - View::doLater([] { ImGui::OpenPopup("hex.common.choose_file"_lang); }); + ImHexApi::Tasks::doLater([] { ImGui::OpenPopup("hex.common.choose_file"_lang); }); } bool View::hasViewMenuItemEntry() const { @@ -154,10 +160,6 @@ namespace hex { ImGui::GetIO().ConfigFlags &= ~ImGuiConfigFlags_NavEnableKeyboard; } - void View::doLater(std::function &&function) { - SharedData::deferredCalls.push_back(function); - } - void View::confirmButtons(const std::string &textLeft, const std::string &textRight, const std::function &leftButtonFn, const std::function &rightButtonFn) { auto width = ImGui::GetWindowWidth(); ImGui::SetCursorPosX(width / 9); diff --git a/main/CMakeLists.txt b/main/CMakeLists.txt index caa4ec59b..38dafe82f 100644 --- a/main/CMakeLists.txt +++ b/main/CMakeLists.txt @@ -11,8 +11,6 @@ add_executable(main ${application_type} source/init/splash_window.cpp source/init/tasks.cpp - source/helpers/plugin_manager.cpp - ${IMHEX_ICON} ) @@ -25,7 +23,7 @@ set_target_properties(main PROPERTIES POSITION_INDEPENDENT_CODE ON) if (WIN32) - target_link_libraries(main PUBLIC dl libimhex wsock32 ws2_32 Dwmapi.lib) + target_link_libraries(main PUBLIC libimhex wsock32 ws2_32 Dwmapi.lib) else () - target_link_libraries(main PUBLIC dl libimhex pthread) + target_link_libraries(main PUBLIC libimhex pthread) endif () \ No newline at end of file diff --git a/main/include/init/tasks.hpp b/main/include/init/tasks.hpp index 56c5c7bff..c464f2245 100644 --- a/main/include/init/tasks.hpp +++ b/main/include/init/tasks.hpp @@ -11,12 +11,6 @@ namespace hex::init { std::function function; }; - struct Argument { - std::string name, value; - }; - std::vector getInitTasks(); std::vector getExitTasks(); - - std::vector &getInitArguments(); } \ No newline at end of file diff --git a/main/include/window.hpp b/main/include/window.hpp index 77d02c38b..8db24cb4f 100644 --- a/main/include/window.hpp +++ b/main/include/window.hpp @@ -6,7 +6,7 @@ #include #include -#include +#include struct GLFWwindow; struct ImGuiSettingsHandler; @@ -47,7 +47,6 @@ namespace hex { GLFWwindow *m_window = nullptr; - double m_targetFps = 60.0; bool m_layoutConfigured = false; std::string m_windowTitle; diff --git a/main/source/init/splash_window.cpp b/main/source/init/splash_window.cpp index 0d0b414fd..66bc16161 100644 --- a/main/source/init/splash_window.cpp +++ b/main/source/init/splash_window.cpp @@ -1,9 +1,9 @@ #include "init/splash_window.hpp" +#include #include #include #include -#include #include @@ -80,7 +80,7 @@ namespace hex::init { auto tasksSucceeded = processTasksAsync(); - auto scale = SharedData::globalScale; + auto scale = ImHexApi::System::getGlobalScale(); while (!glfwWindowShouldClose(this->m_window)) { glfwPollEvents(); @@ -168,18 +168,20 @@ namespace hex::init { float xScale = 0, yScale = 0; glfwGetMonitorContentScale(monitor, &xScale, &yScale); - SharedData::globalScale = SharedData::fontScale = std::midpoint(xScale, yScale); + auto meanScale = std::midpoint(xScale, yScale); -// On Macs with a retina display (basically all modern ones we care about), the OS reports twice -// the actual monitor scale for some obscure reason. Get rid of this here so ImHex doesn't look -// extremely huge with native scaling on MacOS. -#if defined(OS_MACOS) - SharedData::globalScale /= 2; -#endif + // On Macs with a retina display (basically all modern ones we care about), the OS reports twice + // the actual monitor scale for some obscure reason. Get rid of this here so ImHex doesn't look + // extremely huge with native scaling on MacOS. + #if defined(OS_MACOS) + meanScale /= 2; + #endif - if (SharedData::globalScale <= 0) { - SharedData::globalScale = 1.0; + if (meanScale <= 0) { + meanScale = 1.0; } + + ImHexApi::System::impl::setGlobalScale(meanScale); } this->m_window = glfwCreateWindow(640_scaled, 400_scaled, "Starting ImHex...", nullptr, nullptr); @@ -204,7 +206,7 @@ namespace hex::init { auto &io = ImGui::GetIO(); - ImGui::GetStyle().ScaleAllSizes(SharedData::globalScale); + ImGui::GetStyle().ScaleAllSizes(ImHexApi::System::getGlobalScale()); io.Fonts->Clear(); diff --git a/main/source/init/tasks.cpp b/main/source/init/tasks.cpp index 0d072a158..72f251fee 100644 --- a/main/source/init/tasks.cpp +++ b/main/source/init/tasks.cpp @@ -12,7 +12,7 @@ #include #include -#include "helpers/plugin_manager.hpp" +#include #include @@ -37,7 +37,7 @@ namespace hex::init { auto latestVersion = releases.body["tag_name"].get(); if (latestVersion != currVersion) - getInitArguments().push_back({ "update-available", latestVersion.data() }); + ImHexApi::System::getInitArguments().insert({ "update-available", latestVersion.data() }); return true; } @@ -49,7 +49,7 @@ namespace hex::init { if (tip.code != 200) return false; - getInitArguments().push_back({ "tip-of-the-day", tip.body }); + ImHexApi::System::getInitArguments().insert({ "tip-of-the-day", tip.body }); return true; } @@ -83,17 +83,14 @@ namespace hex::init { } if (!result) - getInitArguments().push_back({ "folder-creation-error", {} }); + ImHexApi::System::getInitArguments().insert({ "folder-creation-error", {} }); return result; } bool loadFonts() { - auto &fonts = SharedData::fontAtlas; - auto &cfg = SharedData::fontConfig; - - fonts = IM_NEW(ImFontAtlas)(); - cfg = {}; + auto fonts = IM_NEW(ImFontAtlas)(); + ImFontConfig cfg = {}; fs::path fontFile; for (const auto &dir : hex::getPath(ImHexPath::Resources)) { @@ -131,84 +128,79 @@ namespace hex::init { 0x0020, 0xFFF0, 0 }; - + float fontSize = 13.0F * ImHexApi::System::getGlobalScale(); if (fontFile.empty()) { // Load default font fonts->Clear(); cfg.OversampleH = cfg.OversampleV = 1, cfg.PixelSnapH = true; - cfg.SizePixels = 13.0F * SharedData::fontScale; + cfg.SizePixels = fontSize; fonts->AddFontDefault(&cfg); } else { // Load custom font - auto fontSize = ContentRegistry::Settings::read("hex.builtin.setting.interface", "hex.builtin.setting.interface.font_size", 14); + fontSize = ContentRegistry::Settings::read("hex.builtin.setting.interface", "hex.builtin.setting.interface.font_size", 14) * ImHexApi::System::getGlobalScale(); cfg.OversampleH = cfg.OversampleV = 1, cfg.PixelSnapH = true; - cfg.SizePixels = fontSize * SharedData::fontScale; + cfg.SizePixels = fontSize; - fonts->AddFontFromFileTTF(fontFile.string().c_str(), std::floor(fontSize * SharedData::fontScale), &cfg, ranges.Data); // Needs conversion to char for Windows + fonts->AddFontFromFileTTF(fontFile.string().c_str(), std::floor(fontSize), &cfg, ranges.Data); // Needs conversion to char for Windows } cfg.MergeMode = true; - fonts->AddFontFromMemoryCompressedTTF(font_awesome_compressed_data, font_awesome_compressed_size, 13.0F * SharedData::fontScale, &cfg, fontAwesomeRange); - fonts->AddFontFromMemoryCompressedTTF(codicons_compressed_data, codicons_compressed_size, 13.0F * SharedData::fontScale, &cfg, codiconsRange); - fonts->AddFontFromMemoryCompressedTTF(unifont_compressed_data, unifont_compressed_size, 13.0F * SharedData::fontScale, &cfg, unifontRange); + fonts->AddFontFromMemoryCompressedTTF(font_awesome_compressed_data, font_awesome_compressed_size, fontSize, &cfg, fontAwesomeRange); + fonts->AddFontFromMemoryCompressedTTF(codicons_compressed_data, codicons_compressed_size, fontSize, &cfg, codiconsRange); + fonts->AddFontFromMemoryCompressedTTF(unifont_compressed_data, unifont_compressed_size, fontSize, &cfg, unifontRange); ImGuiFreeType::BuildFontAtlas(fonts); + View::setFontAtlas(fonts); + View::setFontConfig(cfg); + return true; } bool deleteSharedData() { - SharedData::deferredCalls.clear(); + ImHexApi::Tasks::getDeferredCalls().clear(); while (ImHexApi::Provider::isValid()) ImHexApi::Provider::remove(ImHexApi::Provider::get()); + ContentRegistry::Provider::getEntries().clear(); - SharedData::settingsEntries.clear(); - SharedData::settingsJson.clear(); + ContentRegistry::Settings::getEntries().clear(); + ContentRegistry::Settings::getSettingsData().clear(); - SharedData::commandPaletteCommands.clear(); - SharedData::patternLanguageFunctions.clear(); + ContentRegistry::CommandPaletteCommands::getEntries().clear(); + ContentRegistry::PatternLanguage::getFunctions().clear(); + ContentRegistry::PatternLanguage::getPalettes().clear(); for (auto &[name, view] : ContentRegistry::Views::getEntries()) delete view; - SharedData::views.clear(); + ContentRegistry::Views::getEntries().clear(); - SharedData::toolsEntries.clear(); + ContentRegistry::Tools::getEntries().clear(); + ContentRegistry::DataInspector::getEntries().clear(); - SharedData::dataInspectorEntries.clear(); + ContentRegistry::Language::getLanguages().clear(); + ContentRegistry::Language::getLanguageDefinitions().clear(); + LangEntry::resetLanguageStrings(); - SharedData::bookmarkEntries.clear(); + ContentRegistry::Interface::getWelcomeScreenEntries().clear(); + ContentRegistry::Interface::getFooterItems().clear(); + ContentRegistry::Interface::getToolbarItems().clear(); + ContentRegistry::Interface::getMainMenuItems().clear(); + ContentRegistry::Interface::getMenuItems().clear(); - for (auto &pattern : SharedData::patternData) - delete pattern; - SharedData::patternData.clear(); + ShortcutManager::clearShortcuts(); - SharedData::languageNames.clear(); - SharedData::languageDefinitions.clear(); - SharedData::loadedLanguageStrings.clear(); + hex::Task::getRunningTasks().clear(); - SharedData::welcomeScreenEntries.clear(); - SharedData::footerItems.clear(); - SharedData::toolbarItems.clear(); - SharedData::mainMenuItems.clear(); - SharedData::menuItems.clear(); + ContentRegistry::DataProcessorNode::getEntries().clear(); - SharedData::globalShortcuts.clear(); - SharedData::runningTasks.clear(); - - SharedData::dataProcessorNodes.clear(); - - SharedData::recentFilePaths.clear(); - - SharedData::dataFormatters.clear(); - SharedData::fileHandlers.clear(); - - SharedData::clearVariables(); + ContentRegistry::DataFormatter::getEntries().clear(); + ContentRegistry::FileHandler::getEntries().clear(); return true; } @@ -218,16 +210,41 @@ namespace hex::init { PluginManager::load(dir); } - if (PluginManager::getPlugins().empty()) { + auto &plugins = PluginManager::getPlugins(); + + if (plugins.empty()) { log::error("No plugins found!"); - getInitArguments().push_back({ "no-plugins", {} }); + ImHexApi::System::getInitArguments().insert({ "no-plugins", {} }); return false; } - for (const auto &plugin : PluginManager::getPlugins()) { - if (!plugin.initializePlugin()) + u32 builtinPlugins = 0; + u32 loadErrors = 0; + for (const auto &plugin : plugins) { + if (!plugin.initializePlugin()) { log::error("Failed to initialize plugin {}", plugin.getPath().filename().string()); + loadErrors++; + } else { + if (plugin.isBuiltinPlugin()) + builtinPlugins++; + } + } + + if (loadErrors == plugins.size()) { + log::error("No plugins loaded successfully!"); + ImHexApi::System::getInitArguments().insert({ "no-plugins", {} }); + return false; + } + + if (builtinPlugins == 0) { + log::error("Built-in plugin not found!"); + ImHexApi::System::getInitArguments().insert({ "no-plugins", {} }); + return false; + } else if (builtinPlugins > 1) { + log::error("Found more than one built-in plugin!"); + ImHexApi::System::getInitArguments().insert({ "no-plugins", {} }); + return false; } return true; @@ -247,25 +264,28 @@ namespace hex::init { return false; } + float interfaceScaling = 1.0F; switch (ContentRegistry::Settings::read("hex.builtin.setting.interface", "hex.builtin.setting.interface.scaling", 0)) { default: case 0: // Native scaling break; case 1: - SharedData::globalScale = SharedData::fontScale = 0.5F; + interfaceScaling = 0.5F; break; case 2: - SharedData::globalScale = SharedData::fontScale = 1.0F; + interfaceScaling = 1.0F; break; case 3: - SharedData::globalScale = SharedData::fontScale = 1.5F; + interfaceScaling = 1.5F; break; case 4: - SharedData::globalScale = SharedData::fontScale = 2.0F; + interfaceScaling = 2.0F; break; } + ImHexApi::System::impl::setGlobalScale(interfaceScaling); + return true; } @@ -281,7 +301,7 @@ namespace hex::init { std::vector getInitTasks() { return { - {"Checking for updates...", checkForUpdates }, + { "Checking for updates...", checkForUpdates }, { "Downloading information...", downloadInformation}, { "Creating directories...", createDirectories }, { "Loading settings...", loadSettings }, @@ -292,16 +312,10 @@ namespace hex::init { std::vector getExitTasks() { return { - {"Saving settings...", storeSettings }, - { "Cleaning up shared data...", deleteSharedData}, - { "Unloading plugins...", unloadPlugins }, + { "Saving settings...", storeSettings }, + { "Cleaning up shared data...", deleteSharedData }, + { "Unloading plugins...", unloadPlugins }, }; } - std::vector &getInitArguments() { - static std::vector initArguments; - - return initArguments; - } - } \ No newline at end of file diff --git a/main/source/main.cpp b/main/source/main.cpp index 9134e127d..201d15150 100644 --- a/main/source/main.cpp +++ b/main/source/main.cpp @@ -2,7 +2,6 @@ #include #include -#include #include "window.hpp" @@ -12,11 +11,8 @@ #include int main(int argc, char **argv, char **envp) { - hex::SharedData::mainArgc = argc; - hex::SharedData::mainArgv = argv; - hex::SharedData::mainEnvp = envp; - using namespace hex; + ImHexApi::System::impl::setProgramArguments(argc, argv, envp); // Initialization { @@ -30,7 +26,7 @@ int main(int argc, char **argv, char **envp) { splashWindow.addStartupTask(name, task); if (!splashWindow.loop()) - init::getInitArguments().push_back({ "tasks-failed", {} }); + ImHexApi::System::getInitArguments().insert({ "tasks-failed", {} }); } // Clean up diff --git a/main/source/window/linux_window.cpp b/main/source/window/linux_window.cpp index 155ac05de..5cd581e38 100644 --- a/main/source/window/linux_window.cpp +++ b/main/source/window/linux_window.cpp @@ -2,6 +2,9 @@ #if defined(OS_LINUX) + #include + #include + #include #include diff --git a/main/source/window/macos_window.cpp b/main/source/window/macos_window.cpp index f1acfc929..b44f6f9a4 100644 --- a/main/source/window/macos_window.cpp +++ b/main/source/window/macos_window.cpp @@ -2,6 +2,9 @@ #if defined(OS_MACOS) + #include + #include + #include #include diff --git a/main/source/window/win_window.cpp b/main/source/window/win_window.cpp index 8b471b04f..38cdbcd29 100644 --- a/main/source/window/win_window.cpp +++ b/main/source/window/win_window.cpp @@ -1,5 +1,6 @@ #include "window.hpp" +#include #if defined(OS_WINDOWS) @@ -89,8 +90,8 @@ namespace hex { POINT cursor = { GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam) }; const POINT border { - static_cast((::GetSystemMetrics(SM_CXFRAME) + ::GetSystemMetrics(SM_CXPADDEDBORDER)) * SharedData::globalScale / 1.5F), - static_cast((::GetSystemMetrics(SM_CYFRAME) + ::GetSystemMetrics(SM_CXPADDEDBORDER)) * SharedData::globalScale / 1.5F) + static_cast((::GetSystemMetrics(SM_CXFRAME) + ::GetSystemMetrics(SM_CXPADDEDBORDER)) * ImHexApi::System::getGlobalScale() / 1.5F), + static_cast((::GetSystemMetrics(SM_CYFRAME) + ::GetSystemMetrics(SM_CXPADDEDBORDER)) * ImHexApi::System::getGlobalScale() / 1.5F) }; RECT window; @@ -205,8 +206,10 @@ namespace hex { if (!globalMutex) { globalMutex = CreateMutex(nullptr, FALSE, UniqueMutexId); } else { - if (SharedData::mainArgc > 1) { + if (ImHexApi::System::getProgramArguments().argc > 1) { ::EnumWindows([](HWND hWnd, LPARAM lparam) -> BOOL { + auto &programArgs = ImHexApi::System::getProgramArguments(); + auto length = ::GetWindowTextLength(hWnd); std::string windowName(length + 1, '\x00'); ::GetWindowText(hWnd, windowName.data(), windowName.size()); @@ -215,8 +218,8 @@ namespace hex { if (windowName.starts_with("ImHex")) { COPYDATASTRUCT message = { .dwData = 0, - .cbData = static_cast(std::strlen(SharedData::mainArgv[1])) + 1, - .lpData = SharedData::mainArgv[1] + .cbData = static_cast(std::strlen(programArgs.argv[1])) + 1, + .lpData = programArgs.argv[1] }; SendMessage(hWnd, WM_COPYDATA, reinterpret_cast(hWnd), reinterpret_cast(&message)); diff --git a/main/source/window/window.cpp b/main/source/window/window.cpp index 11b3ec947..5e36419ae 100644 --- a/main/source/window/window.cpp +++ b/main/source/window/window.cpp @@ -2,6 +2,10 @@ #include +#include +#include +#include + #include #include #include @@ -33,7 +37,6 @@ #include #include -#include "helpers/plugin_manager.hpp" #include #include "init/tasks.hpp" @@ -70,17 +73,9 @@ namespace hex { Window::Window() { { - for (const auto &[argument, value] : init::getInitArguments()) { - if (argument == "update-available") { - this->m_availableUpdate = value; - } else if (argument == "no-plugins") { - View::doLater([] { ImGui::OpenPopup("No Plugins"); }); - } else if (argument == "tip-of-the-day") { - this->m_tipOfTheDay = value; - - this->m_showTipOfTheDay = ContentRegistry::Settings::read("hex.builtin.setting.general", "hex.builtin.setting.general.show_tips", 1); - if (this->m_showTipOfTheDay) - View::doLater([] { ImGui::OpenPopup("hex.welcome.tip_of_the_day"_lang); }); + for (const auto &[argument, value] : ImHexApi::System::getInitArguments()) { + if (argument == "no-plugins") { + ImHexApi::Tasks::doLater([] { ImGui::OpenPopup("No Plugins"); }); } } } @@ -89,127 +84,6 @@ namespace hex { this->initImGui(); this->setupNativeWindow(); - EventManager::subscribe(this, [this]() { - { - auto theme = ContentRegistry::Settings::getSetting("hex.builtin.setting.interface", "hex.builtin.setting.interface.color"); - - if (theme.is_number()) - EventManager::post(theme.get()); - } - - { - auto language = ContentRegistry::Settings::getSetting("hex.builtin.setting.interface", "hex.builtin.setting.interface.language"); - - if (language.is_string()) { - LangEntry::loadLanguage(static_cast(language)); - } else { - // If no language is specified, fall back to English. - LangEntry::loadLanguage("en-US"); - } - } - - { - auto targetFps = ContentRegistry::Settings::getSetting("hex.builtin.setting.interface", "hex.builtin.setting.interface.fps"); - - if (targetFps.is_number()) - this->m_targetFps = targetFps; - } - - { - if (ContentRegistry::Settings::read("hex.builtin.setting.imhex", "hex.builtin.setting.imhex.launched", 0) == 1) - this->m_layoutConfigured = true; - else - ContentRegistry::Settings::write("hex.builtin.setting.imhex", "hex.builtin.setting.imhex.launched", 1); - } - }); - - EventManager::subscribe(this, [this](u32 theme) { - if (this->m_bannerTexture.valid()) - ImGui::UnloadImage(this->m_bannerTexture); - - switch (theme) { - default: - case 1: /* Dark theme */ - { - ImGui::StyleColorsDark(); - ImGui::StyleCustomColorsDark(); - ImPlot::StyleColorsDark(); - - auto banner = romfs::get("banner_dark.png"); - this->m_bannerTexture = ImGui::LoadImageFromMemory(reinterpret_cast(banner.data()), banner.size()); - - break; - } - case 2: /* Light theme */ - { - ImGui::StyleColorsLight(); - ImGui::StyleCustomColorsLight(); - ImPlot::StyleColorsLight(); - - auto banner = romfs::get("banner_light.png"); - this->m_bannerTexture = ImGui::LoadImageFromMemory(reinterpret_cast(banner.data()), banner.size()); - - break; - } - case 3: /* Classic theme */ - { - ImGui::StyleColorsClassic(); - ImGui::StyleCustomColorsClassic(); - ImPlot::StyleColorsClassic(); - - auto banner = romfs::get("banner_dark.png"); - this->m_bannerTexture = ImGui::LoadImageFromMemory(reinterpret_cast(banner.data()), banner.size()); - - break; - } - } - - ImGui::GetStyle().Colors[ImGuiCol_DockingEmptyBg] = ImGui::GetStyle().Colors[ImGuiCol_WindowBg]; - ImGui::GetStyle().Colors[ImGuiCol_TitleBg] = ImGui::GetStyle().Colors[ImGuiCol_MenuBarBg]; - ImGui::GetStyle().Colors[ImGuiCol_TitleBgActive] = ImGui::GetStyle().Colors[ImGuiCol_MenuBarBg]; - ImGui::GetStyle().Colors[ImGuiCol_TitleBgCollapsed] = ImGui::GetStyle().Colors[ImGuiCol_MenuBarBg]; - - if (!this->m_bannerTexture.valid()) { - log::fatal("Failed to load banner texture!"); - std::abort(); - } - }); - - EventManager::subscribe(this, [](const auto &path) { - SharedData::recentFilePaths.push_front(path); - - { - std::list uniques; - for (auto &file : SharedData::recentFilePaths) { - - bool exists = false; - for (auto &unique : uniques) { - if (file == unique) - exists = true; - } - - if (!exists && !file.empty()) - uniques.push_back(file); - - if (uniques.size() > 5) - break; - } - SharedData::recentFilePaths = uniques; - } - - { - std::vector recentFilesVector; - for (const auto &recentPath : SharedData::recentFilePaths) - recentFilesVector.push_back(recentPath.string()); - - ContentRegistry::Settings::write("hex.builtin.setting.imhex", "hex.builtin.setting.imhex.recent_files", recentFilesVector); - } - }); - - EventManager::subscribe(this, [] { - EventManager::post(""); - }); - EventManager::subscribe(this, [this](bool noQuestions) { glfwSetWindowShouldClose(this->m_window, true); @@ -217,6 +91,10 @@ namespace hex { EventManager::post(this->m_window); }); + EventManager::subscribe(this, [] { + EventManager::post(""); + }); + EventManager::subscribe(this, [this](std::string windowTitle) { std::string title = "ImHex"; @@ -248,17 +126,6 @@ namespace hex { this->m_popupsToOpen.push_back(name); }); - for (const auto &path : hex::getPath(ImHexPath::Config)) { - if (auto filePath = fs::path(path) / CrashBackupFileName; fs::exists(filePath)) { - this->m_safetyBackupPath = filePath; - View::doLater([] { ImGui::OpenPopup("hex.safety_backup.title"_lang); }); - } - } - - for (const auto &path : ContentRegistry::Settings::read("hex.builtin.setting.imhex", "hex.builtin.setting.imhex.recent_files")) - SharedData::recentFilePaths.push_back(path); - - auto signalHandler = [](int signalNumber) { EventManager::post(signalNumber); @@ -269,11 +136,11 @@ namespace hex { // Let's not loop on this... std::signal(signalNumber, nullptr); -#if defined(DEBUG) - assert(false); -#else - std::raise(signalNumber); -#endif + #if defined(DEBUG) + assert(false); + #else + std::raise(signalNumber); + #endif }; std::signal(SIGTERM, signalHandler); @@ -294,17 +161,11 @@ namespace hex { this->exitImGui(); this->exitGLFW(); - EventManager::unsubscribe(this); - EventManager::unsubscribe(this); EventManager::unsubscribe(this); EventManager::unsubscribe(this); EventManager::unsubscribe(this); EventManager::unsubscribe(this); - EventManager::unsubscribe(this); EventManager::unsubscribe(this); - - ImGui::UnloadImage(this->m_bannerTexture); - ImGui::UnloadImage(this->m_logoTexture); } void Window::loop() { @@ -316,7 +177,7 @@ namespace hex { } else { double timeout = (1.0 / 5.0) - (glfwGetTime() - this->m_lastFrameTime); timeout = timeout > 0 ? timeout : 0; - glfwWaitEventsTimeout(ImGui::IsPopupOpen(ImGuiID(0), ImGuiPopupFlags_AnyPopupId) || !SharedData::runningTasks.empty() ? 0 : timeout); + glfwWaitEventsTimeout(ImGui::IsPopupOpen(ImGuiID(0), ImGuiPopupFlags_AnyPopupId) || Task::getRunningTaskCount() > 0 ? 0 : timeout); } @@ -353,9 +214,10 @@ namespace hex { ImGui::SetCursorPosX(sidebarWidth); auto footerHeight = ImGui::GetTextLineHeightWithSpacing() + ImGui::GetStyle().FramePadding.y * 2 + 1_scaled; - auto dockSpaceSize = ImVec2(SharedData::windowSize.x - sidebarWidth, ImGui::GetContentRegionAvail().y - footerHeight); + auto dockSpaceSize = ImVec2(ImHexApi::System::getMainWindowSize().x - sidebarWidth, ImGui::GetContentRegionAvail().y - footerHeight); - SharedData::dockSpaceId = ImGui::DockSpace(ImGui::GetID("MainDock"), dockSpaceSize); + auto dockId = ImGui::DockSpace(ImGui::GetID("MainDock"), dockSpaceSize); + ImHexApi::System::impl::setMainDockSpaceId(dockId); drawList->AddRectFilled(ImGui::GetWindowPos(), ImGui::GetWindowPos() + ImGui::GetWindowSize() - ImVec2(dockSpaceSize.x, footerHeight - ImGui::GetStyle().FramePadding.y - 1_scaled), ImGui::GetColorU32(ImGuiCol_MenuBarBg)); @@ -461,23 +323,6 @@ namespace hex { ImGui::EndMenuBar(); } - if (!ImHexApi::Provider::isValid()) { - static char title[256]; - ImFormatString(title, IM_ARRAYSIZE(title), "%s/DockSpace_%08X", ImGui::GetCurrentWindow()->Name, ImGui::GetID("MainDock")); - if (ImGui::Begin(title)) { - ImGui::PushStyleVar(ImGuiStyleVar_WindowPadding, ImVec2(10_scaled, 10_scaled)); - if (ImGui::BeginChild("Welcome Screen", ImVec2(0, 0), false, ImGuiWindowFlags_AlwaysUseWindowPadding | ImGuiWindowFlags_NoScrollWithMouse)) { - this->drawWelcomeScreen(); - } - ImGui::EndChild(); - ImGui::PopStyleVar(); - } - ImGui::End(); - } else if (!this->m_layoutConfigured) { - this->m_layoutConfigured = true; - this->resetLayout(); - } - this->beginNativeWindowFrame(); drawList->AddLine(ImGui::GetWindowPos() + ImVec2(sidebarWidth - 2, 0), ImGui::GetWindowPos() + ImGui::GetWindowSize() - ImVec2(dockSpaceSize.x + 2, footerHeight - ImGui::GetStyle().FramePadding.y - 2), ImGui::GetColorU32(ImGuiCol_Separator)); @@ -486,28 +331,6 @@ namespace hex { ImGui::End(); ImGui::PopStyleVar(2); - ImGui::SetNextWindowPos(ImGui::GetMainViewport()->GetCenter(), ImGuiCond_Appearing, ImVec2(0.5F, 0.5F)); - ImGui::SetNextWindowSize(ImGui::GetMainViewport()->Size / 3, ImGuiCond_Appearing); - if (ImGui::BeginPopup("hex.welcome.tip_of_the_day"_lang)) { - ImGui::Header("hex.welcome.tip_of_the_day"_lang, true); - - ImGui::TextFormattedWrapped("{}", this->m_tipOfTheDay.c_str()); - ImGui::NewLine(); - - bool dontShowAgain = !this->m_showTipOfTheDay; - if (ImGui::Checkbox("hex.common.dont_show_again"_lang, &dontShowAgain)) { - this->m_showTipOfTheDay = !dontShowAgain; - ContentRegistry::Settings::write("hex.builtin.setting.general", "hex.builtin.setting.general.show_tips", this->m_showTipOfTheDay); - } - - ImGui::SameLine((ImGui::GetMainViewport()->Size / 3 - ImGui::CalcTextSize("hex.common.close"_lang) - ImGui::GetStyle().FramePadding).x); - - if (ImGui::Button("hex.common.close"_lang)) - ImGui::CloseCurrentPopup(); - - ImGui::EndPopup(); - } - ImGui::SetNextWindowPos(ImGui::GetMainViewport()->GetCenter(), ImGuiCond_Appearing, ImVec2(0.5F, 0.5F)); if (ImGui::BeginPopupModal("No Plugins", nullptr, ImGuiWindowFlags_AlwaysAutoResize | ImGuiWindowFlags_NoMove)) { ImGui::TextUnformatted("No ImHex plugins loaded (including the built-in plugin)!"); @@ -516,34 +339,6 @@ namespace hex { ImGui::EndPopup(); } - // Popup for if there is a safety backup present because ImHex crashed - ImGui::SetNextWindowPos(ImGui::GetMainViewport()->GetCenter(), ImGuiCond_Appearing, ImVec2(0.5F, 0.5F)); - if (ImGui::BeginPopupModal("hex.safety_backup.title"_lang, nullptr, ImGuiWindowFlags_AlwaysAutoResize | ImGuiWindowFlags_NoMove)) { - ImGui::TextUnformatted("hex.safety_backup.desc"_lang); - ImGui::NewLine(); - - auto width = ImGui::GetWindowWidth(); - ImGui::SetCursorPosX(width / 9); - if (ImGui::Button("hex.safety_backup.restore"_lang, ImVec2(width / 3, 0))) { - ProjectFile::load(this->m_safetyBackupPath.string()); - ProjectFile::markDirty(); - - ProjectFile::clearProjectFilePath(); - fs::remove(this->m_safetyBackupPath); - - ImGui::CloseCurrentPopup(); - } - ImGui::SameLine(); - ImGui::SetCursorPosX(width / 9 * 5); - if (ImGui::Button("hex.safety_backup.delete"_lang, ImVec2(width / 3, 0))) { - fs::remove(this->m_safetyBackupPath); - - ImGui::CloseCurrentPopup(); - } - - ImGui::EndPopup(); - } - this->m_popupsToOpen.remove_if([](const auto &name) { if (ImGui::IsPopupOpen(name.c_str())) return true; @@ -557,9 +352,12 @@ namespace hex { } void Window::frame() { - for (const auto &call : View::getDeferedCalls()) - call(); - View::getDeferedCalls().clear(); + { + auto &calls = ImHexApi::Tasks::getDeferredCalls(); + for (const auto &callback : calls) + callback(); + calls.clear(); + } View::drawCommonInterfaces(); @@ -619,169 +417,15 @@ namespace hex { glfwSwapBuffers(this->m_window); - if (this->m_targetFps <= 200) - std::this_thread::sleep_for(std::chrono::milliseconds(u64((this->m_lastFrameTime + 1 / this->m_targetFps - glfwGetTime()) * 1000))); + const auto targetFps = ImHexApi::System::getTargetFPS(); + if (targetFps <= 200) + std::this_thread::sleep_for(std::chrono::milliseconds(u64((this->m_lastFrameTime + 1 / targetFps - glfwGetTime()) * 1000))); this->m_lastFrameTime = glfwGetTime(); } void Window::drawWelcomeScreen() { - const auto availableSpace = ImGui::GetContentRegionAvail(); - ImGui::Image(this->m_bannerTexture, this->m_bannerTexture.size() / (2 * (1.0F / SharedData::globalScale))); - - ImGui::Indent(); - if (ImGui::BeginTable("Welcome Left", 1, ImGuiTableFlags_NoBordersInBody, ImVec2(availableSpace.x / 2, 0))) { - - ImGui::TableNextRow(ImGuiTableRowFlags_None, ImGui::GetTextLineHeightWithSpacing() * 3); - ImGui::TableNextColumn(); - - ImGui::TextFormattedWrapped("A Hex Editor for Reverse Engineers, Programmers and people who value their retinas when working at 3 AM."); - - ImGui::TableNextRow(ImGuiTableRowFlags_None, ImGui::GetTextLineHeightWithSpacing() * 6); - ImGui::TableNextColumn(); - - - ImGui::UnderlinedText("hex.welcome.header.start"_lang); - ImGui::SetCursorPosY(ImGui::GetCursorPosY() + 5_scaled); - { - if (ImGui::IconHyperlink(ICON_VS_NEW_FILE, "hex.welcome.start.create_file"_lang)) - EventManager::post("Create File"); - if (ImGui::IconHyperlink(ICON_VS_GO_TO_FILE, "hex.welcome.start.open_file"_lang)) - EventManager::post("Open File"); - if (ImGui::IconHyperlink(ICON_VS_NOTEBOOK, "hex.welcome.start.open_project"_lang)) - EventManager::post("Open Project"); - if (ImGui::IconHyperlink(ICON_VS_TELESCOPE, "hex.welcome.start.open_other"_lang)) - ImGui::OpenPopup("hex.welcome.start.popup.open_other"_lang); - } - - ImGui::SetNextWindowPos(ImGui::GetWindowPos() + ImGui::GetCursorPos()); - if (ImGui::BeginPopup("hex.welcome.start.popup.open_other"_lang)) { - - for (const auto &unlocalizedProviderName : ContentRegistry::Provider::getEntries()) { - if (ImGui::Hyperlink(LangEntry(unlocalizedProviderName))) { - EventManager::post(unlocalizedProviderName, nullptr); - ImGui::CloseCurrentPopup(); - } - } - - ImGui::EndPopup(); - } - - ImGui::TableNextRow(ImGuiTableRowFlags_None, ImGui::GetTextLineHeightWithSpacing() * 9); - ImGui::TableNextColumn(); - ImGui::UnderlinedText("hex.welcome.start.recent"_lang); - ImGui::SetCursorPosY(ImGui::GetCursorPosY() + 5_scaled); - { - if (!SharedData::recentFilePaths.empty()) { - for (auto &path : SharedData::recentFilePaths) { - if (ImGui::BulletHyperlink(fs::path(path).filename().string().c_str())) { - EventManager::post(path); - break; - } - } - } - } - - if (!this->m_availableUpdate.empty()) { - ImGui::TableNextRow(ImGuiTableRowFlags_None, ImGui::GetTextLineHeightWithSpacing() * 5); - ImGui::TableNextColumn(); - ImGui::UnderlinedText("hex.welcome.header.update"_lang); - { - if (ImGui::DescriptionButton("hex.welcome.update.title"_lang, hex::format("hex.welcome.update.desc"_lang, this->m_availableUpdate).c_str(), ImVec2(ImGui::GetContentRegionAvail().x * 0.8F, 0))) - hex::openWebpage("hex.welcome.update.link"_lang); - } - } - - ImGui::TableNextRow(ImGuiTableRowFlags_None, ImGui::GetTextLineHeightWithSpacing() * 6); - ImGui::TableNextColumn(); - ImGui::UnderlinedText("hex.welcome.header.help"_lang); - ImGui::SetCursorPosY(ImGui::GetCursorPosY() + 5_scaled); - { - if (ImGui::IconHyperlink(ICON_VS_GITHUB, "hex.welcome.help.repo"_lang)) hex::openWebpage("hex.welcome.help.repo.link"_lang); - if (ImGui::IconHyperlink(ICON_VS_ORGANIZATION, "hex.welcome.help.gethelp"_lang)) hex::openWebpage("hex.welcome.help.gethelp.link"_lang); - if (ImGui::IconHyperlink(ICON_VS_COMMENT_DISCUSSION, "hex.welcome.help.discord"_lang)) hex::openWebpage("hex.welcome.help.discord.link"_lang); - } - - ImGui::TableNextRow(ImGuiTableRowFlags_None, ImGui::GetTextLineHeightWithSpacing() * 5); - ImGui::TableNextColumn(); - ImGui::UnderlinedText("hex.welcome.header.plugins"_lang); - { - const auto &plugins = PluginManager::getPlugins(); - - if (!plugins.empty()) { - if (ImGui::BeginTable("plugins", 4, ImGuiTableFlags_Borders | ImGuiTableFlags_RowBg | ImGuiTableFlags_ScrollY | ImGuiTableFlags_SizingFixedFit, ImVec2((ImGui::GetContentRegionAvail().x * 5) / 6, ImGui::GetTextLineHeightWithSpacing() * 5))) { - ImGui::TableSetupScrollFreeze(0, 1); - ImGui::TableSetupColumn("hex.welcome.plugins.plugin"_lang, ImGuiTableColumnFlags_WidthStretch, 0.2); - ImGui::TableSetupColumn("hex.welcome.plugins.author"_lang, ImGuiTableColumnFlags_WidthStretch, 0.2); - ImGui::TableSetupColumn("hex.welcome.plugins.desc"_lang, ImGuiTableColumnFlags_WidthStretch, 0.6); - ImGui::TableSetupColumn("##loaded", ImGuiTableColumnFlags_WidthFixed, ImGui::GetTextLineHeight()); - - ImGui::TableHeadersRow(); - - ImGuiListClipper clipper; - clipper.Begin(plugins.size()); - - while (clipper.Step()) { - for (u64 i = clipper.DisplayStart; i < clipper.DisplayEnd; i++) { - const auto &plugin = plugins[i]; - - ImGui::TableNextRow(); - ImGui::TableNextColumn(); - ImGui::TextUnformatted(plugin.getPluginName().c_str()); - ImGui::TableNextColumn(); - ImGui::TextUnformatted(plugin.getPluginAuthor().c_str()); - ImGui::TableNextColumn(); - ImGui::TextUnformatted(plugin.getPluginDescription().c_str()); - ImGui::TableNextColumn(); - ImGui::TextUnformatted(plugin.isLoaded() ? ICON_VS_CHECK : ICON_VS_CLOSE); - } - } - - clipper.End(); - - ImGui::EndTable(); - } - } - } - - ImGui::EndTable(); - } - ImGui::SameLine(); - if (ImGui::BeginTable("Welcome Right", 1, ImGuiTableFlags_NoBordersInBody, ImVec2(availableSpace.x / 2, 0))) { - ImGui::TableNextRow(ImGuiTableRowFlags_None, ImGui::GetTextLineHeightWithSpacing() * 5); - ImGui::TableNextColumn(); - ImGui::UnderlinedText("hex.welcome.header.customize"_lang); - { - if (ImGui::DescriptionButton("hex.welcome.customize.settings.title"_lang, "hex.welcome.customize.settings.desc"_lang, ImVec2(ImGui::GetContentRegionAvail().x * 0.8F, 0))) - EventManager::post("Settings"); - } - ImGui::TableNextRow(ImGuiTableRowFlags_None, ImGui::GetTextLineHeightWithSpacing() * 5); - ImGui::TableNextColumn(); - ImGui::UnderlinedText("hex.welcome.header.learn"_lang); - { - if (ImGui::DescriptionButton("hex.welcome.learn.latest.title"_lang, "hex.welcome.learn.latest.desc"_lang, ImVec2(ImGui::GetContentRegionAvail().x * 0.8F, 0))) - hex::openWebpage("hex.welcome.learn.latest.link"_lang); - if (ImGui::DescriptionButton("hex.welcome.learn.pattern.title"_lang, "hex.welcome.learn.pattern.desc"_lang, ImVec2(ImGui::GetContentRegionAvail().x * 0.8F, 0))) - hex::openWebpage("hex.welcome.learn.pattern.link"_lang); - if (ImGui::DescriptionButton("hex.welcome.learn.plugins.title"_lang, "hex.welcome.learn.plugins.desc"_lang, ImVec2(ImGui::GetContentRegionAvail().x * 0.8F, 0))) - hex::openWebpage("hex.welcome.learn.plugins.link"_lang); - } - - auto extraWelcomeScreenEntries = ContentRegistry::Interface::getWelcomeScreenEntries(); - if (!extraWelcomeScreenEntries.empty()) { - ImGui::TableNextRow(ImGuiTableRowFlags_None, ImGui::GetTextLineHeightWithSpacing() * 5); - ImGui::TableNextColumn(); - ImGui::UnderlinedText("hex.welcome.header.various"_lang); - { - for (const auto &callback : extraWelcomeScreenEntries) - callback(); - } - } - - - ImGui::EndTable(); - } } void Window::resetLayout() const { @@ -789,7 +433,7 @@ namespace hex { if (auto &layouts = ContentRegistry::Interface::getLayouts(); !layouts.empty()) { auto &[name, function] = layouts[0]; - function(ContentRegistry::Interface::getDockSpaceId()); + function(ImHexApi::System::getMainDockSpaceId()); } } @@ -845,18 +489,19 @@ namespace hex { { int x = 0, y = 0; glfwGetWindowPos(this->m_window, &x, &y); - SharedData::windowPos = ImVec2(x, y); + + ImHexApi::System::impl::setMainWindowPosition(x, y); } { int width = 0, height = 0; glfwGetWindowSize(this->m_window, &width, &height); glfwSetWindowSize(this->m_window, width, height); - SharedData::windowSize = ImVec2(width, height); + ImHexApi::System::impl::setMainWindowSize(width, height); } glfwSetWindowPosCallback(this->m_window, [](GLFWwindow *window, int x, int y) { - SharedData::windowPos = ImVec2(x, y); + ImHexApi::System::impl::setMainWindowPosition(x, y); if (auto g = ImGui::GetCurrentContext(); g == nullptr || g->WithinFrameScope) return; @@ -867,7 +512,7 @@ namespace hex { }); glfwSetWindowSizeCallback(this->m_window, [](GLFWwindow *window, int width, int height) { - SharedData::windowSize = ImVec2(width, height); + ImHexApi::System::impl::setMainWindowSize(width, height); if (auto g = ImGui::GetCurrentContext(); g == nullptr || g->WithinFrameScope) return; @@ -913,7 +558,7 @@ namespace hex { for (const auto &extension : extensions) { if (path.extension() == extension) { if (!handler(path)) - View::showMessagePopup("hex.message.file_handler_failed"_lang); + log::error("Handler for extensions '{}' failed to process file!", extension); handled = true; break; @@ -938,7 +583,9 @@ namespace hex { void Window::initImGui() { IMGUI_CHECKVERSION(); - GImGui = ImGui::CreateContext(SharedData::fontAtlas); + auto fonts = View::getFontAtlas(); + + GImGui = ImGui::CreateContext(fonts); GImPlot = ImPlot::CreateContext(); GImNodes = ImNodes::CreateContext(); @@ -953,7 +600,7 @@ namespace hex { io.ConfigFlags |= ImGuiConfigFlags_ViewportsEnable; #endif - for (auto &entry : SharedData::fontAtlas->ConfigData) + for (auto &entry : fonts->ConfigData) io.Fonts->ConfigData.push_back(entry); io.ConfigViewportsNoTaskBarIcon = false; @@ -990,7 +637,7 @@ namespace hex { io.UserData = new ImGui::ImHexCustomData(); - style.ScaleAllSizes(SharedData::globalScale); + style.ScaleAllSizes(ImHexApi::System::getGlobalScale()); { GLsizei width, height; diff --git a/plugins/builtin/CMakeLists.txt b/plugins/builtin/CMakeLists.txt index 7b022f3d5..fdf96b818 100644 --- a/plugins/builtin/CMakeLists.txt +++ b/plugins/builtin/CMakeLists.txt @@ -18,6 +18,7 @@ add_library(${PROJECT_NAME} SHARED source/content/data_formatters.cpp source/content/layouts.cpp source/content/main_menu_items.cpp + source/content/welcome_screen.cpp source/content/providers/file_provider.cpp source/content/providers/gdb_provider.cpp diff --git a/plugins/builtin/include/content/views/view_bookmarks.hpp b/plugins/builtin/include/content/views/view_bookmarks.hpp index 56197fca5..89d5eadb2 100644 --- a/plugins/builtin/include/content/views/view_bookmarks.hpp +++ b/plugins/builtin/include/content/views/view_bookmarks.hpp @@ -1,22 +1,21 @@ #pragma once -#include +#include #include #include namespace hex::plugin::builtin { - namespace prv { - class Provider; - } - class ViewBookmarks : public View { public: ViewBookmarks(); ~ViewBookmarks() override; void drawContent() override; + + private: + std::list m_bookmarks; }; } \ No newline at end of file diff --git a/plugins/builtin/include/content/views/view_command_palette.hpp b/plugins/builtin/include/content/views/view_command_palette.hpp index 16f57ce85..68c1b8e6a 100644 --- a/plugins/builtin/include/content/views/view_command_palette.hpp +++ b/plugins/builtin/include/content/views/view_command_palette.hpp @@ -1,7 +1,7 @@ #pragma once #include -#include +#include #include diff --git a/plugins/builtin/include/content/views/view_constants.hpp b/plugins/builtin/include/content/views/view_constants.hpp index 7c28d6543..c502755d1 100644 --- a/plugins/builtin/include/content/views/view_constants.hpp +++ b/plugins/builtin/include/content/views/view_constants.hpp @@ -1,6 +1,6 @@ #pragma once -#include +#include #include #include diff --git a/plugins/builtin/include/content/views/view_data_inspector.hpp b/plugins/builtin/include/content/views/view_data_inspector.hpp index e02decf4e..ecd58f51e 100644 --- a/plugins/builtin/include/content/views/view_data_inspector.hpp +++ b/plugins/builtin/include/content/views/view_data_inspector.hpp @@ -1,6 +1,6 @@ #pragma once -#include +#include #include diff --git a/plugins/builtin/include/content/views/view_data_processor.hpp b/plugins/builtin/include/content/views/view_data_processor.hpp index 38a2bf46f..927df86c0 100644 --- a/plugins/builtin/include/content/views/view_data_processor.hpp +++ b/plugins/builtin/include/content/views/view_data_processor.hpp @@ -3,7 +3,7 @@ #include #include -#include +#include #include #include diff --git a/plugins/builtin/include/content/views/view_diff.hpp b/plugins/builtin/include/content/views/view_diff.hpp index dc70a78b0..f2788869a 100644 --- a/plugins/builtin/include/content/views/view_diff.hpp +++ b/plugins/builtin/include/content/views/view_diff.hpp @@ -3,7 +3,7 @@ #include #include -#include +#include #include #include diff --git a/plugins/builtin/include/content/views/view_disassembler.hpp b/plugins/builtin/include/content/views/view_disassembler.hpp index 4ee5d3e40..207a4b992 100644 --- a/plugins/builtin/include/content/views/view_disassembler.hpp +++ b/plugins/builtin/include/content/views/view_disassembler.hpp @@ -1,6 +1,6 @@ #pragma once -#include +#include #include diff --git a/plugins/builtin/include/content/views/view_hashes.hpp b/plugins/builtin/include/content/views/view_hashes.hpp index f6d7fb887..2d8964eca 100644 --- a/plugins/builtin/include/content/views/view_hashes.hpp +++ b/plugins/builtin/include/content/views/view_hashes.hpp @@ -1,6 +1,6 @@ #pragma once -#include +#include #include #include diff --git a/plugins/builtin/include/content/views/view_help.hpp b/plugins/builtin/include/content/views/view_help.hpp index c294605a7..e2200557a 100644 --- a/plugins/builtin/include/content/views/view_help.hpp +++ b/plugins/builtin/include/content/views/view_help.hpp @@ -3,7 +3,7 @@ #include #include -#include +#include #include #include diff --git a/plugins/builtin/include/content/views/view_hexeditor.hpp b/plugins/builtin/include/content/views/view_hexeditor.hpp index 726be5801..8d63c2b9d 100644 --- a/plugins/builtin/include/content/views/view_hexeditor.hpp +++ b/plugins/builtin/include/content/views/view_hexeditor.hpp @@ -1,6 +1,6 @@ #pragma once -#include +#include #include #include diff --git a/plugins/builtin/include/content/views/view_information.hpp b/plugins/builtin/include/content/views/view_information.hpp index 7c4551e4f..6abdad117 100644 --- a/plugins/builtin/include/content/views/view_information.hpp +++ b/plugins/builtin/include/content/views/view_information.hpp @@ -1,6 +1,6 @@ #pragma once -#include +#include #include #include diff --git a/plugins/builtin/include/content/views/view_patches.hpp b/plugins/builtin/include/content/views/view_patches.hpp index ca4d86f90..08ed9db8d 100644 --- a/plugins/builtin/include/content/views/view_patches.hpp +++ b/plugins/builtin/include/content/views/view_patches.hpp @@ -3,7 +3,7 @@ #include #include -#include +#include #include diff --git a/plugins/builtin/include/content/views/view_pattern_data.hpp b/plugins/builtin/include/content/views/view_pattern_data.hpp index f5549bdd3..fd18c533c 100644 --- a/plugins/builtin/include/content/views/view_pattern_data.hpp +++ b/plugins/builtin/include/content/views/view_pattern_data.hpp @@ -3,24 +3,12 @@ #include #include -#include +#include #include #include #include -namespace hex { - - namespace prv { - class Provider; - } - namespace lang { - class PatternData; - } - -} - - namespace hex::plugin::builtin { class ViewPatternData : public View { @@ -31,7 +19,7 @@ namespace hex::plugin::builtin { void drawContent() override; private: - std::vector m_sortedPatternData; + std::map> m_sortedPatterns; }; } \ No newline at end of file diff --git a/plugins/builtin/include/content/views/view_pattern_editor.hpp b/plugins/builtin/include/content/views/view_pattern_editor.hpp index 2a31f62c1..698a5d2eb 100644 --- a/plugins/builtin/include/content/views/view_pattern_editor.hpp +++ b/plugins/builtin/include/content/views/view_pattern_editor.hpp @@ -1,6 +1,6 @@ #pragma once -#include +#include #include #include #include @@ -24,14 +24,14 @@ namespace hex::plugin::builtin { void drawContent() override; private: - pl::PatternLanguage *m_parserRuntime, *m_evaluatorRuntime; + pl::PatternLanguage *m_parserRuntime; std::vector m_possiblePatternFiles; u32 m_selectedPatternFile = 0; bool m_runAutomatically = false; - bool m_evaluatorRunning = false; - bool m_parserRunning = false; + std::atomic m_runningEvaluators = 0; + std::atomic m_runningParsers = 0; bool m_hasUnevaluatedChanges = false; diff --git a/plugins/builtin/include/content/views/view_provider_settings.hpp b/plugins/builtin/include/content/views/view_provider_settings.hpp index 822feef7e..b00ac3b20 100644 --- a/plugins/builtin/include/content/views/view_provider_settings.hpp +++ b/plugins/builtin/include/content/views/view_provider_settings.hpp @@ -3,7 +3,7 @@ #include #include -#include +#include #include #include diff --git a/plugins/builtin/include/content/views/view_settings.hpp b/plugins/builtin/include/content/views/view_settings.hpp index f990b0539..71a20d205 100644 --- a/plugins/builtin/include/content/views/view_settings.hpp +++ b/plugins/builtin/include/content/views/view_settings.hpp @@ -1,6 +1,6 @@ #pragma once -#include +#include #include #include diff --git a/plugins/builtin/include/content/views/view_store.hpp b/plugins/builtin/include/content/views/view_store.hpp index 72aedab94..9b42fde1e 100644 --- a/plugins/builtin/include/content/views/view_store.hpp +++ b/plugins/builtin/include/content/views/view_store.hpp @@ -2,7 +2,7 @@ #include -#include +#include #include #include diff --git a/plugins/builtin/include/content/views/view_strings.hpp b/plugins/builtin/include/content/views/view_strings.hpp index 72846cc85..65ad52511 100644 --- a/plugins/builtin/include/content/views/view_strings.hpp +++ b/plugins/builtin/include/content/views/view_strings.hpp @@ -1,6 +1,6 @@ #pragma once -#include +#include #include #include diff --git a/plugins/builtin/include/content/views/view_tools.hpp b/plugins/builtin/include/content/views/view_tools.hpp index 1026c09e2..abeda3916 100644 --- a/plugins/builtin/include/content/views/view_tools.hpp +++ b/plugins/builtin/include/content/views/view_tools.hpp @@ -3,7 +3,7 @@ #include #include -#include +#include #include #include diff --git a/plugins/builtin/include/content/views/view_yara.hpp b/plugins/builtin/include/content/views/view_yara.hpp index 0cf91bbcd..6ed71c50e 100644 --- a/plugins/builtin/include/content/views/view_yara.hpp +++ b/plugins/builtin/include/content/views/view_yara.hpp @@ -3,7 +3,7 @@ #include #include -#include +#include namespace hex::plugin::builtin { diff --git a/plugins/builtin/source/content/command_palette_commands.cpp b/plugins/builtin/source/content/command_palette_commands.cpp index b6ee9a8a8..83997c0d2 100644 --- a/plugins/builtin/source/content/command_palette_commands.cpp +++ b/plugins/builtin/source/content/command_palette_commands.cpp @@ -1,7 +1,6 @@ #include -#include -using namespace hex::lang_literals; +#include #include #include diff --git a/plugins/builtin/source/content/data_inspector.cpp b/plugins/builtin/source/content/data_inspector.cpp index 09fe872ef..e46c058f0 100644 --- a/plugins/builtin/source/content/data_inspector.cpp +++ b/plugins/builtin/source/content/data_inspector.cpp @@ -2,9 +2,10 @@ #include #include -#include #include +#include + #include #include #include diff --git a/plugins/builtin/source/content/data_processor_nodes.cpp b/plugins/builtin/source/content/data_processor_nodes.cpp index a00a94780..e08953233 100644 --- a/plugins/builtin/source/content/data_processor_nodes.cpp +++ b/plugins/builtin/source/content/data_processor_nodes.cpp @@ -2,14 +2,17 @@ #include #include -#include #include +#include + +#include #include #include #include +#include namespace hex::plugin::builtin { diff --git a/plugins/builtin/source/content/layouts.cpp b/plugins/builtin/source/content/layouts.cpp index f2245da46..76bafed30 100644 --- a/plugins/builtin/source/content/layouts.cpp +++ b/plugins/builtin/source/content/layouts.cpp @@ -1,6 +1,6 @@ #include -#include +#include namespace hex::plugin::builtin { diff --git a/plugins/builtin/source/content/main_menu_items.cpp b/plugins/builtin/source/content/main_menu_items.cpp index a992ae1a1..8a231f53a 100644 --- a/plugins/builtin/source/content/main_menu_items.cpp +++ b/plugins/builtin/source/content/main_menu_items.cpp @@ -3,7 +3,7 @@ #include #include -#include +#include namespace hex::plugin::builtin { @@ -33,7 +33,7 @@ namespace hex::plugin::builtin { ContentRegistry::Interface::addMenuItem("hex.builtin.menu.layout", 1000, [] { for (auto &[layoutName, func] : ContentRegistry::Interface::getLayouts()) { if (ImGui::MenuItem(LangEntry(layoutName), "", false, ImHexApi::Provider::isValid())) { - auto dock = ContentRegistry::Interface::getDockSpaceId(); + auto dock = ImHexApi::System::getMainDockSpaceId(); for (auto &[viewName, view] : ContentRegistry::Views::getEntries()) { view->getWindowOpenState() = false; diff --git a/plugins/builtin/source/content/pl_builtin_functions.cpp b/plugins/builtin/source/content/pl_builtin_functions.cpp index 7f06ad832..a24cdcd09 100644 --- a/plugins/builtin/source/content/pl_builtin_functions.cpp +++ b/plugins/builtin/source/content/pl_builtin_functions.cpp @@ -44,6 +44,8 @@ namespace hex::plugin::builtin { void registerPatternLanguageFunctions() { using namespace hex::pl; + ContentRegistry::PatternLanguage::addColorPalette("hex.builtin.palette.pastel", { 0x70B4771F, 0x700E7FFF, 0x702CA02C, 0x702827D6, 0x70BD6794, 0x704B568C, 0x70C277E3, 0x707F7F7F, 0x7022BDBC, 0x70CFBE17 }); + ContentRegistry::PatternLanguage::Namespace nsStd = { "builtin", "std" }; { /* print(format, args...) */ diff --git a/plugins/builtin/source/content/providers/disk_provider.cpp b/plugins/builtin/source/content/providers/disk_provider.cpp index 1700dc748..5c1ed26b7 100644 --- a/plugins/builtin/source/content/providers/disk_provider.cpp +++ b/plugins/builtin/source/content/providers/disk_provider.cpp @@ -1,10 +1,14 @@ #include "content/providers/disk_provider.hpp" #include +#include #include #include +#include +#include + #if defined(OS_LINUX) #include #include diff --git a/plugins/builtin/source/content/providers/file_provider.cpp b/plugins/builtin/source/content/providers/file_provider.cpp index e7b2771d4..921cd6533 100644 --- a/plugins/builtin/source/content/providers/file_provider.cpp +++ b/plugins/builtin/source/content/providers/file_provider.cpp @@ -3,8 +3,10 @@ #include #include +#include #include #include +#include #include namespace hex::plugin::builtin::prv { diff --git a/plugins/builtin/source/content/providers/gdb_provider.cpp b/plugins/builtin/source/content/providers/gdb_provider.cpp index 388926369..4ccdff081 100644 --- a/plugins/builtin/source/content/providers/gdb_provider.cpp +++ b/plugins/builtin/source/content/providers/gdb_provider.cpp @@ -4,8 +4,12 @@ #include #include +#include +#include + #include #include +#include namespace hex::plugin::builtin::prv { diff --git a/plugins/builtin/source/content/settings_entries.cpp b/plugins/builtin/source/content/settings_entries.cpp index 6a06c237b..446d6adda 100644 --- a/plugins/builtin/source/content/settings_entries.cpp +++ b/plugins/builtin/source/content/settings_entries.cpp @@ -1,8 +1,7 @@ #include #include -#include -using namespace hex::lang_literals; +#include #include diff --git a/plugins/builtin/source/content/tools_entries.cpp b/plugins/builtin/source/content/tools_entries.cpp index c7887a160..46d93120f 100644 --- a/plugins/builtin/source/content/tools_entries.cpp +++ b/plugins/builtin/source/content/tools_entries.cpp @@ -2,12 +2,15 @@ #include #include -#include #include #include #include #include #include +#include + +#include +#include #include #include @@ -20,6 +23,7 @@ #include #define IMGUI_DEFINE_MATH_OPERATORS #include +#include #include diff --git a/plugins/builtin/source/content/ui_items.cpp b/plugins/builtin/source/content/ui_items.cpp index e479edf9d..3396e83c6 100644 --- a/plugins/builtin/source/content/ui_items.cpp +++ b/plugins/builtin/source/content/ui_items.cpp @@ -1,8 +1,10 @@ #include -#include #include #include +#include + +#include #include #include @@ -36,12 +38,13 @@ namespace hex::plugin::builtin { std::string taskName; { - std::scoped_lock lock(SharedData::tasksMutex); + std::scoped_lock lock(Task::getTaskMutex()); - taskCount = SharedData::runningTasks.size(); + taskCount = Task::getRunningTasks().size(); if (taskCount > 0) { - taskProgress = SharedData::runningTasks.front()->getProgress(); - taskName = SharedData::runningTasks.front()->getName(); + auto frontTask = Task::getRunningTasks().front(); + taskProgress = frontTask->getProgress(); + taskName = frontTask->getName(); } } @@ -132,14 +135,14 @@ namespace hex::plugin::builtin { std::string preview; if (ImHexApi::Provider::isValid()) - preview = providers[SharedData::currentProvider]->getName(); + preview = ImHexApi::Provider::get()->getName(); ImGui::SetNextItemWidth(200_scaled); if (ImGui::BeginCombo("", preview.c_str())) { for (int i = 0; i < providers.size(); i++) { if (ImGui::Selectable(providers[i]->getName().c_str())) { - SharedData::currentProvider = i; + ImHexApi::Provider::setCurrentProvider(i); } } diff --git a/plugins/builtin/source/content/views/view_bookmarks.cpp b/plugins/builtin/source/content/views/view_bookmarks.cpp index 3b1440127..865a89b12 100644 --- a/plugins/builtin/source/content/views/view_bookmarks.cpp +++ b/plugins/builtin/source/content/views/view_bookmarks.cpp @@ -10,34 +10,38 @@ namespace hex::plugin::builtin { ViewBookmarks::ViewBookmarks() : View("hex.builtin.view.bookmarks.name") { - EventManager::subscribe(this, [](ImHexApi::Bookmarks::Entry bookmark) { - bookmark.comment.resize(0xF'FFFF); - - if (bookmark.name.empty()) { - bookmark.name.resize(64); - std::memset(bookmark.name.data(), 0x00, 64); - std::strcpy(bookmark.name.data(), hex::format("hex.builtin.view.bookmarks.default_title"_lang, bookmark.region.address, bookmark.region.address + bookmark.region.size - 1).c_str()); + EventManager::subscribe(this, [this](Region region, std::string name, std::string comment, color_t color) { + if (name.empty()) { + name = hex::format("hex.builtin.view.bookmarks.default_title"_lang, region.address, region.address + region.size - 1); } - if (bookmark.comment.empty()) - std::memset(bookmark.comment.data(), 0x00, 0xF'FFFF); + if (color == 0x00) + color = ImGui::GetColorU32(ImGuiCol_Header); - bookmark.color = ImGui::GetColorU32(ImGuiCol_Header); - SharedData::bookmarkEntries.push_back(bookmark); + this->m_bookmarks.push_back({ + region, + name, + std::move(comment), + color, + false, + + ImHexApi::HexEditor::addHighlight(region, color, name) + }); + ProjectFile::markDirty(); }); - EventManager::subscribe(this, [] { - SharedData::bookmarkEntries = ProjectFile::getBookmarks(); + EventManager::subscribe(this, [this] { + this->m_bookmarks = ProjectFile::getBookmarks(); }); - EventManager::subscribe(this, [] { - ProjectFile::setBookmarks(SharedData::bookmarkEntries); + EventManager::subscribe(this, [this] { + ProjectFile::setBookmarks(this->m_bookmarks); }); - EventManager::subscribe(this, [] { - ImHexApi::Bookmarks::getEntries().clear(); + EventManager::subscribe(this, [this] { + this->m_bookmarks.clear(); }); } @@ -46,22 +50,22 @@ namespace hex::plugin::builtin { EventManager::unsubscribe(this); EventManager::unsubscribe(this); EventManager::unsubscribe(this); + + this->m_bookmarks.clear(); } void ViewBookmarks::drawContent() { if (ImGui::Begin(View::toWindowName("hex.builtin.view.bookmarks.name").c_str(), &this->getWindowOpenState())) { if (ImGui::BeginChild("##scrolling")) { - auto &bookmarks = ImHexApi::Bookmarks::getEntries(); - - if (bookmarks.empty()) { + if (this->m_bookmarks.empty()) { ImGui::TextFormattedCentered("hex.builtin.view.bookmarks.no_bookmarks"_lang); } u32 id = 1; - auto bookmarkToRemove = bookmarks.end(); - for (auto iter = bookmarks.begin(); iter != bookmarks.end(); iter++) { - auto &[region, name, comment, color, locked] = *iter; + auto bookmarkToRemove = this->m_bookmarks.end(); + for (auto iter = this->m_bookmarks.begin(); iter != this->m_bookmarks.end(); iter++) { + auto &[region, name, comment, color, locked, highlight] = *iter; auto headerColor = ImColor(color); auto hoverColor = ImColor(color); @@ -71,7 +75,7 @@ namespace hex::plugin::builtin { ImGui::PushStyleColor(ImGuiCol_Header, color); ImGui::PushStyleColor(ImGuiCol_HeaderActive, color); ImGui::PushStyleColor(ImGuiCol_HeaderHovered, u32(hoverColor)); - if (ImGui::CollapsingHeader((std::string(name.data()) + "###bookmark").c_str())) { + if (ImGui::CollapsingHeader((name + "###bookmark").c_str())) { ImGui::TextUnformatted("hex.builtin.view.bookmarks.title.info"_lang); ImGui::Separator(); ImGui::TextFormatted("hex.builtin.view.bookmarks.address"_lang, region.address, region.address + region.size - 1, region.size); @@ -146,7 +150,7 @@ namespace hex::plugin::builtin { if (locked) ImGui::TextUnformatted(name.data()); else - ImGui::InputText("##nameInput", name.data(), 64); + ImGui::InputText("##nameInput", name.data(), name.capacity(), ImGuiInputTextFlags_CallbackResize, ImGui::UpdateStringSizeCallback, &name); ImGui::NewLine(); ImGui::TextUnformatted("hex.builtin.view.bookmarks.header.comment"_lang); @@ -155,7 +159,7 @@ namespace hex::plugin::builtin { if (locked) ImGui::TextFormattedWrapped("{}", comment.data()); else - ImGui::InputTextMultiline("##commentInput", comment.data(), 0xF'FFFF); + ImGui::InputTextMultiline("##commentInput", comment.data(), comment.capacity(), ImVec2(0, 0), ImGuiInputTextFlags_CallbackResize, ImGui::UpdateStringSizeCallback, &comment); ImGui::NewLine(); } @@ -164,8 +168,9 @@ namespace hex::plugin::builtin { id++; } - if (bookmarkToRemove != bookmarks.end()) { - bookmarks.erase(bookmarkToRemove); + if (bookmarkToRemove != this->m_bookmarks.end()) { + ImHexApi::HexEditor::removeHighlight(bookmarkToRemove->highlightId); + this->m_bookmarks.erase(bookmarkToRemove); ProjectFile::markDirty(); } } diff --git a/plugins/builtin/source/content/views/view_command_palette.cpp b/plugins/builtin/source/content/views/view_command_palette.cpp index 6fdd7e25f..25e0939ff 100644 --- a/plugins/builtin/source/content/views/view_command_palette.cpp +++ b/plugins/builtin/source/content/views/view_command_palette.cpp @@ -1,5 +1,7 @@ #include "content/views/view_command_palette.hpp" +#include + #include namespace hex::plugin::builtin { @@ -21,7 +23,10 @@ namespace hex::plugin::builtin { if (!this->m_commandPaletteOpen) return; - ImGui::SetNextWindowPos(ImVec2(SharedData::windowPos.x + SharedData::windowSize.x * 0.5F, SharedData::windowPos.y), ImGuiCond_Always, ImVec2(0.5F, 0.0F)); + auto windowPos = ImHexApi::System::getMainWindowPosition(); + auto windowSize = ImHexApi::System::getMainWindowSize(); + + ImGui::SetNextWindowPos(ImVec2(windowPos.x + windowSize.x * 0.5F, windowPos.y), ImGuiCond_Always, ImVec2(0.5F, 0.0F)); if (ImGui::BeginPopup("hex.builtin.view.command_palette.name"_lang)) { if (ImGui::IsKeyDown(ImGui::GetKeyIndex(ImGuiKey_Escape))) ImGui::CloseCurrentPopup(); diff --git a/plugins/builtin/source/content/views/view_constants.cpp b/plugins/builtin/source/content/views/view_constants.cpp index 83bfbcb41..a1e410abb 100644 --- a/plugins/builtin/source/content/views/view_constants.cpp +++ b/plugins/builtin/source/content/views/view_constants.cpp @@ -24,7 +24,7 @@ namespace hex::plugin::builtin { this->m_constants.clear(); this->m_filterIndices.clear(); - for (auto &path : hex::getPath(ImHexPath::Constants)) { + for (const auto &path : hex::getPath(ImHexPath::Constants)) { if (!fs::exists(path)) continue; for (auto &file : fs::directory_iterator(path)) { diff --git a/plugins/builtin/source/content/views/view_data_processor.cpp b/plugins/builtin/source/content/views/view_data_processor.cpp index f8496ecf3..5b8422859 100644 --- a/plugins/builtin/source/content/views/view_data_processor.cpp +++ b/plugins/builtin/source/content/views/view_data_processor.cpp @@ -1,5 +1,7 @@ #include "content/views/view_data_processor.hpp" +#include + #include #include @@ -83,7 +85,7 @@ namespace hex::plugin::builtin { void ViewDataProcessor::eraseLink(u32 id) { - auto link = std::find_if(this->m_links.begin(), this->m_links.end(), [&id](auto link) { return link.getID() == id; }); + auto link = std::find_if(this->m_links.begin(), this->m_links.end(), [&id](auto link) { return link.getId() == id; }); if (link == this->m_links.end()) return; @@ -101,7 +103,7 @@ namespace hex::plugin::builtin { void ViewDataProcessor::eraseNodes(const std::vector &ids) { for (const int id : ids) { - auto node = std::find_if(this->m_nodes.begin(), this->m_nodes.end(), [&id](auto node) { return node->getID() == id; }); + auto node = std::find_if(this->m_nodes.begin(), this->m_nodes.end(), [&id](auto node) { return node->getId() == id; }); for (auto &attr : (*node)->getAttributes()) { std::vector linksToRemove; @@ -114,9 +116,9 @@ namespace hex::plugin::builtin { } for (const int id : ids) { - auto node = std::find_if(this->m_nodes.begin(), this->m_nodes.end(), [&id](auto node) { return node->getID() == id; }); + auto node = std::find_if(this->m_nodes.begin(), this->m_nodes.end(), [&id](auto node) { return node->getId() == id; }); - std::erase_if(this->m_endNodes, [&id](auto node) { return node->getID() == id; }); + std::erase_if(this->m_endNodes, [&id](auto node) { return node->getId() == id; }); delete *node; @@ -238,7 +240,7 @@ namespace hex::plugin::builtin { if (hasInput && !hasOutput) this->m_endNodes.push_back(node); - ImNodes::SetNodeScreenSpacePos(node->getID(), this->m_rightClickedCoords); + ImNodes::SetNodeScreenSpacePos(node->getId(), this->m_rightClickedCoords); } ImGui::EndPopup(); @@ -260,7 +262,7 @@ namespace hex::plugin::builtin { { int nodeId; - if (ImNodes::IsNodeHovered(&nodeId) && this->m_currNodeError.has_value() && this->m_currNodeError->first->getID() == nodeId) { + if (ImNodes::IsNodeHovered(&nodeId) && this->m_currNodeError.has_value() && this->m_currNodeError->first->getId() == nodeId) { ImGui::BeginTooltip(); ImGui::TextUnformatted("hex.common.error"_lang); ImGui::Separator(); @@ -277,7 +279,7 @@ namespace hex::plugin::builtin { if (hasError) ImNodes::PushColorStyle(ImNodesCol_NodeOutline, 0xFF0000FF); - ImNodes::BeginNode(node->getID()); + ImNodes::BeginNode(node->getId()); ImNodes::BeginNodeTitleBar(); ImGui::TextUnformatted(LangEntry(node->getUnlocalizedTitle())); @@ -301,11 +303,11 @@ namespace hex::plugin::builtin { } if (attribute.getIOType() == dp::Attribute::IOType::In) { - ImNodes::BeginInputAttribute(attribute.getID(), pinShape); + ImNodes::BeginInputAttribute(attribute.getId(), pinShape); ImGui::TextUnformatted(LangEntry(attribute.getUnlocalizedName())); ImNodes::EndInputAttribute(); } else if (attribute.getIOType() == dp::Attribute::IOType::Out) { - ImNodes::BeginOutputAttribute(attribute.getID(), ImNodesPinShape(pinShape + 1)); + ImNodes::BeginOutputAttribute(attribute.getId(), ImNodesPinShape(pinShape + 1)); ImGui::TextUnformatted(LangEntry(attribute.getUnlocalizedName())); ImNodes::EndOutputAttribute(); } @@ -318,7 +320,7 @@ namespace hex::plugin::builtin { } for (const auto &link : this->m_links) - ImNodes::Link(link.getID(), link.getFromID(), link.getToID()); + ImNodes::Link(link.getId(), link.getFromId(), link.getToId()); ImNodes::MiniMap(0.2F, ImNodesMiniMapLocation_BottomRight); @@ -339,9 +341,9 @@ namespace hex::plugin::builtin { dp::Attribute *fromAttr, *toAttr; for (auto &node : this->m_nodes) { for (auto &attribute : node->getAttributes()) { - if (attribute.getID() == from) + if (attribute.getId() == from) fromAttr = &attribute; - else if (attribute.getID() == to) + else if (attribute.getId() == to) toAttr = &attribute; } } @@ -360,8 +362,8 @@ namespace hex::plugin::builtin { auto newLink = this->m_links.emplace_back(from, to); - fromAttr->addConnectedAttribute(newLink.getID(), toAttr); - toAttr->addConnectedAttribute(newLink.getID(), fromAttr); + fromAttr->addConnectedAttribute(newLink.getId(), toAttr); + toAttr->addConnectedAttribute(newLink.getId(), fromAttr); } while (false); } } @@ -401,7 +403,7 @@ namespace hex::plugin::builtin { output["nodes"] = json::object(); for (auto &node : this->m_nodes) { - auto id = node->getID(); + auto id = node->getId(); auto &currNodeOutput = output["nodes"][std::to_string(id)]; auto pos = ImNodes::GetNodeGridSpacePos(id); @@ -419,19 +421,19 @@ namespace hex::plugin::builtin { u32 attrIndex = 0; for (auto &attr : node->getAttributes()) { - currNodeOutput["attrs"][attrIndex] = attr.getID(); + currNodeOutput["attrs"][attrIndex] = attr.getId(); attrIndex++; } } output["links"] = json::object(); for (auto &link : this->m_links) { - auto id = link.getID(); + auto id = link.getId(); auto &currOutput = output["links"][std::to_string(id)]; currOutput["id"] = id; - currOutput["from"] = link.getFromID(); - currOutput["to"] = link.getToID(); + currOutput["from"] = link.getFromId(); + currOutput["to"] = link.getToId(); } return output.dump(); @@ -467,7 +469,7 @@ namespace hex::plugin::builtin { u32 nodeId = node["id"]; maxNodeId = std::max(nodeId, maxNodeId); - newNode->setID(nodeId); + newNode->setId(nodeId); bool hasOutput = false; bool hasInput = false; @@ -482,7 +484,7 @@ namespace hex::plugin::builtin { u32 attrId = node["attrs"][attrIndex]; maxAttrId = std::max(attrId, maxAttrId); - attr.setID(attrId); + attr.setId(attrId); attrIndex++; } @@ -508,9 +510,9 @@ namespace hex::plugin::builtin { dp::Attribute *fromAttr, *toAttr; for (auto &node : this->m_nodes) { for (auto &attribute : node->getAttributes()) { - if (attribute.getID() == newLink.getFromID()) + if (attribute.getId() == newLink.getFromId()) fromAttr = &attribute; - else if (attribute.getID() == newLink.getToID()) + else if (attribute.getId() == newLink.getToId()) toAttr = &attribute; } } @@ -527,13 +529,13 @@ namespace hex::plugin::builtin { if (!toAttr->getConnectedAttributes().empty()) break; - fromAttr->addConnectedAttribute(newLink.getID(), toAttr); - toAttr->addConnectedAttribute(newLink.getID(), fromAttr); + fromAttr->addConnectedAttribute(newLink.getId(), toAttr); + toAttr->addConnectedAttribute(newLink.getId(), fromAttr); } - SharedData::dataProcessorNodeIdCounter = maxNodeId + 1; - SharedData::dataProcessorAttrIdCounter = maxAttrId + 1; - SharedData::dataProcessorLinkIdCounter = maxLinkId + 1; + dp::Node::setIdCounter(maxNodeId + 1); + dp::Attribute::setIdCounter(maxAttrId + 1); + dp::Link::setIdCounter(maxLinkId + 1); } } \ No newline at end of file diff --git a/plugins/builtin/source/content/views/view_help.cpp b/plugins/builtin/source/content/views/view_help.cpp index 6b7148a7d..3a5c59bda 100644 --- a/plugins/builtin/source/content/views/view_help.cpp +++ b/plugins/builtin/source/content/views/view_help.cpp @@ -1,9 +1,11 @@ #include "content/views/view_help.hpp" -#include + +#include #include -#include #include +#include +#include #include @@ -13,7 +15,7 @@ namespace hex::plugin::builtin { ContentRegistry::Interface::addMenuItem("hex.builtin.menu.help", 1000, [&, this] { if (ImGui::MenuItem("hex.builtin.view.help.about.name"_lang, "")) { - View::doLater([] { ImGui::OpenPopup(View::toWindowName("hex.builtin.view.help.about.name").c_str()); }); + ImHexApi::Tasks::doLater([] { ImGui::OpenPopup(View::toWindowName("hex.builtin.view.help.about.name").c_str()); }); this->m_aboutWindowOpen = true; this->getWindowOpenState() = true; } diff --git a/plugins/builtin/source/content/views/view_hexeditor.cpp b/plugins/builtin/source/content/views/view_hexeditor.cpp index 380c9d94f..1569ceee6 100644 --- a/plugins/builtin/source/content/views/view_hexeditor.cpp +++ b/plugins/builtin/source/content/views/view_hexeditor.cpp @@ -59,7 +59,7 @@ namespace hex::plugin::builtin { }; this->m_memoryEditor.HighlightFn = [](const ImU8 *data, size_t off, bool next) -> bool { - ViewHexEditor *_this = (ViewHexEditor *)data; + auto _this = (ViewHexEditor*)(data); std::optional currColor, prevColor; @@ -69,7 +69,10 @@ namespace hex::plugin::builtin { u32 alpha = static_cast(_this->m_highlightAlpha) << 24; - for (const auto &[region, name, comment, color, locked] : ImHexApi::Bookmarks::getEntries()) { + for (const auto &[id, highlight] : ImHexApi::HexEditor::getHighlights()) { + auto ®ion = highlight.getRegion(); + auto &color = highlight.getColor(); + if (off >= region.address && off < (region.address + region.size)) currColor = (color & 0x00FFFFFF) | alpha; if ((off - 1) >= region.address && (off - 1) < (region.address + region.size)) @@ -77,7 +80,8 @@ namespace hex::plugin::builtin { } { - for (const auto &pattern : SharedData::patternData) { + auto patterns = provider->getPatternLanguageRuntime().getPatterns(); + for (const auto &pattern : patterns) { auto child = pattern->getPattern(off); if (child != nullptr) { auto color = (child->getColor() & 0x00FFFFFF) | alpha; @@ -86,7 +90,7 @@ namespace hex::plugin::builtin { } } - for (const auto &pattern : SharedData::patternData) { + for (const auto &pattern : patterns) { auto child = pattern->getPattern(off - 1); if (child != nullptr) { auto color = (child->getColor() & 0x00FFFFFF) | alpha; @@ -114,15 +118,19 @@ namespace hex::plugin::builtin { off += ImHexApi::Provider::get()->getBaseAddress(); - for (const auto &[region, name, comment, color, locked] : ImHexApi::Bookmarks::getEntries()) { + for (const auto &[id, highlight] : ImHexApi::HexEditor::getHighlights()) { + auto ®ion = highlight.getRegion(); + auto &color = highlight.getColor(); + auto &tooltip = highlight.getTooltip(); + if (off >= region.address && off < (region.address + region.size)) { - if (!tooltipShown) { + if (!tooltipShown && !tooltip.empty()) { ImGui::BeginTooltip(); tooltipShown = true; } - ImGui::ColorButton(name.data(), ImColor(color).Value); + ImGui::ColorButton(tooltip.c_str(), ImColor(color).Value); ImGui::SameLine(0, 10); - ImGui::TextUnformatted(name.data()); + ImGui::TextUnformatted(tooltip.c_str()); } } @@ -753,18 +761,18 @@ namespace hex::plugin::builtin { if (ImGui::MenuItem("hex.builtin.view.hexeditor.menu.edit.set_base"_lang, nullptr, false, providerValid && provider->isReadable())) { std::memset(this->m_baseAddressBuffer, 0x00, sizeof(this->m_baseAddressBuffer)); - View::doLater([] { ImGui::OpenPopup("hex.builtin.view.hexeditor.menu.edit.set_base"_lang); }); + ImHexApi::Tasks::doLater([] { ImGui::OpenPopup("hex.builtin.view.hexeditor.menu.edit.set_base"_lang); }); } if (ImGui::MenuItem("hex.builtin.view.hexeditor.menu.edit.resize"_lang, nullptr, false, providerValid && provider->isResizable())) { - View::doLater([this] { + ImHexApi::Tasks::doLater([this] { this->m_resizeSize = ImHexApi::Provider::get()->getActualSize(); ImGui::OpenPopup("hex.builtin.view.hexeditor.menu.edit.resize"_lang); }); } if (ImGui::MenuItem("hex.builtin.view.hexeditor.menu.edit.insert"_lang, nullptr, false, providerValid && provider->isResizable())) { - View::doLater([this] { + ImHexApi::Tasks::doLater([this] { this->m_resizeSize = 0; ImGui::OpenPopup("hex.builtin.view.hexeditor.menu.edit.insert"_lang); }); @@ -800,7 +808,7 @@ namespace hex::plugin::builtin { EventManager::subscribe(this, [](GLFWwindow *window) { if (ProjectFile::hasUnsavedChanges()) { glfwSetWindowShouldClose(window, GLFW_FALSE); - View::doLater([] { ImGui::OpenPopup("hex.builtin.view.hexeditor.exit_application.title"_lang); }); + ImHexApi::Tasks::doLater([] { ImGui::OpenPopup("hex.builtin.view.hexeditor.exit_application.title"_lang); }); } }); @@ -958,46 +966,12 @@ namespace hex::plugin::builtin { void ViewHexEditor::registerMenuItems() { /* Basic operations */ - ContentRegistry::Interface::addMenuItem("hex.builtin.menu.file", 1000, [&] { + + ContentRegistry::Interface::addMenuItem("hex.builtin.menu.file", 1100, [&] { auto provider = ImHexApi::Provider::get(); bool providerValid = ImHexApi::Provider::isValid(); - if (ImGui::MenuItem("hex.builtin.view.hexeditor.menu.file.open_file"_lang, "CTRL + O")) { - hex::openFileBrowser("hex.builtin.view.hexeditor.open_file"_lang, DialogMode::Open, {}, [](const auto &path) { - EventManager::post(path); - }); - } - - if (ImGui::BeginMenu("hex.builtin.view.hexeditor.menu.file.open_recent"_lang, !SharedData::recentFilePaths.empty())) { - for (auto &path : SharedData::recentFilePaths) { - if (ImGui::MenuItem(fs::path(path).filename().string().c_str())) { - EventManager::post(path); - } - } - - ImGui::Separator(); - if (ImGui::MenuItem("hex.builtin.view.hexeditor.menu.file.clear_recent"_lang)) { - SharedData::recentFilePaths.clear(); - ContentRegistry::Settings::write( - "hex.builtin.setting.imhex", - "hex.builtin.setting.imhex.recent_files", - std::vector {}); - } - - ImGui::EndMenu(); - } - - if (ImGui::BeginMenu("hex.builtin.view.hexeditor.menu.file.open_other"_lang)) { - - for (const auto &unlocalizedProviderName : ContentRegistry::Provider::getEntries()) { - if (ImGui::MenuItem(LangEntry(unlocalizedProviderName))) { - EventManager::post(unlocalizedProviderName, nullptr); - } - } - - ImGui::EndMenu(); - } if (ImGui::MenuItem("hex.builtin.view.hexeditor.menu.file.save"_lang, "CTRL + S", false, providerValid && provider->isWritable())) { save(); @@ -1020,7 +994,7 @@ namespace hex::plugin::builtin { /* Metadata save/load */ - ContentRegistry::Interface::addMenuItem("hex.builtin.menu.file", 1100, [&, this] { + ContentRegistry::Interface::addMenuItem("hex.builtin.menu.file", 1200, [&, this] { auto provider = ImHexApi::Provider::get(); bool providerValid = ImHexApi::Provider::isValid(); @@ -1070,7 +1044,7 @@ namespace hex::plugin::builtin { /* Import / Export */ - ContentRegistry::Interface::addMenuItem("hex.builtin.menu.file", 1200, [&, this] { + ContentRegistry::Interface::addMenuItem("hex.builtin.menu.file", 1300, [&, this] { auto provider = ImHexApi::Provider::get(); bool providerValid = ImHexApi::Provider::isValid(); @@ -1161,7 +1135,7 @@ namespace hex::plugin::builtin { if (ImGui::MenuItem("hex.builtin.view.hexeditor.menu.file.import.script"_lang)) { this->m_loaderScriptFilePath.clear(); this->m_loaderScriptScriptPath.clear(); - View::doLater([] { ImGui::OpenPopup("hex.builtin.view.hexeditor.script.title"_lang); }); + ImHexApi::Tasks::doLater([] { ImGui::OpenPopup("hex.builtin.view.hexeditor.script.title"_lang); }); } ImGui::EndMenu(); @@ -1185,7 +1159,7 @@ namespace hex::plugin::builtin { this->m_dataToSave = generateIPSPatch(patches); this->m_processingImportExport = false; - View::doLater([this] { + ImHexApi::Tasks::doLater([this] { hex::openFileBrowser("hex.builtin.view.hexeditor.menu.file.export.title"_lang, DialogMode::Save, {}, [this](const auto &path) { auto file = File(path, File::Mode::Create); if (!file.isValid()) { @@ -1214,7 +1188,7 @@ namespace hex::plugin::builtin { this->m_dataToSave = generateIPS32Patch(patches); this->m_processingImportExport = false; - View::doLater([this] { + ImHexApi::Tasks::doLater([this] { hex::openFileBrowser("hex.builtin.view.hexeditor.menu.file.export.title"_lang, DialogMode::Save, {}, [this](const auto &path) { auto file = File(path, File::Mode::Create); if (!file.isValid()) { @@ -1234,7 +1208,7 @@ namespace hex::plugin::builtin { /* Search / Goto */ - ContentRegistry::Interface::addMenuItem("hex.builtin.menu.file", 1300, [&, this] { + ContentRegistry::Interface::addMenuItem("hex.builtin.menu.file", 1400, [&, this] { if (ImGui::MenuItem("hex.builtin.view.hexeditor.menu.file.search"_lang, "CTRL + F")) { this->getWindowOpenState() = true; ImGui::OpenPopupInWindow(View::toWindowName("hex.builtin.view.hexeditor.name").c_str(), "hex.builtin.view.hexeditor.menu.file.search"_lang); diff --git a/plugins/builtin/source/content/views/view_information.cpp b/plugins/builtin/source/content/views/view_information.cpp index 0ebe27b0f..386583413 100644 --- a/plugins/builtin/source/content/views/view_information.cpp +++ b/plugins/builtin/source/content/views/view_information.cpp @@ -1,5 +1,7 @@ #include "content/views/view_information.hpp" +#include + #include #include #include @@ -44,7 +46,7 @@ namespace hex::plugin::builtin { }); ContentRegistry::FileHandler::add({ ".mgc" }, [](const auto &path) { - for (auto &destPath : hex::getPath(ImHexPath::Magic)) { + for (const auto &destPath : hex::getPath(ImHexPath::Magic)) { std::error_code error; if (fs::copy_file(path, destPath / path.filename(), fs::copy_options::overwrite_existing, error)) { View::showMessagePopup("hex.builtin.view.information.magic_db_added"_lang); diff --git a/plugins/builtin/source/content/views/view_pattern_data.cpp b/plugins/builtin/source/content/views/view_pattern_data.cpp index 0adc529b3..ab942ce51 100644 --- a/plugins/builtin/source/content/views/view_pattern_data.cpp +++ b/plugins/builtin/source/content/views/view_pattern_data.cpp @@ -8,7 +8,9 @@ namespace hex::plugin::builtin { ViewPatternData::ViewPatternData() : View("hex.builtin.view.pattern_data.name") { EventManager::subscribe(this, [this](auto &) { - this->m_sortedPatternData.clear(); + if (!ImHexApi::Provider::isValid()) return; + + this->m_sortedPatterns[ImHexApi::Provider::get()].clear(); }); } @@ -52,11 +54,12 @@ namespace hex::plugin::builtin { auto provider = ImHexApi::Provider::get(); if (ImHexApi::Provider::isValid() && provider->isReadable()) { - if (beginPatternDataTable(provider, SharedData::patternData, this->m_sortedPatternData)) { + auto &sortedPatterns = this->m_sortedPatterns[ImHexApi::Provider::get()]; + if (beginPatternDataTable(provider, provider->getPatternLanguageRuntime().getPatterns(), sortedPatterns)) { ImGui::TableHeadersRow(); - if (this->m_sortedPatternData.size() > 0) { + if (!sortedPatterns.empty()) { - for (auto &patternData : this->m_sortedPatternData) + for (auto &patternData : sortedPatterns) patternData->draw(provider); } diff --git a/plugins/builtin/source/content/views/view_pattern_editor.cpp b/plugins/builtin/source/content/views/view_pattern_editor.cpp index 3e25b7344..dce6fa98a 100644 --- a/plugins/builtin/source/content/views/view_pattern_editor.cpp +++ b/plugins/builtin/source/content/views/view_pattern_editor.cpp @@ -73,7 +73,6 @@ namespace hex::plugin::builtin { ViewPatternEditor::ViewPatternEditor() : View("hex.builtin.view.pattern_editor.name") { - this->m_evaluatorRuntime = new pl::PatternLanguage(); this->m_parserRuntime = new pl::PatternLanguage(); this->m_textEditor.SetLanguageDefinition(PatternLanguage()); @@ -148,7 +147,16 @@ namespace hex::plugin::builtin { EventManager::subscribe(this, [this] { this->m_textEditor.SetText(""); - this->m_evaluatorRuntime->abort(); + ImHexApi::Provider::get()->getPatternLanguageRuntime().abort(); + }); + + EventManager::subscribe(this, [this](prv::Provider *oldProvider, prv::Provider *newProvider) { + if (oldProvider != nullptr) oldProvider->getPatternLanguageSourceCode() = this->m_textEditor.GetText(); + if (newProvider != nullptr) this->m_textEditor.SetText(newProvider->getPatternLanguageSourceCode()); + + auto lines = this->m_textEditor.GetTextLines(); + lines.pop_back(); + this->m_textEditor.SetTextLines(lines); }); /* Settings */ @@ -186,7 +194,7 @@ namespace hex::plugin::builtin { std::vector paths; - for (auto &imhexPath : hex::getPath(ImHexPath::Patterns)) { + for (const auto &imhexPath : hex::getPath(ImHexPath::Patterns)) { if (!fs::exists(imhexPath)) continue; for (auto &entry : fs::recursive_directory_iterator(imhexPath)) { @@ -218,7 +226,6 @@ namespace hex::plugin::builtin { } ViewPatternEditor::~ViewPatternEditor() { - delete this->m_evaluatorRuntime; delete this->m_parserRuntime; EventManager::unsubscribe(this); @@ -261,9 +268,10 @@ namespace hex::plugin::builtin { ImGui::PushStyleVar(ImGuiStyleVar_FrameBorderSize, 1); - if (this->m_evaluatorRunning) { + auto &runtime = provider->getPatternLanguageRuntime(); + if (runtime.isRunning()) { if (ImGui::IconButton(ICON_VS_DEBUG_STOP, ImGui::GetCustomColorVec4(ImGuiCustomCol_ToolbarRed))) - this->m_evaluatorRuntime->abort(); + runtime.abort(); } else { if (ImGui::IconButton(ICON_VS_DEBUG_START, ImGui::GetCustomColorVec4(ImGuiCustomCol_ToolbarGreen))) this->evaluatePattern(this->m_textEditor.GetText()); @@ -273,7 +281,7 @@ namespace hex::plugin::builtin { ImGui::PopStyleVar(); ImGui::SameLine(); - if (this->m_evaluatorRunning) + if (this->m_runningEvaluators > 0) ImGui::TextSpinner("hex.builtin.view.pattern_editor.evaluating"_lang); else { if (ImGui::Checkbox("hex.builtin.view.pattern_editor.auto"_lang, &this->m_runAutomatically)) { @@ -286,8 +294,8 @@ namespace hex::plugin::builtin { ImGui::SameLine(); ImGui::TextFormatted("{} / {}", - this->m_evaluatorRuntime->getCreatedPatternCount(), - this->m_evaluatorRuntime->getMaximumPatternCount()); + provider->getPatternLanguageRuntime().getCreatedPatternCount(), + provider->getPatternLanguageRuntime().getMaximumPatternCount()); } if (this->m_textEditor.IsTextChanged()) { @@ -295,7 +303,7 @@ namespace hex::plugin::builtin { this->m_hasUnevaluatedChanges = true; } - if (this->m_hasUnevaluatedChanges && !this->m_evaluatorRunning && !this->m_parserRunning) { + if (this->m_hasUnevaluatedChanges && this->m_runningEvaluators == 0 && this->m_runningParsers == 0) { this->m_hasUnevaluatedChanges = false; if (this->m_runAutomatically) @@ -305,7 +313,7 @@ namespace hex::plugin::builtin { } } - if (this->m_evaluatorRuntime->hasDangerousFunctionBeenCalled() && !ImGui::IsPopupOpen(View::toWindowName("hex.builtin.view.pattern_editor.dangerous_function.name").c_str())) { + if (provider->getPatternLanguageRuntime().hasDangerousFunctionBeenCalled() && !ImGui::IsPopupOpen(View::toWindowName("hex.builtin.view.pattern_editor.dangerous_function.name").c_str())) { ImGui::OpenPopup(View::toWindowName("hex.builtin.view.pattern_editor.dangerous_function.name").c_str()); } @@ -315,11 +323,15 @@ namespace hex::plugin::builtin { ImGui::NewLine(); View::confirmButtons( - "hex.common.yes"_lang, "hex.common.no"_lang, [this] { - this->m_evaluatorRuntime->allowDangerousFunctions(true); - ImGui::CloseCurrentPopup(); }, [this] { - this->m_evaluatorRuntime->allowDangerousFunctions(false); - ImGui::CloseCurrentPopup(); }); + "hex.common.yes"_lang, "hex.common.no"_lang, + [] { + ImHexApi::Provider::get()->getPatternLanguageRuntime().allowDangerousFunctions(true); + ImGui::CloseCurrentPopup(); + }, + [] { + ImHexApi::Provider::get()->getPatternLanguageRuntime().allowDangerousFunctions(false); + ImGui::CloseCurrentPopup(); + }); ImGui::EndPopup(); } @@ -567,16 +579,15 @@ namespace hex::plugin::builtin { } void ViewPatternEditor::clearPatternData() { - for (auto &data : SharedData::patternData) - delete data; + if (!ImHexApi::Provider::isValid()) return; - SharedData::patternData.clear(); - pl::PatternData::resetPalette(); + ImHexApi::Provider::get()->getPatternLanguageRuntime().reset(); + ContentRegistry::PatternLanguage::resetPalette(); } void ViewPatternEditor::parsePattern(const std::string &code) { - this->m_parserRunning = true; + this->m_runningParsers++; std::thread([this, code] { auto ast = this->m_parserRuntime->parseString(code); @@ -606,12 +617,12 @@ namespace hex::plugin::builtin { } } - this->m_parserRunning = false; + this->m_runningParsers--; }).detach(); } void ViewPatternEditor::evaluatePattern(const std::string &code) { - this->m_evaluatorRunning = true; + this->m_runningEvaluators++; this->m_textEditor.SetErrorMarkers({}); this->m_console.clear(); @@ -633,28 +644,31 @@ namespace hex::plugin::builtin { inVariables[name] = variable.value; } - auto result = this->m_evaluatorRuntime->executeString(ImHexApi::Provider::get(), code, envVars, inVariables); + auto provider = ImHexApi::Provider::get(); + auto &runtime = provider->getPatternLanguageRuntime(); - auto error = this->m_evaluatorRuntime->getError(); - if (error.has_value()) { - TextEditor::ErrorMarkers errorMarkers = { { error->getLineNumber(), error->what() } }; - this->m_textEditor.SetErrorMarkers(errorMarkers); + auto result = runtime.executeString(provider, code, envVars, inVariables); + if (!result) { + auto error = runtime.getError(); + if (error) { + TextEditor::ErrorMarkers errorMarkers = { { error->getLineNumber(), error->what() } }; + this->m_textEditor.SetErrorMarkers(errorMarkers); + } } - this->m_console = this->m_evaluatorRuntime->getConsoleLog(); + this->m_console = runtime.getConsoleLog(); - auto outVariables = this->m_evaluatorRuntime->getOutVariables(); + auto outVariables = runtime.getOutVariables(); for (auto &[name, variable] : this->m_patternVariables) { if (variable.outVariable && outVariables.contains(name)) variable.value = outVariables.at(name); } - if (result.has_value()) { - SharedData::patternData = std::move(result.value()); - EventManager::post(SharedData::patternData); + if (result) { + EventManager::post(runtime.getPatterns()); } - this->m_evaluatorRunning = false; + this->m_runningEvaluators--; }).detach(); } diff --git a/plugins/builtin/source/content/views/view_settings.cpp b/plugins/builtin/source/content/views/view_settings.cpp index 25c06fb7d..60f8e6331 100644 --- a/plugins/builtin/source/content/views/view_settings.cpp +++ b/plugins/builtin/source/content/views/view_settings.cpp @@ -9,14 +9,14 @@ namespace hex::plugin::builtin { ViewSettings::ViewSettings() : View("hex.builtin.view.settings.name") { EventManager::subscribe(this, [this](const std::string &name) { if (name == "Settings") { - View::doLater([] { ImGui::OpenPopup(View::toWindowName("hex.builtin.view.settings.name").c_str()); }); + ImHexApi::Tasks::doLater([] { ImGui::OpenPopup(View::toWindowName("hex.builtin.view.settings.name").c_str()); }); this->getWindowOpenState() = true; } }); ContentRegistry::Interface::addMenuItem("hex.builtin.menu.help", 2000, [&, this] { if (ImGui::MenuItem("hex.builtin.view.settings.name"_lang)) { - View::doLater([] { ImGui::OpenPopup(View::toWindowName("hex.builtin.view.settings.name").c_str()); }); + ImHexApi::Tasks::doLater([] { ImGui::OpenPopup(View::toWindowName("hex.builtin.view.settings.name").c_str()); }); this->getWindowOpenState() = true; } }); diff --git a/plugins/builtin/source/content/views/view_store.cpp b/plugins/builtin/source/content/views/view_store.cpp index 0fbf47b49..6f549d1d6 100644 --- a/plugins/builtin/source/content/views/view_store.cpp +++ b/plugins/builtin/source/content/views/view_store.cpp @@ -1,5 +1,7 @@ #include "content/views/view_store.hpp" +#include + #include #define IMGUI_DEFINE_MATH_OPERATORS #include @@ -27,7 +29,7 @@ namespace hex::plugin::builtin { ContentRegistry::Interface::addMenuItem("hex.builtin.menu.help", 3000, [&, this] { if (ImGui::MenuItem("hex.builtin.view.store.name"_lang)) { - View::doLater([] { ImGui::OpenPopup(View::toWindowName("hex.builtin.view.store.name").c_str()); }); + ImHexApi::Tasks::doLater([] { ImGui::OpenPopup(View::toWindowName("hex.builtin.view.store.name").c_str()); }); this->getWindowOpenState() = true; } }); diff --git a/plugins/builtin/source/content/views/view_strings.cpp b/plugins/builtin/source/content/views/view_strings.cpp index a6a3daa8c..c08d2e6c7 100644 --- a/plugins/builtin/source/content/views/view_strings.cpp +++ b/plugins/builtin/source/content/views/view_strings.cpp @@ -52,7 +52,7 @@ namespace hex::plugin::builtin { if (ImGui::MenuItem("hex.builtin.view.strings.demangle"_lang)) { this->m_demangledName = llvm::demangle(this->m_selectedString); if (!this->m_demangledName.empty()) - View::doLater([] { ImGui::OpenPopup("hex.builtin.view.strings.demangle.name"_lang); }); + ImHexApi::Tasks::doLater([] { ImGui::OpenPopup("hex.builtin.view.strings.demangle.name"_lang); }); } ImGui::EndPopup(); } diff --git a/plugins/builtin/source/content/views/view_tools.cpp b/plugins/builtin/source/content/views/view_tools.cpp index 003db161f..8723d2a5f 100644 --- a/plugins/builtin/source/content/views/view_tools.cpp +++ b/plugins/builtin/source/content/views/view_tools.cpp @@ -1,5 +1,7 @@ #include "content/views/view_tools.hpp" +#include + #include namespace hex::plugin::builtin { diff --git a/plugins/builtin/source/content/views/view_yara.cpp b/plugins/builtin/source/content/views/view_yara.cpp index d46a308c1..aab35ea8c 100644 --- a/plugins/builtin/source/content/views/view_yara.cpp +++ b/plugins/builtin/source/content/views/view_yara.cpp @@ -1,5 +1,7 @@ #include "content/views/view_yara.hpp" +#include + #include #include #include @@ -20,7 +22,7 @@ namespace hex::plugin::builtin { this->reloadRules(); ContentRegistry::FileHandler::add({ ".yar" }, [](const auto &path) { - for (auto &destPath : hex::getPath(ImHexPath::Yara)) { + for (const auto &destPath : hex::getPath(ImHexPath::Yara)) { std::error_code error; if (fs::copy_file(path, destPath / path.filename(), fs::copy_options::overwrite_existing, error)) { View::showMessagePopup("hex.builtin.view.yara.rule_added"_lang); @@ -132,7 +134,7 @@ namespace hex::plugin::builtin { void ViewYara::reloadRules() { this->m_rules.clear(); - for (auto path : hex::getPath(ImHexPath::Yara)) { + for (const auto path : hex::getPath(ImHexPath::Yara)) { if (!fs::exists(path)) continue; diff --git a/plugins/builtin/source/content/welcome_screen.cpp b/plugins/builtin/source/content/welcome_screen.cpp new file mode 100644 index 000000000..ddad4736a --- /dev/null +++ b/plugins/builtin/source/content/welcome_screen.cpp @@ -0,0 +1,449 @@ +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include +#include +#include +#include + +#include + +#include +#include + +#include + +namespace hex::plugin::builtin { + + static bool s_layoutConfigured = false; + static ImGui::Texture s_bannerTexture; + static std::list s_recentFilePaths; + + static fs::path s_safetyBackupPath; + + static std::string s_tipOfTheDay; + + + static void drawPopups() { + ImGui::SetNextWindowPos(ImGui::GetMainViewport()->GetCenter(), ImGuiCond_Appearing, ImVec2(0.5F, 0.5F)); + ImGui::SetNextWindowSize(ImGui::GetMainViewport()->Size / 3, ImGuiCond_Appearing); + if (ImGui::BeginPopup("hex.welcome.tip_of_the_day"_lang)) { + ImGui::Header("hex.welcome.tip_of_the_day"_lang, true); + + ImGui::TextFormattedWrapped("{}", s_tipOfTheDay.c_str()); + ImGui::NewLine(); + + static bool dontShowAgain = false; + if (ImGui::Checkbox("hex.common.dont_show_again"_lang, &dontShowAgain)) { + ContentRegistry::Settings::write("hex.builtin.setting.general", "hex.builtin.setting.general.show_tips", dontShowAgain); + } + + ImGui::SameLine((ImGui::GetMainViewport()->Size / 3 - ImGui::CalcTextSize("hex.common.close"_lang) - ImGui::GetStyle().FramePadding).x); + + if (ImGui::Button("hex.common.close"_lang)) + ImGui::CloseCurrentPopup(); + + ImGui::EndPopup(); + } + + + // Popup for if there is a safety backup present because ImHex crashed + ImGui::SetNextWindowPos(ImGui::GetMainViewport()->GetCenter(), ImGuiCond_Appearing, ImVec2(0.5F, 0.5F)); + if (ImGui::BeginPopupModal("hex.safety_backup.title"_lang, nullptr, ImGuiWindowFlags_AlwaysAutoResize | ImGuiWindowFlags_NoMove)) { + ImGui::TextUnformatted("hex.safety_backup.desc"_lang); + ImGui::NewLine(); + + auto width = ImGui::GetWindowWidth(); + ImGui::SetCursorPosX(width / 9); + if (ImGui::Button("hex.safety_backup.restore"_lang, ImVec2(width / 3, 0))) { + ProjectFile::load(s_safetyBackupPath.string()); + ProjectFile::markDirty(); + + ProjectFile::clearProjectFilePath(); + fs::remove(s_safetyBackupPath); + + ImGui::CloseCurrentPopup(); + } + ImGui::SameLine(); + ImGui::SetCursorPosX(width / 9 * 5); + if (ImGui::Button("hex.safety_backup.delete"_lang, ImVec2(width / 3, 0))) { + fs::remove(s_safetyBackupPath); + + ImGui::CloseCurrentPopup(); + } + + ImGui::EndPopup(); + } + } + + static void drawWelcomeScreenContent() { + const auto availableSpace = ImGui::GetContentRegionAvail(); + + ImGui::Image(s_bannerTexture, s_bannerTexture.size() / (2 * (1.0F / ImHexApi::System::getGlobalScale()))); + + ImGui::Indent(); + if (ImGui::BeginTable("Welcome Left", 1, ImGuiTableFlags_NoBordersInBody, ImVec2(availableSpace.x / 2, 0))) { + + ImGui::TableNextRow(ImGuiTableRowFlags_None, ImGui::GetTextLineHeightWithSpacing() * 3); + ImGui::TableNextColumn(); + + ImGui::TextFormattedWrapped("A Hex Editor for Reverse Engineers, Programmers and people who value their retinas when working at 3 AM."); + + ImGui::TableNextRow(ImGuiTableRowFlags_None, ImGui::GetTextLineHeightWithSpacing() * 6); + ImGui::TableNextColumn(); + + + ImGui::UnderlinedText("hex.welcome.header.start"_lang); + ImGui::SetCursorPosY(ImGui::GetCursorPosY() + 5_scaled); + { + if (ImGui::IconHyperlink(ICON_VS_NEW_FILE, "hex.welcome.start.create_file"_lang)) + EventManager::post("Create File"); + if (ImGui::IconHyperlink(ICON_VS_GO_TO_FILE, "hex.welcome.start.open_file"_lang)) + EventManager::post("Open File"); + if (ImGui::IconHyperlink(ICON_VS_NOTEBOOK, "hex.welcome.start.open_project"_lang)) + EventManager::post("Open Project"); + if (ImGui::IconHyperlink(ICON_VS_TELESCOPE, "hex.welcome.start.open_other"_lang)) + ImGui::OpenPopup("hex.welcome.start.popup.open_other"_lang); + } + + ImGui::SetNextWindowPos(ImGui::GetWindowPos() + ImGui::GetCursorPos()); + if (ImGui::BeginPopup("hex.welcome.start.popup.open_other"_lang)) { + + for (const auto &unlocalizedProviderName : ContentRegistry::Provider::getEntries()) { + if (ImGui::Hyperlink(LangEntry(unlocalizedProviderName))) { + EventManager::post(unlocalizedProviderName, nullptr); + ImGui::CloseCurrentPopup(); + } + } + + ImGui::EndPopup(); + } + + ImGui::TableNextRow(ImGuiTableRowFlags_None, ImGui::GetTextLineHeightWithSpacing() * 9); + ImGui::TableNextColumn(); + ImGui::UnderlinedText("hex.welcome.start.recent"_lang); + ImGui::SetCursorPosY(ImGui::GetCursorPosY() + 5_scaled); + { + for (auto &path : s_recentFilePaths) { + if (ImGui::BulletHyperlink(fs::path(path).filename().string().c_str())) { + EventManager::post(path); + break; + } + } + } + + if (ImHexApi::System::getInitArguments().contains("update-available")) { + ImGui::TableNextRow(ImGuiTableRowFlags_None, ImGui::GetTextLineHeightWithSpacing() * 5); + ImGui::TableNextColumn(); + ImGui::UnderlinedText("hex.welcome.header.update"_lang); + { + if (ImGui::DescriptionButton("hex.welcome.update.title"_lang, hex::format("hex.welcome.update.desc"_lang, ImHexApi::System::getInitArguments()["update-available"]).c_str(), ImVec2(ImGui::GetContentRegionAvail().x * 0.8F, 0))) + hex::openWebpage("hex.welcome.update.link"_lang); + } + } + + ImGui::TableNextRow(ImGuiTableRowFlags_None, ImGui::GetTextLineHeightWithSpacing() * 6); + ImGui::TableNextColumn(); + ImGui::UnderlinedText("hex.welcome.header.help"_lang); + ImGui::SetCursorPosY(ImGui::GetCursorPosY() + 5_scaled); + { + if (ImGui::IconHyperlink(ICON_VS_GITHUB, "hex.welcome.help.repo"_lang)) hex::openWebpage("hex.welcome.help.repo.link"_lang); + if (ImGui::IconHyperlink(ICON_VS_ORGANIZATION, "hex.welcome.help.gethelp"_lang)) hex::openWebpage("hex.welcome.help.gethelp.link"_lang); + if (ImGui::IconHyperlink(ICON_VS_COMMENT_DISCUSSION, "hex.welcome.help.discord"_lang)) hex::openWebpage("hex.welcome.help.discord.link"_lang); + } + + ImGui::TableNextRow(ImGuiTableRowFlags_None, ImGui::GetTextLineHeightWithSpacing() * 5); + ImGui::TableNextColumn(); + ImGui::UnderlinedText("hex.welcome.header.plugins"_lang); + { + const auto &plugins = PluginManager::getPlugins(); + + if (!plugins.empty()) { + if (ImGui::BeginTable("plugins", 4, ImGuiTableFlags_Borders | ImGuiTableFlags_RowBg | ImGuiTableFlags_ScrollY | ImGuiTableFlags_SizingFixedFit, ImVec2((ImGui::GetContentRegionAvail().x * 5) / 6, ImGui::GetTextLineHeightWithSpacing() * 5))) { + ImGui::TableSetupScrollFreeze(0, 1); + ImGui::TableSetupColumn("hex.welcome.plugins.plugin"_lang, ImGuiTableColumnFlags_WidthStretch, 0.2); + ImGui::TableSetupColumn("hex.welcome.plugins.author"_lang, ImGuiTableColumnFlags_WidthStretch, 0.2); + ImGui::TableSetupColumn("hex.welcome.plugins.desc"_lang, ImGuiTableColumnFlags_WidthStretch, 0.6); + ImGui::TableSetupColumn("##loaded", ImGuiTableColumnFlags_WidthFixed, ImGui::GetTextLineHeight()); + + ImGui::TableHeadersRow(); + + ImGuiListClipper clipper; + clipper.Begin(plugins.size()); + + while (clipper.Step()) { + for (u64 i = clipper.DisplayStart; i < clipper.DisplayEnd; i++) { + const auto &plugin = plugins[i]; + + ImGui::TableNextRow(); + ImGui::TableNextColumn(); + ImGui::TextUnformatted(plugin.getPluginName().c_str()); + ImGui::TableNextColumn(); + ImGui::TextUnformatted(plugin.getPluginAuthor().c_str()); + ImGui::TableNextColumn(); + ImGui::TextUnformatted(plugin.getPluginDescription().c_str()); + ImGui::TableNextColumn(); + ImGui::TextUnformatted(plugin.isLoaded() ? ICON_VS_CHECK : ICON_VS_CLOSE); + } + } + + clipper.End(); + + ImGui::EndTable(); + } + } + } + + ImGui::EndTable(); + } + ImGui::SameLine(); + if (ImGui::BeginTable("Welcome Right", 1, ImGuiTableFlags_NoBordersInBody, ImVec2(availableSpace.x / 2, 0))) { + ImGui::TableNextRow(ImGuiTableRowFlags_None, ImGui::GetTextLineHeightWithSpacing() * 5); + ImGui::TableNextColumn(); + ImGui::UnderlinedText("hex.welcome.header.customize"_lang); + { + if (ImGui::DescriptionButton("hex.welcome.customize.settings.title"_lang, "hex.welcome.customize.settings.desc"_lang, ImVec2(ImGui::GetContentRegionAvail().x * 0.8F, 0))) + EventManager::post("Settings"); + } + ImGui::TableNextRow(ImGuiTableRowFlags_None, ImGui::GetTextLineHeightWithSpacing() * 5); + ImGui::TableNextColumn(); + ImGui::UnderlinedText("hex.welcome.header.learn"_lang); + { + if (ImGui::DescriptionButton("hex.welcome.learn.latest.title"_lang, "hex.welcome.learn.latest.desc"_lang, ImVec2(ImGui::GetContentRegionAvail().x * 0.8F, 0))) + hex::openWebpage("hex.welcome.learn.latest.link"_lang); + if (ImGui::DescriptionButton("hex.welcome.learn.pattern.title"_lang, "hex.welcome.learn.pattern.desc"_lang, ImVec2(ImGui::GetContentRegionAvail().x * 0.8F, 0))) + hex::openWebpage("hex.welcome.learn.pattern.link"_lang); + if (ImGui::DescriptionButton("hex.welcome.learn.plugins.title"_lang, "hex.welcome.learn.plugins.desc"_lang, ImVec2(ImGui::GetContentRegionAvail().x * 0.8F, 0))) + hex::openWebpage("hex.welcome.learn.plugins.link"_lang); + } + + auto extraWelcomeScreenEntries = ContentRegistry::Interface::getWelcomeScreenEntries(); + if (!extraWelcomeScreenEntries.empty()) { + ImGui::TableNextRow(ImGuiTableRowFlags_None, ImGui::GetTextLineHeightWithSpacing() * 5); + ImGui::TableNextColumn(); + ImGui::UnderlinedText("hex.welcome.header.various"_lang); + { + for (const auto &callback : extraWelcomeScreenEntries) + callback(); + } + } + + + ImGui::EndTable(); + } + } + + static void drawWelcomeScreen() { + if (ImGui::Begin("DockSpace")) { + if (!ImHexApi::Provider::isValid()) { + static char title[256]; + ImFormatString(title, IM_ARRAYSIZE(title), "%s/DockSpace_%08X", ImGui::GetCurrentWindow()->Name, ImGui::GetID("MainDock")); + if (ImGui::Begin(title)) { + ImGui::PushStyleVar(ImGuiStyleVar_WindowPadding, ImVec2(10_scaled, 10_scaled)); + if (ImGui::BeginChild("Welcome Screen", ImVec2(0, 0), false, ImGuiWindowFlags_AlwaysUseWindowPadding | ImGuiWindowFlags_NoScrollWithMouse)) { + drawWelcomeScreenContent(); + } + ImGui::EndChild(); + ImGui::PopStyleVar(); + } + ImGui::End(); + } else if (!s_layoutConfigured) { + s_layoutConfigured = true; + // TODO: FIX RESET LAYOUT + } + } + ImGui::End(); + + drawPopups(); + } + + void createWelcomeScreen() { + (void)EventManager::subscribe(drawWelcomeScreen); + + (void)EventManager::subscribe([]() { + { + auto theme = ContentRegistry::Settings::getSetting("hex.builtin.setting.interface", "hex.builtin.setting.interface.color"); + + if (theme.is_number()) + EventManager::post(theme.get()); + } + + { + auto language = ContentRegistry::Settings::getSetting("hex.builtin.setting.interface", "hex.builtin.setting.interface.language"); + + if (language.is_string()) { + LangEntry::loadLanguage(static_cast(language)); + } else { + // If no language is specified, fall back to English. + LangEntry::loadLanguage("en-US"); + } + } + + { + auto targetFps = ContentRegistry::Settings::getSetting("hex.builtin.setting.interface", "hex.builtin.setting.interface.fps"); + + if (targetFps.is_number()) + ImHexApi::System::setTargetFPS(targetFps); + } + + { + if (ContentRegistry::Settings::read("hex.builtin.setting.imhex", "hex.builtin.setting.imhex.launched", 0) == 1) + s_layoutConfigured = true; + else + ContentRegistry::Settings::write("hex.builtin.setting.imhex", "hex.builtin.setting.imhex.launched", 1); + } + }); + + (void)EventManager::subscribe([](u32 theme) { + if (s_bannerTexture.valid()) + ImGui::UnloadImage(s_bannerTexture); + + switch (theme) { + default: + case 1: /* Dark theme */ + { + ImGui::StyleColorsDark(); + ImGui::StyleCustomColorsDark(); + ImPlot::StyleColorsDark(); + + auto banner = romfs::get("banner_dark.png"); + s_bannerTexture = ImGui::LoadImageFromMemory(reinterpret_cast(banner.data()), banner.size()); + + break; + } + case 2: /* Light theme */ + { + ImGui::StyleColorsLight(); + ImGui::StyleCustomColorsLight(); + ImPlot::StyleColorsLight(); + + auto banner = romfs::get("banner_light.png"); + s_bannerTexture = ImGui::LoadImageFromMemory(reinterpret_cast(banner.data()), banner.size()); + + break; + } + case 3: /* Classic theme */ + { + ImGui::StyleColorsClassic(); + ImGui::StyleCustomColorsClassic(); + ImPlot::StyleColorsClassic(); + + auto banner = romfs::get("banner_dark.png"); + s_bannerTexture = ImGui::LoadImageFromMemory(reinterpret_cast(banner.data()), banner.size()); + + break; + } + } + + ImGui::GetStyle().Colors[ImGuiCol_DockingEmptyBg] = ImGui::GetStyle().Colors[ImGuiCol_WindowBg]; + ImGui::GetStyle().Colors[ImGuiCol_TitleBg] = ImGui::GetStyle().Colors[ImGuiCol_MenuBarBg]; + ImGui::GetStyle().Colors[ImGuiCol_TitleBgActive] = ImGui::GetStyle().Colors[ImGuiCol_MenuBarBg]; + ImGui::GetStyle().Colors[ImGuiCol_TitleBgCollapsed] = ImGui::GetStyle().Colors[ImGuiCol_MenuBarBg]; + + if (!s_bannerTexture.valid()) { + log::error("Failed to load banner texture!"); + } + }); + + (void)EventManager::subscribe([](const auto &path) { + s_recentFilePaths.push_front(path); + + { + std::list uniques; + for (auto &file : s_recentFilePaths) { + + bool exists = false; + for (auto &unique : uniques) { + if (file == unique) + exists = true; + } + + if (!exists && !file.empty()) + uniques.push_back(file); + + if (uniques.size() > 5) + break; + } + s_recentFilePaths = uniques; + } + + { + std::vector recentFilesVector; + for (const auto &recentPath : s_recentFilePaths) + recentFilesVector.push_back(recentPath.string()); + + ContentRegistry::Settings::write("hex.builtin.setting.imhex", "hex.builtin.setting.imhex.recent_files", recentFilesVector); + } + }); + + ContentRegistry::Interface::addMenuItem("hex.builtin.menu.file", 1050, [&] { + if (ImGui::MenuItem("hex.builtin.view.hexeditor.menu.file.open_file"_lang, "CTRL + O")) { + + hex::openFileBrowser("hex.builtin.view.hexeditor.open_file"_lang, DialogMode::Open, {}, + [](const auto &path) { + EventManager::post(path); + }); + } + + if (ImGui::BeginMenu("hex.builtin.view.hexeditor.menu.file.open_recent"_lang, !s_recentFilePaths.empty())) { + for (auto &path : s_recentFilePaths) { + if (ImGui::MenuItem(fs::path(path).filename().string().c_str())) { + EventManager::post(path); + } + } + + ImGui::Separator(); + if (ImGui::MenuItem("hex.builtin.view.hexeditor.menu.file.clear_recent"_lang)) { + s_recentFilePaths.clear(); + ContentRegistry::Settings::write( + "hex.builtin.setting.imhex", + "hex.builtin.setting.imhex.recent_files", + std::vector{}); + } + + ImGui::EndMenu(); + } + + if (ImGui::BeginMenu("hex.builtin.view.hexeditor.menu.file.open_other"_lang)) { + + for (const auto &unlocalizedProviderName : ContentRegistry::Provider::getEntries()) { + if (ImGui::MenuItem(LangEntry(unlocalizedProviderName))) { + EventManager::post(unlocalizedProviderName, nullptr); + } + } + + ImGui::EndMenu(); + } + + }); + + + constexpr auto CrashBackupFileName = "crash_backup.hexproj"; + for (const auto &path : hex::getPath(ImHexPath::Config)) { + if (auto filePath = fs::path(path) / CrashBackupFileName; fs::exists(filePath)) { + s_safetyBackupPath = filePath; + ImHexApi::Tasks::doLater([] { ImGui::OpenPopup("hex.safety_backup.title"_lang); }); + } + } + + for (const auto &path : ContentRegistry::Settings::read("hex.builtin.setting.imhex", "hex.builtin.setting.imhex.recent_files")) + s_recentFilePaths.emplace_back(path); + + if (ImHexApi::System::getInitArguments().contains("tip-of-the-day")) { + s_tipOfTheDay = ImHexApi::System::getInitArguments()["tip-of-the-day"]; + + bool showTipOfTheDay = ContentRegistry::Settings::read("hex.builtin.setting.general", "hex.builtin.setting.general.show_tips", 1); + if (showTipOfTheDay) + ImHexApi::Tasks::doLater([] { ImGui::OpenPopup("hex.welcome.tip_of_the_day"_lang); }); + } + } + +} \ No newline at end of file diff --git a/plugins/builtin/source/lang/de_DE.cpp b/plugins/builtin/source/lang/de_DE.cpp index 8322f02e7..5f8a19cf2 100644 --- a/plugins/builtin/source/lang/de_DE.cpp +++ b/plugins/builtin/source/lang/de_DE.cpp @@ -1,5 +1,5 @@ #include -#include +#include namespace hex::plugin::builtin { diff --git a/plugins/builtin/source/lang/en_US.cpp b/plugins/builtin/source/lang/en_US.cpp index abf4a47ad..e357f61eb 100644 --- a/plugins/builtin/source/lang/en_US.cpp +++ b/plugins/builtin/source/lang/en_US.cpp @@ -1,5 +1,5 @@ #include -#include +#include namespace hex::plugin::builtin { diff --git a/plugins/builtin/source/lang/it_IT.cpp b/plugins/builtin/source/lang/it_IT.cpp index 3b9b19684..45d988b7a 100644 --- a/plugins/builtin/source/lang/it_IT.cpp +++ b/plugins/builtin/source/lang/it_IT.cpp @@ -1,5 +1,5 @@ #include -#include +#include namespace hex::plugin::builtin { diff --git a/plugins/builtin/source/lang/zh_CN.cpp b/plugins/builtin/source/lang/zh_CN.cpp index 1de19af80..39de9a18e 100644 --- a/plugins/builtin/source/lang/zh_CN.cpp +++ b/plugins/builtin/source/lang/zh_CN.cpp @@ -1,5 +1,5 @@ #include -#include +#include namespace hex::plugin::builtin { diff --git a/plugins/builtin/source/plugin_builtin.cpp b/plugins/builtin/source/plugin_builtin.cpp index ddb066b53..dd1aae913 100644 --- a/plugins/builtin/source/plugin_builtin.cpp +++ b/plugins/builtin/source/plugin_builtin.cpp @@ -15,6 +15,7 @@ namespace hex::plugin::builtin { void registerDataFormatters(); void registerLayouts(); void registerMainMenuEntries(); + void createWelcomeScreen(); void addFooterItems(); void addToolbarItems(); @@ -39,6 +40,7 @@ IMHEX_PLUGIN_SETUP("Built-in", "WerWolv", "Default ImHex functionality") { registerDataProcessorNodes(); registerProviders(); registerDataFormatters(); + createWelcomeScreen(); addFooterItems(); addToolbarItems(); @@ -50,3 +52,7 @@ IMHEX_PLUGIN_SETUP("Built-in", "WerWolv", "Default ImHex functionality") { registerLanguageItIT(); registerLanguageZhCN(); } + +// This is the default plugin +// DO NOT USE THIS IN ANY OTHER PLUGIN +extern "C" bool isBuiltinPlugin() { return true; } \ No newline at end of file diff --git a/plugins/example_cpp/source/plugin_example.cpp b/plugins/example_cpp/source/plugin_example.cpp index 35392828c..fef91a797 100644 --- a/plugins/example_cpp/source/plugin_example.cpp +++ b/plugins/example_cpp/source/plugin_example.cpp @@ -1,6 +1,6 @@ #include -#include +#include class ViewExample : public hex::View { public: diff --git a/plugins/windows/include/views/view_tty_console.hpp b/plugins/windows/include/views/view_tty_console.hpp index 9fc04aa4f..6988d1564 100644 --- a/plugins/windows/include/views/view_tty_console.hpp +++ b/plugins/windows/include/views/view_tty_console.hpp @@ -1,6 +1,6 @@ #pragma once -#include +#include #include diff --git a/plugins/windows/source/content/settings_entries.cpp b/plugins/windows/source/content/settings_entries.cpp index d104d0b0a..27f0e9640 100644 --- a/plugins/windows/source/content/settings_entries.cpp +++ b/plugins/windows/source/content/settings_entries.cpp @@ -2,8 +2,7 @@ #include #include -#include -using namespace hex::lang_literals; +#include #include diff --git a/plugins/windows/source/lang/en_US.cpp b/plugins/windows/source/lang/en_US.cpp index 2576393b5..d88c048ea 100644 --- a/plugins/windows/source/lang/en_US.cpp +++ b/plugins/windows/source/lang/en_US.cpp @@ -1,5 +1,5 @@ #include -#include +#include namespace hex::plugin::windows { diff --git a/plugins/windows/source/lang/zh_CN.cpp b/plugins/windows/source/lang/zh_CN.cpp index 7af3cead4..d690de5e1 100644 --- a/plugins/windows/source/lang/zh_CN.cpp +++ b/plugins/windows/source/lang/zh_CN.cpp @@ -1,5 +1,5 @@ #include -#include +#include namespace hex::plugin::windows { diff --git a/plugins/windows/source/plugin_windows.cpp b/plugins/windows/source/plugin_windows.cpp index d78d9dc28..936ed62a1 100644 --- a/plugins/windows/source/plugin_windows.cpp +++ b/plugins/windows/source/plugin_windows.cpp @@ -1,5 +1,7 @@ #include +#include + #include "views/view_tty_console.hpp" namespace hex::plugin::windows { diff --git a/tests/algorithms/source/crypto.cpp b/tests/algorithms/source/crypto.cpp index 9f277e35a..1a656d6d9 100644 --- a/tests/algorithms/source/crypto.cpp +++ b/tests/algorithms/source/crypto.cpp @@ -1,5 +1,5 @@ #include -#include "hex/helpers/logger.hpp" +#include #include #include diff --git a/tests/pattern_language/include/test_patterns/test_pattern.hpp b/tests/pattern_language/include/test_patterns/test_pattern.hpp index f6e40654a..70dc53802 100644 --- a/tests/pattern_language/include/test_patterns/test_pattern.hpp +++ b/tests/pattern_language/include/test_patterns/test_pattern.hpp @@ -29,7 +29,7 @@ namespace hex::test { template static T *create(const std::string &typeName, const std::string &varName, auto... args) { - auto pattern = new T(args...); + auto pattern = new T(nullptr, args...); pattern->setTypeName(typeName); pattern->setVariableName(varName); diff --git a/tests/pattern_language/source/main.cpp b/tests/pattern_language/source/main.cpp index c70e9fc7c..afc762745 100644 --- a/tests/pattern_language/source/main.cpp +++ b/tests/pattern_language/source/main.cpp @@ -58,8 +58,8 @@ int test(int argc, char **argv) { addFunctions(); // Check if compilation succeeded - auto patterns = language.executeString(provider, testPatterns[testName]->getSourceCode()); - if (!patterns.has_value()) { + auto result = language.executeString(provider, testPatterns[testName]->getSourceCode()); + if (!result) { hex::log::fatal("Error during compilation!"); if (auto error = language.getError(); error.has_value()) @@ -76,20 +76,20 @@ int test(int argc, char **argv) { } ON_SCOPE_EXIT { - for (auto &pattern : *patterns) + for (auto &pattern : language.getPatterns()) delete pattern; }; // Check if the right number of patterns have been produced - if (patterns->size() != currTest->getPatterns().size() && !currTest->getPatterns().empty()) { + if (language.getPatterns().size() != currTest->getPatterns().size() && !currTest->getPatterns().empty()) { hex::log::fatal("Source didn't produce expected number of patterns"); return EXIT_FAILURE; } // Check if the produced patterns are the ones expected for (u32 i = 0; i < currTest->getPatterns().size(); i++) { - auto &evaluatedPattern = *patterns->at(i); - auto &controlPattern = *currTest->getPatterns().at(i); + auto &evaluatedPattern = *language.getPatterns()[i]; + auto &controlPattern = *currTest->getPatterns()[i]; if (evaluatedPattern != controlPattern) { hex::log::fatal("Pattern with name {}:{} didn't match template", evaluatedPattern.getTypeName(), evaluatedPattern.getVariableName());