mirror of
https://github.com/WerWolv/ImHex.git
synced 2026-03-31 05:15:55 -05:00
Compare commits
32 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
9c4e314bb6 | ||
|
|
ea26722a18 | ||
|
|
5aee359700 | ||
|
|
5d11fc960e | ||
|
|
707fec0e2a | ||
|
|
55b877d5e0 | ||
|
|
e779285be4 | ||
|
|
cf6ae52889 | ||
|
|
caad705975 | ||
|
|
0c3fc6f858 | ||
|
|
0529155faa | ||
|
|
aa01d58b33 | ||
|
|
0c0caf6942 | ||
|
|
7e01ff451f | ||
|
|
e0e4b0a5a9 | ||
|
|
0e2c1f1355 | ||
|
|
0ed7341f71 | ||
|
|
29e970fd81 | ||
|
|
43ab72dcb8 | ||
|
|
07dc77f13d | ||
|
|
9b2ee998de | ||
|
|
e1c5cd1e86 | ||
|
|
0d0301f4f6 | ||
|
|
29adeae6a3 | ||
|
|
6b62a1963e | ||
|
|
fb2af5593f | ||
|
|
e938b75acd | ||
|
|
03daf0c95b | ||
|
|
189ea1c3c7 | ||
|
|
8448c3367b | ||
|
|
cc29707bb1 | ||
|
|
eff9ecf7cd |
35
.github/workflows/release.yml
vendored
35
.github/workflows/release.yml
vendored
@@ -6,11 +6,12 @@ name: Release
|
||||
on:
|
||||
release:
|
||||
types: [published]
|
||||
workflow_dispatch:
|
||||
|
||||
jobs:
|
||||
release:
|
||||
release-common:
|
||||
runs-on: ubuntu-latest
|
||||
name: Release
|
||||
name: Release Common
|
||||
|
||||
steps:
|
||||
- name: 🧰 Checkout
|
||||
@@ -110,3 +111,33 @@ jobs:
|
||||
tag: ImHex-v${{env.IMHEX_VERSION}}
|
||||
repo: ImHex-Patterns
|
||||
token: ${{ secrets.RELEASE_TOKEN }}
|
||||
|
||||
- name: ✉️ Update C++ Plugin Template
|
||||
uses: mvasigh/dispatch-action@main
|
||||
with:
|
||||
token: ${{ secrets.RELEASE_TOKEN }}
|
||||
repo: ImHex-Cpp-Plugin-Template
|
||||
owner: WerWolv
|
||||
event_type: update_submodule
|
||||
|
||||
release-windows:
|
||||
name: Release Windows
|
||||
needs: release-common
|
||||
runs-on: windows-2022
|
||||
steps:
|
||||
- name: ⬇️ Download dependencies
|
||||
shell: pwsh
|
||||
run: |
|
||||
iwr https://github.com/microsoft/winget-create/releases/download/v1.0.4.0/wingetcreate.exe -OutFile wingetcreate.exe
|
||||
- name: ⬆️ Update winget manifest
|
||||
shell: pwsh
|
||||
env:
|
||||
WINGET_GITHUB_TOKEN: ${{ secrets.RELEASE_TOKEN }}
|
||||
run: |
|
||||
$tagname = $env:GITHUB_REF.Replace("refs/tags/", "")
|
||||
$version = $tagname.Replace("v", "")
|
||||
$url = "https://github.com/WerWolv/ImHex/releases/download/${tagname}/imhex-${version}-win64.msi"
|
||||
.\wingetcreate.exe update WerWolv.ImHex -u $url --version $version
|
||||
if ($version -notmatch "-") {
|
||||
.\wingetcreate.exe submit .\manifests\w\WerWolv\ImHex\${version}\ --token $env:WINGET_GITHUB_TOKEN
|
||||
}
|
||||
|
||||
18
.github/workflows/tests.yml
vendored
18
.github/workflows/tests.yml
vendored
@@ -47,18 +47,18 @@ jobs:
|
||||
run: |
|
||||
mkdir -p build
|
||||
cd build
|
||||
CC=gcc-12 CXX=g++-12 cmake \
|
||||
-DCMAKE_BUILD_TYPE=$BUILD_TYPE \
|
||||
-DCMAKE_INSTALL_PREFIX="$PWD/install" \
|
||||
-DCMAKE_C_COMPILER_LAUNCHER=ccache \
|
||||
-DCMAKE_CXX_COMPILER_LAUNCHER=ccache \
|
||||
-DCMAKE_C_FLAGS="-fuse-ld=lld" \
|
||||
-DCMAKE_CXX_FLAGS="-fuse-ld=lld" \
|
||||
-DIMHEX_PATTERNS_PULL_MASTER=ON \
|
||||
CC=gcc-12 CXX=g++-12 cmake \
|
||||
-DCMAKE_BUILD_TYPE=Debug \
|
||||
-DCMAKE_INSTALL_PREFIX="$PWD/install" \
|
||||
-DCMAKE_C_COMPILER_LAUNCHER=ccache \
|
||||
-DCMAKE_CXX_COMPILER_LAUNCHER=ccache \
|
||||
-DCMAKE_C_FLAGS="-fuse-ld=lld -fsanitize=address,leak,undefined -fno-sanitize-recover=all" \
|
||||
-DCMAKE_CXX_FLAGS="-fuse-ld=lld -fsanitize=address,leak,undefined -fno-sanitize-recover=all" \
|
||||
-DIMHEX_OFFLINE_BUILD=ON \
|
||||
..
|
||||
make -j4 unit_tests install
|
||||
|
||||
- name: 🧪 Perform Unit Tests
|
||||
run: |
|
||||
cd build
|
||||
ctest --output-on-failure
|
||||
ctest --output-on-failure
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
cmake_minimum_required(VERSION 3.16)
|
||||
cmake_minimum_required(VERSION 3.20)
|
||||
|
||||
# Options
|
||||
option(IMHEX_PLUGINS_IN_SHARE "Put the plugins in share/imhex/plugins instead of lib[..]/imhex/plugins" OFF)
|
||||
@@ -46,4 +46,4 @@ enable_testing()
|
||||
add_subdirectory(tests EXCLUDE_FROM_ALL)
|
||||
|
||||
# Configure packaging
|
||||
createPackage()
|
||||
createPackage()
|
||||
|
||||
@@ -133,7 +133,7 @@ macro(configurePackingResources)
|
||||
|
||||
if (CREATE_PACKAGE)
|
||||
set(CPACK_GENERATOR "WIX")
|
||||
set(CPACK_PACKAGE_NAME "ImHex")
|
||||
set(CPACK_PACKAGE_NAME "imhex")
|
||||
set(CPACK_PACKAGE_VENDOR "WerWolv")
|
||||
set(CPACK_WIX_UPGRADE_GUID "05000E99-9659-42FD-A1CF-05C554B39285")
|
||||
set(CPACK_WIX_PRODUCT_ICON "${PROJECT_SOURCE_DIR}/resources/dist/windows/icon.ico")
|
||||
|
||||
2
lib/external/pattern_language
vendored
2
lib/external/pattern_language
vendored
Submodule lib/external/pattern_language updated: 7285b76f82...ec8ed47d66
@@ -126,6 +126,7 @@ namespace hex {
|
||||
EVENT_DEF(RequestSetPatternLanguageCode, std::string);
|
||||
EVENT_DEF(RequestChangeWindowTitle, std::string);
|
||||
EVENT_DEF(RequestCloseImHex, bool);
|
||||
EVENT_DEF(RequestRestartImHex);
|
||||
EVENT_DEF(RequestOpenFile, std::fs::path);
|
||||
EVENT_DEF(RequestChangeTheme, u32);
|
||||
EVENT_DEF(RequestOpenPopup, std::string);
|
||||
|
||||
@@ -150,15 +150,6 @@ namespace hex {
|
||||
|
||||
}
|
||||
|
||||
namespace Tasks {
|
||||
|
||||
Task createTask(const std::string &unlocalizedName, u64 maxValue);
|
||||
|
||||
void doLater(const std::function<void()> &function);
|
||||
std::vector<std::function<void()>> &getDeferredCalls();
|
||||
|
||||
}
|
||||
|
||||
namespace System {
|
||||
|
||||
namespace impl {
|
||||
@@ -210,6 +201,7 @@ namespace hex {
|
||||
|
||||
std::map<std::string, std::string> &getInitArguments();
|
||||
|
||||
constexpr static float DefaultFontSize = 13.0;
|
||||
const std::fs::path &getCustomFontPath();
|
||||
float getFontSize();
|
||||
|
||||
|
||||
@@ -2,40 +2,100 @@
|
||||
|
||||
#include <hex.hpp>
|
||||
|
||||
#include <list>
|
||||
#include <cstdio>
|
||||
#include <thread>
|
||||
#include <functional>
|
||||
#include <cstdint>
|
||||
#include <mutex>
|
||||
#include <string>
|
||||
#include <chrono>
|
||||
#include <memory>
|
||||
#include <list>
|
||||
|
||||
namespace hex {
|
||||
|
||||
class TaskHolder;
|
||||
class TaskManager;
|
||||
|
||||
class Task {
|
||||
public:
|
||||
Task() = default;
|
||||
Task(const std::string &unlocalizedName, u64 maxValue);
|
||||
Task(std::string unlocalizedName, u64 maxValue, std::function<void(Task &)> function);
|
||||
|
||||
Task(const Task&) = delete;
|
||||
Task(Task &&other) noexcept;
|
||||
~Task();
|
||||
|
||||
Task(Task &&other) noexcept;
|
||||
void update(u64 value = 0);
|
||||
void setMaxValue(u64 value);
|
||||
|
||||
void setMaxValue(u64 maxValue);
|
||||
void update(u64 currValue);
|
||||
void finish();
|
||||
[[nodiscard]] bool isFinished() const;
|
||||
[[nodiscard]] bool hadException() const;
|
||||
[[nodiscard]] bool wasInterrupted() const;
|
||||
void clearException();
|
||||
|
||||
[[nodiscard]] double getProgress() const;
|
||||
[[nodiscard]] const std::string &getUnlocalizedName();
|
||||
[[nodiscard]] u64 getValue() const;
|
||||
[[nodiscard]] u64 getMaxValue() const;
|
||||
|
||||
[[nodiscard]] const std::string &getName() const;
|
||||
|
||||
[[nodiscard]] bool isPending() const;
|
||||
|
||||
static size_t getRunningTaskCount();
|
||||
static std::list<Task *> &getRunningTasks() { return Task::s_runningTasks; }
|
||||
static std::mutex &getTaskMutex() { return Task::s_taskMutex; }
|
||||
void interrupt();
|
||||
|
||||
private:
|
||||
std::string m_name;
|
||||
u64 m_maxValue = 0, m_currValue = 0;
|
||||
void finish();
|
||||
void interruption();
|
||||
void exception();
|
||||
|
||||
static std::list<Task *> s_runningTasks;
|
||||
static std::mutex s_taskMutex;
|
||||
private:
|
||||
mutable std::mutex m_mutex;
|
||||
|
||||
std::string m_unlocalizedName;
|
||||
u64 m_currValue, m_maxValue;
|
||||
std::thread m_thread;
|
||||
|
||||
bool m_shouldInterrupt = false;
|
||||
|
||||
bool m_interrupted = false;
|
||||
bool m_finished = false;
|
||||
bool m_hadException = false;
|
||||
|
||||
struct TaskInterruptor { virtual ~TaskInterruptor() = default; };
|
||||
|
||||
friend class TaskHolder;
|
||||
friend class TaskManager;
|
||||
};
|
||||
|
||||
class TaskHolder {
|
||||
public:
|
||||
TaskHolder() = default;
|
||||
explicit TaskHolder(std::weak_ptr<Task> task) : m_task(std::move(task)) { }
|
||||
|
||||
[[nodiscard]] bool isRunning() const;
|
||||
[[nodiscard]] bool hadException() const;
|
||||
[[nodiscard]] bool wasInterrupted() const;
|
||||
|
||||
void interrupt();
|
||||
private:
|
||||
std::weak_ptr<Task> m_task;
|
||||
};
|
||||
|
||||
class TaskManager {
|
||||
public:
|
||||
TaskManager() = delete;
|
||||
|
||||
constexpr static auto NoProgress = 0;
|
||||
|
||||
static TaskHolder createTask(std::string name, u64 maxValue, std::function<void(Task &)> function);
|
||||
static void collectGarbage();
|
||||
|
||||
static size_t getRunningTaskCount();
|
||||
static std::list<std::shared_ptr<Task>> &getRunningTasks();
|
||||
|
||||
static void doLater(const std::function<void()> &function);
|
||||
static void runDeferredCalls();
|
||||
private:
|
||||
static std::mutex s_deferredCallsMutex;
|
||||
|
||||
static std::list<std::shared_ptr<Task>> s_tasks;
|
||||
static std::list<std::function<void()>> s_deferredCalls;
|
||||
};
|
||||
|
||||
}
|
||||
@@ -68,7 +68,7 @@ namespace hex {
|
||||
}
|
||||
|
||||
constexpr inline i128 signExtend(size_t numBits, i128 value) {
|
||||
i128 mask = 1U << (numBits - 1);
|
||||
i128 mask = 1ULL << (numBits - 1);
|
||||
return (value ^ mask) - mask;
|
||||
}
|
||||
|
||||
@@ -84,6 +84,13 @@ namespace hex {
|
||||
return result;
|
||||
}
|
||||
|
||||
constexpr inline size_t strnlen(const char *s, size_t n) {
|
||||
size_t i = 0;
|
||||
while (i < n && s[i] != '\x00') i++;
|
||||
|
||||
return i;
|
||||
}
|
||||
|
||||
template<class... Ts>
|
||||
struct overloaded : Ts... { using Ts::operator()...; };
|
||||
template<class... Ts>
|
||||
|
||||
@@ -20,11 +20,8 @@ namespace hex {
|
||||
}
|
||||
|
||||
void restartImHex() {
|
||||
EventManager::post<RequestRestartImHex>();
|
||||
EventManager::post<RequestCloseImHex>(false);
|
||||
std::atexit([] {
|
||||
auto &programArgs = ImHexApi::System::getProgramArguments();
|
||||
execve(programArgs.argv[0], programArgs.argv, programArgs.envp);
|
||||
});
|
||||
}
|
||||
|
||||
}
|
||||
@@ -239,7 +236,7 @@ namespace hex {
|
||||
}
|
||||
|
||||
void setCurrentProvider(u32 index) {
|
||||
if (Task::getRunningTaskCount() > 0)
|
||||
if (TaskManager::getRunningTaskCount() > 0)
|
||||
return;
|
||||
|
||||
if (index < s_providers.size() && s_currentProvider != index) {
|
||||
@@ -269,7 +266,7 @@ namespace hex {
|
||||
}
|
||||
|
||||
void add(prv::Provider *provider, bool skipLoadInterface) {
|
||||
if (Task::getRunningTaskCount() > 0)
|
||||
if (TaskManager::getRunningTaskCount() > 0)
|
||||
return;
|
||||
|
||||
if (skipLoadInterface)
|
||||
@@ -285,7 +282,7 @@ namespace hex {
|
||||
if (provider == nullptr)
|
||||
return;
|
||||
|
||||
if (Task::getRunningTaskCount() > 0)
|
||||
if (TaskManager::getRunningTaskCount() > 0)
|
||||
return;
|
||||
|
||||
if (!noQuestions) {
|
||||
@@ -322,29 +319,6 @@ namespace hex {
|
||||
|
||||
}
|
||||
|
||||
|
||||
namespace ImHexApi::Tasks {
|
||||
|
||||
Task createTask(const std::string &unlocalizedName, u64 maxValue) {
|
||||
return { unlocalizedName, maxValue };
|
||||
}
|
||||
|
||||
void doLater(const std::function<void()> &function) {
|
||||
static std::mutex tasksMutex;
|
||||
std::scoped_lock lock(tasksMutex);
|
||||
|
||||
getDeferredCalls().push_back(function);
|
||||
}
|
||||
|
||||
std::vector<std::function<void()>> &getDeferredCalls() {
|
||||
static std::vector<std::function<void()>> deferredCalls;
|
||||
|
||||
return deferredCalls;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
namespace ImHexApi::System {
|
||||
|
||||
namespace impl {
|
||||
@@ -393,7 +367,7 @@ namespace hex {
|
||||
s_customFontPath = path;
|
||||
}
|
||||
|
||||
static float s_fontSize = 13.0;
|
||||
static float s_fontSize = DefaultFontSize;
|
||||
void setFontSize(float size) {
|
||||
s_fontSize = size;
|
||||
}
|
||||
|
||||
@@ -6,66 +6,174 @@
|
||||
|
||||
namespace hex {
|
||||
|
||||
std::list<Task *> Task::s_runningTasks;
|
||||
std::mutex Task::s_taskMutex;
|
||||
std::mutex TaskManager::s_deferredCallsMutex;
|
||||
|
||||
Task::Task(const std::string &unlocalizedName, u64 maxValue) : m_name(LangEntry(unlocalizedName)), m_maxValue(maxValue), m_currValue(0) {
|
||||
std::scoped_lock lock(Task::s_taskMutex);
|
||||
std::list<std::shared_ptr<Task>> TaskManager::s_tasks;
|
||||
std::list<std::function<void()>> TaskManager::s_deferredCalls;
|
||||
|
||||
Task::s_runningTasks.push_back(this);
|
||||
}
|
||||
Task::Task(std::string unlocalizedName, u64 maxValue, std::function<void(Task &)> function)
|
||||
: m_unlocalizedName(std::move(unlocalizedName)), m_currValue(0), m_maxValue(maxValue) {
|
||||
this->m_thread = std::thread([this, func = std::move(function)] {
|
||||
try {
|
||||
func(*this);
|
||||
} catch (const TaskInterruptor &) {
|
||||
this->interruption();
|
||||
} catch (...) {
|
||||
this->exception();
|
||||
}
|
||||
|
||||
Task::~Task() {
|
||||
this->finish();
|
||||
this->finish();
|
||||
});
|
||||
}
|
||||
|
||||
Task::Task(hex::Task &&other) noexcept {
|
||||
std::scoped_lock lock(Task::s_taskMutex);
|
||||
std::scoped_lock thisLock(this->m_mutex);
|
||||
std::scoped_lock otherLock(other.m_mutex);
|
||||
|
||||
this->m_thread = std::move(other.m_thread);
|
||||
this->m_unlocalizedName = std::move(other.m_unlocalizedName);
|
||||
|
||||
this->m_name = other.m_name;
|
||||
this->m_maxValue = other.m_maxValue;
|
||||
this->m_currValue = other.m_currValue;
|
||||
|
||||
auto it = std::find(Task::s_runningTasks.begin(), Task::s_runningTasks.end(), &other);
|
||||
if (it != Task::s_runningTasks.end()) {
|
||||
*it = this;
|
||||
}
|
||||
this->m_finished = other.m_finished;
|
||||
this->m_hadException = other.m_hadException;
|
||||
this->m_interrupted = other.m_interrupted;
|
||||
this->m_shouldInterrupt = other.m_shouldInterrupt;
|
||||
}
|
||||
|
||||
Task::~Task() {
|
||||
this->interrupt();
|
||||
this->m_thread.join();
|
||||
}
|
||||
|
||||
void Task::update(u64 value) {
|
||||
std::scoped_lock lock(this->m_mutex);
|
||||
|
||||
this->m_currValue = value;
|
||||
|
||||
if (this->m_shouldInterrupt)
|
||||
throw TaskInterruptor();
|
||||
}
|
||||
|
||||
void Task::setMaxValue(u64 value) {
|
||||
std::scoped_lock lock(this->m_mutex);
|
||||
|
||||
this->m_maxValue = value;
|
||||
}
|
||||
|
||||
|
||||
void Task::interrupt() {
|
||||
std::scoped_lock lock(this->m_mutex);
|
||||
|
||||
this->m_shouldInterrupt = true;
|
||||
}
|
||||
|
||||
bool Task::isFinished() const {
|
||||
std::scoped_lock lock(this->m_mutex);
|
||||
|
||||
return this->m_finished;
|
||||
}
|
||||
|
||||
bool Task::hadException() const {
|
||||
std::scoped_lock lock(this->m_mutex);
|
||||
|
||||
return this->m_hadException;
|
||||
}
|
||||
|
||||
bool Task::wasInterrupted() const {
|
||||
std::scoped_lock lock(this->m_mutex);
|
||||
|
||||
return this->m_interrupted;
|
||||
}
|
||||
|
||||
void Task::clearException() {
|
||||
std::scoped_lock lock(this->m_mutex);
|
||||
|
||||
this->m_hadException = false;
|
||||
}
|
||||
|
||||
const std::string &Task::getUnlocalizedName() {
|
||||
return this->m_unlocalizedName;
|
||||
}
|
||||
|
||||
u64 Task::getValue() const {
|
||||
return this->m_currValue;
|
||||
}
|
||||
|
||||
u64 Task::getMaxValue() const {
|
||||
return this->m_maxValue;
|
||||
}
|
||||
|
||||
void Task::finish() {
|
||||
std::scoped_lock lock(Task::s_taskMutex);
|
||||
std::scoped_lock lock(this->m_mutex);
|
||||
|
||||
Task::s_runningTasks.remove(this);
|
||||
this->m_finished = true;
|
||||
}
|
||||
|
||||
void Task::setMaxValue(u64 maxValue) {
|
||||
this->m_maxValue = maxValue;
|
||||
void Task::interruption() {
|
||||
std::scoped_lock lock(this->m_mutex);
|
||||
|
||||
this->m_interrupted = true;
|
||||
}
|
||||
|
||||
void Task::update(u64 currValue) {
|
||||
if (this->m_currValue < this->m_maxValue)
|
||||
this->m_currValue = currValue;
|
||||
void Task::exception() {
|
||||
std::scoped_lock lock(this->m_mutex);
|
||||
|
||||
this->m_hadException = true;
|
||||
}
|
||||
|
||||
double Task::getProgress() const {
|
||||
if (this->m_maxValue == 0)
|
||||
return 100;
|
||||
|
||||
return static_cast<double>(this->m_currValue) / static_cast<double>(this->m_maxValue);
|
||||
bool TaskHolder::isRunning() const {
|
||||
return !m_task.expired() && !m_task.lock()->isFinished();
|
||||
}
|
||||
|
||||
bool Task::isPending() const {
|
||||
return this->m_maxValue == 0;
|
||||
bool TaskHolder::hadException() const {
|
||||
return m_task.expired() || m_task.lock()->hadException();
|
||||
}
|
||||
|
||||
const std::string &Task::getName() const {
|
||||
return this->m_name;
|
||||
bool TaskHolder::wasInterrupted() const {
|
||||
return m_task.expired() || m_task.lock()->wasInterrupted();
|
||||
}
|
||||
|
||||
size_t Task::getRunningTaskCount() {
|
||||
std::scoped_lock lock(Task::s_taskMutex);
|
||||
void TaskHolder::interrupt() {
|
||||
if (!this->m_task.expired())
|
||||
this->m_task.lock()->interrupt();
|
||||
}
|
||||
|
||||
return Task::s_runningTasks.size();
|
||||
|
||||
TaskHolder TaskManager::createTask(std::string name, u64 maxValue, std::function<void(Task &)> function) {
|
||||
s_tasks.emplace_back(std::make_shared<Task>(std::move(name), maxValue, std::move(function)));
|
||||
|
||||
return TaskHolder(s_tasks.back());
|
||||
}
|
||||
|
||||
void TaskManager::collectGarbage() {
|
||||
std::erase_if(s_tasks, [](const auto &task) { return task->isFinished() && !task->hadException(); });
|
||||
}
|
||||
|
||||
std::list<std::shared_ptr<Task>> &TaskManager::getRunningTasks() {
|
||||
return s_tasks;
|
||||
}
|
||||
|
||||
size_t TaskManager::getRunningTaskCount() {
|
||||
return s_tasks.size();
|
||||
}
|
||||
|
||||
|
||||
void TaskManager::doLater(const std::function<void()> &function) {
|
||||
std::scoped_lock lock(s_deferredCallsMutex);
|
||||
|
||||
s_deferredCalls.push_back(function);
|
||||
}
|
||||
|
||||
void TaskManager::runDeferredCalls() {
|
||||
std::scoped_lock lock(s_deferredCallsMutex);
|
||||
|
||||
for (const auto &call : s_deferredCalls)
|
||||
call();
|
||||
|
||||
s_deferredCalls.clear();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,7 +1,8 @@
|
||||
#include <hex/helpers/file.hpp>
|
||||
|
||||
#include <hex/helpers/utils.hpp>
|
||||
|
||||
#include <unistd.h>
|
||||
#include <cstring>
|
||||
|
||||
namespace hex::fs {
|
||||
|
||||
@@ -90,7 +91,7 @@ namespace hex::fs {
|
||||
return "";
|
||||
|
||||
auto cString = reinterpret_cast<const char *>(bytes.data());
|
||||
return { cString, std::min(bytes.size(), std::strlen(cString)) };
|
||||
return { cString, hex::strnlen(cString, bytes.size()) };
|
||||
}
|
||||
|
||||
std::u8string File::readU8String(size_t numBytes) {
|
||||
@@ -104,7 +105,7 @@ namespace hex::fs {
|
||||
return u8"";
|
||||
|
||||
auto cString = reinterpret_cast<const char8_t *>(bytes.data());
|
||||
return { cString, std::min(bytes.size(), std::strlen(reinterpret_cast<const char*>(bytes.data()))) };
|
||||
return { cString, hex::strnlen(reinterpret_cast<const char*>(bytes.data()), bytes.size()) };
|
||||
}
|
||||
|
||||
void File::write(const u8 *buffer, size_t size) {
|
||||
|
||||
@@ -124,7 +124,7 @@ namespace hex {
|
||||
if (result != CURLE_OK)
|
||||
log::error("Net request failed with error {0}: '{1}'", u32(result), curl_easy_strerror(result));
|
||||
|
||||
i32 responseCode = 0;
|
||||
long responseCode = 0;
|
||||
curl_easy_getinfo(this->m_ctx, CURLINFO_RESPONSE_CODE, &responseCode);
|
||||
|
||||
curl_slist_free_all(this->m_headers);
|
||||
@@ -135,7 +135,7 @@ namespace hex {
|
||||
if (result != CURLE_OK)
|
||||
return std::nullopt;
|
||||
else
|
||||
return responseCode;
|
||||
return i32(responseCode);
|
||||
}
|
||||
|
||||
std::future<Response<std::string>> Net::getString(const std::string &url, u32 timeout) {
|
||||
|
||||
@@ -266,7 +266,7 @@ namespace hex::prv {
|
||||
}
|
||||
|
||||
std::pair<Region, bool> Provider::getRegionValidity(u64 address) const {
|
||||
if (address > this->getActualSize())
|
||||
if ((address - this->getBaseAddress()) > this->getActualSize())
|
||||
return { Region::Invalid(), false };
|
||||
|
||||
bool insideValidRegion = false;
|
||||
@@ -292,7 +292,7 @@ namespace hex::prv {
|
||||
}
|
||||
|
||||
if (!nextRegionAddress.has_value())
|
||||
return { Region { address, this->getActualSize() - address }, true };
|
||||
return { Region::Invalid(), false };
|
||||
else
|
||||
return { Region { address, *nextRegionAddress - address }, insideValidRegion };
|
||||
}
|
||||
|
||||
@@ -13,6 +13,8 @@
|
||||
|
||||
#include <imgui_impl_opengl3_loader.h>
|
||||
|
||||
#include <hex/api/imhex_api.hpp>
|
||||
|
||||
namespace ImGui {
|
||||
|
||||
int UpdateStringSizeCallback(ImGuiInputTextCallbackData *data) {
|
||||
@@ -536,7 +538,7 @@ namespace ImGui {
|
||||
const ImGuiStyle &style = g.Style;
|
||||
|
||||
ImVec2 pos = window->DC.CursorPos + ImVec2(0, yOffset);
|
||||
ImVec2 size = CalcItemSize(ImVec2(100, 5), 100, g.FontSize + style.FramePadding.y * 2.0f);
|
||||
ImVec2 size = CalcItemSize(ImVec2(100, 5) * hex::ImHexApi::System::getGlobalScale(), 100, g.FontSize + style.FramePadding.y * 2.0f);
|
||||
ImRect bb(pos, pos + size);
|
||||
ItemSize(size, 0);
|
||||
if (!ItemAdd(bb, 0))
|
||||
|
||||
@@ -49,7 +49,7 @@ namespace hex {
|
||||
}
|
||||
|
||||
ImVec2 View::getMinSize() const {
|
||||
return scaled(ImVec2(480, 720));
|
||||
return scaled(ImVec2(10, 10));
|
||||
}
|
||||
|
||||
ImVec2 View::getMaxSize() const {
|
||||
|
||||
@@ -173,7 +173,6 @@ namespace hex::init {
|
||||
ContentRegistry::Provider::getEntries().clear();
|
||||
|
||||
ImHexApi::System::getInitArguments().clear();
|
||||
ImHexApi::Tasks::getDeferredCalls().clear();
|
||||
ImHexApi::HexEditor::impl::getBackgroundHighlights().clear();
|
||||
ImHexApi::HexEditor::impl::getForegroundHighlights().clear();
|
||||
ImHexApi::HexEditor::impl::getBackgroundHighlightingFunctions().clear();
|
||||
@@ -215,12 +214,13 @@ namespace hex::init {
|
||||
|
||||
ShortcutManager::clearShortcuts();
|
||||
|
||||
hex::Task::getRunningTasks().clear();
|
||||
TaskManager::getRunningTasks().clear();
|
||||
|
||||
ContentRegistry::DataProcessorNode::getEntries().clear();
|
||||
|
||||
ContentRegistry::DataFormatter::getEntries().clear();
|
||||
ContentRegistry::FileHandler::getEntries().clear();
|
||||
ContentRegistry::Hashes::impl::getHashes().clear();
|
||||
|
||||
{
|
||||
auto &visualizers = ContentRegistry::HexEditor::impl::getVisualizers();
|
||||
|
||||
@@ -18,42 +18,51 @@ int main(int argc, char **argv, char **envp) {
|
||||
ImHexApi::System::impl::setBorderlessWindowMode(true);
|
||||
#endif
|
||||
|
||||
// Initialization
|
||||
{
|
||||
Window::initNative();
|
||||
bool shouldRestart = false;
|
||||
|
||||
hex::log::info("Welcome to ImHex!");
|
||||
EventManager::subscribe<RequestRestartImHex>([&]{ shouldRestart = true; });
|
||||
|
||||
init::WindowSplash splashWindow;
|
||||
do {
|
||||
shouldRestart = false;
|
||||
|
||||
for (const auto &[name, task] : init::getInitTasks())
|
||||
splashWindow.addStartupTask(name, task);
|
||||
// Initialization
|
||||
{
|
||||
Window::initNative();
|
||||
|
||||
if (!splashWindow.loop())
|
||||
ImHexApi::System::getInitArguments().insert({ "tasks-failed", {} });
|
||||
}
|
||||
hex::log::info("Welcome to ImHex!");
|
||||
|
||||
// Clean up
|
||||
ON_SCOPE_EXIT {
|
||||
for (const auto &[name, task] : init::getExitTasks())
|
||||
task();
|
||||
};
|
||||
init::WindowSplash splashWindow;
|
||||
|
||||
// Main window
|
||||
{
|
||||
Window window;
|
||||
for (const auto &[name, task] : init::getInitTasks())
|
||||
splashWindow.addStartupTask(name, task);
|
||||
|
||||
if (argc == 1)
|
||||
; // No arguments provided
|
||||
else if (argc == 2)
|
||||
EventManager::post<RequestOpenFile>(argv[1]);
|
||||
else {
|
||||
hex::log::fatal("Usage: {} [<file_name>]", argv[0]);
|
||||
return EXIT_FAILURE;
|
||||
if (!splashWindow.loop())
|
||||
ImHexApi::System::getInitArguments().insert({ "tasks-failed", {} });
|
||||
}
|
||||
|
||||
window.loop();
|
||||
}
|
||||
// Clean up
|
||||
ON_SCOPE_EXIT {
|
||||
for (const auto &[name, task] : init::getExitTasks())
|
||||
task();
|
||||
};
|
||||
|
||||
// Main window
|
||||
{
|
||||
Window window;
|
||||
|
||||
if (argc == 1)
|
||||
; // No arguments provided
|
||||
else if (argc == 2)
|
||||
EventManager::post<RequestOpenFile>(argv[1]);
|
||||
else {
|
||||
hex::log::fatal("Usage: {} [<file_name>]", argv[0]);
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
window.loop();
|
||||
}
|
||||
|
||||
} while (shouldRestart);
|
||||
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
|
||||
@@ -86,11 +86,11 @@ namespace hex {
|
||||
{
|
||||
for (const auto &[argument, value] : ImHexApi::System::getInitArguments()) {
|
||||
if (argument == "no-plugins") {
|
||||
ImHexApi::Tasks::doLater([] { ImGui::OpenPopup("No Plugins"); });
|
||||
TaskManager::doLater([] { ImGui::OpenPopup("No Plugins"); });
|
||||
} else if (argument == "no-builtin-plugin") {
|
||||
ImHexApi::Tasks::doLater([] { ImGui::OpenPopup("No Builtin Plugin"); });
|
||||
TaskManager::doLater([] { ImGui::OpenPopup("No Builtin Plugin"); });
|
||||
} else if (argument == "multiple-builtin-plugins") {
|
||||
ImHexApi::Tasks::doLater([] { ImGui::OpenPopup("Multiple Builtin Plugins"); });
|
||||
TaskManager::doLater([] { ImGui::OpenPopup("Multiple Builtin Plugins"); });
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -179,7 +179,7 @@ namespace hex {
|
||||
} else {
|
||||
glfwPollEvents();
|
||||
|
||||
bool frameRateUnlocked = ImGui::IsPopupOpen(ImGuiID(0), ImGuiPopupFlags_AnyPopupId) || Task::getRunningTaskCount() > 0 || this->m_mouseButtonDown || this->m_hadEvent || !this->m_pressedKeys.empty();
|
||||
bool frameRateUnlocked = ImGui::IsPopupOpen(ImGuiID(0), ImGuiPopupFlags_AnyPopupId) || TaskManager::getRunningTaskCount() > 0 || this->m_mouseButtonDown || this->m_hadEvent || !this->m_pressedKeys.empty();
|
||||
const double timeout = std::max(0.0, (1.0 / 5.0) - (glfwGetTime() - this->m_lastFrameTime));
|
||||
|
||||
if ((this->m_lastFrameTime - this->m_frameRateUnlockTime) > 5 && this->m_frameRateTemporarilyUnlocked && !frameRateUnlocked) {
|
||||
@@ -202,8 +202,11 @@ namespace hex {
|
||||
this->frameEnd();
|
||||
|
||||
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)));
|
||||
if (targetFps <= 200) {
|
||||
auto leftoverFrameTime = i64((this->m_lastFrameTime + 1 / targetFps - glfwGetTime()) * 1000);
|
||||
if (leftoverFrameTime > 0)
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(leftoverFrameTime));
|
||||
}
|
||||
|
||||
this->m_lastFrameTime = glfwGetTime();
|
||||
|
||||
@@ -421,7 +424,6 @@ namespace hex {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
this->m_popupsToOpen.remove_if([](const auto &name) {
|
||||
if (ImGui::IsPopupOpen(name.c_str()))
|
||||
return true;
|
||||
@@ -431,17 +433,12 @@ namespace hex {
|
||||
return false;
|
||||
});
|
||||
|
||||
TaskManager::runDeferredCalls();
|
||||
|
||||
EventManager::post<EventFrameBegin>();
|
||||
}
|
||||
|
||||
void Window::frame() {
|
||||
{
|
||||
auto &calls = ImHexApi::Tasks::getDeferredCalls();
|
||||
for (const auto &callback : calls)
|
||||
callback();
|
||||
calls.clear();
|
||||
}
|
||||
|
||||
auto &io = ImGui::GetIO();
|
||||
for (auto &[name, view] : ContentRegistry::Views::getEntries()) {
|
||||
ImGui::GetCurrentContext()->NextWindowData.ClearFlags();
|
||||
@@ -452,7 +449,8 @@ namespace hex {
|
||||
continue;
|
||||
|
||||
if (view->isAvailable()) {
|
||||
ImGui::SetNextWindowSizeConstraints(scaled(view->getMinSize()), scaled(view->getMaxSize()));
|
||||
float fontScaling = std::max(1.0F, ImHexApi::System::getFontSize() / ImHexApi::System::DefaultFontSize);
|
||||
ImGui::SetNextWindowSizeConstraints(view->getMinSize() * fontScaling, view->getMaxSize() * fontScaling);
|
||||
view->drawContent();
|
||||
}
|
||||
|
||||
@@ -485,6 +483,8 @@ namespace hex {
|
||||
void Window::frameEnd() {
|
||||
EventManager::post<EventFrameEnd>();
|
||||
|
||||
TaskManager::collectGarbage();
|
||||
|
||||
this->endNativeWindowFrame();
|
||||
ImGui::Render();
|
||||
|
||||
|
||||
@@ -17,6 +17,8 @@ namespace hex::plugin::builtin::prv {
|
||||
[[nodiscard]] bool isResizable() const override { return false; }
|
||||
[[nodiscard]] bool isSavable() const override { return false; }
|
||||
|
||||
void setBaseAddress(u64 address) override;
|
||||
|
||||
void readRaw(u64 offset, void *buffer, size_t size) override;
|
||||
void writeRaw(u64 offset, const void *buffer, size_t size) override;
|
||||
[[nodiscard]] size_t getActualSize() const override;
|
||||
|
||||
@@ -28,7 +28,7 @@ namespace hex::plugin::builtin {
|
||||
void drawContent() override;
|
||||
|
||||
private:
|
||||
bool m_disassembling = false;
|
||||
TaskHolder m_disassemblerTask;
|
||||
|
||||
u64 m_baseAddress = 0;
|
||||
ui::SelectedRegion m_range = ui::SelectedRegion::EntireData;
|
||||
|
||||
@@ -74,7 +74,7 @@ namespace hex::plugin::builtin {
|
||||
std::map<prv::Provider*, std::vector<Occurrence>> m_foundOccurrences, m_sortedOccurrences;
|
||||
std::map<prv::Provider*, OccurrenceTree> m_occurrenceTree;
|
||||
|
||||
std::atomic<bool> m_searchRunning;
|
||||
TaskHolder m_searchTask;
|
||||
bool m_settingsValid = false;
|
||||
|
||||
std::string m_currFilter;
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
#pragma once
|
||||
|
||||
#include <hex/ui/view.hpp>
|
||||
#include <hex/api/task.hpp>
|
||||
|
||||
#include <array>
|
||||
#include <atomic>
|
||||
@@ -27,7 +28,7 @@ namespace hex::plugin::builtin {
|
||||
double m_entropyHandlePosition;
|
||||
|
||||
std::array<ImU64, 256> m_valueCounts = { 0 };
|
||||
bool m_analyzing = false;
|
||||
TaskHolder m_analyzerTask;
|
||||
|
||||
Region m_analyzedRegion = { 0, 0 };
|
||||
|
||||
|
||||
@@ -5,6 +5,8 @@
|
||||
#include <imgui.h>
|
||||
#include <hex/ui/view.hpp>
|
||||
|
||||
#include <hex/api/task.hpp>
|
||||
|
||||
namespace hex::plugin::builtin {
|
||||
|
||||
class ViewYara : public View {
|
||||
@@ -29,7 +31,7 @@ namespace hex::plugin::builtin {
|
||||
std::vector<std::pair<std::fs::path, std::fs::path>> m_rules;
|
||||
std::vector<YaraMatch> m_matches;
|
||||
u32 m_selectedRule = 0;
|
||||
bool m_matching = false;
|
||||
TaskHolder m_matcherTask;
|
||||
|
||||
std::vector<std::string> m_consoleMessages;
|
||||
|
||||
|
||||
@@ -86,7 +86,7 @@ namespace hex::plugin::builtin {
|
||||
auto format = (style == Style::Decimal) ? "{0:d}" : ((style == Style::Hexadecimal) ? hex::format("0x{{0:0{}X}}", Size * 2) : hex::format("0o{{0:0{}o}}", Size * 3));
|
||||
|
||||
T value = 0x00;
|
||||
std::memcpy(&value, buffer.data(), Size);
|
||||
std::memcpy(&value, buffer.data(), std::min(sizeof(T), Size));
|
||||
return hex::format(format, hex::changeEndianess(value, Size, endian));
|
||||
}
|
||||
|
||||
@@ -98,7 +98,7 @@ namespace hex::plugin::builtin {
|
||||
auto format = (style == Style::Decimal) ? "{0}{1:d}" : ((style == Style::Hexadecimal) ? hex::format("{{0}}0x{{1:0{}X}}", Size * 2) : hex::format("{{0}}0o{{1:0{}o}}", Size * 3));
|
||||
|
||||
T value = 0x00;
|
||||
std::memcpy(&value, buffer.data(), Size);
|
||||
std::memcpy(&value, buffer.data(), std::min(sizeof(T), Size));
|
||||
auto number = hex::signExtend(Size * 8, hex::changeEndianess(value, Size, endian));
|
||||
bool negative = number < 0;
|
||||
|
||||
|
||||
@@ -30,14 +30,14 @@ namespace hex::plugin::builtin {
|
||||
EventManager::subscribe<EventWindowClosing>([](GLFWwindow *window) {
|
||||
if (ImHexApi::Provider::isDirty()) {
|
||||
glfwSetWindowShouldClose(window, GLFW_FALSE);
|
||||
ImHexApi::Tasks::doLater([] { ImGui::OpenPopup("hex.builtin.popup.exit_application.title"_lang); });
|
||||
TaskManager::doLater([] { ImGui::OpenPopup("hex.builtin.popup.exit_application.title"_lang); });
|
||||
}
|
||||
});
|
||||
|
||||
EventManager::subscribe<EventProviderClosing>([](hex::prv::Provider *provider, bool *shouldClose) {
|
||||
if (provider->isDirty()) {
|
||||
*shouldClose = false;
|
||||
ImHexApi::Tasks::doLater([] { ImGui::OpenPopup("hex.builtin.popup.close_provider.title"_lang); });
|
||||
TaskManager::doLater([] { ImGui::OpenPopup("hex.builtin.popup.close_provider.title"_lang); });
|
||||
}
|
||||
});
|
||||
|
||||
@@ -87,12 +87,12 @@ namespace hex::plugin::builtin {
|
||||
|
||||
if (provider->hasFilePicker()) {
|
||||
if (!provider->handleFilePicker()) {
|
||||
ImHexApi::Tasks::doLater([provider] { ImHexApi::Provider::remove(provider); });
|
||||
TaskManager::doLater([provider] { ImHexApi::Provider::remove(provider); });
|
||||
return;
|
||||
}
|
||||
if (!provider->open()) {
|
||||
View::showErrorPopup("hex.builtin.popup.error.open"_lang);
|
||||
ImHexApi::Tasks::doLater([provider] { ImHexApi::Provider::remove(provider); });
|
||||
TaskManager::doLater([provider] { ImHexApi::Provider::remove(provider); });
|
||||
return;
|
||||
}
|
||||
}
|
||||
@@ -101,7 +101,7 @@ namespace hex::plugin::builtin {
|
||||
else {
|
||||
if (!provider->open() || !provider->isAvailable()) {
|
||||
View::showErrorPopup("hex.builtin.popup.error.open"_lang);
|
||||
ImHexApi::Tasks::doLater([provider] { ImHexApi::Provider::remove(provider); });
|
||||
TaskManager::doLater([provider] { ImHexApi::Provider::remove(provider); });
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
@@ -9,8 +9,6 @@
|
||||
#include <hex/helpers/crypto.hpp>
|
||||
#include <hex/helpers/patches.hpp>
|
||||
|
||||
#include <thread>
|
||||
|
||||
namespace hex::plugin::builtin {
|
||||
|
||||
static bool g_demoWindowOpen = false;
|
||||
@@ -20,7 +18,7 @@ namespace hex::plugin::builtin {
|
||||
ContentRegistry::Interface::registerMainMenuItem("hex.builtin.menu.file", 1000);
|
||||
|
||||
ContentRegistry::Interface::addMenuItem("hex.builtin.menu.file", 1050, [&] {
|
||||
bool taskRunning = Task::getRunningTaskCount() > 0;
|
||||
bool taskRunning = TaskManager::getRunningTaskCount() > 0;
|
||||
|
||||
if (ImGui::MenuItem("hex.builtin.menu.file.open_file"_lang, "CTRL + O", false, !taskRunning)) {
|
||||
|
||||
@@ -44,7 +42,7 @@ namespace hex::plugin::builtin {
|
||||
/* File open, quit imhex */
|
||||
ContentRegistry::Interface::addMenuItem("hex.builtin.menu.file", 1150, [&] {
|
||||
bool providerValid = ImHexApi::Provider::isValid();
|
||||
bool taskRunning = Task::getRunningTaskCount() > 0;
|
||||
bool taskRunning = TaskManager::getRunningTaskCount() > 0;
|
||||
|
||||
if (ImGui::MenuItem("hex.builtin.menu.file.close"_lang, "CTRL + W", false, providerValid && !taskRunning)) {
|
||||
ImHexApi::Provider::remove(ImHexApi::Provider::get());
|
||||
@@ -59,7 +57,7 @@ namespace hex::plugin::builtin {
|
||||
ContentRegistry::Interface::addMenuItem("hex.builtin.menu.file", 1250, [&] {
|
||||
auto provider = ImHexApi::Provider::get();
|
||||
bool providerValid = ImHexApi::Provider::isValid();
|
||||
bool taskRunning = Task::getRunningTaskCount() > 0;
|
||||
bool taskRunning = TaskManager::getRunningTaskCount() > 0;
|
||||
|
||||
if (ImGui::MenuItem("hex.builtin.menu.file.open_project"_lang, "", false, !taskRunning)) {
|
||||
fs::openFileBrowser(fs::DialogMode::Open, { {"Project File", "hexproj"}
|
||||
@@ -85,7 +83,7 @@ namespace hex::plugin::builtin {
|
||||
ContentRegistry::Interface::addMenuItem("hex.builtin.menu.file", 1300, [&] {
|
||||
auto provider = ImHexApi::Provider::get();
|
||||
bool providerValid = ImHexApi::Provider::isValid();
|
||||
bool taskRunning = Task::getRunningTaskCount() > 0;
|
||||
bool taskRunning = TaskManager::getRunningTaskCount() > 0;
|
||||
|
||||
/* Import */
|
||||
if (ImGui::BeginMenu("hex.builtin.menu.file.import"_lang, !taskRunning)) {
|
||||
@@ -126,9 +124,7 @@ namespace hex::plugin::builtin {
|
||||
if (ImGui::MenuItem("hex.builtin.menu.file.import.ips"_lang, nullptr, false)) {
|
||||
|
||||
fs::openFileBrowser(fs::DialogMode::Open, {}, [](const auto &path) {
|
||||
std::thread([path] {
|
||||
auto task = ImHexApi::Tasks::createTask("hex.builtin.common.processing", 0);
|
||||
|
||||
TaskManager::createTask("hex.builtin.common.processing", TaskManager::NoProgress, [path](auto &task) {
|
||||
auto patchData = fs::File(path, fs::File::Mode::Read).readBytes();
|
||||
auto patch = hex::loadIPSPatch(patchData);
|
||||
|
||||
@@ -144,15 +140,13 @@ namespace hex::plugin::builtin {
|
||||
}
|
||||
|
||||
provider->createUndoPoint();
|
||||
}).detach();
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
if (ImGui::MenuItem("hex.builtin.menu.file.import.ips32"_lang, nullptr, false)) {
|
||||
fs::openFileBrowser(fs::DialogMode::Open, {}, [](const auto &path) {
|
||||
std::thread([path] {
|
||||
auto task = ImHexApi::Tasks::createTask("hex.builtin.common.processing", 0);
|
||||
|
||||
TaskManager::createTask("hex.builtin.common.processing", TaskManager::NoProgress, [path](auto &task) {
|
||||
auto patchData = fs::File(path, fs::File::Mode::Read).readBytes();
|
||||
auto patch = hex::loadIPS32Patch(patchData);
|
||||
|
||||
@@ -168,7 +162,7 @@ namespace hex::plugin::builtin {
|
||||
}
|
||||
|
||||
provider->createUndoPoint();
|
||||
}).detach();
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
@@ -186,12 +180,10 @@ namespace hex::plugin::builtin {
|
||||
patches[0x00454F45] = value;
|
||||
}
|
||||
|
||||
std::thread([patches] {
|
||||
auto task = ImHexApi::Tasks::createTask("hex.builtin.common.processing", 0);
|
||||
|
||||
TaskManager::createTask("hex.builtin.common.processing", TaskManager::NoProgress, [patches](auto &) {
|
||||
auto data = generateIPSPatch(patches);
|
||||
|
||||
ImHexApi::Tasks::doLater([data] {
|
||||
TaskManager::doLater([data] {
|
||||
fs::openFileBrowser(fs::DialogMode::Save, {}, [&data](const auto &path) {
|
||||
auto file = fs::File(path, fs::File::Mode::Create);
|
||||
if (!file.isValid()) {
|
||||
@@ -202,7 +194,7 @@ namespace hex::plugin::builtin {
|
||||
file.write(data);
|
||||
});
|
||||
});
|
||||
}).detach();
|
||||
});
|
||||
}
|
||||
|
||||
if (ImGui::MenuItem("hex.builtin.menu.file.export.ips32"_lang, nullptr, false)) {
|
||||
@@ -213,23 +205,21 @@ namespace hex::plugin::builtin {
|
||||
patches[0x45454F45] = value;
|
||||
}
|
||||
|
||||
std::thread([patches] {
|
||||
auto task = ImHexApi::Tasks::createTask("hex.builtin.common.processing", 0);
|
||||
|
||||
TaskManager::createTask("hex.builtin.common.processing", TaskManager::NoProgress, [patches](auto &) {
|
||||
auto data = generateIPS32Patch(patches);
|
||||
|
||||
ImHexApi::Tasks::doLater([data] {
|
||||
TaskManager::doLater([data] {
|
||||
fs::openFileBrowser(fs::DialogMode::Save, {}, [&data](const auto &path) {
|
||||
auto file = fs::File(path, fs::File::Mode::Create);
|
||||
if (!file.isValid()) {
|
||||
View::showErrorPopup("hex.builtin.menu.file.export.popup.create"_lang);
|
||||
View::showErrorPopup("hex.builtin.menu.file.export.base64.popup.export_error"_lang);
|
||||
return;
|
||||
}
|
||||
|
||||
file.write(data);
|
||||
});
|
||||
});
|
||||
}).detach();
|
||||
});
|
||||
}
|
||||
|
||||
ImGui::EndMenu();
|
||||
|
||||
@@ -32,7 +32,7 @@ namespace hex::plugin::builtin {
|
||||
for (const auto &id : providerIds) {
|
||||
auto providerSettings = nlohmann::json::parse(tar.readString(basePath / hex::format("{}.json", id)));
|
||||
|
||||
auto provider = ImHexApi::Provider::createProvider(providerSettings["type"].get<std::string>());
|
||||
auto provider = ImHexApi::Provider::createProvider(providerSettings["type"].get<std::string>(), true);
|
||||
if (provider == nullptr) {
|
||||
success = false;
|
||||
continue;
|
||||
|
||||
@@ -358,8 +358,10 @@ namespace hex::plugin::builtin::prv {
|
||||
}
|
||||
|
||||
std::pair<Region, bool> DiskProvider::getRegionValidity(u64 address) const {
|
||||
address -= this->getBaseAddress();
|
||||
|
||||
if (address < this->getActualSize())
|
||||
return { Region { address, this->getActualSize() - address }, true };
|
||||
return { Region { this->getBaseAddress() + address, this->getActualSize() - address }, true };
|
||||
else
|
||||
return { Region::Invalid(), false };
|
||||
}
|
||||
|
||||
@@ -336,8 +336,10 @@ namespace hex::plugin::builtin::prv {
|
||||
}
|
||||
|
||||
std::pair<Region, bool> FileProvider::getRegionValidity(u64 address) const {
|
||||
address -= this->getBaseAddress();
|
||||
|
||||
if (address < this->getActualSize())
|
||||
return { Region { address, this->getActualSize() - address }, true };
|
||||
return { Region { this->getBaseAddress() + address, this->getActualSize() - address }, true };
|
||||
else
|
||||
return { Region::Invalid(), false };
|
||||
}
|
||||
|
||||
@@ -325,8 +325,10 @@ namespace hex::plugin::builtin::prv {
|
||||
}
|
||||
|
||||
std::pair<Region, bool> GDBProvider::getRegionValidity(u64 address) const {
|
||||
address -= this->getBaseAddress();
|
||||
|
||||
if (address < this->getActualSize())
|
||||
return { Region { address, this->getActualSize() - address }, true };
|
||||
return { Region { this->getBaseAddress() + address, this->getActualSize() - address }, true };
|
||||
else
|
||||
return { Region::Invalid(), false };
|
||||
}
|
||||
|
||||
@@ -153,6 +153,21 @@ namespace hex::plugin::builtin::prv {
|
||||
|
||||
}
|
||||
|
||||
void IntelHexProvider::setBaseAddress(u64 address) {
|
||||
auto oldBase = this->getBaseAddress();
|
||||
|
||||
auto intervals = this->m_data.findOverlapping(oldBase, oldBase + this->getActualSize());
|
||||
|
||||
for (auto &interval : intervals) {
|
||||
interval.start = (interval.start - oldBase) + address;
|
||||
interval.stop = (interval.stop - oldBase) + address;
|
||||
}
|
||||
|
||||
this->m_data = std::move(intervals);
|
||||
|
||||
Provider::setBaseAddress(address);
|
||||
}
|
||||
|
||||
void IntelHexProvider::readRaw(u64 offset, void *buffer, size_t size) {
|
||||
auto intervals = this->m_data.findOverlapping(offset, (offset + size) - 1);
|
||||
|
||||
|
||||
@@ -484,7 +484,7 @@ namespace hex::plugin::builtin {
|
||||
}
|
||||
|
||||
// If a custom font has been loaded now, also load the font size
|
||||
float fontSize = 13.0F * ImHexApi::System::getGlobalScale();
|
||||
float fontSize = ImHexApi::System::DefaultFontSize * ImHexApi::System::getGlobalScale();
|
||||
if (!fontFile.empty()) {
|
||||
ImHexApi::System::impl::setCustomFontPath(fontFile);
|
||||
|
||||
|
||||
@@ -745,15 +745,15 @@ namespace hex::plugin::builtin {
|
||||
|
||||
|
||||
void drawFileToolShredder() {
|
||||
static bool shredding = false;
|
||||
static std::u8string selectedFile;
|
||||
static bool fastMode = false;
|
||||
static TaskHolder shredderTask;
|
||||
|
||||
ImGui::TextUnformatted("hex.builtin.tools.file_tools.shredder.warning"_lang);
|
||||
ImGui::NewLine();
|
||||
|
||||
if (ImGui::BeginChild("settings", { 0, ImGui::GetTextLineHeightWithSpacing() * 4 }, true, ImGuiWindowFlags_NoScrollbar | ImGuiWindowFlags_NoScrollWithMouse)) {
|
||||
ImGui::BeginDisabled(shredding);
|
||||
ImGui::BeginDisabled(shredderTask.isRunning());
|
||||
{
|
||||
ImGui::TextUnformatted("hex.builtin.tools.file_tools.shredder.input"_lang);
|
||||
ImGui::SameLine();
|
||||
@@ -771,17 +771,14 @@ namespace hex::plugin::builtin {
|
||||
}
|
||||
ImGui::EndChild();
|
||||
|
||||
if (shredding)
|
||||
if (shredderTask.isRunning())
|
||||
ImGui::TextSpinner("hex.builtin.tools.file_tools.shredder.shredding"_lang);
|
||||
else {
|
||||
ImGui::BeginDisabled(selectedFile.empty());
|
||||
{
|
||||
if (ImGui::Button("hex.builtin.tools.file_tools.shredder.shred"_lang)) {
|
||||
shredding = true;
|
||||
|
||||
std::thread([] {
|
||||
shredderTask = TaskManager::createTask("hex.builtin.tools.file_tools.shredder.shredding", 0, [](auto &task) {
|
||||
ON_SCOPE_EXIT {
|
||||
shredding = false;
|
||||
selectedFile.clear();
|
||||
};
|
||||
fs::File file(selectedFile, fs::File::Mode::Write);
|
||||
@@ -791,6 +788,8 @@ namespace hex::plugin::builtin {
|
||||
return;
|
||||
}
|
||||
|
||||
task.setMaxValue(file.getSize());
|
||||
|
||||
std::vector<std::array<u8, 3>> overwritePattern;
|
||||
if (fastMode) {
|
||||
/* Should be sufficient for modern disks */
|
||||
@@ -803,40 +802,40 @@ namespace hex::plugin::builtin {
|
||||
|
||||
/* Fill fixed patterns */
|
||||
overwritePattern = {
|
||||
{ },
|
||||
{ },
|
||||
{},
|
||||
{},
|
||||
{ 0x55, 0x55, 0x55 },
|
||||
{ 0xAA, 0xAA, 0xAA },
|
||||
{ 0x92, 0x49, 0x24 },
|
||||
{ 0x49, 0x24, 0x92 },
|
||||
{ 0x24, 0x92, 0x49 },
|
||||
{ 0x00, 0x00, 0x00 },
|
||||
{ 0x11, 0x11, 0x11 },
|
||||
{ 0x22, 0x22, 0x22 },
|
||||
{ 0x33, 0x33, 0x44 },
|
||||
{ 0x55, 0x55, 0x55 },
|
||||
{ 0x66, 0x66, 0x66 },
|
||||
{ 0x77, 0x77, 0x77 },
|
||||
{ 0x88, 0x88, 0x88 },
|
||||
{ 0x99, 0x99, 0x99 },
|
||||
{ 0xAA, 0xAA, 0xAA },
|
||||
{ 0xBB, 0xBB, 0xBB },
|
||||
{ 0xCC, 0xCC, 0xCC },
|
||||
{ 0xDD, 0xDD, 0xDD },
|
||||
{ 0xEE, 0xEE, 0xEE },
|
||||
{ 0xFF, 0xFF, 0xFF },
|
||||
{ 0x92, 0x49, 0x24 },
|
||||
{ 0x49, 0x24, 0x92 },
|
||||
{ 0x24, 0x92, 0x49 },
|
||||
{ 0x6D, 0xB6, 0xDB },
|
||||
{ 0xB6, 0xDB, 0x6D },
|
||||
{ 0xBD, 0x6D, 0xB6 },
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{}
|
||||
{ },
|
||||
{ },
|
||||
{},
|
||||
{},
|
||||
{ 0x55, 0x55, 0x55 },
|
||||
{ 0xAA, 0xAA, 0xAA },
|
||||
{ 0x92, 0x49, 0x24 },
|
||||
{ 0x49, 0x24, 0x92 },
|
||||
{ 0x24, 0x92, 0x49 },
|
||||
{ 0x00, 0x00, 0x00 },
|
||||
{ 0x11, 0x11, 0x11 },
|
||||
{ 0x22, 0x22, 0x22 },
|
||||
{ 0x33, 0x33, 0x44 },
|
||||
{ 0x55, 0x55, 0x55 },
|
||||
{ 0x66, 0x66, 0x66 },
|
||||
{ 0x77, 0x77, 0x77 },
|
||||
{ 0x88, 0x88, 0x88 },
|
||||
{ 0x99, 0x99, 0x99 },
|
||||
{ 0xAA, 0xAA, 0xAA },
|
||||
{ 0xBB, 0xBB, 0xBB },
|
||||
{ 0xCC, 0xCC, 0xCC },
|
||||
{ 0xDD, 0xDD, 0xDD },
|
||||
{ 0xEE, 0xEE, 0xEE },
|
||||
{ 0xFF, 0xFF, 0xFF },
|
||||
{ 0x92, 0x49, 0x24 },
|
||||
{ 0x49, 0x24, 0x92 },
|
||||
{ 0x24, 0x92, 0x49 },
|
||||
{ 0x6D, 0xB6, 0xDB },
|
||||
{ 0xB6, 0xDB, 0x6D },
|
||||
{ 0xBD, 0x6D, 0xB6 },
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{}
|
||||
};
|
||||
|
||||
/* Fill random patterns */
|
||||
@@ -848,7 +847,6 @@ namespace hex::plugin::builtin {
|
||||
|
||||
size_t fileSize = file.getSize();
|
||||
|
||||
auto task = ImHexApi::Tasks::createTask("hex.builtin.tools.file_tools.shredder.shredding", fileSize);
|
||||
for (const auto &pattern : overwritePattern) {
|
||||
for (u64 offset = 0; offset < fileSize; offset += 3) {
|
||||
file.write(pattern.data(), std::min<u64>(pattern.size(), fileSize - offset));
|
||||
@@ -861,7 +859,7 @@ namespace hex::plugin::builtin {
|
||||
file.remove();
|
||||
|
||||
View::showInfoPopup("hex.builtin.tools.file_tools.shredder.success"_lang);
|
||||
}).detach();
|
||||
});
|
||||
}
|
||||
}
|
||||
ImGui::EndDisabled();
|
||||
@@ -890,14 +888,14 @@ namespace hex::plugin::builtin {
|
||||
1
|
||||
};
|
||||
|
||||
static bool splitting = false;
|
||||
static std::u8string selectedFile;
|
||||
static std::u8string baseOutputPath;
|
||||
static u64 splitSize = sizes[0];
|
||||
static int selectedItem = 0;
|
||||
static TaskHolder splitterTask;
|
||||
|
||||
if (ImGui::BeginChild("split_settings", { 0, ImGui::GetTextLineHeightWithSpacing() * 7 }, true, ImGuiWindowFlags_NoScrollbar | ImGuiWindowFlags_NoScrollWithMouse)) {
|
||||
ImGui::BeginDisabled(splitting);
|
||||
ImGui::BeginDisabled(splitterTask.isRunning());
|
||||
{
|
||||
ImGui::InputText("##path", selectedFile);
|
||||
ImGui::SameLine();
|
||||
@@ -926,7 +924,7 @@ namespace hex::plugin::builtin {
|
||||
}
|
||||
}
|
||||
ImGui::EndDisabled();
|
||||
ImGui::BeginDisabled(splitting || selectedItem != sizes.size() - 1);
|
||||
ImGui::BeginDisabled(splitterTask.isRunning() || selectedItem != sizes.size() - 1);
|
||||
{
|
||||
ImGui::InputScalar("###custom_size", ImGuiDataType_U64, &splitSize);
|
||||
ImGui::SameLine();
|
||||
@@ -938,15 +936,13 @@ namespace hex::plugin::builtin {
|
||||
|
||||
ImGui::BeginDisabled(selectedFile.empty() || baseOutputPath.empty() || splitSize == 0);
|
||||
{
|
||||
if (splitting)
|
||||
if (splitterTask.isRunning())
|
||||
ImGui::TextSpinner("hex.builtin.tools.file_tools.splitter.splitting"_lang);
|
||||
else {
|
||||
if (ImGui::Button("hex.builtin.tools.file_tools.splitter.split"_lang)) {
|
||||
splitting = true;
|
||||
|
||||
std::thread([] {
|
||||
splitterTask = TaskManager::createTask("hex.builtin.tools.file_tools.splitter.splitting", 0, [](auto &task) {
|
||||
ON_SCOPE_EXIT {
|
||||
splitting = false;
|
||||
selectedFile.clear();
|
||||
baseOutputPath.clear();
|
||||
};
|
||||
@@ -962,7 +958,8 @@ namespace hex::plugin::builtin {
|
||||
return;
|
||||
}
|
||||
|
||||
auto task = ImHexApi::Tasks::createTask("hex.builtin.tools.file_tools.splitter.splitting", file.getSize());
|
||||
task.setMaxValue(file.getSize());
|
||||
|
||||
u32 index = 1;
|
||||
for (u64 offset = 0; offset < file.getSize(); offset += splitSize) {
|
||||
task.update(offset);
|
||||
@@ -987,7 +984,7 @@ namespace hex::plugin::builtin {
|
||||
}
|
||||
|
||||
View::showInfoPopup("hex.builtin.tools.file_tools.splitter.success"_lang);
|
||||
}).detach();
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -995,10 +992,10 @@ namespace hex::plugin::builtin {
|
||||
}
|
||||
|
||||
void drawFileToolCombiner() {
|
||||
static bool combining = false;
|
||||
static std::vector<std::fs::path> files;
|
||||
static std::u8string outputPath;
|
||||
static u32 selectedIndex;
|
||||
static TaskHolder combinerTask;
|
||||
|
||||
if (ImGui::BeginTable("files_table", 2, ImGuiTableFlags_SizingStretchProp)) {
|
||||
ImGui::TableSetupColumn("file list", ImGuiTableColumnFlags_NoHeaderLabel, 10);
|
||||
@@ -1041,7 +1038,7 @@ namespace hex::plugin::builtin {
|
||||
ImGui::TableNextRow();
|
||||
ImGui::TableNextColumn();
|
||||
|
||||
ImGui::BeginDisabled(combining);
|
||||
ImGui::BeginDisabled(combinerTask.isRunning());
|
||||
{
|
||||
if (ImGui::Button("hex.builtin.tools.file_tools.combiner.add"_lang)) {
|
||||
fs::openFileBrowser(fs::DialogMode::Open, {}, [](const auto &path) {
|
||||
@@ -1063,7 +1060,7 @@ namespace hex::plugin::builtin {
|
||||
ImGui::EndTable();
|
||||
}
|
||||
|
||||
ImGui::BeginDisabled(combining);
|
||||
ImGui::BeginDisabled(combinerTask.isRunning());
|
||||
{
|
||||
ImGui::InputText("##output_path", outputPath);
|
||||
ImGui::SameLine();
|
||||
@@ -1079,14 +1076,12 @@ namespace hex::plugin::builtin {
|
||||
|
||||
ImGui::BeginDisabled(files.empty() || outputPath.empty());
|
||||
{
|
||||
if (combining)
|
||||
if (combinerTask.isRunning())
|
||||
ImGui::TextSpinner("hex.builtin.tools.file_tools.combiner.combining"_lang);
|
||||
else {
|
||||
if (ImGui::Button("hex.builtin.tools.file_tools.combiner.combine"_lang)) {
|
||||
combining = true;
|
||||
|
||||
std::thread([] {
|
||||
ON_SCOPE_EXIT { combining = false; };
|
||||
combinerTask = TaskManager::createTask("hex.builtin.tools.file_tools.combiner.combining", 0, [](auto &task) {
|
||||
|
||||
fs::File output(outputPath, fs::File::Mode::Create);
|
||||
|
||||
@@ -1095,7 +1090,7 @@ namespace hex::plugin::builtin {
|
||||
return;
|
||||
}
|
||||
|
||||
auto task = ImHexApi::Tasks::createTask("hex.builtin.tools.file_tools.combiner.combining", files.size());
|
||||
task.setMaxValue(files.size());
|
||||
|
||||
u64 fileIndex = 0;
|
||||
for (const auto &file : files) {
|
||||
@@ -1121,7 +1116,7 @@ namespace hex::plugin::builtin {
|
||||
outputPath.clear();
|
||||
|
||||
View::showInfoPopup("hex.builtin.tools.file_tools.combiner.success"_lang);
|
||||
}).detach();
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -161,19 +161,19 @@ namespace hex::plugin::builtin {
|
||||
EventManager::subscribe<RequestShowInfoPopup>([](const std::string &message) {
|
||||
s_popupMessage = message;
|
||||
|
||||
ImHexApi::Tasks::doLater([] { ImGui::OpenPopup("hex.builtin.common.info"_lang); });
|
||||
TaskManager::doLater([] { ImGui::OpenPopup("hex.builtin.common.info"_lang); });
|
||||
});
|
||||
|
||||
EventManager::subscribe<RequestShowErrorPopup>([](const std::string &message) {
|
||||
s_popupMessage = message;
|
||||
|
||||
ImHexApi::Tasks::doLater([] { ImGui::OpenPopup("hex.builtin.common.error"_lang); });
|
||||
TaskManager::doLater([] { ImGui::OpenPopup("hex.builtin.common.error"_lang); });
|
||||
});
|
||||
|
||||
EventManager::subscribe<RequestShowFatalErrorPopup>([](const std::string &message) {
|
||||
s_popupMessage = message;
|
||||
|
||||
ImHexApi::Tasks::doLater([] { ImGui::OpenPopup("hex.builtin.common.fatal"_lang); });
|
||||
TaskManager::doLater([] { ImGui::OpenPopup("hex.builtin.common.fatal"_lang); });
|
||||
});
|
||||
|
||||
EventManager::subscribe<RequestShowYesNoQuestionPopup>([](const std::string &message, const std::function<void()> &yesCallback, const std::function<void()> &noCallback) {
|
||||
@@ -182,7 +182,7 @@ namespace hex::plugin::builtin {
|
||||
s_yesCallback = yesCallback;
|
||||
s_noCallback = noCallback;
|
||||
|
||||
ImHexApi::Tasks::doLater([] { ImGui::OpenPopup("hex.builtin.common.question"_lang); });
|
||||
TaskManager::doLater([] { ImGui::OpenPopup("hex.builtin.common.question"_lang); });
|
||||
});
|
||||
|
||||
EventManager::subscribe<RequestShowFileChooserPopup>([](const std::vector<std::fs::path> &paths, const std::vector<nfdfilteritem_t> &validExtensions, const std::function<void(std::fs::path)> &callback) {
|
||||
@@ -191,7 +191,7 @@ namespace hex::plugin::builtin {
|
||||
s_selectableFilesValidExtensions = validExtensions;
|
||||
s_selectableFileOpenCallback = callback;
|
||||
|
||||
ImHexApi::Tasks::doLater([] { ImGui::OpenPopup("hex.builtin.common.choose_file"_lang); });
|
||||
TaskManager::doLater([] { ImGui::OpenPopup("hex.builtin.common.choose_file"_lang); });
|
||||
});
|
||||
}
|
||||
|
||||
@@ -213,28 +213,51 @@ namespace hex::plugin::builtin {
|
||||
});
|
||||
|
||||
ContentRegistry::Interface::addFooterItem([] {
|
||||
size_t taskCount = 0;
|
||||
double taskProgress = 0.0;
|
||||
std::string taskName;
|
||||
|
||||
{
|
||||
std::scoped_lock lock(Task::getTaskMutex());
|
||||
|
||||
taskCount = Task::getRunningTasks().size();
|
||||
if (taskCount > 0) {
|
||||
auto frontTask = Task::getRunningTasks().front();
|
||||
taskProgress = frontTask->getProgress();
|
||||
taskName = frontTask->getName();
|
||||
}
|
||||
}
|
||||
|
||||
auto taskCount = TaskManager::getRunningTaskCount();
|
||||
if (taskCount > 0) {
|
||||
auto &tasks = TaskManager::getRunningTasks();
|
||||
auto frontTask = tasks.front();
|
||||
|
||||
auto widgetStart = ImGui::GetCursorPos();
|
||||
|
||||
ImGui::TextSpinner(hex::format("({})", taskCount).c_str());
|
||||
ImGui::SameLine();
|
||||
ImGui::SmallProgressBar(frontTask->getMaxValue() == 0 ? 1 : (float(frontTask->getValue()) / frontTask->getMaxValue()), (ImGui::GetCurrentWindow()->MenuBarHeight() - 10_scaled) / 2.0);
|
||||
ImGui::SameLine();
|
||||
|
||||
auto widgetEnd = ImGui::GetCursorPos();
|
||||
ImGui::SetCursorPos(widgetStart);
|
||||
ImGui::InvisibleButton("FrontTask", ImVec2(widgetEnd.x - widgetStart.x, ImGui::GetCurrentWindow()->MenuBarHeight()));
|
||||
ImGui::SetCursorPos(widgetEnd);
|
||||
|
||||
ImGui::InfoTooltip(LangEntry(frontTask->getUnlocalizedName()).get().c_str());
|
||||
|
||||
if (ImGui::BeginPopupContextItem("FrontTask", ImGuiPopupFlags_MouseButtonLeft)) {
|
||||
for (const auto &task : tasks) {
|
||||
ImGui::PushID(&task);
|
||||
ImGui::TextFormatted("{}", LangEntry(task->getUnlocalizedName()));
|
||||
ImGui::SameLine();
|
||||
ImGui::SeparatorEx(ImGuiSeparatorFlags_Vertical);
|
||||
ImGui::SameLine();
|
||||
ImGui::SmallProgressBar(frontTask->getMaxValue() == 0 ? 1 : (float(frontTask->getValue()) / frontTask->getMaxValue()), (ImGui::GetTextLineHeightWithSpacing() - 5_scaled) / 2);
|
||||
ImGui::SameLine();
|
||||
|
||||
ImGui::PushStyleVar(ImGuiStyleVar_WindowPadding, ImVec2(0, 0));
|
||||
if (ImGui::ToolBarButton(ICON_VS_DEBUG_STOP, ImGui::GetStyleColorVec4(ImGuiCol_Text)))
|
||||
task->interrupt();
|
||||
ImGui::PopStyleVar();
|
||||
|
||||
ImGui::PopID();
|
||||
}
|
||||
ImGui::EndPopup();
|
||||
}
|
||||
|
||||
ImGui::SameLine();
|
||||
|
||||
ImGui::SmallProgressBar(taskProgress, (ImGui::GetCurrentWindow()->MenuBarHeight() - 10_scaled) / 2.0);
|
||||
ImGui::InfoTooltip(taskName.c_str());
|
||||
ImGui::PushStyleVar(ImGuiStyleVar_FramePadding, scaled(ImVec2(1, 2)));
|
||||
if (ImGui::ToolBarButton(ICON_VS_DEBUG_STOP, ImGui::GetStyleColorVec4(ImGuiCol_Text)))
|
||||
frontTask->interrupt();
|
||||
ImGui::PopStyleVar();
|
||||
}
|
||||
});
|
||||
}
|
||||
@@ -243,7 +266,7 @@ namespace hex::plugin::builtin {
|
||||
ContentRegistry::Interface::addToolbarItem([] {
|
||||
auto provider = ImHexApi::Provider::get();
|
||||
bool providerValid = provider != nullptr;
|
||||
bool tasksRunning = Task::getRunningTaskCount() > 0;
|
||||
bool tasksRunning = TaskManager::getRunningTaskCount() > 0;
|
||||
|
||||
// Undo
|
||||
ImGui::BeginDisabled(!providerValid || !provider->canUndo());
|
||||
@@ -332,7 +355,7 @@ namespace hex::plugin::builtin {
|
||||
|
||||
bool open = true;
|
||||
ImGui::PushID(tabProvider);
|
||||
if (ImGui::BeginTabItem(tabProvider->getName().c_str(), &open, provider->isDirty() ? ImGuiTabItemFlags_UnsavedDocument : ImGuiTabItemFlags_None)) {
|
||||
if (ImGui::BeginTabItem(tabProvider->getName().c_str(), &open, tabProvider->isDirty() ? ImGuiTabItemFlags_UnsavedDocument : ImGuiTabItemFlags_None)) {
|
||||
ImHexApi::Provider::setCurrentProvider(i);
|
||||
ImGui::EndTabItem();
|
||||
}
|
||||
|
||||
@@ -14,7 +14,7 @@ namespace hex::plugin::builtin {
|
||||
|
||||
ContentRegistry::Interface::addMenuItem("hex.builtin.menu.help", 1000, [&, this] {
|
||||
if (ImGui::MenuItem("hex.builtin.view.help.about.name"_lang, "")) {
|
||||
ImHexApi::Tasks::doLater([] { ImGui::OpenPopup(View::toWindowName("hex.builtin.view.help.about.name").c_str()); });
|
||||
TaskManager::doLater([] { ImGui::OpenPopup(View::toWindowName("hex.builtin.view.help.about.name").c_str()); });
|
||||
this->m_aboutWindowOpen = true;
|
||||
this->getWindowOpenState() = true;
|
||||
}
|
||||
|
||||
@@ -325,16 +325,15 @@ namespace hex::plugin::builtin {
|
||||
|
||||
ContentRegistry::Interface::addMenuItem("hex.builtin.menu.file", 4000, [&] {
|
||||
bool providerValid = ImHexApi::Provider::isValid();
|
||||
auto selection = ImHexApi::HexEditor::getSelection();
|
||||
|
||||
if (ImGui::MenuItem("hex.builtin.menu.file.bookmark.import"_lang, nullptr, false, selection.has_value() && providerValid)) {
|
||||
if (ImGui::MenuItem("hex.builtin.menu.file.bookmark.import"_lang, nullptr, false, providerValid)) {
|
||||
fs::openFileBrowser(fs::DialogMode::Open, { { "Bookmarks File", "hexbm"} }, [&](const std::fs::path &path) {
|
||||
try {
|
||||
importBookmarks(ImHexApi::Provider::get(), nlohmann::json::parse(fs::File(path, fs::File::Mode::Read).readString()));
|
||||
} catch (...) { }
|
||||
});
|
||||
}
|
||||
if (ImGui::MenuItem("hex.builtin.menu.file.bookmark.export"_lang, nullptr, false, selection.has_value() && providerValid)) {
|
||||
if (ImGui::MenuItem("hex.builtin.menu.file.bookmark.export"_lang, nullptr, false, providerValid && !ProviderExtraData::getCurrent().bookmarks.empty())) {
|
||||
fs::openFileBrowser(fs::DialogMode::Save, { { "Bookmarks File", "hexbm"} }, [&](const std::fs::path &path) {
|
||||
nlohmann::json json;
|
||||
exportBookmarks(ImHexApi::Provider::get(), json);
|
||||
|
||||
@@ -24,9 +24,8 @@ namespace hex::plugin::builtin {
|
||||
|
||||
void ViewDisassembler::disassemble() {
|
||||
this->m_disassembly.clear();
|
||||
this->m_disassembling = true;
|
||||
|
||||
std::thread([this] {
|
||||
this->m_disassemblerTask = TaskManager::createTask("hex.builtin.view.disassembler.disassembling", this->m_codeRegion.getSize(), [this](auto &task) {
|
||||
csh capstoneHandle;
|
||||
cs_insn *instructions = nullptr;
|
||||
|
||||
@@ -40,7 +39,6 @@ namespace hex::plugin::builtin {
|
||||
std::vector<u8> buffer(2048, 0x00);
|
||||
size_t size = this->m_codeRegion.getSize();
|
||||
|
||||
auto task = ImHexApi::Tasks::createTask("hex.builtin.view.disassembler.disassembling", size);
|
||||
for (u64 address = 0; address < size; address += 2048) {
|
||||
task.update(address);
|
||||
|
||||
@@ -80,9 +78,7 @@ namespace hex::plugin::builtin {
|
||||
|
||||
cs_close(&capstoneHandle);
|
||||
}
|
||||
|
||||
this->m_disassembling = false;
|
||||
}).detach();
|
||||
});
|
||||
}
|
||||
|
||||
void ViewDisassembler::drawContent() {
|
||||
@@ -321,14 +317,14 @@ namespace hex::plugin::builtin {
|
||||
}
|
||||
ImGui::EndChild();
|
||||
|
||||
ImGui::BeginDisabled(this->m_disassembling);
|
||||
ImGui::BeginDisabled(this->m_disassemblerTask.isRunning());
|
||||
{
|
||||
if (ImGui::Button("hex.builtin.view.disassembler.disassemble"_lang))
|
||||
this->disassemble();
|
||||
}
|
||||
ImGui::EndDisabled();
|
||||
|
||||
if (this->m_disassembling) {
|
||||
if (this->m_disassemblerTask.isRunning()) {
|
||||
ImGui::SameLine();
|
||||
ImGui::TextSpinner("hex.builtin.view.disassembler.disassembling"_lang);
|
||||
}
|
||||
@@ -345,7 +341,7 @@ namespace hex::plugin::builtin {
|
||||
ImGui::TableSetupColumn("hex.builtin.view.disassembler.disassembly.bytes"_lang);
|
||||
ImGui::TableSetupColumn("hex.builtin.view.disassembler.disassembly.title"_lang);
|
||||
|
||||
if (!this->m_disassembling) {
|
||||
if (!this->m_disassemblerTask.isRunning()) {
|
||||
ImGuiListClipper clipper;
|
||||
clipper.Begin(this->m_disassembly.size());
|
||||
|
||||
|
||||
@@ -6,7 +6,6 @@
|
||||
#include <array>
|
||||
#include <regex>
|
||||
#include <string>
|
||||
#include <thread>
|
||||
#include <utility>
|
||||
|
||||
#include <llvm/Demangle/Demangle.h>
|
||||
@@ -319,9 +318,7 @@ namespace hex::plugin::builtin {
|
||||
}
|
||||
}();
|
||||
|
||||
this->m_searchRunning = true;
|
||||
std::thread([this, settings = this->m_searchSettings, searchRegion]{
|
||||
auto task = ImHexApi::Tasks::createTask("hex.builtin.view.find.searching", searchRegion.getSize());
|
||||
this->m_searchTask = TaskManager::createTask("hex.builtin.view.find.searching", searchRegion.getSize(), [this, settings = this->m_searchSettings, searchRegion](auto &task) {
|
||||
auto provider = ImHexApi::Provider::get();
|
||||
|
||||
switch (settings.mode) {
|
||||
@@ -338,7 +335,7 @@ namespace hex::plugin::builtin {
|
||||
case BinaryPattern:
|
||||
this->m_foundOccurrences[provider] = searchBinaryPattern(task, provider, searchRegion, settings.binaryPattern);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
this->m_sortedOccurrences[provider] = this->m_foundOccurrences[provider];
|
||||
|
||||
@@ -346,9 +343,7 @@ namespace hex::plugin::builtin {
|
||||
for (const auto &occurrence : this->m_foundOccurrences[provider])
|
||||
intervals.push_back(OccurrenceTree::interval(occurrence.region.getStartAddress(), occurrence.region.getEndAddress(), occurrence));
|
||||
this->m_occurrenceTree[provider] = std::move(intervals);
|
||||
|
||||
this->m_searchRunning = false;
|
||||
}).detach();
|
||||
});
|
||||
}
|
||||
|
||||
std::string ViewFind::decodeValue(prv::Provider *provider, Occurrence occurrence) const {
|
||||
@@ -408,7 +403,7 @@ namespace hex::plugin::builtin {
|
||||
if (ImGui::Begin(View::toWindowName("hex.builtin.view.find.name").c_str(), &this->getWindowOpenState())) {
|
||||
auto provider = ImHexApi::Provider::get();
|
||||
|
||||
ImGui::BeginDisabled(this->m_searchRunning);
|
||||
ImGui::BeginDisabled(this->m_searchTask.isRunning());
|
||||
{
|
||||
ui::regionSelectionPicker(&this->m_searchSettings.range, true, true);
|
||||
|
||||
|
||||
@@ -189,13 +189,10 @@ namespace hex::plugin::builtin {
|
||||
ImGui::EndTabBar();
|
||||
}
|
||||
|
||||
if (!this->m_searchRunning && !searchSequence.empty() && this->m_shouldSearch) {
|
||||
this->m_searchRunning = true;
|
||||
std::thread([this, searchSequence, editor]{
|
||||
auto task = ImHexApi::Tasks::createTask("Searching", ImHexApi::Provider::get()->getSize());
|
||||
|
||||
if (!this->m_searchTask.isRunning() && !searchSequence.empty() && this->m_shouldSearch) {
|
||||
this->m_searchTask = TaskManager::createTask("hex.builtin.common.processing", ImHexApi::Provider::get()->getActualSize(), [this, editor, searchSequence](auto &) {
|
||||
if (auto region = this->findSequence(editor, searchSequence, this->m_backwards); region.has_value()) {
|
||||
ImHexApi::Tasks::doLater([editor, region]{
|
||||
TaskManager::doLater([editor, region]{
|
||||
editor->setSelection(region->getStartAddress(), region->getEndAddress());
|
||||
editor->jumpToSelection();
|
||||
});
|
||||
@@ -203,8 +200,7 @@ namespace hex::plugin::builtin {
|
||||
|
||||
this->m_shouldSearch = false;
|
||||
this->m_requestFocus = true;
|
||||
this->m_searchRunning = false;
|
||||
}).detach();
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@@ -218,7 +214,7 @@ namespace hex::plugin::builtin {
|
||||
this->m_requestFocus = false;
|
||||
}
|
||||
|
||||
ImGui::BeginDisabled(this->m_searchRunning);
|
||||
ImGui::BeginDisabled(this->m_searchTask.isRunning());
|
||||
{
|
||||
ImGui::SameLine();
|
||||
if (ImGui::IconButton(ICON_VS_SEARCH "##search", ButtonColor, ButtonSize)) {
|
||||
@@ -285,7 +281,7 @@ namespace hex::plugin::builtin {
|
||||
std::atomic<bool> m_shouldSearch = false;
|
||||
std::atomic<bool> m_backwards = false;
|
||||
|
||||
std::atomic<bool> m_searchRunning = false;
|
||||
TaskHolder m_searchTask;
|
||||
};
|
||||
|
||||
class PopupBaseAddress : public ViewHexEditor::Popup {
|
||||
|
||||
@@ -4,20 +4,15 @@
|
||||
|
||||
#include <hex/providers/provider.hpp>
|
||||
#include <hex/providers/buffered_reader.hpp>
|
||||
|
||||
#include <hex/helpers/fs.hpp>
|
||||
#include <hex/helpers/fmt.hpp>
|
||||
#include <hex/helpers/literals.hpp>
|
||||
#include <hex/helpers/magic.hpp>
|
||||
|
||||
#include <cstring>
|
||||
#include <cmath>
|
||||
#include <cinttypes>
|
||||
#include <filesystem>
|
||||
#include <numeric>
|
||||
#include <span>
|
||||
#include <thread>
|
||||
#include <vector>
|
||||
|
||||
#include <hex/helpers/magic.hpp>
|
||||
|
||||
#include <implot.h>
|
||||
|
||||
@@ -80,12 +75,10 @@ namespace hex::plugin::builtin {
|
||||
}
|
||||
|
||||
void ViewInformation::analyze() {
|
||||
this->m_analyzing = true;
|
||||
|
||||
std::thread([this] {
|
||||
this->m_analyzerTask = TaskManager::createTask("hex.builtin.view.information.analyzing", 0, [this](auto &task) {
|
||||
auto provider = ImHexApi::Provider::get();
|
||||
|
||||
auto task = ImHexApi::Tasks::createTask("hex.builtin.view.information.analyzing", provider->getActualSize());
|
||||
task.setMaxValue(provider->getActualSize());
|
||||
|
||||
this->m_analyzedRegion = { provider->getBaseAddress(), provider->getBaseAddress() + provider->getSize() };
|
||||
|
||||
@@ -127,9 +120,7 @@ namespace hex::plugin::builtin {
|
||||
else
|
||||
this->m_highestBlockEntropy = 0;
|
||||
}
|
||||
|
||||
this->m_analyzing = false;
|
||||
}).detach();
|
||||
});
|
||||
}
|
||||
|
||||
void ViewInformation::drawContent() {
|
||||
@@ -138,14 +129,14 @@ namespace hex::plugin::builtin {
|
||||
|
||||
auto provider = ImHexApi::Provider::get();
|
||||
if (ImHexApi::Provider::isValid() && provider->isReadable()) {
|
||||
ImGui::BeginDisabled(this->m_analyzing);
|
||||
ImGui::BeginDisabled(this->m_analyzerTask.isRunning());
|
||||
{
|
||||
if (ImGui::Button("hex.builtin.view.information.analyze"_lang, ImVec2(ImGui::GetContentRegionAvail().x, 0)))
|
||||
this->analyze();
|
||||
}
|
||||
ImGui::EndDisabled();
|
||||
|
||||
if (this->m_analyzing) {
|
||||
if (this->m_analyzerTask.isRunning()) {
|
||||
ImGui::TextSpinner("hex.builtin.view.information.analyzing"_lang);
|
||||
} else {
|
||||
ImGui::NewLine();
|
||||
|
||||
@@ -403,10 +403,14 @@ namespace hex::plugin::builtin {
|
||||
if (this->m_hasUnevaluatedChanges && this->m_runningEvaluators == 0 && this->m_runningParsers == 0) {
|
||||
this->m_hasUnevaluatedChanges = false;
|
||||
|
||||
if (this->m_runAutomatically)
|
||||
this->evaluatePattern(this->m_textEditor.GetText());
|
||||
else
|
||||
std::thread([this, code = this->m_textEditor.GetText()] { this->parsePattern(code); }).detach();
|
||||
|
||||
std::thread([this, code = this->m_textEditor.GetText()]{
|
||||
this->parsePattern(code);
|
||||
|
||||
if (this->m_runAutomatically)
|
||||
this->evaluatePattern(code);
|
||||
}).detach();
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -767,8 +771,6 @@ namespace hex::plugin::builtin {
|
||||
}
|
||||
|
||||
void ViewPatternEditor::parsePattern(const std::string &code) {
|
||||
auto task = ImHexApi::Tasks::createTask("hex.builtin.view.pattern_editor.evaluating", 1);
|
||||
|
||||
this->m_runningParsers++;
|
||||
|
||||
auto ast = this->m_parserRuntime->parseString(code);
|
||||
@@ -813,16 +815,11 @@ namespace hex::plugin::builtin {
|
||||
|
||||
EventManager::post<EventHighlightingChanged>();
|
||||
|
||||
std::thread([this, code, &runtime] {
|
||||
auto task = ImHexApi::Tasks::createTask("hex.builtin.view.pattern_editor.evaluating", 1);
|
||||
|
||||
|
||||
TaskManager::createTask("hex.builtin.view.pattern_editor.evaluating", TaskManager::NoProgress, [this, &runtime, code](auto &) {
|
||||
std::map<std::string, pl::core::Token::Literal> envVars;
|
||||
for (const auto &[id, name, value, type] : this->m_envVarEntries)
|
||||
envVars.insert({ name, value });
|
||||
|
||||
this->parsePattern(code);
|
||||
|
||||
std::map<std::string, pl::core::Token::Literal> inVariables;
|
||||
for (auto &[name, variable] : this->m_patternVariables) {
|
||||
if (variable.inVariable)
|
||||
@@ -851,7 +848,7 @@ namespace hex::plugin::builtin {
|
||||
this->m_runningEvaluators--;
|
||||
|
||||
this->m_lastEvaluationProcessed = false;
|
||||
}).detach();
|
||||
});
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -11,14 +11,14 @@ namespace hex::plugin::builtin {
|
||||
ViewSettings::ViewSettings() : View("hex.builtin.view.settings.name") {
|
||||
EventManager::subscribe<RequestOpenWindow>(this, [this](const std::string &name) {
|
||||
if (name == "Settings") {
|
||||
ImHexApi::Tasks::doLater([] { ImGui::OpenPopup(View::toWindowName("hex.builtin.view.settings.name").c_str()); });
|
||||
TaskManager::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)) {
|
||||
ImHexApi::Tasks::doLater([] { ImGui::OpenPopup(View::toWindowName("hex.builtin.view.settings.name").c_str()); });
|
||||
TaskManager::doLater([] { ImGui::OpenPopup(View::toWindowName("hex.builtin.view.settings.name").c_str()); });
|
||||
this->getWindowOpenState() = true;
|
||||
}
|
||||
});
|
||||
|
||||
@@ -29,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)) {
|
||||
ImHexApi::Tasks::doLater([] { ImGui::OpenPopup(View::toWindowName("hex.builtin.view.store.name").c_str()); });
|
||||
TaskManager::doLater([] { ImGui::OpenPopup(View::toWindowName("hex.builtin.view.store.name").c_str()); });
|
||||
this->getWindowOpenState() = true;
|
||||
}
|
||||
});
|
||||
|
||||
@@ -44,7 +44,7 @@ namespace hex::plugin::builtin {
|
||||
|
||||
if (ImGui::Button("hex.builtin.view.yara.reload"_lang)) this->reloadRules();
|
||||
} else {
|
||||
ImGui::BeginDisabled(this->m_matching);
|
||||
ImGui::BeginDisabled(this->m_matcherTask.isRunning());
|
||||
{
|
||||
if (ImGui::BeginCombo("hex.builtin.view.yara.header.rules"_lang, this->m_rules[this->m_selectedRule].first.string().c_str())) {
|
||||
for (u32 i = 0; i < this->m_rules.size(); i++) {
|
||||
@@ -63,7 +63,7 @@ namespace hex::plugin::builtin {
|
||||
}
|
||||
ImGui::EndDisabled();
|
||||
|
||||
if (this->m_matching) {
|
||||
if (this->m_matcherTask.isRunning()) {
|
||||
ImGui::SameLine();
|
||||
ImGui::TextSpinner("hex.builtin.view.yara.matching"_lang);
|
||||
}
|
||||
@@ -86,7 +86,7 @@ namespace hex::plugin::builtin {
|
||||
|
||||
ImGui::TableHeadersRow();
|
||||
|
||||
if (!this->m_matching) {
|
||||
if (!this->m_matcherTask.isRunning()) {
|
||||
ImGuiListClipper clipper;
|
||||
clipper.Begin(this->m_matches.size());
|
||||
|
||||
@@ -173,19 +173,13 @@ namespace hex::plugin::builtin {
|
||||
void ViewYara::applyRules() {
|
||||
this->clearResult();
|
||||
|
||||
this->m_matching = true;
|
||||
|
||||
std::thread([this] {
|
||||
this->m_matcherTask = TaskManager::createTask("hex.builtin.view.yara.matching", 0, [this](auto &task) {
|
||||
if (!ImHexApi::Provider::isValid()) return;
|
||||
|
||||
auto provider = ImHexApi::Provider::get();
|
||||
auto task = ImHexApi::Tasks::createTask("hex.builtin.view.yara.matching", provider->getActualSize());
|
||||
|
||||
YR_COMPILER *compiler = nullptr;
|
||||
yr_compiler_create(&compiler);
|
||||
ON_SCOPE_EXIT {
|
||||
yr_compiler_destroy(compiler);
|
||||
this->m_matching = false;
|
||||
};
|
||||
|
||||
yr_compiler_set_include_callback(
|
||||
@@ -209,8 +203,8 @@ namespace hex::plugin::builtin {
|
||||
|
||||
delete[] ptr;
|
||||
},
|
||||
fs::toShortPath(this->m_rules[this->m_selectedRule].second).string().data());
|
||||
|
||||
fs::toShortPath(this->m_rules[this->m_selectedRule].second).string().data()
|
||||
);
|
||||
|
||||
fs::File file(this->m_rules[this->m_selectedRule].second, fs::File::Mode::Read);
|
||||
if (!file.isValid()) return;
|
||||
@@ -220,7 +214,7 @@ namespace hex::plugin::builtin {
|
||||
yr_compiler_get_error_message(compiler, errorMessage.data(), errorMessage.size());
|
||||
hex::trim(errorMessage);
|
||||
|
||||
ImHexApi::Tasks::doLater([this, errorMessage] {
|
||||
TaskManager::doLater([this, errorMessage] {
|
||||
this->clearResult();
|
||||
|
||||
this->m_consoleMessages.push_back("Error: " + errorMessage);
|
||||
@@ -246,15 +240,14 @@ namespace hex::plugin::builtin {
|
||||
context.currBlock.base = 0;
|
||||
context.currBlock.fetch_data = [](auto *block) -> const u8 * {
|
||||
auto &context = *static_cast<ScanContext *>(block->context);
|
||||
|
||||
auto provider = ImHexApi::Provider::get();
|
||||
|
||||
context.buffer.resize(context.currBlock.size);
|
||||
|
||||
if (context.buffer.empty()) return nullptr;
|
||||
if (context.buffer.empty())
|
||||
return nullptr;
|
||||
|
||||
block->size = context.currBlock.size;
|
||||
|
||||
provider->read(context.currBlock.base + provider->getBaseAddress(), context.buffer.data(), context.buffer.size());
|
||||
|
||||
return context.buffer.data();
|
||||
@@ -301,11 +294,11 @@ namespace hex::plugin::builtin {
|
||||
ResultContext resultContext;
|
||||
|
||||
yr_rules_scan_mem_blocks(
|
||||
rules, &iterator, 0, [](YR_SCAN_CONTEXT *context, int message, void *data, void *userData) -> int {
|
||||
auto &results = *static_cast<ResultContext *>(userData);
|
||||
rules, &iterator, 0, [](YR_SCAN_CONTEXT *context, int message, void *data, void *userData) -> int {
|
||||
auto &results = *static_cast<ResultContext *>(userData);
|
||||
|
||||
switch (message) {
|
||||
case CALLBACK_MSG_RULE_MATCHING:
|
||||
switch (message) {
|
||||
case CALLBACK_MSG_RULE_MATCHING:
|
||||
{
|
||||
auto rule = static_cast<YR_RULE *>(data);
|
||||
|
||||
@@ -315,30 +308,30 @@ namespace hex::plugin::builtin {
|
||||
if (rule->strings != nullptr) {
|
||||
yr_rule_strings_foreach(rule, string) {
|
||||
yr_string_matches_foreach(context, string, match) {
|
||||
results.newMatches.push_back({ rule->identifier, string->identifier, u64(match->offset), size_t(match->match_length), false, 0, 0 });
|
||||
}
|
||||
results.newMatches.push_back({ rule->identifier, string->identifier, u64(match->offset), size_t(match->match_length), false, 0, 0 });
|
||||
}
|
||||
}
|
||||
} else {
|
||||
results.newMatches.push_back({ rule->identifier, "", 0, 0, true, 0, 0 });
|
||||
}
|
||||
}
|
||||
break;
|
||||
case CALLBACK_MSG_CONSOLE_LOG:
|
||||
break;
|
||||
case CALLBACK_MSG_CONSOLE_LOG:
|
||||
{
|
||||
results.consoleMessages.emplace_back(static_cast<const char *>(data));
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return CALLBACK_CONTINUE;
|
||||
},
|
||||
&resultContext,
|
||||
0);
|
||||
return CALLBACK_CONTINUE;
|
||||
},
|
||||
&resultContext,
|
||||
0);
|
||||
|
||||
|
||||
ImHexApi::Tasks::doLater([this, resultContext] {
|
||||
TaskManager::doLater([this, resultContext] {
|
||||
this->m_matches = resultContext.newMatches;
|
||||
this->m_consoleMessages = resultContext.consoleMessages;
|
||||
|
||||
@@ -348,7 +341,7 @@ namespace hex::plugin::builtin {
|
||||
match.tooltipId = ImHexApi::HexEditor::addTooltip({ match. address, match.size }, hex::format("{0} [{1}]", match.identifier, match.variable), YaraColor);
|
||||
}
|
||||
});
|
||||
}).detach();
|
||||
});
|
||||
}
|
||||
|
||||
}
|
||||
@@ -83,7 +83,7 @@ namespace hex::plugin::builtin {
|
||||
|
||||
if (!provider->open() || !provider->isAvailable()) {
|
||||
View::showErrorPopup("hex.builtin.popup.error.open"_lang);
|
||||
ImHexApi::Tasks::doLater([provider] { ImHexApi::Provider::remove(provider); });
|
||||
TaskManager::doLater([provider] { ImHexApi::Provider::remove(provider); });
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -215,6 +215,9 @@ namespace hex::plugin::builtin {
|
||||
ImGui::SetCursorPosY(ImGui::GetCursorPosY() + 5_scaled);
|
||||
{
|
||||
for (const auto &recentProvider : s_recentProviders) {
|
||||
ImGui::PushID(&recentProvider);
|
||||
ON_SCOPE_EXIT { ImGui::PopID(); };
|
||||
|
||||
if (ImGui::BulletHyperlink(recentProvider.displayName.c_str())) {
|
||||
loadRecentProvider(recentProvider);
|
||||
break;
|
||||
@@ -322,7 +325,7 @@ namespace hex::plugin::builtin {
|
||||
ImGui::EndTable();
|
||||
}
|
||||
|
||||
ImGui::SetCursorPos(ImVec2(ImGui::GetWindowSize().x - ImGui::CalcTextSize("X").x * 2, 0));
|
||||
ImGui::SetCursorPos(ImVec2(ImGui::GetContentRegionAvail().x, 0));
|
||||
if (ImGui::Hyperlink("X")) {
|
||||
auto provider = ImHexApi::Provider::createProvider("hex.builtin.provider.null");
|
||||
if (provider != nullptr)
|
||||
@@ -514,7 +517,7 @@ namespace hex::plugin::builtin {
|
||||
for (const auto &path : fs::getDefaultPaths(fs::ImHexPath::Config)) {
|
||||
if (auto filePath = std::fs::path(path) / CrashBackupFileName; fs::exists(filePath)) {
|
||||
s_safetyBackupPath = filePath;
|
||||
ImHexApi::Tasks::doLater([] { ImGui::OpenPopup("hex.builtin.welcome.safety_backup.title"_lang); });
|
||||
TaskManager::doLater([] { ImGui::OpenPopup("hex.builtin.welcome.safety_backup.title"_lang); });
|
||||
}
|
||||
}
|
||||
|
||||
@@ -523,7 +526,7 @@ namespace hex::plugin::builtin {
|
||||
|
||||
bool showTipOfTheDay = ContentRegistry::Settings::read("hex.builtin.setting.general", "hex.builtin.setting.general.show_tips", 1);
|
||||
if (showTipOfTheDay)
|
||||
ImHexApi::Tasks::doLater([] { ImGui::OpenPopup("hex.builtin.welcome.tip_of_the_day"_lang); });
|
||||
TaskManager::doLater([] { ImGui::OpenPopup("hex.builtin.welcome.tip_of_the_day"_lang); });
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -38,7 +38,7 @@ namespace hex::plugin::builtin {
|
||||
{ "hex.builtin.welcome.learn.latest.link", "https://github.com/WerWolv/ImHex/releases/latest" },
|
||||
{ "hex.builtin.welcome.learn.pattern.title", "Pattern Language Dokumentation" },
|
||||
{ "hex.builtin.welcome.learn.pattern.desc", "Lern ImHex Patterns zu schreiben mit unserer umfangreichen Dokumentation" },
|
||||
{ "hex.builtin.welcome.learn.pattern.link", "https://imhex.werwolv.net/docs/pattern_language/pattern_language.html" },
|
||||
{ "hex.builtin.welcome.learn.pattern.link", "https://imhex.werwolv.net/docs" },
|
||||
{ "hex.builtin.welcome.learn.plugins.title", "Plugins API" },
|
||||
{ "hex.builtin.welcome.learn.plugins.desc", "Erweitere ImHex mit neuen Funktionen mit Plugins" },
|
||||
{ "hex.builtin.welcome.learn.plugins.link", "https://github.com/WerWolv/ImHex/wiki/Plugins-Development-Guide" },
|
||||
|
||||
@@ -39,7 +39,7 @@ namespace hex::plugin::builtin {
|
||||
{ "hex.builtin.welcome.learn.latest.link", "https://github.com/WerWolv/ImHex/releases/latest" },
|
||||
{ "hex.builtin.welcome.learn.pattern.title", "Pattern Language Documentation" },
|
||||
{ "hex.builtin.welcome.learn.pattern.desc", "Learn how to write ImHex patterns with our extensive documentation" },
|
||||
{ "hex.builtin.welcome.learn.pattern.link", "https://imhex.werwolv.net/docs/pattern_language/pattern_language.html" },
|
||||
{ "hex.builtin.welcome.learn.pattern.link", "https://imhex.werwolv.net/docs" },
|
||||
{ "hex.builtin.welcome.learn.plugins.title", "Plugins API" },
|
||||
{ "hex.builtin.welcome.learn.plugins.desc", "Extend ImHex with additional features using plugins" },
|
||||
{ "hex.builtin.welcome.learn.plugins.link", "https://github.com/WerWolv/ImHex/wiki/Plugins-Development-Guide" },
|
||||
|
||||
@@ -38,7 +38,7 @@ namespace hex::plugin::builtin {
|
||||
{ "hex.builtin.welcome.learn.latest.link", "https://github.com/WerWolv/ImHex/releases/latest" },
|
||||
{ "hex.builtin.welcome.learn.pattern.title", "Documentazione dei Pattern" },
|
||||
{ "hex.builtin.welcome.learn.pattern.desc", "Scopri come scrivere pattern per ImHex con la nostra dettagliata documentazione" },
|
||||
{ "hex.builtin.welcome.learn.pattern.link", "https://imhex.werwolv.net/docs/pattern_language/pattern_language.html" },
|
||||
{ "hex.builtin.welcome.learn.pattern.link", "https://imhex.werwolv.net/docs" },
|
||||
{ "hex.builtin.welcome.learn.plugins.title", "Plugins API" },
|
||||
{ "hex.builtin.welcome.learn.plugins.desc", "Espandi l'utilizzo di ImHex con i Plugin" },
|
||||
{ "hex.builtin.welcome.learn.plugins.link", "https://github.com/WerWolv/ImHex/wiki/Plugins-Development-Guide" },
|
||||
|
||||
@@ -38,7 +38,7 @@ namespace hex::plugin::builtin {
|
||||
{ "hex.builtin.welcome.learn.latest.link", "https://github.com/WerWolv/ImHex/releases/latest" },
|
||||
{ "hex.builtin.welcome.learn.pattern.title", "ImHexオリジナル言語について" },
|
||||
{ "hex.builtin.welcome.learn.pattern.desc", "公式ドキュメントを読む" },
|
||||
{ "hex.builtin.welcome.learn.pattern.link", "https://imhex.werwolv.net/docs/pattern_language/pattern_language.html" },
|
||||
{ "hex.builtin.welcome.learn.pattern.link", "https://imhex.werwolv.net/docs" },
|
||||
{ "hex.builtin.welcome.learn.plugins.title", "プラグインAPI" },
|
||||
{ "hex.builtin.welcome.learn.plugins.desc", "ImHexの機能を拡張する" },
|
||||
{ "hex.builtin.welcome.learn.plugins.link", "https://github.com/WerWolv/ImHex/wiki/Plugins-Development-Guide" },
|
||||
@@ -81,13 +81,13 @@ namespace hex::plugin::builtin {
|
||||
{ "hex.builtin.common.browse", "ファイルを参照…" },
|
||||
{ "hex.builtin.common.choose_file", "ファイルを選択" },
|
||||
// { "hex.builtin.common.processing", "Processing" },
|
||||
//{ "hex.builtin.common.filter", "Filter" },
|
||||
//{ "hex.builtin.common.value", "Value" },
|
||||
{ "hex.builtin.common.filter", "フィルタ" },
|
||||
{ "hex.builtin.common.value", "値" },
|
||||
{ "hex.builtin.common.offset", "オフセット" },
|
||||
//{ "hex.builtin.common.range", "Range" },
|
||||
//{ "hex.builtin.common.range.entire_data", "Entire Data" },
|
||||
//{ "hex.builtin.common.range.selection", "Selection" },
|
||||
//{ "hex.builtin.common.comment", "Comment" },
|
||||
{ "hex.builtin.common.range", "範囲" },
|
||||
{ "hex.builtin.common.range.entire_data", "データ全体" },
|
||||
{ "hex.builtin.common.range.selection", "選択範囲" },
|
||||
{ "hex.builtin.common.comment", "コメント" },
|
||||
|
||||
{ "hex.builtin.common.encoding.ascii", "ASCII" },
|
||||
{ "hex.builtin.common.encoding.utf16le", "UTF-16LE" },
|
||||
@@ -123,9 +123,9 @@ namespace hex::plugin::builtin {
|
||||
{ "hex.builtin.menu.file.export.ips", "IPSパッチ" },
|
||||
{ "hex.builtin.menu.file.export.ips32", "IPS32パッチ" },
|
||||
{ "hex.builtin.menu.file.export.base64.popup.export_error", "有効なBase64形式ではありません。" },
|
||||
{ "hex.builtin.menu.file.export.popup.create", "データをエクスポートできません。\nファイルの作成に失敗しました。" },
|
||||
//{ "hex.builtin.menu.file.bookmark.import", "Import bookmarks" },
|
||||
//{ "hex.builtin.menu.file.bookmark.export", "Export bookmarks" },
|
||||
{ "hex.builtin.menu.file.export.popup.create", "データをエクスポートできません。\nファイルの作成に失敗しました。" },
|
||||
{ "hex.builtin.menu.file.bookmark.import", "ブックマークをインポート…" },
|
||||
{ "hex.builtin.menu.file.bookmark.export", "ブックマークをエクスポート…" },
|
||||
|
||||
{ "hex.builtin.menu.edit", "編集" },
|
||||
{ "hex.builtin.menu.edit.undo", "元に戻す" },
|
||||
@@ -259,10 +259,10 @@ namespace hex::plugin::builtin {
|
||||
|
||||
{ "hex.builtin.view.hex_editor.name", "Hexエディタ" },
|
||||
{ "hex.builtin.view.hex_editor.page", "ページ" },
|
||||
//{ "hex.builtin.view.hex_editor.selection", "Selection" },
|
||||
//{ "hex.builtin.view.hex_editor.selection.none", "None" },
|
||||
//{ "hex.builtin.view.hex_editor.region", "Region" },
|
||||
//{ "hex.builtin.view.hex_editor.data_size", "Data Size" },
|
||||
{ "hex.builtin.view.hex_editor.selection", "選択中" },
|
||||
{ "hex.builtin.view.hex_editor.selection.none", "なし" },
|
||||
{ "hex.builtin.view.hex_editor.region", "ページの領域" },
|
||||
{ "hex.builtin.view.hex_editor.data_size", "ファイルサイズ" },
|
||||
//{ "hex.builtin.view.hex_editor.no_bytes", "No bytes available" },
|
||||
|
||||
{ "hex.builtin.view.hex_editor.menu.file.search", "検索" },
|
||||
@@ -303,9 +303,9 @@ namespace hex::plugin::builtin {
|
||||
{ "hex.builtin.view.hex_editor.menu.edit.resize", "リサイズ…" },
|
||||
{ "hex.builtin.view.hex_editor.menu.edit.insert", "挿入…" },
|
||||
|
||||
{ "hex.builtin.view.information.name", "データ情報" },
|
||||
{ "hex.builtin.view.information.name", "データ解析" },
|
||||
{ "hex.builtin.view.information.control", "コントロール" },
|
||||
{ "hex.builtin.view.information.analyze", "解析ページ" },
|
||||
{ "hex.builtin.view.information.analyze", "表示中のページを解析する" },
|
||||
{ "hex.builtin.view.information.analyzing", "解析中…" },
|
||||
{ "hex.builtin.view.information.region", "解析する領域" },
|
||||
{ "hex.builtin.view.information.magic", "Magic情報" },
|
||||
@@ -318,7 +318,7 @@ namespace hex::plugin::builtin {
|
||||
{ "hex.builtin.view.information.block_size.desc", "{0} ブロック/ {1} バイト" },
|
||||
{ "hex.builtin.view.information.file_entropy", "ファイルのエントロピー" },
|
||||
{ "hex.builtin.view.information.highest_entropy", "最大エントロピーブロック" },
|
||||
{ "hex.builtin.view.information.encrypted", "暗号化もしくは圧縮されているデータの可能性が高いです。" },
|
||||
{ "hex.builtin.view.information.encrypted", "暗号化や圧縮を経たデータと推測されます。" },
|
||||
{ "hex.builtin.view.information.magic_db_added", "Magicデータベースが追加されました。" },
|
||||
|
||||
{ "hex.builtin.view.patches.name", "パッチ" },
|
||||
@@ -400,31 +400,30 @@ namespace hex::plugin::builtin {
|
||||
{ "hex.builtin.view.provider_settings.load_popup", "プロバイダを開く" },
|
||||
{ "hex.builtin.view.provider_settings.load_error", "プロバイダを開く際にエラーが発生しました。"},
|
||||
|
||||
//{ "hex.builtin.view.find.name", "Find" },
|
||||
// { "hex.builtin.view.find.searching", "Searching…" },
|
||||
{ "hex.builtin.view.find.name", "検索" },
|
||||
{ "hex.builtin.view.find.searching", "検索中…" },
|
||||
// { "hex.builtin.view.find.demangled", "Demangled" },
|
||||
// { "hex.builtin.view.find.range", "Range" },
|
||||
// { "hex.builtin.view.find.range.entire_data", "Entire Data" },
|
||||
// { "hex.builtin.view.find.range.selection", "Selection" },
|
||||
{ "hex.builtin.view.find.range", "検索する範囲" },
|
||||
{ "hex.builtin.view.find.range.selection", "選択中の箇所のみ" },
|
||||
// { "hex.builtin.view.find.strings", "文字列" },
|
||||
// { "hex.builtin.view.find.strings.min_length", "Minimum length" },
|
||||
// { "hex.builtin.view.find.strings.match_settings", "Match Settings" },
|
||||
// { "hex.builtin.view.find.strings.null_term", "Require Null Termination" },
|
||||
{ "hex.builtin.view.find.strings.match_settings", "条件設定" },
|
||||
{ "hex.builtin.view.find.strings.null_term", "ヌル終端を含む文字列のみ検索" },
|
||||
// { "hex.builtin.view.find.strings.chars", "Characters" },
|
||||
// { "hex.builtin.view.find.strings.lower_case", "Lower case letters" },
|
||||
// { "hex.builtin.view.find.strings.upper_case", "Upper case letters" },
|
||||
// { "hex.builtin.view.find.strings.numbers", "Numbers" },
|
||||
// { "hex.builtin.view.find.strings.underscores", "Underscores" },
|
||||
// { "hex.builtin.view.find.strings.symbols", "Symbols" },
|
||||
// { "hex.builtin.view.find.strings.spaces", "Spaces" },
|
||||
// { "hex.builtin.view.find.strings.line_feeds", "Line Feeds" },
|
||||
// { "hex.builtin.view.find.sequences", "Sequences" },
|
||||
// { "hex.builtin.view.find.regex", "Regex" },
|
||||
// { "hex.builtin.view.find.binary_pattern", "Binary Pattern" },
|
||||
// { "hex.builtin.view.find.search", "Search" },
|
||||
// { "hex.builtin.view.find.context.copy", "Copy Value" },
|
||||
{ "hex.builtin.view.find.strings.lower_case", "大文字" },
|
||||
{ "hex.builtin.view.find.strings.upper_case", "小文字" },
|
||||
{ "hex.builtin.view.find.strings.numbers", "数字" },
|
||||
{ "hex.builtin.view.find.strings.underscores", "アンダースコア" },
|
||||
{ "hex.builtin.view.find.strings.symbols", "その他の記号" },
|
||||
{ "hex.builtin.view.find.strings.spaces", "半角スペース" },
|
||||
{ "hex.builtin.view.find.strings.line_feeds", "ラインフィード" },
|
||||
{ "hex.builtin.view.find.sequences", "通常検索" },
|
||||
{ "hex.builtin.view.find.regex", "正規表現" },
|
||||
{ "hex.builtin.view.find.binary_pattern", "16進数" },
|
||||
{ "hex.builtin.view.find.search", "検索を実行" },
|
||||
{ "hex.builtin.view.find.context.copy", "値をコピー" },
|
||||
// { "hex.builtin.view.find.context.copy_demangle", "Copy Demangled Value" },
|
||||
// { "hex.builtin.view.find.search.entries", "{} entries found" },
|
||||
{ "hex.builtin.view.find.search.entries", "一致件数: {}" },
|
||||
|
||||
{ "hex.builtin.command.calc.desc", "電卓" },
|
||||
{ "hex.builtin.command.cmd.desc", "コマンド" },
|
||||
|
||||
@@ -38,7 +38,7 @@ namespace hex::plugin::builtin {
|
||||
{ "hex.builtin.welcome.learn.latest.link", "https://github.com/WerWolv/ImHex/releases/latest" },
|
||||
{ "hex.builtin.welcome.learn.pattern.title", "Documentação da linguagem padrão" },
|
||||
{ "hex.builtin.welcome.learn.pattern.desc", "Aprenda a escrever padrões ImHex com nossa extensa documentação" },
|
||||
{ "hex.builtin.welcome.learn.pattern.link", "https://imhex.werwolv.net/docs/pattern_language/pattern_language.html" },
|
||||
{ "hex.builtin.welcome.learn.pattern.link", "https://imhex.werwolv.net/docs" },
|
||||
{ "hex.builtin.welcome.learn.plugins.title", "Plugins API" },
|
||||
{ "hex.builtin.welcome.learn.plugins.desc", "Estenda o ImHex com recursos adicionais usando plugins" },
|
||||
{ "hex.builtin.welcome.learn.plugins.link", "https://github.com/WerWolv/ImHex/wiki/Plugins-Development-Guide" },
|
||||
|
||||
@@ -38,7 +38,7 @@ namespace hex::plugin::builtin {
|
||||
{ "hex.builtin.welcome.learn.latest.link", "https://github.com/WerWolv/ImHex/releases/latest" },
|
||||
{ "hex.builtin.welcome.learn.pattern.title", "模式文档" },
|
||||
{ "hex.builtin.welcome.learn.pattern.desc", "如何基于我们完善的文档编写 ImHex 模式" },
|
||||
{ "hex.builtin.welcome.learn.pattern.link", "https://imhex.werwolv.net/docs/pattern_language/pattern_language.html" },
|
||||
{ "hex.builtin.welcome.learn.pattern.link", "https://imhex.werwolv.net/docs" },
|
||||
{ "hex.builtin.welcome.learn.plugins.title", "插件 API" },
|
||||
{ "hex.builtin.welcome.learn.plugins.desc", "通过插件扩展 ImHex 获得更多功能" },
|
||||
{ "hex.builtin.welcome.learn.plugins.link", "https://github.com/WerWolv/ImHex/wiki/Plugins-Development-Guide" },
|
||||
|
||||
@@ -38,7 +38,7 @@ namespace hex::plugin::builtin {
|
||||
{ "hex.builtin.welcome.learn.latest.link", "https://github.com/WerWolv/ImHex/releases/latest" },
|
||||
{ "hex.builtin.welcome.learn.pattern.title", "模式語言說明文件" },
|
||||
{ "hex.builtin.welcome.learn.pattern.desc", " 閱覽我們詳盡的說明文件來學習如何編寫 ImHex 的模式" },
|
||||
{ "hex.builtin.welcome.learn.pattern.link", "https://imhex.werwolv.net/docs/pattern_language/pattern_language.html" },
|
||||
{ "hex.builtin.welcome.learn.pattern.link", "https://imhex.werwolv.net/docs" },
|
||||
{ "hex.builtin.welcome.learn.plugins.title", "外掛程式 API" },
|
||||
{ "hex.builtin.welcome.learn.plugins.desc", " 使用外掛程式來拓展 ImHex 的功能" },
|
||||
{ "hex.builtin.welcome.learn.plugins.link", "https://github.com/WerWolv/ImHex/wiki/Plugins-Development-Guide" },
|
||||
|
||||
Reference in New Issue
Block a user