From b89af0c51e3984909419a99c515d06884b6c0afc Mon Sep 17 00:00:00 2001 From: Duncan Ogilvie Date: Fri, 22 Sep 2023 18:51:13 +0200 Subject: [PATCH] Add some cross platform example projects --- src/cross/.gitattributes | 3 + src/cross/CMakeLists.txt | 133 + src/cross/cmake.toml | 49 + src/cross/cmkr.cmake | 253 + src/cross/gui/Bridge.cpp | 334 + src/cross/gui/Bridge.h | 172 + src/cross/gui/CMakeLists.txt | 100 + src/cross/gui/Configuration.cpp | 1226 + src/cross/gui/Configuration.h | 132 + src/cross/gui/Imports.h | 3 + src/cross/gui/MagicMenu.h | 120 + src/cross/gui/MiscUtil.cpp | 404 + src/cross/gui/MiscUtil.h | 28 + src/cross/gui/Qt.cmake | 63 + src/cross/gui/StringUtil.cpp | 284 + src/cross/gui/StringUtil.h | 137 + src/cross/gui/Types.h | 76 + src/cross/remote_table/JsonRpcClient.cpp | 62 + src/cross/remote_table/JsonRpcClient.h | 49 + src/cross/remote_table/MainWindow.cpp | 33 + src/cross/remote_table/MainWindow.h | 32 + src/cross/remote_table/MainWindow.ui | 47 + src/cross/remote_table/RemoteTable.cpp | 197 + src/cross/remote_table/RemoteTable.h | 46 + src/cross/remote_table/TableRpcData.h | 28 + src/cross/remote_table/TableServer.cpp | 106 + src/cross/remote_table/TableServer.h | 22 + src/cross/remote_table/json.hpp | 24596 ++++++++++++++++ src/cross/remote_table/main.cpp | 20 + src/cross/vendor/CMakeLists.txt | 15 + src/cross/vendor/cmake.toml | 3 + src/cross/vendor/cpp-httplib/httplib.h | 10263 +++++++ src/gui/Src/BasicView/AbstractStdTable.cpp | 2 +- src/gui/Src/BasicView/AbstractTableView.cpp | 6 +- src/gui/Src/BasicView/AbstractTableView.h | 4 +- src/gui/Src/BasicView/Disassembly.cpp | 12 +- src/gui/Src/BasicView/Disassembly.h | 4 +- src/gui/Src/BasicView/HexDump.h | 7 +- src/gui/Src/Disassembler/QZydis.cpp | 6 +- src/gui/Src/Disassembler/ZydisTokenizer.cpp | 4 +- src/gui/Src/Disassembler/ZydisTokenizer.h | 4 +- src/gui/Src/Gui/BrowseDialog.cpp | 4 +- src/gui/Src/Gui/ColumnReorderDialog.cpp | 2 +- src/gui/Src/Gui/DisassemblyPopup.cpp | 10 +- src/gui/Src/Gui/DisassemblyPopup.h | 7 +- src/gui/Src/Memory/MemoryPage.cpp | 1 + src/gui/Src/Memory/MemoryPage.h | 2 +- src/gui/Src/Utils/ActionHelpers.h | 2 +- src/gui/Src/Utils/BackgroundFlickerThread.cpp | 2 +- src/gui/Src/Utils/CodeFolding.h | 2 +- src/gui/Src/Utils/Configuration.cpp | 2 +- src/gui/Src/Utils/EncodeMap.cpp | 3 +- src/gui/Src/Utils/EncodeMap.h | 6 +- src/gui/Src/Utils/MenuBuilder.cpp | 6 +- src/gui/Src/Utils/MenuBuilder.h | 14 +- src/gui/Src/Utils/StringUtil.cpp | 2 +- src/gui/Src/Utils/SymbolAutoCompleteModel.cpp | 2 +- src/zydis_wrapper/CMakeLists.txt | 29 + 58 files changed, 39125 insertions(+), 56 deletions(-) create mode 100644 src/cross/.gitattributes create mode 100644 src/cross/CMakeLists.txt create mode 100644 src/cross/cmake.toml create mode 100644 src/cross/cmkr.cmake create mode 100644 src/cross/gui/Bridge.cpp create mode 100644 src/cross/gui/Bridge.h create mode 100644 src/cross/gui/CMakeLists.txt create mode 100644 src/cross/gui/Configuration.cpp create mode 100644 src/cross/gui/Configuration.h create mode 100644 src/cross/gui/Imports.h create mode 100644 src/cross/gui/MagicMenu.h create mode 100644 src/cross/gui/MiscUtil.cpp create mode 100644 src/cross/gui/MiscUtil.h create mode 100644 src/cross/gui/Qt.cmake create mode 100644 src/cross/gui/StringUtil.cpp create mode 100644 src/cross/gui/StringUtil.h create mode 100644 src/cross/gui/Types.h create mode 100644 src/cross/remote_table/JsonRpcClient.cpp create mode 100644 src/cross/remote_table/JsonRpcClient.h create mode 100644 src/cross/remote_table/MainWindow.cpp create mode 100644 src/cross/remote_table/MainWindow.h create mode 100644 src/cross/remote_table/MainWindow.ui create mode 100644 src/cross/remote_table/RemoteTable.cpp create mode 100644 src/cross/remote_table/RemoteTable.h create mode 100644 src/cross/remote_table/TableRpcData.h create mode 100644 src/cross/remote_table/TableServer.cpp create mode 100644 src/cross/remote_table/TableServer.h create mode 100644 src/cross/remote_table/json.hpp create mode 100644 src/cross/remote_table/main.cpp create mode 100644 src/cross/vendor/CMakeLists.txt create mode 100644 src/cross/vendor/cmake.toml create mode 100644 src/cross/vendor/cpp-httplib/httplib.h create mode 100644 src/zydis_wrapper/CMakeLists.txt diff --git a/src/cross/.gitattributes b/src/cross/.gitattributes new file mode 100644 index 00000000..1a139ac9 --- /dev/null +++ b/src/cross/.gitattributes @@ -0,0 +1,3 @@ +# cmkr +/**/CMakeLists.txt linguist-generated +/**/cmkr.cmake linguist-vendored diff --git a/src/cross/CMakeLists.txt b/src/cross/CMakeLists.txt new file mode 100644 index 00000000..5995baab --- /dev/null +++ b/src/cross/CMakeLists.txt @@ -0,0 +1,133 @@ +# This file is automatically generated from cmake.toml - DO NOT EDIT +# See https://github.com/build-cpp/cmkr for more information + +cmake_minimum_required(VERSION 3.15) + +if(CMAKE_SOURCE_DIR STREQUAL CMAKE_BINARY_DIR) + message(FATAL_ERROR "In-tree builds are not supported. Run CMake from a separate directory: cmake -B build") +endif() + +set(CMKR_ROOT_PROJECT OFF) +if(CMAKE_CURRENT_SOURCE_DIR STREQUAL CMAKE_SOURCE_DIR) + set(CMKR_ROOT_PROJECT ON) + + # Bootstrap cmkr and automatically regenerate CMakeLists.txt + include(cmkr.cmake OPTIONAL RESULT_VARIABLE CMKR_INCLUDE_RESULT) + if(CMKR_INCLUDE_RESULT) + cmkr() + endif() + + # Enable folder support + set_property(GLOBAL PROPERTY USE_FOLDERS ON) + + # Create a configure-time dependency on cmake.toml to improve IDE support + configure_file(cmake.toml cmake.toml COPYONLY) +endif() + +project(cross) + +include("gui/Qt.cmake") + +# Subdirectory: gui +set(CMKR_CMAKE_FOLDER ${CMAKE_FOLDER}) +if(CMAKE_FOLDER) + set(CMAKE_FOLDER "${CMAKE_FOLDER}/gui") +else() + set(CMAKE_FOLDER gui) +endif() +add_subdirectory(gui) +set(CMAKE_FOLDER ${CMKR_CMAKE_FOLDER}) + +# Subdirectory: vendor +set(CMKR_CMAKE_FOLDER ${CMAKE_FOLDER}) +if(CMAKE_FOLDER) + set(CMAKE_FOLDER "${CMAKE_FOLDER}/vendor") +else() + set(CMAKE_FOLDER vendor) +endif() +add_subdirectory(vendor) +set(CMAKE_FOLDER ${CMKR_CMAKE_FOLDER}) + +# Target: minidump +set(minidump_SOURCES + "minidump/GotoDialog.cpp" + "minidump/MainWindow.cpp" + "minidump/MiniDisassembly.cpp" + "minidump/MiniDump.cpp" + "minidump/MiniHexDump.cpp" + "minidump/MiniMemoryMap.cpp" + "minidump/Navigation.cpp" + "minidump/REToolSync.cpp" + "minidump/main.cpp" + "minidump/GotoDialog.h" + "minidump/MainWindow.h" + "minidump/MiniDisassembly.h" + "minidump/MiniDump.h" + "minidump/MiniHexDump.h" + "minidump/MiniMemoryMap.h" + "minidump/Navigation.h" + "minidump/REToolSync.h" + "minidump/udmp-parser.h" + "minidump/udmp-utils.h" + "minidump/MainWindow.ui" + cmake.toml +) + +qt_executable(minidump ${minidump_SOURCES}) +source_group(TREE ${CMAKE_CURRENT_SOURCE_DIR} FILES ${minidump_SOURCES}) + +target_compile_features(minidump PRIVATE + cxx_std_17 +) + +target_link_libraries(minidump PRIVATE + ${QT_LIBRARIES} + widgets + cpp-httplib +) + +get_directory_property(CMKR_VS_STARTUP_PROJECT DIRECTORY ${PROJECT_SOURCE_DIR} DEFINITION VS_STARTUP_PROJECT) +if(NOT CMKR_VS_STARTUP_PROJECT) + set_property(DIRECTORY ${PROJECT_SOURCE_DIR} PROPERTY VS_STARTUP_PROJECT minidump) +endif() + +set(CMKR_TARGET minidump) +qt_finalize_executable(${CMKR_TARGET}) + +# Target: remote_table +set(remote_table_SOURCES + "remote_table/JsonRpcClient.cpp" + "remote_table/MainWindow.cpp" + "remote_table/RemoteTable.cpp" + "remote_table/TableServer.cpp" + "remote_table/main.cpp" + "remote_table/JsonRpcClient.h" + "remote_table/MainWindow.h" + "remote_table/RemoteTable.h" + "remote_table/TableRpcData.h" + "remote_table/TableServer.h" + "remote_table/MainWindow.ui" + "remote_table/json.hpp" + cmake.toml +) + +qt_executable(remote_table ${remote_table_SOURCES}) +source_group(TREE ${CMAKE_CURRENT_SOURCE_DIR} FILES ${remote_table_SOURCES}) + +target_compile_features(remote_table PRIVATE + cxx_std_17 +) + +target_link_libraries(remote_table PRIVATE + ${QT_LIBRARIES} + widgets +) + +get_directory_property(CMKR_VS_STARTUP_PROJECT DIRECTORY ${PROJECT_SOURCE_DIR} DEFINITION VS_STARTUP_PROJECT) +if(NOT CMKR_VS_STARTUP_PROJECT) + set_property(DIRECTORY ${PROJECT_SOURCE_DIR} PROPERTY VS_STARTUP_PROJECT remote_table) +endif() + +set(CMKR_TARGET remote_table) +qt_finalize_executable(${CMKR_TARGET}) + diff --git a/src/cross/cmake.toml b/src/cross/cmake.toml new file mode 100644 index 00000000..99562bc8 --- /dev/null +++ b/src/cross/cmake.toml @@ -0,0 +1,49 @@ +# Reference: https://build-cpp.github.io/cmkr/cmake-toml +[project] +name = "cross" +include-after = ["gui/Qt.cmake"] + +[subdir.gui] + +[subdir.vendor] + +[template.qt_executable] +type = "executable" +add-function = "qt_executable" +pass-sources = true + +[target.minidump] +type = "qt_executable" +sources = [ + "minidump/*.cpp", + "minidump/*.h", + "minidump/*.ui", + "minidump/*.qrc", +] +link-libraries = [ + "${QT_LIBRARIES}", + "widgets", + "cpp-httplib", +] +compile-features = ["cxx_std_17"] +cmake-after = """ +qt_finalize_executable(${CMKR_TARGET}) +""" + +[target.remote_table] +type = "qt_executable" +sources = [ + "remote_table/*.cpp", + "remote_table/*.h", + "remote_table/*.ui", + "remote_table/*.qrc", + "remote_table/json.hpp", +] +link-libraries = [ + "${QT_LIBRARIES}", + "widgets", +] +compile-features = ["cxx_std_17"] +cmake-after = """ +qt_finalize_executable(${CMKR_TARGET}) +""" diff --git a/src/cross/cmkr.cmake b/src/cross/cmkr.cmake new file mode 100644 index 00000000..bb7c522d --- /dev/null +++ b/src/cross/cmkr.cmake @@ -0,0 +1,253 @@ +include_guard() + +# Change these defaults to point to your infrastructure if desired +set(CMKR_REPO "https://github.com/build-cpp/cmkr" CACHE STRING "cmkr git repository" FORCE) +set(CMKR_TAG "v0.2.23" CACHE STRING "cmkr git tag (this needs to be available forever)" FORCE) +set(CMKR_COMMIT_HASH "" CACHE STRING "cmkr git commit hash (optional)" FORCE) + +# To bootstrap/generate a cmkr project: cmake -P cmkr.cmake +if(CMAKE_SCRIPT_MODE_FILE) + set(CMAKE_BINARY_DIR "${CMAKE_BINARY_DIR}/build") + set(CMAKE_CURRENT_BINARY_DIR "${CMAKE_BINARY_DIR}") + file(MAKE_DIRECTORY "${CMAKE_BINARY_DIR}") +endif() + +# Set these from the command line to customize for development/debugging purposes +set(CMKR_EXECUTABLE "" CACHE FILEPATH "cmkr executable") +set(CMKR_SKIP_GENERATION OFF CACHE BOOL "skip automatic cmkr generation") +set(CMKR_BUILD_TYPE "Debug" CACHE STRING "cmkr build configuration") +mark_as_advanced(CMKR_REPO CMKR_TAG CMKR_COMMIT_HASH CMKR_EXECUTABLE CMKR_SKIP_GENERATION CMKR_BUILD_TYPE) + +# Disable cmkr if generation is disabled +if(DEFINED ENV{CI} OR CMKR_SKIP_GENERATION OR CMKR_BUILD_SKIP_GENERATION) + message(STATUS "[cmkr] Skipping automatic cmkr generation") + unset(CMKR_BUILD_SKIP_GENERATION CACHE) + macro(cmkr) + endmacro() + return() +endif() + +# Disable cmkr if no cmake.toml file is found +if(NOT CMAKE_SCRIPT_MODE_FILE AND NOT EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/cmake.toml") + message(AUTHOR_WARNING "[cmkr] Not found: ${CMAKE_CURRENT_SOURCE_DIR}/cmake.toml") + macro(cmkr) + endmacro() + return() +endif() + +# Convert a Windows native path to CMake path +if(CMKR_EXECUTABLE MATCHES "\\\\") + string(REPLACE "\\" "/" CMKR_EXECUTABLE_CMAKE "${CMKR_EXECUTABLE}") + set(CMKR_EXECUTABLE "${CMKR_EXECUTABLE_CMAKE}" CACHE FILEPATH "" FORCE) + unset(CMKR_EXECUTABLE_CMAKE) +endif() + +# Helper macro to execute a process (COMMAND_ERROR_IS_FATAL ANY is 3.19 and higher) +function(cmkr_exec) + execute_process(COMMAND ${ARGV} RESULT_VARIABLE CMKR_EXEC_RESULT) + if(NOT CMKR_EXEC_RESULT EQUAL 0) + message(FATAL_ERROR "cmkr_exec(${ARGV}) failed (exit code ${CMKR_EXEC_RESULT})") + endif() +endfunction() + +# Windows-specific hack (CMAKE_EXECUTABLE_PREFIX is not set at the moment) +if(WIN32) + set(CMKR_EXECUTABLE_NAME "cmkr.exe") +else() + set(CMKR_EXECUTABLE_NAME "cmkr") +endif() + +# Use cached cmkr if found +if(DEFINED ENV{CMKR_CACHE}) + set(CMKR_DIRECTORY_PREFIX "$ENV{CMKR_CACHE}") + string(REPLACE "\\" "/" CMKR_DIRECTORY_PREFIX "${CMKR_DIRECTORY_PREFIX}") + if(NOT CMKR_DIRECTORY_PREFIX MATCHES "\\/$") + set(CMKR_DIRECTORY_PREFIX "${CMKR_DIRECTORY_PREFIX}/") + endif() + # Build in release mode for the cache + set(CMKR_BUILD_TYPE "Release") +else() + set(CMKR_DIRECTORY_PREFIX "${CMAKE_CURRENT_BINARY_DIR}/_cmkr_") +endif() +set(CMKR_DIRECTORY "${CMKR_DIRECTORY_PREFIX}${CMKR_TAG}") +set(CMKR_CACHED_EXECUTABLE "${CMKR_DIRECTORY}/bin/${CMKR_EXECUTABLE_NAME}") + +# Helper function to check if a string starts with a prefix +# Cannot use MATCHES, see: https://github.com/build-cpp/cmkr/issues/61 +function(cmkr_startswith str prefix result) + string(LENGTH "${prefix}" prefix_length) + string(LENGTH "${str}" str_length) + if(prefix_length LESS_EQUAL str_length) + string(SUBSTRING "${str}" 0 ${prefix_length} str_prefix) + if(prefix STREQUAL str_prefix) + set("${result}" ON PARENT_SCOPE) + return() + endif() + endif() + set("${result}" OFF PARENT_SCOPE) +endfunction() + +# Handle upgrading logic +if(CMKR_EXECUTABLE AND NOT CMKR_CACHED_EXECUTABLE STREQUAL CMKR_EXECUTABLE) + cmkr_startswith("${CMKR_EXECUTABLE}" "${CMAKE_CURRENT_BINARY_DIR}/_cmkr" CMKR_STARTSWITH_BUILD) + cmkr_startswith("${CMKR_EXECUTABLE}" "${CMKR_DIRECTORY_PREFIX}" CMKR_STARTSWITH_CACHE) + if(CMKR_STARTSWITH_BUILD) + if(DEFINED ENV{CMKR_CACHE}) + message(AUTHOR_WARNING "[cmkr] Switching to cached cmkr: '${CMKR_CACHED_EXECUTABLE}'") + if(EXISTS "${CMKR_CACHED_EXECUTABLE}") + set(CMKR_EXECUTABLE "${CMKR_CACHED_EXECUTABLE}" CACHE FILEPATH "Full path to cmkr executable" FORCE) + else() + unset(CMKR_EXECUTABLE CACHE) + endif() + else() + message(AUTHOR_WARNING "[cmkr] Upgrading '${CMKR_EXECUTABLE}' to '${CMKR_CACHED_EXECUTABLE}'") + unset(CMKR_EXECUTABLE CACHE) + endif() + elseif(DEFINED ENV{CMKR_CACHE} AND CMKR_STARTSWITH_CACHE) + message(AUTHOR_WARNING "[cmkr] Upgrading cached '${CMKR_EXECUTABLE}' to '${CMKR_CACHED_EXECUTABLE}'") + unset(CMKR_EXECUTABLE CACHE) + endif() +endif() + +if(CMKR_EXECUTABLE AND EXISTS "${CMKR_EXECUTABLE}") + message(VERBOSE "[cmkr] Found cmkr: '${CMKR_EXECUTABLE}'") +elseif(CMKR_EXECUTABLE AND NOT CMKR_EXECUTABLE STREQUAL CMKR_CACHED_EXECUTABLE) + message(FATAL_ERROR "[cmkr] '${CMKR_EXECUTABLE}' not found") +elseif(NOT CMKR_EXECUTABLE AND EXISTS "${CMKR_CACHED_EXECUTABLE}") + set(CMKR_EXECUTABLE "${CMKR_CACHED_EXECUTABLE}" CACHE FILEPATH "Full path to cmkr executable" FORCE) + message(STATUS "[cmkr] Found cached cmkr: '${CMKR_EXECUTABLE}'") +else() + set(CMKR_EXECUTABLE "${CMKR_CACHED_EXECUTABLE}" CACHE FILEPATH "Full path to cmkr executable" FORCE) + message(VERBOSE "[cmkr] Bootstrapping '${CMKR_EXECUTABLE}'") + + message(STATUS "[cmkr] Fetching cmkr...") + if(EXISTS "${CMKR_DIRECTORY}") + cmkr_exec("${CMAKE_COMMAND}" -E rm -rf "${CMKR_DIRECTORY}") + endif() + find_package(Git QUIET REQUIRED) + cmkr_exec("${GIT_EXECUTABLE}" + clone + --config advice.detachedHead=false + --branch ${CMKR_TAG} + --depth 1 + ${CMKR_REPO} + "${CMKR_DIRECTORY}" + ) + if(CMKR_COMMIT_HASH) + execute_process( + COMMAND "${GIT_EXECUTABLE}" checkout -q "${CMKR_COMMIT_HASH}" + RESULT_VARIABLE CMKR_EXEC_RESULT + WORKING_DIRECTORY "${CMKR_DIRECTORY}" + ) + if(NOT CMKR_EXEC_RESULT EQUAL 0) + message(FATAL_ERROR "Tag '${CMKR_TAG}' hash is not '${CMKR_COMMIT_HASH}'") + endif() + endif() + message(STATUS "[cmkr] Building cmkr (using system compiler)...") + cmkr_exec("${CMAKE_COMMAND}" + --no-warn-unused-cli + "${CMKR_DIRECTORY}" + "-B${CMKR_DIRECTORY}/build" + "-DCMAKE_BUILD_TYPE=${CMKR_BUILD_TYPE}" + "-DCMAKE_UNITY_BUILD=ON" + "-DCMAKE_INSTALL_PREFIX=${CMKR_DIRECTORY}" + "-DCMKR_GENERATE_DOCUMENTATION=OFF" + ) + cmkr_exec("${CMAKE_COMMAND}" + --build "${CMKR_DIRECTORY}/build" + --config "${CMKR_BUILD_TYPE}" + --parallel + ) + cmkr_exec("${CMAKE_COMMAND}" + --install "${CMKR_DIRECTORY}/build" + --config "${CMKR_BUILD_TYPE}" + --prefix "${CMKR_DIRECTORY}" + --component cmkr + ) + if(NOT EXISTS ${CMKR_EXECUTABLE}) + message(FATAL_ERROR "[cmkr] Failed to bootstrap '${CMKR_EXECUTABLE}'") + endif() + cmkr_exec("${CMKR_EXECUTABLE}" version) + message(STATUS "[cmkr] Bootstrapped ${CMKR_EXECUTABLE}") +endif() +execute_process(COMMAND "${CMKR_EXECUTABLE}" version + RESULT_VARIABLE CMKR_EXEC_RESULT +) +if(NOT CMKR_EXEC_RESULT EQUAL 0) + message(FATAL_ERROR "[cmkr] Failed to get version, try clearing the cache and rebuilding") +endif() + +# Use cmkr.cmake as a script +if(CMAKE_SCRIPT_MODE_FILE) + if(NOT EXISTS "${CMAKE_SOURCE_DIR}/cmake.toml") + execute_process(COMMAND "${CMKR_EXECUTABLE}" init + RESULT_VARIABLE CMKR_EXEC_RESULT + ) + if(NOT CMKR_EXEC_RESULT EQUAL 0) + message(FATAL_ERROR "[cmkr] Failed to bootstrap cmkr project. Please report an issue: https://github.com/build-cpp/cmkr/issues/new") + else() + message(STATUS "[cmkr] Modify cmake.toml and then configure using: cmake -B build") + endif() + else() + execute_process(COMMAND "${CMKR_EXECUTABLE}" gen + RESULT_VARIABLE CMKR_EXEC_RESULT + ) + if(NOT CMKR_EXEC_RESULT EQUAL 0) + message(FATAL_ERROR "[cmkr] Failed to generate project.") + else() + message(STATUS "[cmkr] Configure using: cmake -B build") + endif() + endif() +endif() + +# This is the macro that contains black magic +macro(cmkr) + # When this macro is called from the generated file, fake some internal CMake variables + get_source_file_property(CMKR_CURRENT_LIST_FILE "${CMAKE_CURRENT_LIST_FILE}" CMKR_CURRENT_LIST_FILE) + if(CMKR_CURRENT_LIST_FILE) + set(CMAKE_CURRENT_LIST_FILE "${CMKR_CURRENT_LIST_FILE}") + get_filename_component(CMAKE_CURRENT_LIST_DIR "${CMAKE_CURRENT_LIST_FILE}" DIRECTORY) + endif() + + # File-based include guard (include_guard is not documented to work) + get_source_file_property(CMKR_INCLUDE_GUARD "${CMAKE_CURRENT_LIST_FILE}" CMKR_INCLUDE_GUARD) + if(NOT CMKR_INCLUDE_GUARD) + set_source_files_properties("${CMAKE_CURRENT_LIST_FILE}" PROPERTIES CMKR_INCLUDE_GUARD TRUE) + + file(SHA256 "${CMAKE_CURRENT_LIST_FILE}" CMKR_LIST_FILE_SHA256_PRE) + + # Generate CMakeLists.txt + cmkr_exec("${CMKR_EXECUTABLE}" gen + WORKING_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}" + ) + + file(SHA256 "${CMAKE_CURRENT_LIST_FILE}" CMKR_LIST_FILE_SHA256_POST) + + # Delete the temporary file if it was left for some reason + set(CMKR_TEMP_FILE "${CMAKE_CURRENT_SOURCE_DIR}/CMakerLists.txt") + if(EXISTS "${CMKR_TEMP_FILE}") + file(REMOVE "${CMKR_TEMP_FILE}") + endif() + + if(NOT CMKR_LIST_FILE_SHA256_PRE STREQUAL CMKR_LIST_FILE_SHA256_POST) + # Copy the now-generated CMakeLists.txt to CMakerLists.txt + # This is done because you cannot include() a file you are currently in + configure_file(CMakeLists.txt "${CMKR_TEMP_FILE}" COPYONLY) + + # Add the macro required for the hack at the start of the cmkr macro + set_source_files_properties("${CMKR_TEMP_FILE}" PROPERTIES + CMKR_CURRENT_LIST_FILE "${CMAKE_CURRENT_LIST_FILE}" + ) + + # 'Execute' the newly-generated CMakeLists.txt + include("${CMKR_TEMP_FILE}") + + # Delete the generated file + file(REMOVE "${CMKR_TEMP_FILE}") + + # Do not execute the rest of the original CMakeLists.txt + return() + endif() + # Resume executing the unmodified CMakeLists.txt + endif() +endmacro() diff --git a/src/cross/gui/Bridge.cpp b/src/cross/gui/Bridge.cpp new file mode 100644 index 00000000..aa896c96 --- /dev/null +++ b/src/cross/gui/Bridge.cpp @@ -0,0 +1,334 @@ +#include + +#include +#include + +#include "Bridge.h" + +#include "Types.h" +#include "Bridge.h" +#include + +struct InvalidMemoryProvider : MemoryProvider +{ + bool read(duint addr, void* dest, duint size) override + { + return false; + } + + bool getRange(duint addr, duint & base, duint & size) override + { + return false; + } + + bool isCodePtr(duint addr) override + { + return false; + } + + bool isValidPtr(duint addr) override + { + return false; + } +} gInvalidMemoryProvider; + +static MemoryProvider* gMemory = &gInvalidMemoryProvider; + +void DbgSetMemoryProvider(MemoryProvider* provider) +{ + gMemory = provider ? provider : &gInvalidMemoryProvider; +} + +// BRIDGE + +bool BridgeSettingGet(const char* section, const char* key, char* value) +{ + return false; +} + +bool BridgeSettingSet(const char* section, const char* key, const char* value) +{ + return false; +} + +bool BridgeSettingGetUint(const char* section, const char* key, duint* value) +{ + return false; +} + +bool BridgeSettingSetUint(const char* section, const char* key, duint value) +{ + return false; +} + +const wchar_t* BridgeUserDirectory() +{ + return L"."; +} + +void* BridgeAlloc(size_t size) +{ + return malloc(size); +} + +void BridgeFree(void* ptr) +{ + free(ptr); +} + +// DBG + +bool DbgIsDebugging() +{ + return true; +} + +DBGFUNCTIONS* DbgFunctions() +{ + static DBGFUNCTIONS* cache = [] + { + static DBGFUNCTIONS f; + f.GetTraceRecordHitCount = [](duint addr) -> duint + { + return 0; + }; + f.ModBaseFromAddr = [](duint addr) -> duint + { + return 0; + }; + f.ModNameFromAddr = [](duint addr, char* name, bool extension) + { + return false; + }; + f.StringFormatInline = [](char* dest, duint size, const char* format) + { + return false; + }; + f.MemIsCodePage = [](duint addr, bool refresh) + { + return gMemory->isCodePtr(addr); + }; + f.GetMnemonicBrief = [](const char* mnem, size_t resultSize, char* result) + { + *result = '\0'; + }; + f.ModRelocationAtAddr = [](duint addr, DBGRELOCATIONINFO * relocation) + { + return false; + }; + f.PatchGetEx = [](duint addr, DBGPATCHINFO * info) + { + return false; + }; + f.ValFromString = [](const char* expr, duint * value) + { + bool success = false; + *value = DbgEval(expr, &success); + return success; + }; + f.ModGetParty = [](duint addr) + { + return 0; + }; + f.PatchInRange = [](duint start, duint end) + { + return false; + }; + f.MemPatch = [](duint start, const unsigned char* data, duint size) + { + return false; + }; + return &f; + }(); + return cache; +} + +bool DbgGetLabelAt(duint addr, SEGTYPE seg, char* label) +{ + return false; +} + +bool DbgGetModuleAt(duint addr, char* module) +{ + return false; +} + +bool DbgGetCommentAt(duint addr, char* comment) +{ + return false; +} + +bool DbgGetBookmarkAt(duint addr) +{ + return false; +} + +BPXTYPE DbgGetBpxTypeAt(duint addr) +{ + return bp_none; +} + +bool DbgMemIsValidReadPtr(duint addr) +{ + return gMemory->isValidPtr(addr); +} + +bool DbgGetStringAt(duint addr, char* str) +{ + return false; +} + +bool DbgEval(const char* expr, bool* success) +{ + return false; +} + +duint DbgValFromString(const char* expr) +{ + duint result = 0; + if(!DbgEval(expr)) + result = 0; + return result; +} + +bool DbgCmdExec(const char* cmd) +{ + printf("DbgCmdExec(\"%s\")\n", cmd); + return false; +} + +bool DbgCmdExecDirect(const char* cmd) +{ + printf("DbgCmdExecDirect(\"%s\")\n", cmd); + return false; +} + +bool DbgCmdExec(const QString & cmd) +{ + return DbgCmdExec(cmd.toUtf8().constData()); +} + +bool DbgCmdExecDirect(const QString & cmd) +{ + return DbgCmdExecDirect(cmd.toUtf8().constData()); +} + +duint DbgMemFindBaseAddr(duint addr, duint* size) +{ + duint rangeBase = 0; + duint rangeSize = 0; + if(!gMemory->getRange(addr, rangeBase, rangeSize)) + return 0; + + if(size != nullptr) + *size = rangeSize; + + return rangeBase; +} + +bool DbgMemRead(duint addr, void* dest, size_t size) +{ + return gMemory->read(addr, dest, size); +} + +FUNCTYPE DbgGetFunctionTypeAt(duint addr) +{ + return FUNC_NONE; +} + +XREFTYPE DbgGetXrefTypeAt(duint addr) +{ + return XREF_NONE; +} + +ARGTYPE DbgGetArgTypeAt(duint addr) +{ + return ARG_NONE; +} + +LOOPTYPE DbgGetLoopTypeAt(duint addr, int depth) +{ + return LOOP_NONE; +} + +duint DbgGetBranchDestination(duint addr) +{ + uint8_t data[MAX_DISASM_BUFFER]; + if(!DbgMemRead(addr, data, sizeof(data))) + return 0; + Zydis zydis(true); // TODO: architecture + if(!zydis.Disassemble(addr, data)) + return 0; + return zydis.BranchDestination(); +} + +bool DbgIsJumpGoingToExecute(duint addr) +{ + return false; // TODO +} + +bool DbgXrefGet(duint addr, XREF_INFO* info) +{ + return false; +} + +void DbgReleaseEncodeTypeBuffer(void* buffer) +{ + BridgeFree(buffer); +} + +void* DbgGetEncodeTypeBuffer(duint addr, duint* size) +{ + return nullptr; +} + +bool DbgSetEncodeType(duint addr, duint size, ENCODETYPE type) +{ + return false; +} + +void DbgDelEncodeTypeRange(duint start, duint end) +{ +} + +void DbgDelEncodeTypeSegment(duint start) +{ +} + +// GUI + +void GuiExecuteOnGuiThreadEx(GuiCallback callback, void* data) +{ + // TODO: force schedule on the GUI thread + callback(data); +} + +void GuiAddLogMessage(const char* msg) +{ + Bridge::getBridge()->addMsgToLog(msg); +} + +void GuiUpdateAllViews() +{ + Bridge::getBridge()->repaintTableView(); +} + +void GuiUpdatePatches() +{ +} + +Bridge* Bridge::getBridge() +{ + static Bridge i; + return &i; +} + +void Bridge::CopyToClipboard(const QString & str) +{ + QGuiApplication::clipboard()->setText(str); +} + +void Bridge::addMsgToLog(const QByteArray & bytes) +{ + printf("addMsgToLog: %s\n", bytes.data()); +} diff --git a/src/cross/gui/Bridge.h b/src/cross/gui/Bridge.h new file mode 100644 index 00000000..46387c21 --- /dev/null +++ b/src/cross/gui/Bridge.h @@ -0,0 +1,172 @@ +#pragma once + +#include +#include +#include + +#include "Types.h" + +#define MAX_SETTING_SIZE 4096 + +bool BridgeSettingGet(const char* section, const char* key, char* value); +bool BridgeSettingSet(const char* section, const char* key, const char* value); +bool BridgeSettingGetUint(const char* section, const char* key, duint* value); +bool BridgeSettingSetUint(const char* section, const char* key, duint value); +const wchar_t* BridgeUserDirectory(); +void* BridgeAlloc(size_t size); +void BridgeFree(void* ptr); + +#define MAX_LABEL_SIZE 256 +#define MAX_MODULE_SIZE 256 +#define MAX_COMMENT_SIZE 256 +#define MAX_STRING_SIZE 2048 + +enum SEGTYPE +{ + SEG_DEFAULT, + SEG_ES, + SEG_DS, + SEG_FS, + SEG_GS, + SEG_CS, + SEG_SS, +}; + +enum BPXTYPE +{ + bp_none, + bp_normal, + bp_hardware, + bp_memory, +}; + +typedef enum +{ + FUNC_NONE, + FUNC_BEGIN, + FUNC_MIDDLE, + FUNC_END, + FUNC_SINGLE +} FUNCTYPE; + +typedef enum +{ + LOOP_NONE, + LOOP_BEGIN, + LOOP_MIDDLE, + LOOP_ENTRY, + LOOP_END, + LOOP_SINGLE +} LOOPTYPE; + +typedef enum +{ + ARG_NONE, + ARG_BEGIN, + ARG_MIDDLE, + ARG_END, + ARG_SINGLE +} ARGTYPE; + +typedef struct +{ + uint32_t rva; + uint8_t type; + uint16_t size; +} DBGRELOCATIONINFO; + +typedef struct +{ + char mod[MAX_MODULE_SIZE]; + duint addr; + unsigned char oldbyte; + unsigned char newbyte; +} DBGPATCHINFO; + +struct DBGFUNCTIONS +{ + duint(*GetTraceRecordHitCount)(duint addr); + duint(*ModBaseFromAddr)(duint addr); + bool (*ModNameFromAddr)(duint base, char* name, bool extension); + bool (*StringFormatInline)(char* dest, duint size, const char* format); + bool (*MemIsCodePage)(duint addr, bool refresh); + void (*GetMnemonicBrief)(const char* mnem, size_t resultSize, char* result); + bool (*ModRelocationAtAddr)(duint addr, DBGRELOCATIONINFO* relocation); + bool (*PatchGetEx)(duint addr, DBGPATCHINFO* info); + bool (*ValFromString)(const char* expr, duint* value); + int (*ModGetParty)(duint addr); + bool (*PatchInRange)(duint start, duint end); + bool (*MemPatch)(duint start, const unsigned char* data, duint size); +}; + +struct MemoryProvider +{ + virtual ~MemoryProvider() = default; + virtual bool read(duint addr, void* dest, duint size) = 0; + virtual bool getRange(duint addr, duint & base, duint & size) = 0; + virtual bool isCodePtr(duint addr) = 0; + virtual bool isValidPtr(duint addr) = 0; +}; + +void DbgSetMemoryProvider(MemoryProvider* provider); + +bool DbgIsDebugging(); +DBGFUNCTIONS* DbgFunctions(); +bool DbgGetLabelAt(duint addr, SEGTYPE seg, char* label); +bool DbgGetModuleAt(duint addr, char* module); +bool DbgGetCommentAt(duint addr, char* comment); +bool DbgGetBookmarkAt(duint addr); +BPXTYPE DbgGetBpxTypeAt(duint addr); +bool DbgMemIsValidReadPtr(duint addr); +bool DbgGetStringAt(duint addr, char* str); +bool DbgEval(const char* expr, bool* success = nullptr); +duint DbgValFromString(const char* expr); +bool DbgCmdExec(const char* cmd); +bool DbgCmdExecDirect(const char* cmd); +duint DbgMemFindBaseAddr(duint addr, duint* size); +bool DbgMemRead(duint addr, void* dest, size_t size); +FUNCTYPE DbgGetFunctionTypeAt(duint addr); +XREFTYPE DbgGetXrefTypeAt(duint addr); +ARGTYPE DbgGetArgTypeAt(duint addr); +LOOPTYPE DbgGetLoopTypeAt(duint addr, int depth); +duint DbgGetBranchDestination(duint addr); +bool DbgIsJumpGoingToExecute(duint addr); +bool DbgXrefGet(duint addr, XREF_INFO* info); +void DbgReleaseEncodeTypeBuffer(void* buffer); +void* DbgGetEncodeTypeBuffer(duint addr, duint* size); +bool DbgSetEncodeType(duint addr, duint size, ENCODETYPE type); +void DbgDelEncodeTypeRange(duint start, duint end); +void DbgDelEncodeTypeSegment(duint start); + +using GuiCallback = void(*)(void*); + +void GuiExecuteOnGuiThreadEx(GuiCallback callback, void* data); +void GuiAddLogMessage(const char* msg); +void GuiUpdateAllViews(); +void GuiUpdatePatches(); + +// QString helpers +bool DbgCmdExec(const QString & cmd); +bool DbgCmdExecDirect(const QString & cmd); + +class Bridge : public QObject +{ + Q_OBJECT + Bridge() = default; + +signals: + void close(); + void repaintTableView(); + void updateDump(); + void updateDisassembly(); + void dbgStateChanged(DBGSTATE state); + +public: + static Bridge* getBridge(); + static void CopyToClipboard(const QString & str); + + void addMsgToLog(const QByteArray & bytes); + + duint mLastCip = 0; + bool mIsRunning = true; +}; diff --git a/src/cross/gui/CMakeLists.txt b/src/cross/gui/CMakeLists.txt new file mode 100644 index 00000000..10d4a13b --- /dev/null +++ b/src/cross/gui/CMakeLists.txt @@ -0,0 +1,100 @@ +set(widgets_SOURCE_DIR "${CMAKE_CURRENT_SOURCE_DIR}/../../gui/Src") + +add_subdirectory( + ${CMAKE_CURRENT_SOURCE_DIR}/../../zydis_wrapper + ${CMAKE_CURRENT_BINARY_DIR}/zydis_wrapper +) + +include(Qt.cmake) + +set(hook_SOURCES + ${CMAKE_CURRENT_SOURCE_DIR}/Bridge.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/Bridge.h + ${CMAKE_CURRENT_SOURCE_DIR}/Configuration.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/Configuration.h + ${CMAKE_CURRENT_SOURCE_DIR}/MagicMenu.h + ${CMAKE_CURRENT_SOURCE_DIR}/MiscUtil.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/MiscUtil.h + ${CMAKE_CURRENT_SOURCE_DIR}/StringUtil.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/StringUtil.h + ${CMAKE_CURRENT_SOURCE_DIR}/Types.h + ${CMAKE_CURRENT_SOURCE_DIR}/Imports.h +) + +set(widgets_SOURCES + ${widgets_SOURCE_DIR}/BasicView/AbstractStdTable.cpp + ${widgets_SOURCE_DIR}/BasicView/AbstractStdTable.h + ${widgets_SOURCE_DIR}/BasicView/AbstractTableView.cpp + ${widgets_SOURCE_DIR}/BasicView/AbstractTableView.h + ${widgets_SOURCE_DIR}/BasicView/Disassembly.cpp + ${widgets_SOURCE_DIR}/BasicView/Disassembly.h + ${widgets_SOURCE_DIR}/BasicView/HexDump.cpp + ${widgets_SOURCE_DIR}/BasicView/HexDump.h + ${widgets_SOURCE_DIR}/BasicView/HistoryLineEdit.cpp + ${widgets_SOURCE_DIR}/BasicView/HistoryLineEdit.h + ${widgets_SOURCE_DIR}/BasicView/StdTable.cpp + ${widgets_SOURCE_DIR}/BasicView/StdTable.h + ${widgets_SOURCE_DIR}/Disassembler/Architecture.cpp + ${widgets_SOURCE_DIR}/Disassembler/Architecture.h + ${widgets_SOURCE_DIR}/Disassembler/QZydis.cpp + ${widgets_SOURCE_DIR}/Disassembler/QZydis.h + ${widgets_SOURCE_DIR}/Disassembler/ZydisTokenizer.cpp + ${widgets_SOURCE_DIR}/Disassembler/ZydisTokenizer.h + ${widgets_SOURCE_DIR}/Gui/BrowseDialog.cpp + ${widgets_SOURCE_DIR}/Gui/BrowseDialog.h + ${widgets_SOURCE_DIR}/Gui/BrowseDialog.ui + ${widgets_SOURCE_DIR}/Gui/ColumnReorderDialog.cpp + ${widgets_SOURCE_DIR}/Gui/ColumnReorderDialog.h + ${widgets_SOURCE_DIR}/Gui/ColumnReorderDialog.ui + ${widgets_SOURCE_DIR}/Gui/ComboBoxDialog.cpp + ${widgets_SOURCE_DIR}/Gui/ComboBoxDialog.h + ${widgets_SOURCE_DIR}/Gui/ComboBoxDialog.ui + ${widgets_SOURCE_DIR}/Gui/DisassemblyPopup.cpp + ${widgets_SOURCE_DIR}/Gui/DisassemblyPopup.h + ${widgets_SOURCE_DIR}/Gui/LineEditDialog.cpp + ${widgets_SOURCE_DIR}/Gui/LineEditDialog.h + ${widgets_SOURCE_DIR}/Gui/LineEditDialog.ui + ${widgets_SOURCE_DIR}/Memory/MemoryPage.cpp + ${widgets_SOURCE_DIR}/Memory/MemoryPage.h + ${widgets_SOURCE_DIR}/Utils/ActionHelpers.h + ${widgets_SOURCE_DIR}/Utils/CachedFontMetrics.h + ${widgets_SOURCE_DIR}/Utils/CodeFolding.cpp + ${widgets_SOURCE_DIR}/Utils/CodeFolding.h + ${widgets_SOURCE_DIR}/Utils/EncodeMap.cpp + ${widgets_SOURCE_DIR}/Utils/EncodeMap.h + ${widgets_SOURCE_DIR}/Utils/MenuBuilder.cpp + ${widgets_SOURCE_DIR}/Utils/MenuBuilder.h + ${widgets_SOURCE_DIR}/Utils/MethodInvoker.h + ${widgets_SOURCE_DIR}/Utils/RichTextPainter.cpp + ${widgets_SOURCE_DIR}/Utils/RichTextPainter.h + ${widgets_SOURCE_DIR}/Utils/VaHistory.h +) + +include_directories(BEFORE ${CMAKE_CURRENT_SOURCE_DIR}) + +add_library(widgets STATIC + ${hook_SOURCES} + ${widgets_SOURCES} +) + +target_include_directories(widgets PUBLIC + ${CMAKE_CURRENT_SOURCE_DIR} + ${widgets_SOURCE_DIR} +) + +source_group(TREE ${widgets_SOURCE_DIR} FILES ${widgets_SOURCES}) +source_group(TREE ${CMAKE_CURRENT_SOURCE_DIR} PREFIX hook FILES ${hook_SOURCES}) + +target_compile_definitions(widgets PRIVATE + QT_NO_DEPRECATED_WARNINGS +) + +target_link_libraries(widgets PUBLIC + ${QT_LIBRARIES} + zydis_wrapper +) + +# https://doc.qt.io/qt-6/wasm.html#asyncify +if(EMSCRIPTEN) + #target_link_options(${CMKR_TARGET} PUBLIC -sASYNCIFY -Os) +endif() \ No newline at end of file diff --git a/src/cross/gui/Configuration.cpp b/src/cross/gui/Configuration.cpp new file mode 100644 index 00000000..a30ee53e --- /dev/null +++ b/src/cross/gui/Configuration.cpp @@ -0,0 +1,1226 @@ +#include "Configuration.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "Bridge.h" + +Configuration* Configuration::mPtr = nullptr; + +inline void insertMenuBuilderBools(QMap* config, const char* id, size_t count) +{ + for(size_t i = 0; i < count; i++) + config->insert(QString("Menu%1Hidden%2").arg(id).arg(i), false); +} + +inline static void addWindowPosConfig(QMap & guiUint, const char* windowName) +{ + QString n(windowName); + guiUint.insert(n + "X", 0); + guiUint.insert(n + "Y", 0); +} + +Configuration::Configuration() : QObject(), noMoreMsgbox(false) +{ + mPtr = this; + //setup default color map + defaultColors.clear(); + defaultColors.insert("AbstractTableViewSeparatorColor", QColor("#808080")); + defaultColors.insert("AbstractTableViewBackgroundColor", QColor("#FFF8F0")); + defaultColors.insert("AbstractTableViewTextColor", QColor("#000000")); + defaultColors.insert("AbstractTableViewHeaderTextColor", QColor("#000000")); + defaultColors.insert("AbstractTableViewHeaderBackgroundColor", QColor("#C0C0C0")); + defaultColors.insert("AbstractTableViewSelectionColor", QColor("#C0C0C0")); + + defaultColors.insert("DisassemblyCipColor", QColor("#FFFFFF")); + defaultColors.insert("DisassemblyCipBackgroundColor", QColor("#000000")); + defaultColors.insert("DisassemblyBreakpointColor", QColor("#000000")); + defaultColors.insert("DisassemblyBreakpointBackgroundColor", QColor("#FF0000")); + defaultColors.insert("DisassemblyHardwareBreakpointColor", QColor("#000000")); + defaultColors.insert("DisassemblyHardwareBreakpointBackgroundColor", Qt::transparent); + defaultColors.insert("DisassemblyBookmarkColor", QColor("#000000")); + defaultColors.insert("DisassemblyBookmarkBackgroundColor", QColor("#FEE970")); + defaultColors.insert("DisassemblyLabelColor", QColor("#FF0000")); + defaultColors.insert("DisassemblyLabelBackgroundColor", Qt::transparent); + defaultColors.insert("DisassemblyBackgroundColor", QColor("#FFF8F0")); + defaultColors.insert("DisassemblySelectionColor", QColor("#C0C0C0")); + defaultColors.insert("DisassemblyTracedBackgroundColor", QColor("#C0FFC0")); + defaultColors.insert("DisassemblyAddressColor", QColor("#808080")); + defaultColors.insert("DisassemblyAddressBackgroundColor", Qt::transparent); + defaultColors.insert("DisassemblySelectedAddressColor", QColor("#000000")); + defaultColors.insert("DisassemblySelectedAddressBackgroundColor", Qt::transparent); + defaultColors.insert("DisassemblyConditionalJumpLineTrueColor", QColor("#FF0000")); + defaultColors.insert("DisassemblyConditionalJumpLineFalseColor", QColor("#808080")); + defaultColors.insert("DisassemblyUnconditionalJumpLineColor", QColor("#FF0000")); + defaultColors.insert("DisassemblyBytesColor", QColor("#000000")); + defaultColors.insert("DisassemblyBytesBackgroundColor", Qt::transparent); + defaultColors.insert("DisassemblyModifiedBytesColor", QColor("#FF0000")); + defaultColors.insert("DisassemblyModifiedBytesBackgroundColor", Qt::transparent); + defaultColors.insert("DisassemblyRestoredBytesColor", QColor("#808080")); + defaultColors.insert("DisassemblyRestoredBytesBackgroundColor", Qt::transparent); + defaultColors.insert("DisassemblyRelocationUnderlineColor", QColor("#000000")); + defaultColors.insert("DisassemblyCommentColor", QColor("#000000")); + defaultColors.insert("DisassemblyCommentBackgroundColor", Qt::transparent); + defaultColors.insert("DisassemblyAutoCommentColor", QColor("#AA5500")); + defaultColors.insert("DisassemblyAutoCommentBackgroundColor", Qt::transparent); + defaultColors.insert("DisassemblyMnemonicBriefColor", QColor("#717171")); + defaultColors.insert("DisassemblyMnemonicBriefBackgroundColor", Qt::transparent); + defaultColors.insert("DisassemblyFunctionColor", QColor("#000000")); + defaultColors.insert("DisassemblyLoopColor", QColor("#000000")); + + defaultColors.insert("SideBarBackgroundColor", QColor("#FFF8F0")); + defaultColors.insert("SideBarCipLabelColor", QColor("#FFFFFF")); + defaultColors.insert("SideBarCipLabelBackgroundColor", QColor("#4040FF")); + defaultColors.insert("SideBarBulletColor", QColor("#808080")); + defaultColors.insert("SideBarBulletBreakpointColor", QColor("#FF0000")); + defaultColors.insert("SideBarBulletDisabledBreakpointColor", QColor("#00AA00")); + defaultColors.insert("SideBarBulletBookmarkColor", QColor("#FEE970")); + defaultColors.insert("SideBarCheckBoxForeColor", QColor("#000000")); + defaultColors.insert("SideBarCheckBoxBackColor", QColor("#FFFFFF")); + defaultColors.insert("SideBarConditionalJumpLineTrueColor", QColor("#FF0000")); + defaultColors.insert("SideBarConditionalJumpLineTrueBackwardsColor", QColor("#FF0000")); + defaultColors.insert("SideBarConditionalJumpLineFalseColor", QColor("#00BBFF")); + defaultColors.insert("SideBarConditionalJumpLineFalseBackwardsColor", QColor("#FFA500")); + defaultColors.insert("SideBarUnconditionalJumpLineTrueColor", QColor("#FF0000")); + defaultColors.insert("SideBarUnconditionalJumpLineTrueBackwardsColor", QColor("#FF0000")); + defaultColors.insert("SideBarUnconditionalJumpLineFalseColor", QColor("#00BBFF")); + defaultColors.insert("SideBarUnconditionalJumpLineFalseBackwardsColor", QColor("#FFA500")); + + defaultColors.insert("RegistersBackgroundColor", QColor("#FFF8F0")); + defaultColors.insert("RegistersColor", QColor("#000000")); + defaultColors.insert("RegistersModifiedColor", QColor("#FF0000")); + defaultColors.insert("RegistersSelectionColor", QColor("#EEEEEE")); + defaultColors.insert("RegistersLabelColor", QColor("#000000")); + defaultColors.insert("RegistersArgumentLabelColor", Qt::darkGreen); + defaultColors.insert("RegistersExtraInfoColor", QColor("#000000")); + defaultColors.insert("RegistersHighlightReadColor", QColor("#00A000")); + defaultColors.insert("RegistersHighlightWriteColor", QColor("#B00000")); + defaultColors.insert("RegistersHighlightReadWriteColor", QColor("#808000")); + + defaultColors.insert("InstructionHighlightColor", QColor("#FFFFFF")); + defaultColors.insert("InstructionHighlightBackgroundColor", QColor("#CC0000")); + defaultColors.insert("InstructionCommaColor", QColor("#000000")); + defaultColors.insert("InstructionCommaBackgroundColor", Qt::transparent); + defaultColors.insert("InstructionPrefixColor", QColor("#000000")); + defaultColors.insert("InstructionPrefixBackgroundColor", Qt::transparent); + defaultColors.insert("InstructionUncategorizedColor", QColor("#000000")); + defaultColors.insert("InstructionUncategorizedBackgroundColor", Qt::transparent); + defaultColors.insert("InstructionAddressColor", QColor("#000000")); + defaultColors.insert("InstructionAddressBackgroundColor", QColor("#FFFF00")); + defaultColors.insert("InstructionValueColor", QColor("#828200")); + defaultColors.insert("InstructionValueBackgroundColor", Qt::transparent); + defaultColors.insert("InstructionMnemonicColor", QColor("#000000")); + defaultColors.insert("InstructionMnemonicBackgroundColor", Qt::transparent); + defaultColors.insert("InstructionPushPopColor", QColor("#0000FF")); + defaultColors.insert("InstructionPushPopBackgroundColor", Qt::transparent); + defaultColors.insert("InstructionCallColor", QColor("#000000")); + defaultColors.insert("InstructionCallBackgroundColor", QColor("#00FFFF")); + defaultColors.insert("InstructionRetColor", QColor("#000000")); + defaultColors.insert("InstructionRetBackgroundColor", QColor("#00FFFF")); + defaultColors.insert("InstructionConditionalJumpColor", QColor("#FF0000")); + defaultColors.insert("InstructionConditionalJumpBackgroundColor", QColor("#FFFF00")); + defaultColors.insert("InstructionUnconditionalJumpColor", QColor("#000000")); + defaultColors.insert("InstructionUnconditionalJumpBackgroundColor", QColor("#FFFF00")); + defaultColors.insert("InstructionUnusualColor", QColor("#000000")); + defaultColors.insert("InstructionUnusualBackgroundColor", QColor("#C00000")); + defaultColors.insert("InstructionNopColor", QColor("#808080")); + defaultColors.insert("InstructionNopBackgroundColor", Qt::transparent); + defaultColors.insert("InstructionFarColor", QColor("#000000")); + defaultColors.insert("InstructionFarBackgroundColor", Qt::transparent); + defaultColors.insert("InstructionInt3Color", QColor("#000000")); + defaultColors.insert("InstructionInt3BackgroundColor", Qt::transparent); + defaultColors.insert("InstructionMemorySizeColor", QColor("#000080")); + defaultColors.insert("InstructionMemorySizeBackgroundColor", Qt::transparent); + defaultColors.insert("InstructionMemorySegmentColor", QColor("#FF00FF")); + defaultColors.insert("InstructionMemorySegmentBackgroundColor", Qt::transparent); + defaultColors.insert("InstructionMemoryBracketsColor", QColor("#000000")); + defaultColors.insert("InstructionMemoryBracketsBackgroundColor", Qt::transparent); + defaultColors.insert("InstructionMemoryStackBracketsColor", QColor("#000000")); + defaultColors.insert("InstructionMemoryStackBracketsBackgroundColor", QColor("#00FFFF")); + defaultColors.insert("InstructionMemoryBaseRegisterColor", QColor("#B03434")); + defaultColors.insert("InstructionMemoryBaseRegisterBackgroundColor", Qt::transparent); + defaultColors.insert("InstructionMemoryIndexRegisterColor", QColor("#3838BC")); + defaultColors.insert("InstructionMemoryIndexRegisterBackgroundColor", Qt::transparent); + defaultColors.insert("InstructionMemoryScaleColor", QColor("#B30059")); + defaultColors.insert("InstructionMemoryScaleBackgroundColor", Qt::transparent); + defaultColors.insert("InstructionMemoryOperatorColor", QColor("#F27711")); + defaultColors.insert("InstructionMemoryOperatorBackgroundColor", Qt::transparent); + defaultColors.insert("InstructionGeneralRegisterColor", QColor("#008300")); + defaultColors.insert("InstructionGeneralRegisterBackgroundColor", Qt::transparent); + defaultColors.insert("InstructionFpuRegisterColor", QColor("#000080")); + defaultColors.insert("InstructionFpuRegisterBackgroundColor", Qt::transparent); + defaultColors.insert("InstructionMmxRegisterColor", QColor("#000080")); + defaultColors.insert("InstructionMmxRegisterBackgroundColor", Qt::transparent); + defaultColors.insert("InstructionXmmRegisterColor", QColor("#000080")); + defaultColors.insert("InstructionXmmRegisterBackgroundColor", Qt::transparent); + defaultColors.insert("InstructionYmmRegisterColor", QColor("#000080")); + defaultColors.insert("InstructionYmmRegisterBackgroundColor", Qt::transparent); + defaultColors.insert("InstructionZmmRegisterColor", QColor("#000080")); + defaultColors.insert("InstructionZmmRegisterBackgroundColor", Qt::transparent); + + defaultColors.insert("HexDumpTextColor", QColor("#000000")); + defaultColors.insert("HexDumpModifiedBytesColor", QColor("#FF0000")); + defaultColors.insert("HexDumpModifiedBytesBackgroundColor", Qt::transparent); + defaultColors.insert("HexDumpRestoredBytesColor", QColor("#808080")); + defaultColors.insert("HexDumpRestoredBytesBackgroundColor", Qt::transparent); + defaultColors.insert("HexDumpByte00Color", QColor("#008000")); + defaultColors.insert("HexDumpByte00BackgroundColor", Qt::transparent); + defaultColors.insert("HexDumpByte7FColor", QColor("#808000")); + defaultColors.insert("HexDumpByte7FBackgroundColor", Qt::transparent); + defaultColors.insert("HexDumpByteFFColor", QColor("#800000")); + defaultColors.insert("HexDumpByteFFBackgroundColor", Qt::transparent); + defaultColors.insert("HexDumpByteIsPrintColor", QColor("#800080")); + defaultColors.insert("HexDumpByteIsPrintBackgroundColor", Qt::transparent); + defaultColors.insert("HexDumpBackgroundColor", QColor("#FFF8F0")); + defaultColors.insert("HexDumpSelectionColor", QColor("#C0C0C0")); + defaultColors.insert("HexDumpAddressColor", QColor("#000000")); + defaultColors.insert("HexDumpAddressBackgroundColor", Qt::transparent); + defaultColors.insert("HexDumpLabelColor", QColor("#FF0000")); + defaultColors.insert("HexDumpLabelBackgroundColor", Qt::transparent); + defaultColors.insert("HexDumpUserModuleCodePointerHighlightColor", QColor("#00FF00")); + defaultColors.insert("HexDumpUserModuleDataPointerHighlightColor", QColor("#008000")); + defaultColors.insert("HexDumpSystemModuleCodePointerHighlightColor", QColor("#FF0000")); + defaultColors.insert("HexDumpSystemModuleDataPointerHighlightColor", QColor("#800000")); + defaultColors.insert("HexDumpUnknownCodePointerHighlightColor", QColor("#0000FF")); + defaultColors.insert("HexDumpUnknownDataPointerHighlightColor", QColor("#000080")); + + defaultColors.insert("StackTextColor", QColor("#000000")); + defaultColors.insert("StackInactiveTextColor", QColor("#808080")); + defaultColors.insert("StackBackgroundColor", QColor("#FFF8F0")); + defaultColors.insert("StackSelectionColor", QColor("#C0C0C0")); + defaultColors.insert("StackCspColor", QColor("#FFFFFF")); + defaultColors.insert("StackCspBackgroundColor", QColor("#000000")); + defaultColors.insert("StackAddressColor", QColor("#808080")); + defaultColors.insert("StackAddressBackgroundColor", Qt::transparent); + defaultColors.insert("StackSelectedAddressColor", QColor("#000000")); + defaultColors.insert("StackSelectedAddressBackgroundColor", Qt::transparent); + defaultColors.insert("StackLabelColor", QColor("#FF0000")); + defaultColors.insert("StackLabelBackgroundColor", Qt::transparent); + defaultColors.insert("StackReturnToColor", QColor("#FF0000")); + defaultColors.insert("StackSEHChainColor", QColor("#AE81FF")); + defaultColors.insert("StackFrameColor", QColor("#000000")); + defaultColors.insert("StackFrameSystemColor", QColor("#0000FF")); + + defaultColors.insert("HexEditTextColor", QColor("#000000")); + defaultColors.insert("HexEditWildcardColor", QColor("#FF0000")); + defaultColors.insert("HexEditBackgroundColor", QColor("#FFF8F0")); + defaultColors.insert("HexEditSelectionColor", QColor("#C0C0C0")); + + defaultColors.insert("GraphJmpColor", QColor("#0148FB")); + defaultColors.insert("GraphBrtrueColor", QColor("#387804")); + defaultColors.insert("GraphBrfalseColor", QColor("#ED4630")); + defaultColors.insert("GraphCurrentShadowColor", QColor("#473a3a")); + defaultColors.insert("GraphRetShadowColor", QColor("#900000")); + defaultColors.insert("GraphIndirectcallShadowColor", QColor("#008080")); + defaultColors.insert("GraphBackgroundColor", Qt::transparent); + defaultColors.insert("GraphNodeColor", QColor("#000000")); + defaultColors.insert("GraphNodeBackgroundColor", Qt::transparent); + defaultColors.insert("GraphCipColor", QColor("#000000")); + defaultColors.insert("GraphBreakpointColor", QColor("#FF0000")); + defaultColors.insert("GraphDisabledBreakpointColor", QColor("#00AA00")); + + defaultColors.insert("ThreadCurrentColor", QColor("#FFFFFF")); + defaultColors.insert("ThreadCurrentBackgroundColor", QColor("#000000")); + defaultColors.insert("WatchTriggeredColor", QColor("#FF0000")); + defaultColors.insert("WatchTriggeredBackgroundColor", QColor("#FFF8F0")); + defaultColors.insert("MemoryMapBreakpointColor", QColor("#000000")); + defaultColors.insert("MemoryMapBreakpointBackgroundColor", QColor("#FF0000")); + defaultColors.insert("MemoryMapCipColor", QColor("#FFFFFF")); + defaultColors.insert("MemoryMapCipBackgroundColor", QColor("#000000")); + defaultColors.insert("MemoryMapSectionTextColor", QColor("#8B671F")); + defaultColors.insert("SearchListViewHighlightColor", QColor("#FF0000")); + defaultColors.insert("SearchListViewHighlightBackgroundColor", Qt::transparent); + defaultColors.insert("StructTextColor", QColor("#000000")); + defaultColors.insert("StructBackgroundColor", QColor("#FFF8F0")); + defaultColors.insert("StructAlternateBackgroundColor", QColor("#DCD9CF")); + defaultColors.insert("LogLinkColor", QColor("#00CC00")); + defaultColors.insert("LogLinkBackgroundColor", Qt::transparent); + defaultColors.insert("BreakpointSummaryParenColor", Qt::red); + defaultColors.insert("BreakpointSummaryKeywordColor", QColor("#8B671F")); + defaultColors.insert("BreakpointSummaryStringColor", QColor("#008000")); + defaultColors.insert("PatchRelocatedByteHighlightColor", QColor("#0000DD")); + defaultColors.insert("SymbolUserTextColor", QColor("#000000")); + defaultColors.insert("SymbolSystemTextColor", QColor("#000000")); + defaultColors.insert("SymbolUnloadedTextColor", QColor("#000000")); + defaultColors.insert("SymbolLoadingTextColor", QColor("#8B671F")); + defaultColors.insert("SymbolLoadedTextColor", QColor("#008000")); + defaultColors.insert("BackgroundFlickerColor", QColor("#ff6961")); + defaultColors.insert("LinkColor", QColor("#0000ff")); + + //bool settings + QMap disassemblyBool; + disassemblyBool.insert("ArgumentSpaces", false); + disassemblyBool.insert("HidePointerSizes", false); + disassemblyBool.insert("HideNormalSegments", false); + disassemblyBool.insert("MemorySpaces", false); + disassemblyBool.insert("KeepSize", false); + disassemblyBool.insert("FillNOPs", false); + disassemblyBool.insert("Uppercase", false); + disassemblyBool.insert("FindCommandEntireBlock", false); + disassemblyBool.insert("OnlyCipAutoComments", false); + disassemblyBool.insert("TabbedMnemonic", false); + disassemblyBool.insert("LongDataInstruction", false); + disassemblyBool.insert("NoHighlightOperands", false); + disassemblyBool.insert("PermanentHighlightingMode", false); + disassemblyBool.insert("0xPrefixValues", false); + disassemblyBool.insert("NoBranchDisasmPreview", false); + disassemblyBool.insert("NoCurrentModuleText", false); + defaultBools.insert("Disassembler", disassemblyBool); + + QMap engineBool; + engineBool.insert("ListAllPages", false); + engineBool.insert("ShowSuspectedCallStack", false); + defaultBools.insert("Engine", engineBool); + + QMap miscBool; + miscBool.insert("TransparentExceptionStepping", true); + miscBool.insert("CheckForAntiCheatDrivers", true); + defaultBools.insert("Misc", miscBool); + + QMap guiBool; + guiBool.insert("FpuRegistersLittleEndian", false); + guiBool.insert("SaveColumnOrder", true); + guiBool.insert("NoCloseDialog", false); + guiBool.insert("PidTidInHex", false); + guiBool.insert("SidebarWatchLabels", true); + guiBool.insert("LoadSaveTabOrder", true); + guiBool.insert("ShowGraphRva", false); + guiBool.insert("GraphZoomMode", true); + guiBool.insert("ShowExitConfirmation", false); + guiBool.insert("DisableAutoComplete", false); + guiBool.insert("CaseSensitiveAutoComplete", false); + guiBool.insert("AutoRepeatOnEnter", false); + guiBool.insert("AutoFollowInStack", true); + guiBool.insert("EnableQtHighDpiScaling", true); + //Named menu settings + insertMenuBuilderBools(&guiBool, "CPUDisassembly", 50); //CPUDisassembly + insertMenuBuilderBools(&guiBool, "CPUDump", 50); //CPUDump + insertMenuBuilderBools(&guiBool, "WatchView", 50); //Watch + insertMenuBuilderBools(&guiBool, "CallStackView", 50); //CallStackView + insertMenuBuilderBools(&guiBool, "ThreadView", 50); //Thread + insertMenuBuilderBools(&guiBool, "CPUStack", 50); //Stack + insertMenuBuilderBools(&guiBool, "SourceView", 50); //Source + insertMenuBuilderBools(&guiBool, "DisassemblerGraphView", 50); //Graph + insertMenuBuilderBools(&guiBool, "XrefBrowseDialog", 50); //XrefBrowseDialog + insertMenuBuilderBools(&guiBool, "StructWidget", 50); //StructWidget + insertMenuBuilderBools(&guiBool, "File", 50); //Main Menu : File + insertMenuBuilderBools(&guiBool, "Debug", 50); //Main Menu : Debug + insertMenuBuilderBools(&guiBool, "Option", 50); //Main Menu : Option + //"Favourites" menu cannot be customized for item hiding. + insertMenuBuilderBools(&guiBool, "Help", 50); //Main Menu : Help + insertMenuBuilderBools(&guiBool, "View", 50); //Main Menu : View + defaultBools.insert("Gui", guiBool); + + QMap guiUint; + AbstractTableView::setupColumnConfigDefaultValue(guiUint, "CPUDisassembly", 4); + AbstractTableView::setupColumnConfigDefaultValue(guiUint, "CPUStack", 3); + for(int i = 1; i <= 5; i++) + AbstractTableView::setupColumnConfigDefaultValue(guiUint, QString("CPUDump%1").arg(i), 4); + AbstractTableView::setupColumnConfigDefaultValue(guiUint, "Watch1", 6); + AbstractTableView::setupColumnConfigDefaultValue(guiUint, "BreakpointsView", 7); + AbstractTableView::setupColumnConfigDefaultValue(guiUint, "MemoryMap", 8); + AbstractTableView::setupColumnConfigDefaultValue(guiUint, "CallStack", 7); + AbstractTableView::setupColumnConfigDefaultValue(guiUint, "SEH", 4); + AbstractTableView::setupColumnConfigDefaultValue(guiUint, "Script", 3); + AbstractTableView::setupColumnConfigDefaultValue(guiUint, "Thread", 14); + AbstractTableView::setupColumnConfigDefaultValue(guiUint, "Handle", 5); + AbstractTableView::setupColumnConfigDefaultValue(guiUint, "Window", 10); + AbstractTableView::setupColumnConfigDefaultValue(guiUint, "TcpConnection", 3); + AbstractTableView::setupColumnConfigDefaultValue(guiUint, "Privilege", 2); + AbstractTableView::setupColumnConfigDefaultValue(guiUint, "LocalVarsView", 3); + AbstractTableView::setupColumnConfigDefaultValue(guiUint, "Module", 5); + AbstractTableView::setupColumnConfigDefaultValue(guiUint, "Symbol", 5); + AbstractTableView::setupColumnConfigDefaultValue(guiUint, "SourceView", 4); + AbstractTableView::setupColumnConfigDefaultValue(guiUint, "Trace", 7); + guiUint.insert("SIMDRegistersDisplayMode", 0); + guiUint.insert("EditFloatRegisterDefaultMode", 0); + addWindowPosConfig(guiUint, "AssembleDialog"); + addWindowPosConfig(guiUint, "AttachDialog"); + addWindowPosConfig(guiUint, "GotoDialog"); + addWindowPosConfig(guiUint, "EditBreakpointDialog"); + addWindowPosConfig(guiUint, "BrowseDialog"); + addWindowPosConfig(guiUint, "FavouriteTools"); + addWindowPosConfig(guiUint, "HexEditDialog"); + addWindowPosConfig(guiUint, "WordEditDialog"); + addWindowPosConfig(guiUint, "SystemBreakpointScriptDialog"); + defaultUints.insert("Gui", guiUint); + + //uint settings + QMap hexdumpUint; + hexdumpUint.insert("DefaultView", 0); + hexdumpUint.insert("CopyDataType", 0); + defaultUints.insert("HexDump", hexdumpUint); + QMap hexdumpBool; + hexdumpBool.insert("KeepSize", false); + defaultBools.insert("HexDump", hexdumpBool); + + QMap disasmUint; + disasmUint.insert("MaxModuleSize", -1); + defaultUints.insert("Disassembler", disasmUint); + + QMap tabOrderUint; + int curTab = 0; + tabOrderUint.insert("CPUTab", curTab++); + tabOrderUint.insert("GraphTab", curTab++); + tabOrderUint.insert("LogTab", curTab++); + tabOrderUint.insert("NotesTab", curTab++); + tabOrderUint.insert("BreakpointsTab", curTab++); + tabOrderUint.insert("MemoryMapTab", curTab++); + tabOrderUint.insert("CallStackTab", curTab++); + tabOrderUint.insert("SEHTab", curTab++); + tabOrderUint.insert("ScriptTab", curTab++); + tabOrderUint.insert("SymbolsTab", curTab++); + tabOrderUint.insert("SourceTab", curTab++); + tabOrderUint.insert("ReferencesTab", curTab++); + tabOrderUint.insert("ThreadsTab", curTab++); + curTab++; // removed SnowmanTab + tabOrderUint.insert("HandlesTab", curTab++); + tabOrderUint.insert("TraceTab", curTab++); + defaultUints.insert("TabOrder", tabOrderUint); + + //font settings +#ifdef Q_OS_DARWIN + QFont font("Menlo", 13, QFont::Normal, false); +#elif defined(Q_OS_WIN) + QFont font("Lucida Console", 8, QFont::Normal, false); +#else + auto font = QFontDatabase::systemFont(QFontDatabase::FixedFont); + font.setPointSize(13); +#endif // Q_OS_DARWIN + defaultFonts.insert("AbstractTableView", font); + defaultFonts.insert("Disassembly", font); + defaultFonts.insert("HexDump", font); + defaultFonts.insert("Stack", font); + defaultFonts.insert("Registers", font); + defaultFonts.insert("HexEdit", font); + defaultFonts.insert("Application", QApplication::font()); + defaultFonts.insert("Log", font); + + // hotkeys settings + defaultShortcuts.insert("FileOpen", Shortcut({tr("File"), tr("Open")}, "F3", true)); + defaultShortcuts.insert("FileAttach", Shortcut({tr("File"), tr("Attach")}, "Alt+A", true)); + defaultShortcuts.insert("FileDetach", Shortcut({tr("File"), tr("Detach")}, "Ctrl+Alt+F2", true)); + defaultShortcuts.insert("FileDbsave", Shortcut({tr("File"), tr("Save database")}, "", true)); + defaultShortcuts.insert("FileDbrecovery", Shortcut({tr("File"), tr("Restore backup database")}, "", true)); + defaultShortcuts.insert("FileDbload", Shortcut({tr("File"), tr("Reload database")}, "", true)); + defaultShortcuts.insert("FileDbclear", Shortcut({tr("File"), tr("Clear database")}, "", true)); + defaultShortcuts.insert("FileImportDatabase", Shortcut({tr("File"), tr("Import database")}, "", true)); + defaultShortcuts.insert("FileExportDatabase", Shortcut({tr("File"), tr("Export database")}, "", true)); + defaultShortcuts.insert("FileRestartAdmin", Shortcut({tr("File"), tr("Restart as Admin")}, "", true)); + defaultShortcuts.insert("FileExit", Shortcut({tr("File"), tr("Exit")}, "Alt+X", true)); + + defaultShortcuts.insert("ViewCpu", Shortcut({tr("View"), tr("CPU")}, "Alt+C", true)); + defaultShortcuts.insert("ViewLog", Shortcut({tr("View"), tr("Log")}, "Alt+L", true)); + defaultShortcuts.insert("ViewBreakpoints", Shortcut({tr("View"), tr("Breakpoints")}, "Alt+B", true)); + defaultShortcuts.insert("ViewMemoryMap", Shortcut({tr("View"), tr("Memory Map")}, "Alt+M", true)); + defaultShortcuts.insert("ViewCallStack", Shortcut({tr("View"), tr("Call Stack")}, "Alt+K", true)); + defaultShortcuts.insert("ViewNotes", Shortcut({tr("View"), tr("Notes")}, "Alt+N", true)); + defaultShortcuts.insert("ViewSEHChain", Shortcut({tr("View"), tr("SEH")}, "", true)); + defaultShortcuts.insert("ViewScript", Shortcut({tr("View"), tr("Script")}, "Alt+S", true)); + defaultShortcuts.insert("ViewSymbolInfo", Shortcut({tr("View"), tr("Symbol Info")}, "Ctrl+Alt+S", true)); + defaultShortcuts.insert("ViewModules", Shortcut({tr("View"), tr("Modules")}, "Alt+E", true)); + defaultShortcuts.insert("ViewSource", Shortcut({tr("View"), tr("Source")}, "Ctrl+Shift+S", true)); + defaultShortcuts.insert("ViewReferences", Shortcut({tr("View"), tr("References")}, "Alt+R", true)); + defaultShortcuts.insert("ViewThreads", Shortcut({tr("View"), tr("Threads")}, "Alt+T", true)); + defaultShortcuts.insert("ViewPatches", Shortcut({tr("View"), tr("Patches")}, "Ctrl+P", true)); + defaultShortcuts.insert("ViewComments", Shortcut({tr("View"), tr("Comments")}, "Ctrl+Alt+C", true)); + defaultShortcuts.insert("ViewLabels", Shortcut({tr("View"), tr("Labels")}, "Ctrl+Alt+L", true)); + defaultShortcuts.insert("ViewBookmarks", Shortcut({tr("View"), tr("Bookmarks")}, "Ctrl+Alt+B", true)); + defaultShortcuts.insert("ViewFunctions", Shortcut({tr("View"), tr("Functions")}, "Ctrl+Alt+F", true)); + defaultShortcuts.insert("ViewVariables", Shortcut({tr("View"), tr("Variables")}, "", true)); + defaultShortcuts.insert("ViewHandles", Shortcut({tr("View"), tr("Handles")}, "", true)); + defaultShortcuts.insert("ViewGraph", Shortcut({tr("View"), tr("Graph")}, "Alt+G", true)); + defaultShortcuts.insert("ViewPreviousTab", Shortcut({tr("View"), tr("Previous Tab")}, "Alt+Left")); + defaultShortcuts.insert("ViewNextTab", Shortcut({tr("View"), tr("Next Tab")}, "Alt+Right")); + defaultShortcuts.insert("ViewPreviousHistory", Shortcut({tr("View"), tr("Previous View")}, "Ctrl+Shift+Tab")); + defaultShortcuts.insert("ViewNextHistory", Shortcut({tr("View"), tr("Next View")}, "Ctrl+Tab")); + defaultShortcuts.insert("ViewHideTab", Shortcut({tr("View"), tr("Hide Tab")}, "Ctrl+W")); + + defaultShortcuts.insert("DebugRun", Shortcut({tr("Debug"), tr("Run")}, "F9", true)); + defaultShortcuts.insert("DebugeRun", Shortcut({tr("Debug"), tr("Run (pass exception)")}, "Shift+F9", true)); + defaultShortcuts.insert("DebugseRun", Shortcut({tr("Debug"), tr("Run (swallow exception)")}, "Ctrl+Alt+Shift+F9", true)); + defaultShortcuts.insert("DebugRunSelection", Shortcut({tr("Debug"), tr("Run until selection")}, "F4", true)); + defaultShortcuts.insert("DebugRunExpression", Shortcut({tr("Debug"), tr("Run until expression")}, "Shift+F4", true)); + defaultShortcuts.insert("DebugPause", Shortcut({tr("Debug"), tr("Pause")}, "F12", true)); + defaultShortcuts.insert("DebugRestart", Shortcut({tr("Debug"), tr("Restart")}, "Ctrl+F2", true)); + defaultShortcuts.insert("DebugClose", Shortcut({tr("Debug"), tr("Close")}, "Alt+F2", true)); + defaultShortcuts.insert("DebugStepInto", Shortcut({tr("Debug"), tr("Step into")}, "F7", true)); + defaultShortcuts.insert("DebugeStepInto", Shortcut({tr("Debug"), tr("Step into (pass exception)")}, "Shift+F7", true)); + defaultShortcuts.insert("DebugseStepInto", Shortcut({tr("Debug"), tr("Step into (swallow exception)")}, "Ctrl+Alt+Shift+F7", true)); + defaultShortcuts.insert("DebugStepIntoSource", Shortcut({tr("Debug"), tr("Step into (source)")}, "F11", true)); + defaultShortcuts.insert("DebugStepOver", Shortcut({tr("Debug"), tr("Step over")}, "F8", true)); + defaultShortcuts.insert("DebugeStepOver", Shortcut({tr("Debug"), tr("Step over (pass exception)")}, "Shift+F8", true)); + defaultShortcuts.insert("DebugseStepOver", Shortcut({tr("Debug"), tr("Step over (swallow exception)")}, "Ctrl+Alt+Shift+F8", true)); + defaultShortcuts.insert("DebugStepOverSource", Shortcut({tr("Debug"), tr("Step over (source)")}, "F10", true)); + defaultShortcuts.insert("DebugRtr", Shortcut({tr("Debug"), tr("Execute till return")}, "Ctrl+F9", true)); + defaultShortcuts.insert("DebugeRtr", Shortcut({tr("Debug"), tr("Execute till return (pass exception)")}, "Ctrl+Shift+F9", true)); + defaultShortcuts.insert("DebugRtu", Shortcut({tr("Debug"), tr("Run to user code")}, "Alt+F9", true)); + defaultShortcuts.insert("DebugSkipNextInstruction", Shortcut({tr("Debug"), tr("Skip next instruction")}, "", true)); + defaultShortcuts.insert("DebugCommand", Shortcut({tr("Debug"), tr("Command")}, "Ctrl+Return", true)); + defaultShortcuts.insert("DebugTraceIntoConditional", Shortcut({tr("Debug"), tr("Trace into...")}, "Ctrl+Alt+F7", true)); + defaultShortcuts.insert("DebugTraceOverConditional", Shortcut({tr("Debug"), tr("Trace over...")}, "Ctrl+Alt+F8", true)); + defaultShortcuts.insert("DebugEnableTraceRecordBit", Shortcut({tr("Debug"), tr("Trace coverage"), tr("Bit")}, "", true)); + defaultShortcuts.insert("DebugTraceRecordNone", Shortcut({tr("Debug"), tr("Trace coverage"), tr("None")}, "", true)); + defaultShortcuts.insert("DebugInstrUndo", Shortcut({tr("Debug"), tr("Undo instruction")}, "Alt+U", true)); + defaultShortcuts.insert("DebugAnimateInto", Shortcut({tr("Debug"), tr("Animate into")}, "Ctrl+F7", true)); + defaultShortcuts.insert("DebugAnimateOver", Shortcut({tr("Debug"), tr("Animate over")}, "Ctrl+F8", true)); + defaultShortcuts.insert("DebugAnimateCommand", Shortcut({tr("Debug"), tr("Animate command")}, "", true)); + defaultShortcuts.insert("DebugTraceIntoIntoTracerecord", Shortcut({tr("Debug"), tr("Step into until reaching uncovered code")}, "", true)); + defaultShortcuts.insert("DebugTraceOverIntoTracerecord", Shortcut({tr("Debug"), tr("Step over until reaching uncovered code")}, "", true)); + defaultShortcuts.insert("DebugTraceIntoBeyondTracerecord", Shortcut({tr("Debug"), tr("Step into until reaching covered code")}, "", true)); + defaultShortcuts.insert("DebugTraceOverBeyondTracerecord", Shortcut({tr("Debug"), tr("Step over until reaching covered code")}, "", true)); + + defaultShortcuts.insert("PluginsScylla", Shortcut({tr("Plugins"), tr("Scylla")}, "Ctrl+I", true)); + + defaultShortcuts.insert("FavouritesManage", Shortcut({tr("Favourites"), tr("Manage Favourite Tools")}, "", true)); + + defaultShortcuts.insert("OptionsPreferences", Shortcut({tr("Options"), tr("Preferences")}, "", true)); + defaultShortcuts.insert("OptionsAppearance", Shortcut({tr("Options"), tr("Appearance")}, "", true)); + defaultShortcuts.insert("OptionsShortcuts", Shortcut({tr("Options"), tr("Hotkeys")}, "", true)); + defaultShortcuts.insert("OptionsTopmost", Shortcut({tr("Options"), tr("Topmost")}, "Ctrl+F5", true)); + defaultShortcuts.insert("OptionsReloadStylesheet", Shortcut({tr("Options"), tr("Reload style.css")}, "", true)); + + defaultShortcuts.insert("HelpAbout", Shortcut({tr("Help"), tr("About")}, "", true)); + defaultShortcuts.insert("HelpBlog", Shortcut({tr("Help"), tr("Blog")}, "", true)); + defaultShortcuts.insert("HelpDonate", Shortcut({tr("Help"), tr("Donate")}, "", true)); + defaultShortcuts.insert("HelpCalculator", Shortcut({tr("Help"), tr("Calculator")}, "?")); + defaultShortcuts.insert("HelpReportBug", Shortcut({tr("Help"), tr("Report Bug")}, "", true)); + defaultShortcuts.insert("HelpManual", Shortcut({tr("Help"), tr("Manual")}, "F1", true)); + defaultShortcuts.insert("HelpCrashDump", Shortcut({tr("Help"), tr("Generate Crash Dump")}, "", true)); + + defaultShortcuts.insert("ActionFindStrings", Shortcut({tr("Actions"), tr("Find Strings")}, "", true)); + defaultShortcuts.insert("ActionFindStringsModule", Shortcut({tr("Actions"), tr("Find Strings in Current Module")}, "Shift+D", true)); + defaultShortcuts.insert("ActionFindIntermodularCalls", Shortcut({tr("Actions"), tr("Find Intermodular Calls")}, "", true)); + defaultShortcuts.insert("ActionToggleBreakpoint", Shortcut({tr("Actions"), tr("Toggle Breakpoint")}, "F2")); + defaultShortcuts.insert("ActionEditBreakpoint", Shortcut({tr("Actions"), tr("Set Conditional Breakpoint")}, "Shift+F2")); + defaultShortcuts.insert("ActionToggleBookmark", Shortcut({tr("Actions"), tr("Toggle Bookmark")}, "Ctrl+D")); + defaultShortcuts.insert("ActionDeleteBreakpoint", Shortcut({tr("Actions"), tr("Delete Breakpoint")}, "Delete")); + defaultShortcuts.insert("ActionEnableDisableBreakpoint", Shortcut({tr("Actions"), tr("Enable/Disable Breakpoint")}, "Space")); + defaultShortcuts.insert("ActionResetHitCountBreakpoint", Shortcut({tr("Actions"), tr("Reset breakpoint hit count")})); + defaultShortcuts.insert("ActionEnableAllBreakpoints", Shortcut({tr("Actions"), tr("Enable all breakpoints")})); + defaultShortcuts.insert("ActionDisableAllBreakpoints", Shortcut({tr("Actions"), tr("Disable all breakpoints")})); + defaultShortcuts.insert("ActionRemoveAllBreakpoints", Shortcut({tr("Actions"), tr("Remove all breakpoints")})); + + defaultShortcuts.insert("ActionBinaryEdit", Shortcut({tr("Actions"), tr("Binary Edit")}, "Ctrl+E")); + defaultShortcuts.insert("ActionBinaryFill", Shortcut({tr("Actions"), tr("Binary Fill")}, "F")); + defaultShortcuts.insert("ActionBinaryFillNops", Shortcut({tr("Actions"), tr("Binary Fill NOPs")}, "Ctrl+9")); + defaultShortcuts.insert("ActionBinaryCopy", Shortcut({tr("Actions"), tr("Binary Copy")}, "Shift+C")); + defaultShortcuts.insert("ActionBinaryPaste", Shortcut({tr("Actions"), tr("Binary Paste")}, "Shift+V")); + defaultShortcuts.insert("ActionBinaryPasteIgnoreSize", Shortcut({tr("Actions"), tr("Binary Paste (Ignore Size)")}, "Ctrl+Shift+V")); + defaultShortcuts.insert("ActionBinarySave", Shortcut({tr("Actions"), tr("Binary Save")})); + defaultShortcuts.insert("ActionUndoSelection", Shortcut({tr("Actions"), tr("Undo Selection")}, "Ctrl+Backspace")); + defaultShortcuts.insert("ActionSetLabel", Shortcut({tr("Actions"), tr("Set Label")}, ":")); + defaultShortcuts.insert("ActionSetLabelOperand", Shortcut({tr("Actions"), tr("Set Label for the Operand")}, "Alt+;")); + defaultShortcuts.insert("ActionSetComment", Shortcut({tr("Actions"), tr("Set Comment")}, ";")); + defaultShortcuts.insert("ActionToggleFunction", Shortcut({tr("Actions"), tr("Toggle Function")}, "Shift+F")); + defaultShortcuts.insert("ActionAddLoop", Shortcut({tr("Actions"), tr("Add Loop")}, "Shift+L")); + defaultShortcuts.insert("ActionDeleteLoop", Shortcut({tr("Actions"), tr("Delete Loop")}, "Ctrl+Shift+L")); + defaultShortcuts.insert("ActionToggleArgument", Shortcut({tr("Actions"), tr("Toggle Argument")}, "Shift+A")); + defaultShortcuts.insert("ActionAssemble", Shortcut({tr("Actions"), tr("Assemble")}, "Space")); + defaultShortcuts.insert("ActionSetNewOriginHere", Shortcut({tr("Actions"), tr("Set EIP/RIP Here")}, "Ctrl+*")); + defaultShortcuts.insert("ActionGotoOrigin", Shortcut({tr("Actions"), tr("Goto Origin")}, "*")); + defaultShortcuts.insert("ActionGotoCBP", Shortcut({tr("Actions"), tr("Goto EBP/RBP")})); + defaultShortcuts.insert("ActionGotoPrevious", Shortcut({tr("Actions"), tr("Goto Previous")}, "-")); + defaultShortcuts.insert("ActionGotoNext", Shortcut({tr("Actions"), tr("Goto Next")}, "+")); + defaultShortcuts.insert("ActionGotoExpression", Shortcut({tr("Actions"), tr("Goto Expression")}, "Ctrl+G")); + defaultShortcuts.insert("ActionGotoStart", Shortcut({tr("Actions"), tr("Goto Start of Page")}, "Home")); + defaultShortcuts.insert("ActionGotoEnd", Shortcut({tr("Actions"), tr("Goto End of Page")}, "End")); + defaultShortcuts.insert("ActionGotoFunctionStart", Shortcut({tr("Actions"), tr("Goto Start of Function")}, "Ctrl+Home")); + defaultShortcuts.insert("ActionGotoFunctionEnd", Shortcut({tr("Actions"), tr("Goto End of Function")}, "Ctrl+End")); + defaultShortcuts.insert("ActionGotoFileOffset", Shortcut({tr("Actions"), tr("Goto File Offset")}, "Ctrl+Shift+G")); + defaultShortcuts.insert("ActionFindReferencesToSelectedAddress", Shortcut({tr("Actions"), tr("Find References to Selected Address")}, "Ctrl+R")); + defaultShortcuts.insert("ActionFindPattern", Shortcut({tr("Actions"), tr("Find Pattern")}, "Ctrl+B")); + defaultShortcuts.insert("ActionFindPatternInModule", Shortcut({tr("Actions"), tr("Find Pattern in Current Module")}, "Ctrl+Shift+B")); + defaultShortcuts.insert("ActionFindNamesInModule", Shortcut({tr("Actions"), tr("Find Names in Current Module")}, "Ctrl+N")); + defaultShortcuts.insert("ActionFindReferences", Shortcut({tr("Actions"), tr("Find References")}, "Ctrl+R")); + defaultShortcuts.insert("ActionXrefs", Shortcut({tr("Actions"), tr("xrefs...")}, "X")); + defaultShortcuts.insert("ActionAnalyzeSingleFunction", Shortcut({tr("Actions"), tr("Analyze Single Function")}, "A")); + defaultShortcuts.insert("ActionAnalyzeModule", Shortcut({tr("Actions"), tr("Analyze Module")}, "Ctrl+A")); + defaultShortcuts.insert("ActionHelpOnMnemonic", Shortcut({tr("Actions"), tr("Help on Mnemonic")}, "Ctrl+F1")); + defaultShortcuts.insert("ActionToggleMnemonicBrief", Shortcut({tr("Actions"), tr("Toggle Mnemonic Brief")}, "Ctrl+Shift+F1")); + defaultShortcuts.insert("ActionHighlightingMode", Shortcut({tr("Actions"), tr("Highlighting Mode")}, "H")); + defaultShortcuts.insert("ActionToggleDestinationPreview", Shortcut({tr("Actions"), tr("Enable/Disable Branch Destination Preview")}, "P")); + defaultShortcuts.insert("ActionFind", Shortcut({tr("Actions"), tr("Find")}, "Ctrl+F")); + defaultShortcuts.insert("ActionFindInModule", Shortcut({tr("Actions"), tr("Find in Current Module")}, "Ctrl+Shift+F")); + defaultShortcuts.insert("ActionToggleLogging", Shortcut({tr("Actions"), tr("Enable/Disable Logging")}, "")); + defaultShortcuts.insert("ActionAllocateMemory", Shortcut({tr("Actions"), tr("Allocate Memory")}, "")); + defaultShortcuts.insert("ActionFreeMemory", Shortcut({tr("Actions"), tr("Free Memory")}, "")); + defaultShortcuts.insert("ActionSyncWithExpression", Shortcut({tr("Actions"), tr("Sync With Expression")}, "")); + defaultShortcuts.insert("ActionCopyAllRegisters", Shortcut({tr("Actions"), tr("Copy All Registers")}, "")); + defaultShortcuts.insert("ActionMarkAsUser", Shortcut({tr("Actions"), tr("Mark As User Module")}, "")); + defaultShortcuts.insert("ActionMarkAsSystem", Shortcut({tr("Actions"), tr("Mark As System Module")}, "")); + defaultShortcuts.insert("ActionMarkAsParty", Shortcut({tr("Actions"), tr("Mark As Party")}, "")); + defaultShortcuts.insert("ActionSetHwBpE", Shortcut({tr("Actions"), tr("Set Hardware Breakpoint (Execute)")}, "")); + defaultShortcuts.insert("ActionRemoveHwBp", Shortcut({tr("Actions"), tr("Remove Hardware Breakpoint")}, "")); + defaultShortcuts.insert("ActionRemoveTypeAnalysisFromModule", Shortcut({tr("Actions"), tr("Remove Type Analysis From Module")}, "Ctrl+Shift+U")); + defaultShortcuts.insert("ActionRemoveTypeAnalysisFromSelection", Shortcut({tr("Actions"), tr("Remove Type Analysis From Selection")}, "U")); + defaultShortcuts.insert("ActionTreatSelectionAsCode", Shortcut({tr("Actions"), tr("Treat Selection As"), tr("Code")}, "C")); + defaultShortcuts.insert("ActionTreatSelectionAsByte", Shortcut({tr("Actions"), tr("Treat Selection As"), tr("Byte")}, "B")); + defaultShortcuts.insert("ActionTreatSelectionAsWord", Shortcut({tr("Actions"), tr("Treat Selection As"), tr("Word")}, "W")); + defaultShortcuts.insert("ActionTreatSelectionAsDword", Shortcut({tr("Actions"), tr("Treat Selection As"), tr("Dword")}, "D")); + defaultShortcuts.insert("ActionTreatSelectionAsFword", Shortcut({tr("Actions"), tr("Treat Selection As"), tr("Fword")}, "")); + defaultShortcuts.insert("ActionTreatSelectionAsQword", Shortcut({tr("Actions"), tr("Treat Selection As"), tr("Qword")}, "Q")); + defaultShortcuts.insert("ActionTreatSelectionAsTbyte", Shortcut({tr("Actions"), tr("Treat Selection As"), tr("Tbyte")}, "")); + defaultShortcuts.insert("ActionTreatSelectionAsOword", Shortcut({tr("Actions"), tr("Treat Selection As"), tr("Oword")}, "")); + defaultShortcuts.insert("ActionTreatSelectionAsFloat", Shortcut({tr("Actions"), tr("Treat Selection As"), tr("Float")}, "")); + defaultShortcuts.insert("ActionTreatSelectionAsDouble", Shortcut({tr("Actions"), tr("Treat Selection As"), tr("Double")}, "")); + defaultShortcuts.insert("ActionTreatSelectionAsLongDouble", Shortcut({tr("Actions"), tr("Treat Selection As"), tr("LongDouble")}, "")); + defaultShortcuts.insert("ActionTreatSelectionAsASCII", Shortcut({tr("Actions"), tr("Treat Selection As"), tr("ASCII")}, "")); + defaultShortcuts.insert("ActionTreatSelectionAsUNICODE", Shortcut({tr("Actions"), tr("Treat Selection As"), tr("UNICODE")}, "")); + defaultShortcuts.insert("ActionTreatSelectionAsMMWord", Shortcut({tr("Actions"), tr("Treat Selection As"), tr("MMWord")}, "")); + defaultShortcuts.insert("ActionTreatSelectionAsXMMWord", Shortcut({tr("Actions"), tr("Treat Selection As"), tr("XMMWord")}, "")); + defaultShortcuts.insert("ActionTreatSelectionAsYMMWord", Shortcut({tr("Actions"), tr("Treat Selection As"), tr("YMMWord")}, "")); + defaultShortcuts.insert("ActionTreatSelectionHeadAsCode", Shortcut({tr("Actions"), tr("Treat Selection Head As"), tr("Code")}, "")); + defaultShortcuts.insert("ActionTreatSelectionHeadAsByte", Shortcut({tr("Actions"), tr("Treat Selection Head As"), tr("Byte")}, "")); + defaultShortcuts.insert("ActionTreatSelectionHeadAsWord", Shortcut({tr("Actions"), tr("Treat Selection Head As"), tr("Word")}, "")); + defaultShortcuts.insert("ActionTreatSelectionHeadAsDword", Shortcut({tr("Actions"), tr("Treat Selection Head As"), tr("Dword")}, "")); + defaultShortcuts.insert("ActionTreatSelectionHeadAsFword", Shortcut({tr("Actions"), tr("Treat Selection Head As"), tr("Fword")}, "")); + defaultShortcuts.insert("ActionTreatSelectionHeadAsQword", Shortcut({tr("Actions"), tr("Treat Selection Head As"), tr("Qword")}, "")); + defaultShortcuts.insert("ActionTreatSelectionHeadAsTbyte", Shortcut({tr("Actions"), tr("Treat Selection Head As"), tr("Tbyte")}, "")); + defaultShortcuts.insert("ActionTreatSelectionHeadAsOword", Shortcut({tr("Actions"), tr("Treat Selection Head As"), tr("Oword")}, "")); + defaultShortcuts.insert("ActionTreatSelectionHeadAsFloat", Shortcut({tr("Actions"), tr("Treat Selection Head As"), tr("Float")}, "")); + defaultShortcuts.insert("ActionTreatSelectionHeadAsDouble", Shortcut({tr("Actions"), tr("Treat Selection Head As"), tr("Double")}, "")); + defaultShortcuts.insert("ActionTreatSelectionHeadAsLongDouble", Shortcut({tr("Actions"), tr("Treat Selection Head As"), tr("LongDouble")}, "")); + defaultShortcuts.insert("ActionTreatSelectionHeadAsASCII", Shortcut({tr("Actions"), tr("Treat Selection Head As"), tr("ASCII")}, "")); + defaultShortcuts.insert("ActionTreatSelectionHeadAsUNICODE", Shortcut({tr("Actions"), tr("Treat Selection Head As"), tr("UNICODE")}, "")); + defaultShortcuts.insert("ActionTreatSelectionHeadAsMMWord", Shortcut({tr("Actions"), tr("Treat Selection Head As"), tr("MMWord")}, "")); + defaultShortcuts.insert("ActionTreatSelectionHeadAsXMMWord", Shortcut({tr("Actions"), tr("Treat Selection Head As"), tr("XMMWord")}, "")); + defaultShortcuts.insert("ActionTreatSelectionHeadAsYMMWord", Shortcut({tr("Actions"), tr("Treat Selection Head As"), tr("YMMWord")}, "")); + defaultShortcuts.insert("ActionToggleRegisterValue", Shortcut({tr("Actions"), tr("Toggle Register Value")}, "Space")); + defaultShortcuts.insert("ActionClear", Shortcut({tr("Actions"), tr("Clear")}, "Ctrl+L")); + defaultShortcuts.insert("ActionCopy", Shortcut({tr("Actions"), tr("Copy")}, "Ctrl+C")); + defaultShortcuts.insert("ActionCopyAddress", Shortcut({tr("Actions"), tr("Copy Address")}, "Alt+INS")); + defaultShortcuts.insert("ActionCopyRva", Shortcut({tr("Actions"), tr("Copy RVA")}, "")); + defaultShortcuts.insert("ActionCopySymbol", Shortcut({tr("Actions"), tr("Copy Symbol")}, "Ctrl+S")); + defaultShortcuts.insert("ActionCopyLine", Shortcut({tr("Actions"), tr("Copy Line")}, "")); + defaultShortcuts.insert("ActionLoadScript", Shortcut({tr("Actions"), tr("Load Script")}, "Ctrl+O")); + defaultShortcuts.insert("ActionReloadScript", Shortcut({tr("Actions"), tr("Reload Script")}, "Ctrl+R")); + defaultShortcuts.insert("ActionUnloadScript", Shortcut({tr("Actions"), tr("Unload Script")}, "Ctrl+U")); + defaultShortcuts.insert("ActionEditScript", Shortcut({tr("Actions"), tr("Edit Script")}, "")); + defaultShortcuts.insert("ActionRunScript", Shortcut({tr("Actions"), tr("Run Script")}, "Space")); + defaultShortcuts.insert("ActionToggleBreakpointScript", Shortcut({tr("Actions"), tr("Toggle Script Breakpoint")}, "F2")); + defaultShortcuts.insert("ActionRunToCursorScript", Shortcut({tr("Actions"), tr("Run Script to Cursor")}, "Shift+F4")); + defaultShortcuts.insert("ActionStepScript", Shortcut({tr("Actions"), tr("Step Script")}, "Tab")); + defaultShortcuts.insert("ActionAbortScript", Shortcut({tr("Actions"), tr("Abort Script")}, "Esc")); + defaultShortcuts.insert("ActionExecuteCommandScript", Shortcut({tr("Actions"), tr("Execute Script Command")}, "X")); + defaultShortcuts.insert("ActionRefresh", Shortcut({tr("Actions"), tr("Refresh")}, "F5")); + defaultShortcuts.insert("ActionGraph", Shortcut({tr("Actions"), tr("Graph")}, "G")); + defaultShortcuts.insert("ActionGraphZoomToCursor", Shortcut({tr("Actions"), tr("Graph"), tr("Zoom to cursor")}, "Z")); + defaultShortcuts.insert("ActionGraphFitToWindow", Shortcut({tr("Actions"), tr("Graph"), tr("Fit To Window")}, "Shift+Z")); + defaultShortcuts.insert("ActionGraphFollowDisassembler", Shortcut({tr("Actions"), tr("Graph"), tr("Follow in disassembler")}, "Shift+Return")); + defaultShortcuts.insert("ActionGraphSaveImage", Shortcut({tr("Actions"), tr("Graph"), tr("Save as image")}, "I")); + defaultShortcuts.insert("ActionGraphToggleOverview", Shortcut({tr("Actions"), tr("Graph"), tr("Toggle overview")}, "O")); + defaultShortcuts.insert("ActionGraphToggleSummary", Shortcut({tr("Actions"), tr("Graph"), tr("Toggle summary")}, "U")); + defaultShortcuts.insert("ActionGraphSyncOrigin", Shortcut({tr("Actions"), tr("Graph"), tr("Toggle sync with EIP/RIP")}, "S")); + defaultShortcuts.insert("ActionIncrementx87Stack", Shortcut({tr("Actions"), tr("Increment x87 Stack")})); + defaultShortcuts.insert("ActionDecrementx87Stack", Shortcut({tr("Actions"), tr("Decrement x87 Stack")})); + defaultShortcuts.insert("ActionRedirectLog", Shortcut({tr("Actions"), tr("Redirect Log")})); + defaultShortcuts.insert("ActionBrowseInExplorer", Shortcut({tr("Actions"), tr("Browse in Explorer")})); + defaultShortcuts.insert("ActionDownloadSymbol", Shortcut({tr("Actions"), tr("Download Symbols for This Module")})); + defaultShortcuts.insert("ActionDownloadAllSymbol", Shortcut({tr("Actions"), tr("Download Symbols for All Modules")})); + defaultShortcuts.insert("ActionCreateNewThreadHere", Shortcut({tr("Actions"), tr("Create New Thread Here")})); + defaultShortcuts.insert("ActionOpenSourceFile", Shortcut({tr("Actions"), tr("Open Source File")})); + defaultShortcuts.insert("ActionFollowMemMap", Shortcut({tr("Actions"), tr("Follow in Memory Map")})); + defaultShortcuts.insert("ActionFollowStack", Shortcut({tr("Actions"), tr("Follow in Stack")})); + defaultShortcuts.insert("ActionFollowDisasm", Shortcut({tr("Actions"), tr("Follow in Disassembler")})); + defaultShortcuts.insert("ActionFollowDwordQwordDisasm", Shortcut({tr("Actions"), tr("Follow DWORD/QWORD in Disassembler")})); + defaultShortcuts.insert("ActionFollowDwordQwordDump", Shortcut({tr("Actions"), tr("Follow DWORD/QWORD in Dump")})); + defaultShortcuts.insert("ActionFreezeStack", Shortcut({tr("Actions"), tr("Freeze the stack")})); + defaultShortcuts.insert("ActionGotoBaseOfStackFrame", Shortcut({tr("Actions"), tr("Go to Base of Stack Frame")})); + defaultShortcuts.insert("ActionGotoPrevStackFrame", Shortcut({tr("Actions"), tr("Go to Previous Stack Frame")})); + defaultShortcuts.insert("ActionGotoNextStackFrame", Shortcut({tr("Actions"), tr("Go to Next Stack Frame")})); + defaultShortcuts.insert("ActionGotoPreviousReference", Shortcut({tr("Actions"), tr("Go to Previous Reference")}, "Ctrl+K")); + defaultShortcuts.insert("ActionGotoNextReference", Shortcut({tr("Actions"), tr("Go to Next Reference")}, "Ctrl+L")); + defaultShortcuts.insert("ActionModifyValue", Shortcut({tr("Actions"), tr("Modify value")}, "Space")); + defaultShortcuts.insert("ActionWatchDwordQword", Shortcut({tr("Actions"), tr("Watch DWORD/QWORD")})); + defaultShortcuts.insert("ActionCopyFileOffset", Shortcut({tr("Actions"), tr("Copy File Offset")})); + defaultShortcuts.insert("ActionToggleRunTrace", Shortcut({tr("Actions"), tr("Start/Stop trace recording")})); + + defaultShortcuts.insert("ActionCopyCroppedTable", Shortcut({tr("Actions"), tr("Copy -> Cropped Table")})); + defaultShortcuts.insert("ActionCopyTable", Shortcut({tr("Actions"), tr("Copy -> Table")})); + defaultShortcuts.insert("ActionCopyLineToLog", Shortcut({tr("Actions"), tr("Copy -> Line, To Log")})); + defaultShortcuts.insert("ActionCopyCroppedTableToLog", Shortcut({tr("Actions"), tr("Copy -> Cropped Table, To Log")})); + defaultShortcuts.insert("ActionCopyTableToLog", Shortcut({tr("Actions"), tr("Copy -> Table, To Log")})); + defaultShortcuts.insert("ActionExport", Shortcut({tr("Actions"), tr("Copy -> Export Table")})); + + Shortcuts = defaultShortcuts; + + load(); + + //because we changed the default this needs special handling for old configurations + if(Shortcuts["ViewPreviousTab"].Hotkey.toString() == Shortcuts["ViewPreviousHistory"].Hotkey.toString()) + { + Shortcuts["ViewPreviousTab"].Hotkey = defaultShortcuts["ViewPreviousTab"].Hotkey; + save(); + } + if(Shortcuts["ViewNextTab"].Hotkey.toString() == Shortcuts["ViewNextHistory"].Hotkey.toString()) + { + Shortcuts["ViewNextTab"].Hotkey = defaultShortcuts["ViewNextTab"].Hotkey; + save(); + } +} + +Configuration* Configuration::instance() +{ + return mPtr; +} + +void Configuration::load() +{ + readColors(); + readBools(); + readUints(); + readFonts(); + readShortcuts(); +} + +void Configuration::save() +{ + writeColors(); + writeBools(); + writeUints(); + writeFonts(); + writeShortcuts(); +} + +void Configuration::readColors() +{ + Colors = defaultColors; + //read config + for(auto it = Colors.begin(); it != Colors.end(); ++it) + it.value() = colorFromConfig(it.key()); +} + +void Configuration::writeColors() +{ + //write config + for(auto it = Colors.begin(); it != Colors.end(); ++it) + colorToConfig(it.key(), it.value()); + emit colorsUpdated(); +} + +void Configuration::readBools() +{ + Bools = defaultBools; + //read config + for(auto itMap = Bools.begin(); itMap != Bools.end(); ++itMap) + { + const QString & category = itMap.key(); + for(auto it = itMap.value().begin(); it != itMap.value().end(); it++) + { + it.value() = boolFromConfig(category, it.key()); + } + } +} + +void Configuration::writeBools() +{ + //write config + for(auto itMap = Bools.cbegin(); itMap != Bools.cend(); ++itMap) + { + const QString & category = itMap.key(); + for(auto it = itMap.value().cbegin(); it != itMap.value().cend(); it++) + { + boolToConfig(category, it.key(), it.value()); + } + } +} + +void Configuration::readUints() +{ + Uints = defaultUints; + //read config + for(auto itMap = Uints.begin(); itMap != Uints.end(); ++itMap) + { + const QString & category = itMap.key(); + for(auto it = itMap.value().begin(); it != itMap.value().end(); it++) + { + it.value() = uintFromConfig(category, it.key()); + } + } +} + +void Configuration::writeUints() +{ + duint setting; + bool bSaveLoadTabOrder = ConfigBool("Gui", "LoadSaveTabOrder"); + + //write config + for(auto itMap = Uints.cbegin(); itMap != Uints.cend(); ++itMap) + { + const QString & category = itMap.key(); + for(auto it = itMap.value().cbegin(); it != itMap.value().cend(); it++) + { + // Do not save settings to file if saveLoadTabOrder checkbox is Unchecked + const QString & id = it.key(); + if(!bSaveLoadTabOrder && category == "TabOrder" && BridgeSettingGetUint(category.toUtf8().constData(), id.toUtf8().constData(), &setting)) + continue; + + uintToConfig(category, id, it.value()); + } + } +} + +void Configuration::readFonts() +{ + Fonts = defaultFonts; + //read config + for(auto it = Fonts.begin(); it != Fonts.end(); ++it) + { + const QString & id = it.key(); + QFont font = fontFromConfig(id); + it.value() = font; + /*QFontInfo fontInfo(font); + if(id == "Application" || fontInfo.fixedPitch()) + it.value() = font;*/ + } +} + +void Configuration::writeFonts() +{ + //write config + for(auto it = Fonts.cbegin(); it != Fonts.cend(); ++it) + fontToConfig(it.key(), it.value()); + emit fontsUpdated(); +} + +void Configuration::readShortcuts() +{ + Shortcuts = defaultShortcuts; + QMap::const_iterator it = Shortcuts.begin(); + + while(it != Shortcuts.end()) + { + const QString & id = it.key(); + QString key = shortcutFromConfig(id); + if(key != "") + { + if(key == "NOT_SET") + Shortcuts[it.key()].Hotkey = QKeySequence(); + else + { + QKeySequence KeySequence(key); + Shortcuts[it.key()].Hotkey = KeySequence; + } + } + it++; + } + emit shortcutsUpdated(); +} + +void Configuration::writeShortcuts() +{ + QMap::const_iterator it = Shortcuts.begin(); + + while(it != Shortcuts.end()) + { + shortcutToConfig(it.key(), it.value().Hotkey); + it++; + } + emit shortcutsUpdated(); +} + +const QColor Configuration::getColor(const QString & id) const +{ + if(Colors.contains(id)) + return Colors.constFind(id).value(); + if(noMoreMsgbox) + return Qt::black; + QMessageBox msg(QMessageBox::Warning, tr("NOT FOUND IN CONFIG!"), id, QMessageBox::Retry | QMessageBox::Cancel); + msg.setWindowIcon(DIcon("compile-warning")); + msg.setWindowFlags(msg.windowFlags() & (~Qt::WindowContextHelpButtonHint)); + if(msg.exec() == QMessageBox::Cancel) + noMoreMsgbox = true; + return Qt::black; +} + +const bool Configuration::getBool(const QString & category, const QString & id) const +{ + if(Bools.contains(category)) + { + if(Bools[category].contains(id)) + return Bools[category][id]; + if(noMoreMsgbox) + return false; + QMessageBox msg(QMessageBox::Warning, tr("NOT FOUND IN CONFIG!"), category + ":" + id, QMessageBox::Retry | QMessageBox::Cancel); /* insertMenuBuilderBools */ + msg.setWindowIcon(DIcon("compile-warning")); + msg.setWindowFlags(msg.windowFlags() & (~Qt::WindowContextHelpButtonHint)); + if(msg.exec() == QMessageBox::Cancel) + noMoreMsgbox = true; + return false; + } + if(noMoreMsgbox) + return false; + QMessageBox msg(QMessageBox::Warning, tr("NOT FOUND IN CONFIG!"), category, QMessageBox::Retry | QMessageBox::Cancel); + msg.setWindowIcon(DIcon("compile-warning")); + msg.setWindowFlags(msg.windowFlags() & (~Qt::WindowContextHelpButtonHint)); + if(msg.exec() == QMessageBox::Cancel) + noMoreMsgbox = true; + return false; +} + +void Configuration::setBool(const QString & category, const QString & id, const bool b) +{ + if(Bools.contains(category)) + { + if(Bools[category].contains(id)) + { + Bools[category][id] = b; + return; + } + if(noMoreMsgbox) + return; + QMessageBox msg(QMessageBox::Warning, tr("NOT FOUND IN CONFIG!"), category + ":" + id, QMessageBox::Retry | QMessageBox::Cancel); + msg.setWindowIcon(DIcon("compile-warning")); + msg.setWindowFlags(msg.windowFlags() & (~Qt::WindowContextHelpButtonHint)); + if(msg.exec() == QMessageBox::Cancel) + noMoreMsgbox = true; + return; + } + if(noMoreMsgbox) + return; + QMessageBox msg(QMessageBox::Warning, tr("NOT FOUND IN CONFIG!"), category, QMessageBox::Retry | QMessageBox::Cancel); + msg.setWindowIcon(DIcon("compile-warning")); + msg.setWindowFlags(msg.windowFlags() & (~Qt::WindowContextHelpButtonHint)); + if(msg.exec() == QMessageBox::Cancel) + noMoreMsgbox = true; +} + +const duint Configuration::getUint(const QString & category, const QString & id) const +{ + if(Uints.contains(category)) + { + if(Uints[category].contains(id)) + return Uints[category][id]; + if(noMoreMsgbox) + return 0; + QMessageBox msg(QMessageBox::Warning, tr("NOT FOUND IN CONFIG!"), category + ":" + id, QMessageBox::Retry | QMessageBox::Cancel); + msg.setWindowIcon(DIcon("compile-warning")); + msg.setWindowFlags(msg.windowFlags() & (~Qt::WindowContextHelpButtonHint)); + if(msg.exec() == QMessageBox::Cancel) + noMoreMsgbox = true; + return 0; + } + if(noMoreMsgbox) + return 0; + QMessageBox msg(QMessageBox::Warning, tr("NOT FOUND IN CONFIG!"), category, QMessageBox::Retry | QMessageBox::Cancel); + msg.setWindowIcon(DIcon("compile-warning")); + msg.setWindowFlags(msg.windowFlags() & (~Qt::WindowContextHelpButtonHint)); + if(msg.exec() == QMessageBox::Cancel) + noMoreMsgbox = true; + return 0; +} + +void Configuration::setUint(const QString & category, const QString & id, const duint i) +{ + if(Uints.contains(category)) + { + if(Uints[category].contains(id)) + { + Uints[category][id] = i; + return; + } + if(noMoreMsgbox) + return; + QMessageBox msg(QMessageBox::Warning, tr("NOT FOUND IN CONFIG!"), category + ":" + id, QMessageBox::Retry | QMessageBox::Cancel); + msg.setWindowIcon(DIcon("compile-warning")); + msg.setWindowFlags(msg.windowFlags() & (~Qt::WindowContextHelpButtonHint)); + if(msg.exec() == QMessageBox::Cancel) + noMoreMsgbox = true; + return; + } + if(noMoreMsgbox) + return; + QMessageBox msg(QMessageBox::Warning, tr("NOT FOUND IN CONFIG!"), category, QMessageBox::Retry | QMessageBox::Cancel); + msg.setWindowIcon(DIcon("compile-warning")); + msg.setWindowFlags(msg.windowFlags() & (~Qt::WindowContextHelpButtonHint)); + if(msg.exec() == QMessageBox::Cancel) + noMoreMsgbox = true; +} + +const QFont Configuration::getFont(const QString & id) const +{ + if(Fonts.contains(id)) + return Fonts.constFind(id).value(); + QFont ret("Lucida Console", 8, QFont::Normal, false); + ret.setFixedPitch(true); + ret.setStyleHint(QFont::Monospace); + if(noMoreMsgbox) + return ret; + QMessageBox msg(QMessageBox::Warning, tr("NOT FOUND IN CONFIG!"), id, QMessageBox::Retry | QMessageBox::Cancel); + msg.setWindowIcon(DIcon("compile-warning")); + msg.setWindowFlags(msg.windowFlags() & (~Qt::WindowContextHelpButtonHint)); + if(msg.exec() == QMessageBox::Cancel) + noMoreMsgbox = true; + return ret; +} + +const Configuration::Shortcut Configuration::getShortcut(const QString & key_id) const +{ + if(Shortcuts.contains(key_id)) + return Shortcuts.constFind(key_id).value(); + if(!noMoreMsgbox) + { + QMessageBox msg(QMessageBox::Warning, tr("NOT FOUND IN CONFIG!"), key_id, QMessageBox::Retry | QMessageBox::Cancel); + msg.setWindowIcon(DIcon("compile-warning")); + msg.setWindowFlags(msg.windowFlags() & (~Qt::WindowContextHelpButtonHint)); + if(msg.exec() == QMessageBox::Cancel) + noMoreMsgbox = true; + } + return Shortcut(); +} + +void Configuration::setShortcut(const QString & key_id, const QKeySequence key_sequence) +{ + if(Shortcuts.contains(key_id)) + { + Shortcuts[key_id].Hotkey = key_sequence; + return; + } + if(noMoreMsgbox) + return; + QMessageBox msg(QMessageBox::Warning, tr("NOT FOUND IN CONFIG!"), key_id, QMessageBox::Retry | QMessageBox::Cancel); + msg.setWindowIcon(DIcon("compile-warning")); + msg.setWindowFlags(msg.windowFlags() & (~Qt::WindowContextHelpButtonHint)); + if(msg.exec() == QMessageBox::Cancel) + noMoreMsgbox = true; +} + +void Configuration::setPluginShortcut(const QString & key_id, QString description, QString defaultShortcut, bool global) +{ + defaultShortcuts[key_id] = Shortcut(description, defaultShortcut, global); + readShortcuts(); +} + +QColor Configuration::colorFromConfig(const QString & id) +{ + char setting[MAX_SETTING_SIZE] = ""; + if(!BridgeSettingGet("Colors", id.toUtf8().constData(), setting)) + { + if(defaultColors.contains(id)) + { + QColor ret = defaultColors.find(id).value(); + colorToConfig(id, ret); + return ret; + } + return Qt::black; //black is default + } + if(QString(setting).toUpper() == "#XXXXXX") //support custom transparent color name + return Qt::transparent; + QColor color(setting); + if(!color.isValid()) + { + if(defaultColors.contains(id)) + { + QColor ret = defaultColors.find(id).value(); + colorToConfig(id, ret); + return ret; + } + return Qt::black; //black is default + } + return color; +} + +bool Configuration::colorToConfig(const QString & id, const QColor color) +{ + QString colorName = color.name().toUpper(); + if(!color.alpha()) + colorName = "#XXXXXX"; + return BridgeSettingSet("Colors", id.toUtf8().constData(), colorName.toUtf8().constData()); +} + +bool Configuration::boolFromConfig(const QString & category, const QString & id) +{ + duint setting; + if(!BridgeSettingGetUint(category.toUtf8().constData(), id.toUtf8().constData(), &setting)) + { + if(defaultBools.contains(category) && defaultBools[category].contains(id)) + { + bool ret = defaultBools[category][id]; + boolToConfig(category, id, ret); + return ret; + } + return false; //DAFUG + } + return (setting != 0); +} + +bool Configuration::boolToConfig(const QString & category, const QString & id, const bool bBool) +{ + return BridgeSettingSetUint(category.toUtf8().constData(), id.toUtf8().constData(), bBool); +} + +duint Configuration::uintFromConfig(const QString & category, const QString & id) +{ + duint setting; + if(!BridgeSettingGetUint(category.toUtf8().constData(), id.toUtf8().constData(), &setting)) + { + if(defaultUints.contains(category) && defaultUints[category].contains(id)) + { + setting = defaultUints[category][id]; + uintToConfig(category, id, setting); + return setting; + } + return 0; //DAFUG + } + return setting; +} + +bool Configuration::uintToConfig(const QString & category, const QString & id, duint i) +{ + return BridgeSettingSetUint(category.toUtf8().constData(), id.toUtf8().constData(), i); +} + +QFont Configuration::fontFromConfig(const QString & id) +{ + char setting[MAX_SETTING_SIZE] = ""; + if(!BridgeSettingGet("Fonts", id.toUtf8().constData(), setting)) + { + if(defaultFonts.contains(id)) + { + QFont ret = defaultFonts.find(id).value(); + fontToConfig(id, ret); + return ret; + } + if(id == "Application") + return QApplication::font(); + QFont ret("Lucida Console", 8, QFont::Normal, false); + ret.setFixedPitch(true); + ret.setStyleHint(QFont::Monospace); + return ret; + } + QFont font; + if(!font.fromString(setting)) + { + if(defaultFonts.contains(id)) + { + QFont ret = defaultFonts.find(id).value(); + fontToConfig(id, ret); + return ret; + } + if(id == "Application") + return QApplication::font(); + QFont ret("Lucida Console", 8, QFont::Normal, false); + ret.setFixedPitch(true); + ret.setStyleHint(QFont::Monospace); + return ret; + } + return font; +} + +bool Configuration::fontToConfig(const QString & id, const QFont font) +{ + return BridgeSettingSet("Fonts", id.toUtf8().constData(), font.toString().toUtf8().constData()); +} + +QString Configuration::shortcutFromConfig(const QString & id) +{ + QString _id = QString("%1").arg(id); + char setting[MAX_SETTING_SIZE] = ""; + if(BridgeSettingGet("Shortcuts", _id.toUtf8().constData(), setting)) + { + return QString(setting); + } + return QString(); +} + +bool Configuration::shortcutToConfig(const QString & id, const QKeySequence shortcut) +{ + QString _id = QString("%1").arg(id); + QString _key = ""; + if(!shortcut.isEmpty()) + _key = shortcut.toString(QKeySequence::NativeText); + else + _key = "NOT_SET"; + return BridgeSettingSet("Shortcuts", _id.toUtf8().constData(), _key.toUtf8().constData()); +} + +void Configuration::registerMenuBuilder(MenuBuilder* menu, size_t count) +{ + QString id = menu->getId(); + for(const auto & i : NamedMenuBuilders) + if(i.type == 0 && i.builder->getId() == id) + return; //already exists + NamedMenuBuilders.append(MenuMap(menu, count)); +} + +void Configuration::registerMainMenuStringList(QList* menu) +{ + NamedMenuBuilders.append(MenuMap(menu, menu->size() - 1)); +} + +void Configuration::zoomFont(const QString & fontName, QWheelEvent* event) +{ + auto & angleDeltaY = mZoomFontDelta[fontName]; + angleDeltaY += event->angleDelta().y(); + + const auto tickValue = 15 * 8; + auto ticks = std::min(std::max(angleDeltaY / tickValue, -1), 1); + if(ticks != 0) + { + angleDeltaY %= tickValue; + + QFont myFont = Fonts[fontName]; + int fontSizes[] = {6, 7, 8, 9, 10, 11, 12, 14, 16, 18, 20, 22}; // The list of font sizes in ApperanceDialog + auto currentFontSize = std::find_if(std::begin(fontSizes), std::end(fontSizes), [&myFont](int fontSize) + { + return fontSize >= myFont.pointSize(); + }); + + if(currentFontSize != std::end(fontSizes)) + { + currentFontSize += ticks; + if(currentFontSize >= std::end(fontSizes)) + currentFontSize = std::end(fontSizes) - 1; + else if(currentFontSize < fontSizes) + currentFontSize = fontSizes; + + myFont.setPointSize(*currentFontSize); + Fonts[fontName] = myFont; + writeFonts(); + GuiUpdateAllViews(); + } + } +} + +static bool IsPointVisible(QPoint pos) +{ + for(const auto & i : QGuiApplication::screens()) + { + QRect rt = i->geometry(); + if(rt.left() <= pos.x() && rt.right() >= pos.x() && rt.top() <= pos.y() && rt.bottom() >= pos.y()) + return true; + } + return false; +} + +/** + * @brief Configuration::setupWindowPos Loads the position/size of a dialog. + * @param window this + */ +void Configuration::loadWindowGeometry(QWidget* window) +{ + QString name = window->metaObject()->className(); + char setting[MAX_SETTING_SIZE] = ""; + if(!BridgeSettingGet("Gui", (name + "Geometry").toUtf8().constData(), setting)) + return; + auto oldPos = window->pos(); + window->restoreGeometry(QByteArray::fromBase64(QByteArray(setting))); + if(!IsPointVisible(window->pos())) + window->move(oldPos); +} + +/** + * @brief Configuration::saveWindowPos Saves the position/size of a dialog. + * @param window this + */ +void Configuration::saveWindowGeometry(QWidget* window) +{ + QString name = window->metaObject()->className(); + BridgeSettingSet("Gui", (name + "Geometry").toUtf8().constData(), window->saveGeometry().toBase64().data()); +} diff --git a/src/cross/gui/Configuration.h b/src/cross/gui/Configuration.h new file mode 100644 index 00000000..29af735f --- /dev/null +++ b/src/cross/gui/Configuration.h @@ -0,0 +1,132 @@ +#pragma once + +#include +#include +#include +#include +#include +#include "Types.h" + +// TODO: declare AppearanceDialog and SettingsDialog entries here, so that you only have to do it in once place +#define Config() (Configuration::instance()) +#define ConfigColor(x) (Config()->getColor(x)) +#define ConfigBool(x,y) (Config()->getBool(x,y)) +#define ConfigUint(x,y) (Config()->getUint(x,y)) +#define ConfigFont(x) (Config()->getFont(x)) +#define ConfigShortcut(x) (Config()->getShortcut(x).Hotkey) +#define ConfigHScrollBarStyle() "QScrollBar:horizontal{border:1px solid grey;background:#f1f1f1;height:10px}QScrollBar::handle:horizontal{background:#aaaaaa;min-width:20px;margin:1px}QScrollBar::add-line:horizontal,QScrollBar::sub-line:horizontal{width:0;height:0}" +#define ConfigVScrollBarStyle() "QScrollBar:vertical{border:1px solid grey;background:#f1f1f1;width:10px}QScrollBar::handle:vertical{background:#aaaaaa;min-height:20px;margin:1px}QScrollBar::add-line:vertical,QScrollBar::sub-line:vertical{width:0;height:0}" + +class MenuBuilder; +class QAction; +class QWheelEvent; + +class Configuration : public QObject +{ + Q_OBJECT +public: + //Structures + struct Shortcut + { + QString Name; + QKeySequence Hotkey; + bool GlobalShortcut; + + Shortcut(QString name = QString(), QString hotkey = QString(), bool global = false) + : Name(name), Hotkey(hotkey, QKeySequence::PortableText), GlobalShortcut(global) { } + + Shortcut(std::initializer_list names, QString hotkey = QString(), bool global = false) + : Shortcut(QStringList(names).join(" -> "), hotkey, global) { } + }; + + //Functions + Configuration(); + static Configuration* instance(); + void load(); + void save(); + void readColors(); + void writeColors(); + void readBools(); + void writeBools(); + void readUints(); + void writeUints(); + void readFonts(); + void writeFonts(); + void readShortcuts(); + void writeShortcuts(); + void registerMenuBuilder(MenuBuilder* menu, size_t count); + void registerMainMenuStringList(QList* menu); + + const QColor getColor(const QString & id) const; + const bool getBool(const QString & category, const QString & id) const; + void setBool(const QString & category, const QString & id, const bool b); + const duint getUint(const QString & category, const QString & id) const; + void setUint(const QString & category, const QString & id, const duint i); + const QFont getFont(const QString & id) const; + const Shortcut getShortcut(const QString & key_id) const; + void setShortcut(const QString & key_id, const QKeySequence key_sequence); + void setPluginShortcut(const QString & key_id, QString description, QString defaultShortcut, bool global); + void loadWindowGeometry(QWidget* window); + void saveWindowGeometry(QWidget* window); + + void zoomFont(const QString & fontName, QWheelEvent* event); + + //default setting maps + QMap defaultColors; + QMap> defaultBools; + QMap> defaultUints; + QMap defaultFonts; + QMap defaultShortcuts; + + //public variables + QMap Colors; + QMap> Bools; + QMap> Uints; + QMap Fonts; + QMap Shortcuts; + + //custom menu maps + struct MenuMap + { + union + { + QList* mainMenuList; + MenuBuilder* builder; + }; + int type; + size_t count; + + MenuMap() { } + MenuMap(QList* mainMenuList, size_t count) + : mainMenuList(mainMenuList), type(1), count(count) { } + MenuMap(MenuBuilder* builder, size_t count) + : builder(builder), type(0), count(count) { } + }; + + QList NamedMenuBuilders; + + static Configuration* mPtr; + +signals: + void colorsUpdated(); + void fontsUpdated(); + void guiOptionsUpdated(); + void shortcutsUpdated(); + void tokenizerConfigUpdated(); + void disableAutoCompleteUpdated(); + +private: + QColor colorFromConfig(const QString & id); + bool colorToConfig(const QString & id, const QColor color); + bool boolFromConfig(const QString & category, const QString & id); + bool boolToConfig(const QString & category, const QString & id, bool bBool); + duint uintFromConfig(const QString & category, const QString & id); + bool uintToConfig(const QString & category, const QString & id, duint i); + QFont fontFromConfig(const QString & id); + bool fontToConfig(const QString & id, const QFont font); + QString shortcutFromConfig(const QString & id); + bool shortcutToConfig(const QString & id, const QKeySequence shortcut); + + mutable bool noMoreMsgbox; + QMap mZoomFontDelta; +}; diff --git a/src/cross/gui/Imports.h b/src/cross/gui/Imports.h new file mode 100644 index 00000000..01a80f8b --- /dev/null +++ b/src/cross/gui/Imports.h @@ -0,0 +1,3 @@ +#pragma once + +#include "Types.h" diff --git a/src/cross/gui/MagicMenu.h b/src/cross/gui/MagicMenu.h new file mode 100644 index 00000000..7ae002b0 --- /dev/null +++ b/src/cross/gui/MagicMenu.h @@ -0,0 +1,120 @@ +#pragma once + +#include + +#include "Utils/MenuBuilder.h" +#include +#include + +// TODO: support QT_TR_NOOP in linguist +#define TR(str) TranslatedText(str) + +template +class MagicMenu +{ + MenuBuilder* mMenuBuilder = nullptr; + + Base* base() + { + return static_cast(this); + } + +public: + struct TranslatedText + { + const char* text = nullptr; + + explicit TranslatedText(const char* text) + : text(text) + { + } + + TranslatedText(const TranslatedText &) = delete; + TranslatedText(TranslatedText &&) = delete; + }; + + // TODO: see if it's possible to support ActionDescription("Goto", "G") directly in linguist + struct TableAction + { + const char* name = nullptr; + const char* defaultShortcut = nullptr; + + TableAction(const TranslatedText & name, const char* defaultShortcut = nullptr) + : name(name.text), defaultShortcut(defaultShortcut) + { + } + + TableAction(const TableAction &) = delete; + TableAction(TableAction &&) = delete; + + QAction* buildAction(QWidget* widget) const + { + auto className = widget->metaObject()->className(); + qDebug() << "Register shortcut action:" << className << ":" << name; + auto qAction = new QAction(QCoreApplication::translate(className, name)); + // TODO: set shortcut based on configuration + qAction->setShortcut(QKeySequence(defaultShortcut)); + qAction->setShortcutContext(Qt::WidgetShortcut); + // TODO: allow shortcut to update dynamically + widget->addAction(qAction); + return qAction; + } + }; + + MagicMenu() + { + mMenuBuilder = new MenuBuilder(base()); + + base()->setContextMenuPolicy(Qt::CustomContextMenu); + QObject::connect(base(), &QWidget::customContextMenuRequested, [this](const QPoint & pos) + { + if(pos.y() < base()->getHeaderHeight()) + return; + auto wMenu = new QMenu(base()); + mMenuBuilder->build(wMenu); + if(wMenu->actions().length()) + { + wMenu->popup(base()->mapToGlobal(pos)); + } + }); + } + + MenuBuilder* menuBuilder() + { + return mMenuBuilder; + } + + // TODO: support conditional actions + template + void addMenuAction(const TableAction & action, SlotFn && slot) + { + auto qAction = action.buildAction(base()); + QObject::connect(qAction, &QAction::triggered, base(), slot); + mMenuBuilder->addAction(qAction); + } + + template + void addMenuAction(const TableAction & action, SlotFn && slot, const std::function & condition) + { + auto qAction = action.buildAction(base()); + QObject::connect(qAction, &QAction::triggered, base(), slot); + mMenuBuilder->addAction(qAction, [condition](QMenu*) + { + return condition(); + }); + } + + /*void addMenuAction(const TableAction& action, const char* slot) + { + auto qAction = action.buildAction(base()); + QObject::connect(qAction, SIGNAL(triggered(bool)), base(), SLOT(slot)); + mMenuBuilder->addAction(qAction); + }*/ + + void addMenuBuilder(const TranslatedText & title, MenuBuilder::BuildCallback && callback) + { + auto trTitle = QCoreApplication::translate(base()->metaObject()->className(), title.text); + auto qMenu = new QMenu(trTitle, base()); + mMenuBuilder->addMenu(qMenu, std::move(callback)); + } +}; diff --git a/src/cross/gui/MiscUtil.cpp b/src/cross/gui/MiscUtil.cpp new file mode 100644 index 00000000..8f1b2986 --- /dev/null +++ b/src/cross/gui/MiscUtil.cpp @@ -0,0 +1,404 @@ +#include "MiscUtil.h" +//#include +#include +#include +#include +#include +#include +#include "StringUtil.h" +#include +#include "Bridge.h" +#include + +#if 0 +void SetApplicationIcon(WId winId) +{ + std::thread([winId] + { + HICON hIcon = LoadIcon(GetModuleHandleW(0), MAKEINTRESOURCE(100)); + SendMessageW((HWND)winId, WM_SETICON, ICON_BIG, (LPARAM)hIcon); + DestroyIcon(hIcon); + }).detach(); +} +#endif // 0 + +QByteArray & ByteReverse(QByteArray & array) +{ + int length = array.length(); + for(int i = 0; i < length / 2; i++) + { + char temp = array[i]; + array[i] = array[length - i - 1]; + array[length - i - 1] = temp; + } + return array; +} + +QByteArray ByteReverse(QByteArray && array) +{ + int length = array.length(); + for(int i = 0; i < length / 2; i++) + { + char temp = array[i]; + array[i] = array[length - i - 1]; + array[length - i - 1] = temp; + } + return array; +} + +bool SimpleInputBox(QWidget* parent, const QString & title, QString defaultValue, QString & output, const QString & placeholderText, const QIcon* icon) +{ + LineEditDialog mEdit(parent); + mEdit.setWindowIcon(icon ? *icon : parent->windowIcon()); + mEdit.setText(defaultValue); + mEdit.setPlaceholderText(placeholderText); + mEdit.setWindowTitle(title); + mEdit.setCheckBox(false); + // TODO: WebAssembly support + if(mEdit.exec() == QDialog::Accepted) + { + output = mEdit.editText; + return true; + } + else + return false; +} + +bool SimpleChoiceBox(QWidget* parent, const QString & title, QString defaultValue, const QStringList & choices, QString & output, bool editable, const QString & placeholderText, const QIcon* icon, int minimumContentsLength) +{ + ComboBoxDialog mChoice(parent); + mChoice.setWindowIcon(icon ? *icon : parent->windowIcon()); + mChoice.setEditable(editable); + mChoice.setItems(choices); + mChoice.setText(defaultValue); + mChoice.setPlaceholderText(placeholderText); + mChoice.setWindowTitle(title); + mChoice.setCheckBox(false); + if(minimumContentsLength >= 0) + mChoice.setMinimumContentsLength(minimumContentsLength); + // TODO: WebAssembly support + if(mChoice.exec() == QDialog::Accepted) + { + output = mChoice.currentText(); + return true; + } + else + return false; +} + +void SimpleErrorBox(QWidget* parent, const QString & title, const QString & text) +{ + QMessageBox msg(QMessageBox::Critical, title, text, QMessageBox::NoButton, parent); + msg.setWindowIcon(DIcon("fatal-error")); + msg.setParent(parent, Qt::Dialog); + msg.setWindowFlags(msg.windowFlags() & (~Qt::WindowContextHelpButtonHint)); + // TODO: WebAssembly support + msg.exec(); +} + +void SimpleWarningBox(QWidget* parent, const QString & title, const QString & text) +{ + QMessageBox msg(QMessageBox::Warning, title, text, QMessageBox::NoButton, parent); + msg.setWindowIcon(DIcon("exclamation")); + msg.setParent(parent, Qt::Dialog); + msg.setWindowFlags(msg.windowFlags() & (~Qt::WindowContextHelpButtonHint)); + // TODO: WebAssembly support + msg.exec(); +} + +void SimpleInfoBox(QWidget* parent, const QString & title, const QString & text) +{ + QMessageBox msg(QMessageBox::Information, title, text, QMessageBox::NoButton, parent); + msg.setWindowIcon(DIcon("information")); + msg.setParent(parent, Qt::Dialog); + msg.setWindowFlags(msg.windowFlags() & (~Qt::WindowContextHelpButtonHint)); + msg.exec(); +} + +QString getSymbolicName(duint addr) +{ + char labelText[MAX_LABEL_SIZE] = ""; + char moduleText[MAX_MODULE_SIZE] = ""; + bool bHasLabel = DbgGetLabelAt(addr, SEG_DEFAULT, labelText); + bool bHasModule = (DbgGetModuleAt(addr, moduleText) && !QString(labelText).startsWith("JMP.&")); + QString addrText = ToPtrString(addr); + + if(bHasLabel && bHasModule) // + return QString("%1 <%2.%3>").arg(addrText).arg(moduleText).arg(labelText); + else if(bHasModule) // module.addr + return QString("%1.%2").arg(moduleText).arg(addrText); + else if(bHasLabel) //