mirror of https://github.com/WerWolv/ImHex
Merge b35fe2b9e0 into 62732de227
This commit is contained in:
commit
6b9af87db5
|
|
@ -58,6 +58,7 @@ set(LIBIMHEX_SOURCES
|
||||||
source/ui/banner.cpp
|
source/ui/banner.cpp
|
||||||
|
|
||||||
source/subcommands/subcommands.cpp
|
source/subcommands/subcommands.cpp
|
||||||
|
source/init/cli.cpp
|
||||||
)
|
)
|
||||||
|
|
||||||
if (APPLE)
|
if (APPLE)
|
||||||
|
|
|
||||||
|
|
@ -88,6 +88,8 @@ EXPORT_MODULE namespace hex {
|
||||||
bool frameRateUnlockRequested();
|
bool frameRateUnlockRequested();
|
||||||
void resetFrameRateUnlockRequested();
|
void resetFrameRateUnlockRequested();
|
||||||
|
|
||||||
|
void setReadOnlyMode(bool enabled);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -186,6 +188,11 @@ EXPORT_MODULE namespace hex {
|
||||||
*/
|
*/
|
||||||
std::string getInitArgument(const std::string &key);
|
std::string getInitArgument(const std::string &key);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Returns whether ImHex is running in read-only mode (no edits/saves)
|
||||||
|
*/
|
||||||
|
bool isReadOnlyMode();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Sets if ImHex should follow the system theme
|
* @brief Sets if ImHex should follow the system theme
|
||||||
* @param enabled Whether to follow the system theme
|
* @param enabled Whether to follow the system theme
|
||||||
|
|
|
||||||
|
|
@ -619,6 +619,11 @@ namespace hex {
|
||||||
s_frameRateUnlockRequested = false;
|
s_frameRateUnlockRequested = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static bool s_readOnlyMode = false;
|
||||||
|
void setReadOnlyMode(bool enabled) {
|
||||||
|
s_readOnlyMode = enabled;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool isMainInstance() {
|
bool isMainInstance() {
|
||||||
|
|
@ -1092,6 +1097,10 @@ namespace hex {
|
||||||
RequestSetPostProcessingShader::post(vertexShader, fragmentShader);
|
RequestSetPostProcessingShader::post(vertexShader, fragmentShader);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool isReadOnlyMode() {
|
||||||
|
return impl::s_readOnlyMode;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,15 @@
|
||||||
|
#include <hex.hpp>
|
||||||
|
|
||||||
|
#include <hex/api/imhex_api/system.hpp>
|
||||||
|
|
||||||
|
namespace hex::init::cli_support {
|
||||||
|
|
||||||
|
void applyGlobalFlag(const std::string &arg) {
|
||||||
|
if (arg == "--readonly" || arg == "-r") {
|
||||||
|
ImHexApi::System::impl::setReadOnlyMode(true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -68,7 +68,7 @@ namespace hex::prv {
|
||||||
}
|
}
|
||||||
|
|
||||||
void Provider::write(u64 offset, const void *buffer, size_t size) {
|
void Provider::write(u64 offset, const void *buffer, size_t size) {
|
||||||
if (!this->isWritable())
|
if (!this->isWritable() || ImHexApi::System::isReadOnlyMode())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
EventProviderDataModified::post(this, offset, size, static_cast<const u8*>(buffer));
|
EventProviderDataModified::post(this, offset, size, static_cast<const u8*>(buffer));
|
||||||
|
|
@ -76,7 +76,7 @@ namespace hex::prv {
|
||||||
}
|
}
|
||||||
|
|
||||||
void Provider::save() {
|
void Provider::save() {
|
||||||
if (!this->isWritable())
|
if (!this->isWritable() || ImHexApi::System::isReadOnlyMode())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
EventProviderSaved::post(this);
|
EventProviderSaved::post(this);
|
||||||
|
|
@ -100,6 +100,9 @@ namespace hex::prv {
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Provider::resize(u64 newSize) {
|
bool Provider::resize(u64 newSize) {
|
||||||
|
if (ImHexApi::System::isReadOnlyMode()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
if (newSize >> 63) {
|
if (newSize >> 63) {
|
||||||
log::error("new provider size is very large ({}). Is it a negative number ?", newSize);
|
log::error("new provider size is very large ({}). Is it a negative number ?", newSize);
|
||||||
return false;
|
return false;
|
||||||
|
|
@ -116,12 +119,14 @@ namespace hex::prv {
|
||||||
}
|
}
|
||||||
|
|
||||||
void Provider::insert(u64 offset, u64 size) {
|
void Provider::insert(u64 offset, u64 size) {
|
||||||
|
if (ImHexApi::System::isReadOnlyMode()) return;
|
||||||
EventProviderDataInserted::post(this, offset, size);
|
EventProviderDataInserted::post(this, offset, size);
|
||||||
|
|
||||||
this->markDirty();
|
this->markDirty();
|
||||||
}
|
}
|
||||||
|
|
||||||
void Provider::remove(u64 offset, u64 size) {
|
void Provider::remove(u64 offset, u64 size) {
|
||||||
|
if (ImHexApi::System::isReadOnlyMode()) return;
|
||||||
EventProviderDataRemoved::post(this, offset, size);
|
EventProviderDataRemoved::post(this, offset, size);
|
||||||
|
|
||||||
this->markDirty();
|
this->markDirty();
|
||||||
|
|
|
||||||
|
|
@ -71,7 +71,24 @@ namespace hex::init {
|
||||||
PluginManager::load(dir);
|
PluginManager::load(dir);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Process the arguments
|
// Process our own global flags first
|
||||||
|
{
|
||||||
|
std::vector<std::string> remaining;
|
||||||
|
remaining.reserve(args.size());
|
||||||
|
|
||||||
|
for (size_t i = 0; i < args.size(); i += 1) {
|
||||||
|
const auto &arg = args[i];
|
||||||
|
if (arg == "--readonly" || arg == "-r") {
|
||||||
|
ImHexApi::System::impl::setReadOnlyMode(true);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
remaining.push_back(arg);
|
||||||
|
}
|
||||||
|
|
||||||
|
args.swap(remaining);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Process the arguments (subcommands) after handling globals
|
||||||
hex::subcommands::processArguments(args);
|
hex::subcommands::processArguments(args);
|
||||||
|
|
||||||
// Explicitly don't unload plugins again here.
|
// Explicitly don't unload plugins again here.
|
||||||
|
|
|
||||||
|
|
@ -84,7 +84,7 @@ namespace hex::plugin::builtin {
|
||||||
|
|
||||||
EventWindowClosing::subscribe([](GLFWwindow *window) {
|
EventWindowClosing::subscribe([](GLFWwindow *window) {
|
||||||
imhexClosing = false;
|
imhexClosing = false;
|
||||||
if (ImHexApi::Provider::isDirty() && !imhexClosing) {
|
if (!ImHexApi::System::isReadOnlyMode() && ImHexApi::Provider::isDirty() && !imhexClosing) {
|
||||||
glfwSetWindowShouldClose(window, GLFW_FALSE);
|
glfwSetWindowShouldClose(window, GLFW_FALSE);
|
||||||
ui::PopupQuestion::open("hex.builtin.popup.exit_application.desc"_lang,
|
ui::PopupQuestion::open("hex.builtin.popup.exit_application.desc"_lang,
|
||||||
[] {
|
[] {
|
||||||
|
|
@ -108,7 +108,7 @@ namespace hex::plugin::builtin {
|
||||||
|
|
||||||
EventCloseButtonPressed::subscribe([]() {
|
EventCloseButtonPressed::subscribe([]() {
|
||||||
if (ImHexApi::Provider::isValid()) {
|
if (ImHexApi::Provider::isValid()) {
|
||||||
if (ImHexApi::Provider::isDirty()) {
|
if (!ImHexApi::System::isReadOnlyMode() && ImHexApi::Provider::isDirty()) {
|
||||||
ui::PopupQuestion::open("hex.builtin.popup.exit_application.desc"_lang,
|
ui::PopupQuestion::open("hex.builtin.popup.exit_application.desc"_lang,
|
||||||
[] {
|
[] {
|
||||||
for (const auto &provider : ImHexApi::Provider::getProviders())
|
for (const auto &provider : ImHexApi::Provider::getProviders())
|
||||||
|
|
@ -134,7 +134,7 @@ namespace hex::plugin::builtin {
|
||||||
});
|
});
|
||||||
|
|
||||||
EventProviderClosing::subscribe([](const prv::Provider *provider, bool *shouldClose) {
|
EventProviderClosing::subscribe([](const prv::Provider *provider, bool *shouldClose) {
|
||||||
if (provider->isDirty()) {
|
if (!ImHexApi::System::isReadOnlyMode() && provider->isDirty()) {
|
||||||
*shouldClose = false;
|
*shouldClose = false;
|
||||||
PopupUnsavedChanges::open("hex.builtin.popup.close_provider.desc"_lang,
|
PopupUnsavedChanges::open("hex.builtin.popup.close_provider.desc"_lang,
|
||||||
[]{
|
[]{
|
||||||
|
|
|
||||||
|
|
@ -52,7 +52,7 @@ namespace hex::plugin::builtin {
|
||||||
}
|
}
|
||||||
|
|
||||||
bool noRunningTaskAndWritableProvider() {
|
bool noRunningTaskAndWritableProvider() {
|
||||||
return noRunningTasks() && ImHexApi::Provider::isValid() && ImHexApi::Provider::get()->isWritable();
|
return noRunningTasks() && !ImHexApi::System::isReadOnlyMode() && ImHexApi::Provider::isValid() && ImHexApi::Provider::get()->isWritable();
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -5,4 +5,5 @@ target_compile_definitions(tests_common PUBLIC IMHEX_PROJECT_NAME="${PROJECT_NAM
|
||||||
|
|
||||||
add_subdirectory(helpers)
|
add_subdirectory(helpers)
|
||||||
add_subdirectory(algorithms)
|
add_subdirectory(algorithms)
|
||||||
add_subdirectory(plugins)
|
add_subdirectory(plugins)
|
||||||
|
add_subdirectory(cli)
|
||||||
|
|
@ -0,0 +1,25 @@
|
||||||
|
cmake_minimum_required(VERSION 3.16)
|
||||||
|
|
||||||
|
project(cli_test)
|
||||||
|
set(TEST_CATEGORY CLI)
|
||||||
|
|
||||||
|
set(AVAILABLE_TESTS
|
||||||
|
ReadOnlyFlagSetsMode
|
||||||
|
)
|
||||||
|
|
||||||
|
add_executable(${PROJECT_NAME}
|
||||||
|
source/test_cli_readonly.cpp
|
||||||
|
)
|
||||||
|
|
||||||
|
target_include_directories(${PROJECT_NAME} PRIVATE include)
|
||||||
|
target_link_libraries(${PROJECT_NAME} PRIVATE libimhex tests_common ${FMT_LIBRARIES})
|
||||||
|
|
||||||
|
set_target_properties(${PROJECT_NAME} PROPERTIES RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR})
|
||||||
|
|
||||||
|
foreach (test IN LISTS AVAILABLE_TESTS)
|
||||||
|
add_test(NAME "${TEST_CATEGORY}/${test}" COMMAND ${PROJECT_NAME} "${test}" WORKING_DIRECTORY ${CMAKE_BINARY_DIR})
|
||||||
|
endforeach ()
|
||||||
|
|
||||||
|
add_dependencies(unit_tests ${PROJECT_NAME})
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -0,0 +1,33 @@
|
||||||
|
#include <hex/test/tests.hpp>
|
||||||
|
|
||||||
|
#include <hex/api/imhex_api/system.hpp>
|
||||||
|
|
||||||
|
// We only declare the CLI runner here; it's defined in the GUI main module
|
||||||
|
namespace hex::init {
|
||||||
|
void runCommandLine(int argc, char **argv);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int runReadOnlyCLI(const std::vector<const char*> &args) {
|
||||||
|
int argc = static_cast<int>(args.size());
|
||||||
|
// const_cast is safe here because CLI layer doesn't mutate program name/args strings
|
||||||
|
auto argv = const_cast<char**>(reinterpret_cast<char* const*>(args.data()));
|
||||||
|
hex::init::runCommandLine(argc, argv);
|
||||||
|
return EXIT_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_SEQUENCE("ReadOnlyFlagSetsMode") {
|
||||||
|
// Simulate: imhex --readonly somefile
|
||||||
|
const char *prog = "imhex";
|
||||||
|
const char *flag = "--readonly";
|
||||||
|
const char *file = "dummy.bin";
|
||||||
|
const std::vector<const char*> argv = { prog, flag, file };
|
||||||
|
|
||||||
|
(void) runReadOnlyCLI(argv);
|
||||||
|
|
||||||
|
// Expect the global read-only mode to be enabled
|
||||||
|
TEST_ASSERT(hex::ImHexApi::System::isReadOnlyMode());
|
||||||
|
|
||||||
|
TEST_SUCCESS();
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
Loading…
Reference in New Issue