Compare commits

...

66 Commits

Author SHA1 Message Date
WerWolv
8802a8e861 build: Bumped version to 1.33.2 2024-03-23 10:15:12 +01:00
WerWolv
8a01f3cc6b impr: Show hint if advanced data information section doesn't yield any result 2024-03-22 21:33:57 +01:00
WerWolv
7d7bd0d642 fix: Splash screen being scaled incorrectly 2024-03-22 17:53:43 +01:00
WerWolv
2b1be7bc30 fix: Icons not being scaled correctly anymore 2024-03-22 17:53:34 +01:00
WerWolv
9df21c7952 fix: Missing include in notification toasts 2024-03-22 17:52:55 +01:00
Nobutaka Mantani
70b9ceba72 build: Added support patches for FreeBSD (#1584)
This pull request fixes build on FreeBSD. The changes are conditioned
with `#if defined(__FreeBSD__)` preprocessor macro and they should not
affect build for other operating systems.

---------

Co-authored-by: Nik <werwolv98@gmail.com>
Co-authored-by: iTrooz <hey@itrooz.fr>
2024-03-22 17:52:38 +01:00
WerWolv
27f3c634ba impr: Load unifont at correct size
Fixes #1604
2024-03-22 17:50:45 +01:00
WerWolv
33b091e9e6 fix: Decompress functions not extracting full data
Thanks a lot to tocklime
2024-03-22 17:47:25 +01:00
WerWolv
976caf53ae fix: Prevent view providers from pointing to themselves and being saved as recent provider
#1607
2024-03-22 17:47:14 +01:00
WerWolv
c2bb6e37b1 fix: Crash when trying to open unopenable file 2024-03-22 17:46:50 +01:00
WerWolv
b4b47ff60e fix: Make sure pattern runtime is always properly configured 2024-03-22 17:46:24 +01:00
WerWolv
db2ad0951f fix: File open achievement not triggering when dropping a file onto ImHex 2024-03-22 17:46:13 +01:00
WerWolv
e5969c5d2e fix: Potential crash when log file is unavailable 2024-03-22 17:45:59 +01:00
WerWolv
b1d6086c0c fix: Control characters ending up in log files 2024-03-22 17:45:38 +01:00
WerWolv
7dfcbb15a4 fix: Infinite loop when exporting selection to file 2024-03-22 17:45:11 +01:00
WerWolv
4d470385d8 fix: Right clicking reverse selected regions deselecting it 2024-03-22 17:45:02 +01:00
WerWolv
b0f010690c fix: Various issues with the virtual file system 2024-03-22 17:44:49 +01:00
WerWolv
360ae718b9 fix: Advanced data information not showing up correctly 2024-03-22 17:44:36 +01:00
WerWolv
6f45a7939a fix: Diffing option popup flickering when opening 2024-03-22 17:43:00 +01:00
WerWolv
e27a4df8b0 fix: Base address issues with the data inspector and copy as array option
Fixes #1595
2024-03-22 17:42:17 +01:00
WerWolv
84cd3f989b fix: Denying server contact leaving crash upload option enabled
Fixes #1594
2024-03-22 17:41:35 +01:00
WerWolv
2e09a4e567 fix: ImHex using a ton of CPU power on Linux 2024-03-22 17:41:03 +01:00
WerWolv
0ce1a87cbf fix: Toasts not printing their message to the console correctly 2024-03-22 17:40:51 +01:00
WerWolv
6a158f99d7 fix: Highlighting not updating correctly when changing bookmark region
Fixes #1591
2024-03-22 17:40:06 +01:00
WerWolv
77f46317f0 fix: Update all task progress not increasing correctly 2024-03-22 17:39:56 +01:00
WerWolv
4c98f6bca6 fix: View provider not saving top-level data to project file 2024-03-22 17:39:41 +01:00
WerWolv
77bc45ca17 fix: View provider not correctly saving its state to a project file 2024-03-22 17:39:17 +01:00
iTrooz
1647fa9446 fix: fix ui plugin linking to pl when libimhex already does it (#1583) 2024-03-22 17:38:27 +01:00
WerWolv
41a3fdaf3c fix: Updater not working correctly on Windows 2024-03-22 17:38:05 +01:00
iTrooz
e517406f06 fix: Use find_library() instead of find_file() to find system yara library (#1581)
Discord discussion:
https://discord.com/channels/789833418631675954/789840633414025246/1213564050848485427
2024-03-22 09:44:35 +01:00
WerWolv
0cf2477988 build: Bumped version to 1.33.1 2024-03-02 16:44:54 +01:00
WerWolv
cc3a5aed9a patterns: Updated pattern language 2024-03-02 15:59:59 +01:00
WerWolv
af10317bae impr: Added testers to About screen 2024-03-02 15:59:38 +01:00
WerWolv
5153ad6458 build: Allow precompiled headers to be turned off 2024-03-02 15:59:33 +01:00
WerWolv
432f2f0862 build: Added option to disable precompiled headers 2024-03-02 15:59:11 +01:00
WerWolv
7eb3ee7150 build: Disable precompiled headers in plugins again 2024-03-02 15:58:57 +01:00
WerWolv
6cf2990808 fix: Race condition when downloading multiple elements from the content store 2024-03-02 15:58:53 +01:00
WerWolv
6cb0d4d7d8 fix: MIME based auto loading not working correctly 2024-03-02 15:58:45 +01:00
WerWolv
0d08b36a73 impr: Prevent ImHex from getting stuck in an infinite crash loop 2024-03-02 15:58:26 +01:00
WerWolv
7efdaa73f1 fix: Platform window not being updated when recovering from a crash 2024-03-02 15:58:11 +01:00
WerWolv
6d548180bb fix: Endless loop when throwing exception in deferred tasks 2024-03-02 15:58:02 +01:00
WerWolv
4b64e044f7 fix: Compile error 2024-03-02 15:57:51 +01:00
WerWolv
4a118b94cc impr: Better recovery from exceptions thrown in main thread (#1577)
This PR improves many things which can be seen by the commit name, but
the most important thing is the addition of a popup telling the user
when an exception is thrown

![image](https://github.com/WerWolv/ImHex/assets/42669835/db796416-9cce-4aa5-ad60-c22f05b5fc73)
2024-03-02 15:57:30 +01:00
WerWolv
8e27eb8d36 build: Updated libwolv 2024-02-29 23:06:49 +01:00
WerWolv
b33453f03c git: Run workflows on release branches 2024-02-29 22:28:58 +01:00
WerWolv
7cf88d128b patterns: Updated pattern language 2024-02-29 22:24:01 +01:00
WerWolv
5b7c4324ff build: Disable unknown pragmas warning 2024-02-29 22:18:31 +01:00
WerWolv
aaf9fdf61c fix: Build with precompiled headers for WebAssembly 2024-02-29 22:18:22 +01:00
WerWolv
6e36586ebc fix: Build with precompiled headers on Linux 2024-02-29 22:18:14 +01:00
WerWolv
773f9d3f1c build: Don't add defines to libimhex after precompiling headers 2024-02-29 22:18:09 +01:00
WerWolv
b448583105 build: Added precompiled headers 2024-02-29 22:17:57 +01:00
WerWolv
d1de10c606 fix: Pressing buttons while window is unfocused not working 2024-02-29 22:17:22 +01:00
WerWolv
9ce3a9e612 fix: Inserting bytes and resizing files not working correctly 2024-02-29 22:17:15 +01:00
WerWolv
99eaca4d09 fix: MIME-based pattern loading not working correctly
Fixes #1574
2024-02-29 22:17:03 +01:00
WerWolv
29443af90f fix: Buggy window detachment 2024-02-29 22:16:57 +01:00
WerWolv
d1fb41783d fix: Make sure glfw waits properly on Wayland 2024-02-29 22:16:49 +01:00
WerWolv
99277d71cc fix: Frame limiting not working correctly on Linux 2024-02-28 18:48:24 +01:00
WerWolv
db11c4c791 fix: Crash when using CRC hashes 2024-02-27 22:39:28 +01:00
WerWolv
87c254a437 fix: Read-only file toast showing up for all providers 2024-02-27 20:20:56 +01:00
WerWolv
63a4d65d96 fix: Import menu being disabled with read-only providers
Fixes #1573
2024-02-27 19:42:03 +01:00
WerWolv
cf1868b0b3 impr: Implement a better algorithm to determine if the frame content has changed 2024-02-27 18:59:06 +01:00
WerWolv
a135381b80 fix: Yara rules not being read correctly in data information section 2024-02-27 18:59:01 +01:00
WerWolv
c424e71f7e impr: Add better error handling when loading projects 2024-02-27 18:58:50 +01:00
WerWolv
976baec753 fix: Opening project files through the command line opening them as regular files 2024-02-27 18:58:31 +01:00
WerWolv
25cfa6f10b patterns: Updated pattern language 2024-02-27 18:57:02 +01:00
WerWolv
265213bbac impr: Make hex editor minimap rows stay a fixed height 2024-02-27 18:56:53 +01:00
59 changed files with 788 additions and 463 deletions

View File

@@ -2,7 +2,9 @@ name: Build
on:
push:
branches: ["*"]
branches:
- 'master'
- 'releases/**'
pull_request:
workflow_dispatch:

View File

@@ -2,7 +2,9 @@ name: Build for the web
on:
push:
branches: ["*"]
branches:
- 'master'
- 'releases/**'
pull_request:
workflow_dispatch:

View File

@@ -2,9 +2,13 @@ name: "Unit Tests"
on:
push:
branches: [ master ]
branches:
- 'master'
- 'releases/**'
pull_request:
branches: [ master ]
branches:
- 'master'
- 'releases/**'
workflow_dispatch:
jobs:

View File

@@ -19,6 +19,8 @@ option(IMHEX_ENABLE_UNITY_BUILD "Enables building ImHex as a unity build
option(IMHEX_GENERATE_PDBS "Enable generating PDB files in non-debug builds (Windows only)" OFF)
option(IMHEX_REPLACE_DWARF_WITH_PDB "Remove DWARF information from binaries when generating PDBS (Windows only)" OFF)
option(IMHEX_ENABLE_STD_ASSERTS "Enable debug asserts in the C++ std library. (Breaks Plugin ABI!)" OFF)
option(IMHEX_ENABLE_UNIT_TESTS "Enable building unit tests" OFF)
option(IMHEX_ENABLE_PRECOMPILED_HEADERS "Enable precompiled headers" OFF)
# Basic compiler and cmake configurations
set(CMAKE_CXX_STANDARD 23)

View File

@@ -1 +1 @@
1.33.0
1.33.2

View File

@@ -46,6 +46,9 @@ function(addDefineToSource SOURCE DEFINE)
APPEND
PROPERTY COMPILE_DEFINITIONS "${DEFINE}"
)
# Disable precompiled headers for this file
set_source_files_properties(${SOURCE} PROPERTIES SKIP_PRECOMPILE_HEADERS ON)
endfunction()
# Detect current OS / System
@@ -67,6 +70,9 @@ macro(detectOS)
add_compile_definitions(OS_WEB)
elseif (UNIX AND NOT APPLE)
add_compile_definitions(OS_LINUX)
if (BSD AND BSD STREQUAL "FreeBSD")
add_compile_definitions(OS_FREEBSD)
endif()
include(GNUInstallDirs)
if(IMHEX_PLUGINS_IN_SHARE)
@@ -503,7 +509,7 @@ macro(setupCompilerFlags target)
set(IMHEX_CXX_FLAGS "-fexceptions -frtti")
# Disable some warnings
set(IMHEX_C_CXX_FLAGS "-Wno-unknown-warning-option -Wno-array-bounds -Wno-deprecated-declarations")
set(IMHEX_C_CXX_FLAGS "-Wno-unknown-warning-option -Wno-array-bounds -Wno-deprecated-declarations -Wno-unknown-pragmas")
endif()
if (CMAKE_CXX_COMPILER_ID MATCHES "GNU")
@@ -611,6 +617,7 @@ macro(addBundledLibraries)
endif()
set(LIBPL_BUILD_CLI_AS_EXECUTABLE OFF CACHE BOOL "" FORCE)
set(LIBPL_ENABLE_PRECOMPILED_HEADERS ${IMHEX_ENABLE_PRECOMPILED_HEADERS} CACHE BOOL "" FORCE)
if (WIN32)
set(LIBPL_SHARED_LIBRARY ON CACHE BOOL "" FORCE)
@@ -758,4 +765,19 @@ endfunction()
function(addIncludesFromLibrary target library)
get_target_property(library_include_dirs ${library} INTERFACE_INCLUDE_DIRECTORIES)
target_include_directories(${target} PRIVATE ${library_include_dirs})
endfunction()
function(precompileHeaders target includeFolder)
if (NOT IMHEX_ENABLE_PRECOMPILED_HEADERS)
return()
endif()
file(GLOB_RECURSE TARGET_INCLUDES "${includeFolder}/**/*.hpp")
set(SYSTEM_INCLUDES "<algorithm>;<array>;<atomic>;<chrono>;<cmath>;<cstddef>;<cstdint>;<cstdio>;<cstdlib>;<cstring>;<exception>;<filesystem>;<functional>;<iterator>;<limits>;<list>;<map>;<memory>;<optional>;<ranges>;<set>;<stdexcept>;<string>;<string_view>;<thread>;<tuple>;<type_traits>;<unordered_map>;<unordered_set>;<utility>;<variant>;<vector>")
set(INCLUDES "${SYSTEM_INCLUDES};${TARGET_INCLUDES}")
string(REPLACE ">" "$<ANGLE-R>" INCLUDES "${INCLUDES}")
target_precompile_headers(${target}
PUBLIC
"$<$<COMPILE_LANGUAGE:CXX>:${INCLUDES}>"
)
endfunction()

View File

@@ -1,4 +1,4 @@
find_file(libyara.a YARA_LIBRARIES)
find_library(YARA_LIBRARIES NAMES yara)
find_file(yara.h YARA_INCLUDE_DIRS)
mark_as_advanced(YARA_LIBRARIES YARA_INCLUDE_DIRS)

View File

@@ -36,8 +36,12 @@ macro(add_imhex_plugin)
# Add include directories and link libraries
target_include_directories(${IMHEX_PLUGIN_NAME} PUBLIC ${IMHEX_PLUGIN_INCLUDES})
target_link_libraries(${IMHEX_PLUGIN_NAME} PRIVATE libimhex ${IMHEX_PLUGIN_LIBRARIES} ${FMT_LIBRARIES} imgui_all_includes libwolv)
target_link_libraries(${IMHEX_PLUGIN_NAME} PUBLIC ${IMHEX_PLUGIN_LIBRARIES})
target_link_libraries(${IMHEX_PLUGIN_NAME} PRIVATE libimhex ${FMT_LIBRARIES} imgui_all_includes libwolv)
addIncludesFromLibrary(${IMHEX_PLUGIN_NAME} libpl)
addIncludesFromLibrary(${IMHEX_PLUGIN_NAME} libpl-gen)
precompileHeaders(${IMHEX_PLUGIN_NAME} "${CMAKE_CURRENT_SOURCE_DIR}/include")
# Add IMHEX_PROJECT_NAME and IMHEX_VERSION define
target_compile_definitions(${IMHEX_PLUGIN_NAME} PRIVATE IMHEX_PROJECT_NAME="${IMHEX_PLUGIN_NAME}")
@@ -88,6 +92,12 @@ macro(add_imhex_plugin)
elseif (UNIX)
set_target_properties(${IMHEX_PLUGIN_NAME} PROPERTIES INSTALL_RPATH_USE_ORIGIN ON INSTALL_RPATH "$ORIGIN/")
endif()
if (EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/tests/CMakeLists.txt AND IMHEX_ENABLE_UNIT_TESTS)
add_subdirectory(${CMAKE_CURRENT_SOURCE_DIR}/tests)
target_link_libraries(${IMHEX_PLUGIN_NAME} PUBLIC ${IMHEX_PLUGIN_NAME}_tests)
target_compile_definitions(${IMHEX_PLUGIN_NAME}_tests PRIVATE IMHEX_PROJECT_NAME="${IMHEX_PLUGIN_NAME}-tests")
endif()
endmacro()
macro(add_romfs_resource input output)

View File

@@ -77,37 +77,6 @@ else()
target_compile_definitions(libimhex PRIVATE IMHEX_PROJECT_NAME="${PROJECT_NAME}")
endif()
enableUnityBuild(libimhex)
setupCompilerFlags(libimhex)
include(GenerateExportHeader)
generate_export_header(libimhex)
target_include_directories(libimhex ${LIBIMHEX_LIBRARY_TYPE} include ${XDGPP_INCLUDE_DIRS} ${MBEDTLS_INCLUDE_DIR} ${MAGIC_INCLUDE_DIRS} ${LLVM_INCLUDE_DIRS} ${FMT_INCLUDE_DIRS} ${LIBBACKTRACE_INCLUDE_DIRS})
target_link_directories(libimhex ${LIBIMHEX_LIBRARY_TYPE} ${MBEDTLS_LIBRARY_DIR} ${MAGIC_LIBRARY_DIRS})
if (NOT EMSCRIPTEN)
# curl is only used in non-emscripten builds
target_link_libraries(libimhex ${LIBIMHEX_LIBRARY_TYPE} ${CURL_LIBRARIES})
endif()
if (NOT IMHEX_EXTERNAL_PLUGIN_BUILD)
if (WIN32)
set_target_properties(libimhex PROPERTIES WINDOWS_EXPORT_ALL_SYMBOLS TRUE)
target_link_options(libimhex PRIVATE -Wl,--export-all-symbols)
elseif (APPLE)
find_library(FOUNDATION NAMES Foundation)
target_link_libraries(libimhex PUBLIC ${FOUNDATION})
endif ()
target_link_libraries(libimhex PRIVATE microtar libwolv ${NFD_LIBRARIES} magic dl ${JTHREAD_LIBRARIES})
target_link_libraries(libimhex PUBLIC libpl ${IMGUI_LIBRARIES})
endif()
target_link_libraries(libimhex ${LIBIMHEX_LIBRARY_TYPE} ${NLOHMANN_JSON_LIBRARIES} imgui_all_includes ${MBEDTLS_LIBRARIES} ${FMT_LIBRARIES})
set_property(TARGET libimhex PROPERTY INTERPROCEDURAL_OPTIMIZATION FALSE)
if (DEFINED IMHEX_COMMIT_HASH_LONG AND DEFINED IMHEX_COMMIT_BRANCH)
set(GIT_COMMIT_HASH_LONG "${IMHEX_COMMIT_HASH_LONG}")
@@ -142,4 +111,38 @@ endif ()
addDefineToSource(source/api/imhex_api.cpp "IMHEX_VERSION=\"${IMHEX_VERSION_STRING}\"")
enableUnityBuild(libimhex)
setupCompilerFlags(libimhex)
include(GenerateExportHeader)
generate_export_header(libimhex)
target_include_directories(libimhex ${LIBIMHEX_LIBRARY_TYPE} include ${XDGPP_INCLUDE_DIRS} ${MBEDTLS_INCLUDE_DIR} ${MAGIC_INCLUDE_DIRS} ${LLVM_INCLUDE_DIRS} ${FMT_INCLUDE_DIRS} ${LIBBACKTRACE_INCLUDE_DIRS})
target_link_directories(libimhex ${LIBIMHEX_LIBRARY_TYPE} ${MBEDTLS_LIBRARY_DIR} ${MAGIC_LIBRARY_DIRS})
if (NOT EMSCRIPTEN)
# curl is only used in non-emscripten builds
target_link_libraries(libimhex ${LIBIMHEX_LIBRARY_TYPE} ${CURL_LIBRARIES})
endif()
if (NOT IMHEX_EXTERNAL_PLUGIN_BUILD)
if (WIN32)
set_target_properties(libimhex PROPERTIES WINDOWS_EXPORT_ALL_SYMBOLS TRUE)
target_link_options(libimhex PRIVATE -Wl,--export-all-symbols)
elseif (APPLE)
find_library(FOUNDATION NAMES Foundation)
target_link_libraries(libimhex PUBLIC ${FOUNDATION})
endif ()
target_link_libraries(libimhex PRIVATE microtar libwolv ${NFD_LIBRARIES} magic dl ${JTHREAD_LIBRARIES})
target_link_libraries(libimhex PUBLIC libpl ${IMGUI_LIBRARIES})
precompileHeaders(libimhex "${CMAKE_CURRENT_SOURCE_DIR}/include")
endif()
target_link_libraries(libimhex ${LIBIMHEX_LIBRARY_TYPE} ${NLOHMANN_JSON_LIBRARIES} imgui_all_includes ${MBEDTLS_LIBRARIES} ${FMT_LIBRARIES})
set_property(TARGET libimhex PROPERTY INTERPROCEDURAL_OPTIMIZATION FALSE)
add_dependencies(imhex_all libimhex)

View File

@@ -22,7 +22,7 @@
static void subscribe(void *token, Event::Callback function) { EventManager::subscribe<event_name>(token, function); } \
static void unsubscribe(const EventManager::EventList::iterator &token) noexcept { EventManager::unsubscribe(token); } \
static void unsubscribe(void *token) noexcept { EventManager::unsubscribe<event_name>(token); } \
static void post(auto &&...args) noexcept { EventManager::post<event_name>(std::forward<decltype(args)>(args)...); } \
static void post(auto &&...args) { EventManager::post<event_name>(std::forward<decltype(args)>(args)...); } \
};
#define EVENT_DEF(event_name, ...) EVENT_DEF_IMPL(event_name, #event_name, true, __VA_ARGS__)
@@ -71,11 +71,12 @@ namespace hex {
explicit Event(Callback func) noexcept : m_func(std::move(func)) { }
void operator()(Params... params) const noexcept {
void operator()(std::string_view eventName, Params... params) const {
try {
m_func(params...);
} catch (const std::exception &e) {
log::error("An exception occurred while handling event: {}", e.what());
log::error("An exception occurred while handling event {}: {}", eventName, e.what());
throw;
}
}
@@ -172,12 +173,12 @@ namespace hex {
* @param args Arguments to pass to the event
*/
template<impl::EventType E>
static void post(auto &&...args) noexcept {
static void post(auto && ...args) {
std::scoped_lock lock(getEventMutex());
for (const auto &[id, event] : getEvents()) {
if (id == E::Id) {
(*static_cast<E *const>(event.get()))(std::forward<decltype(args)>(args)...);
(*static_cast<E *const>(event.get()))(wolv::type::getTypeName<E>(), std::forward<decltype(args)>(args)...);
}
}
@@ -308,4 +309,9 @@ namespace hex {
* The 'from' provider should not have any per provider data after this, and should be immediately deleted
*/
EVENT_DEF(MovePerProviderData, prv::Provider *, prv::Provider *);
/**
* Called when ImHex managed to catch an error in a general try/catch to prevent/recover from a crash
*/
EVENT_DEF(EventCrashRecovered, const std::exception &);
}

View File

@@ -698,6 +698,7 @@ namespace hex {
std::vector<GlyphRange> glyphRanges;
Offset offset;
u32 flags;
std::optional<u32> defaultSize;
};
namespace impl {
@@ -716,8 +717,8 @@ namespace hex {
GlyphRange range(const char *glyphBegin, const char *glyphEnd);
GlyphRange range(u32 codepointBegin, u32 codepointEnd);
void loadFont(const std::fs::path &path, const std::vector<GlyphRange> &glyphRanges = {}, Offset offset = {}, u32 flags = 0);
void loadFont(const std::string &name, const std::span<const u8> &data, const std::vector<GlyphRange> &glyphRanges = {}, Offset offset = {}, u32 flags = 0);
void loadFont(const std::fs::path &path, const std::vector<GlyphRange> &glyphRanges = {}, Offset offset = {}, u32 flags = 0, std::optional<u32> defaultSize = std::nullopt);
void loadFont(const std::string &name, const std::span<const u8> &data, const std::vector<GlyphRange> &glyphRanges = {}, Offset offset = {}, u32 flags = 0, std::optional<u32> defaultSize = std::nullopt);
constexpr static float DefaultFontSize = 13.0;

View File

@@ -1,72 +1,76 @@
#pragma once
#include <future>
#if defined(OS_WEB)
#include <emscripten/fetch.h>
#include <future>
namespace hex {
template<typename T>
std::future<HttpRequest::Result<T>> HttpRequest::downloadFile(const std::fs::path &path) {
return std::async(std::launch::async, [this, path] {
std::vector<u8> response;
#include <emscripten/fetch.h>
// Execute the request
auto result = this->executeImpl<T>(response);
namespace hex {
template<typename T>
std::future<HttpRequest::Result<T>> HttpRequest::downloadFile(const std::fs::path &path) {
return std::async(std::launch::async, [this, path] {
std::vector<u8> response;
// Write the result to the file
wolv::io::File file(path, wolv::io::File::Mode::Create);
file.writeBuffer(reinterpret_cast<const u8*>(result.getData().data()), result.getData().size());
// Execute the request
auto result = this->executeImpl<T>(response);
return result;
});
}
// Write the result to the file
wolv::io::File file(path, wolv::io::File::Mode::Create);
file.writeBuffer(reinterpret_cast<const u8*>(result.getData().data()), result.getData().size());
template<typename T>
std::future<HttpRequest::Result<T>> HttpRequest::uploadFile(const std::fs::path &path, const std::string &mimeName) {
hex::unused(path, mimeName);
throw std::logic_error("Not implemented");
}
template<typename T>
std::future<HttpRequest::Result<T>> HttpRequest::uploadFile(std::vector<u8> data, const std::string &mimeName, const std::fs::path &fileName) {
hex::unused(data, mimeName, fileName);
throw std::logic_error("Not implemented");
}
template<typename T>
std::future<HttpRequest::Result<T>> HttpRequest::execute() {
return std::async(std::launch::async, [this] {
std::vector<u8> responseData;
return this->executeImpl<T>(responseData);
});
}
template<typename T>
HttpRequest::Result<T> HttpRequest::executeImpl(std::vector<u8> &data) {
strcpy(m_attr.requestMethod, m_method.c_str());
m_attr.attributes = EMSCRIPTEN_FETCH_SYNCHRONOUS | EMSCRIPTEN_FETCH_LOAD_TO_MEMORY;
if (!m_body.empty()) {
m_attr.requestData = m_body.c_str();
m_attr.requestDataSize = m_body.size();
return result;
});
}
std::vector<const char*> headers;
for (auto it = m_headers.begin(); it != m_headers.end(); it++) {
headers.push_back(it->first.c_str());
headers.push_back(it->second.c_str());
template<typename T>
std::future<HttpRequest::Result<T>> HttpRequest::uploadFile(const std::fs::path &path, const std::string &mimeName) {
hex::unused(path, mimeName);
throw std::logic_error("Not implemented");
}
headers.push_back(nullptr);
m_attr.requestHeaders = headers.data();
// Send request
emscripten_fetch_t* fetch = emscripten_fetch(&m_attr, m_url.c_str());
template<typename T>
std::future<HttpRequest::Result<T>> HttpRequest::uploadFile(std::vector<u8> data, const std::string &mimeName, const std::fs::path &fileName) {
hex::unused(data, mimeName, fileName);
throw std::logic_error("Not implemented");
}
data.resize(fetch->numBytes);
std::copy(fetch->data, fetch->data + fetch->numBytes, data.begin());
template<typename T>
std::future<HttpRequest::Result<T>> HttpRequest::execute() {
return std::async(std::launch::async, [this] {
std::vector<u8> responseData;
return this->executeImpl<T>(responseData);
});
}
template<typename T>
HttpRequest::Result<T> HttpRequest::executeImpl(std::vector<u8> &data) {
strcpy(m_attr.requestMethod, m_method.c_str());
m_attr.attributes = EMSCRIPTEN_FETCH_SYNCHRONOUS | EMSCRIPTEN_FETCH_LOAD_TO_MEMORY;
if (!m_body.empty()) {
m_attr.requestData = m_body.c_str();
m_attr.requestDataSize = m_body.size();
}
std::vector<const char*> headers;
for (auto it = m_headers.begin(); it != m_headers.end(); it++) {
headers.push_back(it->first.c_str());
headers.push_back(it->second.c_str());
}
headers.push_back(nullptr);
m_attr.requestHeaders = headers.data();
// Send request
emscripten_fetch_t* fetch = emscripten_fetch(&m_attr, m_url.c_str());
data.resize(fetch->numBytes);
std::copy(fetch->data, fetch->data + fetch->numBytes, data.begin());
return Result<T>(fetch->status, { data.begin(), data.end() });
}
return Result<T>(fetch->status, { data.begin(), data.end() });
}
}
#endif

View File

@@ -1,145 +1,149 @@
#pragma once
#include <string>
#include <future>
#if !defined(OS_WEB)
#include <curl/curl.h>
#include <string>
#include <future>
#include <hex/helpers/logger.hpp>
#include <hex/helpers/fmt.hpp>
#include <curl/curl.h>
#include <wolv/utils/string.hpp>
#include <hex/helpers/logger.hpp>
#include <hex/helpers/fmt.hpp>
namespace hex {
#include <wolv/utils/string.hpp>
template<typename T>
std::future<HttpRequest::Result<T>> HttpRequest::downloadFile(const std::fs::path &path) {
return std::async(std::launch::async, [this, path] {
std::vector<u8> response;
namespace hex {
wolv::io::File file(path, wolv::io::File::Mode::Create);
curl_easy_setopt(m_curl, CURLOPT_WRITEFUNCTION, writeToFile);
curl_easy_setopt(m_curl, CURLOPT_WRITEDATA, &file);
template<typename T>
std::future<HttpRequest::Result<T>> HttpRequest::downloadFile(const std::fs::path &path) {
return std::async(std::launch::async, [this, path] {
std::vector<u8> response;
return this->executeImpl<T>(response);
});
}
wolv::io::File file(path, wolv::io::File::Mode::Create);
curl_easy_setopt(m_curl, CURLOPT_WRITEFUNCTION, writeToFile);
curl_easy_setopt(m_curl, CURLOPT_WRITEDATA, &file);
template<typename T>
std::future<HttpRequest::Result<T>> HttpRequest::uploadFile(const std::fs::path &path, const std::string &mimeName) {
return std::async(std::launch::async, [this, path, mimeName]{
auto fileName = wolv::util::toUTF8String(path.filename());
curl_mime *mime = curl_mime_init(m_curl);
curl_mimepart *part = curl_mime_addpart(mime);
wolv::io::File file(path, wolv::io::File::Mode::Read);
curl_mime_data_cb(part, file.getSize(),
[](char *buffer, size_t size, size_t nitems, void *arg) -> size_t {
auto handle = static_cast<FILE*>(arg);
return fread(buffer, size, nitems, handle);
},
[](void *arg, curl_off_t offset, int origin) -> int {
auto handle = static_cast<FILE*>(arg);
if (fseek(handle, offset, origin) != 0)
return CURL_SEEKFUNC_CANTSEEK;
else
return CURL_SEEKFUNC_OK;
},
[](void *arg) {
auto handle = static_cast<FILE*>(arg);
fclose(handle);
},
file.getHandle());
curl_mime_filename(part, fileName.c_str());
curl_mime_name(part, mimeName.c_str());
curl_easy_setopt(m_curl, CURLOPT_MIMEPOST, mime);
std::vector<u8> responseData;
curl_easy_setopt(m_curl, CURLOPT_WRITEFUNCTION, writeToVector);
curl_easy_setopt(m_curl, CURLOPT_WRITEDATA, &responseData);
return this->executeImpl<T>(responseData);
});
}
template<typename T>
std::future<HttpRequest::Result<T>> HttpRequest::uploadFile(std::vector<u8> data, const std::string &mimeName, const std::fs::path &fileName) {
return std::async(std::launch::async, [this, data = std::move(data), mimeName, fileName]{
curl_mime *mime = curl_mime_init(m_curl);
curl_mimepart *part = curl_mime_addpart(mime);
curl_mime_data(part, reinterpret_cast<const char *>(data.data()), data.size());
auto fileNameStr = wolv::util::toUTF8String(fileName.filename());
curl_mime_filename(part, fileNameStr.c_str());
curl_mime_name(part, mimeName.c_str());
curl_easy_setopt(m_curl, CURLOPT_MIMEPOST, mime);
std::vector<u8> responseData;
curl_easy_setopt(m_curl, CURLOPT_WRITEFUNCTION, writeToVector);
curl_easy_setopt(m_curl, CURLOPT_WRITEDATA, &responseData);
return this->executeImpl<T>(responseData);
});
}
template<typename T>
std::future<HttpRequest::Result<T>> HttpRequest::execute() {
return std::async(std::launch::async, [this] {
std::vector<u8> responseData;
curl_easy_setopt(m_curl, CURLOPT_WRITEFUNCTION, writeToVector);
curl_easy_setopt(m_curl, CURLOPT_WRITEDATA, &responseData);
return this->executeImpl<T>(responseData);
});
}
template<typename T>
HttpRequest::Result<T> HttpRequest::executeImpl(std::vector<u8> &data) {
curl_easy_setopt(m_curl, CURLOPT_URL, m_url.c_str());
curl_easy_setopt(m_curl, CURLOPT_CUSTOMREQUEST, m_method.c_str());
setDefaultConfig();
if (!m_body.empty()) {
curl_easy_setopt(m_curl, CURLOPT_POSTFIELDS, m_body.c_str());
return this->executeImpl<T>(response);
});
}
curl_slist *headers = nullptr;
headers = curl_slist_append(headers, "Cache-Control: no-cache");
ON_SCOPE_EXIT { curl_slist_free_all(headers); };
template<typename T>
std::future<HttpRequest::Result<T>> HttpRequest::uploadFile(const std::fs::path &path, const std::string &mimeName) {
return std::async(std::launch::async, [this, path, mimeName]{
auto fileName = wolv::util::toUTF8String(path.filename());
for (auto &[key, value] : m_headers) {
std::string header = hex::format("{}: {}", key, value);
headers = curl_slist_append(headers, header.c_str());
curl_mime *mime = curl_mime_init(m_curl);
curl_mimepart *part = curl_mime_addpart(mime);
wolv::io::File file(path, wolv::io::File::Mode::Read);
curl_mime_data_cb(part, file.getSize(),
[](char *buffer, size_t size, size_t nitems, void *arg) -> size_t {
auto handle = static_cast<FILE*>(arg);
return fread(buffer, size, nitems, handle);
},
[](void *arg, curl_off_t offset, int origin) -> int {
auto handle = static_cast<FILE*>(arg);
if (fseek(handle, offset, origin) != 0)
return CURL_SEEKFUNC_CANTSEEK;
else
return CURL_SEEKFUNC_OK;
},
[](void *arg) {
auto handle = static_cast<FILE*>(arg);
fclose(handle);
},
file.getHandle());
curl_mime_filename(part, fileName.c_str());
curl_mime_name(part, mimeName.c_str());
curl_easy_setopt(m_curl, CURLOPT_MIMEPOST, mime);
std::vector<u8> responseData;
curl_easy_setopt(m_curl, CURLOPT_WRITEFUNCTION, writeToVector);
curl_easy_setopt(m_curl, CURLOPT_WRITEDATA, &responseData);
return this->executeImpl<T>(responseData);
});
}
curl_easy_setopt(m_curl, CURLOPT_HTTPHEADER, headers);
{
std::scoped_lock lock(m_transmissionMutex);
template<typename T>
std::future<HttpRequest::Result<T>> HttpRequest::uploadFile(std::vector<u8> data, const std::string &mimeName, const std::fs::path &fileName) {
return std::async(std::launch::async, [this, data = std::move(data), mimeName, fileName]{
curl_mime *mime = curl_mime_init(m_curl);
curl_mimepart *part = curl_mime_addpart(mime);
auto result = curl_easy_perform(m_curl);
if (result != CURLE_OK){
char *url = nullptr;
curl_easy_getinfo(m_curl, CURLINFO_EFFECTIVE_URL, &url);
log::error("Http request '{0} {1}' failed with error {2}: '{3}'", m_method, url, u32(result), curl_easy_strerror(result));
checkProxyErrors();
curl_mime_data(part, reinterpret_cast<const char *>(data.data()), data.size());
auto fileNameStr = wolv::util::toUTF8String(fileName.filename());
curl_mime_filename(part, fileNameStr.c_str());
curl_mime_name(part, mimeName.c_str());
return { };
curl_easy_setopt(m_curl, CURLOPT_MIMEPOST, mime);
std::vector<u8> responseData;
curl_easy_setopt(m_curl, CURLOPT_WRITEFUNCTION, writeToVector);
curl_easy_setopt(m_curl, CURLOPT_WRITEDATA, &responseData);
return this->executeImpl<T>(responseData);
});
}
template<typename T>
std::future<HttpRequest::Result<T>> HttpRequest::execute() {
return std::async(std::launch::async, [this] {
std::vector<u8> responseData;
curl_easy_setopt(m_curl, CURLOPT_WRITEFUNCTION, writeToVector);
curl_easy_setopt(m_curl, CURLOPT_WRITEDATA, &responseData);
return this->executeImpl<T>(responseData);
});
}
template<typename T>
HttpRequest::Result<T> HttpRequest::executeImpl(std::vector<u8> &data) {
curl_easy_setopt(m_curl, CURLOPT_URL, m_url.c_str());
curl_easy_setopt(m_curl, CURLOPT_CUSTOMREQUEST, m_method.c_str());
setDefaultConfig();
if (!m_body.empty()) {
curl_easy_setopt(m_curl, CURLOPT_POSTFIELDS, m_body.c_str());
}
curl_slist *headers = nullptr;
headers = curl_slist_append(headers, "Cache-Control: no-cache");
ON_SCOPE_EXIT { curl_slist_free_all(headers); };
for (auto &[key, value] : m_headers) {
std::string header = hex::format("{}: {}", key, value);
headers = curl_slist_append(headers, header.c_str());
}
curl_easy_setopt(m_curl, CURLOPT_HTTPHEADER, headers);
{
std::scoped_lock lock(m_transmissionMutex);
auto result = curl_easy_perform(m_curl);
if (result != CURLE_OK){
char *url = nullptr;
curl_easy_getinfo(m_curl, CURLINFO_EFFECTIVE_URL, &url);
log::error("Http request '{0} {1}' failed with error {2}: '{3}'", m_method, url, u32(result), curl_easy_strerror(result));
checkProxyErrors();
return { };
}
}
long statusCode = 0;
curl_easy_getinfo(m_curl, CURLINFO_RESPONSE_CODE, &statusCode);
return Result<T>(statusCode, { data.begin(), data.end() });
}
long statusCode = 0;
curl_easy_getinfo(m_curl, CURLINFO_RESPONSE_CODE, &statusCode);
return Result<T>(statusCode, { data.begin(), data.end() });
}
}
#endif

View File

@@ -40,13 +40,15 @@ namespace hex::log {
std::scoped_lock lock(getLoggerMutex());
auto dest = getDestination();
printPrefix(dest, ts, level, IMHEX_PROJECT_NAME);
try {
printPrefix(dest, ts, level, IMHEX_PROJECT_NAME);
auto message = fmt::format(fmt::runtime(fmt), args...);
fmt::print(dest, "{}\n", message);
fflush(dest);
auto message = fmt::format(fmt::runtime(fmt), args...);
fmt::print(dest, "{}\n", message);
fflush(dest);
addLogEntry(IMHEX_PROJECT_NAME, level, std::move(message));
addLogEntry(IMHEX_PROJECT_NAME, level, std::move(message));
} catch (const std::exception&) { }
}
namespace color {
@@ -92,19 +94,23 @@ namespace hex::log {
[[maybe_unused]] void print(const std::string &fmt, auto && ... args) {
std::scoped_lock lock(impl::getLoggerMutex());
auto dest = impl::getDestination();
auto message = fmt::format(fmt::runtime(fmt), args...);
fmt::print(dest, "{}", message);
fflush(dest);
try {
auto dest = impl::getDestination();
auto message = fmt::format(fmt::runtime(fmt), args...);
fmt::print(dest, "{}", message);
fflush(dest);
} catch (const std::exception&) { }
}
[[maybe_unused]] void println(const std::string &fmt, auto && ... args) {
std::scoped_lock lock(impl::getLoggerMutex());
auto dest = impl::getDestination();
auto message = fmt::format(fmt::runtime(fmt), args...);
fmt::print(dest, "{}\n", message);
fflush(dest);
try {
auto dest = impl::getDestination();
auto message = fmt::format(fmt::runtime(fmt), args...);
fmt::print(dest, "{}\n", message);
fflush(dest);
} catch (const std::exception&) { }
}
}

View File

@@ -74,7 +74,7 @@ namespace hex {
return m_data | std::views::values;
}
void setOnCreateCallback(std::function<void(const prv::Provider *, T&)> callback) {
void setOnCreateCallback(std::function<void(prv::Provider *, T&)> callback) {
m_onCreateCallback = std::move(callback);
}
@@ -84,7 +84,7 @@ namespace hex {
auto [it, inserted] = m_data.emplace(provider, T());
auto &[key, value] = *it;
if (m_onCreateCallback)
m_onCreateCallback(key, value);
m_onCreateCallback(provider, value);
});
EventProviderDeleted::subscribe(this, [this](prv::Provider *provider){
@@ -121,7 +121,7 @@ namespace hex {
private:
std::map<const prv::Provider *, T> m_data;
std::function<void(const prv::Provider *, T&)> m_onCreateCallback;
std::function<void(prv::Provider *, T&)> m_onCreateCallback;
};
}

View File

@@ -533,6 +533,11 @@ namespace hex {
pl::PatternLanguage& getRuntime() {
static PerProvider<pl::PatternLanguage> runtime;
AT_FIRST_TIME {
runtime.setOnCreateCallback([](prv::Provider *provider, pl::PatternLanguage &runtime) {
configureRuntime(runtime, provider);
});
};
return *runtime;
}

View File

@@ -658,7 +658,11 @@ namespace hex {
#if defined(OS_WINDOWS)
return "Windows";
#elif defined(OS_LINUX)
return "Linux";
#if defined(OS_FREEBSD)
return "FreeBSD";
#else
return "Linux";
#endif
#elif defined(OS_MACOS)
return "macOS";
#elif defined(OS_WEB)
@@ -915,7 +919,7 @@ namespace hex {
};
}
void loadFont(const std::fs::path &path, const std::vector<GlyphRange> &glyphRanges, Offset offset, u32 flags) {
void loadFont(const std::fs::path &path, const std::vector<GlyphRange> &glyphRanges, Offset offset, u32 flags, std::optional<u32> defaultSize) {
wolv::io::File fontFile(path, wolv::io::File::Mode::Read);
if (!fontFile.isValid()) {
log::error("Failed to load font from file '{}'", wolv::util::toUTF8String(path));
@@ -927,17 +931,19 @@ namespace hex {
fontFile.readVector(),
glyphRanges,
offset,
flags
flags,
defaultSize
});
}
void loadFont(const std::string &name, const std::span<const u8> &data, const std::vector<GlyphRange> &glyphRanges, Offset offset, u32 flags) {
void loadFont(const std::string &name, const std::span<const u8> &data, const std::vector<GlyphRange> &glyphRanges, Offset offset, u32 flags, std::optional<u32> defaultSize) {
impl::s_fonts->emplace_back(Font {
name,
{ data.begin(), data.end() },
glyphRanges,
offset,
flags
flags,
defaultSize
});
}

View File

@@ -412,13 +412,15 @@ namespace hex {
void TaskManager::runDeferredCalls() {
std::scoped_lock lock(s_deferredCallsMutex);
for (const auto &call : s_deferredCalls)
call();
for (const auto &[location, call] : s_onceDeferredCalls)
call();
s_deferredCalls.clear();
s_onceDeferredCalls.clear();
while (!s_deferredCalls.empty()) {
auto callback = s_deferredCalls.front();
s_deferredCalls.pop_front();
callback();
}
while (!s_onceDeferredCalls.empty()) {
auto node = s_onceDeferredCalls.extract(s_onceDeferredCalls.begin());
node.mapped()();
}
}
void TaskManager::runWhenTasksFinished(const std::function<void()> &function) {

View File

@@ -13,7 +13,11 @@
#include <shellapi.h>
#elif defined(OS_LINUX) || defined(OS_WEB)
#include <xdg.hpp>
# if defined(OS_FREEBSD)
#include <sys/syslimits.h>
# else
#include <limits.h>
# endif
#endif
#if defined(OS_WEB)

View File

@@ -65,7 +65,7 @@ namespace hex::log {
s_loggerFile.disableBuffering();
if (s_loggerFile.isValid()) {
s_colorOutputEnabled = true;
s_colorOutputEnabled = false;
break;
}
}

View File

@@ -63,6 +63,8 @@ else ()
target_link_libraries(main PRIVATE pthread)
endif ()
precompileHeaders(main ${CMAKE_CURRENT_SOURCE_DIR}/include)
if (APPLE)
add_compile_definitions(GL_SILENCE_DEPRECATION)
endif ()

View File

@@ -238,7 +238,7 @@ namespace hex::init {
FrameResult WindowSplash::fullFrame() {
glfwSetWindowSize(m_window, 640_scaled, 400_scaled);
glfwSetWindowSize(m_window, 640, 400);
centerWindow(m_window);
glfwPollEvents();
@@ -248,23 +248,21 @@ namespace hex::init {
ImGui_ImplGlfw_NewFrame();
ImGui::NewFrame();
auto scale = ImHexApi::System::getGlobalScale();
// Draw the splash screen background
auto drawList = ImGui::GetBackgroundDrawList();
{
// Draw the splash screen background
drawList->AddImage(this->splashBackgroundTexture, ImVec2(0, 0), this->splashBackgroundTexture.getSize() * scale);
drawList->AddImage(this->splashBackgroundTexture, ImVec2(0, 0), this->splashBackgroundTexture.getSize());
{
// Function to highlight a given number of bytes at a position in the splash screen
const auto highlightBytes = [&](ImVec2 start, size_t count, ImColor color, float opacity) {
// Dimensions and number of bytes that are drawn. Taken from the splash screen image
const auto hexSize = ImVec2(29, 18) * scale;
const auto hexSpacing = ImVec2(17.4, 15) * scale;
const auto hexStart = ImVec2(27, 127) * scale;
const auto hexSize = ImVec2(29, 18);
const auto hexSpacing = ImVec2(17.4, 15);
const auto hexStart = ImVec2(27, 127);
constexpr auto HexCount = ImVec2(13, 7);
@@ -312,10 +310,10 @@ namespace hex::init {
this->progressLerp += (m_progress - this->progressLerp) * 0.1F;
// Draw the splash screen foreground
drawList->AddImage(this->splashTextTexture, ImVec2(0, 0), this->splashTextTexture.getSize() * scale);
drawList->AddImage(this->splashTextTexture, ImVec2(0, 0), this->splashTextTexture.getSize());
// Draw the "copyright" notice
drawList->AddText(ImVec2(35, 85) * scale, ImColor(0xFF, 0xFF, 0xFF, 0xFF), hex::format("WerWolv\n2020 - {0}", &__DATE__[7]).c_str());
drawList->AddText(ImVec2(35, 85), ImColor(0xFF, 0xFF, 0xFF, 0xFF), hex::format("WerWolv\n2020 - {0}", &__DATE__[7]).c_str());
// Draw version information
// In debug builds, also display the current commit hash and branch
@@ -325,18 +323,18 @@ namespace hex::init {
const static auto VersionInfo = hex::format("{0}", ImHexApi::System::getImHexVersion());
#endif
drawList->AddText(ImVec2((this->splashBackgroundTexture.getSize().x * scale - ImGui::CalcTextSize(VersionInfo.c_str()).x) / 2, 105 * scale), ImColor(0xFF, 0xFF, 0xFF, 0xFF), VersionInfo.c_str());
drawList->AddText(ImVec2((this->splashBackgroundTexture.getSize().x - ImGui::CalcTextSize(VersionInfo.c_str()).x) / 2, 105), ImColor(0xFF, 0xFF, 0xFF, 0xFF), VersionInfo.c_str());
}
// Draw the task progress bar
{
std::lock_guard guard(m_progressMutex);
const auto progressBackgroundStart = ImVec2(99, 357) * scale;
const auto progressBackgroundSize = ImVec2(442, 30) * scale;
const auto progressBackgroundStart = ImVec2(99, 357);
const auto progressBackgroundSize = ImVec2(442, 30);
const auto progressStart = progressBackgroundStart + ImVec2(0, 20) * scale;
const auto progressSize = ImVec2(progressBackgroundSize.x * m_progress, 10 * scale);
const auto progressStart = progressBackgroundStart + ImVec2(0, 20);
const auto progressSize = ImVec2(progressBackgroundSize.x * m_progress, 10);
// Draw progress bar
drawList->AddRectFilled(progressStart, progressStart + progressSize, 0xD0FFFFFF);
@@ -344,7 +342,7 @@ namespace hex::init {
// Draw task names separated by | characters
if (!m_currTaskNames.empty()) {
drawList->PushClipRect(progressBackgroundStart, progressBackgroundStart + progressBackgroundSize, true);
drawList->AddText(progressStart + ImVec2(5, -20) * scale, ImColor(0xFF, 0xFF, 0xFF, 0xFF), hex::format("{}", fmt::join(m_currTaskNames, " | ")).c_str());
drawList->AddText(progressStart + ImVec2(5, -20), ImColor(0xFF, 0xFF, 0xFF, 0xFF), hex::format("{}", fmt::join(m_currTaskNames, " | ")).c_str());
drawList->PopClipRect();
}
}
@@ -492,7 +490,7 @@ namespace hex::init {
ImFontConfig cfg;
cfg.OversampleH = cfg.OversampleV = 1, cfg.PixelSnapH = true;
cfg.SizePixels = 13.0_scaled;
cfg.SizePixels = ImHexApi::Fonts::DefaultFontSize;
io.Fonts->AddFontDefault(&cfg);
std::uint8_t *px;

View File

@@ -126,6 +126,7 @@ namespace hex {
throw;
} catch (const std::exception &e) {
log::fatal("Unhandled exception: {}", e.what());
EventCrashRecovered::post(e);
} catch (...) {
log::fatal("Unhandled exception: Unknown exception");
}
@@ -133,26 +134,47 @@ namespace hex {
void errorRecoverLogCallback(void*, const char* fmt, ...) {
va_list args;
va_start(args, fmt);
std::string message;
message.resize(std::vsnprintf(nullptr, 0, fmt, args));
std::vsnprintf(message.data(), message.size(), fmt, args);
message.resize(message.size() - 1);
va_start(args, fmt);
message.resize(std::vsnprintf(nullptr, 0, fmt, args));
va_end(args);
va_start(args, fmt);
std::vsnprintf(message.data(), message.size(), fmt, args);
va_end(args);
message.resize(message.size() - 1);
log::error("{}", message);
}
void Window::fullFrame() {
static u32 crashWatchdog = 0;
try {
this->frameBegin();
this->frame();
this->frameEnd();
// Feed the watchdog
crashWatchdog = 0;
} catch (...) {
// If an exception keeps being thrown, abort the application after 10 frames
// This is done to avoid the application getting stuck in an infinite loop of exceptions
crashWatchdog += 1;
if (crashWatchdog > 10) {
log::fatal("Crash watchdog triggered, aborting");
std::abort();
}
// Try to recover from the exception by bringing ImGui back into a working state
ImGui::ErrorCheckEndFrameRecover(errorRecoverLogCallback, nullptr);
ImGui::EndFrame();
ImGui::UpdatePlatformWindows();
// Handle the exception
handleException();
}
}
@@ -165,10 +187,9 @@ namespace hex {
bool shouldLongSleep = !m_unlockFrameRate;
// Wait 5 frames before actually enabling the long sleep mode to make animations not stutter
constexpr static auto LongSleepTimeout = 5;
static i32 lockTimeout = 0;
if (!shouldLongSleep) {
lockTimeout = LongSleepTimeout;
lockTimeout = m_lastFrameTime * 10'000;
} else if (lockTimeout > 0) {
lockTimeout -= 1;
}
@@ -192,6 +213,7 @@ namespace hex {
constexpr static auto LongSleepFPS = 5.0;
const double timeout = std::max(0.0, (1.0 / LongSleepFPS) - (glfwGetTime() - m_lastStartFrameTime));
glfwPollEvents();
glfwWaitEventsTimeout(timeout);
} else {
glfwPollEvents();
@@ -567,29 +589,54 @@ namespace hex {
// Finalize ImGui frame
ImGui::Render();
// Hash the draw data to determine if anything changed on the screen
// Compare the previous frame buffer to the current one to determine if the window content has changed
// If not, there's no point in sending the draw data off to the GPU and swapping buffers
// NOTE: For anybody looking at this code and thinking "why not just hash the buffer and compare the hashes",
// the reason is that hashing the buffer is significantly slower than just comparing the buffers directly.
// The buffer might become quite large if there's a lot of vertices on the screen but it's still usually less than
// 10MB (out of which only the active portion needs to actually be compared) which is worth the ~60x speedup.
bool shouldRender = false;
{
u32 drawDataHash = 0;
static u32 previousDrawDataHash = 0;
static std::vector<u8> previousVtxData;
static size_t previousVtxDataSize = 0;
size_t offset = 0;
size_t vtxDataSize = 0;
for (const auto viewPort : ImGui::GetPlatformIO().Viewports) {
auto drawData = viewPort->DrawData;
for (int n = 0; n < drawData->CmdListsCount; n++) {
const ImDrawList *cmdList = drawData->CmdLists[n];
drawDataHash = ImHashData(cmdList->VtxBuffer.Data, cmdList->VtxBuffer.Size * sizeof(ImDrawVert), drawDataHash);
vtxDataSize += drawData->CmdLists[n]->VtxBuffer.size() * sizeof(ImDrawVert);
}
}
for (const auto viewPort : ImGui::GetPlatformIO().Viewports) {
auto drawData = viewPort->DrawData;
for (int n = 0; n < drawData->CmdListsCount; n++) {
const ImDrawList *cmdList = drawData->CmdLists[n];
drawDataHash = ImHashData(cmdList->IdxBuffer.Data, cmdList->IdxBuffer.Size * sizeof(ImDrawIdx), drawDataHash);
if (vtxDataSize == previousVtxDataSize) {
shouldRender = shouldRender || std::memcmp(previousVtxData.data() + offset, cmdList->VtxBuffer.Data, cmdList->VtxBuffer.size() * sizeof(ImDrawVert)) != 0;
} else {
shouldRender = true;
}
if (previousVtxData.size() < offset + cmdList->VtxBuffer.size() * sizeof(ImDrawVert)) {
previousVtxData.resize(offset + cmdList->VtxBuffer.size() * sizeof(ImDrawVert));
}
std::memcpy(previousVtxData.data() + offset, cmdList->VtxBuffer.Data, cmdList->VtxBuffer.size() * sizeof(ImDrawVert));
offset += cmdList->VtxBuffer.size() * sizeof(ImDrawVert);
}
}
shouldRender = drawDataHash != previousDrawDataHash;
previousDrawDataHash = drawDataHash;
previousVtxDataSize = vtxDataSize;
}
GLFWwindow *backupContext = glfwGetCurrentContext();
ImGui::UpdatePlatformWindows();
ImGui::RenderPlatformWindowsDefault();
glfwMakeContextCurrent(backupContext);
if (shouldRender) {
int displayWidth, displayHeight;
glfwGetFramebufferSize(m_window, &displayWidth, &displayHeight);
@@ -603,11 +650,6 @@ namespace hex {
m_unlockFrameRate = true;
}
GLFWwindow *backupContext = glfwGetCurrentContext();
ImGui::UpdatePlatformWindows();
ImGui::RenderPlatformWindowsDefault();
glfwMakeContextCurrent(backupContext);
// Process layout load requests
// NOTE: This needs to be done before a new frame is started, otherwise ImGui won't handle docking correctly
LayoutManager::process();

View File

@@ -61,6 +61,8 @@ std::optional<std::fs::path> downloadUpdate(const std::string &url) {
return std::nullopt;
}
hex::log::info("Writing update to file: {}", file.getPath().string());
// Write the downloaded update data to the file
file.writeVector(data);
@@ -97,7 +99,7 @@ int installUpdate(const std::string &type, std::fs::path updatePath) {
};
constexpr static auto UpdateHandlers = {
UpdateHandler { "win-msi", ".msi", "msiexec /fa {} /passive" },
UpdateHandler { "win-msi", ".msi", "msiexec /passive /package {}" },
UpdateHandler { "macos-dmg", ".dmg", "hdiutil attach {}" },
UpdateHandler { "linux-deb-22.04", ".deb", "sudo apt update && sudo apt install -y --fix-broken {}" },
UpdateHandler { "linux-deb-23.04", ".deb", "sudo apt update && sudo apt install -y --fix-broken {}" },
@@ -108,10 +110,14 @@ int installUpdate(const std::string &type, std::fs::path updatePath) {
// Rename the update file to the correct extension
const auto originalPath = updatePath;
updatePath.replace_extension(handler.extension);
hex::log::info("Moving update package from {} to {}", originalPath.string(), updatePath.string());
std::fs::rename(originalPath, updatePath);
// Install the update using the correct command
hex::startProgram(hex::format(handler.command, updatePath.string()));
const auto command = hex::format(handler.command, updatePath.string());
hex::log::info("Starting update process with command: '{}'", command);
hex::startProgram(command);
return EXIT_SUCCESS;
}
@@ -163,6 +169,8 @@ int main(int argc, char **argv) {
if (!updatePath.has_value())
return EXIT_FAILURE;
hex::log::info("Downloaded update successfully");
// Install the update
return installUpdate(updateType, *updatePath);
}

View File

@@ -0,0 +1,46 @@
#pragma once
#include <hex/ui/popup.hpp>
#include <hex/api/localization_manager.hpp>
#include <llvm/Demangle/Demangle.h>
#include <string>
namespace hex::plugin::builtin {
class PopupCrashRecovered : public Popup<PopupCrashRecovered> {
public:
PopupCrashRecovered(const std::exception &e)
: hex::Popup<PopupCrashRecovered>("hex.builtin.popup.crash_recover.title", false),
m_errorType(typeid(e).name()),
m_errorMessage(e.what()) { }
void drawContent() override {
ImGuiExt::TextFormattedWrapped("hex.builtin.popup.crash_recover.message"_lang);
ImGuiExt::TextFormattedWrapped(hex::format("Error: {}: {}", llvm::itaniumDemangle(this->m_errorType), this->m_errorMessage));
if (ImGui::Button("hex.ui.common.okay"_lang)) {
this->close();
}
}
[[nodiscard]] ImGuiWindowFlags getFlags() const override {
return ImGuiWindowFlags_AlwaysAutoResize;
}
[[nodiscard]] ImVec2 getMinSize() const override {
return scaled({ 400, 100 });
}
[[nodiscard]] ImVec2 getMaxSize() const override {
return scaled({ 600, 300 });
}
private:
std::string m_errorType, m_errorMessage;
};
}

View File

@@ -1,6 +1,6 @@
#pragma once
#if defined(OS_WINDOWS) || defined (OS_LINUX)
#if defined(OS_WINDOWS) || (defined(OS_LINUX) && !defined(OS_FREEBSD))
#include <hex/providers/provider.hpp>
#include <hex/api/localization_manager.hpp>

View File

@@ -46,11 +46,13 @@ namespace hex::plugin::builtin {
return m_provider->isSavable();
}
[[nodiscard]] bool isSavableAsRecent() const override { return false; }
void save() override {
m_provider->save();
}
[[nodiscard]] bool open() override { return true; }
[[nodiscard]] bool open() override { return m_provider != this; }
void close() override { }
void resizeRaw(u64 newSize) override {
@@ -101,8 +103,31 @@ namespace hex::plugin::builtin {
return m_provider->getDataDescription();
}
void loadSettings(const nlohmann::json &settings) override { hex::unused(settings); }
[[nodiscard]] nlohmann::json storeSettings(nlohmann::json settings) const override { return settings; }
void loadSettings(const nlohmann::json &settings) override {
Provider::loadSettings(settings);
auto id = settings.at("id").get<u64>();
m_startAddress = settings.at("start_address").get<u64>();
m_size = settings.at("size").get<size_t>();
const auto &providers = ImHexApi::Provider::getProviders();
auto provider = std::ranges::find_if(providers, [id](const prv::Provider *provider) {
return provider->getID() == id;
});
if (provider == providers.end())
return;
m_provider = *provider;
}
[[nodiscard]] nlohmann::json storeSettings(nlohmann::json settings) const override {
settings["id"] = m_provider->getID();
settings["start_address"] = m_startAddress;
settings["size"] = m_size;
return Provider::storeSettings(settings);
}
[[nodiscard]] std::string getTypeName() const override {
return "hex.builtin.provider.view";

View File

@@ -374,6 +374,8 @@
"hex.builtin.popup.exit_application.desc": "You have unsaved changes made to your Project.\nAre you sure you want to exit?",
"hex.builtin.popup.exit_application.title": "Exit Application?",
"hex.builtin.popup.waiting_for_tasks.title": "Waiting for Tasks",
"hex.builtin.popup.crash_recover.title": "Crash recovery",
"hex.builtin.popup.crash_recover.message": "An exception was thrown, but ImHex was able to catch it and advert a crash",
"hex.builtin.popup.blocking_task.title": "Running Task",
"hex.builtin.popup.blocking_task.desc": "A task is currently executing.",
"hex.builtin.popup.save_layout.title": "Save Layout",
@@ -498,7 +500,7 @@
"hex.builtin.setting.toolbar.icons": "Toolbar Icons",
"hex.builtin.shortcut.next_provider": "Select next provider",
"hex.builtin.shortcut.prev_provider": "Select previous provider",
"hex.builtin.title_bar_button.debug_build": "Debug build",
"hex.builtin.title_bar_button.debug_build": "Debug build\nShift+Click to crash using exception\nCtrl+Click to crash using signal",
"hex.builtin.title_bar_button.feedback": "Leave Feedback",
"hex.builtin.tools.ascii_table": "ASCII table",
"hex.builtin.tools.ascii_table.octal": "Show octal",

View File

@@ -21,10 +21,19 @@
#include <popups/popup_question.hpp>
#include <content/popups/popup_tasks_waiting.hpp>
#include <content/popups/popup_unsaved_changes.hpp>
#include <content/popups/popup_crash_recovered.hpp>
namespace hex::plugin::builtin {
static void openFile(const std::fs::path &path) {
if (path.extension() == ".hexproj") {
if (!ProjectFile::load(path)) {
ui::ToastError::open(hex::format("hex.builtin.popup.error.project.load"_lang, wolv::util::toUTF8String(path)));
} else {
return;
}
}
auto provider = ImHexApi::Provider::createProvider("hex.builtin.provider.file", true);
if (auto *fileProvider = dynamic_cast<FileProvider*>(provider); fileProvider != nullptr) {
fileProvider->setPath(path);
@@ -33,6 +42,7 @@ namespace hex::plugin::builtin {
TaskManager::doLater([provider] { ImHexApi::Provider::remove(provider); });
} else {
EventProviderOpened::post(fileProvider);
AchievementManager::unlockAchievement("hex.builtin.achievement.starting_out", "hex.builtin.achievement.starting_out.open_file.name");
}
}
}
@@ -40,6 +50,10 @@ namespace hex::plugin::builtin {
void registerEventHandlers() {
static bool imhexClosing = false;
EventCrashRecovered::subscribe([](const std::exception &e) {
PopupCrashRecovered::open(e);
});
EventWindowClosing::subscribe([](GLFWwindow *window) {
imhexClosing = false;
if (ImHexApi::Provider::isDirty() && !imhexClosing) {
@@ -91,9 +105,6 @@ namespace hex::plugin::builtin {
EventProviderOpened::subscribe([](hex::prv::Provider *provider) {
if (provider != nullptr && ImHexApi::Provider::get() == provider) {
RequestUpdateWindowTitle::post();
if (!provider->isWritable())
ui::ToastInfo::open("hex.builtin.popup.error.read_only"_lang);
}
});
@@ -111,23 +122,24 @@ namespace hex::plugin::builtin {
if (path.extension() == ".hexproj") {
if (!ProjectFile::load(path)) {
ui::ToastError::open(hex::format("hex.builtin.popup.error.project.load"_lang, wolv::util::toUTF8String(path)));
}
} else {
auto newProvider = static_cast<FileProvider*>(
ImHexApi::Provider::createProvider("hex.builtin.provider.file", true)
);
if (newProvider == nullptr)
return;
newProvider->setPath(path);
if (!newProvider->open()) {
hex::ImHexApi::Provider::remove(newProvider);
} else {
EventProviderOpened::post(newProvider);
AchievementManager::unlockAchievement("hex.builtin.achievement.starting_out", "hex.builtin.achievement.starting_out.open_file.name");
return;
}
}
auto newProvider = static_cast<FileProvider*>(
ImHexApi::Provider::createProvider("hex.builtin.provider.file", true)
);
if (newProvider == nullptr)
return;
newProvider->setPath(path);
if (!newProvider->open()) {
hex::ImHexApi::Provider::remove(newProvider);
} else {
EventProviderOpened::post(newProvider);
AchievementManager::unlockAchievement("hex.builtin.achievement.starting_out", "hex.builtin.achievement.starting_out.open_file.name");
}
}, {}, true);
} else if (name == "Open Project") {
@@ -239,6 +251,8 @@ namespace hex::plugin::builtin {
if (ImGui::IsPopupOpen("", ImGuiPopupFlags_AnyPopup))
return;
if (ImGui::IsAnyItemHovered())
return;
static ImGuiWindow *lastFocusedWindow = nullptr;

View File

@@ -278,6 +278,13 @@ namespace hex::plugin::builtin {
// Disable merge mode for this font but retain the rest of the configuration
cfg.MergeMode = false;
auto size = fontSize;
if (font.defaultSize.has_value())
size = font.defaultSize.value() * ImHexApi::System::getGlobalScale();
cfg.SizePixels = size;
ON_SCOPE_EXIT { cfg.MergeMode = true; };
// Construct a range that only contains the first glyph of the font

View File

@@ -200,7 +200,7 @@ namespace hex::plugin::builtin {
std::vector<u8> bytes(5_MiB);
auto selection = ImHexApi::HexEditor::getSelection();
for (u64 address = selection->getStartAddress(); address <= selection->getEndAddress(); address += bytes.size()) {
for (u64 address = selection->getStartAddress(); address < selection->getEndAddress(); address += bytes.size()) {
bytes.resize(std::min<u64>(bytes.size(), selection->getEndAddress() - address));
provider->read(address, bytes.data(), bytes.size());
@@ -416,7 +416,7 @@ namespace hex::plugin::builtin {
/* Import */
{
ContentRegistry::Interface::addMenuItemSubMenu({ "hex.builtin.menu.file", "hex.builtin.menu.file.import" }, ICON_VS_SIGN_IN, 2140, []{}, noRunningTaskAndWritableProvider);
ContentRegistry::Interface::addMenuItemSubMenu({ "hex.builtin.menu.file", "hex.builtin.menu.file.import" }, ICON_VS_SIGN_IN, 2140, []{}, noRunningTaskAndValidProvider);
/* IPS */
ContentRegistry::Interface::addMenuItem({ "hex.builtin.menu.file", "hex.builtin.menu.file.import", "hex.builtin.menu.file.import.ips"}, ICON_VS_GIT_PULL_REQUEST_NEW_CHANGES, 2150,

View File

@@ -348,6 +348,8 @@ namespace hex::plugin::builtin {
// Draw deny button
ImGui::SetCursorPosX(buttonPos(2));
if (ImGui::Button("hex.ui.common.deny"_lang, buttonSize)) {
ContentRegistry::Settings::write<int>("hex.builtin.setting.general", "hex.builtin.setting.general.server_contact", 0);
ContentRegistry::Settings::write<int>("hex.builtin.setting.general", "hex.builtin.setting.general.upload_crash_logs", 0);
page += 1;
}

View File

@@ -37,7 +37,7 @@ namespace hex::plugin::builtin {
ContentRegistry::Provider::add<MemoryFileProvider>(false);
ContentRegistry::Provider::add<ViewProvider>(false);
#if defined(OS_WINDOWS) ||defined (OS_LINUX)
#if defined(OS_WINDOWS) || (defined(OS_LINUX) && !defined(OS_FREEBSD))
ContentRegistry::Provider::add<ProcessMemoryProvider>();
#endif

View File

@@ -28,7 +28,9 @@
#elif defined(OS_LINUX)
#include <fcntl.h>
#include <unistd.h>
#include <linux/fs.h>
#if !defined(OS_FREEBSD)
#include <linux/fs.h>
#endif
#include <sys/stat.h>
#include <sys/ioctl.h>
#include <sys/types.h>
@@ -41,8 +43,11 @@
#include <sys/disk.h>
#endif
#if defined(OS_LINUX)
#define lseek lseek64
#if defined(OS_LINUX) && !defined(OS_FREEBSD)
#define lseek lseek64
#elif defined(OS_FREEBSD)
#include <sys/disk.h>
#define DEFAULT_SECTOR_SIZE 512
#endif
namespace hex::plugin::builtin {
@@ -83,6 +88,12 @@ namespace hex::plugin::builtin {
return -1;
return 0;
}
#elif defined(OS_FREEBSD) && defined(DIOCGSECTORSIZE)
int blkdev_get_sector_size(int fd, int *sector_size) {
if (ioctl(fd, DIOCGSECTORSIZE, sector_size) < 0)
return -1;
return 0;
}
#else
int blkdev_get_sector_size(int fd, int *sector_size) {
(void)fd;
@@ -97,6 +108,12 @@ namespace hex::plugin::builtin {
return -1;
return 0;
}
#elif defined(OS_FREEBSD) && defined(DIOCGMEDIASIZE)
int blkdev_get_size(int fd, u64 *bytes) {
if (ioctl(fd, DIOCGMEDIASIZE, bytes) < 0)
return -1;
return 0;
}
#else
int blkdev_get_size(int fd, u64 *bytes) {
struct stat st;

View File

@@ -1,13 +1,13 @@
#include "content/providers/file_provider.hpp"
#include "content/providers/memory_file_provider.hpp"
#include <cstring>
#include <hex/api/imhex_api.hpp>
#include <hex/api/localization_manager.hpp>
#include <hex/api/project_file_manager.hpp>
#include <hex/api/task_manager.hpp>
#include <toasts/toast_notification.hpp>
#include <hex/helpers/utils.hpp>
#include <hex/helpers/fmt.hpp>
#include <fmt/chrono.h>
@@ -15,6 +15,7 @@
#include <wolv/utils/string.hpp>
#include <nlohmann/json.hpp>
#include <cstring>
#if defined(OS_WINDOWS)
#include <windows.h>
@@ -86,6 +87,7 @@ namespace hex::plugin::builtin {
void FileProvider::resizeRaw(u64 newSize) {
m_file.setSize(newSize);
m_fileSize = newSize;
}
void FileProvider::insertRaw(u64 offset, u64 size) {
@@ -207,7 +209,7 @@ namespace hex::plugin::builtin {
m_readable = true;
m_writable = true;
if (!std::fs::exists(m_path)) {
if (!wolv::io::fs::exists(m_path)) {
this->setErrorMessage(hex::format("hex.builtin.provider.file.error.open"_lang, m_path.string(), ::strerror(ENOENT)));
return false;
}
@@ -222,6 +224,8 @@ namespace hex::plugin::builtin {
this->setErrorMessage(hex::format("hex.builtin.provider.file.error.open"_lang, m_path.string(), ::strerror(errno)));
return false;
}
ui::ToastInfo::open("hex.builtin.popup.error.read_only"_lang);
}
m_file = std::move(file);

View File

@@ -1,4 +1,4 @@
#if defined(OS_WINDOWS) || defined (OS_LINUX)
#if defined(OS_WINDOWS) || (defined(OS_LINUX) && !defined(OS_FREEBSD))
#include <content/providers/process_memory_provider.hpp>

View File

@@ -219,7 +219,9 @@ namespace hex::plugin::builtin::recent {
void loadRecentEntry(const RecentEntry &recentEntry) {
if (recentEntry.type == "project") {
std::fs::path projectPath = recentEntry.data["path"].get<std::string>();
ProjectFile::load(projectPath);
if (!ProjectFile::load(projectPath)) {
ui::ToastError::open(hex::format("hex.builtin.popup.error.project.load"_lang, wolv::util::toUTF8String(projectPath)));
}
return;
}
auto *provider = ImHexApi::Provider::createProvider(recentEntry.type, true);

View File

@@ -7,6 +7,7 @@
#include <hex/helpers/utils.hpp>
#include <hex/helpers/fmt.hpp>
#include <hex/helpers/logger.hpp>
#include <hex/helpers/debugging.hpp>
#include <fonts/codicons_font.h>
#include <imgui.h>

View File

@@ -235,32 +235,20 @@ namespace hex::plugin::builtin {
ImGui::NewLine();
}
void ViewAbout::drawContributorPage() {
struct Contributor {
const char *name;
const char *description;
const char *link;
bool mainContributor;
};
constexpr static std::array Contributors = {
Contributor { "iTrooz", "A huge amount of help maintaining ImHex and the CI", "https://github.com/iTrooz", true },
Contributor { "jumanji144", "A ton of help with the Pattern Language, API and usage stats", "https://github.com/Nowilltolife", true },
Contributor { "Mary", "Porting ImHex to macOS originally", "https://github.com/marysaka", false },
Contributor { "Roblabla", "Adding the MSI Windows installer", "https://github.com/roblabla", false },
Contributor { "jam1garner", "Adding support for Rust plugins", "https://github.com/jam1garner", false },
Contributor { "All other amazing contributors", "Being part of the community, opening issues, PRs and donating", "https://github.com/WerWolv/ImHex/graphs/contributors", false }
};
ImGuiExt::TextFormattedWrapped("These amazing people have contributed some incredible things to ImHex in the past.\nConsider opening a PR on the Git Repository to take your place among them!");
ImGui::NewLine();
struct Contributor {
const char *name;
const char *description;
const char *link;
bool mainContributor;
};
static void drawContributorTable(const char *title, const auto &contributors) {
ImGui::PushStyleVar(ImGuiStyleVar_WindowPadding, ImVec2());
ImGuiExt::BeginSubWindow("Contributors", ImVec2(ImGui::GetContentRegionAvail().x, 0), ImGuiChildFlags_AutoResizeX);
ImGuiExt::BeginSubWindow(title, ImVec2(ImGui::GetContentRegionAvail().x, 0), ImGuiChildFlags_AutoResizeX);
ImGui::PopStyleVar();
{
if (ImGui::BeginTable("Contributors", 1, ImGuiTableFlags_RowBg | ImGuiTableFlags_Borders)) {
for (const auto &contributor : Contributors) {
if (ImGui::BeginTable(title, 1, ImGuiTableFlags_RowBg | ImGuiTableFlags_Borders)) {
for (const auto &contributor : contributors) {
ImGui::TableNextRow();
if (contributor.mainContributor) {
ImGui::TableSetBgColor(ImGuiTableBgTarget_RowBg0, ImGui::GetColorU32(ImGuiCol_PlotHistogram) & 0x1FFFFFFF);
@@ -270,10 +258,11 @@ namespace hex::plugin::builtin {
if (ImGuiExt::Hyperlink(contributor.name))
hex::openWebpage(contributor.link);
ImGui::Indent();
ImGui::TextUnformatted(contributor.description);
ImGui::Unindent();
if (contributor.description[0] != '\0') {
ImGui::Indent();
ImGui::TextUnformatted(contributor.description);
ImGui::Unindent();
}
}
ImGui::EndTable();
@@ -282,6 +271,35 @@ namespace hex::plugin::builtin {
ImGuiExt::EndSubWindow();
}
void ViewAbout::drawContributorPage() {
constexpr static std::array Contributors = {
Contributor { "iTrooz", "A huge amount of help maintaining ImHex and the CI", "https://github.com/iTrooz", true },
Contributor { "jumanji144", "A ton of help with the Pattern Language, API and usage stats", "https://github.com/jumanji144", true },
Contributor { "Mary", "Porting ImHex to macOS originally", "https://github.com/marysaka", false },
Contributor { "Roblabla", "Adding the MSI Windows installer", "https://github.com/roblabla", false },
Contributor { "jam1garner", "Adding support for Rust plugins", "https://github.com/jam1garner", false },
Contributor { "All other amazing contributors", "Being part of the community, opening issues, PRs and donating", "https://github.com/WerWolv/ImHex/graphs/contributors", false }
};
constexpr static std::array Testers = {
Contributor { "Nemoumbra", "Breaking my code literal seconds after I push it", "https://github.com/Nemoumbra", true },
Contributor { "Berylskid", "", "https://github.com/Berylskid", false },
Contributor { "Jan Polak", "", "https://github.com/polak-jan", false },
Contributor { "Ken-Kaneki", "", "https://github.com/loneicewolf", false },
Contributor { "Everybody who has reported issues", "Helping me find bugs and improve the software", "https://github.com/WerWolv/ImHex/issues", false }
};
ImGuiExt::TextFormattedWrapped("These amazing people have contributed some incredible things to ImHex in the past.\nConsider opening a PR on the Git Repository to take your place among them!");
ImGui::NewLine();
drawContributorTable("Contributors", Contributors);
ImGui::NewLine();
ImGuiExt::TextFormattedWrapped("All of these great people made ImHex work much much smoother.\nConsider joining our Tester team to help making ImHex better for everyone!");
ImGui::NewLine();
drawContributorTable("Testers", Testers);
}
void ViewAbout::drawLibraryCreditsPage() {
struct Library {
const char *name;

View File

@@ -313,8 +313,8 @@ namespace hex::plugin::builtin {
u64 droppedBookmarkId = *static_cast<const u64*>(payload->Data);
// Find the correct bookmark with that id
auto droppedIter = std::ranges::find_if(m_bookmarks->begin(), m_bookmarks->end(), [droppedBookmarkId](const auto &bookmark) {
return bookmark.entry.id == droppedBookmarkId;
auto droppedIter = std::ranges::find_if(m_bookmarks->begin(), m_bookmarks->end(), [droppedBookmarkId](const auto &bookmarkItem) {
return bookmarkItem.entry.id == droppedBookmarkId;
});
// Swap the two bookmarks
@@ -412,16 +412,25 @@ namespace hex::plugin::builtin {
u64 end = region.getEndAddress();
if (!locked) {
bool updated = false;
ImGui::PushItemWidth(100_scaled);
ImGuiExt::InputHexadecimal("##begin", &begin);
if (ImGuiExt::InputHexadecimal("##begin", &begin))
updated = true;
ImGui::SameLine(0, 0);
ImGui::TextUnformatted(" - ");
ImGui::SameLine(0, 0);
ImGuiExt::InputHexadecimal("##end", &end);
if (ImGuiExt::InputHexadecimal("##end", &end))
updated = true;
ImGui::PopItemWidth();
if (end > begin)
if (updated && end > begin) {
region = Region(begin, end - begin + 1);
EventHighlightingChanged::post();
}
} else {
ImGuiExt::TextFormatted("0x{:02X} - 0x{:02X}", begin, end);
}

View File

@@ -29,7 +29,7 @@ namespace hex::plugin::builtin {
m_validBytes = 0;
m_selectedProvider = nullptr;
} else {
m_validBytes = u64(region.getProvider()->getActualSize() - region.address);
m_validBytes = u64((region.getProvider()->getBaseAddress() + region.getProvider()->getActualSize()) - region.address);
m_startAddress = region.address;
m_selectedProvider = region.getProvider();
}

View File

@@ -1050,7 +1050,7 @@ namespace hex::plugin::builtin {
ImGui::SetClipboardText(
callback(
provider,
selection->getStartAddress() + provider->getBaseAddress() + provider->getCurrentPageAddress(),
selection->getStartAddress(),
selection->size
).c_str()
);

View File

@@ -133,6 +133,9 @@ namespace hex::plugin::builtin {
}
static void drawVirtualFileTree(const std::vector<const ViewPatternEditor::VirtualFile*> &virtualFiles, u32 level = 0) {
ImGui::PushID(level + 1);
ON_SCOPE_EXIT { ImGui::PopID(); };
std::map<std::string, std::vector<const ViewPatternEditor::VirtualFile*>> currFolderEntries;
for (const auto &file : virtualFiles) {
const auto &path = file->path;
@@ -146,8 +149,7 @@ namespace hex::plugin::builtin {
ImGui::SameLine();
ImGui::TreeNodeEx(currSegment.c_str(), ImGuiTreeNodeFlags_SpanFullWidth | ImGuiTreeNodeFlags_Leaf | ImGuiTreeNodeFlags_NoTreePushOnOpen);
if (ImGui::IsMouseDoubleClicked(ImGuiMouseButton_Left)) {
if (ImGui::IsMouseDoubleClicked(ImGuiMouseButton_Left) && ImGui::IsItemHovered()) {
ImHexApi::Provider::add<prv::MemoryProvider>(file->data, wolv::util::toUTF8String(file->path.filename()));
}
@@ -157,6 +159,7 @@ namespace hex::plugin::builtin {
currFolderEntries[currSegment].emplace_back(file);
}
int id = 1;
for (const auto &[segment, entries] : currFolderEntries) {
ImGui::TableNextRow();
ImGui::TableNextColumn();
@@ -167,11 +170,16 @@ namespace hex::plugin::builtin {
ImGui::TextUnformatted(ICON_VS_FOLDER);
}
ImGui::PushID(id);
ImGui::SameLine();
if (ImGui::TreeNodeEx(segment.c_str(), ImGuiTreeNodeFlags_SpanFullWidth)) {
drawVirtualFileTree(entries, level + 1);
ImGui::TreePop();
}
ImGui::PopID();
id += 1;
}
}
@@ -1158,7 +1166,7 @@ namespace hex::plugin::builtin {
for (const auto &file : virtualFiles)
virtualFilePointers.emplace_back(&file);
if (ImGui::BeginTable("Virtual File Tree", 1, ImGuiTableFlags_BordersOuter | ImGuiTableFlags_BordersInnerH | ImGuiTableFlags_RowBg, size)) {
if (ImGui::BeginTable("Virtual File Tree", 1, ImGuiTableFlags_BordersOuter | ImGuiTableFlags_BordersInnerH | ImGuiTableFlags_RowBg | ImGuiTableFlags_ScrollY, size)) {
ImGui::TableSetupColumn("##path", ImGuiTableColumnFlags_WidthStretch);
drawVirtualFileTree(virtualFilePointers);
@@ -1305,7 +1313,7 @@ namespace hex::plugin::builtin {
pl::PatternLanguage runtime;
ContentRegistry::PatternLanguage::configureRuntime(runtime, provider);
auto mimeType = magic::getMIMEType(provider, true);
auto mimeType = magic::getMIMEType(provider, 0, 100_KiB, true);
bool foundCorrectType = false;
runtime.addPragma("MIME", [&mimeType, &foundCorrectType](const pl::PatternLanguage &runtime, const std::string &value) {
@@ -1392,12 +1400,8 @@ namespace hex::plugin::builtin {
if (!file.isValid())
continue;
auto &preprocessor = runtime.getInternals().preprocessor;
pl::api::Source source(file.readString());
auto ret = preprocessor->preprocess(&runtime, &source);
if (ret.hasErrs()) {
auto result = runtime.preprocessString(file.readString(), pl::api::Source::DefaultSource);
if (!result.has_value()) {
log::warn("Failed to preprocess file {} during MIME analysis", entry.path().string());
}
@@ -1542,6 +1546,7 @@ namespace hex::plugin::builtin {
m_sectionWindowDrawer.clear();
m_consoleEditor.SetText("");
m_virtualFiles->clear();
m_accessHistory = {};
m_accessHistoryIndex = 0;

View File

@@ -198,7 +198,6 @@ namespace hex::plugin::builtin {
ImGui::BeginDisabled(m_updateAllTask.isRunning() || m_updateCount == 0);
if (ImGuiExt::IconButton(ICON_VS_CLOUD_DOWNLOAD, ImGui::GetStyleColorVec4(ImGuiCol_Text))) {
m_updateAllTask = TaskManager::createTask("Update All...", m_updateCount, [this](auto &task) {
u32 progress = 0;
for (auto &category : m_categories) {
for (auto &entry : category.entries) {
if (entry.hasUpdate) {
@@ -207,8 +206,12 @@ namespace hex::plugin::builtin {
continue;
m_download.wait();
this->handleDownloadFinished(category, entry);
task.update(progress);
while (m_download.valid()) {
std::this_thread::sleep_for(10ms);
}
task.increment();
}
}
}
@@ -369,7 +372,6 @@ namespace hex::plugin::builtin {
log::error("Download failed! HTTP Code {}", response.getStatusCode());
}
m_download = {};
}

View File

@@ -1,5 +1,6 @@
#include <hex.hpp>
#include <hex/helpers/http_requests.hpp>
#include <hex/api/workspace_manager.hpp>
#include <hex/api/event_manager.hpp>
#include <hex/api/content_registry.hpp>
#include <hex/api/localization_manager.hpp>
@@ -7,7 +8,11 @@
#include <hex/api/layout_manager.hpp>
#include <hex/api/achievement_manager.hpp>
#include <hex/api_urls.hpp>
#include <hex/ui/view.hpp>
#include <toasts/toast_notification.hpp>
#include <hex/helpers/http_requests.hpp>
#include <hex/helpers/fs.hpp>
#include <hex/helpers/logger.hpp>
@@ -28,8 +33,6 @@
#include <string>
#include <random>
#include <popups/popup_question.hpp>
#include <hex/api/workspace_manager.hpp>
namespace hex::plugin::builtin {
@@ -546,14 +549,17 @@ namespace hex::plugin::builtin {
// Restore callback
[crashFileData, backupFilePath, hasProject, hasBackupFile] {
if (hasBackupFile) {
ProjectFile::load(backupFilePath);
if (hasProject) {
ProjectFile::setPath(crashFileData["project"].get<std::string>());
if (ProjectFile::load(backupFilePath)) {
if (hasProject) {
ProjectFile::setPath(crashFileData["project"].get<std::string>());
} else {
ProjectFile::setPath("");
}
RequestUpdateWindowTitle::post();
} else {
ProjectFile::setPath("");
ui::ToastError::open(hex::format("hex.builtin.popup.error.project.load"_lang, wolv::util::toUTF8String(backupFilePath)));
}
RequestUpdateWindowTitle::post();
}else{
} else {
if (hasProject) {
ProjectFile::setPath(crashFileData["project"].get<std::string>());
}

View File

@@ -80,9 +80,10 @@ namespace hex::plugin::decompress {
if (stream.avail_out != 0)
break;
section.resize(section.size() * 2);
stream.next_out = section.data();
stream.avail_out = section.size();
const auto prevSectionSize = section.size();
section.resize(prevSectionSize * 2);
stream.next_out = section.data() + prevSectionSize;
stream.avail_out = prevSectionSize;
}
return true;
@@ -126,9 +127,10 @@ namespace hex::plugin::decompress {
if (stream.avail_out != 0)
break;
section.resize(section.size() * 2);
stream.next_out = reinterpret_cast<char*>(section.data());
stream.avail_out = section.size();
const auto prevSectionSize = section.size();
section.resize(prevSectionSize * 2);
stream.next_out = reinterpret_cast<char*>(section.data()) + prevSectionSize;
stream.avail_out = prevSectionSize;
}
return true;
@@ -173,9 +175,10 @@ namespace hex::plugin::decompress {
if (stream.avail_out != 0)
break;
section.resize(section.size() * 2);
stream.next_out = compressedData.data();
stream.avail_out = compressedData.size();
const auto prevSectionSize = section.size();
section.resize(prevSectionSize * 2);
stream.next_out = section.data() + prevSectionSize;
stream.avail_out = prevSectionSize;
}
return true;

View File

@@ -18,6 +18,7 @@ namespace hex::plugin::diffing {
~ViewDiff() override;
void drawContent() override;
void drawAlwaysVisibleContent() override;
ImGuiWindowFlags getWindowFlags() const override { return ImGuiWindowFlags_NoScrollbar | ImGuiWindowFlags_NoScrollWithMouse; }
public:

View File

@@ -192,14 +192,12 @@ namespace hex::plugin::diffing {
ImGui::TableSetupColumn("hex.diffing.view.diff.provider_b"_lang);
ImGui::TableHeadersRow();
ImVec2 buttonPos;
ImGui::BeginDisabled(m_diffTask.isRunning());
{
// Draw settings button
ImGui::TableNextColumn();
if (ImGuiExt::DimmedIconButton(ICON_VS_SETTINGS_GEAR, ImGui::GetStyleColorVec4(ImGuiCol_Text)))
ImGui::OpenPopup("DiffingAlgorithmSettings");
buttonPos = ImGui::GetCursorScreenPos();
RequestOpenPopup::post("##DiffingAlgorithmSettings");
ImGui::SameLine();
@@ -212,41 +210,6 @@ namespace hex::plugin::diffing {
}
ImGui::EndDisabled();
ImGui::SetNextWindowPos(buttonPos);
if (ImGui::BeginPopup("DiffingAlgorithmSettings")) {
ImGuiExt::Header("hex.diffing.view.diff.algorithm"_lang, true);
ImGui::PushItemWidth(300_scaled);
if (ImGui::BeginCombo("##Algorithm", m_algorithm == nullptr ? "" : Lang(m_algorithm->getUnlocalizedName()))) {
for (const auto &algorithm : ContentRegistry::Diffing::impl::getAlgorithms()) {
ImGui::PushID(algorithm.get());
if (ImGui::Selectable(Lang(algorithm->getUnlocalizedName()))) {
m_algorithm = algorithm.get();
m_analyzed = false;
}
ImGui::PopID();
}
ImGui::EndCombo();
}
ImGui::PopItemWidth();
if (m_algorithm != nullptr) {
ImGuiExt::TextFormattedWrapped("{}", Lang(m_algorithm->getUnlocalizedDescription()));
}
ImGuiExt::Header("hex.diffing.view.diff.settings"_lang);
if (m_algorithm != nullptr) {
auto drawList = ImGui::GetWindowDrawList();
auto prevIdx = drawList->_VtxCurrentIdx;
m_algorithm->drawSettings();
auto currIdx = drawList->_VtxCurrentIdx;
if (prevIdx == currIdx)
ImGuiExt::TextFormatted("hex.diffing.view.diff.settings.no_settings"_lang);
}
ImGui::EndPopup();
}
ImGui::TableNextRow();
// Draw first hex editor column
@@ -337,4 +300,42 @@ namespace hex::plugin::diffing {
}
}
void ViewDiff::drawAlwaysVisibleContent() {
ImGui::SetNextWindowSizeConstraints(ImVec2(0, 0), ImVec2(400_scaled, 600_scaled));
if (ImGui::BeginPopup("##DiffingAlgorithmSettings")) {
ImGuiExt::Header("hex.diffing.view.diff.algorithm"_lang, true);
ImGui::PushItemWidth(300_scaled);
if (ImGui::BeginCombo("##Algorithm", m_algorithm == nullptr ? "" : Lang(m_algorithm->getUnlocalizedName()))) {
for (const auto &algorithm : ContentRegistry::Diffing::impl::getAlgorithms()) {
ImGui::PushID(algorithm.get());
if (ImGui::Selectable(Lang(algorithm->getUnlocalizedName()))) {
m_algorithm = algorithm.get();
m_analyzed = false;
}
ImGui::PopID();
}
ImGui::EndCombo();
}
ImGui::PopItemWidth();
if (m_algorithm != nullptr) {
ImGuiExt::TextFormattedWrapped("{}", Lang(m_algorithm->getUnlocalizedDescription()));
}
ImGuiExt::Header("hex.diffing.view.diff.settings"_lang);
if (m_algorithm != nullptr) {
auto drawList = ImGui::GetWindowDrawList();
auto prevIdx = drawList->_VtxCurrentIdx;
m_algorithm->drawSettings();
auto currIdx = drawList->_VtxCurrentIdx;
if (prevIdx == currIdx)
ImGuiExt::TextFormatted("hex.diffing.view.diff.settings.no_settings"_lang);
}
ImGui::EndPopup();
}
}
}

View File

@@ -2,6 +2,8 @@
#include <hex.hpp>
#include <array>
#include <capstone/capstone.h>
namespace hex::plugin::disasm {

View File

@@ -18,15 +18,15 @@ namespace hex::fonts {
* efficient when packing the glyphs into the font atlas and therefor make the atlas much smaller.
*/
ImHexApi::Fonts::loadFont("Blender Icons", romfs::get("fonts/blendericons.ttf").span<u8>(),{ { ICON_MIN_BI, ICON_MAX_BI } }, { -1_scaled, -1_scaled });
ImHexApi::Fonts::loadFont("Blender Icons", romfs::get("fonts/blendericons.ttf").span<u8>(),{ { ICON_MIN_BI, ICON_MAX_BI } }, { -1_scaled, -1_scaled }, 0, 13);
ImHexApi::Fonts::loadFont("VS Codicons", romfs::get("fonts/codicons.ttf").span<u8>(),
{
{ ICON_MIN_VS, ICON_MAX_VS }
},
{ -1_scaled, -1_scaled });
{ -1_scaled, -1_scaled }, 0, 13);
ImHexApi::Fonts::loadFont("Unifont", romfs::get("fonts/unifont.otf").span<u8>());
ImHexApi::Fonts::loadFont("Unifont", romfs::get("fonts/unifont.otf").span<u8>(), {}, {}, 0, 16);
}
}

View File

@@ -183,6 +183,9 @@ namespace hex::plugin::hashes {
Function create(std::string name) override {
return Hash::create(name, [hash = *this](const Region& region, prv::Provider *provider) -> std::vector<u8> {
auto crc = HashFactory::Checksum::CreateCRC(hash.m_width, hash.m_polynomial, hash.m_initialValue, hash.m_reflectIn, hash.m_reflectOut, hash.m_xorOut, 0, { "CRC" });
crc->Initialize();
auto bytes = hashProviderRegionWithHashLib(region, provider, crc);
return bytes;

View File

@@ -9,6 +9,8 @@
#include <functional>
#include <string>
#include <vector>
#include <set>
namespace hex::ui {

View File

@@ -6,6 +6,7 @@
#include <fonts/codicons_font.h>
#include <hex/helpers/utils.hpp>
#include <hex/helpers/logger.hpp>
#include <popups/popup_notification.hpp>
@@ -48,18 +49,24 @@ namespace hex::ui {
}
struct ToastInfo : impl::ToastNotification<ToastInfo> {
ToastInfo(std::string message)
: ToastNotification(ImGuiExt::GetCustomColorVec4(ImGuiCustomCol_LoggerInfo), ICON_VS_INFO, "hex.ui.common.info", std::move(message)) {}
explicit ToastInfo(std::string message)
: ToastNotification(ImGuiExt::GetCustomColorVec4(ImGuiCustomCol_LoggerInfo), ICON_VS_INFO, "hex.ui.common.info", message) {
log::info("{}", message);
}
};
struct ToastWarning : impl::ToastNotification<ToastWarning> {
ToastWarning(std::string message)
: ToastNotification(ImGuiExt::GetCustomColorVec4(ImGuiCustomCol_LoggerWarning), ICON_VS_WARNING, "hex.ui.common.warning", std::move(message)) {}
explicit ToastWarning(std::string message)
: ToastNotification(ImGuiExt::GetCustomColorVec4(ImGuiCustomCol_LoggerWarning), ICON_VS_WARNING, "hex.ui.common.warning", message) {
log::warn("{}", message);
}
};
struct ToastError : impl::ToastNotification<ToastError> {
ToastError(std::string message)
: ToastNotification(ImGuiExt::GetCustomColorVec4(ImGuiCustomCol_LoggerError), ICON_VS_ERROR, "hex.ui.common.error", std::move(message)) {}
explicit ToastError(std::string message)
: ToastNotification(ImGuiExt::GetCustomColorVec4(ImGuiCustomCol_LoggerError), ICON_VS_ERROR, "hex.ui.common.error", message) {
log::error("{}", message);
}
};
}

View File

@@ -206,11 +206,11 @@ namespace hex::ui {
constexpr auto roundingCorners = ImDrawFlags_RoundCornersTopRight | ImDrawFlags_RoundCornersBottomRight;
constexpr auto axis = ImGuiAxis_Y;
constexpr static u64 RowCount = 256;
const auto rowHeight = innerRect.GetSize().y / RowCount;
const auto rowHeight = 4_scaled;
const u64 rowCount = innerRect.GetSize().y / rowHeight;
const ImS64 scrollPos = m_scrollPosition.get();
const auto grabSize = rowHeight * m_visibleRowCount;
const ImS64 grabPos = (RowCount - m_visibleRowCount) * (double(scrollPos) / numRows);
const ImS64 grabPos = (rowCount - m_visibleRowCount) * (double(scrollPos) / numRows);
auto drawList = ImGui::GetWindowDrawList();
@@ -239,7 +239,7 @@ namespace hex::ui {
std::vector<u8> rowData(m_bytesPerRow);
const auto drawStart = std::max<ImS64>(0, scrollPos - grabPos);
for (ImS64 y = drawStart; y < std::min<ImS64>(drawStart + RowCount, m_provider->getSize() / m_bytesPerRow); y += 1) {
for (ImS64 y = drawStart; y < std::min<ImS64>(drawStart + rowCount, m_provider->getSize() / m_bytesPerRow); y += 1) {
const auto rowStart = bb.Min + ImVec2(0, (y - drawStart) * rowHeight);
const auto rowEnd = rowStart + ImVec2(bb.GetSize().x, rowHeight);
@@ -1050,7 +1050,7 @@ namespace hex::ui {
this->setSelection(selectionStart.value_or(address), endAddress);
this->scrollToSelection();
}
else if (ImGui::IsMouseDown(ImGuiMouseButton_Left) || (ImGui::IsMouseDown(ImGuiMouseButton_Right) && (address < m_selectionStart || address > m_selectionEnd))) {
else if (ImGui::IsMouseDown(ImGuiMouseButton_Left) || (ImGui::IsMouseDown(ImGuiMouseButton_Right) && (address < std::min(m_selectionStart, m_selectionEnd) || address > std::max(m_selectionStart, m_selectionEnd)))) {
if (ImGui::GetIO().KeyShift)
this->setSelection(selectionStart.value_or(address), endAddress);
else

View File

@@ -5,6 +5,7 @@
"language": "German",
"translations": {
"hex.yara.information_section.advanced_data_info": "Erweiterte Dateninformationen",
"hex.yara.information_section.advanced_data_info.no_information": "Kein erweiterten Informationen gefunden",
"hex.yara_rules.view.yara.error": "Yara Kompilerfehler: {0}",
"hex.yara_rules.view.yara.header.matches": "Treffer",
"hex.yara_rules.view.yara.header.rules": "Regeln",

View File

@@ -5,6 +5,7 @@
"fallback": true,
"translations": {
"hex.yara.information_section.advanced_data_info": "Advanced Data Information",
"hex.yara.information_section.advanced_data_info.no_information": "No further information found",
"hex.yara_rules.view.yara.error": "Yara Compiler error: {0}",
"hex.yara_rules.view.yara.header.matches": "Matches",
"hex.yara_rules.view.yara.header.rules": "Rules",

View File

@@ -1,6 +1,4 @@
#include <hex/api/content_registry.hpp>
#include <hex/helpers/magic.hpp>
#include <hex/providers/provider.hpp>
#include <imgui.h>
#include <hex/api/task_manager.hpp>
@@ -29,9 +27,11 @@ namespace hex::plugin::yara {
void process(Task &task, prv::Provider *provider, Region region) override {
for (const auto &yaraSignaturePath : fs::getDefaultPaths(fs::ImHexPath::YaraAdvancedAnalysis)) {
for (const auto &ruleFilePath : std::fs::recursive_directory_iterator(yaraSignaturePath)) {
const std::string fileContent = romfs::get(ruleFilePath).data<const char>();
wolv::io::File file(ruleFilePath.path(), wolv::io::File::Mode::Read);
if (!file.isValid())
continue;
YaraRule yaraRule(fileContent);
YaraRule yaraRule(file.readString());
task.setInterruptCallback([&yaraRule] {
yaraRule.interrupt();
});
@@ -57,28 +57,39 @@ namespace hex::plugin::yara {
}
void drawContent() override {
if (ImGui::BeginTable("information", 2, ImGuiTableFlags_SizingStretchProp | ImGuiTableFlags_NoKeepColumnsVisible)) {
ImGui::TableSetupColumn("Left", ImGuiTableColumnFlags_WidthStretch, 0.5F);
ImGui::TableSetupColumn("Right", ImGuiTableColumnFlags_WidthStretch, 0.5F);
const auto empty = !std::ranges::any_of(m_categories, [](const auto &entry) {
const auto &[categoryName, category] = entry;
return !category.matchedRules.empty();
});
ImGui::TableNextRow();
if (!empty) {
if (ImGui::BeginTable("information", 2, ImGuiTableFlags_SizingStretchProp | ImGuiTableFlags_NoKeepColumnsVisible)) {
ImGui::TableSetupColumn("Left", ImGuiTableColumnFlags_WidthStretch, 0.5F);
ImGui::TableSetupColumn("Right", ImGuiTableColumnFlags_WidthStretch, 0.5F);
for (auto &[categoryName, category] : m_categories) {
if (category.matchedRules.empty())
continue;
ImGui::TableNextRow();
ImGui::TableNextColumn();
ImGuiExt::BeginSubWindow(categoryName.c_str());
{
for (const auto &match : category.matchedRules) {
const auto &ruleName = match.metadata.contains("name") ? match.metadata.at("name") : match.identifier;
ImGui::TextUnformatted(ruleName.c_str());
for (auto &[categoryName, category] : m_categories) {
if (category.matchedRules.empty())
continue;
ImGui::TableNextColumn();
ImGuiExt::BeginSubWindow(categoryName.c_str());
{
for (const auto &match : category.matchedRules) {
const auto &ruleName = match.metadata.contains("name") ? match.metadata.at("name") : match.identifier;
ImGui::TextUnformatted(ruleName.c_str());
}
}
ImGuiExt::EndSubWindow();
}
ImGuiExt::EndSubWindow();
}
ImGui::EndTable();
ImGui::EndTable();
}
} else {
ImGui::NewLine();
ImGuiExt::TextFormattedCenteredHorizontal("{}", "hex.yara.information_section.advanced_data_info.no_information"_lang);
ImGui::NewLine();
}
}